]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/dh/dh_pmeth.c
Add FFC param/key generation
[thirdparty/openssl.git] / crypto / dh / dh_pmeth.c
CommitLineData
0f113f3e 1/*
28428130 2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
3ba0885a 3 *
e38873f5 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
aa6bb135
RS
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
3ba0885a
DSH
8 */
9
10#include <stdio.h>
b39fc560 11#include "internal/cryptlib.h"
3ba0885a
DSH
12#include <openssl/asn1t.h>
13#include <openssl/x509.h>
3ba0885a 14#include <openssl/evp.h>
706457b7 15#include "dh_local.h"
1e26a8ba 16#include <openssl/bn.h>
3c27208f 17#include <openssl/dsa.h>
bd59f2b9 18#include <openssl/objects.h>
25f2138b 19#include "crypto/evp.h"
3ba0885a
DSH
20
21/* DH pkey context structure */
22
0f113f3e
MC
23typedef struct {
24 /* Parameter gen parameters */
25 int prime_len;
26 int generator;
f11f86f6 27 int paramgen_type;
0f113f3e 28 int subprime_len;
f4403a1f 29 int pad;
0f113f3e
MC
30 /* message digest used for parameter generation */
31 const EVP_MD *md;
32 int rfc5114_param;
d59d853a 33 int param_nid;
0f113f3e
MC
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;
3ba0885a
DSH
48
49static int pkey_dh_init(EVP_PKEY_CTX *ctx)
0f113f3e
MC
50{
51 DH_PKEY_CTX *dctx;
64b25758 52
cdb10bae
RS
53 if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
54 DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE);
0f113f3e 55 return 0;
cdb10bae 56 }
70b0b977 57 dctx->prime_len = 2048;
0f113f3e
MC
58 dctx->subprime_len = -1;
59 dctx->generator = 2;
0f113f3e 60 dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
0f113f3e
MC
61
62 ctx->data = dctx;
63 ctx->keygen_info = dctx->gentmp;
64 ctx->keygen_info_count = 2;
65
66 return 1;
67}
3ba0885a 68
edeb3fd2
IY
69static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
70{
71 DH_PKEY_CTX *dctx = ctx->data;
f11f86f6 72
edeb3fd2
IY
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
9fdcc21f 81static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
0f113f3e
MC
82{
83 DH_PKEY_CTX *dctx, *sctx;
12a765a5 84
0f113f3e
MC
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;
f11f86f6 92 dctx->paramgen_type = sctx->paramgen_type;
f4403a1f 93 dctx->pad = sctx->pad;
0f113f3e
MC
94 dctx->md = sctx->md;
95 dctx->rfc5114_param = sctx->rfc5114_param;
d59d853a 96 dctx->param_nid = sctx->param_nid;
0f113f3e
MC
97
98 dctx->kdf_type = sctx->kdf_type;
99 dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
edeb3fd2 100 if (dctx->kdf_oid == NULL)
0f113f3e
MC
101 return 0;
102 dctx->kdf_md = sctx->kdf_md;
edeb3fd2 103 if (sctx->kdf_ukm != NULL) {
7644a9ae 104 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
edeb3fd2
IY
105 if (dctx->kdf_ukm == NULL)
106 return 0;
0f113f3e
MC
107 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
108 }
109 dctx->kdf_outlen = sctx->kdf_outlen;
110 return 1;
111}
8bdcef40 112
3ba0885a 113static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
0f113f3e
MC
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:
f11f86f6 124 if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
0f113f3e
MC
125 return -2;
126 dctx->subprime_len = p1;
127 return 1;
128
f4403a1f
DSH
129 case EVP_PKEY_CTRL_DH_PAD:
130 dctx->pad = p1;
131 return 1;
132
0f113f3e 133 case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
f11f86f6 134 if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
0f113f3e
MC
135 return -2;
136 dctx->generator = p1;
137 return 1;
138
139 case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
39090878 140#ifdef OPENSSL_NO_DSA
f11f86f6 141 if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
0f113f3e 142 return -2;
39090878 143#else
0f113f3e
MC
144 if (p1 < 0 || p1 > 2)
145 return -2;
39090878 146#endif
f11f86f6 147 dctx->paramgen_type = p1;
0f113f3e
MC
148 return 1;
149
150 case EVP_PKEY_CTRL_DH_RFC5114:
d59d853a 151 if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
0f113f3e
MC
152 return -2;
153 dctx->rfc5114_param = p1;
154 return 1;
155
d59d853a
DSH
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
0f113f3e
MC
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;
e968561d
DB
169#ifdef OPENSSL_NO_CMS
170 if (p1 != EVP_PKEY_DH_KDF_NONE)
171#else
0f113f3e 172 if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
e968561d 173#endif
0f113f3e
MC
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:
b548a1f1 197 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
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:
0dfb9398 210 ASN1_OBJECT_free(dctx->kdf_oid);
0f113f3e
MC
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}
39090878 223
3ba0885a 224static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
225 const char *type, const char *value)
226{
86885c28 227 if (strcmp(type, "dh_paramgen_prime_len") == 0) {
0f113f3e
MC
228 int len;
229 len = atoi(value);
230 return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
231 }
86885c28 232 if (strcmp(type, "dh_rfc5114") == 0) {
0f113f3e
MC
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 }
d59d853a
DSH
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 }
86885c28 252 if (strcmp(type, "dh_paramgen_generator") == 0) {
0f113f3e
MC
253 int len;
254 len = atoi(value);
255 return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
256 }
86885c28 257 if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
0f113f3e
MC
258 int len;
259 len = atoi(value);
260 return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
261 }
86885c28 262 if (strcmp(type, "dh_paramgen_type") == 0) {
0f113f3e
MC
263 int typ;
264 typ = atoi(value);
265 return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
266 }
f4403a1f
DSH
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 }
0f113f3e
MC
272 return -2;
273}
3ba0885a 274
f11f86f6
SL
275static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx,
276 BN_GENCB *pcb)
0f113f3e 277{
f11f86f6 278 DH *ret;
0f113f3e 279 int rv = 0;
f11f86f6 280 int res;
0f113f3e
MC
281 int prime_len = dctx->prime_len;
282 int subprime_len = dctx->subprime_len;
283 const EVP_MD *md = dctx->md;
f11f86f6
SL
284
285 if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
0f113f3e 286 return NULL;
f11f86f6 287 ret = DH_new();
90945fa3 288 if (ret == NULL)
0f113f3e 289 return NULL;
f11f86f6 290
0f113f3e
MC
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 }
f11f86f6
SL
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);
0f113f3e 317 if (rv <= 0) {
f11f86f6 318 DH_free(ret);
0f113f3e
MC
319 return NULL;
320 }
321 return ret;
322}
39090878 323
f11f86f6
SL
324static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
325 EVP_PKEY *pkey)
0f113f3e
MC
326{
327 DH *dh = NULL;
328 DH_PKEY_CTX *dctx = ctx->data;
ca2bf555 329 BN_GENCB *pcb = NULL;
0f113f3e 330 int ret;
ca2bf555
SL
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
0f113f3e
MC
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 }
ca2bf555 364#endif /* FIPS_MODE */
0f113f3e 365
ca2bf555 366 if (ctx->pkey_gencb != NULL) {
0f113f3e 367 pcb = BN_GENCB_new();
90945fa3
MC
368 if (pcb == NULL)
369 return 0;
0f113f3e 370 evp_pkey_set_cb_translate(pcb, ctx);
ca2bf555 371 }
f11f86f6
SL
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);
23a1d5e9 377 BN_GENCB_free(pcb);
f11f86f6 378 if (dh == NULL)
0f113f3e
MC
379 return 0;
380 EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
381 return 1;
382 }
0f113f3e 383 dh = DH_new();
90945fa3 384 if (dh == NULL) {
23a1d5e9 385 BN_GENCB_free(pcb);
0f113f3e
MC
386 return 0;
387 }
388 ret = DH_generate_parameters_ex(dh,
389 dctx->prime_len, dctx->generator, pcb);
23a1d5e9 390 BN_GENCB_free(pcb);
0f113f3e
MC
391 if (ret)
392 EVP_PKEY_assign_DH(pkey, dh);
393 else
394 DH_free(dh);
395 return ret;
396}
3ba0885a
DSH
397
398static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e 399{
d59d853a 400 DH_PKEY_CTX *dctx = ctx->data;
0f113f3e 401 DH *dh = NULL;
d59d853a 402
ca2bf555 403 if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
0f113f3e
MC
404 DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
405 return 0;
406 }
ca2bf555 407 if (dctx->param_nid != NID_undef)
d59d853a
DSH
408 dh = DH_new_by_nid(dctx->param_nid);
409 else
410 dh = DH_new();
90945fa3 411 if (dh == NULL)
0f113f3e
MC
412 return 0;
413 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
414 /* Note: if error return, pkey is freed by parent routine */
d59d853a 415 if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
0f113f3e
MC
416 return 0;
417 return DH_generate_key(pkey->pkey.dh);
418}
419
420static 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 }
f4403a1f
DSH
438 if (dctx->pad)
439 ret = DH_compute_key_padded(key, dhpub, dh);
440 else
441 ret = DH_compute_key(key, dhpub, dh);
0f113f3e
MC
442 if (ret < 0)
443 return ret;
444 *keylen = ret;
445 return 1;
e968561d
DB
446 }
447#ifndef OPENSSL_NO_CMS
448 else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
449
0f113f3e
MC
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);
90945fa3 463 if (Z == NULL) {
918bb865
MC
464 goto err;
465 }
0f113f3e
MC
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:
4b45c6e5 474 OPENSSL_clear_free(Z, Zlen);
0f113f3e
MC
475 return ret;
476 }
e968561d
DB
477#endif
478 return 0;
0f113f3e
MC
479}
480
19bd1fa1 481static const EVP_PKEY_METHOD dh_pkey_meth = {
0f113f3e
MC
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
19bd1fa1
PS
515const EVP_PKEY_METHOD *dh_pkey_method(void)
516{
517 return &dh_pkey_meth;
518}
519
520static const EVP_PKEY_METHOD dhx_pkey_meth = {
0f113f3e
MC
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};
19bd1fa1
PS
553
554const EVP_PKEY_METHOD *dhx_pkey_method(void)
555{
556 return &dhx_pkey_meth;
557}