xref: /openssl/crypto/asn1/p5_pbev2.c (revision 7ed6de99)
1 /*
2  * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include "crypto/asn1.h"
13 #include "crypto/evp.h"
14 #include <openssl/asn1t.h>
15 #include <openssl/core.h>
16 #include <openssl/core_names.h>
17 #include <openssl/x509.h>
18 #include <openssl/rand.h>
19 
20 /* PKCS#5 v2.0 password based encryption structures */
21 
22 ASN1_SEQUENCE(PBE2PARAM) = {
23         ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
24         ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
25 } ASN1_SEQUENCE_END(PBE2PARAM)
26 
27 IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
28 
29 ASN1_SEQUENCE(PBKDF2PARAM) = {
30         ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
31         ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
32         ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
33         ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
34 } ASN1_SEQUENCE_END(PBKDF2PARAM)
35 
36 IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
37 
38 ASN1_SEQUENCE(PBMAC1PARAM) = {
39     ASN1_SIMPLE(PBMAC1PARAM, keyDerivationFunc, X509_ALGOR),
40     ASN1_SIMPLE(PBMAC1PARAM, messageAuthScheme, X509_ALGOR)
41 } ASN1_SEQUENCE_END(PBMAC1PARAM)
42 
43 IMPLEMENT_ASN1_FUNCTIONS(PBMAC1PARAM)
44 
45 /*
46  * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know
47  * this is horrible! Extended version to allow application supplied PRF NID
48  * and IV.
49  */
50 
51 X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
52                                  unsigned char *salt, int saltlen,
53                                  unsigned char *aiv, int prf_nid,
54                                  OSSL_LIB_CTX *libctx)
55 {
56     X509_ALGOR *scheme = NULL, *ret = NULL;
57     int alg_nid, keylen, ivlen;
58     EVP_CIPHER_CTX *ctx = NULL;
59     unsigned char iv[EVP_MAX_IV_LENGTH];
60     PBE2PARAM *pbe2 = NULL;
61 
62     alg_nid = EVP_CIPHER_get_type(cipher);
63     if (alg_nid == NID_undef) {
64         ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
65         goto err;
66     }
67 
68     if ((pbe2 = PBE2PARAM_new()) == NULL) {
69         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
70         goto err;
71     }
72 
73     /* Setup the AlgorithmIdentifier for the encryption scheme */
74     scheme = pbe2->encryption;
75     scheme->algorithm = OBJ_nid2obj(alg_nid);
76     if ((scheme->parameter = ASN1_TYPE_new()) == NULL) {
77         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
78         goto err;
79     }
80 
81     /* Create random IV */
82     ivlen = EVP_CIPHER_get_iv_length(cipher);
83     if (ivlen > 0) {
84         if (aiv)
85             memcpy(iv, aiv, ivlen);
86         else if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0)
87             goto err;
88     }
89 
90     ctx = EVP_CIPHER_CTX_new();
91     if (ctx == NULL) {
92         ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
93         goto err;
94     }
95 
96     /* Dummy cipherinit to just setup the IV, and PRF */
97     if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0))
98         goto err;
99     if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
100         ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
101         goto err;
102     }
103     /*
104      * If prf NID unspecified see if cipher has a preference. An error is OK
105      * here: just means use default PRF.
106      */
107     ERR_set_mark();
108     if ((prf_nid == -1) &&
109         EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
110         prf_nid = NID_hmacWithSHA256;
111     }
112     ERR_pop_to_mark();
113     EVP_CIPHER_CTX_free(ctx);
114     ctx = NULL;
115 
116     /* If its RC2 then we'd better setup the key length */
117 
118     if (alg_nid == NID_rc2_cbc)
119         keylen = EVP_CIPHER_get_key_length(cipher);
120     else
121         keylen = -1;
122 
123     /* Setup keyfunc */
124 
125     X509_ALGOR_free(pbe2->keyfunc);
126 
127     pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen,
128                                         libctx);
129 
130     if (pbe2->keyfunc == NULL) {
131         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
132         goto err;
133     }
134 
135     /* Now set up top level AlgorithmIdentifier */
136 
137     if ((ret = X509_ALGOR_new()) == NULL) {
138         ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB);
139         goto err;
140     }
141 
142     ret->algorithm = OBJ_nid2obj(NID_pbes2);
143 
144     /* Encode PBE2PARAM into parameter */
145 
146     if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2,
147                                  &ret->parameter)) {
148         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
149         goto err;
150     }
151 
152     PBE2PARAM_free(pbe2);
153     pbe2 = NULL;
154 
155     return ret;
156 
157  err:
158     EVP_CIPHER_CTX_free(ctx);
159     PBE2PARAM_free(pbe2);
160     /* Note 'scheme' is freed as part of pbe2 */
161     X509_ALGOR_free(ret);
162 
163     return NULL;
164 }
165 
PKCS5_pbe2_set_iv(const EVP_CIPHER * cipher,int iter,unsigned char * salt,int saltlen,unsigned char * aiv,int prf_nid)166 X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
167                               unsigned char *salt, int saltlen,
168                               unsigned char *aiv, int prf_nid)
169 {
170     return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, aiv, prf_nid,
171                                 NULL);
172 }
173 
PKCS5_pbe2_set(const EVP_CIPHER * cipher,int iter,unsigned char * salt,int saltlen)174 X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
175                            unsigned char *salt, int saltlen)
176 {
177     return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1,
178                                 NULL);
179 }
180 
181 
PKCS5_pbkdf2_set_ex(int iter,unsigned char * salt,int saltlen,int prf_nid,int keylen,OSSL_LIB_CTX * libctx)182 X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
183                                 int prf_nid, int keylen,
184                                 OSSL_LIB_CTX *libctx)
185 {
186     X509_ALGOR *keyfunc = NULL;
187     PBKDF2PARAM *kdf = NULL;
188     ASN1_OCTET_STRING *osalt = NULL;
189 
190     if ((kdf = PBKDF2PARAM_new()) == NULL) {
191         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
192         goto err;
193     }
194     if ((osalt = ASN1_OCTET_STRING_new()) == NULL) {
195         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
196         goto err;
197     }
198 
199     kdf->salt->value.octet_string = osalt;
200     kdf->salt->type = V_ASN1_OCTET_STRING;
201 
202     if (saltlen < 0) {
203         ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT);
204         goto err;
205     }
206     if (saltlen == 0)
207         saltlen = PKCS5_DEFAULT_PBE2_SALT_LEN;
208     if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
209         goto err;
210 
211 
212     osalt->length = saltlen;
213 
214     if (salt) {
215         memcpy(osalt->data, salt, saltlen);
216     } else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0) {
217         ERR_raise(ERR_LIB_ASN1, ERR_R_RAND_LIB);
218         goto err;
219     }
220 
221     if (iter <= 0)
222         iter = PKCS5_DEFAULT_ITER;
223 
224     if (!ASN1_INTEGER_set(kdf->iter, iter)) {
225         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
226         goto err;
227     }
228 
229     /* If have a key len set it up */
230 
231     if (keylen > 0) {
232         if ((kdf->keylength = ASN1_INTEGER_new()) == NULL) {
233             ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
234             goto err;
235         }
236         if (!ASN1_INTEGER_set(kdf->keylength, keylen)) {
237             ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
238             goto err;
239         }
240     }
241 
242     /* prf can stay NULL if we are using hmacWithSHA1 */
243     if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) {
244         kdf->prf = ossl_X509_ALGOR_from_nid(prf_nid, V_ASN1_NULL, NULL);
245         if (kdf->prf == NULL) {
246             ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB);
247             goto err;
248         }
249     }
250 
251     /* Finally setup the keyfunc structure */
252 
253     keyfunc = X509_ALGOR_new();
254     if (keyfunc == NULL) {
255         ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB);
256         goto err;
257     }
258 
259     keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
260 
261     /* Encode PBKDF2PARAM into parameter of pbe2 */
262 
263     if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf,
264                                  &keyfunc->parameter)) {
265         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
266         goto err;
267     }
268 
269     PBKDF2PARAM_free(kdf);
270     return keyfunc;
271 
272  err:
273     PBKDF2PARAM_free(kdf);
274     X509_ALGOR_free(keyfunc);
275     return NULL;
276 }
277 
PKCS5_pbkdf2_set(int iter,unsigned char * salt,int saltlen,int prf_nid,int keylen)278 X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
279                              int prf_nid, int keylen)
280 {
281     return PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, NULL);
282 }
283 
284