1 /* 2 * Copyright 2019-2022 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 /* 11 * DH low level APIs are deprecated for public use, but still ok for 12 * internal use. 13 */ 14 #include "internal/deprecated.h" 15 16 #include <string.h> 17 #include <openssl/crypto.h> 18 #include <openssl/core_dispatch.h> 19 #include <openssl/core_names.h> 20 #include <openssl/dh.h> 21 #include <openssl/err.h> 22 #include <openssl/proverr.h> 23 #include <openssl/params.h> 24 #include "prov/providercommon.h" 25 #include "prov/implementations.h" 26 #include "prov/provider_ctx.h" 27 #include "prov/securitycheck.h" 28 #include "crypto/dh.h" 29 30 static OSSL_FUNC_keyexch_newctx_fn dh_newctx; 31 static OSSL_FUNC_keyexch_init_fn dh_init; 32 static OSSL_FUNC_keyexch_set_peer_fn dh_set_peer; 33 static OSSL_FUNC_keyexch_derive_fn dh_derive; 34 static OSSL_FUNC_keyexch_freectx_fn dh_freectx; 35 static OSSL_FUNC_keyexch_dupctx_fn dh_dupctx; 36 static OSSL_FUNC_keyexch_set_ctx_params_fn dh_set_ctx_params; 37 static OSSL_FUNC_keyexch_settable_ctx_params_fn dh_settable_ctx_params; 38 static OSSL_FUNC_keyexch_get_ctx_params_fn dh_get_ctx_params; 39 static OSSL_FUNC_keyexch_gettable_ctx_params_fn dh_gettable_ctx_params; 40 41 /* 42 * This type is only really used to handle some legacy related functionality. 43 * If you need to use other KDF's (such as SSKDF) just use PROV_DH_KDF_NONE 44 * here and then create and run a KDF after the key is derived. 45 * Note that X942 has 2 variants of key derivation: 46 * (1) DH_KDF_X9_42_ASN1 - which contains an ANS1 encoded object that has 47 * the counter embedded in it. 48 * (2) DH_KDF_X941_CONCAT - which is the same as ECDH_X963_KDF (which can be 49 * done by creating a "X963KDF". 50 */ 51 enum kdf_type { 52 PROV_DH_KDF_NONE = 0, 53 PROV_DH_KDF_X9_42_ASN1 54 }; 55 56 /* 57 * What's passed as an actual key is defined by the KEYMGMT interface. 58 * We happen to know that our KEYMGMT simply passes DH structures, so 59 * we use that here too. 60 */ 61 62 typedef struct { 63 OSSL_LIB_CTX *libctx; 64 DH *dh; 65 DH *dhpeer; 66 unsigned int pad : 1; 67 68 /* DH KDF */ 69 /* KDF (if any) to use for DH */ 70 enum kdf_type kdf_type; 71 /* Message digest to use for key derivation */ 72 EVP_MD *kdf_md; 73 /* User key material */ 74 unsigned char *kdf_ukm; 75 size_t kdf_ukmlen; 76 /* KDF output length */ 77 size_t kdf_outlen; 78 char *kdf_cekalg; 79 } PROV_DH_CTX; 80 81 static void *dh_newctx(void *provctx) 82 { 83 PROV_DH_CTX *pdhctx; 84 85 if (!ossl_prov_is_running()) 86 return NULL; 87 88 pdhctx = OPENSSL_zalloc(sizeof(PROV_DH_CTX)); 89 if (pdhctx == NULL) 90 return NULL; 91 pdhctx->libctx = PROV_LIBCTX_OF(provctx); 92 pdhctx->kdf_type = PROV_DH_KDF_NONE; 93 return pdhctx; 94 } 95 96 static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[]) 97 { 98 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 99 100 if (!ossl_prov_is_running() 101 || pdhctx == NULL 102 || vdh == NULL 103 || !DH_up_ref(vdh)) 104 return 0; 105 DH_free(pdhctx->dh); 106 pdhctx->dh = vdh; 107 pdhctx->kdf_type = PROV_DH_KDF_NONE; 108 return dh_set_ctx_params(pdhctx, params) 109 && ossl_dh_check_key(pdhctx->libctx, vdh); 110 } 111 112 /* The 2 parties must share the same domain parameters */ 113 static int dh_match_params(DH *priv, DH *peer) 114 { 115 int ret; 116 FFC_PARAMS *dhparams_priv = ossl_dh_get0_params(priv); 117 FFC_PARAMS *dhparams_peer = ossl_dh_get0_params(peer); 118 119 ret = dhparams_priv != NULL 120 && dhparams_peer != NULL 121 && ossl_ffc_params_cmp(dhparams_priv, dhparams_peer, 1); 122 if (!ret) 123 ERR_raise(ERR_LIB_PROV, PROV_R_MISMATCHING_DOMAIN_PARAMETERS); 124 return ret; 125 } 126 127 static int dh_set_peer(void *vpdhctx, void *vdh) 128 { 129 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 130 131 if (!ossl_prov_is_running() 132 || pdhctx == NULL 133 || vdh == NULL 134 || !dh_match_params(vdh, pdhctx->dh) 135 || !DH_up_ref(vdh)) 136 return 0; 137 DH_free(pdhctx->dhpeer); 138 pdhctx->dhpeer = vdh; 139 return 1; 140 } 141 142 static int dh_plain_derive(void *vpdhctx, 143 unsigned char *secret, size_t *secretlen, 144 size_t outlen, unsigned int pad) 145 { 146 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 147 int ret; 148 size_t dhsize; 149 const BIGNUM *pub_key = NULL; 150 151 if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) { 152 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); 153 return 0; 154 } 155 156 dhsize = (size_t)DH_size(pdhctx->dh); 157 if (secret == NULL) { 158 *secretlen = dhsize; 159 return 1; 160 } 161 if (outlen < dhsize) { 162 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 163 return 0; 164 } 165 166 DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); 167 if (pad) 168 ret = DH_compute_key_padded(secret, pub_key, pdhctx->dh); 169 else 170 ret = DH_compute_key(secret, pub_key, pdhctx->dh); 171 if (ret <= 0) 172 return 0; 173 174 *secretlen = ret; 175 return 1; 176 } 177 178 static int dh_X9_42_kdf_derive(void *vpdhctx, unsigned char *secret, 179 size_t *secretlen, size_t outlen) 180 { 181 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 182 unsigned char *stmp = NULL; 183 size_t stmplen; 184 int ret = 0; 185 186 if (secret == NULL) { 187 *secretlen = pdhctx->kdf_outlen; 188 return 1; 189 } 190 191 if (pdhctx->kdf_outlen > outlen) { 192 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 193 return 0; 194 } 195 if (!dh_plain_derive(pdhctx, NULL, &stmplen, 0, 1)) 196 return 0; 197 if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) { 198 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 199 return 0; 200 } 201 if (!dh_plain_derive(pdhctx, stmp, &stmplen, stmplen, 1)) 202 goto err; 203 204 /* Do KDF stuff */ 205 if (pdhctx->kdf_type == PROV_DH_KDF_X9_42_ASN1) { 206 if (!ossl_dh_kdf_X9_42_asn1(secret, pdhctx->kdf_outlen, 207 stmp, stmplen, 208 pdhctx->kdf_cekalg, 209 pdhctx->kdf_ukm, 210 pdhctx->kdf_ukmlen, 211 pdhctx->kdf_md, 212 pdhctx->libctx, NULL)) 213 goto err; 214 } 215 *secretlen = pdhctx->kdf_outlen; 216 ret = 1; 217 err: 218 OPENSSL_secure_clear_free(stmp, stmplen); 219 return ret; 220 } 221 222 static int dh_derive(void *vpdhctx, unsigned char *secret, 223 size_t *psecretlen, size_t outlen) 224 { 225 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 226 227 if (!ossl_prov_is_running()) 228 return 0; 229 230 switch (pdhctx->kdf_type) { 231 case PROV_DH_KDF_NONE: 232 return dh_plain_derive(pdhctx, secret, psecretlen, outlen, 233 pdhctx->pad); 234 case PROV_DH_KDF_X9_42_ASN1: 235 return dh_X9_42_kdf_derive(pdhctx, secret, psecretlen, outlen); 236 default: 237 break; 238 } 239 return 0; 240 } 241 242 static void dh_freectx(void *vpdhctx) 243 { 244 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 245 246 OPENSSL_free(pdhctx->kdf_cekalg); 247 DH_free(pdhctx->dh); 248 DH_free(pdhctx->dhpeer); 249 EVP_MD_free(pdhctx->kdf_md); 250 OPENSSL_clear_free(pdhctx->kdf_ukm, pdhctx->kdf_ukmlen); 251 252 OPENSSL_free(pdhctx); 253 } 254 255 static void *dh_dupctx(void *vpdhctx) 256 { 257 PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx; 258 PROV_DH_CTX *dstctx; 259 260 if (!ossl_prov_is_running()) 261 return NULL; 262 263 dstctx = OPENSSL_zalloc(sizeof(*srcctx)); 264 if (dstctx == NULL) 265 return NULL; 266 267 *dstctx = *srcctx; 268 dstctx->dh = NULL; 269 dstctx->dhpeer = NULL; 270 dstctx->kdf_md = NULL; 271 dstctx->kdf_ukm = NULL; 272 dstctx->kdf_cekalg = NULL; 273 274 if (srcctx->dh != NULL && !DH_up_ref(srcctx->dh)) 275 goto err; 276 else 277 dstctx->dh = srcctx->dh; 278 279 if (srcctx->dhpeer != NULL && !DH_up_ref(srcctx->dhpeer)) 280 goto err; 281 else 282 dstctx->dhpeer = srcctx->dhpeer; 283 284 if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md)) 285 goto err; 286 else 287 dstctx->kdf_md = srcctx->kdf_md; 288 289 /* Duplicate UKM data if present */ 290 if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) { 291 dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm, 292 srcctx->kdf_ukmlen); 293 if (dstctx->kdf_ukm == NULL) 294 goto err; 295 } 296 297 if (srcctx->kdf_cekalg != NULL) { 298 dstctx->kdf_cekalg = OPENSSL_strdup(srcctx->kdf_cekalg); 299 if (dstctx->kdf_cekalg == NULL) 300 goto err; 301 } 302 303 return dstctx; 304 err: 305 dh_freectx(dstctx); 306 return NULL; 307 } 308 309 static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[]) 310 { 311 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 312 const OSSL_PARAM *p; 313 unsigned int pad; 314 char name[80] = { '\0' }; /* should be big enough */ 315 char *str = NULL; 316 317 if (pdhctx == NULL) 318 return 0; 319 if (params == NULL) 320 return 1; 321 322 p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); 323 if (p != NULL) { 324 str = name; 325 if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name))) 326 return 0; 327 328 if (name[0] == '\0') 329 pdhctx->kdf_type = PROV_DH_KDF_NONE; 330 else if (strcmp(name, OSSL_KDF_NAME_X942KDF_ASN1) == 0) 331 pdhctx->kdf_type = PROV_DH_KDF_X9_42_ASN1; 332 else 333 return 0; 334 } 335 p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST); 336 if (p != NULL) { 337 char mdprops[80] = { '\0' }; /* should be big enough */ 338 339 str = name; 340 if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name))) 341 return 0; 342 343 str = mdprops; 344 p = OSSL_PARAM_locate_const(params, 345 OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS); 346 347 if (p != NULL) { 348 if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops))) 349 return 0; 350 } 351 352 EVP_MD_free(pdhctx->kdf_md); 353 pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops); 354 if (!ossl_digest_is_allowed(pdhctx->libctx, pdhctx->kdf_md)) { 355 EVP_MD_free(pdhctx->kdf_md); 356 pdhctx->kdf_md = NULL; 357 } 358 if (pdhctx->kdf_md == NULL) 359 return 0; 360 } 361 362 p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); 363 if (p != NULL) { 364 size_t outlen; 365 366 if (!OSSL_PARAM_get_size_t(p, &outlen)) 367 return 0; 368 pdhctx->kdf_outlen = outlen; 369 } 370 371 p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM); 372 if (p != NULL) { 373 void *tmp_ukm = NULL; 374 size_t tmp_ukmlen; 375 376 OPENSSL_free(pdhctx->kdf_ukm); 377 pdhctx->kdf_ukm = NULL; 378 pdhctx->kdf_ukmlen = 0; 379 /* ukm is an optional field so it can be NULL */ 380 if (p->data != NULL && p->data_size != 0) { 381 if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen)) 382 return 0; 383 pdhctx->kdf_ukm = tmp_ukm; 384 pdhctx->kdf_ukmlen = tmp_ukmlen; 385 } 386 } 387 388 p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD); 389 if (p != NULL) { 390 if (!OSSL_PARAM_get_uint(p, &pad)) 391 return 0; 392 pdhctx->pad = pad ? 1 : 0; 393 } 394 395 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG); 396 if (p != NULL) { 397 str = name; 398 399 OPENSSL_free(pdhctx->kdf_cekalg); 400 pdhctx->kdf_cekalg = NULL; 401 if (p->data != NULL && p->data_size != 0) { 402 if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name))) 403 return 0; 404 pdhctx->kdf_cekalg = OPENSSL_strdup(name); 405 if (pdhctx->kdf_cekalg == NULL) 406 return 0; 407 } 408 } 409 return 1; 410 } 411 412 static const OSSL_PARAM known_settable_ctx_params[] = { 413 OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL), 414 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0), 415 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0), 416 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0), 417 OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), 418 OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0), 419 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), 420 OSSL_PARAM_END 421 }; 422 423 static const OSSL_PARAM *dh_settable_ctx_params(ossl_unused void *vpdhctx, 424 ossl_unused void *provctx) 425 { 426 return known_settable_ctx_params; 427 } 428 429 static const OSSL_PARAM known_gettable_ctx_params[] = { 430 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0), 431 OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0), 432 OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), 433 OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, 434 NULL, 0), 435 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), 436 OSSL_PARAM_END 437 }; 438 439 static const OSSL_PARAM *dh_gettable_ctx_params(ossl_unused void *vpdhctx, 440 ossl_unused void *provctx) 441 { 442 return known_gettable_ctx_params; 443 } 444 445 static int dh_get_ctx_params(void *vpdhctx, OSSL_PARAM params[]) 446 { 447 PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; 448 OSSL_PARAM *p; 449 450 if (pdhctx == NULL) 451 return 0; 452 453 p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); 454 if (p != NULL) { 455 const char *kdf_type = NULL; 456 457 switch (pdhctx->kdf_type) { 458 case PROV_DH_KDF_NONE: 459 kdf_type = ""; 460 break; 461 case PROV_DH_KDF_X9_42_ASN1: 462 kdf_type = OSSL_KDF_NAME_X942KDF_ASN1; 463 break; 464 default: 465 return 0; 466 } 467 468 if (!OSSL_PARAM_set_utf8_string(p, kdf_type)) 469 return 0; 470 } 471 472 p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST); 473 if (p != NULL 474 && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_md == NULL 475 ? "" 476 : EVP_MD_get0_name(pdhctx->kdf_md))){ 477 return 0; 478 } 479 480 p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); 481 if (p != NULL && !OSSL_PARAM_set_size_t(p, pdhctx->kdf_outlen)) 482 return 0; 483 484 p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM); 485 if (p != NULL 486 && !OSSL_PARAM_set_octet_ptr(p, pdhctx->kdf_ukm, pdhctx->kdf_ukmlen)) 487 return 0; 488 489 p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_CEK_ALG); 490 if (p != NULL 491 && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL 492 ? "" : pdhctx->kdf_cekalg)) 493 return 0; 494 495 return 1; 496 } 497 498 const OSSL_DISPATCH ossl_dh_keyexch_functions[] = { 499 { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx }, 500 { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init }, 501 { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive }, 502 { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer }, 503 { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx }, 504 { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx }, 505 { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params }, 506 { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, 507 (void (*)(void))dh_settable_ctx_params }, 508 { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))dh_get_ctx_params }, 509 { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, 510 (void (*)(void))dh_gettable_ctx_params }, 511 { 0, NULL } 512 }; 513