1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci/* 12e1051a39Sopenharmony_ci * ECDH low level APIs are deprecated for public use, but still ok for 13e1051a39Sopenharmony_ci * internal use. 14e1051a39Sopenharmony_ci */ 15e1051a39Sopenharmony_ci#include "internal/deprecated.h" 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#include <string.h> 18e1051a39Sopenharmony_ci#include <limits.h> 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci#include <openssl/err.h> 23e1051a39Sopenharmony_ci#include <openssl/bn.h> 24e1051a39Sopenharmony_ci#include <openssl/objects.h> 25e1051a39Sopenharmony_ci#include <openssl/ec.h> 26e1051a39Sopenharmony_ci#include "ec_local.h" 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ciint ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen, 29e1051a39Sopenharmony_ci const EC_POINT *pub_key, const EC_KEY *ecdh) 30e1051a39Sopenharmony_ci{ 31e1051a39Sopenharmony_ci if (ecdh->group->meth->ecdh_compute_key == NULL) { 32e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH); 33e1051a39Sopenharmony_ci return 0; 34e1051a39Sopenharmony_ci } 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci return ecdh->group->meth->ecdh_compute_key(psec, pseclen, pub_key, ecdh); 37e1051a39Sopenharmony_ci} 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci/*- 40e1051a39Sopenharmony_ci * This implementation is based on the following primitives in the 41e1051a39Sopenharmony_ci * IEEE 1363 standard: 42e1051a39Sopenharmony_ci * - ECKAS-DH1 43e1051a39Sopenharmony_ci * - ECSVDP-DH 44e1051a39Sopenharmony_ci * 45e1051a39Sopenharmony_ci * It also conforms to SP800-56A r3 46e1051a39Sopenharmony_ci * See Section 5.7.1.2 "Elliptic Curve Cryptography Cofactor Diffie-Hellman 47e1051a39Sopenharmony_ci * (ECC CDH) Primitive:". The steps listed below refer to SP800-56A. 48e1051a39Sopenharmony_ci */ 49e1051a39Sopenharmony_ciint ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, 50e1051a39Sopenharmony_ci const EC_POINT *pub_key, const EC_KEY *ecdh) 51e1051a39Sopenharmony_ci{ 52e1051a39Sopenharmony_ci BN_CTX *ctx; 53e1051a39Sopenharmony_ci EC_POINT *tmp = NULL; 54e1051a39Sopenharmony_ci BIGNUM *x = NULL; 55e1051a39Sopenharmony_ci const BIGNUM *priv_key; 56e1051a39Sopenharmony_ci const EC_GROUP *group; 57e1051a39Sopenharmony_ci int ret = 0; 58e1051a39Sopenharmony_ci size_t buflen, len; 59e1051a39Sopenharmony_ci unsigned char *buf = NULL; 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci if ((ctx = BN_CTX_new_ex(ecdh->libctx)) == NULL) 62e1051a39Sopenharmony_ci goto err; 63e1051a39Sopenharmony_ci BN_CTX_start(ctx); 64e1051a39Sopenharmony_ci x = BN_CTX_get(ctx); 65e1051a39Sopenharmony_ci if (x == NULL) { 66e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 67e1051a39Sopenharmony_ci goto err; 68e1051a39Sopenharmony_ci } 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci priv_key = EC_KEY_get0_private_key(ecdh); 71e1051a39Sopenharmony_ci if (priv_key == NULL) { 72e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); 73e1051a39Sopenharmony_ci goto err; 74e1051a39Sopenharmony_ci } 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci group = EC_KEY_get0_group(ecdh); 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci /* 79e1051a39Sopenharmony_ci * Step(1) - Compute the point tmp = cofactor * owners_private_key 80e1051a39Sopenharmony_ci * * peer_public_key. 81e1051a39Sopenharmony_ci */ 82e1051a39Sopenharmony_ci if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { 83e1051a39Sopenharmony_ci if (!EC_GROUP_get_cofactor(group, x, NULL) || 84e1051a39Sopenharmony_ci !BN_mul(x, x, priv_key, ctx)) { 85e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 86e1051a39Sopenharmony_ci goto err; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci priv_key = x; 89e1051a39Sopenharmony_ci } 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci if ((tmp = EC_POINT_new(group)) == NULL) { 92e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 93e1051a39Sopenharmony_ci goto err; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { 97e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE); 98e1051a39Sopenharmony_ci goto err; 99e1051a39Sopenharmony_ci } 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci /* 102e1051a39Sopenharmony_ci * Step(2) : If point tmp is at infinity then clear intermediate values and 103e1051a39Sopenharmony_ci * exit. Note: getting affine coordinates returns 0 if point is at infinity. 104e1051a39Sopenharmony_ci * Step(3a) : Get x-coordinate of point x = tmp.x 105e1051a39Sopenharmony_ci */ 106e1051a39Sopenharmony_ci if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) { 107e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_POINT_ARITHMETIC_FAILURE); 108e1051a39Sopenharmony_ci goto err; 109e1051a39Sopenharmony_ci } 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci /* 112e1051a39Sopenharmony_ci * Step(3b) : convert x to a byte string, using the field-element-to-byte 113e1051a39Sopenharmony_ci * string conversion routine defined in Appendix C.2 114e1051a39Sopenharmony_ci */ 115e1051a39Sopenharmony_ci buflen = (EC_GROUP_get_degree(group) + 7) / 8; 116e1051a39Sopenharmony_ci len = BN_num_bytes(x); 117e1051a39Sopenharmony_ci if (len > buflen) { 118e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); 119e1051a39Sopenharmony_ci goto err; 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci if ((buf = OPENSSL_malloc(buflen)) == NULL) { 122e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 123e1051a39Sopenharmony_ci goto err; 124e1051a39Sopenharmony_ci } 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_ci memset(buf, 0, buflen - len); 127e1051a39Sopenharmony_ci if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { 128e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 129e1051a39Sopenharmony_ci goto err; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci *pout = buf; 133e1051a39Sopenharmony_ci *poutlen = buflen; 134e1051a39Sopenharmony_ci buf = NULL; 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci ret = 1; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci err: 139e1051a39Sopenharmony_ci /* Step(4) : Destroy all intermediate calculations */ 140e1051a39Sopenharmony_ci BN_clear(x); 141e1051a39Sopenharmony_ci EC_POINT_clear_free(tmp); 142e1051a39Sopenharmony_ci BN_CTX_end(ctx); 143e1051a39Sopenharmony_ci BN_CTX_free(ctx); 144e1051a39Sopenharmony_ci OPENSSL_free(buf); 145e1051a39Sopenharmony_ci return ret; 146e1051a39Sopenharmony_ci} 147