]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/pem/pem_encoder.c
Store and parse BLISS private and public keys in DER and PEM format
[thirdparty/strongswan.git] / src / libstrongswan / plugins / pem / pem_encoder.c
1 /*
2 * Copyright (C) 2010 Andreas Steffen
3 * Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "pem_encoder.h"
17
18 #define BYTES_PER_LINE 48
19
20 /**
21 * See header.
22 */
23 bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
24 va_list args)
25 {
26 chunk_t asn1;
27 char *label;
28 u_char *pos;
29 size_t len, written, pem_chars, pem_lines;
30 chunk_t n, e, d, p, q, exp1, exp2, coeff, to_free = chunk_empty;
31
32 switch (type)
33 {
34 case PUBKEY_PEM:
35 label ="PUBLIC KEY";
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))
41 {
42 break;
43 }
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))
47 {
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))
51 {
52 to_free = asn1;
53 break;
54 }
55 }
56 if (cred_encoding_args(args, CRED_PART_BLISS_PUB_ASN1_DER,
57 &asn1, CRED_PART_END))
58 {
59 break;
60 }
61 return FALSE;
62 case PRIVKEY_PEM:
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))
67 {
68 break;
69 }
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))
76 {
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))
83 {
84 to_free = asn1;
85 break;
86 }
87 }
88 if (cred_encoding_args(args, CRED_PART_ECDSA_PRIV_ASN1_DER,
89 &asn1, CRED_PART_END))
90 {
91 label ="EC PRIVATE KEY";
92 break;
93 }
94 if (cred_encoding_args(args, CRED_PART_BLISS_PRIV_ASN1_DER,
95 &asn1, CRED_PART_END))
96 {
97 label ="BLISS PRIVATE KEY";
98 break;
99 }
100 return FALSE;
101 case CERT_PEM:
102 if (cred_encoding_args(args, CRED_PART_X509_ASN1_DER,
103 &asn1, CRED_PART_END))
104 { /* PEM encode x509 certificate */
105 label = "CERTIFICATE";
106 break;
107 }
108 if (cred_encoding_args(args, CRED_PART_X509_CRL_ASN1_DER,
109 &asn1, CRED_PART_END))
110 { /* PEM encode CRL */
111 label = "X509 CRL";
112 break;
113 }
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";
118 break;
119 }
120 if (cred_encoding_args(args, CRED_PART_X509_AC_ASN1_DER,
121 &asn1, CRED_PART_END))
122 {
123 label = "ATTRIBUTE CERTIFICATE";
124 break;
125 }
126 default:
127 return FALSE;
128 }
129
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);
134 pos = encoding->ptr;
135 len = encoding->len;
136
137 /* write PEM header */
138 written = snprintf(pos, len, "-----BEGIN %s-----\n", label);
139 pos += written;
140 len -= written;
141
142 /* write PEM body */
143 while (pem_lines--)
144 {
145 chunk_t asn1_line, pem_line;
146
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);
151 pos += pem_line.len;
152 len -= pem_line.len;
153 *pos = '\n';
154 pos++;
155 len--;
156 }
157
158 chunk_clear(&to_free);
159
160 /* write PEM trailer */
161 written = snprintf(pos, len, "-----END %s-----", label);
162 pos += written;
163 len -= written;
164
165 /* replace termination null character with newline */
166 *pos = '\n';
167 pos++;
168 len--;
169
170 /* compute effective length of PEM object */
171 encoding->len = pos - encoding->ptr;
172 return TRUE;
173 }