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/*
11e1051a39Sopenharmony_ci * HMAC low level APIs are deprecated for public use, but still ok for internal
12e1051a39Sopenharmony_ci * use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <stdio.h>
17e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
18e1051a39Sopenharmony_ci#include <openssl/crypto.h>
19e1051a39Sopenharmony_ci#include <openssl/hmac.h>
20e1051a39Sopenharmony_ci#include <openssl/rand.h>
21e1051a39Sopenharmony_ci#include <openssl/pkcs12.h>
22e1051a39Sopenharmony_ci#include "p12_local.h"
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ciint PKCS12_mac_present(const PKCS12 *p12)
25e1051a39Sopenharmony_ci{
26e1051a39Sopenharmony_ci    return p12->mac ? 1 : 0;
27e1051a39Sopenharmony_ci}
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_civoid PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac,
30e1051a39Sopenharmony_ci                     const X509_ALGOR **pmacalg,
31e1051a39Sopenharmony_ci                     const ASN1_OCTET_STRING **psalt,
32e1051a39Sopenharmony_ci                     const ASN1_INTEGER **piter,
33e1051a39Sopenharmony_ci                     const PKCS12 *p12)
34e1051a39Sopenharmony_ci{
35e1051a39Sopenharmony_ci    if (p12->mac) {
36e1051a39Sopenharmony_ci        X509_SIG_get0(p12->mac->dinfo, pmacalg, pmac);
37e1051a39Sopenharmony_ci        if (psalt)
38e1051a39Sopenharmony_ci            *psalt = p12->mac->salt;
39e1051a39Sopenharmony_ci        if (piter)
40e1051a39Sopenharmony_ci            *piter = p12->mac->iter;
41e1051a39Sopenharmony_ci    } else {
42e1051a39Sopenharmony_ci        if (pmac)
43e1051a39Sopenharmony_ci            *pmac = NULL;
44e1051a39Sopenharmony_ci        if (pmacalg)
45e1051a39Sopenharmony_ci            *pmacalg = NULL;
46e1051a39Sopenharmony_ci        if (psalt)
47e1051a39Sopenharmony_ci            *psalt = NULL;
48e1051a39Sopenharmony_ci        if (piter)
49e1051a39Sopenharmony_ci            *piter = NULL;
50e1051a39Sopenharmony_ci    }
51e1051a39Sopenharmony_ci}
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_ci#define TK26_MAC_KEY_LEN 32
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_cistatic int pkcs12_gen_gost_mac_key(const char *pass, int passlen,
56e1051a39Sopenharmony_ci                                   const unsigned char *salt, int saltlen,
57e1051a39Sopenharmony_ci                                   int iter, int keylen, unsigned char *key,
58e1051a39Sopenharmony_ci                                   const EVP_MD *digest)
59e1051a39Sopenharmony_ci{
60e1051a39Sopenharmony_ci    unsigned char out[96];
61e1051a39Sopenharmony_ci
62e1051a39Sopenharmony_ci    if (keylen != TK26_MAC_KEY_LEN) {
63e1051a39Sopenharmony_ci        return 0;
64e1051a39Sopenharmony_ci    }
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci    if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter,
67e1051a39Sopenharmony_ci                           digest, sizeof(out), out)) {
68e1051a39Sopenharmony_ci        return 0;
69e1051a39Sopenharmony_ci    }
70e1051a39Sopenharmony_ci    memcpy(key, out + sizeof(out) - TK26_MAC_KEY_LEN, TK26_MAC_KEY_LEN);
71e1051a39Sopenharmony_ci    OPENSSL_cleanse(out, sizeof(out));
72e1051a39Sopenharmony_ci    return 1;
73e1051a39Sopenharmony_ci}
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_ci/* Generate a MAC */
76e1051a39Sopenharmony_cistatic int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
77e1051a39Sopenharmony_ci                          unsigned char *mac, unsigned int *maclen,
78e1051a39Sopenharmony_ci                          int (*pkcs12_key_gen)(const char *pass, int passlen,
79e1051a39Sopenharmony_ci                                                unsigned char *salt, int slen,
80e1051a39Sopenharmony_ci                                                int id, int iter, int n,
81e1051a39Sopenharmony_ci                                                unsigned char *out,
82e1051a39Sopenharmony_ci                                                const EVP_MD *md_type))
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    int ret = 0;
85e1051a39Sopenharmony_ci    const EVP_MD *md;
86e1051a39Sopenharmony_ci    EVP_MD *md_fetch;
87e1051a39Sopenharmony_ci    HMAC_CTX *hmac = NULL;
88e1051a39Sopenharmony_ci    unsigned char key[EVP_MAX_MD_SIZE], *salt;
89e1051a39Sopenharmony_ci    int saltlen, iter;
90e1051a39Sopenharmony_ci    char md_name[80];
91e1051a39Sopenharmony_ci    int md_size = 0;
92e1051a39Sopenharmony_ci    int md_nid;
93e1051a39Sopenharmony_ci    const X509_ALGOR *macalg;
94e1051a39Sopenharmony_ci    const ASN1_OBJECT *macoid;
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_ci    if (!PKCS7_type_is_data(p12->authsafes)) {
97e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA);
98e1051a39Sopenharmony_ci        return 0;
99e1051a39Sopenharmony_ci    }
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci    if (p12->authsafes->d.data == NULL) {
102e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_DECODE_ERROR);
103e1051a39Sopenharmony_ci        return 0;
104e1051a39Sopenharmony_ci    }
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci    salt = p12->mac->salt->data;
107e1051a39Sopenharmony_ci    saltlen = p12->mac->salt->length;
108e1051a39Sopenharmony_ci    if (p12->mac->iter == NULL)
109e1051a39Sopenharmony_ci        iter = 1;
110e1051a39Sopenharmony_ci    else
111e1051a39Sopenharmony_ci        iter = ASN1_INTEGER_get(p12->mac->iter);
112e1051a39Sopenharmony_ci    X509_SIG_get0(p12->mac->dinfo, &macalg, NULL);
113e1051a39Sopenharmony_ci    X509_ALGOR_get0(&macoid, NULL, NULL, macalg);
114e1051a39Sopenharmony_ci    if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0)
115e1051a39Sopenharmony_ci        return 0;
116e1051a39Sopenharmony_ci    md = md_fetch = EVP_MD_fetch(p12->authsafes->ctx.libctx, md_name,
117e1051a39Sopenharmony_ci                                 p12->authsafes->ctx.propq);
118e1051a39Sopenharmony_ci    if (md == NULL)
119e1051a39Sopenharmony_ci        md = EVP_get_digestbynid(OBJ_obj2nid(macoid));
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci    if (md == NULL) {
122e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
123e1051a39Sopenharmony_ci        return 0;
124e1051a39Sopenharmony_ci    }
125e1051a39Sopenharmony_ci    md_size = EVP_MD_get_size(md);
126e1051a39Sopenharmony_ci    md_nid = EVP_MD_get_type(md);
127e1051a39Sopenharmony_ci    if (md_size < 0)
128e1051a39Sopenharmony_ci        goto err;
129e1051a39Sopenharmony_ci    if ((md_nid == NID_id_GostR3411_94
130e1051a39Sopenharmony_ci         || md_nid == NID_id_GostR3411_2012_256
131e1051a39Sopenharmony_ci         || md_nid == NID_id_GostR3411_2012_512)
132e1051a39Sopenharmony_ci        && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) {
133e1051a39Sopenharmony_ci        md_size = TK26_MAC_KEY_LEN;
134e1051a39Sopenharmony_ci        if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter,
135e1051a39Sopenharmony_ci                                     md_size, key, md)) {
136e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
137e1051a39Sopenharmony_ci            goto err;
138e1051a39Sopenharmony_ci        }
139e1051a39Sopenharmony_ci    } else {
140e1051a39Sopenharmony_ci        if (pkcs12_key_gen != NULL) {
141e1051a39Sopenharmony_ci            if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
142e1051a39Sopenharmony_ci                                   iter, md_size, key, md)) {
143e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
144e1051a39Sopenharmony_ci                goto err;
145e1051a39Sopenharmony_ci            }
146e1051a39Sopenharmony_ci        } else {
147e1051a39Sopenharmony_ci            /* Default to UTF-8 password */
148e1051a39Sopenharmony_ci            if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
149e1051a39Sopenharmony_ci                                       iter, md_size, key, md,
150e1051a39Sopenharmony_ci                                       p12->authsafes->ctx.libctx,
151e1051a39Sopenharmony_ci                                       p12->authsafes->ctx.propq)) {
152e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
153e1051a39Sopenharmony_ci                goto err;
154e1051a39Sopenharmony_ci            }
155e1051a39Sopenharmony_ci        }
156e1051a39Sopenharmony_ci    }
157e1051a39Sopenharmony_ci    if ((hmac = HMAC_CTX_new()) == NULL
158e1051a39Sopenharmony_ci        || !HMAC_Init_ex(hmac, key, md_size, md, NULL)
159e1051a39Sopenharmony_ci        || !HMAC_Update(hmac, p12->authsafes->d.data->data,
160e1051a39Sopenharmony_ci                        p12->authsafes->d.data->length)
161e1051a39Sopenharmony_ci        || !HMAC_Final(hmac, mac, maclen)) {
162e1051a39Sopenharmony_ci        goto err;
163e1051a39Sopenharmony_ci    }
164e1051a39Sopenharmony_ci    ret = 1;
165e1051a39Sopenharmony_ci
166e1051a39Sopenharmony_cierr:
167e1051a39Sopenharmony_ci    OPENSSL_cleanse(key, sizeof(key));
168e1051a39Sopenharmony_ci    HMAC_CTX_free(hmac);
169e1051a39Sopenharmony_ci    EVP_MD_free(md_fetch);
170e1051a39Sopenharmony_ci    return ret;
171e1051a39Sopenharmony_ci}
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ciint PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
174e1051a39Sopenharmony_ci                   unsigned char *mac, unsigned int *maclen)
175e1051a39Sopenharmony_ci{
176e1051a39Sopenharmony_ci    return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NULL);
177e1051a39Sopenharmony_ci}
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci/* Verify the mac */
180e1051a39Sopenharmony_ciint PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
181e1051a39Sopenharmony_ci{
182e1051a39Sopenharmony_ci    unsigned char mac[EVP_MAX_MD_SIZE];
183e1051a39Sopenharmony_ci    unsigned int maclen;
184e1051a39Sopenharmony_ci    const ASN1_OCTET_STRING *macoct;
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci    if (p12->mac == NULL) {
187e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT);
188e1051a39Sopenharmony_ci        return 0;
189e1051a39Sopenharmony_ci    }
190e1051a39Sopenharmony_ci    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
191e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
192e1051a39Sopenharmony_ci        return 0;
193e1051a39Sopenharmony_ci    }
194e1051a39Sopenharmony_ci    X509_SIG_get0(p12->mac->dinfo, NULL, &macoct);
195e1051a39Sopenharmony_ci    if ((maclen != (unsigned int)ASN1_STRING_length(macoct))
196e1051a39Sopenharmony_ci        || CRYPTO_memcmp(mac, ASN1_STRING_get0_data(macoct), maclen) != 0)
197e1051a39Sopenharmony_ci        return 0;
198e1051a39Sopenharmony_ci
199e1051a39Sopenharmony_ci    return 1;
200e1051a39Sopenharmony_ci}
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci/* Set a mac */
203e1051a39Sopenharmony_ci
204e1051a39Sopenharmony_ciint PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
205e1051a39Sopenharmony_ci                   unsigned char *salt, int saltlen, int iter,
206e1051a39Sopenharmony_ci                   const EVP_MD *md_type)
207e1051a39Sopenharmony_ci{
208e1051a39Sopenharmony_ci    unsigned char mac[EVP_MAX_MD_SIZE];
209e1051a39Sopenharmony_ci    unsigned int maclen;
210e1051a39Sopenharmony_ci    ASN1_OCTET_STRING *macoct;
211e1051a39Sopenharmony_ci
212e1051a39Sopenharmony_ci    if (md_type == NULL)
213e1051a39Sopenharmony_ci        /* No need to do a fetch as the md_type is used only to get a NID */
214e1051a39Sopenharmony_ci        md_type = EVP_sha256();
215e1051a39Sopenharmony_ci    if (!iter)
216e1051a39Sopenharmony_ci        iter = PKCS12_DEFAULT_ITER;
217e1051a39Sopenharmony_ci    if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) == PKCS12_ERROR) {
218e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR);
219e1051a39Sopenharmony_ci        return 0;
220e1051a39Sopenharmony_ci    }
221e1051a39Sopenharmony_ci    /*
222e1051a39Sopenharmony_ci     * Note that output mac is forced to UTF-8...
223e1051a39Sopenharmony_ci     */
224e1051a39Sopenharmony_ci    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
225e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
226e1051a39Sopenharmony_ci        return 0;
227e1051a39Sopenharmony_ci    }
228e1051a39Sopenharmony_ci    X509_SIG_getm(p12->mac->dinfo, NULL, &macoct);
229e1051a39Sopenharmony_ci    if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) {
230e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_STRING_SET_ERROR);
231e1051a39Sopenharmony_ci        return 0;
232e1051a39Sopenharmony_ci    }
233e1051a39Sopenharmony_ci    return 1;
234e1051a39Sopenharmony_ci}
235e1051a39Sopenharmony_ci
236e1051a39Sopenharmony_ci/* Set up a mac structure */
237e1051a39Sopenharmony_ciint PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
238e1051a39Sopenharmony_ci                     const EVP_MD *md_type)
239e1051a39Sopenharmony_ci{
240e1051a39Sopenharmony_ci    X509_ALGOR *macalg;
241e1051a39Sopenharmony_ci
242e1051a39Sopenharmony_ci    PKCS12_MAC_DATA_free(p12->mac);
243e1051a39Sopenharmony_ci    p12->mac = NULL;
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_ci    if ((p12->mac = PKCS12_MAC_DATA_new()) == NULL)
246e1051a39Sopenharmony_ci        return PKCS12_ERROR;
247e1051a39Sopenharmony_ci    if (iter > 1) {
248e1051a39Sopenharmony_ci        if ((p12->mac->iter = ASN1_INTEGER_new()) == NULL) {
249e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
250e1051a39Sopenharmony_ci            return 0;
251e1051a39Sopenharmony_ci        }
252e1051a39Sopenharmony_ci        if (!ASN1_INTEGER_set(p12->mac->iter, iter)) {
253e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
254e1051a39Sopenharmony_ci            return 0;
255e1051a39Sopenharmony_ci        }
256e1051a39Sopenharmony_ci    }
257e1051a39Sopenharmony_ci    if (saltlen == 0)
258e1051a39Sopenharmony_ci        saltlen = PKCS12_SALT_LEN;
259e1051a39Sopenharmony_ci    else if (saltlen < 0)
260e1051a39Sopenharmony_ci        return 0;
261e1051a39Sopenharmony_ci    if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) {
262e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
263e1051a39Sopenharmony_ci        return 0;
264e1051a39Sopenharmony_ci    }
265e1051a39Sopenharmony_ci    p12->mac->salt->length = saltlen;
266e1051a39Sopenharmony_ci    if (salt == NULL) {
267e1051a39Sopenharmony_ci        if (RAND_bytes_ex(p12->authsafes->ctx.libctx, p12->mac->salt->data,
268e1051a39Sopenharmony_ci                          (size_t)saltlen, 0) <= 0)
269e1051a39Sopenharmony_ci            return 0;
270e1051a39Sopenharmony_ci    } else {
271e1051a39Sopenharmony_ci        memcpy(p12->mac->salt->data, salt, saltlen);
272e1051a39Sopenharmony_ci    }
273e1051a39Sopenharmony_ci    X509_SIG_getm(p12->mac->dinfo, &macalg, NULL);
274e1051a39Sopenharmony_ci    if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_get_type(md_type)),
275e1051a39Sopenharmony_ci                         V_ASN1_NULL, NULL)) {
276e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
277e1051a39Sopenharmony_ci        return 0;
278e1051a39Sopenharmony_ci    }
279e1051a39Sopenharmony_ci
280e1051a39Sopenharmony_ci    return 1;
281e1051a39Sopenharmony_ci}
282