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