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
14 static const char * const _oid_pbes2 = "1.2.840.113549.1.5.13";
15 static const char * const _oid_pbkdf2 = "1.2.840.113549.1.5.12";
16
17 typedef struct {
18 const char *oid;
19 const char *id;
20 } oid_id_st;
21
22 static const oid_id_st _hmac_oid_names[] = {
23 { "1.2.840.113549.2.7", "sha1" },
24 { "1.2.840.113549.2.8", "sha224" },
25 { "1.2.840.113549.2.9", "sha256" },
26 { "1.2.840.113549.2.10", "sha384" },
27 { "1.2.840.113549.2.11", "sha512" },
28 { "1.2.840.113549.2.12", "sha512-224" },
29 { "1.2.840.113549.2.13", "sha512-256" },
30 };
31
32 static const pbes_properties _pbes2_default_types[] = {
33 { pkcs_5_alg2, "sha1", "des", 8, 0 },
34 { pkcs_5_alg2, "sha1", "rc2", 4, 0 },
35 { pkcs_5_alg2, "sha1", "3des", 24, 0 },
36 { pkcs_5_alg2, "sha1", "aes", 16, 0 },
37 { pkcs_5_alg2, "sha1", "aes", 24, 0 },
38 { pkcs_5_alg2, "sha1", "aes", 32, 0 },
39 };
40
41 typedef struct {
42 const pbes_properties *data;
43 const char* oid;
44 } oid_to_pbes;
45
46 static const oid_to_pbes _pbes2_list[] = {
47 { &_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */
48 { &_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */
49 { &_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */
50 { &_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */
51 { &_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */
52 { &_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */
53 };
54
_pbes2_from_oid(const ltc_asn1_list * cipher_oid,const ltc_asn1_list * hmac_oid,pbes_properties * res)55 static int _pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res)
56 {
57 unsigned int i;
58 for (i = 0; i < sizeof(_pbes2_list)/sizeof(_pbes2_list[0]); ++i) {
59 if (pk_oid_cmp_with_asn1(_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) {
60 *res = *_pbes2_list[i].data;
61 break;
62 }
63 }
64 if (res->c == NULL) return CRYPT_INVALID_CIPHER;
65 if (hmac_oid != NULL) {
66 for (i = 0; i < sizeof(_hmac_oid_names)/sizeof(_hmac_oid_names[0]); ++i) {
67 if (pk_oid_cmp_with_asn1(_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) {
68 res->h = _hmac_oid_names[i].id;
69 return CRYPT_OK;
70 }
71 }
72 return CRYPT_INVALID_HASH;
73 }
74 return CRYPT_OK;
75 }
76
77
78 /**
79 Extract PBES2 parameters
80
81 @param s The start of the sequence with potential PBES2 parameters
82 @param res Pointer to where the extracted parameters should be stored
83 @return CRYPT_OK on success
84 */
pbes2_extract(const ltc_asn1_list * s,pbes_arg * res)85 int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res)
86 {
87 unsigned long klen;
88 ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac;
89 int err;
90
91 LTC_ARGCHK(s != NULL);
92 LTC_ARGCHK(res != NULL);
93
94 if ((err = pk_oid_cmp_with_asn1(_oid_pbes2, s)) != CRYPT_OK) return err;
95
96 if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
97 !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) ||
98 !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) ||
99 !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) ||
100 !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) ||
101 !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
102 return CRYPT_INVALID_PACKET;
103 }
104 /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
105 * 0:d=0 hl=4 l= 380 cons: SEQUENCE
106 * 4:d=1 hl=2 l= 78 cons: SEQUENCE
107 * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s)
108 * 17:d=2 hl=2 l= 65 cons: SEQUENCE
109 * 19:d=3 hl=2 l= 41 cons: SEQUENCE
110 * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf)
111 * 32:d=4 hl=2 l= 28 cons: SEQUENCE
112 * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt)
113 * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter)
114 * 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing)
115 * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac)
116 * 60:d=6 hl=2 l= 0 prim: NULL
117 * 62:d=3 hl=2 l= 20 cons: SEQUENCE
118 * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc)
119 * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A
120 * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
121 */
122 lkdf = s->next->child->child;
123 lenc = s->next->child->next->child;
124
125 if ((err = pk_oid_cmp_with_asn1(_oid_pbkdf2, lkdf)) != CRYPT_OK) return err;
126
127 if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) ||
128 !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) ||
129 !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) {
130 return CRYPT_INVALID_PACKET;
131 }
132
133 liter = lkdf->next->child->next;
134 loptseq = liter->next;
135 res->salt = lkdf->next->child;
136 res->iterations = mp_get_int(liter->data);
137
138 /* There's an optional INTEGER keyLength after the iterations, skip that if it's there.
139 * c.f. RFC 2898 A.2 PBKDF2 */
140 if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) {
141 loptseq = loptseq->next;
142 }
143
144 /* this sequence is optional */
145 lhmac = NULL;
146 if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) &&
147 LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
148 lhmac = loptseq->child;
149 }
150 if ((err = _pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err;
151
152 if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) {
153 /* 'NON-RC2'-CBC */
154 res->iv = lenc->next;
155 } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) {
156 /* RC2-CBC is a bit special ...
157 *
158 * RC2-CBC-Parameter ::= SEQUENCE {
159 * rc2ParameterVersion INTEGER OPTIONAL,
160 * iv OCTET STRING (SIZE(8)) }
161 */
162 if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) &&
163 LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) {
164 klen = mp_get_int(lenc->next->child->data);
165 res->iv = lenc->next->child->next;
166 /*
167 * Effective Key Bits Encoding
168 * 40 160
169 * 64 120
170 * 128 58
171 * b >= 256 b
172 */
173 switch (klen) {
174 case 160:
175 res->key_bits = 40;
176 break;
177 case 120:
178 res->key_bits = 64;
179 break;
180 case 58:
181 res->key_bits = 128;
182 break;
183 default:
184 /* We don't handle undefined Key Bits */
185 if (klen < 256) return CRYPT_INVALID_KEYSIZE;
186
187 res->key_bits = klen;
188 break;
189 }
190 } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) {
191 res->iv = lenc->next->child;
192 /*
193 * If the rc2ParameterVersion field is omitted, the "effective key bits"
194 * defaults to 32.
195 */
196 res->key_bits = 32;
197 } else {
198 return CRYPT_INVALID_PACKET;
199 }
200 }
201
202 return CRYPT_OK;
203 }
204
205 #endif
206
207 /* ref: $Format:%D$ */
208 /* git commit: $Format:%H$ */
209 /* commit time: $Format:%ai$ */
210