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