1 /* $OpenBSD: p5_pbev2.c,v 1.35 2024/03/26 07:03:10 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 1999-2004.
4 */
5 /* ====================================================================
6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62
63 #include <openssl/asn1t.h>
64 #include <openssl/err.h>
65 #include <openssl/x509.h>
66
67 #include "evp_local.h"
68 #include "x509_local.h"
69
70 /* PKCS#5 v2.0 password based encryption structures */
71
72 static const ASN1_TEMPLATE PBE2PARAM_seq_tt[] = {
73 {
74 .offset = offsetof(PBE2PARAM, keyfunc),
75 .field_name = "keyfunc",
76 .item = &X509_ALGOR_it,
77 },
78 {
79 .offset = offsetof(PBE2PARAM, encryption),
80 .field_name = "encryption",
81 .item = &X509_ALGOR_it,
82 },
83 };
84
85 const ASN1_ITEM PBE2PARAM_it = {
86 .itype = ASN1_ITYPE_SEQUENCE,
87 .utype = V_ASN1_SEQUENCE,
88 .templates = PBE2PARAM_seq_tt,
89 .tcount = sizeof(PBE2PARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
90 .size = sizeof(PBE2PARAM),
91 .sname = "PBE2PARAM",
92 };
93
94
95 PBE2PARAM *
d2i_PBE2PARAM(PBE2PARAM ** a,const unsigned char ** in,long len)96 d2i_PBE2PARAM(PBE2PARAM **a, const unsigned char **in, long len)
97 {
98 return (PBE2PARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
99 &PBE2PARAM_it);
100 }
101
102 int
i2d_PBE2PARAM(PBE2PARAM * a,unsigned char ** out)103 i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **out)
104 {
105 return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBE2PARAM_it);
106 }
107
108 PBE2PARAM *
PBE2PARAM_new(void)109 PBE2PARAM_new(void)
110 {
111 return (PBE2PARAM *)ASN1_item_new(&PBE2PARAM_it);
112 }
113
114 void
PBE2PARAM_free(PBE2PARAM * a)115 PBE2PARAM_free(PBE2PARAM *a)
116 {
117 ASN1_item_free((ASN1_VALUE *)a, &PBE2PARAM_it);
118 }
119
120 static const ASN1_TEMPLATE PBKDF2PARAM_seq_tt[] = {
121 {
122 .offset = offsetof(PBKDF2PARAM, salt),
123 .field_name = "salt",
124 .item = &ASN1_ANY_it,
125 },
126 {
127 .offset = offsetof(PBKDF2PARAM, iter),
128 .field_name = "iter",
129 .item = &ASN1_INTEGER_it,
130 },
131 {
132 .flags = ASN1_TFLG_OPTIONAL,
133 .offset = offsetof(PBKDF2PARAM, keylength),
134 .field_name = "keylength",
135 .item = &ASN1_INTEGER_it,
136 },
137 {
138 .flags = ASN1_TFLG_OPTIONAL,
139 .offset = offsetof(PBKDF2PARAM, prf),
140 .field_name = "prf",
141 .item = &X509_ALGOR_it,
142 },
143 };
144
145 const ASN1_ITEM PBKDF2PARAM_it = {
146 .itype = ASN1_ITYPE_SEQUENCE,
147 .utype = V_ASN1_SEQUENCE,
148 .templates = PBKDF2PARAM_seq_tt,
149 .tcount = sizeof(PBKDF2PARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
150 .size = sizeof(PBKDF2PARAM),
151 .sname = "PBKDF2PARAM",
152 };
153
154
155 PBKDF2PARAM *
d2i_PBKDF2PARAM(PBKDF2PARAM ** a,const unsigned char ** in,long len)156 d2i_PBKDF2PARAM(PBKDF2PARAM **a, const unsigned char **in, long len)
157 {
158 return (PBKDF2PARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
159 &PBKDF2PARAM_it);
160 }
161
162 int
i2d_PBKDF2PARAM(PBKDF2PARAM * a,unsigned char ** out)163 i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **out)
164 {
165 return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBKDF2PARAM_it);
166 }
167
168 PBKDF2PARAM *
PBKDF2PARAM_new(void)169 PBKDF2PARAM_new(void)
170 {
171 return (PBKDF2PARAM *)ASN1_item_new(&PBKDF2PARAM_it);
172 }
173
174 void
PBKDF2PARAM_free(PBKDF2PARAM * a)175 PBKDF2PARAM_free(PBKDF2PARAM *a)
176 {
177 ASN1_item_free((ASN1_VALUE *)a, &PBKDF2PARAM_it);
178 }
179
180 /*
181 * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm:
182 * yes I know this is horrible!
183 */
184
185 X509_ALGOR *
PKCS5_pbe2_set(const EVP_CIPHER * cipher,int iter,unsigned char * salt,int saltlen)186 PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, unsigned char *salt,
187 int saltlen)
188 {
189 X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL;
190 int prf_nid = NID_hmacWithSHA1;
191 int alg_nid, keylen;
192 EVP_CIPHER_CTX ctx;
193 unsigned char iv[EVP_MAX_IV_LENGTH];
194 PBE2PARAM *pbe2 = NULL;
195 ASN1_OBJECT *obj;
196
197 alg_nid = EVP_CIPHER_type(cipher);
198 if (alg_nid == NID_undef) {
199 ASN1error(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
200 goto err;
201 }
202 obj = OBJ_nid2obj(alg_nid);
203
204 if (!(pbe2 = PBE2PARAM_new()))
205 goto merr;
206
207 /* Setup the AlgorithmIdentifier for the encryption scheme */
208 scheme = pbe2->encryption;
209
210 scheme->algorithm = obj;
211 if (!(scheme->parameter = ASN1_TYPE_new()))
212 goto merr;
213
214 /* Create random IV */
215 if (EVP_CIPHER_iv_length(cipher) > 0)
216 arc4random_buf(iv, EVP_CIPHER_iv_length(cipher));
217
218 EVP_CIPHER_CTX_legacy_clear(&ctx);
219
220 /* Dummy cipherinit to just setup the IV, and PRF */
221 if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0))
222 goto err;
223 if (EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) {
224 ASN1error(ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
225 EVP_CIPHER_CTX_cleanup(&ctx);
226 goto err;
227 }
228 EVP_CIPHER_CTX_cleanup(&ctx);
229
230 /* If its RC2 then we'd better setup the key length */
231
232 if (alg_nid == NID_rc2_cbc)
233 keylen = EVP_CIPHER_key_length(cipher);
234 else
235 keylen = -1;
236
237 /* Setup keyfunc */
238
239 X509_ALGOR_free(pbe2->keyfunc);
240
241 pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
242
243 if (!pbe2->keyfunc)
244 goto merr;
245
246 /* Now set up top level AlgorithmIdentifier */
247
248 if (!(ret = X509_ALGOR_new()))
249 goto merr;
250 if (!(ret->parameter = ASN1_TYPE_new()))
251 goto merr;
252
253 ret->algorithm = OBJ_nid2obj(NID_pbes2);
254
255 /* Encode PBE2PARAM into parameter */
256
257 if (!ASN1_item_pack(pbe2, &PBE2PARAM_it,
258 &ret->parameter->value.sequence)) goto merr;
259 ret->parameter->type = V_ASN1_SEQUENCE;
260
261 PBE2PARAM_free(pbe2);
262 pbe2 = NULL;
263
264 return ret;
265
266 merr:
267 ASN1error(ERR_R_MALLOC_FAILURE);
268
269 err:
270 PBE2PARAM_free(pbe2);
271 /* Note 'scheme' is freed as part of pbe2 */
272 X509_ALGOR_free(kalg);
273 X509_ALGOR_free(ret);
274
275 return NULL;
276 }
277
278 X509_ALGOR *
PKCS5_pbkdf2_set(int iter,unsigned char * salt,int saltlen,int prf_nid,int keylen)279 PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, int prf_nid,
280 int keylen)
281 {
282 X509_ALGOR *keyfunc = NULL;
283 PBKDF2PARAM *kdf = NULL;
284 ASN1_OCTET_STRING *osalt = NULL;
285
286 if (!(kdf = PBKDF2PARAM_new()))
287 goto merr;
288 if (!(osalt = ASN1_OCTET_STRING_new()))
289 goto merr;
290
291 kdf->salt->value.octet_string = osalt;
292 kdf->salt->type = V_ASN1_OCTET_STRING;
293
294 if (!saltlen)
295 saltlen = PKCS5_SALT_LEN;
296 if (!(osalt->data = malloc (saltlen)))
297 goto merr;
298
299 osalt->length = saltlen;
300
301 if (salt)
302 memcpy (osalt->data, salt, saltlen);
303 else
304 arc4random_buf(osalt->data, saltlen);
305
306 if (iter <= 0)
307 iter = PKCS5_DEFAULT_ITER;
308
309 if (!ASN1_INTEGER_set(kdf->iter, iter))
310 goto merr;
311
312 /* If have a key len set it up */
313
314 if (keylen > 0) {
315 if (!(kdf->keylength = ASN1_INTEGER_new()))
316 goto merr;
317 if (!ASN1_INTEGER_set(kdf->keylength, keylen))
318 goto merr;
319 }
320
321 /* prf can stay NULL if we are using hmacWithSHA1 */
322 if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) {
323 kdf->prf = X509_ALGOR_new();
324 if (!kdf->prf)
325 goto merr;
326 X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid),
327 V_ASN1_NULL, NULL);
328 }
329
330 /* Finally setup the keyfunc structure */
331
332 keyfunc = X509_ALGOR_new();
333 if (!keyfunc)
334 goto merr;
335
336 keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
337
338 /* Encode PBKDF2PARAM into parameter of pbe2 */
339
340 if (!(keyfunc->parameter = ASN1_TYPE_new()))
341 goto merr;
342
343 if (!ASN1_item_pack(kdf, &PBKDF2PARAM_it,
344 &keyfunc->parameter->value.sequence))
345 goto merr;
346 keyfunc->parameter->type = V_ASN1_SEQUENCE;
347
348 PBKDF2PARAM_free(kdf);
349 return keyfunc;
350
351 merr:
352 ASN1error(ERR_R_MALLOC_FAILURE);
353 PBKDF2PARAM_free(kdf);
354 X509_ALGOR_free(keyfunc);
355 return NULL;
356 }
357