]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/pkey_kdf.c
Params: add argument to the _from_text calls to indicate if the param exists.
[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);
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
208static 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(&params[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
247static 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 */
261static 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 309static 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
339const EVP_PKEY_METHOD *scrypt_pkey_method(void)
340{
341 return &scrypt_pkey_meth;
342}
5a285add
DM
343#endif
344
19bd1fa1 345static 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
375const EVP_PKEY_METHOD *tls1_prf_pkey_method(void)
376{
377 return &tls1_prf_pkey_meth;
378}
379
380static 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
410const EVP_PKEY_METHOD *hkdf_pkey_method(void)
411{
412 return &hkdf_pkey_meth;
413}