]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/pkcs8/pkcs8_builder.c
Add a return value to crypter_t.decrypt()
[thirdparty/strongswan.git] / src / libstrongswan / plugins / pkcs8 / pkcs8_builder.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
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 "pkcs8_builder.h"
17
18 #include <debug.h>
19 #include <asn1/oid.h>
20 #include <asn1/asn1.h>
21 #include <asn1/asn1_parser.h>
22 #include <credentials/keys/private_key.h>
23
24 /**
25 * ASN.1 definition of a privateKeyInfo structure
26 */
27 static const asn1Object_t pkinfoObjects[] = {
28 { 0, "privateKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
29 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
30 { 1, "privateKeyAlgorithm", ASN1_EOC, ASN1_RAW }, /* 2 */
31 { 1, "privateKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */
32 { 1, "attributes", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
33 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 5 */
34 { 0, "exit", ASN1_EOC, ASN1_EXIT }
35 };
36 #define PKINFO_PRIVATE_KEY_ALGORITHM 2
37 #define PKINFO_PRIVATE_KEY 3
38
39 /**
40 * Load a generic private key from an ASN.1 encoded blob
41 */
42 static private_key_t *parse_private_key(chunk_t blob)
43 {
44 asn1_parser_t *parser;
45 chunk_t object, params = chunk_empty;
46 int objectID;
47 private_key_t *key = NULL;
48 key_type_t type = KEY_ANY;
49
50 parser = asn1_parser_create(pkinfoObjects, blob);
51 parser->set_flags(parser, FALSE, TRUE);
52
53 while (parser->iterate(parser, &objectID, &object))
54 {
55 switch (objectID)
56 {
57 case PKINFO_PRIVATE_KEY_ALGORITHM:
58 {
59 int oid = asn1_parse_algorithmIdentifier(object,
60 parser->get_level(parser) + 1, &params);
61
62 switch (oid)
63 {
64 case OID_RSA_ENCRYPTION:
65 type = KEY_RSA;
66 break;
67 case OID_EC_PUBLICKEY:
68 type = KEY_ECDSA;
69 break;
70 default:
71 /* key type not supported */
72 goto end;
73 }
74 break;
75 }
76 case PKINFO_PRIVATE_KEY:
77 {
78 DBG2(DBG_ASN, "-- > --");
79 if (params.ptr)
80 {
81 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
82 type, BUILD_BLOB_ALGID_PARAMS,
83 params, BUILD_BLOB_ASN1_DER,
84 object, BUILD_END);
85 }
86 else
87 {
88 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
89 type, BUILD_BLOB_ASN1_DER, object,
90 BUILD_END);
91 }
92 DBG2(DBG_ASN, "-- < --");
93 break;
94 }
95 }
96 }
97
98 end:
99 parser->destroy(parser);
100 return key;
101 }
102
103 /**
104 * Verify padding of decrypted blob.
105 * Length of blob is adjusted accordingly.
106 */
107 static bool verify_padding(chunk_t *blob)
108 {
109 u_int8_t padding, count;
110
111 padding = count = blob->ptr[blob->len - 1];
112 if (padding > 8)
113 {
114 return FALSE;
115 }
116 for (; blob->len && count; --blob->len, --count)
117 {
118 if (blob->ptr[blob->len - 1] != padding)
119 {
120 return FALSE;
121 }
122 }
123 return TRUE;
124 }
125
126 /**
127 * Prototype for key derivation functions.
128 */
129 typedef bool (*kdf_t)(void *generator, chunk_t password, chunk_t salt,
130 u_int64_t iterations, chunk_t key);
131
132 /**
133 * Try to decrypt the given blob with multiple passwords using the given
134 * key derivation function. keymat is where the kdf function writes the key
135 * to, key and iv point to the actual keys and initialization vectors resp.
136 */
137 static private_key_t *decrypt_private_key(chunk_t blob,
138 encryption_algorithm_t encr, size_t key_len, kdf_t kdf,
139 void *generator, chunk_t salt, u_int64_t iterations,
140 chunk_t keymat, chunk_t key, chunk_t iv)
141 {
142 enumerator_t *enumerator;
143 shared_key_t *shared;
144 crypter_t *crypter;
145 private_key_t *private_key = NULL;
146
147 crypter = lib->crypto->create_crypter(lib->crypto, encr, key_len);
148 if (!crypter)
149 {
150 DBG1(DBG_ASN, " %N encryption algorithm not available",
151 encryption_algorithm_names, encr);
152 return NULL;
153 }
154 if (blob.len % crypter->get_block_size(crypter))
155 {
156 DBG1(DBG_ASN, " data size is not a multiple of block size");
157 crypter->destroy(crypter);
158 return NULL;
159 }
160
161 enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
162 SHARED_PRIVATE_KEY_PASS, NULL, NULL);
163 while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
164 {
165 chunk_t decrypted;
166
167 if (!kdf(generator, shared->get_key(shared), salt, iterations, keymat))
168 {
169 continue;
170 }
171
172 crypter->set_key(crypter, key);
173 if (!crypter->decrypt(crypter, blob, iv, &decrypted))
174 {
175 continue;
176 }
177 if (verify_padding(&decrypted))
178 {
179 private_key = parse_private_key(decrypted);
180 if (private_key)
181 {
182 chunk_clear(&decrypted);
183 break;
184 }
185 }
186 chunk_free(&decrypted);
187 }
188 enumerator->destroy(enumerator);
189 crypter->destroy(crypter);
190
191 return private_key;
192 }
193
194 /**
195 * Function F of PBKDF2
196 */
197 static bool pbkdf2_f(chunk_t block, prf_t *prf, chunk_t seed,
198 u_int64_t iterations)
199 {
200 chunk_t u;
201 u_int64_t i;
202
203 u = chunk_alloca(prf->get_block_size(prf));
204 if (!prf->get_bytes(prf, seed, u.ptr))
205 {
206 return FALSE;
207 }
208 memcpy(block.ptr, u.ptr, block.len);
209
210 for (i = 1; i < iterations; i++)
211 {
212 if (!prf->get_bytes(prf, u, u.ptr))
213 {
214 return FALSE;
215 }
216 memxor(block.ptr, u.ptr, block.len);
217 }
218 return TRUE;
219 }
220
221 /**
222 * PBKDF2 key derivation function
223 */
224 static bool pbkdf2(prf_t *prf, chunk_t password, chunk_t salt,
225 u_int64_t iterations, chunk_t key)
226 {
227 chunk_t keymat, block, seed;
228 size_t blocks;
229 u_int32_t i = 0, *ni;
230
231 if (!prf->set_key(prf, password))
232 {
233 return FALSE;
234 }
235
236 block.len = prf->get_block_size(prf);
237 blocks = (key.len - 1) / block.len + 1;
238 keymat = chunk_alloca(blocks * block.len);
239
240 seed = chunk_cata("cc", salt, chunk_from_thing(i));
241 ni = (u_int32_t*)(seed.ptr + salt.len);
242
243 for (; i < blocks; i++)
244 {
245 *ni = htonl(i + 1);
246 block.ptr = keymat.ptr + (i * block.len);
247 if (!pbkdf2_f(block, prf, seed, iterations))
248 {
249 return FALSE;
250 }
251 }
252
253 memcpy(key.ptr, keymat.ptr, key.len);
254
255 return TRUE;
256 }
257
258 /**
259 * Decrypt an encrypted PKCS#8 encoded private key according to PBES2
260 */
261 static private_key_t *decrypt_private_key_pbes2(chunk_t blob,
262 encryption_algorithm_t encr, size_t key_len,
263 chunk_t iv, pseudo_random_function_t prf_func,
264 chunk_t salt, u_int64_t iterations)
265 {
266 private_key_t *private_key;
267 prf_t *prf;
268 chunk_t key;
269
270 prf = lib->crypto->create_prf(lib->crypto, prf_func);
271 if (!prf)
272 {
273 DBG1(DBG_ASN, " %N prf algorithm not available",
274 pseudo_random_function_names, prf_func);
275 return NULL;
276 }
277
278 key = chunk_alloca(key_len);
279
280 private_key = decrypt_private_key(blob, encr, key_len, (kdf_t)pbkdf2, prf,
281 salt, iterations, key, key, iv);
282
283 prf->destroy(prf);
284 return private_key;
285 }
286
287 /**
288 * PBKDF1 key derivation function
289 */
290 static bool pbkdf1(hasher_t *hasher, chunk_t password, chunk_t salt,
291 u_int64_t iterations, chunk_t key)
292 {
293 chunk_t hash;
294 u_int64_t i;
295
296 hash = chunk_alloca(hasher->get_hash_size(hasher));
297 hasher->get_hash(hasher, password, NULL);
298 hasher->get_hash(hasher, salt, hash.ptr);
299
300 for (i = 1; i < iterations; i++)
301 {
302 hasher->get_hash(hasher, hash, hash.ptr);
303 }
304
305 memcpy(key.ptr, hash.ptr, key.len);
306
307 return TRUE;
308 }
309
310 /**
311 * Decrypt an encrypted PKCS#8 encoded private key according to PBES1
312 */
313 static private_key_t *decrypt_private_key_pbes1(chunk_t blob,
314 encryption_algorithm_t encr, size_t key_len,
315 hash_algorithm_t hash, chunk_t salt,
316 u_int64_t iterations)
317 {
318 private_key_t *private_key = NULL;
319 hasher_t *hasher = NULL;
320 chunk_t keymat, key, iv;
321
322 hasher = lib->crypto->create_hasher(lib->crypto, hash);
323 if (!hasher)
324 {
325 DBG1(DBG_ASN, " %N hash algorithm not available",
326 hash_algorithm_names, hash);
327 goto end;
328 }
329 if (hasher->get_hash_size(hasher) < key_len)
330 {
331 goto end;
332 }
333
334 keymat = chunk_alloca(key_len * 2);
335 key.len = key_len;
336 key.ptr = keymat.ptr;
337 iv.len = key_len;
338 iv.ptr = keymat.ptr + key_len;
339
340 private_key = decrypt_private_key(blob, encr, key_len, (kdf_t)pbkdf1,
341 hasher, salt, iterations, keymat,
342 key, iv);
343
344 end:
345 DESTROY_IF(hasher);
346 return private_key;
347 }
348
349 /**
350 * Parse an ASN1_INTEGER to a u_int64_t.
351 */
352 static u_int64_t parse_asn1_integer_uint64(chunk_t blob)
353 {
354 u_int64_t val = 0;
355 int i;
356
357 for (i = 0; i < blob.len; i++)
358 { /* if it is longer than 8 bytes, we just use the 8 LSBs */
359 val <<= 8;
360 val |= (u_int64_t)blob.ptr[i];
361 }
362 return val;
363 }
364
365 /**
366 * ASN.1 definition of a PBKDF2-params structure
367 * The salt is actually a CHOICE and could be an AlgorithmIdentifier from
368 * PBKDF2-SaltSources (but as per RFC 2898 that's for future versions).
369 */
370 static const asn1Object_t pbkdf2ParamsObjects[] = {
371 { 0, "PBKDF2-params", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
372 { 1, "salt", ASN1_OCTET_STRING, ASN1_BODY }, /* 1 */
373 { 1, "iterationCount",ASN1_INTEGER, ASN1_BODY }, /* 2 */
374 { 1, "keyLength", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 3 */
375 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
376 { 1, "prf", ASN1_EOC, ASN1_DEF|ASN1_RAW }, /* 5 */
377 { 0, "exit", ASN1_EOC, ASN1_EXIT }
378 };
379 #define PBKDF2_SALT 1
380 #define PBKDF2_ITERATION_COUNT 2
381 #define PBKDF2_KEY_LENGTH 3
382 #define PBKDF2_PRF 5
383
384 /**
385 * Parse a PBKDF2-params structure
386 */
387 static void parse_pbkdf2_params(chunk_t blob, chunk_t *salt,
388 u_int64_t *iterations, size_t *key_len,
389 pseudo_random_function_t *prf)
390 {
391 asn1_parser_t *parser;
392 chunk_t object;
393 int objectID;
394
395 parser = asn1_parser_create(pbkdf2ParamsObjects, blob);
396
397 *key_len = 0; /* key_len is optional */
398
399 while (parser->iterate(parser, &objectID, &object))
400 {
401 switch (objectID)
402 {
403 case PBKDF2_SALT:
404 {
405 *salt = object;
406 break;
407 }
408 case PBKDF2_ITERATION_COUNT:
409 {
410 *iterations = parse_asn1_integer_uint64(object);
411 break;
412 }
413 case PBKDF2_KEY_LENGTH:
414 {
415 *key_len = (size_t)parse_asn1_integer_uint64(object);
416 break;
417 }
418 case PBKDF2_PRF:
419 { /* defaults to id-hmacWithSHA1 */
420 *prf = PRF_HMAC_SHA1;
421 break;
422 }
423 }
424 }
425
426 parser->destroy(parser);
427 }
428
429 /**
430 * ASN.1 definition of a PBES2-params structure
431 */
432 static const asn1Object_t pbes2ParamsObjects[] = {
433 { 0, "PBES2-params", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
434 { 1, "keyDerivationFunc", ASN1_EOC, ASN1_RAW }, /* 1 */
435 { 1, "encryptionScheme", ASN1_EOC, ASN1_RAW }, /* 2 */
436 { 0, "exit", ASN1_EOC, ASN1_EXIT }
437 };
438 #define PBES2PARAMS_KEY_DERIVATION_FUNC 1
439 #define PBES2PARAMS_ENCRYPTION_SCHEME 2
440
441 /**
442 * Parse a PBES2-params structure
443 */
444 static void parse_pbes2_params(chunk_t blob, chunk_t *salt,
445 u_int64_t *iterations, size_t *key_len,
446 pseudo_random_function_t *prf,
447 encryption_algorithm_t *encr, chunk_t *iv)
448 {
449 asn1_parser_t *parser;
450 chunk_t object, params;
451 int objectID;
452
453 parser = asn1_parser_create(pbes2ParamsObjects, blob);
454
455 while (parser->iterate(parser, &objectID, &object))
456 {
457 switch (objectID)
458 {
459 case PBES2PARAMS_KEY_DERIVATION_FUNC:
460 {
461 int oid = asn1_parse_algorithmIdentifier(object,
462 parser->get_level(parser) + 1, &params);
463 if (oid != OID_PBKDF2)
464 { /* unsupported key derivation function */
465 goto end;
466 }
467 parse_pbkdf2_params(params, salt, iterations, key_len, prf);
468 break;
469 }
470 case PBES2PARAMS_ENCRYPTION_SCHEME:
471 {
472 int oid = asn1_parse_algorithmIdentifier(object,
473 parser->get_level(parser) + 1, &params);
474 if (oid != OID_3DES_EDE_CBC)
475 { /* unsupported encryption scheme */
476 goto end;
477 }
478 if (*key_len <= 0)
479 { /* default key len for DES-EDE3-CBC-Pad */
480 *key_len = 24;
481 }
482 if (!asn1_parse_simple_object(&params, ASN1_OCTET_STRING,
483 parser->get_level(parser) + 1, "IV"))
484 {
485 goto end;
486 }
487 *encr = ENCR_3DES;
488 *iv = params;
489 break;
490 }
491 }
492 }
493
494 end:
495 parser->destroy(parser);
496 }
497
498 /**
499 * ASN.1 definition of a PBEParameter structure
500 */
501 static const asn1Object_t pbeParameterObjects[] = {
502 { 0, "PBEParameter", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
503 { 1, "salt", ASN1_OCTET_STRING, ASN1_BODY }, /* 1 */
504 { 1, "iterationCount", ASN1_INTEGER, ASN1_BODY }, /* 2 */
505 { 0, "exit", ASN1_EOC, ASN1_EXIT }
506 };
507 #define PBEPARAM_SALT 1
508 #define PBEPARAM_ITERATION_COUNT 2
509
510 /**
511 * Parse a PBEParameter structure
512 */
513 static void parse_pbe_parameters(chunk_t blob, chunk_t *salt,
514 u_int64_t *iterations)
515 {
516 asn1_parser_t *parser;
517 chunk_t object;
518 int objectID;
519
520 parser = asn1_parser_create(pbeParameterObjects, blob);
521
522 while (parser->iterate(parser, &objectID, &object))
523 {
524 switch (objectID)
525 {
526 case PBEPARAM_SALT:
527 {
528 *salt = object;
529 break;
530 }
531 case PBEPARAM_ITERATION_COUNT:
532 {
533 *iterations = parse_asn1_integer_uint64(object);
534 break;
535 }
536 }
537 }
538
539 parser->destroy(parser);
540 }
541
542 /**
543 * ASN.1 definition of an encryptedPrivateKeyInfo structure
544 */
545 static const asn1Object_t encryptedPKIObjects[] = {
546 { 0, "encryptedPrivateKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
547 { 1, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
548 { 1, "encryptedData", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
549 { 0, "exit", ASN1_EOC, ASN1_EXIT }
550 };
551 #define EPKINFO_ENCRYPTION_ALGORITHM 1
552 #define EPKINFO_ENCRYPTED_DATA 2
553
554 /**
555 * Load an encrypted private key from an ASN.1 encoded blob
556 * Schemes per PKCS#5 (RFC 2898)
557 */
558 static private_key_t *parse_encrypted_private_key(chunk_t blob)
559 {
560 asn1_parser_t *parser;
561 chunk_t object, params, salt = chunk_empty, iv = chunk_empty;
562 u_int64_t iterations = 0;
563 int objectID;
564 encryption_algorithm_t encr = ENCR_UNDEFINED;
565 hash_algorithm_t hash = HASH_UNKNOWN;
566 pseudo_random_function_t prf = PRF_UNDEFINED;
567 private_key_t *key = NULL;
568 size_t key_len = 8;
569
570 parser = asn1_parser_create(encryptedPKIObjects, blob);
571
572 while (parser->iterate(parser, &objectID, &object))
573 {
574 switch (objectID)
575 {
576 case EPKINFO_ENCRYPTION_ALGORITHM:
577 {
578 int oid = asn1_parse_algorithmIdentifier(object,
579 parser->get_level(parser) + 1, &params);
580
581 switch (oid)
582 {
583 case OID_PBE_MD5_DES_CBC:
584 encr = ENCR_DES;
585 hash = HASH_MD5;
586 parse_pbe_parameters(params, &salt, &iterations);
587 break;
588 case OID_PBE_SHA1_DES_CBC:
589 encr = ENCR_DES;
590 hash = HASH_SHA1;
591 parse_pbe_parameters(params, &salt, &iterations);
592 break;
593 case OID_PBES2:
594 parse_pbes2_params(params, &salt, &iterations,
595 &key_len, &prf, &encr, &iv);
596 break;
597 default:
598 /* encryption scheme not supported */
599 goto end;
600 }
601 break;
602 }
603 case EPKINFO_ENCRYPTED_DATA:
604 {
605 if (prf != PRF_UNDEFINED)
606 {
607 key = decrypt_private_key_pbes2(object, encr, key_len, iv,
608 prf, salt, iterations);
609 }
610 else
611 {
612 key = decrypt_private_key_pbes1(object, encr, key_len, hash,
613 salt, iterations);
614 }
615 break;
616 }
617 }
618 }
619
620 end:
621 parser->destroy(parser);
622 return key;
623 }
624
625 /**
626 * See header.
627 */
628 private_key_t *pkcs8_private_key_load(key_type_t type, va_list args)
629 {
630 chunk_t blob = chunk_empty;
631 private_key_t *key;
632
633 while (TRUE)
634 {
635 switch (va_arg(args, builder_part_t))
636 {
637 case BUILD_BLOB_ASN1_DER:
638 blob = va_arg(args, chunk_t);
639 continue;
640 case BUILD_END:
641 break;
642 default:
643 return NULL;
644 }
645 break;
646 }
647 /* we don't know whether it is encrypted or not, try both ways */
648 key = parse_encrypted_private_key(blob);
649 if (!key)
650 {
651 key = parse_private_key(blob);
652 }
653 return key;
654 }
655