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