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