Annotation of embedaddon/strongswan/src/libstrongswan/crypto/pkcs5.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012-2013 Tobias Brunner
3: * HSR 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 "pkcs5.h"
17:
18: #include <utils/debug.h>
19: #include <asn1/oid.h>
20: #include <asn1/asn1.h>
21: #include <asn1/asn1_parser.h>
22: #include <credentials/containers/pkcs12.h>
23:
24: typedef struct private_pkcs5_t private_pkcs5_t;
25:
26: /**
27: * Private data of a pkcs5_t object
28: */
29: struct private_pkcs5_t {
30:
31: /**
32: * Implements pkcs5_t.
33: */
34: pkcs5_t public;
35:
36: /**
37: * Salt used during encryption
38: */
39: chunk_t salt;
40:
41: /**
42: * Iterations for key derivation
43: */
44: uint64_t iterations;
45:
46: /**
47: * Encryption algorithm
48: */
49: encryption_algorithm_t encr;
50:
51: /**
52: * Encryption key length
53: */
54: size_t keylen;
55:
56: /**
57: * Crypter
58: */
59: crypter_t *crypter;
60:
61:
62: /**
63: * The encryption scheme
64: */
65: enum {
66: PKCS5_SCHEME_PBES1,
67: PKCS5_SCHEME_PBES2,
68: PKCS5_SCHEME_PKCS12,
69: } scheme;
70:
71: /**
72: * Data used for individual schemes
73: */
74: union {
75: struct {
76: /**
77: * Hash algorithm
78: */
79: hash_algorithm_t hash;
80:
81: /**
82: * Hasher
83: */
84: hasher_t *hasher;
85:
86: } pbes1;
87: struct {
88: /**
89: * PRF algorithm
90: */
91: pseudo_random_function_t prf_alg;
92:
93: /**
94: * PRF
95: */
96: prf_t * prf;
97:
98: /**
99: * IV
100: */
101: chunk_t iv;
102:
103: } pbes2;
104: } data;
105: };
106:
107: /**
108: * Verify padding of decrypted blob.
109: * Length of blob is adjusted accordingly.
110: */
111: static bool verify_padding(crypter_t *crypter, chunk_t *blob)
112: {
113: uint8_t padding, count;
114:
115: padding = count = blob->ptr[blob->len - 1];
116:
117: if (padding > crypter->get_block_size(crypter))
118: {
119: return FALSE;
120: }
121: for (; blob->len && count; --blob->len, --count)
122: {
123: if (blob->ptr[blob->len - 1] != padding)
124: {
125: return FALSE;
126: }
127: }
128: return TRUE;
129: }
130:
131: /**
132: * Prototype for key derivation functions.
133: */
134: typedef bool (*kdf_t)(private_pkcs5_t *this, chunk_t password, chunk_t key);
135:
136: /**
137: * Try to decrypt the given data with the given password using the given
138: * key derivation function. keymat is where the kdf function writes the key
139: * to, key and iv point to the actual keys and initialization vectors resp.
140: */
141: static bool decrypt_generic(private_pkcs5_t *this, chunk_t password,
142: chunk_t data, chunk_t *decrypted, kdf_t kdf,
143: chunk_t keymat, chunk_t key, chunk_t iv)
144: {
145: if (!kdf(this, password, keymat))
146: {
147: return FALSE;
148: }
149: if (!this->crypter->set_key(this->crypter, key) ||
150: !this->crypter->decrypt(this->crypter, data, iv, decrypted))
151: {
152: memwipe(keymat.ptr, keymat.len);
153: return FALSE;
154: }
155: memwipe(keymat.ptr, keymat.len);
156: if (verify_padding(this->crypter, decrypted))
157: {
158: return TRUE;
159: }
160: chunk_free(decrypted);
161: return FALSE;
162: }
163:
164: /**
165: * KDF as used by PKCS#12
166: */
167: static bool pkcs12_kdf(private_pkcs5_t *this, chunk_t password, chunk_t keymat)
168: {
169: chunk_t key, iv;
170:
171: key = chunk_create(keymat.ptr, this->keylen);
172: iv = chunk_create(keymat.ptr + this->keylen, keymat.len - this->keylen);
173:
174: return pkcs12_derive_key(this->data.pbes1.hash, password, this->salt,
175: this->iterations, PKCS12_KEY_ENCRYPTION, key) &&
176: pkcs12_derive_key(this->data.pbes1.hash, password, this->salt,
177: this->iterations, PKCS12_KEY_IV, iv);
178: }
179:
180: /**
181: * Function F of PBKDF2
182: */
183: static bool pbkdf2_f(chunk_t block, prf_t *prf, chunk_t seed,
184: uint64_t iterations)
185: {
186: chunk_t u;
187: uint64_t i;
188:
189: u = chunk_alloca(prf->get_block_size(prf));
190: if (!prf->get_bytes(prf, seed, u.ptr))
191: {
192: return FALSE;
193: }
194: memcpy(block.ptr, u.ptr, block.len);
195:
196: for (i = 1; i < iterations; i++)
197: {
198: if (!prf->get_bytes(prf, u, u.ptr))
199: {
200: return FALSE;
201: }
202: memxor(block.ptr, u.ptr, block.len);
203: }
204: return TRUE;
205: }
206:
207: /**
208: * PBKDF2 key derivation function for PBES2, key must be allocated
209: */
210: static bool pbkdf2(private_pkcs5_t *this, chunk_t password, chunk_t key)
211: {
212: prf_t *prf;
213: chunk_t keymat, block, seed;
214: size_t blocks;
215: uint32_t i = 0;
216:
217: prf = this->data.pbes2.prf;
218:
219: if (!prf->set_key(prf, password))
220: {
221: return FALSE;
222: }
223:
224: block.len = prf->get_block_size(prf);
225: blocks = (key.len - 1) / block.len + 1;
226: keymat = chunk_alloca(blocks * block.len);
227:
228: seed = chunk_cata("cc", this->salt, chunk_from_thing(i));
229:
230: for (; i < blocks; i++)
231: {
232: htoun32(seed.ptr + this->salt.len, i + 1);
233: block.ptr = keymat.ptr + (i * block.len);
234: if (!pbkdf2_f(block, prf, seed, this->iterations))
235: {
236: return FALSE;
237: }
238: }
239: memcpy(key.ptr, keymat.ptr, key.len);
240: return TRUE;
241: }
242:
243: /**
244: * PBKDF1 key derivation function for PBES1, key must be allocated
245: */
246: static bool pbkdf1(private_pkcs5_t *this, chunk_t password, chunk_t key)
247: {
248: hasher_t *hasher;
249: chunk_t hash;
250: uint64_t i;
251:
252: hasher = this->data.pbes1.hasher;
253:
254: hash = chunk_alloca(hasher->get_hash_size(hasher));
255: if (!hasher->get_hash(hasher, password, NULL) ||
256: !hasher->get_hash(hasher, this->salt, hash.ptr))
257: {
258: return FALSE;
259: }
260:
261: for (i = 1; i < this->iterations; i++)
262: {
263: if (!hasher->get_hash(hasher, hash, hash.ptr))
264: {
265: return FALSE;
266: }
267: }
268: memcpy(key.ptr, hash.ptr, key.len);
269: return TRUE;
270: }
271:
272: static bool ensure_crypto_primitives(private_pkcs5_t *this, chunk_t data)
273: {
274: if (!this->crypter)
275: {
276: this->crypter = lib->crypto->create_crypter(lib->crypto, this->encr,
277: this->keylen);
278: if (!this->crypter)
279: {
280: DBG1(DBG_ASN, " %N encryption algorithm not available",
281: encryption_algorithm_names, this->encr);
282: return FALSE;
283: }
284: }
285: if (data.len % this->crypter->get_block_size(this->crypter))
286: {
287: DBG1(DBG_ASN, " data size is not a multiple of block size");
288: return FALSE;
289: }
290: switch (this->scheme)
291: {
292: case PKCS5_SCHEME_PBES1:
293: {
294: if (!this->data.pbes1.hasher)
295: {
296: hasher_t *hasher;
297:
298: hasher = lib->crypto->create_hasher(lib->crypto,
299: this->data.pbes1.hash);
300: if (!hasher)
301: {
302: DBG1(DBG_ASN, " %N hash algorithm not available",
303: hash_algorithm_names, this->data.pbes1.hash);
304: return FALSE;
305: }
306: if (hasher->get_hash_size(hasher) < this->keylen)
307: {
308: hasher->destroy(hasher);
309: return FALSE;
310: }
311: this->data.pbes1.hasher = hasher;
312: }
313: break;
314: }
315: case PKCS5_SCHEME_PBES2:
316: {
317: if (!this->data.pbes2.prf)
318: {
319: prf_t *prf;
320:
321: prf = lib->crypto->create_prf(lib->crypto,
322: this->data.pbes2.prf_alg);
323: if (!prf)
324: {
325: DBG1(DBG_ASN, " %N prf algorithm not available",
326: pseudo_random_function_names,
327: this->data.pbes2.prf_alg);
328: return FALSE;
329: }
330: this->data.pbes2.prf = prf;
331: }
332: break;
333: }
334: case PKCS5_SCHEME_PKCS12:
335: break;
336: }
337: return TRUE;
338: }
339:
340: METHOD(pkcs5_t, decrypt, bool,
341: private_pkcs5_t *this, chunk_t password, chunk_t data, chunk_t *decrypted)
342: {
343: chunk_t keymat, key, iv;
344: kdf_t kdf;
345:
346: if (!ensure_crypto_primitives(this, data) || !decrypted)
347: {
348: return FALSE;
349: }
350: kdf = pbkdf1;
351: switch (this->scheme)
352: {
353: case PKCS5_SCHEME_PKCS12:
354: kdf = pkcs12_kdf;
355: /* fall-through */
356: case PKCS5_SCHEME_PBES1:
357: keymat = chunk_alloca(this->keylen +
358: this->crypter->get_iv_size(this->crypter));
359: key = chunk_create(keymat.ptr, this->keylen);
360: iv = chunk_create(keymat.ptr + this->keylen,
361: keymat.len - this->keylen);
362: break;
363: case PKCS5_SCHEME_PBES2:
364: kdf = pbkdf2;
365: keymat = chunk_alloca(this->keylen);
366: key = keymat;
367: iv = this->data.pbes2.iv;
368: break;
369: default:
370: return FALSE;
371: }
372: return decrypt_generic(this, password, data, decrypted, kdf,
373: keymat, key, iv);
374: }
375:
376: /**
377: * ASN.1 definition of a PBEParameter structure
378: */
379: static const asn1Object_t pbeParameterObjects[] = {
380: { 0, "PBEParameter", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
381: { 1, "salt", ASN1_OCTET_STRING, ASN1_BODY }, /* 1 */
382: { 1, "iterationCount", ASN1_INTEGER, ASN1_BODY }, /* 2 */
383: { 0, "exit", ASN1_EOC, ASN1_EXIT }
384: };
385: #define PBEPARAM_SALT 1
386: #define PBEPARAM_ITERATION_COUNT 2
387:
388: /**
389: * Parse a PBEParameter structure
390: */
391: static bool parse_pbes1_params(private_pkcs5_t *this, chunk_t blob, int level0)
392: {
393: asn1_parser_t *parser;
394: chunk_t object;
395: int objectID;
396: bool success;
397:
398: parser = asn1_parser_create(pbeParameterObjects, blob);
399: parser->set_top_level(parser, level0);
400:
401: while (parser->iterate(parser, &objectID, &object))
402: {
403: switch (objectID)
404: {
405: case PBEPARAM_SALT:
406: {
407: this->salt = chunk_clone(object);
408: break;
409: }
410: case PBEPARAM_ITERATION_COUNT:
411: {
412: this->iterations = asn1_parse_integer_uint64(object);
413: break;
414: }
415: }
416: }
417: success = parser->success(parser);
418: parser->destroy(parser);
419: return success;
420: }
421:
422: /**
423: * ASN.1 definition of a PBKDF2-params structure
424: * The salt is actually a CHOICE and could be an AlgorithmIdentifier from
425: * PBKDF2-SaltSources (but as per RFC 8018 that's for future versions).
426: * The PRF algorithm is actually defined as DEFAULT and not OPTIONAL, but the
427: * parser can't handle ASN1_DEF with SEQUENCEs.
428: */
429: static const asn1Object_t pbkdf2ParamsObjects[] = {
430: { 0, "PBKDF2-params", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
431: { 1, "salt", ASN1_OCTET_STRING, ASN1_BODY }, /* 1 */
432: { 1, "iterationCount",ASN1_INTEGER, ASN1_BODY }, /* 2 */
433: { 1, "keyLength", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 3 */
434: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
435: { 1, "prf", ASN1_SEQUENCE, ASN1_OPT|ASN1_RAW }, /* 5 */
436: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
437: { 0, "exit", ASN1_EOC, ASN1_EXIT }
438: };
439: #define PBKDF2_SALT 1
440: #define PBKDF2_ITERATION_COUNT 2
441: #define PBKDF2_KEYLENGTH 3
442: #define PBKDF2_PRF 5
443:
444: /**
445: * Parse a PBKDF2-params structure
446: */
447: static bool parse_pbkdf2_params(private_pkcs5_t *this, chunk_t blob, int level0)
448: {
449: asn1_parser_t *parser;
450: chunk_t object;
451: int objectID;
452: bool success = FALSE;
453:
454: parser = asn1_parser_create(pbkdf2ParamsObjects, blob);
455: parser->set_top_level(parser, level0);
456:
457: /* keylen is optional */
458: this->keylen = 0;
459: /* defaults to id-hmacWithSHA1 */
460: this->data.pbes2.prf_alg = PRF_HMAC_SHA1;
461:
462: while (parser->iterate(parser, &objectID, &object))
463: {
464: switch (objectID)
465: {
466: case PBKDF2_SALT:
467: {
468: this->salt = chunk_clone(object);
469: break;
470: }
471: case PBKDF2_ITERATION_COUNT:
472: {
473: this->iterations = asn1_parse_integer_uint64(object);
474: break;
475: }
476: case PBKDF2_KEYLENGTH:
477: {
478: this->keylen = (size_t)asn1_parse_integer_uint64(object);
479: break;
480: }
481: case PBKDF2_PRF:
482: {
483: int oid;
484:
485: oid = asn1_parse_algorithmIdentifier(object,
486: parser->get_level(parser) + 1, NULL);
487: this->data.pbes2.prf_alg = pseudo_random_function_from_oid(oid);
488: if (this->data.pbes2.prf_alg == PRF_UNDEFINED)
489: { /* unsupported PRF algorithm */
490: goto end;
491: }
492: break;
493: }
494: }
495: }
496: success = parser->success(parser);
497: end:
498: parser->destroy(parser);
499: return success;
500: }
501:
502: /**
503: * ASN.1 definition of a PBES2-params structure
504: */
505: static const asn1Object_t pbes2ParamsObjects[] = {
506: { 0, "PBES2-params", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
507: { 1, "keyDerivationFunc", ASN1_EOC, ASN1_RAW }, /* 1 */
508: { 1, "encryptionScheme", ASN1_EOC, ASN1_RAW }, /* 2 */
509: { 0, "exit", ASN1_EOC, ASN1_EXIT }
510: };
511: #define PBES2PARAMS_KEY_DERIVATION_FUNC 1
512: #define PBES2PARAMS_ENCRYPTION_SCHEME 2
513:
514: /**
515: * Parse a PBES2-params structure
516: */
517: static bool parse_pbes2_params(private_pkcs5_t *this, chunk_t blob, int level0)
518: {
519: asn1_parser_t *parser;
520: chunk_t object, params;
521: size_t keylen;
522: int objectID;
523: bool success = FALSE;
524:
525: parser = asn1_parser_create(pbes2ParamsObjects, blob);
526: parser->set_top_level(parser, level0);
527:
528: while (parser->iterate(parser, &objectID, &object))
529: {
530: switch (objectID)
531: {
532: case PBES2PARAMS_KEY_DERIVATION_FUNC:
533: {
534: int oid = asn1_parse_algorithmIdentifier(object,
535: parser->get_level(parser) + 1, ¶ms);
536: if (oid != OID_PBKDF2)
537: { /* unsupported key derivation function */
538: goto end;
539: }
540: if (!parse_pbkdf2_params(this, params,
541: parser->get_level(parser) + 1))
542: {
543: goto end;
544: }
545: break;
546: }
547: case PBES2PARAMS_ENCRYPTION_SCHEME:
548: {
549: int oid = asn1_parse_algorithmIdentifier(object,
550: parser->get_level(parser) + 1, ¶ms);
551: this->encr = encryption_algorithm_from_oid(oid, &keylen);
552: if (this->encr == ENCR_UNDEFINED)
553: { /* unsupported encryption scheme */
554: goto end;
555: }
556: /* prefer encoded key length */
557: this->keylen = this->keylen ?: keylen / 8;
558: if (!this->keylen)
559: { /* set default key length for known algorithms */
560: switch (this->encr)
561: {
562: case ENCR_DES:
563: this->keylen = 8;
564: break;
565: case ENCR_3DES:
566: this->keylen = 24;
567: break;
568: case ENCR_BLOWFISH:
569: this->keylen = 16;
570: break;
571: default:
572: goto end;
573: }
574: }
575: if (!asn1_parse_simple_object(¶ms, ASN1_OCTET_STRING,
576: parser->get_level(parser) + 1, "IV"))
577: {
578: goto end;
579: }
580: this->data.pbes2.iv = chunk_clone(params);
581: break;
582: }
583: }
584: }
585: success = parser->success(parser);
586: end:
587: parser->destroy(parser);
588: return success;
589: }
590:
591: METHOD(pkcs5_t, destroy, void,
592: private_pkcs5_t *this)
593: {
594: DESTROY_IF(this->crypter);
595: chunk_free(&this->salt);
596: switch (this->scheme)
597: {
598: case PKCS5_SCHEME_PBES1:
599: DESTROY_IF(this->data.pbes1.hasher);
600: break;
601: case PKCS5_SCHEME_PBES2:
602: DESTROY_IF(this->data.pbes2.prf);
603: chunk_free(&this->data.pbes2.iv);
604: break;
605: case PKCS5_SCHEME_PKCS12:
606: break;
607: }
608: free(this);
609: }
610:
611: /*
612: * Described in header
613: */
614: pkcs5_t *pkcs5_from_algorithmIdentifier(chunk_t blob, int level0)
615: {
616: private_pkcs5_t *this;
617: chunk_t params;
618: int oid;
619:
620: INIT(this,
621: .public = {
622: .decrypt = _decrypt,
623: .destroy = _destroy,
624: },
625: .scheme = PKCS5_SCHEME_PBES1,
626: .keylen = 8,
627: );
628:
629: oid = asn1_parse_algorithmIdentifier(blob, level0, ¶ms);
630:
631: switch (oid)
632: {
633: case OID_PBE_MD5_DES_CBC:
634: this->encr = ENCR_DES;
635: this->data.pbes1.hash = HASH_MD5;
636: break;
637: case OID_PBE_SHA1_DES_CBC:
638: this->encr = ENCR_DES;
639: this->data.pbes1.hash = HASH_SHA1;
640: break;
641: case OID_PBE_SHA1_3DES_CBC:
642: this->scheme = PKCS5_SCHEME_PKCS12;
643: this->keylen = 24;
644: this->encr = ENCR_3DES;
645: this->data.pbes1.hash = HASH_SHA1;
646: break;
647: case OID_PBE_SHA1_RC2_CBC_40:
648: case OID_PBE_SHA1_RC2_CBC_128:
649: this->scheme = PKCS5_SCHEME_PKCS12;
650: this->keylen = (oid == OID_PBE_SHA1_RC2_CBC_40) ? 5 : 16;
651: this->encr = ENCR_RC2_CBC;
652: this->data.pbes1.hash = HASH_SHA1;
653: break;
654: case OID_PBES2:
655: this->scheme = PKCS5_SCHEME_PBES2;
656: break;
657: default:
658: /* encryption scheme not supported */
659: goto failure;
660: }
661:
662: switch (this->scheme)
663: {
664: case PKCS5_SCHEME_PBES1:
665: case PKCS5_SCHEME_PKCS12:
666: if (!parse_pbes1_params(this, params, level0))
667: {
668: goto failure;
669: }
670: break;
671: case PKCS5_SCHEME_PBES2:
672: if (!parse_pbes2_params(this, params, level0))
673: {
674: goto failure;
675: }
676: break;
677: }
678: return &this->public;
679:
680: failure:
681: destroy(this);
682: return NULL;
683: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>