pkcs1: Support building of KEY_ANY private keys
[strongswan.git] / src / libstrongswan / plugins / pkcs1 / pkcs1_builder.c
1 /*
2 * Copyright (C) 2008-2016 Tobias Brunner
3 * Copyright (C) 2008-2009 Martin Willi
4 * Copyright (C) 2000-2008 Andreas Steffen
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "pkcs1_builder.h"
19
20 #include <utils/debug.h>
21 #include <asn1/oid.h>
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
24 #include <credentials/keys/private_key.h>
25
26 /**
27 * ASN.1 definition of a subjectPublicKeyInfo structure
28 */
29 static const asn1Object_t pkinfoObjects[] = {
30 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
31 { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
32 { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
33 { 0, "exit", ASN1_EOC, ASN1_EXIT }
34 };
35 #define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
36 #define PKINFO_SUBJECT_PUBLIC_KEY 2
37
38 /**
39 * Load a generic public key from an ASN.1 encoded blob
40 */
41 static public_key_t *parse_public_key(chunk_t blob)
42 {
43 asn1_parser_t *parser;
44 chunk_t object;
45 int objectID;
46 public_key_t *key = NULL;
47 key_type_t type = KEY_ANY;
48
49 parser = asn1_parser_create(pkinfoObjects, blob);
50
51 while (parser->iterate(parser, &objectID, &object))
52 {
53 switch (objectID)
54 {
55 case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
56 {
57 int oid = asn1_parse_algorithmIdentifier(object,
58 parser->get_level(parser)+1, NULL);
59
60 if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP)
61 {
62 type = KEY_RSA;
63 }
64 else if (oid == OID_EC_PUBLICKEY)
65 {
66 /* Need the whole subjectPublicKeyInfo for EC public keys */
67 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
68 KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
69 goto end;
70 }
71 else if (oid == OID_BLISS_PUBLICKEY)
72 {
73 /* Need the whole subjectPublicKeyInfo for BLISS public keys */
74 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
75 KEY_BLISS, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
76 goto end;
77 }
78 else
79 {
80 /* key type not supported */
81 goto end;
82 }
83 break;
84 }
85 case PKINFO_SUBJECT_PUBLIC_KEY:
86 if (object.len > 0 && *object.ptr == 0x00)
87 {
88 /* skip initial bit string octet defining 0 unused bits */
89 object = chunk_skip(object, 1);
90 }
91 DBG2(DBG_ASN, "-- > --");
92 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
93 BUILD_BLOB_ASN1_DER, object, BUILD_END);
94 DBG2(DBG_ASN, "-- < --");
95 break;
96 }
97 }
98
99 end:
100 parser->destroy(parser);
101 return key;
102 }
103
104 /**
105 * ASN.1 definition of RSApublicKey
106 */
107 static const asn1Object_t pubkeyObjects[] = {
108 { 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
109 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
110 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
111 { 0, "exit", ASN1_EOC, ASN1_EXIT }
112 };
113 #define PUB_KEY_RSA_PUBLIC_KEY 0
114 #define PUB_KEY_MODULUS 1
115 #define PUB_KEY_EXPONENT 2
116
117 /**
118 * Load a RSA public key from an ASN.1 encoded blob.
119 */
120 static public_key_t *parse_rsa_public_key(chunk_t blob)
121 {
122 chunk_t n, e;
123 asn1_parser_t *parser;
124 chunk_t object;
125 int objectID;
126 bool success = FALSE;
127
128 parser = asn1_parser_create(pubkeyObjects, blob);
129
130 while (parser->iterate(parser, &objectID, &object))
131 {
132 switch (objectID)
133 {
134 case PUB_KEY_MODULUS:
135 n = object;
136 break;
137 case PUB_KEY_EXPONENT:
138 e = object;
139 break;
140 }
141 }
142 success = parser->success(parser);
143 parser->destroy(parser);
144
145 if (!success)
146 {
147 return NULL;
148 }
149 return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
150 BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
151 }
152
153 /**
154 * ASN.1 definition of a PKCS#1 RSA private key
155 */
156 static const asn1Object_t privkeyObjects[] = {
157 { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
158 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
159 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
160 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
161 { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
162 { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
163 { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
164 { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
165 { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
166 { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
167 { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
168 ASN1_LOOP }, /* 10 */
169 { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
170 { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
171 { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
172 { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
173 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 15 */
174 { 0, "exit", ASN1_EOC, ASN1_EXIT }
175 };
176 #define PRIV_KEY_VERSION 1
177 #define PRIV_KEY_MODULUS 2
178 #define PRIV_KEY_PUB_EXP 3
179 #define PRIV_KEY_PRIV_EXP 4
180 #define PRIV_KEY_PRIME1 5
181 #define PRIV_KEY_PRIME2 6
182 #define PRIV_KEY_EXP1 7
183 #define PRIV_KEY_EXP2 8
184 #define PRIV_KEY_COEFF 9
185
186 /**
187 * Load a RSA private key from a ASN1 encoded blob.
188 */
189 static private_key_t *parse_rsa_private_key(chunk_t blob)
190 {
191 chunk_t n, e, d, p, q, exp1, exp2, coeff;
192 asn1_parser_t *parser;
193 chunk_t object;
194 int objectID ;
195 bool success = FALSE;
196
197 parser = asn1_parser_create(privkeyObjects, blob);
198 parser->set_flags(parser, FALSE, TRUE);
199
200 while (parser->iterate(parser, &objectID, &object))
201 {
202 switch (objectID)
203 {
204 case PRIV_KEY_VERSION:
205 if (object.len > 0 && *object.ptr != 0)
206 {
207 goto end;
208 }
209 break;
210 case PRIV_KEY_MODULUS:
211 n = object;
212 break;
213 case PRIV_KEY_PUB_EXP:
214 e = object;
215 break;
216 case PRIV_KEY_PRIV_EXP:
217 d = object;
218 break;
219 case PRIV_KEY_PRIME1:
220 p = object;
221 break;
222 case PRIV_KEY_PRIME2:
223 q = object;
224 break;
225 case PRIV_KEY_EXP1:
226 exp1 = object;
227 break;
228 case PRIV_KEY_EXP2:
229 exp2 = object;
230 break;
231 case PRIV_KEY_COEFF:
232 coeff = object;
233 break;
234 }
235 }
236 success = parser->success(parser);
237
238 end:
239 parser->destroy(parser);
240 if (!success)
241 {
242 return NULL;
243 }
244 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
245 BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_RSA_PRIV_EXP, d,
246 BUILD_RSA_PRIME1, p, BUILD_RSA_PRIME2, q, BUILD_RSA_EXP1, exp1,
247 BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END);
248 }
249
250 /**
251 * Check if the ASN.1 structure looks like an EC private key according to
252 * RFC 5915.
253 *
254 * ECPrivateKey :=: SEQUENCE {
255 * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
256 * privateKey OCTET STRING,
257 * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
258 * publicKey [1] BIT STRING OPTIONAL
259 * }
260 *
261 * While the parameters and publicKey fields are OPTIONAL, RFC 5915 says that
262 * paramaters MUST be included and publicKey SHOULD be.
263 */
264 static bool is_ec_private_key(chunk_t blob)
265 {
266 chunk_t data;
267 return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
268 asn1_unwrap(&blob, &data) == ASN1_INTEGER &&
269 asn1_parse_integer_uint64(data) == 1 &&
270 asn1_unwrap(&blob, &data) == ASN1_OCTET_STRING &&
271 asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_0 &&
272 asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1;
273 }
274
275 /**
276 * Check if the ASN.1 structure looks like a BLISS private key.
277 */
278 static bool is_bliss_private_key(chunk_t blob)
279 {
280 chunk_t data;
281 return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
282 asn1_unwrap(&blob, &data) == ASN1_OID &&
283 asn1_unwrap(&blob, &data) == ASN1_BIT_STRING &&
284 asn1_unwrap(&blob, &data) == ASN1_BIT_STRING &&
285 asn1_unwrap(&blob, &data) == ASN1_BIT_STRING;
286 }
287
288 /**
289 * Load a private key from an ASN.1 encoded blob trying to detect the type
290 * automatically.
291 */
292 static private_key_t *parse_private_key(chunk_t blob)
293 {
294 if (is_ec_private_key(blob))
295 {
296 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
297 BUILD_BLOB_ASN1_DER, blob, BUILD_END);
298 }
299 else if (is_bliss_private_key(blob))
300 {
301 return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
302 BUILD_BLOB_ASN1_DER, blob, BUILD_END);
303 }
304 return parse_rsa_private_key(blob);
305 }
306
307 /**
308 * See header.
309 */
310 public_key_t *pkcs1_public_key_load(key_type_t type, va_list args)
311 {
312 chunk_t blob = chunk_empty;
313
314 while (TRUE)
315 {
316 switch (va_arg(args, builder_part_t))
317 {
318 case BUILD_BLOB_ASN1_DER:
319 blob = va_arg(args, chunk_t);
320 continue;
321 case BUILD_END:
322 break;
323 default:
324 return NULL;
325 }
326 break;
327 }
328 switch (type)
329 {
330 case KEY_ANY:
331 return parse_public_key(blob);
332 case KEY_RSA:
333 return parse_rsa_public_key(blob);
334 default:
335 return NULL;
336 }
337 }
338
339 /**
340 * See header.
341 */
342 private_key_t *pkcs1_private_key_load(key_type_t type, va_list args)
343 {
344 chunk_t blob = chunk_empty;
345
346 while (TRUE)
347 {
348 switch (va_arg(args, builder_part_t))
349 {
350 case BUILD_BLOB_ASN1_DER:
351 blob = va_arg(args, chunk_t);
352 continue;
353 case BUILD_END:
354 break;
355 default:
356 return NULL;
357 }
358 break;
359 }
360 switch (type)
361 {
362 case KEY_ANY:
363 return parse_private_key(blob);
364 case KEY_RSA:
365 return parse_rsa_private_key(blob);
366 default:
367 return NULL;
368 }
369 }
370