1/* 2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include "internal/deprecated.h" 11 12#include <openssl/core_names.h> 13#include <openssl/params.h> 14#include <openssl/err.h> 15#include <openssl/dh.h> 16#include "crypto/dh.h" 17#include "crypto/evp.h" 18 19static int dh_paramgen_check(EVP_PKEY_CTX *ctx) 20{ 21 if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) { 22 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 23 /* Uses the same return values as EVP_PKEY_CTX_ctrl */ 24 return -2; 25 } 26 /* If key type not DH return error */ 27 if (evp_pkey_ctx_is_legacy(ctx) 28 && ctx->pmeth->pkey_id != EVP_PKEY_DH 29 && ctx->pmeth->pkey_id != EVP_PKEY_DHX) 30 return -1; 31 return 1; 32} 33 34static int dh_param_derive_check(EVP_PKEY_CTX *ctx) 35{ 36 if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { 37 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 38 /* Uses the same return values as EVP_PKEY_CTX_ctrl */ 39 return -2; 40 } 41 /* If key type not DH return error */ 42 if (evp_pkey_ctx_is_legacy(ctx) 43 && ctx->pmeth->pkey_id != EVP_PKEY_DH 44 && ctx->pmeth->pkey_id != EVP_PKEY_DHX) 45 return -1; 46 return 1; 47} 48 49int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX *ctx, int gindex) 50{ 51 int ret; 52 OSSL_PARAM params[2], *p = params; 53 54 if ((ret = dh_paramgen_check(ctx)) <= 0) 55 return ret; 56 57 *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX, &gindex); 58 *p = OSSL_PARAM_construct_end(); 59 60 return evp_pkey_ctx_set_params_strict(ctx, params); 61} 62 63int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX *ctx, 64 const unsigned char *seed, 65 size_t seedlen) 66{ 67 int ret; 68 OSSL_PARAM params[2], *p = params; 69 70 if ((ret = dh_paramgen_check(ctx)) <= 0) 71 return ret; 72 73 *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED, 74 (void *)seed, seedlen); 75 *p = OSSL_PARAM_construct_end(); 76 77 return evp_pkey_ctx_set_params_strict(ctx, params); 78} 79 80/* 81 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 82 * simply because that's easier. 83 */ 84int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX *ctx, int typ) 85{ 86 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, 87 EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, typ, NULL); 88} 89 90int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX *ctx, int pbits) 91{ 92 int ret; 93 OSSL_PARAM params[2], *p = params; 94 size_t bits = pbits; 95 96 if ((ret = dh_paramgen_check(ctx)) <= 0) 97 return ret; 98 99 *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &bits); 100 *p = OSSL_PARAM_construct_end(); 101 return evp_pkey_ctx_set_params_strict(ctx, params); 102} 103 104int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX *ctx, int qbits) 105{ 106 int ret; 107 OSSL_PARAM params[2], *p = params; 108 size_t bits2 = qbits; 109 110 if ((ret = dh_paramgen_check(ctx)) <= 0) 111 return ret; 112 113 *p++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS, &bits2); 114 *p = OSSL_PARAM_construct_end(); 115 116 return evp_pkey_ctx_set_params_strict(ctx, params); 117} 118 119int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX *ctx, int gen) 120{ 121 int ret; 122 OSSL_PARAM params[2], *p = params; 123 124 if ((ret = dh_paramgen_check(ctx)) <= 0) 125 return ret; 126 127 *p++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_DH_GENERATOR, &gen); 128 *p = OSSL_PARAM_construct_end(); 129 130 return evp_pkey_ctx_set_params_strict(ctx, params); 131} 132 133/* 134 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 135 * simply because that's easier. 136 */ 137int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX *ctx, int gen) 138{ 139 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_PARAMGEN, 140 EVP_PKEY_CTRL_DH_RFC5114, gen, NULL); 141} 142 143int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX *ctx, int gen) 144{ 145 return EVP_PKEY_CTX_set_dh_rfc5114(ctx, gen); 146} 147 148/* 149 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 150 * simply because that's easier. 151 */ 152int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX *ctx, int nid) 153{ 154 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, 155 EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN, 156 EVP_PKEY_CTRL_DH_NID, nid, NULL); 157} 158 159int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad) 160{ 161 OSSL_PARAM dh_pad_params[2]; 162 unsigned int upad = pad; 163 164 /* We use EVP_PKEY_CTX_ctrl return values */ 165 if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) { 166 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 167 return -2; 168 } 169 170 dh_pad_params[0] = OSSL_PARAM_construct_uint(OSSL_EXCHANGE_PARAM_PAD, &upad); 171 dh_pad_params[1] = OSSL_PARAM_construct_end(); 172 173 return evp_pkey_ctx_set_params_strict(ctx, dh_pad_params); 174} 175 176/* 177 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 178 * simply because that's easier. 179 */ 180int EVP_PKEY_CTX_set_dh_kdf_type(EVP_PKEY_CTX *ctx, int kdf) 181{ 182 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, 183 EVP_PKEY_CTRL_DH_KDF_TYPE, kdf, NULL); 184} 185 186/* 187 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 188 * simply because that's easier. 189 */ 190int EVP_PKEY_CTX_get_dh_kdf_type(EVP_PKEY_CTX *ctx) 191{ 192 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, 193 EVP_PKEY_CTRL_DH_KDF_TYPE, -2, NULL); 194} 195 196/* 197 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 198 * simply because that's easier. 199 */ 200int EVP_PKEY_CTX_set0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT *oid) 201{ 202 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, 203 EVP_PKEY_CTRL_DH_KDF_OID, 0, (void *)(oid)); 204} 205 206/* 207 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 208 * simply because that's easier. 209 */ 210int EVP_PKEY_CTX_get0_dh_kdf_oid(EVP_PKEY_CTX *ctx, ASN1_OBJECT **oid) 211{ 212 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, 213 EVP_PKEY_CTRL_GET_DH_KDF_OID, 0, (void *)(oid)); 214} 215 216/* 217 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 218 * simply because that's easier. 219 */ 220int EVP_PKEY_CTX_set_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) 221{ 222 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, 223 EVP_PKEY_CTRL_DH_KDF_MD, 0, (void *)(md)); 224} 225 226/* 227 * This one is currently implemented as an EVP_PKEY_CTX_ctrl() wrapper, 228 * simply because that's easier. 229 */ 230int EVP_PKEY_CTX_get_dh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd) 231{ 232 return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, 233 EVP_PKEY_CTRL_GET_DH_KDF_MD, 0, (void *)(pmd)); 234} 235 236int EVP_PKEY_CTX_set_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int outlen) 237{ 238 int ret; 239 size_t len = outlen; 240 OSSL_PARAM params[2], *p = params; 241 242 ret = dh_param_derive_check(ctx); 243 if (ret != 1) 244 return ret; 245 246 if (outlen <= 0) { 247 /* 248 * This would ideally be -1 or 0, but we have to retain compatibility 249 * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if 250 * inlen <= 0 251 */ 252 return -2; 253 } 254 255 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, 256 &len); 257 *p = OSSL_PARAM_construct_end(); 258 259 ret = evp_pkey_ctx_set_params_strict(ctx, params); 260 if (ret == -2) 261 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 262 return ret; 263} 264 265int EVP_PKEY_CTX_get_dh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen) 266{ 267 int ret; 268 size_t len = UINT_MAX; 269 OSSL_PARAM params[2], *p = params; 270 271 ret = dh_param_derive_check(ctx); 272 if (ret != 1) 273 return ret; 274 275 *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, 276 &len); 277 *p = OSSL_PARAM_construct_end(); 278 279 ret = evp_pkey_ctx_get_params_strict(ctx, params); 280 if (ret == -2) 281 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 282 if (ret != 1 || len > INT_MAX) 283 return -1; 284 285 *plen = (int)len; 286 287 return 1; 288} 289 290int EVP_PKEY_CTX_set0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len) 291{ 292 int ret; 293 OSSL_PARAM params[2], *p = params; 294 295 if (len < 0) 296 return -1; 297 298 ret = dh_param_derive_check(ctx); 299 if (ret != 1) 300 return ret; 301 302 *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, 303 /* 304 * Cast away the const. This is read 305 * only so should be safe 306 */ 307 (void *)ukm, 308 (size_t)len); 309 *p = OSSL_PARAM_construct_end(); 310 311 ret = evp_pkey_ctx_set_params_strict(ctx, params); 312 if (ret == -2) 313 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 314 if (ret == 1) 315 OPENSSL_free(ukm); 316 return ret; 317} 318 319#ifndef OPENSSL_NO_DEPRECATED_3_0 320int EVP_PKEY_CTX_get0_dh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm) 321{ 322 int ret; 323 size_t ukmlen; 324 OSSL_PARAM params[2], *p = params; 325 326 ret = dh_param_derive_check(ctx); 327 if (ret != 1) 328 return ret; 329 330 *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM, 331 (void **)pukm, 0); 332 *p = OSSL_PARAM_construct_end(); 333 334 ret = evp_pkey_ctx_get_params_strict(ctx, params); 335 if (ret == -2) 336 ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED); 337 if (ret != 1) 338 return -1; 339 340 ukmlen = params[0].return_size; 341 if (ukmlen > INT_MAX) 342 return -1; 343 344 return (int)ukmlen; 345} 346#endif 347