]> git.ipfire.org Git - thirdparty/openssl.git/blame_incremental - crypto/evp/pkey_kdf.c
Make relevant tests more sensitive to 'no-fips'
[thirdparty/openssl.git] / crypto / evp / pkey_kdf.c
... / ...
CommitLineData
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
24typedef 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
33static 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
41static 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
65static 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
74static 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
95static 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
209static 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_CTX_settable_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(&params[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
248static 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 */
262static 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
310static 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
340const EVP_PKEY_METHOD *scrypt_pkey_method(void)
341{
342 return &scrypt_pkey_meth;
343}
344#endif
345
346static 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
376const EVP_PKEY_METHOD *tls1_prf_pkey_method(void)
377{
378 return &tls1_prf_pkey_meth;
379}
380
381static 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
411const EVP_PKEY_METHOD *hkdf_pkey_method(void)
412{
413 return &hkdf_pkey_meth;
414}