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