]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/dh/dh_pmeth.c
Add FFC param/key generation
[thirdparty/openssl.git] / crypto / dh / dh_pmeth.c
1 /*
2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/asn1t.h>
13 #include <openssl/x509.h>
14 #include <openssl/evp.h>
15 #include "dh_local.h"
16 #include <openssl/bn.h>
17 #include <openssl/dsa.h>
18 #include <openssl/objects.h>
19 #include "crypto/evp.h"
20
21 /* DH pkey context structure */
22
23 typedef struct {
24 /* Parameter gen parameters */
25 int prime_len;
26 int generator;
27 int paramgen_type;
28 int subprime_len;
29 int pad;
30 /* message digest used for parameter generation */
31 const EVP_MD *md;
32 int rfc5114_param;
33 int param_nid;
34 /* Keygen callback info */
35 int gentmp[2];
36 /* KDF (if any) to use for DH */
37 char kdf_type;
38 /* OID to use for KDF */
39 ASN1_OBJECT *kdf_oid;
40 /* Message digest to use for key derivation */
41 const EVP_MD *kdf_md;
42 /* User key material */
43 unsigned char *kdf_ukm;
44 size_t kdf_ukmlen;
45 /* KDF output length */
46 size_t kdf_outlen;
47 } DH_PKEY_CTX;
48
49 static int pkey_dh_init(EVP_PKEY_CTX *ctx)
50 {
51 DH_PKEY_CTX *dctx;
52
53 if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
54 DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE);
55 return 0;
56 }
57 dctx->prime_len = 2048;
58 dctx->subprime_len = -1;
59 dctx->generator = 2;
60 dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
61
62 ctx->data = dctx;
63 ctx->keygen_info = dctx->gentmp;
64 ctx->keygen_info_count = 2;
65
66 return 1;
67 }
68
69 static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
70 {
71 DH_PKEY_CTX *dctx = ctx->data;
72
73 if (dctx != NULL) {
74 OPENSSL_free(dctx->kdf_ukm);
75 ASN1_OBJECT_free(dctx->kdf_oid);
76 OPENSSL_free(dctx);
77 }
78 }
79
80
81 static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
82 {
83 DH_PKEY_CTX *dctx, *sctx;
84
85 if (!pkey_dh_init(dst))
86 return 0;
87 sctx = src->data;
88 dctx = dst->data;
89 dctx->prime_len = sctx->prime_len;
90 dctx->subprime_len = sctx->subprime_len;
91 dctx->generator = sctx->generator;
92 dctx->paramgen_type = sctx->paramgen_type;
93 dctx->pad = sctx->pad;
94 dctx->md = sctx->md;
95 dctx->rfc5114_param = sctx->rfc5114_param;
96 dctx->param_nid = sctx->param_nid;
97
98 dctx->kdf_type = sctx->kdf_type;
99 dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
100 if (dctx->kdf_oid == NULL)
101 return 0;
102 dctx->kdf_md = sctx->kdf_md;
103 if (sctx->kdf_ukm != NULL) {
104 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
105 if (dctx->kdf_ukm == NULL)
106 return 0;
107 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
108 }
109 dctx->kdf_outlen = sctx->kdf_outlen;
110 return 1;
111 }
112
113 static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
114 {
115 DH_PKEY_CTX *dctx = ctx->data;
116 switch (type) {
117 case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
118 if (p1 < 256)
119 return -2;
120 dctx->prime_len = p1;
121 return 1;
122
123 case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
124 if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
125 return -2;
126 dctx->subprime_len = p1;
127 return 1;
128
129 case EVP_PKEY_CTRL_DH_PAD:
130 dctx->pad = p1;
131 return 1;
132
133 case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
134 if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
135 return -2;
136 dctx->generator = p1;
137 return 1;
138
139 case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
140 #ifdef OPENSSL_NO_DSA
141 if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
142 return -2;
143 #else
144 if (p1 < 0 || p1 > 2)
145 return -2;
146 #endif
147 dctx->paramgen_type = p1;
148 return 1;
149
150 case EVP_PKEY_CTRL_DH_RFC5114:
151 if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
152 return -2;
153 dctx->rfc5114_param = p1;
154 return 1;
155
156 case EVP_PKEY_CTRL_DH_NID:
157 if (p1 <= 0 || dctx->rfc5114_param != 0)
158 return -2;
159 dctx->param_nid = p1;
160 return 1;
161
162 case EVP_PKEY_CTRL_PEER_KEY:
163 /* Default behaviour is OK */
164 return 1;
165
166 case EVP_PKEY_CTRL_DH_KDF_TYPE:
167 if (p1 == -2)
168 return dctx->kdf_type;
169 #ifdef OPENSSL_NO_CMS
170 if (p1 != EVP_PKEY_DH_KDF_NONE)
171 #else
172 if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
173 #endif
174 return -2;
175 dctx->kdf_type = p1;
176 return 1;
177
178 case EVP_PKEY_CTRL_DH_KDF_MD:
179 dctx->kdf_md = p2;
180 return 1;
181
182 case EVP_PKEY_CTRL_GET_DH_KDF_MD:
183 *(const EVP_MD **)p2 = dctx->kdf_md;
184 return 1;
185
186 case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
187 if (p1 <= 0)
188 return -2;
189 dctx->kdf_outlen = (size_t)p1;
190 return 1;
191
192 case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
193 *(int *)p2 = dctx->kdf_outlen;
194 return 1;
195
196 case EVP_PKEY_CTRL_DH_KDF_UKM:
197 OPENSSL_free(dctx->kdf_ukm);
198 dctx->kdf_ukm = p2;
199 if (p2)
200 dctx->kdf_ukmlen = p1;
201 else
202 dctx->kdf_ukmlen = 0;
203 return 1;
204
205 case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
206 *(unsigned char **)p2 = dctx->kdf_ukm;
207 return dctx->kdf_ukmlen;
208
209 case EVP_PKEY_CTRL_DH_KDF_OID:
210 ASN1_OBJECT_free(dctx->kdf_oid);
211 dctx->kdf_oid = p2;
212 return 1;
213
214 case EVP_PKEY_CTRL_GET_DH_KDF_OID:
215 *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
216 return 1;
217
218 default:
219 return -2;
220
221 }
222 }
223
224 static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
225 const char *type, const char *value)
226 {
227 if (strcmp(type, "dh_paramgen_prime_len") == 0) {
228 int len;
229 len = atoi(value);
230 return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
231 }
232 if (strcmp(type, "dh_rfc5114") == 0) {
233 DH_PKEY_CTX *dctx = ctx->data;
234 int len;
235 len = atoi(value);
236 if (len < 0 || len > 3)
237 return -2;
238 dctx->rfc5114_param = len;
239 return 1;
240 }
241 if (strcmp(type, "dh_param") == 0) {
242 DH_PKEY_CTX *dctx = ctx->data;
243 int nid = OBJ_sn2nid(value);
244
245 if (nid == NID_undef) {
246 DHerr(DH_F_PKEY_DH_CTRL_STR, DH_R_INVALID_PARAMETER_NAME);
247 return -2;
248 }
249 dctx->param_nid = nid;
250 return 1;
251 }
252 if (strcmp(type, "dh_paramgen_generator") == 0) {
253 int len;
254 len = atoi(value);
255 return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
256 }
257 if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
258 int len;
259 len = atoi(value);
260 return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
261 }
262 if (strcmp(type, "dh_paramgen_type") == 0) {
263 int typ;
264 typ = atoi(value);
265 return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
266 }
267 if (strcmp(type, "dh_pad") == 0) {
268 int pad;
269 pad = atoi(value);
270 return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
271 }
272 return -2;
273 }
274
275 static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx,
276 BN_GENCB *pcb)
277 {
278 DH *ret;
279 int rv = 0;
280 int res;
281 int prime_len = dctx->prime_len;
282 int subprime_len = dctx->subprime_len;
283 const EVP_MD *md = dctx->md;
284
285 if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
286 return NULL;
287 ret = DH_new();
288 if (ret == NULL)
289 return NULL;
290
291 if (subprime_len == -1) {
292 if (prime_len >= 2048)
293 subprime_len = 256;
294 else
295 subprime_len = 160;
296 }
297 if (md == NULL) {
298 if (prime_len >= 2048)
299 md = EVP_sha256();
300 else
301 md = EVP_sha1();
302 }
303 # ifndef FIPS_MODE
304 if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
305 rv = ffc_params_FIPS186_2_generate(libctx, &ret->params,
306 FFC_PARAM_TYPE_DH,
307 prime_len, subprime_len, md, &res,
308 pcb);
309 else
310 # endif
311 /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
312 if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
313 rv = ffc_params_FIPS186_4_generate(libctx, &ret->params,
314 FFC_PARAM_TYPE_DH,
315 prime_len, subprime_len, md, &res,
316 pcb);
317 if (rv <= 0) {
318 DH_free(ret);
319 return NULL;
320 }
321 return ret;
322 }
323
324 static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
325 EVP_PKEY *pkey)
326 {
327 DH *dh = NULL;
328 DH_PKEY_CTX *dctx = ctx->data;
329 BN_GENCB *pcb = NULL;
330 int ret;
331
332 /*
333 * Look for a safe prime group for key establishment. Which uses
334 * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
335 */
336 if (dctx->param_nid != NID_undef) {
337 if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
338 return 0;
339 EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh);
340 return 1;
341 }
342
343 #ifndef FIPS_MODE
344 if (dctx->rfc5114_param) {
345 switch (dctx->rfc5114_param) {
346 case 1:
347 dh = DH_get_1024_160();
348 break;
349
350 case 2:
351 dh = DH_get_2048_224();
352 break;
353
354 case 3:
355 dh = DH_get_2048_256();
356 break;
357
358 default:
359 return -2;
360 }
361 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
362 return 1;
363 }
364 #endif /* FIPS_MODE */
365
366 if (ctx->pkey_gencb != NULL) {
367 pcb = BN_GENCB_new();
368 if (pcb == NULL)
369 return 0;
370 evp_pkey_set_cb_translate(pcb, ctx);
371 }
372 # ifdef FIPS_MODE
373 dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
374 # endif /* FIPS_MODE */
375 if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
376 dh = ffc_params_generate(NULL, dctx, pcb);
377 BN_GENCB_free(pcb);
378 if (dh == NULL)
379 return 0;
380 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
381 return 1;
382 }
383 dh = DH_new();
384 if (dh == NULL) {
385 BN_GENCB_free(pcb);
386 return 0;
387 }
388 ret = DH_generate_parameters_ex(dh,
389 dctx->prime_len, dctx->generator, pcb);
390 BN_GENCB_free(pcb);
391 if (ret)
392 EVP_PKEY_assign_DH(pkey, dh);
393 else
394 DH_free(dh);
395 return ret;
396 }
397
398 static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
399 {
400 DH_PKEY_CTX *dctx = ctx->data;
401 DH *dh = NULL;
402
403 if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
404 DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
405 return 0;
406 }
407 if (dctx->param_nid != NID_undef)
408 dh = DH_new_by_nid(dctx->param_nid);
409 else
410 dh = DH_new();
411 if (dh == NULL)
412 return 0;
413 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
414 /* Note: if error return, pkey is freed by parent routine */
415 if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
416 return 0;
417 return DH_generate_key(pkey->pkey.dh);
418 }
419
420 static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
421 size_t *keylen)
422 {
423 int ret;
424 DH *dh;
425 DH_PKEY_CTX *dctx = ctx->data;
426 BIGNUM *dhpub;
427 if (!ctx->pkey || !ctx->peerkey) {
428 DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
429 return 0;
430 }
431 dh = ctx->pkey->pkey.dh;
432 dhpub = ctx->peerkey->pkey.dh->pub_key;
433 if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
434 if (key == NULL) {
435 *keylen = DH_size(dh);
436 return 1;
437 }
438 if (dctx->pad)
439 ret = DH_compute_key_padded(key, dhpub, dh);
440 else
441 ret = DH_compute_key(key, dhpub, dh);
442 if (ret < 0)
443 return ret;
444 *keylen = ret;
445 return 1;
446 }
447 #ifndef OPENSSL_NO_CMS
448 else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
449
450 unsigned char *Z = NULL;
451 size_t Zlen = 0;
452 if (!dctx->kdf_outlen || !dctx->kdf_oid)
453 return 0;
454 if (key == NULL) {
455 *keylen = dctx->kdf_outlen;
456 return 1;
457 }
458 if (*keylen != dctx->kdf_outlen)
459 return 0;
460 ret = 0;
461 Zlen = DH_size(dh);
462 Z = OPENSSL_malloc(Zlen);
463 if (Z == NULL) {
464 goto err;
465 }
466 if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
467 goto err;
468 if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
469 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
470 goto err;
471 *keylen = dctx->kdf_outlen;
472 ret = 1;
473 err:
474 OPENSSL_clear_free(Z, Zlen);
475 return ret;
476 }
477 #endif
478 return 0;
479 }
480
481 static const EVP_PKEY_METHOD dh_pkey_meth = {
482 EVP_PKEY_DH,
483 0,
484 pkey_dh_init,
485 pkey_dh_copy,
486 pkey_dh_cleanup,
487
488 0,
489 pkey_dh_paramgen,
490
491 0,
492 pkey_dh_keygen,
493
494 0,
495 0,
496
497 0,
498 0,
499
500 0, 0,
501
502 0, 0, 0, 0,
503
504 0, 0,
505
506 0, 0,
507
508 0,
509 pkey_dh_derive,
510
511 pkey_dh_ctrl,
512 pkey_dh_ctrl_str
513 };
514
515 const EVP_PKEY_METHOD *dh_pkey_method(void)
516 {
517 return &dh_pkey_meth;
518 }
519
520 static const EVP_PKEY_METHOD dhx_pkey_meth = {
521 EVP_PKEY_DHX,
522 0,
523 pkey_dh_init,
524 pkey_dh_copy,
525 pkey_dh_cleanup,
526
527 0,
528 pkey_dh_paramgen,
529
530 0,
531 pkey_dh_keygen,
532
533 0,
534 0,
535
536 0,
537 0,
538
539 0, 0,
540
541 0, 0, 0, 0,
542
543 0, 0,
544
545 0, 0,
546
547 0,
548 pkey_dh_derive,
549
550 pkey_dh_ctrl,
551 pkey_dh_ctrl_str
552 };
553
554 const EVP_PKEY_METHOD *dhx_pkey_method(void)
555 {
556 return &dhx_pkey_meth;
557 }