1 | /* |
2 | * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. |
3 | * Copyright (c) 2018, 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 <string.h> |
12 | #include <openssl/evp.h> |
13 | #include <openssl/err.h> |
14 | #include <openssl/buffer.h> |
15 | #include <openssl/kdf.h> |
16 | #include <openssl/core.h> |
17 | #include <openssl/core_names.h> |
18 | #include <openssl/params.h> |
19 | #include "internal/numbers.h" |
20 | #include "crypto/evp.h" |
21 | |
22 | #define MAX_PARAM 20 |
23 | |
24 | typedef struct { |
25 | EVP_KDF_CTX *kctx; |
26 | /* |
27 | * EVP_PKEY implementations collect bits of certain data |
28 | */ |
29 | BUF_MEM *collected_seed; |
30 | BUF_MEM *collected_info; |
31 | } EVP_PKEY_KDF_CTX; |
32 | |
33 | static void pkey_kdf_free_collected(EVP_PKEY_KDF_CTX *pkctx) |
34 | { |
35 | BUF_MEM_free(pkctx->collected_seed); |
36 | pkctx->collected_seed = NULL; |
37 | BUF_MEM_free(pkctx->collected_info); |
38 | pkctx->collected_info = NULL; |
39 | } |
40 | |
41 | static int pkey_kdf_init(EVP_PKEY_CTX *ctx) |
42 | { |
43 | EVP_PKEY_KDF_CTX *pkctx; |
44 | EVP_KDF_CTX *kctx; |
45 | const char *kdf_name = OBJ_nid2sn(ctx->pmeth->pkey_id); |
46 | EVP_KDF *kdf; |
47 | |
48 | pkctx = OPENSSL_zalloc(sizeof(*pkctx)); |
49 | if (pkctx == NULL) |
50 | return 0; |
51 | |
52 | kdf = EVP_KDF_fetch(NULL, kdf_name, NULL); |
53 | kctx = EVP_KDF_CTX_new(kdf); |
54 | EVP_KDF_free(kdf); |
55 | if (kctx == NULL) { |
56 | OPENSSL_free(pkctx); |
57 | return 0; |
58 | } |
59 | |
60 | pkctx->kctx = kctx; |
61 | ctx->data = pkctx; |
62 | return 1; |
63 | } |
64 | |
65 | static void pkey_kdf_cleanup(EVP_PKEY_CTX *ctx) |
66 | { |
67 | EVP_PKEY_KDF_CTX *pkctx = ctx->data; |
68 | |
69 | EVP_KDF_CTX_free(pkctx->kctx); |
70 | pkey_kdf_free_collected(pkctx); |
71 | OPENSSL_free(pkctx); |
72 | } |
73 | |
74 | static int collect(BUF_MEM **collector, void *data, size_t datalen) |
75 | { |
76 | size_t i; |
77 | |
78 | if (*collector == NULL) |
79 | *collector = BUF_MEM_new(); |
80 | if (*collector == NULL) { |
81 | ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); |
82 | return 0; |
83 | } |
84 | |
85 | if (data != NULL && datalen > 0) { |
86 | i = (*collector)->length; /* BUF_MEM_grow() changes it! */ |
87 | |
88 | if (!BUF_MEM_grow(*collector, i + datalen)) |
89 | return 0; |
90 | memcpy((*collector)->data + i, data, datalen); |
91 | } |
92 | return 1; |
93 | } |
94 | |
95 | static int pkey_kdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) |
96 | { |
97 | EVP_PKEY_KDF_CTX *pkctx = ctx->data; |
98 | EVP_KDF_CTX *kctx = pkctx->kctx; |
99 | enum { T_OCTET_STRING, T_UINT64, T_DIGEST, T_INT } cmd; |
100 | const char *name, *mdname; |
101 | BUF_MEM **collector = NULL; |
102 | OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; |
103 | |
104 | switch (type) { |
105 | case EVP_PKEY_CTRL_PASS: |
106 | cmd = T_OCTET_STRING; |
107 | name = OSSL_KDF_PARAM_PASSWORD; |
108 | break; |
109 | case EVP_PKEY_CTRL_HKDF_SALT: |
110 | case EVP_PKEY_CTRL_SCRYPT_SALT: |
111 | cmd = T_OCTET_STRING; |
112 | name = OSSL_KDF_PARAM_SALT; |
113 | break; |
114 | case EVP_PKEY_CTRL_TLS_MD: |
115 | case EVP_PKEY_CTRL_HKDF_MD: |
116 | cmd = T_DIGEST; |
117 | name = OSSL_KDF_PARAM_DIGEST; |
118 | break; |
119 | case EVP_PKEY_CTRL_TLS_SECRET: |
120 | cmd = T_OCTET_STRING; |
121 | name = OSSL_KDF_PARAM_SECRET; |
122 | /* |
123 | * Perform the semantics described in |
124 | * EVP_PKEY_CTX_add1_tls1_prf_seed(3) |
125 | */ |
126 | if (ctx->pmeth->pkey_id == NID_tls1_prf) { |
127 | BUF_MEM_free(pkctx->collected_seed); |
128 | pkctx->collected_seed = NULL; |
129 | } |
130 | break; |
131 | case EVP_PKEY_CTRL_TLS_SEED: |
132 | cmd = T_OCTET_STRING; |
133 | name = OSSL_KDF_PARAM_SEED; |
134 | collector = &pkctx->collected_seed; |
135 | break; |
136 | case EVP_PKEY_CTRL_HKDF_KEY: |
137 | cmd = T_OCTET_STRING; |
138 | name = OSSL_KDF_PARAM_KEY; |
139 | break; |
140 | case EVP_PKEY_CTRL_HKDF_INFO: |
141 | cmd = T_OCTET_STRING; |
142 | name = OSSL_KDF_PARAM_INFO; |
143 | collector = &pkctx->collected_info; |
144 | break; |
145 | case EVP_PKEY_CTRL_HKDF_MODE: |
146 | cmd = T_INT; |
147 | name = OSSL_KDF_PARAM_MODE; |
148 | break; |
149 | case EVP_PKEY_CTRL_SCRYPT_N: |
150 | cmd = T_UINT64; |
151 | name = OSSL_KDF_PARAM_SCRYPT_N; |
152 | break; |
153 | case EVP_PKEY_CTRL_SCRYPT_R: |
154 | cmd = T_UINT64; /* Range checking occurs on the provider side */ |
155 | name = OSSL_KDF_PARAM_SCRYPT_R; |
156 | break; |
157 | case EVP_PKEY_CTRL_SCRYPT_P: |
158 | cmd = T_UINT64; /* Range checking occurs on the provider side */ |
159 | name = OSSL_KDF_PARAM_SCRYPT_P; |
160 | break; |
161 | case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES: |
162 | cmd = T_UINT64; |
163 | name = OSSL_KDF_PARAM_SCRYPT_MAXMEM; |
164 | break; |
165 | default: |
166 | return -2; |
167 | } |
168 | |
169 | if (collector != NULL) { |
170 | switch (cmd) { |
171 | case T_OCTET_STRING: |
172 | return collect(collector, p2, p1); |
173 | default: |
174 | OPENSSL_assert("You shouldn't be here" ); |
175 | break; |
176 | } |
177 | return 1; |
178 | } |
179 | |
180 | switch (cmd) { |
181 | case T_OCTET_STRING: |
182 | params[0] = |
183 | OSSL_PARAM_construct_octet_string(name, (unsigned char *)p2, |
184 | (size_t)p1); |
185 | break; |
186 | |
187 | case T_DIGEST: |
188 | mdname = EVP_MD_name((const EVP_MD *)p2); |
189 | params[0] = OSSL_PARAM_construct_utf8_string(name, (char *)mdname, |
190 | strlen(mdname) + 1); |
191 | break; |
192 | |
193 | /* |
194 | * These are special because the helper macros pass a pointer to the |
195 | * stack, so a local copy is required. |
196 | */ |
197 | case T_INT: |
198 | params[0] = OSSL_PARAM_construct_int(name, &p1); |
199 | break; |
200 | |
201 | case T_UINT64: |
202 | params[0] = OSSL_PARAM_construct_uint64(name, (uint64_t *)p2); |
203 | break; |
204 | } |
205 | |
206 | return EVP_KDF_CTX_set_params(kctx, params); |
207 | } |
208 | |
209 | static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, |
210 | const char *value) |
211 | { |
212 | EVP_PKEY_KDF_CTX *pkctx = ctx->data; |
213 | EVP_KDF_CTX *kctx = pkctx->kctx; |
214 | const EVP_KDF *kdf = EVP_KDF_CTX_kdf(kctx); |
215 | BUF_MEM **collector = NULL; |
216 | const OSSL_PARAM *defs = EVP_KDF_settable_ctx_params(kdf); |
217 | OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; |
218 | int ok = 0; |
219 | |
220 | /* Deal with ctrl name aliasing */ |
221 | if (strcmp(type, "md" ) == 0) |
222 | type = OSSL_KDF_PARAM_DIGEST; |
223 | /* scrypt uses 'N', params uses 'n' */ |
224 | if (strcmp(type, "N" ) == 0) |
225 | type = OSSL_KDF_PARAM_SCRYPT_N; |
226 | |
227 | if (!OSSL_PARAM_allocate_from_text(¶ms[0], defs, type, |
228 | value, strlen(value))) |
229 | return 0; |
230 | |
231 | /* |
232 | * We do the same special casing of seed and info here as in |
233 | * pkey_kdf_ctrl() |
234 | */ |
235 | if (strcmp(params[0].key, OSSL_KDF_PARAM_SEED) == 0) |
236 | collector = &pkctx->collected_seed; |
237 | else if (strcmp(params[0].key, OSSL_KDF_PARAM_INFO) == 0) |
238 | collector = &pkctx->collected_info; |
239 | |
240 | if (collector != NULL) |
241 | ok = collect(collector, params[0].data, params[0].data_size); |
242 | else |
243 | ok = EVP_KDF_CTX_set_params(kctx, params); |
244 | OPENSSL_free(params[0].data); |
245 | return ok; |
246 | } |
247 | |
248 | static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx) |
249 | { |
250 | EVP_PKEY_KDF_CTX *pkctx = ctx->data; |
251 | |
252 | pkey_kdf_free_collected(pkctx); |
253 | if (pkctx->kctx != NULL) |
254 | EVP_KDF_reset(pkctx->kctx); |
255 | return 1; |
256 | } |
257 | |
258 | /* |
259 | * For fixed-output algorithms the keylen parameter is an "out" parameter |
260 | * otherwise it is an "in" parameter. |
261 | */ |
262 | static int pkey_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, |
263 | size_t *keylen) |
264 | { |
265 | EVP_PKEY_KDF_CTX *pkctx = ctx->data; |
266 | EVP_KDF_CTX *kctx = pkctx->kctx; |
267 | size_t outlen = EVP_KDF_size(kctx); |
268 | int r; |
269 | |
270 | if (pkctx->collected_seed != NULL) { |
271 | OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; |
272 | |
273 | params[0] = |
274 | OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED, |
275 | pkctx->collected_seed->data, |
276 | pkctx->collected_seed->length); |
277 | |
278 | r = EVP_KDF_CTX_set_params(kctx, params); |
279 | pkey_kdf_free_collected(pkctx); |
280 | if (!r) |
281 | return 0; |
282 | } |
283 | if (pkctx->collected_info != NULL) { |
284 | OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; |
285 | |
286 | params[0] = |
287 | OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, |
288 | pkctx->collected_info->data, |
289 | pkctx->collected_info->length); |
290 | |
291 | r = EVP_KDF_CTX_set_params(kctx, params); |
292 | pkey_kdf_free_collected(pkctx); |
293 | if (!r) |
294 | return 0; |
295 | } |
296 | if (outlen == 0 || outlen == SIZE_MAX) { |
297 | /* Variable-output algorithm */ |
298 | if (key == NULL) |
299 | return 0; |
300 | } else { |
301 | /* Fixed-output algorithm */ |
302 | *keylen = outlen; |
303 | if (key == NULL) |
304 | return 1; |
305 | } |
306 | return EVP_KDF_derive(kctx, key, *keylen); |
307 | } |
308 | |
309 | #ifndef OPENSSL_NO_SCRYPT |
310 | static const EVP_PKEY_METHOD scrypt_pkey_meth = { |
311 | EVP_PKEY_SCRYPT, |
312 | 0, |
313 | pkey_kdf_init, |
314 | 0, |
315 | pkey_kdf_cleanup, |
316 | |
317 | 0, 0, |
318 | 0, 0, |
319 | |
320 | 0, |
321 | 0, |
322 | |
323 | 0, |
324 | 0, |
325 | |
326 | 0, 0, |
327 | |
328 | 0, 0, 0, 0, |
329 | |
330 | 0, 0, |
331 | |
332 | 0, 0, |
333 | |
334 | pkey_kdf_derive_init, |
335 | pkey_kdf_derive, |
336 | pkey_kdf_ctrl, |
337 | pkey_kdf_ctrl_str |
338 | }; |
339 | |
340 | const EVP_PKEY_METHOD *scrypt_pkey_method(void) |
341 | { |
342 | return &scrypt_pkey_meth; |
343 | } |
344 | #endif |
345 | |
346 | static const EVP_PKEY_METHOD tls1_prf_pkey_meth = { |
347 | EVP_PKEY_TLS1_PRF, |
348 | 0, |
349 | pkey_kdf_init, |
350 | 0, |
351 | pkey_kdf_cleanup, |
352 | |
353 | 0, 0, |
354 | 0, 0, |
355 | |
356 | 0, |
357 | 0, |
358 | |
359 | 0, |
360 | 0, |
361 | |
362 | 0, 0, |
363 | |
364 | 0, 0, 0, 0, |
365 | |
366 | 0, 0, |
367 | |
368 | 0, 0, |
369 | |
370 | pkey_kdf_derive_init, |
371 | pkey_kdf_derive, |
372 | pkey_kdf_ctrl, |
373 | pkey_kdf_ctrl_str |
374 | }; |
375 | |
376 | const EVP_PKEY_METHOD *tls1_prf_pkey_method(void) |
377 | { |
378 | return &tls1_prf_pkey_meth; |
379 | } |
380 | |
381 | static const EVP_PKEY_METHOD hkdf_pkey_meth = { |
382 | EVP_PKEY_HKDF, |
383 | 0, |
384 | pkey_kdf_init, |
385 | 0, |
386 | pkey_kdf_cleanup, |
387 | |
388 | 0, 0, |
389 | 0, 0, |
390 | |
391 | 0, |
392 | 0, |
393 | |
394 | 0, |
395 | 0, |
396 | |
397 | 0, 0, |
398 | |
399 | 0, 0, 0, 0, |
400 | |
401 | 0, 0, |
402 | |
403 | 0, 0, |
404 | |
405 | pkey_kdf_derive_init, |
406 | pkey_kdf_derive, |
407 | pkey_kdf_ctrl, |
408 | pkey_kdf_ctrl_str |
409 | }; |
410 | |
411 | const EVP_PKEY_METHOD *hkdf_pkey_method(void) |
412 | { |
413 | return &hkdf_pkey_meth; |
414 | } |
415 | |