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/pkcs12.h>
13e1051a39Sopenharmony_ci#include <openssl/bn.h>
14e1051a39Sopenharmony_ci#include <openssl/trace.h>
15e1051a39Sopenharmony_ci#include <openssl/kdf.h>
16e1051a39Sopenharmony_ci#include <openssl/core_names.h>
17e1051a39Sopenharmony_ci#include "internal/provider.h"
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ciint PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
20e1051a39Sopenharmony_ci                          int saltlen, int id, int iter, int n,
21e1051a39Sopenharmony_ci                          unsigned char *out, const EVP_MD *md_type,
22e1051a39Sopenharmony_ci                          OSSL_LIB_CTX *ctx, const char *propq)
23e1051a39Sopenharmony_ci{
24e1051a39Sopenharmony_ci    int ret;
25e1051a39Sopenharmony_ci    unsigned char *unipass;
26e1051a39Sopenharmony_ci    int uniplen;
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ci    if (pass == NULL) {
29e1051a39Sopenharmony_ci        unipass = NULL;
30e1051a39Sopenharmony_ci        uniplen = 0;
31e1051a39Sopenharmony_ci    } else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) {
32e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
33e1051a39Sopenharmony_ci        return 0;
34e1051a39Sopenharmony_ci    }
35e1051a39Sopenharmony_ci    ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter,
36e1051a39Sopenharmony_ci                                n, out, md_type, ctx, propq);
37e1051a39Sopenharmony_ci    OPENSSL_clear_free(unipass, uniplen);
38e1051a39Sopenharmony_ci    return ret > 0;
39e1051a39Sopenharmony_ci}
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ciint PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
42e1051a39Sopenharmony_ci                       int saltlen, int id, int iter, int n,
43e1051a39Sopenharmony_ci                       unsigned char *out, const EVP_MD *md_type)
44e1051a39Sopenharmony_ci{
45e1051a39Sopenharmony_ci    return PKCS12_key_gen_asc_ex(pass, passlen, salt, saltlen, id, iter, n,
46e1051a39Sopenharmony_ci                                  out, md_type, NULL, NULL);
47e1051a39Sopenharmony_ci}
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_ciint PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
50e1051a39Sopenharmony_ci                           int saltlen, int id, int iter, int n,
51e1051a39Sopenharmony_ci                           unsigned char *out, const EVP_MD *md_type,
52e1051a39Sopenharmony_ci                           OSSL_LIB_CTX *ctx, const char *propq)
53e1051a39Sopenharmony_ci{
54e1051a39Sopenharmony_ci    int ret;
55e1051a39Sopenharmony_ci    unsigned char *unipass;
56e1051a39Sopenharmony_ci    int uniplen;
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_ci    if (pass == NULL) {
59e1051a39Sopenharmony_ci        unipass = NULL;
60e1051a39Sopenharmony_ci        uniplen = 0;
61e1051a39Sopenharmony_ci    } else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) {
62e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
63e1051a39Sopenharmony_ci        return 0;
64e1051a39Sopenharmony_ci    }
65e1051a39Sopenharmony_ci    ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter,
66e1051a39Sopenharmony_ci                                n, out, md_type, ctx, propq);
67e1051a39Sopenharmony_ci    OPENSSL_clear_free(unipass, uniplen);
68e1051a39Sopenharmony_ci    return ret > 0;
69e1051a39Sopenharmony_ci}
70e1051a39Sopenharmony_ci
71e1051a39Sopenharmony_ciint PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
72e1051a39Sopenharmony_ci                        int saltlen, int id, int iter, int n,
73e1051a39Sopenharmony_ci                        unsigned char *out, const EVP_MD *md_type)
74e1051a39Sopenharmony_ci{
75e1051a39Sopenharmony_ci    return PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, id, iter, n,
76e1051a39Sopenharmony_ci                                  out, md_type, NULL, NULL);
77e1051a39Sopenharmony_ci}
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ciint PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
80e1051a39Sopenharmony_ci                          int saltlen, int id, int iter, int n,
81e1051a39Sopenharmony_ci                          unsigned char *out, const EVP_MD *md_type,
82e1051a39Sopenharmony_ci                          OSSL_LIB_CTX *libctx, const char *propq)
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    int res = 0;
85e1051a39Sopenharmony_ci    EVP_KDF *kdf;
86e1051a39Sopenharmony_ci    EVP_KDF_CTX *ctx;
87e1051a39Sopenharmony_ci    OSSL_PARAM params[6], *p = params;
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci    if (n <= 0)
90e1051a39Sopenharmony_ci        return 0;
91e1051a39Sopenharmony_ci
92e1051a39Sopenharmony_ci    kdf = EVP_KDF_fetch(libctx, "PKCS12KDF", propq);
93e1051a39Sopenharmony_ci    if (kdf == NULL)
94e1051a39Sopenharmony_ci        return 0;
95e1051a39Sopenharmony_ci    ctx = EVP_KDF_CTX_new(kdf);
96e1051a39Sopenharmony_ci    EVP_KDF_free(kdf);
97e1051a39Sopenharmony_ci    if (ctx == NULL)
98e1051a39Sopenharmony_ci        return 0;
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_ci    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
101e1051a39Sopenharmony_ci                                            (char *)EVP_MD_get0_name(md_type),
102e1051a39Sopenharmony_ci                                            0);
103e1051a39Sopenharmony_ci    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
104e1051a39Sopenharmony_ci                                             pass, passlen);
105e1051a39Sopenharmony_ci    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
106e1051a39Sopenharmony_ci                                             salt, saltlen);
107e1051a39Sopenharmony_ci    *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS12_ID, &id);
108e1051a39Sopenharmony_ci    *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
109e1051a39Sopenharmony_ci    *p = OSSL_PARAM_construct_end();
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci    OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
112e1051a39Sopenharmony_ci        BIO_printf(trc_out, "PKCS12_key_gen_uni_ex(): ID %d, ITER %d\n", id, iter);
113e1051a39Sopenharmony_ci        BIO_printf(trc_out, "Password (length %d):\n", passlen);
114e1051a39Sopenharmony_ci        BIO_hex_string(trc_out, 0, passlen, pass, passlen);
115e1051a39Sopenharmony_ci        BIO_printf(trc_out, "\n");
116e1051a39Sopenharmony_ci        BIO_printf(trc_out, "Salt (length %d):\n", saltlen);
117e1051a39Sopenharmony_ci        BIO_hex_string(trc_out, 0, saltlen, salt, saltlen);
118e1051a39Sopenharmony_ci        BIO_printf(trc_out, "\n");
119e1051a39Sopenharmony_ci    } OSSL_TRACE_END(PKCS12_KEYGEN);
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci    if (EVP_KDF_derive(ctx, out, (size_t)n, params)) {
122e1051a39Sopenharmony_ci        res = 1;
123e1051a39Sopenharmony_ci        OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
124e1051a39Sopenharmony_ci            BIO_printf(trc_out, "Output KEY (length %d)\n", n);
125e1051a39Sopenharmony_ci            BIO_hex_string(trc_out, 0, n, out, n);
126e1051a39Sopenharmony_ci            BIO_printf(trc_out, "\n");
127e1051a39Sopenharmony_ci        } OSSL_TRACE_END(PKCS12_KEYGEN);
128e1051a39Sopenharmony_ci    }
129e1051a39Sopenharmony_ci    EVP_KDF_CTX_free(ctx);
130e1051a39Sopenharmony_ci    return res;
131e1051a39Sopenharmony_ci}
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_ciint PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
134e1051a39Sopenharmony_ci                       int saltlen, int id, int iter, int n,
135e1051a39Sopenharmony_ci                       unsigned char *out, const EVP_MD *md_type)
136e1051a39Sopenharmony_ci{
137e1051a39Sopenharmony_ci    return PKCS12_key_gen_uni_ex(pass, passlen, salt, saltlen, id, iter, n, out, md_type, NULL, NULL);
138e1051a39Sopenharmony_ci}
139