2 * Copyright (C) 2010 Andreas Steffen
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "pem_encoder.h"
18 #define BYTES_PER_LINE 48
23 bool pem_encoder_encode(cred_encoding_type_t type
, chunk_t
*encoding
,
29 size_t len
, written
, pem_chars
, pem_lines
;
30 chunk_t n
, e
, d
, p
, q
, exp1
, exp2
, coeff
, to_free
= chunk_empty
;
36 /* direct PKCS#1 PEM encoding */
37 if (cred_encoding_args(args
, CRED_PART_RSA_PUB_ASN1_DER
,
38 &asn1
, CRED_PART_END
) ||
39 cred_encoding_args(args
, CRED_PART_ECDSA_PUB_ASN1_DER
,
40 &asn1
, CRED_PART_END
))
44 /* indirect PEM encoding from components */
45 if (cred_encoding_args(args
, CRED_PART_RSA_MODULUS
, &n
,
46 CRED_PART_RSA_PUB_EXP
, &e
, CRED_PART_END
))
48 if (lib
->encoding
->encode(lib
->encoding
, PUBKEY_SPKI_ASN1_DER
,
49 NULL
, &asn1
, CRED_PART_RSA_MODULUS
, n
,
50 CRED_PART_RSA_PUB_EXP
, e
, CRED_PART_END
))
56 if (cred_encoding_args(args
, CRED_PART_BLISS_PUB_ASN1_DER
,
57 &asn1
, CRED_PART_END
))
63 label
="RSA PRIVATE KEY";
64 /* direct PKCS#1 PEM encoding */
65 if (cred_encoding_args(args
, CRED_PART_RSA_PRIV_ASN1_DER
,
66 &asn1
, CRED_PART_END
))
70 /* indirect PEM encoding from components */
71 if (cred_encoding_args(args
, CRED_PART_RSA_MODULUS
, &n
,
72 CRED_PART_RSA_PUB_EXP
, &e
, CRED_PART_RSA_PRIV_EXP
, &d
,
73 CRED_PART_RSA_PRIME1
, &p
, CRED_PART_RSA_PRIME2
, &q
,
74 CRED_PART_RSA_EXP1
, &exp1
, CRED_PART_RSA_EXP2
, &exp2
,
75 CRED_PART_RSA_COEFF
, &coeff
, CRED_PART_END
))
77 if (lib
->encoding
->encode(lib
->encoding
, PRIVKEY_ASN1_DER
, NULL
,
78 &asn1
, CRED_PART_RSA_MODULUS
, n
,
79 CRED_PART_RSA_PUB_EXP
, e
, CRED_PART_RSA_PRIV_EXP
, d
,
80 CRED_PART_RSA_PRIME1
, p
, CRED_PART_RSA_PRIME2
, q
,
81 CRED_PART_RSA_EXP1
, exp1
, CRED_PART_RSA_EXP2
, exp2
,
82 CRED_PART_RSA_COEFF
, coeff
, CRED_PART_END
))
88 if (cred_encoding_args(args
, CRED_PART_ECDSA_PRIV_ASN1_DER
,
89 &asn1
, CRED_PART_END
))
91 label
="EC PRIVATE KEY";
94 if (cred_encoding_args(args
, CRED_PART_BLISS_PRIV_ASN1_DER
,
95 &asn1
, CRED_PART_END
))
97 label
="BLISS PRIVATE KEY";
102 if (cred_encoding_args(args
, CRED_PART_X509_ASN1_DER
,
103 &asn1
, CRED_PART_END
))
104 { /* PEM encode x509 certificate */
105 label
= "CERTIFICATE";
108 if (cred_encoding_args(args
, CRED_PART_X509_CRL_ASN1_DER
,
109 &asn1
, CRED_PART_END
))
110 { /* PEM encode CRL */
114 if (cred_encoding_args(args
, CRED_PART_PKCS10_ASN1_DER
,
115 &asn1
, CRED_PART_END
))
116 { /* PEM encode PKCS10 certificate reqeuest */
117 label
= "CERTIFICATE REQUEST";
120 if (cred_encoding_args(args
, CRED_PART_X509_AC_ASN1_DER
,
121 &asn1
, CRED_PART_END
))
123 label
= "ATTRIBUTE CERTIFICATE";
130 /* compute and allocate maximum size of PEM object */
131 pem_chars
= 4 * ((asn1
.len
+ 2) / 3);
132 pem_lines
= (asn1
.len
+ BYTES_PER_LINE
- 1) / BYTES_PER_LINE
;
133 *encoding
= chunk_alloc(5 + 2*(6 + strlen(label
) + 6) + 3 + pem_chars
+ pem_lines
);
137 /* write PEM header */
138 written
= snprintf(pos
, len
, "-----BEGIN %s-----\n", label
);
145 chunk_t asn1_line
, pem_line
;
147 asn1_line
= chunk_create(asn1
.ptr
, min(asn1
.len
, BYTES_PER_LINE
));
148 asn1
.ptr
+= asn1_line
.len
;
149 asn1
.len
-= asn1_line
.len
;
150 pem_line
= chunk_to_base64(asn1_line
, pos
);
158 chunk_clear(&to_free
);
160 /* write PEM trailer */
161 written
= snprintf(pos
, len
, "-----END %s-----", label
);
165 /* replace termination null character with newline */
170 /* compute effective length of PEM object */
171 encoding
->len
= pos
- encoding
->ptr
;