]> git.ipfire.org Git - thirdparty/openssl.git/blob - 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
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, 0);
190 break;
191
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:
197 params[0] = OSSL_PARAM_construct_int(name, &p1);
198 break;
199
200 case T_UINT64:
201 params[0] = OSSL_PARAM_construct_uint64(name, (uint64_t *)p2);
202 break;
203 }
204
205 return EVP_KDF_CTX_set_params(kctx, params);
206 }
207
208 static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
209 const char *value)
210 {
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);
214 BUF_MEM **collector = NULL;
215 const OSSL_PARAM *defs = EVP_KDF_settable_ctx_params(kdf);
216 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
217 int ok = 0;
218
219 /* Deal with ctrl name aliasing */
220 if (strcmp(type, "md") == 0)
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
226 if (!OSSL_PARAM_allocate_from_text(&params[0], defs, type,
227 value, strlen(value), NULL))
228 return 0;
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);
243 OPENSSL_free(params[0].data);
244 return ok;
245 }
246
247 static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
248 {
249 EVP_PKEY_KDF_CTX *pkctx = ctx->data;
250
251 pkey_kdf_free_collected(pkctx);
252 if (pkctx->kctx != NULL)
253 EVP_KDF_reset(pkctx->kctx);
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 {
264 EVP_PKEY_KDF_CTX *pkctx = ctx->data;
265 EVP_KDF_CTX *kctx = pkctx->kctx;
266 size_t outlen = EVP_KDF_size(kctx);
267 int r;
268
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);
292 if (!r)
293 return 0;
294 }
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
309 static const EVP_PKEY_METHOD scrypt_pkey_meth = {
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 };
338
339 const EVP_PKEY_METHOD *scrypt_pkey_method(void)
340 {
341 return &scrypt_pkey_meth;
342 }
343 #endif
344
345 static const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
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
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 = {
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
410 const EVP_PKEY_METHOD *hkdf_pkey_method(void)
411 {
412 return &hkdf_pkey_meth;
413 }