]>
Commit | Line | Data |
---|---|---|
1aec7716 SL |
1 | /* |
2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. | |
4 | * | |
5 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
6 | * this file except in compliance with the License. You can obtain a copy | |
7 | * in the file LICENSE in the source distribution or at | |
8 | * https://www.openssl.org/source/license.html | |
9 | */ | |
10 | ||
11 | #include "e_os.h" | |
12 | ||
13 | #ifndef OPENSSL_NO_CMS | |
14 | ||
15 | # include <stdlib.h> | |
16 | # include <stdarg.h> | |
17 | # include <string.h> | |
18 | # include <openssl/hmac.h> | |
19 | # include <openssl/cms.h> | |
20 | # include <openssl/evp.h> | |
21 | # include <openssl/kdf.h> | |
22 | # include <openssl/x509.h> | |
23 | # include <openssl/obj_mac.h> | |
24 | # include "internal/cryptlib.h" | |
25 | # include "internal/evp_int.h" | |
26 | # include "kdf_local.h" | |
27 | ||
28 | # define X942KDF_MAX_INLEN (1 << 30) | |
29 | ||
30 | struct evp_kdf_impl_st { | |
31 | const EVP_MD *md; | |
32 | unsigned char *secret; | |
33 | size_t secret_len; | |
34 | int cek_nid; | |
35 | unsigned char *ukm; | |
36 | size_t ukm_len; | |
37 | size_t dkm_len; | |
38 | }; | |
39 | ||
40 | /* A table of allowed wrapping algorithms and the associated output lengths */ | |
41 | static const struct { | |
42 | int nid; | |
43 | size_t keklen; /* size in bytes */ | |
44 | } kek_algs[] = { | |
45 | { NID_id_smime_alg_CMS3DESwrap, 24 }, | |
46 | { NID_id_smime_alg_CMSRC2wrap, 16 }, | |
47 | { NID_id_aes128_wrap, 16 }, | |
48 | { NID_id_aes192_wrap, 24 }, | |
49 | { NID_id_aes256_wrap, 32 }, | |
50 | { NID_id_camellia128_wrap, 16 }, | |
51 | { NID_id_camellia192_wrap, 24 }, | |
52 | { NID_id_camellia256_wrap, 32 } | |
53 | }; | |
54 | ||
55 | /* Skip past an ASN1 structure: for OBJECT skip content octets too */ | |
56 | static int skip_asn1(unsigned char **pp, long *plen, int exptag) | |
57 | { | |
58 | int i, tag, xclass; | |
59 | long tmplen; | |
60 | const unsigned char *q = *pp; | |
61 | ||
62 | i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen); | |
63 | if ((i & 0x80) != 0 || tag != exptag || xclass != V_ASN1_UNIVERSAL) | |
64 | return 0; | |
65 | if (tag == V_ASN1_OBJECT) | |
66 | q += tmplen; | |
67 | *pp = (unsigned char *)q; | |
68 | *plen -= q - *pp; | |
69 | return 1; | |
70 | } | |
71 | ||
72 | /* | |
73 | * Encode the other info structure. | |
74 | * | |
75 | * RFC2631 Section 2.1.2 Contains the following definition for otherinfo | |
76 | * | |
77 | * OtherInfo ::= SEQUENCE { | |
78 | * keyInfo KeySpecificInfo, | |
79 | * partyAInfo [0] OCTET STRING OPTIONAL, | |
80 | * suppPubInfo [2] OCTET STRING | |
81 | * } | |
82 | * | |
83 | * KeySpecificInfo ::= SEQUENCE { | |
84 | * algorithm OBJECT IDENTIFIER, | |
85 | * counter OCTET STRING SIZE (4..4) | |
86 | * } | |
87 | * | |
88 | * |nid| is the algorithm object identifier. | |
89 | * |keylen| is the length (in bytes) of the generated KEK. It is stored into | |
90 | * suppPubInfo (in bits). | |
91 | * |ukm| is the optional user keying material that is stored into partyAInfo. It | |
92 | * can be NULL. | |
93 | * |ukmlen| is the user keying material length (in bytes). | |
94 | * |der| is the returned encoded data. It must be freed by the caller. | |
95 | * |der_len| is the returned size of the encoded data. | |
96 | * |out_ctr| returns a pointer to the counter data which is embedded inside the | |
97 | * encoded data. This allows the counter bytes to be updated without re-encoding. | |
98 | * | |
99 | * Returns: 1 if successfully encoded, or 0 otherwise. | |
100 | * Assumptions: |der|, |der_len| & |out_ctr| are not NULL. | |
101 | */ | |
102 | static int x942_encode_otherinfo(int nid, size_t keylen, | |
103 | const unsigned char *ukm, size_t ukmlen, | |
104 | unsigned char **der, size_t *der_len, | |
105 | unsigned char **out_ctr) | |
106 | { | |
107 | unsigned char *p, *encoded = NULL; | |
108 | int ret = 0, encoded_len; | |
109 | long tlen; | |
110 | /* "magic" value to check offset is sane */ | |
111 | static unsigned char ctr[4] = { 0x00, 0x00, 0x00, 0x01 }; | |
112 | X509_ALGOR *ksi = NULL; | |
113 | ASN1_OBJECT *alg_oid = NULL; | |
114 | ASN1_OCTET_STRING *ctr_oct = NULL, *ukm_oct = NULL; | |
115 | ||
116 | /* set the KeySpecificInfo - which contains an algorithm oid and counter */ | |
117 | ksi = X509_ALGOR_new(); | |
118 | alg_oid = OBJ_dup(OBJ_nid2obj(nid)); | |
119 | ctr_oct = ASN1_OCTET_STRING_new(); | |
120 | if (ksi == NULL | |
121 | || alg_oid == NULL | |
122 | || ctr_oct == NULL | |
123 | || !ASN1_OCTET_STRING_set(ctr_oct, ctr, sizeof(ctr)) | |
124 | || !X509_ALGOR_set0(ksi, alg_oid, V_ASN1_OCTET_STRING, ctr_oct)) | |
125 | goto err; | |
126 | /* NULL these as they now belong to ksi */ | |
127 | alg_oid = NULL; | |
128 | ctr_oct = NULL; | |
129 | ||
130 | /* Set the optional partyAInfo */ | |
131 | if (ukm != NULL) { | |
132 | ukm_oct = ASN1_OCTET_STRING_new(); | |
133 | if (ukm_oct == NULL) | |
134 | goto err; | |
135 | ASN1_OCTET_STRING_set(ukm_oct, (unsigned char *)ukm, ukmlen); | |
136 | } | |
137 | /* Generate the OtherInfo DER data */ | |
138 | encoded_len = CMS_SharedInfo_encode(&encoded, ksi, ukm_oct, keylen); | |
139 | if (encoded_len <= 0) | |
140 | goto err; | |
141 | ||
142 | /* Parse the encoded data to find the offset of the counter data */ | |
143 | p = encoded; | |
144 | tlen = (long)encoded_len; | |
145 | if (skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) | |
146 | && skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) | |
147 | && skip_asn1(&p, &tlen, V_ASN1_OBJECT) | |
148 | && skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING) | |
149 | && CRYPTO_memcmp(p, ctr, 4) == 0) { | |
150 | *out_ctr = p; | |
151 | *der = encoded; | |
152 | *der_len = (size_t)encoded_len; | |
153 | ret = 1; | |
154 | } | |
155 | err: | |
156 | if (ret != 1) | |
157 | OPENSSL_free(encoded); | |
158 | ASN1_OCTET_STRING_free(ctr_oct); | |
159 | ASN1_OCTET_STRING_free(ukm_oct); | |
160 | ASN1_OBJECT_free(alg_oid); | |
161 | X509_ALGOR_free(ksi); | |
162 | return ret; | |
163 | } | |
164 | ||
165 | static int x942kdf_hash_kdm(const EVP_MD *kdf_md, | |
166 | const unsigned char *z, size_t z_len, | |
167 | const unsigned char *other, size_t other_len, | |
168 | unsigned char *ctr, | |
169 | unsigned char *derived_key, size_t derived_key_len) | |
170 | { | |
171 | int ret = 0, hlen; | |
172 | size_t counter, out_len, len = derived_key_len; | |
173 | unsigned char mac[EVP_MAX_MD_SIZE]; | |
174 | unsigned char *out = derived_key; | |
175 | EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; | |
176 | ||
177 | if (z_len > X942KDF_MAX_INLEN || other_len > X942KDF_MAX_INLEN | |
178 | || derived_key_len > X942KDF_MAX_INLEN | |
179 | || derived_key_len == 0) { | |
180 | KDFerr(KDF_F_X942KDF_HASH_KDM, KDF_R_BAD_LENGTH); | |
181 | return 0; | |
182 | } | |
183 | ||
184 | hlen = EVP_MD_size(kdf_md); | |
185 | if (hlen <= 0) | |
186 | return 0; | |
187 | out_len = (size_t)hlen; | |
188 | ||
189 | ctx = EVP_MD_CTX_create(); | |
190 | ctx_init = EVP_MD_CTX_create(); | |
191 | if (ctx == NULL || ctx_init == NULL) | |
192 | goto end; | |
193 | ||
194 | if (!EVP_DigestInit(ctx_init, kdf_md)) | |
195 | goto end; | |
196 | ||
197 | for (counter = 1;; counter++) { | |
198 | /* updating the ctr modifies 4 bytes in the 'other' buffer */ | |
199 | ctr[0] = (unsigned char)((counter >> 24) & 0xff); | |
200 | ctr[1] = (unsigned char)((counter >> 16) & 0xff); | |
201 | ctr[2] = (unsigned char)((counter >> 8) & 0xff); | |
202 | ctr[3] = (unsigned char)(counter & 0xff); | |
203 | ||
204 | if (!EVP_MD_CTX_copy_ex(ctx, ctx_init) | |
205 | || !EVP_DigestUpdate(ctx, z, z_len) | |
206 | || !EVP_DigestUpdate(ctx, other, other_len)) | |
207 | goto end; | |
208 | if (len >= out_len) { | |
209 | if (!EVP_DigestFinal_ex(ctx, out, NULL)) | |
210 | goto end; | |
211 | out += out_len; | |
212 | len -= out_len; | |
213 | if (len == 0) | |
214 | break; | |
215 | } else { | |
216 | if (!EVP_DigestFinal_ex(ctx, mac, NULL)) | |
217 | goto end; | |
218 | memcpy(out, mac, len); | |
219 | break; | |
220 | } | |
221 | } | |
222 | ret = 1; | |
223 | end: | |
224 | EVP_MD_CTX_free(ctx); | |
225 | EVP_MD_CTX_free(ctx_init); | |
226 | OPENSSL_cleanse(mac, sizeof(mac)); | |
227 | return ret; | |
228 | } | |
229 | ||
230 | static EVP_KDF_IMPL *x942kdf_new(void) | |
231 | { | |
232 | EVP_KDF_IMPL *impl; | |
233 | ||
234 | if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL) | |
235 | KDFerr(KDF_F_X942KDF_NEW, ERR_R_MALLOC_FAILURE); | |
236 | return impl; | |
237 | } | |
238 | ||
239 | static void x942kdf_reset(EVP_KDF_IMPL *impl) | |
240 | { | |
241 | OPENSSL_clear_free(impl->secret, impl->secret_len); | |
242 | OPENSSL_clear_free(impl->ukm, impl->ukm_len); | |
243 | memset(impl, 0, sizeof(*impl)); | |
244 | } | |
245 | ||
246 | static void x942kdf_free(EVP_KDF_IMPL *impl) | |
247 | { | |
248 | x942kdf_reset(impl); | |
249 | OPENSSL_free(impl); | |
250 | } | |
251 | ||
252 | static int x942kdf_set_buffer(va_list args, unsigned char **out, size_t *out_len) | |
253 | { | |
254 | const unsigned char *p; | |
255 | size_t len; | |
256 | ||
257 | p = va_arg(args, const unsigned char *); | |
258 | len = va_arg(args, size_t); | |
259 | if (len == 0 || p == NULL) | |
260 | return 1; | |
261 | ||
262 | OPENSSL_free(*out); | |
263 | *out = OPENSSL_memdup(p, len); | |
264 | if (*out == NULL) | |
265 | return 0; | |
266 | ||
267 | *out_len = len; | |
268 | return 1; | |
269 | } | |
270 | ||
271 | static int x942kdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) | |
272 | { | |
273 | const EVP_MD *md; | |
274 | char *alg_str = NULL; | |
275 | size_t i; | |
276 | ||
277 | switch (cmd) { | |
278 | case EVP_KDF_CTRL_SET_MD: | |
279 | md = va_arg(args, const EVP_MD *); | |
280 | if (md == NULL) | |
281 | return 0; | |
282 | ||
283 | impl->md = md; | |
284 | return 1; | |
285 | ||
286 | case EVP_KDF_CTRL_SET_KEY: | |
287 | return x942kdf_set_buffer(args, &impl->secret, &impl->secret_len); | |
288 | ||
289 | case EVP_KDF_CTRL_SET_UKM: | |
290 | return x942kdf_set_buffer(args, &impl->ukm, &impl->ukm_len); | |
291 | ||
292 | case EVP_KDF_CTRL_SET_CEK_ALG: | |
293 | alg_str = va_arg(args, char *); | |
294 | if (alg_str == NULL) | |
295 | return 0; | |
296 | impl->cek_nid = OBJ_sn2nid(alg_str); | |
297 | for (i = 0; i < (size_t)OSSL_NELEM(kek_algs); ++i) { | |
298 | if (kek_algs[i].nid == impl->cek_nid) { | |
299 | impl->dkm_len = kek_algs[i].keklen; | |
300 | return 1; | |
301 | } | |
302 | } | |
303 | KDFerr(KDF_F_X942KDF_CTRL, KDF_R_UNSUPPORTED_CEK_ALG); | |
304 | return 0; | |
305 | ||
306 | default: | |
307 | return -2; | |
308 | } | |
309 | } | |
310 | ||
311 | static int x942kdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, | |
312 | const char *value) | |
313 | { | |
314 | if (strcmp(type, "digest") == 0) | |
315 | return kdf_md2ctrl(impl, x942kdf_ctrl, EVP_KDF_CTRL_SET_MD, value); | |
316 | ||
317 | if (strcmp(type, "secret") == 0 || strcmp(type, "key") == 0) | |
318 | return kdf_str2ctrl(impl, x942kdf_ctrl, EVP_KDF_CTRL_SET_KEY, | |
319 | value); | |
320 | ||
321 | if (strcmp(type, "hexsecret") == 0 || strcmp(type, "hexkey") == 0) | |
322 | return kdf_hex2ctrl(impl, x942kdf_ctrl, EVP_KDF_CTRL_SET_KEY, | |
323 | value); | |
324 | ||
325 | if (strcmp(type, "ukm") == 0) | |
326 | return kdf_str2ctrl(impl, x942kdf_ctrl, EVP_KDF_CTRL_SET_UKM, | |
327 | value); | |
328 | ||
329 | if (strcmp(type, "hexukm") == 0) | |
330 | return kdf_hex2ctrl(impl, x942kdf_ctrl, EVP_KDF_CTRL_SET_UKM, | |
331 | value); | |
332 | ||
333 | if (strcmp(type, "cekalg") == 0) | |
334 | return kdf_str2ctrl(impl, x942kdf_ctrl, EVP_KDF_CTRL_SET_CEK_ALG, | |
335 | value); | |
336 | ||
337 | return -2; | |
338 | } | |
339 | ||
340 | static size_t x942kdf_size(EVP_KDF_IMPL *impl) | |
341 | { | |
342 | int len; | |
343 | ||
344 | if (impl->md == NULL) { | |
345 | KDFerr(KDF_F_X942KDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST); | |
346 | return 0; | |
347 | } | |
348 | len = EVP_MD_size(impl->md); | |
349 | return (len <= 0) ? 0 : (size_t)len; | |
350 | } | |
351 | ||
352 | static int x942kdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen) | |
353 | { | |
354 | int ret = 0; | |
355 | unsigned char *ctr; | |
356 | unsigned char *der = NULL; | |
357 | size_t der_len = 0; | |
358 | ||
359 | if (impl->secret == NULL) { | |
360 | KDFerr(KDF_F_X942KDF_DERIVE, KDF_R_MISSING_SECRET); | |
361 | return 0; | |
362 | } | |
363 | if (impl->md == NULL) { | |
364 | KDFerr(KDF_F_X942KDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); | |
365 | return 0; | |
366 | } | |
367 | if (impl->cek_nid == NID_undef) { | |
368 | KDFerr(KDF_F_X942KDF_DERIVE, KDF_R_MISSING_CEK_ALG); | |
369 | return 0; | |
370 | } | |
371 | if (impl->ukm != NULL && impl->ukm_len >= X942KDF_MAX_INLEN) { | |
372 | /* | |
373 | * Note the ukm length MUST be 512 bits. | |
374 | * For backwards compatibility the old check is being done. | |
375 | */ | |
376 | KDFerr(KDF_F_X942KDF_DERIVE, KDF_R_INAVLID_UKM_LEN); | |
377 | return 0; | |
378 | } | |
379 | if (keylen != impl->dkm_len) { | |
380 | KDFerr(KDF_F_X942KDF_DERIVE, KDF_R_MISSING_CEK_ALG); | |
381 | return 0; | |
382 | } | |
383 | /* generate the otherinfo der */ | |
384 | if (!x942_encode_otherinfo(impl->cek_nid, impl->dkm_len, | |
385 | impl->ukm, impl->ukm_len, | |
386 | &der, &der_len, &ctr)) { | |
387 | KDFerr(KDF_F_X942KDF_DERIVE, KDF_R_BAD_ENCODING); | |
388 | return 0; | |
389 | } | |
390 | ret = x942kdf_hash_kdm(impl->md, impl->secret, impl->secret_len, | |
391 | der, der_len, ctr, key, keylen); | |
392 | OPENSSL_free(der); | |
393 | return ret; | |
394 | } | |
395 | ||
396 | const EVP_KDF x942_kdf_meth = { | |
397 | EVP_KDF_X942, | |
398 | x942kdf_new, | |
399 | x942kdf_free, | |
400 | x942kdf_reset, | |
401 | x942kdf_ctrl, | |
402 | x942kdf_ctrl_str, | |
403 | x942kdf_size, | |
404 | x942kdf_derive | |
405 | }; | |
406 | ||
407 | #endif /* OPENSSL_NO_CMS */ |