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