16f9291ceSJung-uk Kim /*
2*b077aed3SPierre Pronchery * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
31f13597dSJung-uk Kim *
4*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
81f13597dSJung-uk Kim */
91f13597dSJung-uk Kim
10*b077aed3SPierre Pronchery /*
11*b077aed3SPierre Pronchery * DH & DSA low level APIs are deprecated for public use, but still ok for
12*b077aed3SPierre Pronchery * internal use.
13*b077aed3SPierre Pronchery */
14*b077aed3SPierre Pronchery #include "internal/deprecated.h"
15*b077aed3SPierre Pronchery
161f13597dSJung-uk Kim #include <stdio.h>
17e71b7053SJung-uk Kim #include "internal/cryptlib.h"
181f13597dSJung-uk Kim #include <openssl/asn1t.h>
191f13597dSJung-uk Kim #include <openssl/x509.h>
201f13597dSJung-uk Kim #include <openssl/evp.h>
2117f01e99SJung-uk Kim #include "dh_local.h"
221f13597dSJung-uk Kim #include <openssl/bn.h>
237bded2dbSJung-uk Kim #include <openssl/dsa.h>
247bded2dbSJung-uk Kim #include <openssl/objects.h>
2517f01e99SJung-uk Kim #include "crypto/evp.h"
261f13597dSJung-uk Kim
271f13597dSJung-uk Kim /* DH pkey context structure */
281f13597dSJung-uk Kim
296f9291ceSJung-uk Kim typedef struct {
301f13597dSJung-uk Kim /* Parameter gen parameters */
311f13597dSJung-uk Kim int prime_len;
321f13597dSJung-uk Kim int generator;
33*b077aed3SPierre Pronchery int paramgen_type;
347bded2dbSJung-uk Kim int subprime_len;
35e71b7053SJung-uk Kim int pad;
367bded2dbSJung-uk Kim /* message digest used for parameter generation */
377bded2dbSJung-uk Kim const EVP_MD *md;
38e71b7053SJung-uk Kim int param_nid;
391f13597dSJung-uk Kim /* Keygen callback info */
401f13597dSJung-uk Kim int gentmp[2];
417bded2dbSJung-uk Kim /* KDF (if any) to use for DH */
427bded2dbSJung-uk Kim char kdf_type;
437bded2dbSJung-uk Kim /* OID to use for KDF */
447bded2dbSJung-uk Kim ASN1_OBJECT *kdf_oid;
457bded2dbSJung-uk Kim /* Message digest to use for key derivation */
467bded2dbSJung-uk Kim const EVP_MD *kdf_md;
477bded2dbSJung-uk Kim /* User key material */
487bded2dbSJung-uk Kim unsigned char *kdf_ukm;
497bded2dbSJung-uk Kim size_t kdf_ukmlen;
507bded2dbSJung-uk Kim /* KDF output length */
517bded2dbSJung-uk Kim size_t kdf_outlen;
521f13597dSJung-uk Kim } DH_PKEY_CTX;
531f13597dSJung-uk Kim
pkey_dh_init(EVP_PKEY_CTX * ctx)541f13597dSJung-uk Kim static int pkey_dh_init(EVP_PKEY_CTX *ctx)
551f13597dSJung-uk Kim {
561f13597dSJung-uk Kim DH_PKEY_CTX *dctx;
57e71b7053SJung-uk Kim
58e71b7053SJung-uk Kim if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
59*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
601f13597dSJung-uk Kim return 0;
61e71b7053SJung-uk Kim }
62610a21fdSJung-uk Kim dctx->prime_len = 2048;
637bded2dbSJung-uk Kim dctx->subprime_len = -1;
641f13597dSJung-uk Kim dctx->generator = 2;
657bded2dbSJung-uk Kim dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
661f13597dSJung-uk Kim
671f13597dSJung-uk Kim ctx->data = dctx;
681f13597dSJung-uk Kim ctx->keygen_info = dctx->gentmp;
691f13597dSJung-uk Kim ctx->keygen_info_count = 2;
701f13597dSJung-uk Kim
711f13597dSJung-uk Kim return 1;
721f13597dSJung-uk Kim }
731f13597dSJung-uk Kim
pkey_dh_cleanup(EVP_PKEY_CTX * ctx)74e71b7053SJung-uk Kim static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
75e71b7053SJung-uk Kim {
76e71b7053SJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
77*b077aed3SPierre Pronchery
78e71b7053SJung-uk Kim if (dctx != NULL) {
79e71b7053SJung-uk Kim OPENSSL_free(dctx->kdf_ukm);
80e71b7053SJung-uk Kim ASN1_OBJECT_free(dctx->kdf_oid);
81e71b7053SJung-uk Kim OPENSSL_free(dctx);
82e71b7053SJung-uk Kim }
83e71b7053SJung-uk Kim }
84e71b7053SJung-uk Kim
85e71b7053SJung-uk Kim
pkey_dh_copy(EVP_PKEY_CTX * dst,const EVP_PKEY_CTX * src)86*b077aed3SPierre Pronchery static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
871f13597dSJung-uk Kim {
881f13597dSJung-uk Kim DH_PKEY_CTX *dctx, *sctx;
89*b077aed3SPierre Pronchery
901f13597dSJung-uk Kim if (!pkey_dh_init(dst))
911f13597dSJung-uk Kim return 0;
921f13597dSJung-uk Kim sctx = src->data;
931f13597dSJung-uk Kim dctx = dst->data;
941f13597dSJung-uk Kim dctx->prime_len = sctx->prime_len;
957bded2dbSJung-uk Kim dctx->subprime_len = sctx->subprime_len;
961f13597dSJung-uk Kim dctx->generator = sctx->generator;
97*b077aed3SPierre Pronchery dctx->paramgen_type = sctx->paramgen_type;
98e71b7053SJung-uk Kim dctx->pad = sctx->pad;
997bded2dbSJung-uk Kim dctx->md = sctx->md;
100e71b7053SJung-uk Kim dctx->param_nid = sctx->param_nid;
1017bded2dbSJung-uk Kim
1027bded2dbSJung-uk Kim dctx->kdf_type = sctx->kdf_type;
1037bded2dbSJung-uk Kim dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
104e71b7053SJung-uk Kim if (dctx->kdf_oid == NULL)
1057bded2dbSJung-uk Kim return 0;
1067bded2dbSJung-uk Kim dctx->kdf_md = sctx->kdf_md;
107e71b7053SJung-uk Kim if (sctx->kdf_ukm != NULL) {
108e71b7053SJung-uk Kim dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
109e71b7053SJung-uk Kim if (dctx->kdf_ukm == NULL)
110e71b7053SJung-uk Kim return 0;
1117bded2dbSJung-uk Kim dctx->kdf_ukmlen = sctx->kdf_ukmlen;
1127bded2dbSJung-uk Kim }
1137bded2dbSJung-uk Kim dctx->kdf_outlen = sctx->kdf_outlen;
1141f13597dSJung-uk Kim return 1;
1151f13597dSJung-uk Kim }
1161f13597dSJung-uk Kim
pkey_dh_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)1171f13597dSJung-uk Kim static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
1181f13597dSJung-uk Kim {
1191f13597dSJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
1206f9291ceSJung-uk Kim switch (type) {
1211f13597dSJung-uk Kim case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
1221f13597dSJung-uk Kim if (p1 < 256)
1231f13597dSJung-uk Kim return -2;
1241f13597dSJung-uk Kim dctx->prime_len = p1;
1251f13597dSJung-uk Kim return 1;
1261f13597dSJung-uk Kim
1277bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
128*b077aed3SPierre Pronchery if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR)
1297bded2dbSJung-uk Kim return -2;
1307bded2dbSJung-uk Kim dctx->subprime_len = p1;
1317bded2dbSJung-uk Kim return 1;
1327bded2dbSJung-uk Kim
133e71b7053SJung-uk Kim case EVP_PKEY_CTRL_DH_PAD:
134e71b7053SJung-uk Kim dctx->pad = p1;
135e71b7053SJung-uk Kim return 1;
136e71b7053SJung-uk Kim
1371f13597dSJung-uk Kim case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
138*b077aed3SPierre Pronchery if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR)
1397bded2dbSJung-uk Kim return -2;
1401f13597dSJung-uk Kim dctx->generator = p1;
1411f13597dSJung-uk Kim return 1;
1421f13597dSJung-uk Kim
1437bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
1447bded2dbSJung-uk Kim #ifdef OPENSSL_NO_DSA
145*b077aed3SPierre Pronchery if (p1 != DH_PARAMGEN_TYPE_GENERATOR)
1467bded2dbSJung-uk Kim return -2;
1477bded2dbSJung-uk Kim #else
1487bded2dbSJung-uk Kim if (p1 < 0 || p1 > 2)
1497bded2dbSJung-uk Kim return -2;
1507bded2dbSJung-uk Kim #endif
151*b077aed3SPierre Pronchery dctx->paramgen_type = p1;
1527bded2dbSJung-uk Kim return 1;
1537bded2dbSJung-uk Kim
1547bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_RFC5114:
155e71b7053SJung-uk Kim if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
1567bded2dbSJung-uk Kim return -2;
157*b077aed3SPierre Pronchery dctx->param_nid = p1;
1587bded2dbSJung-uk Kim return 1;
1597bded2dbSJung-uk Kim
160e71b7053SJung-uk Kim case EVP_PKEY_CTRL_DH_NID:
161*b077aed3SPierre Pronchery if (p1 <= 0 || dctx->param_nid != NID_undef)
162e71b7053SJung-uk Kim return -2;
163e71b7053SJung-uk Kim dctx->param_nid = p1;
164e71b7053SJung-uk Kim return 1;
165e71b7053SJung-uk Kim
1661f13597dSJung-uk Kim case EVP_PKEY_CTRL_PEER_KEY:
1671f13597dSJung-uk Kim /* Default behaviour is OK */
1681f13597dSJung-uk Kim return 1;
1691f13597dSJung-uk Kim
1707bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_KDF_TYPE:
1717bded2dbSJung-uk Kim if (p1 == -2)
1727bded2dbSJung-uk Kim return dctx->kdf_type;
1737bded2dbSJung-uk Kim if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
1747bded2dbSJung-uk Kim return -2;
1757bded2dbSJung-uk Kim dctx->kdf_type = p1;
1767bded2dbSJung-uk Kim return 1;
1777bded2dbSJung-uk Kim
1787bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_KDF_MD:
1797bded2dbSJung-uk Kim dctx->kdf_md = p2;
1807bded2dbSJung-uk Kim return 1;
1817bded2dbSJung-uk Kim
1827bded2dbSJung-uk Kim case EVP_PKEY_CTRL_GET_DH_KDF_MD:
1837bded2dbSJung-uk Kim *(const EVP_MD **)p2 = dctx->kdf_md;
1847bded2dbSJung-uk Kim return 1;
1857bded2dbSJung-uk Kim
1867bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
1877bded2dbSJung-uk Kim if (p1 <= 0)
1887bded2dbSJung-uk Kim return -2;
1897bded2dbSJung-uk Kim dctx->kdf_outlen = (size_t)p1;
1907bded2dbSJung-uk Kim return 1;
1917bded2dbSJung-uk Kim
1927bded2dbSJung-uk Kim case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
1937bded2dbSJung-uk Kim *(int *)p2 = dctx->kdf_outlen;
1947bded2dbSJung-uk Kim return 1;
1957bded2dbSJung-uk Kim
1967bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_KDF_UKM:
1977bded2dbSJung-uk Kim OPENSSL_free(dctx->kdf_ukm);
1987bded2dbSJung-uk Kim dctx->kdf_ukm = p2;
1997bded2dbSJung-uk Kim if (p2)
2007bded2dbSJung-uk Kim dctx->kdf_ukmlen = p1;
2017bded2dbSJung-uk Kim else
2027bded2dbSJung-uk Kim dctx->kdf_ukmlen = 0;
2037bded2dbSJung-uk Kim return 1;
2047bded2dbSJung-uk Kim
2057bded2dbSJung-uk Kim case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
2067bded2dbSJung-uk Kim *(unsigned char **)p2 = dctx->kdf_ukm;
2077bded2dbSJung-uk Kim return dctx->kdf_ukmlen;
2087bded2dbSJung-uk Kim
2097bded2dbSJung-uk Kim case EVP_PKEY_CTRL_DH_KDF_OID:
2107bded2dbSJung-uk Kim ASN1_OBJECT_free(dctx->kdf_oid);
2117bded2dbSJung-uk Kim dctx->kdf_oid = p2;
2127bded2dbSJung-uk Kim return 1;
2137bded2dbSJung-uk Kim
2147bded2dbSJung-uk Kim case EVP_PKEY_CTRL_GET_DH_KDF_OID:
2157bded2dbSJung-uk Kim *(ASN1_OBJECT **)p2 = dctx->kdf_oid;
2167bded2dbSJung-uk Kim return 1;
2177bded2dbSJung-uk Kim
2181f13597dSJung-uk Kim default:
2191f13597dSJung-uk Kim return -2;
2201f13597dSJung-uk Kim
2211f13597dSJung-uk Kim }
2221f13597dSJung-uk Kim }
2231f13597dSJung-uk Kim
pkey_dh_ctrl_str(EVP_PKEY_CTX * ctx,const char * type,const char * value)2241f13597dSJung-uk Kim static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
2251f13597dSJung-uk Kim const char *type, const char *value)
2261f13597dSJung-uk Kim {
227e71b7053SJung-uk Kim if (strcmp(type, "dh_paramgen_prime_len") == 0) {
2281f13597dSJung-uk Kim int len;
2291f13597dSJung-uk Kim len = atoi(value);
2301f13597dSJung-uk Kim return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
2311f13597dSJung-uk Kim }
232e71b7053SJung-uk Kim if (strcmp(type, "dh_rfc5114") == 0) {
2337bded2dbSJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
234*b077aed3SPierre Pronchery int id;
235*b077aed3SPierre Pronchery
236*b077aed3SPierre Pronchery id = atoi(value);
237*b077aed3SPierre Pronchery if (id < 0 || id > 3)
2387bded2dbSJung-uk Kim return -2;
239*b077aed3SPierre Pronchery dctx->param_nid = id;
2407bded2dbSJung-uk Kim return 1;
2417bded2dbSJung-uk Kim }
242e71b7053SJung-uk Kim if (strcmp(type, "dh_param") == 0) {
243e71b7053SJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
244e71b7053SJung-uk Kim int nid = OBJ_sn2nid(value);
245e71b7053SJung-uk Kim
246e71b7053SJung-uk Kim if (nid == NID_undef) {
247*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME);
248e71b7053SJung-uk Kim return -2;
249e71b7053SJung-uk Kim }
250e71b7053SJung-uk Kim dctx->param_nid = nid;
251e71b7053SJung-uk Kim return 1;
252e71b7053SJung-uk Kim }
253e71b7053SJung-uk Kim if (strcmp(type, "dh_paramgen_generator") == 0) {
2541f13597dSJung-uk Kim int len;
2551f13597dSJung-uk Kim len = atoi(value);
2561f13597dSJung-uk Kim return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
2571f13597dSJung-uk Kim }
258e71b7053SJung-uk Kim if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
2597bded2dbSJung-uk Kim int len;
2607bded2dbSJung-uk Kim len = atoi(value);
2617bded2dbSJung-uk Kim return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
2627bded2dbSJung-uk Kim }
263e71b7053SJung-uk Kim if (strcmp(type, "dh_paramgen_type") == 0) {
2647bded2dbSJung-uk Kim int typ;
2657bded2dbSJung-uk Kim typ = atoi(value);
2667bded2dbSJung-uk Kim return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
2677bded2dbSJung-uk Kim }
268e71b7053SJung-uk Kim if (strcmp(type, "dh_pad") == 0) {
269e71b7053SJung-uk Kim int pad;
270e71b7053SJung-uk Kim pad = atoi(value);
271e71b7053SJung-uk Kim return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
272e71b7053SJung-uk Kim }
2731f13597dSJung-uk Kim return -2;
2741f13597dSJung-uk Kim }
2751f13597dSJung-uk Kim
ffc_params_generate(OSSL_LIB_CTX * libctx,DH_PKEY_CTX * dctx,BN_GENCB * pcb)276*b077aed3SPierre Pronchery static DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx,
277*b077aed3SPierre Pronchery BN_GENCB *pcb)
2787bded2dbSJung-uk Kim {
279*b077aed3SPierre Pronchery DH *ret;
2807bded2dbSJung-uk Kim int rv = 0;
281*b077aed3SPierre Pronchery int res;
2827bded2dbSJung-uk Kim int prime_len = dctx->prime_len;
2837bded2dbSJung-uk Kim int subprime_len = dctx->subprime_len;
284*b077aed3SPierre Pronchery
285*b077aed3SPierre Pronchery if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
2867bded2dbSJung-uk Kim return NULL;
287*b077aed3SPierre Pronchery ret = DH_new();
288e71b7053SJung-uk Kim if (ret == NULL)
2897bded2dbSJung-uk Kim return NULL;
290*b077aed3SPierre Pronchery
2917bded2dbSJung-uk Kim if (subprime_len == -1) {
2927bded2dbSJung-uk Kim if (prime_len >= 2048)
2937bded2dbSJung-uk Kim subprime_len = 256;
2947bded2dbSJung-uk Kim else
2957bded2dbSJung-uk Kim subprime_len = 160;
2967bded2dbSJung-uk Kim }
297*b077aed3SPierre Pronchery
298*b077aed3SPierre Pronchery if (dctx->md != NULL)
299*b077aed3SPierre Pronchery ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL);
300*b077aed3SPierre Pronchery
301*b077aed3SPierre Pronchery # ifndef FIPS_MODULE
302*b077aed3SPierre Pronchery if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
303*b077aed3SPierre Pronchery rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params,
304*b077aed3SPierre Pronchery FFC_PARAM_TYPE_DH,
305*b077aed3SPierre Pronchery prime_len, subprime_len, &res,
306*b077aed3SPierre Pronchery pcb);
3077bded2dbSJung-uk Kim else
308*b077aed3SPierre Pronchery # endif
309*b077aed3SPierre Pronchery /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
310*b077aed3SPierre Pronchery if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
311*b077aed3SPierre Pronchery rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params,
312*b077aed3SPierre Pronchery FFC_PARAM_TYPE_DH,
313*b077aed3SPierre Pronchery prime_len, subprime_len, &res,
314*b077aed3SPierre Pronchery pcb);
3157bded2dbSJung-uk Kim if (rv <= 0) {
316*b077aed3SPierre Pronchery DH_free(ret);
3177bded2dbSJung-uk Kim return NULL;
3187bded2dbSJung-uk Kim }
3197bded2dbSJung-uk Kim return ret;
3207bded2dbSJung-uk Kim }
3217bded2dbSJung-uk Kim
pkey_dh_paramgen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)322*b077aed3SPierre Pronchery static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
323*b077aed3SPierre Pronchery EVP_PKEY *pkey)
3241f13597dSJung-uk Kim {
3251f13597dSJung-uk Kim DH *dh = NULL;
3261f13597dSJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
327*b077aed3SPierre Pronchery BN_GENCB *pcb = NULL;
3281f13597dSJung-uk Kim int ret;
3297bded2dbSJung-uk Kim
330*b077aed3SPierre Pronchery /*
331*b077aed3SPierre Pronchery * Look for a safe prime group for key establishment. Which uses
332*b077aed3SPierre Pronchery * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
333*b077aed3SPierre Pronchery * RFC_5114 is also handled here for param_nid = (1..3)
334*b077aed3SPierre Pronchery */
335*b077aed3SPierre Pronchery if (dctx->param_nid != NID_undef) {
336*b077aed3SPierre Pronchery int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH;
3377bded2dbSJung-uk Kim
338e71b7053SJung-uk Kim if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
339e71b7053SJung-uk Kim return 0;
340*b077aed3SPierre Pronchery EVP_PKEY_assign(pkey, type, dh);
341e71b7053SJung-uk Kim return 1;
342e71b7053SJung-uk Kim }
343e71b7053SJung-uk Kim
344*b077aed3SPierre Pronchery if (ctx->pkey_gencb != NULL) {
345e71b7053SJung-uk Kim pcb = BN_GENCB_new();
346e71b7053SJung-uk Kim if (pcb == NULL)
347e71b7053SJung-uk Kim return 0;
3481f13597dSJung-uk Kim evp_pkey_set_cb_translate(pcb, ctx);
349*b077aed3SPierre Pronchery }
350*b077aed3SPierre Pronchery # ifdef FIPS_MODULE
351*b077aed3SPierre Pronchery dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
352*b077aed3SPierre Pronchery # endif /* FIPS_MODULE */
353*b077aed3SPierre Pronchery if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
354*b077aed3SPierre Pronchery dh = ffc_params_generate(NULL, dctx, pcb);
355e71b7053SJung-uk Kim BN_GENCB_free(pcb);
356*b077aed3SPierre Pronchery if (dh == NULL)
3577bded2dbSJung-uk Kim return 0;
3587bded2dbSJung-uk Kim EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
3597bded2dbSJung-uk Kim return 1;
3607bded2dbSJung-uk Kim }
3611f13597dSJung-uk Kim dh = DH_new();
362e71b7053SJung-uk Kim if (dh == NULL) {
363e71b7053SJung-uk Kim BN_GENCB_free(pcb);
3641f13597dSJung-uk Kim return 0;
365e71b7053SJung-uk Kim }
3661f13597dSJung-uk Kim ret = DH_generate_parameters_ex(dh,
3671f13597dSJung-uk Kim dctx->prime_len, dctx->generator, pcb);
368e71b7053SJung-uk Kim BN_GENCB_free(pcb);
3691f13597dSJung-uk Kim if (ret)
3701f13597dSJung-uk Kim EVP_PKEY_assign_DH(pkey, dh);
3711f13597dSJung-uk Kim else
3721f13597dSJung-uk Kim DH_free(dh);
3731f13597dSJung-uk Kim return ret;
3741f13597dSJung-uk Kim }
3751f13597dSJung-uk Kim
pkey_dh_keygen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)3761f13597dSJung-uk Kim static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
3771f13597dSJung-uk Kim {
378e71b7053SJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
3791f13597dSJung-uk Kim DH *dh = NULL;
380e71b7053SJung-uk Kim
381*b077aed3SPierre Pronchery if (ctx->pkey == NULL && dctx->param_nid == NID_undef) {
382*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_DH, DH_R_NO_PARAMETERS_SET);
3831f13597dSJung-uk Kim return 0;
3841f13597dSJung-uk Kim }
385*b077aed3SPierre Pronchery if (dctx->param_nid != NID_undef)
386e71b7053SJung-uk Kim dh = DH_new_by_nid(dctx->param_nid);
387e71b7053SJung-uk Kim else
3881f13597dSJung-uk Kim dh = DH_new();
389e71b7053SJung-uk Kim if (dh == NULL)
3901f13597dSJung-uk Kim return 0;
3917bded2dbSJung-uk Kim EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
3921f13597dSJung-uk Kim /* Note: if error return, pkey is freed by parent routine */
393e71b7053SJung-uk Kim if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
3941f13597dSJung-uk Kim return 0;
395*b077aed3SPierre Pronchery return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey));
3961f13597dSJung-uk Kim }
3971f13597dSJung-uk Kim
pkey_dh_derive(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)3986f9291ceSJung-uk Kim static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
3996f9291ceSJung-uk Kim size_t *keylen)
4001f13597dSJung-uk Kim {
4011f13597dSJung-uk Kim int ret;
4027bded2dbSJung-uk Kim DH *dh;
403*b077aed3SPierre Pronchery const DH *dhpub;
4047bded2dbSJung-uk Kim DH_PKEY_CTX *dctx = ctx->data;
405*b077aed3SPierre Pronchery BIGNUM *dhpubbn;
406*b077aed3SPierre Pronchery
407*b077aed3SPierre Pronchery if (ctx->pkey == NULL || ctx->peerkey == NULL) {
408*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
4091f13597dSJung-uk Kim return 0;
4101f13597dSJung-uk Kim }
411*b077aed3SPierre Pronchery dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey);
412*b077aed3SPierre Pronchery dhpub = EVP_PKEY_get0_DH(ctx->peerkey);
413*b077aed3SPierre Pronchery if (dhpub == NULL) {
414*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET);
415*b077aed3SPierre Pronchery return 0;
416*b077aed3SPierre Pronchery }
417*b077aed3SPierre Pronchery dhpubbn = dhpub->pub_key;
4187bded2dbSJung-uk Kim if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
4197bded2dbSJung-uk Kim if (key == NULL) {
4207bded2dbSJung-uk Kim *keylen = DH_size(dh);
4217bded2dbSJung-uk Kim return 1;
4227bded2dbSJung-uk Kim }
423e71b7053SJung-uk Kim if (dctx->pad)
424*b077aed3SPierre Pronchery ret = DH_compute_key_padded(key, dhpubbn, dh);
425e71b7053SJung-uk Kim else
426*b077aed3SPierre Pronchery ret = DH_compute_key(key, dhpubbn, dh);
4271f13597dSJung-uk Kim if (ret < 0)
4281f13597dSJung-uk Kim return ret;
4291f13597dSJung-uk Kim *keylen = ret;
4301f13597dSJung-uk Kim return 1;
43147902a71SJung-uk Kim }
43247902a71SJung-uk Kim else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
433e71b7053SJung-uk Kim
4347bded2dbSJung-uk Kim unsigned char *Z = NULL;
435*b077aed3SPierre Pronchery int Zlen = 0;
436*b077aed3SPierre Pronchery
4377bded2dbSJung-uk Kim if (!dctx->kdf_outlen || !dctx->kdf_oid)
4387bded2dbSJung-uk Kim return 0;
4397bded2dbSJung-uk Kim if (key == NULL) {
4407bded2dbSJung-uk Kim *keylen = dctx->kdf_outlen;
4417bded2dbSJung-uk Kim return 1;
4427bded2dbSJung-uk Kim }
4437bded2dbSJung-uk Kim if (*keylen != dctx->kdf_outlen)
4447bded2dbSJung-uk Kim return 0;
4457bded2dbSJung-uk Kim ret = 0;
446*b077aed3SPierre Pronchery if ((Zlen = DH_size(dh)) <= 0)
447*b077aed3SPierre Pronchery return 0;
448*b077aed3SPierre Pronchery if ((Z = OPENSSL_malloc(Zlen)) == NULL) {
449*b077aed3SPierre Pronchery ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
450*b077aed3SPierre Pronchery return 0;
4517bded2dbSJung-uk Kim }
452*b077aed3SPierre Pronchery if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0)
4537bded2dbSJung-uk Kim goto err;
4547bded2dbSJung-uk Kim if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
4557bded2dbSJung-uk Kim dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
4567bded2dbSJung-uk Kim goto err;
4577bded2dbSJung-uk Kim *keylen = dctx->kdf_outlen;
4587bded2dbSJung-uk Kim ret = 1;
4597bded2dbSJung-uk Kim err:
460e71b7053SJung-uk Kim OPENSSL_clear_free(Z, Zlen);
4617bded2dbSJung-uk Kim return ret;
4627bded2dbSJung-uk Kim }
463dea77ea6SJung-uk Kim return 0;
4641f13597dSJung-uk Kim }
4651f13597dSJung-uk Kim
466*b077aed3SPierre Pronchery static const EVP_PKEY_METHOD dh_pkey_meth = {
4671f13597dSJung-uk Kim EVP_PKEY_DH,
4687bded2dbSJung-uk Kim 0,
4697bded2dbSJung-uk Kim pkey_dh_init,
4707bded2dbSJung-uk Kim pkey_dh_copy,
4717bded2dbSJung-uk Kim pkey_dh_cleanup,
4727bded2dbSJung-uk Kim
4737bded2dbSJung-uk Kim 0,
4747bded2dbSJung-uk Kim pkey_dh_paramgen,
4757bded2dbSJung-uk Kim
4767bded2dbSJung-uk Kim 0,
4777bded2dbSJung-uk Kim pkey_dh_keygen,
4787bded2dbSJung-uk Kim
4797bded2dbSJung-uk Kim 0,
4807bded2dbSJung-uk Kim 0,
4817bded2dbSJung-uk Kim
4827bded2dbSJung-uk Kim 0,
4837bded2dbSJung-uk Kim 0,
4847bded2dbSJung-uk Kim
4857bded2dbSJung-uk Kim 0, 0,
4867bded2dbSJung-uk Kim
4877bded2dbSJung-uk Kim 0, 0, 0, 0,
4887bded2dbSJung-uk Kim
4897bded2dbSJung-uk Kim 0, 0,
4907bded2dbSJung-uk Kim
4917bded2dbSJung-uk Kim 0, 0,
4927bded2dbSJung-uk Kim
4937bded2dbSJung-uk Kim 0,
4947bded2dbSJung-uk Kim pkey_dh_derive,
4957bded2dbSJung-uk Kim
4967bded2dbSJung-uk Kim pkey_dh_ctrl,
4977bded2dbSJung-uk Kim pkey_dh_ctrl_str
4987bded2dbSJung-uk Kim };
4997bded2dbSJung-uk Kim
ossl_dh_pkey_method(void)500*b077aed3SPierre Pronchery const EVP_PKEY_METHOD *ossl_dh_pkey_method(void)
501*b077aed3SPierre Pronchery {
502*b077aed3SPierre Pronchery return &dh_pkey_meth;
503*b077aed3SPierre Pronchery }
504*b077aed3SPierre Pronchery
505*b077aed3SPierre Pronchery static const EVP_PKEY_METHOD dhx_pkey_meth = {
5067bded2dbSJung-uk Kim EVP_PKEY_DHX,
5077bded2dbSJung-uk Kim 0,
5081f13597dSJung-uk Kim pkey_dh_init,
5091f13597dSJung-uk Kim pkey_dh_copy,
5101f13597dSJung-uk Kim pkey_dh_cleanup,
5111f13597dSJung-uk Kim
5121f13597dSJung-uk Kim 0,
5131f13597dSJung-uk Kim pkey_dh_paramgen,
5141f13597dSJung-uk Kim
5151f13597dSJung-uk Kim 0,
5161f13597dSJung-uk Kim pkey_dh_keygen,
5171f13597dSJung-uk Kim
5181f13597dSJung-uk Kim 0,
5191f13597dSJung-uk Kim 0,
5201f13597dSJung-uk Kim
5211f13597dSJung-uk Kim 0,
5221f13597dSJung-uk Kim 0,
5231f13597dSJung-uk Kim
5241f13597dSJung-uk Kim 0, 0,
5251f13597dSJung-uk Kim
5261f13597dSJung-uk Kim 0, 0, 0, 0,
5271f13597dSJung-uk Kim
5281f13597dSJung-uk Kim 0, 0,
5291f13597dSJung-uk Kim
5301f13597dSJung-uk Kim 0, 0,
5311f13597dSJung-uk Kim
5321f13597dSJung-uk Kim 0,
5331f13597dSJung-uk Kim pkey_dh_derive,
5341f13597dSJung-uk Kim
5351f13597dSJung-uk Kim pkey_dh_ctrl,
5361f13597dSJung-uk Kim pkey_dh_ctrl_str
5371f13597dSJung-uk Kim };
538*b077aed3SPierre Pronchery
ossl_dhx_pkey_method(void)539*b077aed3SPierre Pronchery const EVP_PKEY_METHOD *ossl_dhx_pkey_method(void)
540*b077aed3SPierre Pronchery {
541*b077aed3SPierre Pronchery return &dhx_pkey_meth;
542*b077aed3SPierre Pronchery }
543