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 <openssl/core_names.h> |
25 | # include "internal/cryptlib.h" |
26 | # include "internal/numbers.h" |
27 | # include "crypto/evp.h" |
28 | # include "prov/provider_ctx.h" |
29 | # include "prov/providercommonerr.h" |
30 | # include "prov/implementations.h" |
31 | # include "prov/provider_util.h" |
32 | |
33 | # define X942KDF_MAX_INLEN (1 << 30) |
34 | |
35 | static OSSL_OP_kdf_newctx_fn x942kdf_new; |
36 | static OSSL_OP_kdf_freectx_fn x942kdf_free; |
37 | static OSSL_OP_kdf_reset_fn x942kdf_reset; |
38 | static OSSL_OP_kdf_derive_fn x942kdf_derive; |
39 | static OSSL_OP_kdf_settable_ctx_params_fn x942kdf_settable_ctx_params; |
40 | static OSSL_OP_kdf_set_ctx_params_fn x942kdf_set_ctx_params; |
41 | static OSSL_OP_kdf_gettable_ctx_params_fn x942kdf_gettable_ctx_params; |
42 | static OSSL_OP_kdf_get_ctx_params_fn x942kdf_get_ctx_params; |
43 | |
44 | typedef struct { |
45 | void *provctx; |
46 | PROV_DIGEST digest; |
47 | unsigned char *secret; |
48 | size_t secret_len; |
49 | int cek_nid; |
50 | unsigned char *ukm; |
51 | size_t ukm_len; |
52 | size_t dkm_len; |
53 | } KDF_X942; |
54 | |
55 | /* A table of allowed wrapping algorithms and the associated output lengths */ |
56 | static const struct { |
57 | int nid; |
58 | size_t keklen; /* size in bytes */ |
59 | } kek_algs[] = { |
60 | { NID_id_smime_alg_CMS3DESwrap, 24 }, |
61 | { NID_id_smime_alg_CMSRC2wrap, 16 }, |
62 | { NID_id_aes128_wrap, 16 }, |
63 | { NID_id_aes192_wrap, 24 }, |
64 | { NID_id_aes256_wrap, 32 }, |
65 | { NID_id_camellia128_wrap, 16 }, |
66 | { NID_id_camellia192_wrap, 24 }, |
67 | { NID_id_camellia256_wrap, 32 } |
68 | }; |
69 | |
70 | /* Skip past an ASN1 structure: for OBJECT skip content octets too */ |
71 | static int skip_asn1(unsigned char **pp, long *plen, int exptag) |
72 | { |
73 | int i, tag, xclass; |
74 | long tmplen; |
75 | const unsigned char *q = *pp; |
76 | |
77 | i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen); |
78 | if ((i & 0x80) != 0 || tag != exptag || xclass != V_ASN1_UNIVERSAL) |
79 | return 0; |
80 | if (tag == V_ASN1_OBJECT) |
81 | q += tmplen; |
82 | *pp = (unsigned char *)q; |
83 | *plen -= q - *pp; |
84 | return 1; |
85 | } |
86 | |
87 | /* |
88 | * Encode the other info structure. |
89 | * |
90 | * RFC2631 Section 2.1.2 Contains the following definition for otherinfo |
91 | * |
92 | * OtherInfo ::= SEQUENCE { |
93 | * keyInfo KeySpecificInfo, |
94 | * partyAInfo [0] OCTET STRING OPTIONAL, |
95 | * suppPubInfo [2] OCTET STRING |
96 | * } |
97 | * |
98 | * KeySpecificInfo ::= SEQUENCE { |
99 | * algorithm OBJECT IDENTIFIER, |
100 | * counter OCTET STRING SIZE (4..4) |
101 | * } |
102 | * |
103 | * |nid| is the algorithm object identifier. |
104 | * |keylen| is the length (in bytes) of the generated KEK. It is stored into |
105 | * suppPubInfo (in bits). |
106 | * |ukm| is the optional user keying material that is stored into partyAInfo. It |
107 | * can be NULL. |
108 | * |ukmlen| is the user keying material length (in bytes). |
109 | * |der| is the returned encoded data. It must be freed by the caller. |
110 | * |der_len| is the returned size of the encoded data. |
111 | * |out_ctr| returns a pointer to the counter data which is embedded inside the |
112 | * encoded data. This allows the counter bytes to be updated without re-encoding. |
113 | * |
114 | * Returns: 1 if successfully encoded, or 0 otherwise. |
115 | * Assumptions: |der|, |der_len| & |out_ctr| are not NULL. |
116 | */ |
117 | static int x942_encode_otherinfo(int nid, size_t keylen, |
118 | const unsigned char *ukm, size_t ukmlen, |
119 | unsigned char **der, size_t *der_len, |
120 | unsigned char **out_ctr) |
121 | { |
122 | unsigned char *p, *encoded = NULL; |
123 | int ret = 0, encoded_len; |
124 | long tlen; |
125 | /* "magic" value to check offset is sane */ |
126 | static unsigned char ctr[4] = { 0x00, 0x00, 0x00, 0x01 }; |
127 | X509_ALGOR *ksi = NULL; |
128 | ASN1_OBJECT *alg_oid = NULL; |
129 | ASN1_OCTET_STRING *ctr_oct = NULL, *ukm_oct = NULL; |
130 | |
131 | /* set the KeySpecificInfo - which contains an algorithm oid and counter */ |
132 | ksi = X509_ALGOR_new(); |
133 | alg_oid = OBJ_dup(OBJ_nid2obj(nid)); |
134 | ctr_oct = ASN1_OCTET_STRING_new(); |
135 | if (ksi == NULL |
136 | || alg_oid == NULL |
137 | || ctr_oct == NULL |
138 | || !ASN1_OCTET_STRING_set(ctr_oct, ctr, sizeof(ctr)) |
139 | || !X509_ALGOR_set0(ksi, alg_oid, V_ASN1_OCTET_STRING, ctr_oct)) |
140 | goto err; |
141 | /* NULL these as they now belong to ksi */ |
142 | alg_oid = NULL; |
143 | ctr_oct = NULL; |
144 | |
145 | /* Set the optional partyAInfo */ |
146 | if (ukm != NULL) { |
147 | ukm_oct = ASN1_OCTET_STRING_new(); |
148 | if (ukm_oct == NULL) |
149 | goto err; |
150 | ASN1_OCTET_STRING_set(ukm_oct, (unsigned char *)ukm, ukmlen); |
151 | } |
152 | /* Generate the OtherInfo DER data */ |
153 | encoded_len = CMS_SharedInfo_encode(&encoded, ksi, ukm_oct, keylen); |
154 | if (encoded_len <= 0) |
155 | goto err; |
156 | |
157 | /* Parse the encoded data to find the offset of the counter data */ |
158 | p = encoded; |
159 | tlen = (long)encoded_len; |
160 | if (skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) |
161 | && skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) |
162 | && skip_asn1(&p, &tlen, V_ASN1_OBJECT) |
163 | && skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING) |
164 | && CRYPTO_memcmp(p, ctr, 4) == 0) { |
165 | *out_ctr = p; |
166 | *der = encoded; |
167 | *der_len = (size_t)encoded_len; |
168 | ret = 1; |
169 | } |
170 | err: |
171 | if (ret != 1) |
172 | OPENSSL_free(encoded); |
173 | ASN1_OCTET_STRING_free(ctr_oct); |
174 | ASN1_OCTET_STRING_free(ukm_oct); |
175 | ASN1_OBJECT_free(alg_oid); |
176 | X509_ALGOR_free(ksi); |
177 | return ret; |
178 | } |
179 | |
180 | static int x942kdf_hash_kdm(const EVP_MD *kdf_md, |
181 | const unsigned char *z, size_t z_len, |
182 | const unsigned char *other, size_t other_len, |
183 | unsigned char *ctr, |
184 | unsigned char *derived_key, size_t derived_key_len) |
185 | { |
186 | int ret = 0, hlen; |
187 | size_t counter, out_len, len = derived_key_len; |
188 | unsigned char mac[EVP_MAX_MD_SIZE]; |
189 | unsigned char *out = derived_key; |
190 | EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; |
191 | |
192 | if (z_len > X942KDF_MAX_INLEN || other_len > X942KDF_MAX_INLEN |
193 | || derived_key_len > X942KDF_MAX_INLEN |
194 | || derived_key_len == 0) { |
195 | ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); |
196 | return 0; |
197 | } |
198 | |
199 | hlen = EVP_MD_size(kdf_md); |
200 | if (hlen <= 0) |
201 | return 0; |
202 | out_len = (size_t)hlen; |
203 | |
204 | ctx = EVP_MD_CTX_create(); |
205 | ctx_init = EVP_MD_CTX_create(); |
206 | if (ctx == NULL || ctx_init == NULL) |
207 | goto end; |
208 | |
209 | if (!EVP_DigestInit(ctx_init, kdf_md)) |
210 | goto end; |
211 | |
212 | for (counter = 1;; counter++) { |
213 | /* updating the ctr modifies 4 bytes in the 'other' buffer */ |
214 | ctr[0] = (unsigned char)((counter >> 24) & 0xff); |
215 | ctr[1] = (unsigned char)((counter >> 16) & 0xff); |
216 | ctr[2] = (unsigned char)((counter >> 8) & 0xff); |
217 | ctr[3] = (unsigned char)(counter & 0xff); |
218 | |
219 | if (!EVP_MD_CTX_copy_ex(ctx, ctx_init) |
220 | || !EVP_DigestUpdate(ctx, z, z_len) |
221 | || !EVP_DigestUpdate(ctx, other, other_len)) |
222 | goto end; |
223 | if (len >= out_len) { |
224 | if (!EVP_DigestFinal_ex(ctx, out, NULL)) |
225 | goto end; |
226 | out += out_len; |
227 | len -= out_len; |
228 | if (len == 0) |
229 | break; |
230 | } else { |
231 | if (!EVP_DigestFinal_ex(ctx, mac, NULL)) |
232 | goto end; |
233 | memcpy(out, mac, len); |
234 | break; |
235 | } |
236 | } |
237 | ret = 1; |
238 | end: |
239 | EVP_MD_CTX_free(ctx); |
240 | EVP_MD_CTX_free(ctx_init); |
241 | OPENSSL_cleanse(mac, sizeof(mac)); |
242 | return ret; |
243 | } |
244 | |
245 | static void *x942kdf_new(void *provctx) |
246 | { |
247 | KDF_X942 *ctx; |
248 | |
249 | if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) |
250 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
251 | ctx->provctx = provctx; |
252 | return ctx; |
253 | } |
254 | |
255 | static void x942kdf_reset(void *vctx) |
256 | { |
257 | KDF_X942 *ctx = (KDF_X942 *)vctx; |
258 | |
259 | ossl_prov_digest_reset(&ctx->digest); |
260 | OPENSSL_clear_free(ctx->secret, ctx->secret_len); |
261 | OPENSSL_clear_free(ctx->ukm, ctx->ukm_len); |
262 | memset(ctx, 0, sizeof(*ctx)); |
263 | } |
264 | |
265 | static void x942kdf_free(void *vctx) |
266 | { |
267 | KDF_X942 *ctx = (KDF_X942 *)vctx; |
268 | |
269 | if (ctx != NULL) { |
270 | x942kdf_reset(ctx); |
271 | OPENSSL_free(ctx); |
272 | } |
273 | } |
274 | |
275 | static int x942kdf_set_buffer(unsigned char **out, size_t *out_len, |
276 | const OSSL_PARAM *p) |
277 | { |
278 | if (p->data_size == 0 || p->data == NULL) |
279 | return 1; |
280 | |
281 | OPENSSL_free(*out); |
282 | *out = NULL; |
283 | return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); |
284 | } |
285 | |
286 | static size_t x942kdf_size(KDF_X942 *ctx) |
287 | { |
288 | int len; |
289 | const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
290 | |
291 | if (md == NULL) { |
292 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
293 | return 0; |
294 | } |
295 | len = EVP_MD_size(md); |
296 | return (len <= 0) ? 0 : (size_t)len; |
297 | } |
298 | |
299 | static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen) |
300 | { |
301 | KDF_X942 *ctx = (KDF_X942 *)vctx; |
302 | const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
303 | int ret = 0; |
304 | unsigned char *ctr; |
305 | unsigned char *der = NULL; |
306 | size_t der_len = 0; |
307 | |
308 | if (ctx->secret == NULL) { |
309 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); |
310 | return 0; |
311 | } |
312 | if (md == NULL) { |
313 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); |
314 | return 0; |
315 | } |
316 | if (ctx->cek_nid == NID_undef) { |
317 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); |
318 | return 0; |
319 | } |
320 | if (ctx->ukm != NULL && ctx->ukm_len >= X942KDF_MAX_INLEN) { |
321 | /* |
322 | * Note the ukm length MUST be 512 bits. |
323 | * For backwards compatibility the old check is being done. |
324 | */ |
325 | ERR_raise(ERR_LIB_PROV, PROV_R_INAVLID_UKM_LENGTH); |
326 | return 0; |
327 | } |
328 | if (keylen != ctx->dkm_len) { |
329 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); |
330 | return 0; |
331 | } |
332 | /* generate the otherinfo der */ |
333 | if (!x942_encode_otherinfo(ctx->cek_nid, ctx->dkm_len, |
334 | ctx->ukm, ctx->ukm_len, |
335 | &der, &der_len, &ctr)) { |
336 | ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); |
337 | return 0; |
338 | } |
339 | ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len, |
340 | der, der_len, ctr, key, keylen); |
341 | OPENSSL_free(der); |
342 | return ret; |
343 | } |
344 | |
345 | static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) |
346 | { |
347 | const OSSL_PARAM *p; |
348 | KDF_X942 *ctx = vctx; |
349 | OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); |
350 | size_t i; |
351 | |
352 | if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) |
353 | return 0; |
354 | |
355 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL |
356 | || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) |
357 | if (!x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) |
358 | return 0; |
359 | |
360 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_UKM)) != NULL) |
361 | if (!x942kdf_set_buffer(&ctx->ukm, &ctx->ukm_len, p)) |
362 | return 0; |
363 | |
364 | if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG)) != NULL) { |
365 | if (p->data_type != OSSL_PARAM_UTF8_STRING) |
366 | return 0; |
367 | ctx->cek_nid = OBJ_sn2nid(p->data); |
368 | for (i = 0; i < OSSL_NELEM(kek_algs); i++) |
369 | if (kek_algs[i].nid == ctx->cek_nid) |
370 | goto cek_found; |
371 | ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_CEK_ALG); |
372 | return 0; |
373 | cek_found: |
374 | ctx->dkm_len = kek_algs[i].keklen; |
375 | } |
376 | return 1; |
377 | } |
378 | |
379 | static const OSSL_PARAM *x942kdf_settable_ctx_params(void) |
380 | { |
381 | static const OSSL_PARAM known_settable_ctx_params[] = { |
382 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), |
383 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), |
384 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), |
385 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), |
386 | OSSL_PARAM_octet_string(OSSL_KDF_PARAM_UKM, NULL, 0), |
387 | OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), |
388 | OSSL_PARAM_END |
389 | }; |
390 | return known_settable_ctx_params; |
391 | } |
392 | |
393 | static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
394 | { |
395 | KDF_X942 *ctx = (KDF_X942 *)vctx; |
396 | OSSL_PARAM *p; |
397 | |
398 | if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) |
399 | return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx)); |
400 | return -2; |
401 | } |
402 | |
403 | static const OSSL_PARAM *x942kdf_gettable_ctx_params(void) |
404 | { |
405 | static const OSSL_PARAM known_gettable_ctx_params[] = { |
406 | OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), |
407 | OSSL_PARAM_END |
408 | }; |
409 | return known_gettable_ctx_params; |
410 | } |
411 | |
412 | const OSSL_DISPATCH kdf_x942_kdf_functions[] = { |
413 | { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x942kdf_new }, |
414 | { OSSL_FUNC_KDF_FREECTX, (void(*)(void))x942kdf_free }, |
415 | { OSSL_FUNC_KDF_RESET, (void(*)(void))x942kdf_reset }, |
416 | { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x942kdf_derive }, |
417 | { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, |
418 | (void(*)(void))x942kdf_settable_ctx_params }, |
419 | { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))x942kdf_set_ctx_params }, |
420 | { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, |
421 | (void(*)(void))x942kdf_gettable_ctx_params }, |
422 | { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))x942kdf_get_ctx_params }, |
423 | { 0, NULL } |
424 | }; |
425 | |
426 | #endif /* OPENSSL_NO_CMS */ |
427 | |