1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10 #include "tomcrypt_private.h"
11
12 #ifdef LTC_PBES
13
_pkcs_5_alg1_wrap(const unsigned char * password,unsigned long password_len,const unsigned char * salt,unsigned long salt_len,int iteration_count,int hash_idx,unsigned char * out,unsigned long * outlen)14 static int _pkcs_5_alg1_wrap(const unsigned char *password, unsigned long password_len,
15 const unsigned char *salt, unsigned long salt_len,
16 int iteration_count, int hash_idx,
17 unsigned char *out, unsigned long *outlen)
18 {
19 LTC_UNUSED_PARAM(salt_len);
20 return pkcs_5_alg1(password, password_len, salt, iteration_count, hash_idx, out, outlen);
21 }
22
_pkcs_12_wrap(const unsigned char * password,unsigned long password_len,const unsigned char * salt,unsigned long salt_len,int iteration_count,int hash_idx,unsigned char * out,unsigned long * outlen)23 static int _pkcs_12_wrap(const unsigned char *password, unsigned long password_len,
24 const unsigned char *salt, unsigned long salt_len,
25 int iteration_count, int hash_idx,
26 unsigned char *out, unsigned long *outlen)
27 {
28 int err;
29 /* convert password to unicode/utf16-be */
30 unsigned long pwlen = password_len * 2;
31 unsigned char* pw;
32 if (*outlen < 32) return CRYPT_INVALID_ARG;
33 pw = XMALLOC(pwlen + 2);
34 if (pw == NULL) return CRYPT_MEM;
35 if ((err = pkcs12_utf8_to_utf16(password, password_len, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR;
36 pw[pwlen++] = 0;
37 pw[pwlen++] = 0;
38 /* derive KEY */
39 if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR;
40 /* derive IV */
41 if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR;
42
43 *outlen = 32;
44 LBL_ERROR:
45 zeromem(pw, pwlen);
46 XFREE(pw);
47 return err;
48 }
49
50 static const pbes_properties _pbes1_types[] = {
51 { _pkcs_5_alg1_wrap, "md2", "des", 8, 8 },
52 { _pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 },
53 { _pkcs_5_alg1_wrap, "md5", "des", 8, 8 },
54 { _pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 },
55 { _pkcs_5_alg1_wrap, "sha1", "des", 8, 8 },
56 { _pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 },
57 { _pkcs_12_wrap, "sha1", "3des", 24, 8 },
58 };
59
60 typedef struct {
61 const pbes_properties *data;
62 const char *oid;
63 } oid_to_pbes;
64
65 static const oid_to_pbes _pbes1_list[] = {
66 { &_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
67 { &_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
68 { &_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
69 { &_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
70 { &_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
71 { &_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
72 { &_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
73 { 0 },
74 };
75
_pbes1_from_oid(const ltc_asn1_list * oid,pbes_properties * res)76 static int _pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res)
77 {
78 unsigned int i;
79 for (i = 0; _pbes1_list[i].data != NULL; ++i) {
80 if (pk_oid_cmp_with_asn1(_pbes1_list[i].oid, oid) == CRYPT_OK) {
81 if (res != NULL) *res = *_pbes1_list[i].data;
82 return CRYPT_OK;
83 }
84 }
85 return CRYPT_INVALID_ARG;
86 }
87
88 /**
89 Extract PBES1 parameters
90
91 @param s The start of the sequence with potential PBES1 parameters
92 @param res Pointer to where the extracted parameters should be stored
93 @return CRYPT_OK on success
94 */
pbes1_extract(const ltc_asn1_list * s,pbes_arg * res)95 int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res)
96 {
97 int err;
98
99 LTC_ARGCHK(s != NULL);
100 LTC_ARGCHK(res != NULL);
101
102 if ((err = _pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err;
103
104 if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
105 !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) ||
106 !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) {
107 return CRYPT_INVALID_PACKET;
108 }
109 /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
110 * 0:d=0 hl=4 l= 329 cons: SEQUENCE
111 * 4:d=1 hl=2 l= 27 cons: SEQUENCE
112 * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s)
113 * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
114 * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
115 * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
116 * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
117 */
118 res->salt = s->next->child;
119 res->iterations = mp_get_int(s->next->child->next->data);
120
121 return CRYPT_OK;
122 }
123
124 #endif
125
126 /* ref: $Format:%D$ */
127 /* git commit: $Format:%H$ */
128 /* commit time: $Format:%ai$ */
129