]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/pkey_kdf.c
Make relevant tests more sensitive to 'no-fips'
[thirdparty/openssl.git] / crypto / evp / pkey_kdf.c
CommitLineData
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
24typedef 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 33static 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
41static 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
65static 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
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
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
95static 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);
a9419205
RL
189 params[0] = OSSL_PARAM_construct_utf8_string(name, (char *)mdname,
190 strlen(mdname) + 1);
7707526b 191 break;
5a285add 192
7707526b
P
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:
a9419205 198 params[0] = OSSL_PARAM_construct_int(name, &p1);
7707526b 199 break;
5a285add 200
7707526b 201 case T_UINT64:
a9419205 202 params[0] = OSSL_PARAM_construct_uint64(name, (uint64_t *)p2);
7707526b 203 break;
5a285add 204 }
a9419205
RL
205
206 return EVP_KDF_CTX_set_params(kctx, params);
5a285add
DM
207}
208
209static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
210 const char *value)
211{
7707526b
P
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);
ea643c95 215 BUF_MEM **collector = NULL;
7707526b 216 const OSSL_PARAM *defs = EVP_KDF_CTX_settable_params(kdf);
a9419205
RL
217 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
218 int ok = 0;
5a285add 219
7707526b 220 /* Deal with ctrl name aliasing */
5a285add 221 if (strcmp(type, "md") == 0)
7707526b
P
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
a9419205
RL
227 if (!OSSL_PARAM_allocate_from_text(&params[0], defs, type,
228 value, strlen(value)))
7707526b 229 return 0;
ea643c95
RL
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);
a9419205
RL
244 OPENSSL_free(params[0].data);
245 return ok;
5a285add
DM
246}
247
248static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
249{
7707526b 250 EVP_PKEY_KDF_CTX *pkctx = ctx->data;
5a285add 251
a9419205
RL
252 pkey_kdf_free_collected(pkctx);
253 if (pkctx->kctx != NULL)
254 EVP_KDF_reset(pkctx->kctx);
5a285add
DM
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{
7707526b
P
265 EVP_PKEY_KDF_CTX *pkctx = ctx->data;
266 EVP_KDF_CTX *kctx = pkctx->kctx;
5a285add 267 size_t outlen = EVP_KDF_size(kctx);
7707526b 268 int r;
5a285add 269
a9419205
RL
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);
7707526b
P
293 if (!r)
294 return 0;
295 }
5a285add
DM
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
19bd1fa1 310static const EVP_PKEY_METHOD scrypt_pkey_meth = {
5a285add
DM
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};
19bd1fa1
PS
339
340const EVP_PKEY_METHOD *scrypt_pkey_method(void)
341{
342 return &scrypt_pkey_meth;
343}
5a285add
DM
344#endif
345
19bd1fa1 346static const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
5a285add
DM
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
19bd1fa1
PS
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 = {
5a285add
DM
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
19bd1fa1
PS
411const EVP_PKEY_METHOD *hkdf_pkey_method(void)
412{
413 return &hkdf_pkey_meth;
414}