11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* 111cb0ef41Sopenharmony_ci * DH & DSA low level APIs are deprecated for public use, but still ok for 121cb0ef41Sopenharmony_ci * internal use. 131cb0ef41Sopenharmony_ci */ 141cb0ef41Sopenharmony_ci#include "internal/deprecated.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#include <stdio.h> 171cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 181cb0ef41Sopenharmony_ci#include <openssl/asn1t.h> 191cb0ef41Sopenharmony_ci#include <openssl/x509.h> 201cb0ef41Sopenharmony_ci#include <openssl/evp.h> 211cb0ef41Sopenharmony_ci#include "dh_local.h" 221cb0ef41Sopenharmony_ci#include <openssl/bn.h> 231cb0ef41Sopenharmony_ci#include <openssl/dsa.h> 241cb0ef41Sopenharmony_ci#include <openssl/objects.h> 251cb0ef41Sopenharmony_ci#include "crypto/evp.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ci/* DH pkey context structure */ 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_citypedef struct { 301cb0ef41Sopenharmony_ci /* Parameter gen parameters */ 311cb0ef41Sopenharmony_ci int prime_len; 321cb0ef41Sopenharmony_ci int generator; 331cb0ef41Sopenharmony_ci int paramgen_type; 341cb0ef41Sopenharmony_ci int subprime_len; 351cb0ef41Sopenharmony_ci int pad; 361cb0ef41Sopenharmony_ci /* message digest used for parameter generation */ 371cb0ef41Sopenharmony_ci const EVP_MD *md; 381cb0ef41Sopenharmony_ci int param_nid; 391cb0ef41Sopenharmony_ci /* Keygen callback info */ 401cb0ef41Sopenharmony_ci int gentmp[2]; 411cb0ef41Sopenharmony_ci /* KDF (if any) to use for DH */ 421cb0ef41Sopenharmony_ci char kdf_type; 431cb0ef41Sopenharmony_ci /* OID to use for KDF */ 441cb0ef41Sopenharmony_ci ASN1_OBJECT *kdf_oid; 451cb0ef41Sopenharmony_ci /* Message digest to use for key derivation */ 461cb0ef41Sopenharmony_ci const EVP_MD *kdf_md; 471cb0ef41Sopenharmony_ci /* User key material */ 481cb0ef41Sopenharmony_ci unsigned char *kdf_ukm; 491cb0ef41Sopenharmony_ci size_t kdf_ukmlen; 501cb0ef41Sopenharmony_ci /* KDF output length */ 511cb0ef41Sopenharmony_ci size_t kdf_outlen; 521cb0ef41Sopenharmony_ci} DH_PKEY_CTX; 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cistatic int pkey_dh_init(EVP_PKEY_CTX *ctx) 551cb0ef41Sopenharmony_ci{ 561cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { 591cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); 601cb0ef41Sopenharmony_ci return 0; 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci dctx->prime_len = 2048; 631cb0ef41Sopenharmony_ci dctx->subprime_len = -1; 641cb0ef41Sopenharmony_ci dctx->generator = 2; 651cb0ef41Sopenharmony_ci dctx->kdf_type = EVP_PKEY_DH_KDF_NONE; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci ctx->data = dctx; 681cb0ef41Sopenharmony_ci ctx->keygen_info = dctx->gentmp; 691cb0ef41Sopenharmony_ci ctx->keygen_info_count = 2; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci return 1; 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_cistatic void pkey_dh_cleanup(EVP_PKEY_CTX *ctx) 751cb0ef41Sopenharmony_ci{ 761cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci if (dctx != NULL) { 791cb0ef41Sopenharmony_ci OPENSSL_free(dctx->kdf_ukm); 801cb0ef41Sopenharmony_ci ASN1_OBJECT_free(dctx->kdf_oid); 811cb0ef41Sopenharmony_ci OPENSSL_free(dctx); 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci} 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cistatic int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) 871cb0ef41Sopenharmony_ci{ 881cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx, *sctx; 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci if (!pkey_dh_init(dst)) 911cb0ef41Sopenharmony_ci return 0; 921cb0ef41Sopenharmony_ci sctx = src->data; 931cb0ef41Sopenharmony_ci dctx = dst->data; 941cb0ef41Sopenharmony_ci dctx->prime_len = sctx->prime_len; 951cb0ef41Sopenharmony_ci dctx->subprime_len = sctx->subprime_len; 961cb0ef41Sopenharmony_ci dctx->generator = sctx->generator; 971cb0ef41Sopenharmony_ci dctx->paramgen_type = sctx->paramgen_type; 981cb0ef41Sopenharmony_ci dctx->pad = sctx->pad; 991cb0ef41Sopenharmony_ci dctx->md = sctx->md; 1001cb0ef41Sopenharmony_ci dctx->param_nid = sctx->param_nid; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci dctx->kdf_type = sctx->kdf_type; 1031cb0ef41Sopenharmony_ci dctx->kdf_oid = OBJ_dup(sctx->kdf_oid); 1041cb0ef41Sopenharmony_ci if (dctx->kdf_oid == NULL) 1051cb0ef41Sopenharmony_ci return 0; 1061cb0ef41Sopenharmony_ci dctx->kdf_md = sctx->kdf_md; 1071cb0ef41Sopenharmony_ci if (sctx->kdf_ukm != NULL) { 1081cb0ef41Sopenharmony_ci dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); 1091cb0ef41Sopenharmony_ci if (dctx->kdf_ukm == NULL) 1101cb0ef41Sopenharmony_ci return 0; 1111cb0ef41Sopenharmony_ci dctx->kdf_ukmlen = sctx->kdf_ukmlen; 1121cb0ef41Sopenharmony_ci } 1131cb0ef41Sopenharmony_ci dctx->kdf_outlen = sctx->kdf_outlen; 1141cb0ef41Sopenharmony_ci return 1; 1151cb0ef41Sopenharmony_ci} 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_cistatic int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 1181cb0ef41Sopenharmony_ci{ 1191cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 1201cb0ef41Sopenharmony_ci switch (type) { 1211cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN: 1221cb0ef41Sopenharmony_ci if (p1 < 256) 1231cb0ef41Sopenharmony_ci return -2; 1241cb0ef41Sopenharmony_ci dctx->prime_len = p1; 1251cb0ef41Sopenharmony_ci return 1; 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN: 1281cb0ef41Sopenharmony_ci if (dctx->paramgen_type == DH_PARAMGEN_TYPE_GENERATOR) 1291cb0ef41Sopenharmony_ci return -2; 1301cb0ef41Sopenharmony_ci dctx->subprime_len = p1; 1311cb0ef41Sopenharmony_ci return 1; 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_PAD: 1341cb0ef41Sopenharmony_ci dctx->pad = p1; 1351cb0ef41Sopenharmony_ci return 1; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR: 1381cb0ef41Sopenharmony_ci if (dctx->paramgen_type != DH_PARAMGEN_TYPE_GENERATOR) 1391cb0ef41Sopenharmony_ci return -2; 1401cb0ef41Sopenharmony_ci dctx->generator = p1; 1411cb0ef41Sopenharmony_ci return 1; 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE: 1441cb0ef41Sopenharmony_ci#ifdef OPENSSL_NO_DSA 1451cb0ef41Sopenharmony_ci if (p1 != DH_PARAMGEN_TYPE_GENERATOR) 1461cb0ef41Sopenharmony_ci return -2; 1471cb0ef41Sopenharmony_ci#else 1481cb0ef41Sopenharmony_ci if (p1 < 0 || p1 > 2) 1491cb0ef41Sopenharmony_ci return -2; 1501cb0ef41Sopenharmony_ci#endif 1511cb0ef41Sopenharmony_ci dctx->paramgen_type = p1; 1521cb0ef41Sopenharmony_ci return 1; 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_RFC5114: 1551cb0ef41Sopenharmony_ci if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef) 1561cb0ef41Sopenharmony_ci return -2; 1571cb0ef41Sopenharmony_ci dctx->param_nid = p1; 1581cb0ef41Sopenharmony_ci return 1; 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_NID: 1611cb0ef41Sopenharmony_ci if (p1 <= 0 || dctx->param_nid != NID_undef) 1621cb0ef41Sopenharmony_ci return -2; 1631cb0ef41Sopenharmony_ci dctx->param_nid = p1; 1641cb0ef41Sopenharmony_ci return 1; 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_PEER_KEY: 1671cb0ef41Sopenharmony_ci /* Default behaviour is OK */ 1681cb0ef41Sopenharmony_ci return 1; 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_KDF_TYPE: 1711cb0ef41Sopenharmony_ci if (p1 == -2) 1721cb0ef41Sopenharmony_ci return dctx->kdf_type; 1731cb0ef41Sopenharmony_ci if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42) 1741cb0ef41Sopenharmony_ci return -2; 1751cb0ef41Sopenharmony_ci dctx->kdf_type = p1; 1761cb0ef41Sopenharmony_ci return 1; 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_KDF_MD: 1791cb0ef41Sopenharmony_ci dctx->kdf_md = p2; 1801cb0ef41Sopenharmony_ci return 1; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_GET_DH_KDF_MD: 1831cb0ef41Sopenharmony_ci *(const EVP_MD **)p2 = dctx->kdf_md; 1841cb0ef41Sopenharmony_ci return 1; 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_KDF_OUTLEN: 1871cb0ef41Sopenharmony_ci if (p1 <= 0) 1881cb0ef41Sopenharmony_ci return -2; 1891cb0ef41Sopenharmony_ci dctx->kdf_outlen = (size_t)p1; 1901cb0ef41Sopenharmony_ci return 1; 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN: 1931cb0ef41Sopenharmony_ci *(int *)p2 = dctx->kdf_outlen; 1941cb0ef41Sopenharmony_ci return 1; 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_KDF_UKM: 1971cb0ef41Sopenharmony_ci OPENSSL_free(dctx->kdf_ukm); 1981cb0ef41Sopenharmony_ci dctx->kdf_ukm = p2; 1991cb0ef41Sopenharmony_ci if (p2) 2001cb0ef41Sopenharmony_ci dctx->kdf_ukmlen = p1; 2011cb0ef41Sopenharmony_ci else 2021cb0ef41Sopenharmony_ci dctx->kdf_ukmlen = 0; 2031cb0ef41Sopenharmony_ci return 1; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_GET_DH_KDF_UKM: 2061cb0ef41Sopenharmony_ci *(unsigned char **)p2 = dctx->kdf_ukm; 2071cb0ef41Sopenharmony_ci return dctx->kdf_ukmlen; 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_DH_KDF_OID: 2101cb0ef41Sopenharmony_ci ASN1_OBJECT_free(dctx->kdf_oid); 2111cb0ef41Sopenharmony_ci dctx->kdf_oid = p2; 2121cb0ef41Sopenharmony_ci return 1; 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci case EVP_PKEY_CTRL_GET_DH_KDF_OID: 2151cb0ef41Sopenharmony_ci *(ASN1_OBJECT **)p2 = dctx->kdf_oid; 2161cb0ef41Sopenharmony_ci return 1; 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci default: 2191cb0ef41Sopenharmony_ci return -2; 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_cistatic int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, 2251cb0ef41Sopenharmony_ci const char *type, const char *value) 2261cb0ef41Sopenharmony_ci{ 2271cb0ef41Sopenharmony_ci if (strcmp(type, "dh_paramgen_prime_len") == 0) { 2281cb0ef41Sopenharmony_ci int len; 2291cb0ef41Sopenharmony_ci len = atoi(value); 2301cb0ef41Sopenharmony_ci return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len); 2311cb0ef41Sopenharmony_ci } 2321cb0ef41Sopenharmony_ci if (strcmp(type, "dh_rfc5114") == 0) { 2331cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 2341cb0ef41Sopenharmony_ci int id; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci id = atoi(value); 2371cb0ef41Sopenharmony_ci if (id < 0 || id > 3) 2381cb0ef41Sopenharmony_ci return -2; 2391cb0ef41Sopenharmony_ci dctx->param_nid = id; 2401cb0ef41Sopenharmony_ci return 1; 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci if (strcmp(type, "dh_param") == 0) { 2431cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 2441cb0ef41Sopenharmony_ci int nid = OBJ_sn2nid(value); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci if (nid == NID_undef) { 2471cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME); 2481cb0ef41Sopenharmony_ci return -2; 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci dctx->param_nid = nid; 2511cb0ef41Sopenharmony_ci return 1; 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci if (strcmp(type, "dh_paramgen_generator") == 0) { 2541cb0ef41Sopenharmony_ci int len; 2551cb0ef41Sopenharmony_ci len = atoi(value); 2561cb0ef41Sopenharmony_ci return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len); 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci if (strcmp(type, "dh_paramgen_subprime_len") == 0) { 2591cb0ef41Sopenharmony_ci int len; 2601cb0ef41Sopenharmony_ci len = atoi(value); 2611cb0ef41Sopenharmony_ci return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len); 2621cb0ef41Sopenharmony_ci } 2631cb0ef41Sopenharmony_ci if (strcmp(type, "dh_paramgen_type") == 0) { 2641cb0ef41Sopenharmony_ci int typ; 2651cb0ef41Sopenharmony_ci typ = atoi(value); 2661cb0ef41Sopenharmony_ci return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci if (strcmp(type, "dh_pad") == 0) { 2691cb0ef41Sopenharmony_ci int pad; 2701cb0ef41Sopenharmony_ci pad = atoi(value); 2711cb0ef41Sopenharmony_ci return EVP_PKEY_CTX_set_dh_pad(ctx, pad); 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci return -2; 2741cb0ef41Sopenharmony_ci} 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_cistatic DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx, 2771cb0ef41Sopenharmony_ci BN_GENCB *pcb) 2781cb0ef41Sopenharmony_ci{ 2791cb0ef41Sopenharmony_ci DH *ret; 2801cb0ef41Sopenharmony_ci int rv = 0; 2811cb0ef41Sopenharmony_ci int res; 2821cb0ef41Sopenharmony_ci int prime_len = dctx->prime_len; 2831cb0ef41Sopenharmony_ci int subprime_len = dctx->subprime_len; 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4) 2861cb0ef41Sopenharmony_ci return NULL; 2871cb0ef41Sopenharmony_ci ret = DH_new(); 2881cb0ef41Sopenharmony_ci if (ret == NULL) 2891cb0ef41Sopenharmony_ci return NULL; 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci if (subprime_len == -1) { 2921cb0ef41Sopenharmony_ci if (prime_len >= 2048) 2931cb0ef41Sopenharmony_ci subprime_len = 256; 2941cb0ef41Sopenharmony_ci else 2951cb0ef41Sopenharmony_ci subprime_len = 160; 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci if (dctx->md != NULL) 2991cb0ef41Sopenharmony_ci ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci# ifndef FIPS_MODULE 3021cb0ef41Sopenharmony_ci if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2) 3031cb0ef41Sopenharmony_ci rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params, 3041cb0ef41Sopenharmony_ci FFC_PARAM_TYPE_DH, 3051cb0ef41Sopenharmony_ci prime_len, subprime_len, &res, 3061cb0ef41Sopenharmony_ci pcb); 3071cb0ef41Sopenharmony_ci else 3081cb0ef41Sopenharmony_ci# endif 3091cb0ef41Sopenharmony_ci /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */ 3101cb0ef41Sopenharmony_ci if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) 3111cb0ef41Sopenharmony_ci rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params, 3121cb0ef41Sopenharmony_ci FFC_PARAM_TYPE_DH, 3131cb0ef41Sopenharmony_ci prime_len, subprime_len, &res, 3141cb0ef41Sopenharmony_ci pcb); 3151cb0ef41Sopenharmony_ci if (rv <= 0) { 3161cb0ef41Sopenharmony_ci DH_free(ret); 3171cb0ef41Sopenharmony_ci return NULL; 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci return ret; 3201cb0ef41Sopenharmony_ci} 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_cistatic int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, 3231cb0ef41Sopenharmony_ci EVP_PKEY *pkey) 3241cb0ef41Sopenharmony_ci{ 3251cb0ef41Sopenharmony_ci DH *dh = NULL; 3261cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 3271cb0ef41Sopenharmony_ci BN_GENCB *pcb = NULL; 3281cb0ef41Sopenharmony_ci int ret; 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci /* 3311cb0ef41Sopenharmony_ci * Look for a safe prime group for key establishment. Which uses 3321cb0ef41Sopenharmony_ci * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX). 3331cb0ef41Sopenharmony_ci * RFC_5114 is also handled here for param_nid = (1..3) 3341cb0ef41Sopenharmony_ci */ 3351cb0ef41Sopenharmony_ci if (dctx->param_nid != NID_undef) { 3361cb0ef41Sopenharmony_ci int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH; 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL) 3391cb0ef41Sopenharmony_ci return 0; 3401cb0ef41Sopenharmony_ci EVP_PKEY_assign(pkey, type, dh); 3411cb0ef41Sopenharmony_ci return 1; 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci if (ctx->pkey_gencb != NULL) { 3451cb0ef41Sopenharmony_ci pcb = BN_GENCB_new(); 3461cb0ef41Sopenharmony_ci if (pcb == NULL) 3471cb0ef41Sopenharmony_ci return 0; 3481cb0ef41Sopenharmony_ci evp_pkey_set_cb_translate(pcb, ctx); 3491cb0ef41Sopenharmony_ci } 3501cb0ef41Sopenharmony_ci# ifdef FIPS_MODULE 3511cb0ef41Sopenharmony_ci dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4; 3521cb0ef41Sopenharmony_ci# endif /* FIPS_MODULE */ 3531cb0ef41Sopenharmony_ci if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) { 3541cb0ef41Sopenharmony_ci dh = ffc_params_generate(NULL, dctx, pcb); 3551cb0ef41Sopenharmony_ci BN_GENCB_free(pcb); 3561cb0ef41Sopenharmony_ci if (dh == NULL) 3571cb0ef41Sopenharmony_ci return 0; 3581cb0ef41Sopenharmony_ci EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); 3591cb0ef41Sopenharmony_ci return 1; 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci dh = DH_new(); 3621cb0ef41Sopenharmony_ci if (dh == NULL) { 3631cb0ef41Sopenharmony_ci BN_GENCB_free(pcb); 3641cb0ef41Sopenharmony_ci return 0; 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci ret = DH_generate_parameters_ex(dh, 3671cb0ef41Sopenharmony_ci dctx->prime_len, dctx->generator, pcb); 3681cb0ef41Sopenharmony_ci BN_GENCB_free(pcb); 3691cb0ef41Sopenharmony_ci if (ret) 3701cb0ef41Sopenharmony_ci EVP_PKEY_assign_DH(pkey, dh); 3711cb0ef41Sopenharmony_ci else 3721cb0ef41Sopenharmony_ci DH_free(dh); 3731cb0ef41Sopenharmony_ci return ret; 3741cb0ef41Sopenharmony_ci} 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_cistatic int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 3771cb0ef41Sopenharmony_ci{ 3781cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 3791cb0ef41Sopenharmony_ci DH *dh = NULL; 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci if (ctx->pkey == NULL && dctx->param_nid == NID_undef) { 3821cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_NO_PARAMETERS_SET); 3831cb0ef41Sopenharmony_ci return 0; 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci if (dctx->param_nid != NID_undef) 3861cb0ef41Sopenharmony_ci dh = DH_new_by_nid(dctx->param_nid); 3871cb0ef41Sopenharmony_ci else 3881cb0ef41Sopenharmony_ci dh = DH_new(); 3891cb0ef41Sopenharmony_ci if (dh == NULL) 3901cb0ef41Sopenharmony_ci return 0; 3911cb0ef41Sopenharmony_ci EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh); 3921cb0ef41Sopenharmony_ci /* Note: if error return, pkey is freed by parent routine */ 3931cb0ef41Sopenharmony_ci if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 3941cb0ef41Sopenharmony_ci return 0; 3951cb0ef41Sopenharmony_ci return DH_generate_key((DH *)EVP_PKEY_get0_DH(pkey)); 3961cb0ef41Sopenharmony_ci} 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_cistatic int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, 3991cb0ef41Sopenharmony_ci size_t *keylen) 4001cb0ef41Sopenharmony_ci{ 4011cb0ef41Sopenharmony_ci int ret; 4021cb0ef41Sopenharmony_ci DH *dh; 4031cb0ef41Sopenharmony_ci const DH *dhpub; 4041cb0ef41Sopenharmony_ci DH_PKEY_CTX *dctx = ctx->data; 4051cb0ef41Sopenharmony_ci BIGNUM *dhpubbn; 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci if (ctx->pkey == NULL || ctx->peerkey == NULL) { 4081cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET); 4091cb0ef41Sopenharmony_ci return 0; 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci dh = (DH *)EVP_PKEY_get0_DH(ctx->pkey); 4121cb0ef41Sopenharmony_ci dhpub = EVP_PKEY_get0_DH(ctx->peerkey); 4131cb0ef41Sopenharmony_ci if (dhpub == NULL) { 4141cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_KEYS_NOT_SET); 4151cb0ef41Sopenharmony_ci return 0; 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci dhpubbn = dhpub->pub_key; 4181cb0ef41Sopenharmony_ci if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) { 4191cb0ef41Sopenharmony_ci if (key == NULL) { 4201cb0ef41Sopenharmony_ci *keylen = DH_size(dh); 4211cb0ef41Sopenharmony_ci return 1; 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci if (dctx->pad) 4241cb0ef41Sopenharmony_ci ret = DH_compute_key_padded(key, dhpubbn, dh); 4251cb0ef41Sopenharmony_ci else 4261cb0ef41Sopenharmony_ci ret = DH_compute_key(key, dhpubbn, dh); 4271cb0ef41Sopenharmony_ci if (ret < 0) 4281cb0ef41Sopenharmony_ci return ret; 4291cb0ef41Sopenharmony_ci *keylen = ret; 4301cb0ef41Sopenharmony_ci return 1; 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) { 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci unsigned char *Z = NULL; 4351cb0ef41Sopenharmony_ci int Zlen = 0; 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci if (!dctx->kdf_outlen || !dctx->kdf_oid) 4381cb0ef41Sopenharmony_ci return 0; 4391cb0ef41Sopenharmony_ci if (key == NULL) { 4401cb0ef41Sopenharmony_ci *keylen = dctx->kdf_outlen; 4411cb0ef41Sopenharmony_ci return 1; 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci if (*keylen != dctx->kdf_outlen) 4441cb0ef41Sopenharmony_ci return 0; 4451cb0ef41Sopenharmony_ci ret = 0; 4461cb0ef41Sopenharmony_ci if ((Zlen = DH_size(dh)) <= 0) 4471cb0ef41Sopenharmony_ci return 0; 4481cb0ef41Sopenharmony_ci if ((Z = OPENSSL_malloc(Zlen)) == NULL) { 4491cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); 4501cb0ef41Sopenharmony_ci return 0; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0) 4531cb0ef41Sopenharmony_ci goto err; 4541cb0ef41Sopenharmony_ci if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid, 4551cb0ef41Sopenharmony_ci dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md)) 4561cb0ef41Sopenharmony_ci goto err; 4571cb0ef41Sopenharmony_ci *keylen = dctx->kdf_outlen; 4581cb0ef41Sopenharmony_ci ret = 1; 4591cb0ef41Sopenharmony_ci err: 4601cb0ef41Sopenharmony_ci OPENSSL_clear_free(Z, Zlen); 4611cb0ef41Sopenharmony_ci return ret; 4621cb0ef41Sopenharmony_ci } 4631cb0ef41Sopenharmony_ci return 0; 4641cb0ef41Sopenharmony_ci} 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_cistatic const EVP_PKEY_METHOD dh_pkey_meth = { 4671cb0ef41Sopenharmony_ci EVP_PKEY_DH, 4681cb0ef41Sopenharmony_ci 0, 4691cb0ef41Sopenharmony_ci pkey_dh_init, 4701cb0ef41Sopenharmony_ci pkey_dh_copy, 4711cb0ef41Sopenharmony_ci pkey_dh_cleanup, 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci 0, 4741cb0ef41Sopenharmony_ci pkey_dh_paramgen, 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci 0, 4771cb0ef41Sopenharmony_ci pkey_dh_keygen, 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci 0, 4801cb0ef41Sopenharmony_ci 0, 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci 0, 4831cb0ef41Sopenharmony_ci 0, 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci 0, 0, 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci 0, 0, 0, 0, 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci 0, 0, 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci 0, 0, 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci 0, 4941cb0ef41Sopenharmony_ci pkey_dh_derive, 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ci pkey_dh_ctrl, 4971cb0ef41Sopenharmony_ci pkey_dh_ctrl_str 4981cb0ef41Sopenharmony_ci}; 4991cb0ef41Sopenharmony_ci 5001cb0ef41Sopenharmony_ciconst EVP_PKEY_METHOD *ossl_dh_pkey_method(void) 5011cb0ef41Sopenharmony_ci{ 5021cb0ef41Sopenharmony_ci return &dh_pkey_meth; 5031cb0ef41Sopenharmony_ci} 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_cistatic const EVP_PKEY_METHOD dhx_pkey_meth = { 5061cb0ef41Sopenharmony_ci EVP_PKEY_DHX, 5071cb0ef41Sopenharmony_ci 0, 5081cb0ef41Sopenharmony_ci pkey_dh_init, 5091cb0ef41Sopenharmony_ci pkey_dh_copy, 5101cb0ef41Sopenharmony_ci pkey_dh_cleanup, 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci 0, 5131cb0ef41Sopenharmony_ci pkey_dh_paramgen, 5141cb0ef41Sopenharmony_ci 5151cb0ef41Sopenharmony_ci 0, 5161cb0ef41Sopenharmony_ci pkey_dh_keygen, 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci 0, 5191cb0ef41Sopenharmony_ci 0, 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci 0, 5221cb0ef41Sopenharmony_ci 0, 5231cb0ef41Sopenharmony_ci 5241cb0ef41Sopenharmony_ci 0, 0, 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ci 0, 0, 0, 0, 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci 0, 0, 5291cb0ef41Sopenharmony_ci 5301cb0ef41Sopenharmony_ci 0, 0, 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ci 0, 5331cb0ef41Sopenharmony_ci pkey_dh_derive, 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci pkey_dh_ctrl, 5361cb0ef41Sopenharmony_ci pkey_dh_ctrl_str 5371cb0ef41Sopenharmony_ci}; 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ciconst EVP_PKEY_METHOD *ossl_dhx_pkey_method(void) 5401cb0ef41Sopenharmony_ci{ 5411cb0ef41Sopenharmony_ci return &dhx_pkey_meth; 5421cb0ef41Sopenharmony_ci} 543