1160814Ssimon/* crypto/ecdh/ech_ossl.c */ 2160814Ssimon/* ==================================================================== 3160814Ssimon * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 4160814Ssimon * 5160814Ssimon * The Elliptic Curve Public-Key Crypto Library (ECC Code) included 6160814Ssimon * herein is developed by SUN MICROSYSTEMS, INC., and is contributed 7160814Ssimon * to the OpenSSL project. 8160814Ssimon * 9160814Ssimon * The ECC Code is licensed pursuant to the OpenSSL open source 10160814Ssimon * license provided below. 11160814Ssimon * 12160814Ssimon * The ECDH software is originally written by Douglas Stebila of 13160814Ssimon * Sun Microsystems Laboratories. 14160814Ssimon * 15160814Ssimon */ 16160814Ssimon/* ==================================================================== 17348343Sjkim * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved. 18160814Ssimon * 19160814Ssimon * Redistribution and use in source and binary forms, with or without 20160814Ssimon * modification, are permitted provided that the following conditions 21160814Ssimon * are met: 22160814Ssimon * 23160814Ssimon * 1. Redistributions of source code must retain the above copyright 24280297Sjkim * notice, this list of conditions and the following disclaimer. 25160814Ssimon * 26160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 27160814Ssimon * notice, this list of conditions and the following disclaimer in 28160814Ssimon * the documentation and/or other materials provided with the 29160814Ssimon * distribution. 30160814Ssimon * 31160814Ssimon * 3. All advertising materials mentioning features or use of this 32160814Ssimon * software must display the following acknowledgment: 33160814Ssimon * "This product includes software developed by the OpenSSL Project 34160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 35160814Ssimon * 36160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 37160814Ssimon * endorse or promote products derived from this software without 38160814Ssimon * prior written permission. For written permission, please contact 39160814Ssimon * openssl-core@OpenSSL.org. 40160814Ssimon * 41160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 42160814Ssimon * nor may "OpenSSL" appear in their names without prior written 43160814Ssimon * permission of the OpenSSL Project. 44160814Ssimon * 45160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 46160814Ssimon * acknowledgment: 47160814Ssimon * "This product includes software developed by the OpenSSL Project 48160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 49160814Ssimon * 50160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 51160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 54160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 55160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 59160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 61160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 62160814Ssimon * ==================================================================== 63160814Ssimon * 64160814Ssimon * This product includes cryptographic software written by Eric Young 65160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 66160814Ssimon * Hudson (tjh@cryptsoft.com). 67160814Ssimon * 68160814Ssimon */ 69160814Ssimon 70160814Ssimon#include <string.h> 71160814Ssimon#include <limits.h> 72160814Ssimon 73160814Ssimon#include "cryptlib.h" 74160814Ssimon 75160814Ssimon#include "ech_locl.h" 76160814Ssimon#include <openssl/err.h> 77160814Ssimon#include <openssl/sha.h> 78160814Ssimon#include <openssl/obj_mac.h> 79160814Ssimon#include <openssl/bn.h> 80160814Ssimon 81160814Ssimonstatic int ecdh_compute_key(void *out, size_t len, const EC_POINT *pub_key, 82280297Sjkim EC_KEY *ecdh, 83280297Sjkim void *(*KDF) (const void *in, size_t inlen, 84280297Sjkim void *out, size_t *outlen)); 85160814Ssimon 86160814Ssimonstatic ECDH_METHOD openssl_ecdh_meth = { 87280297Sjkim "OpenSSL ECDH method", 88280297Sjkim ecdh_compute_key, 89160814Ssimon#if 0 90280297Sjkim NULL, /* init */ 91280297Sjkim NULL, /* finish */ 92160814Ssimon#endif 93280297Sjkim 0, /* flags */ 94280297Sjkim NULL /* app_data */ 95160814Ssimon}; 96160814Ssimon 97160814Ssimonconst ECDH_METHOD *ECDH_OpenSSL(void) 98280297Sjkim{ 99280297Sjkim return &openssl_ecdh_meth; 100280297Sjkim} 101160814Ssimon 102280297Sjkim/*- 103280297Sjkim * This implementation is based on the following primitives in the IEEE 1363 standard: 104160814Ssimon * - ECKAS-DH1 105160814Ssimon * - ECSVDP-DH 106160814Ssimon * Finally an optional KDF is applied. 107160814Ssimon */ 108160814Ssimonstatic int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, 109280297Sjkim EC_KEY *ecdh, 110280297Sjkim void *(*KDF) (const void *in, size_t inlen, 111280297Sjkim void *out, size_t *outlen)) 112280297Sjkim{ 113280297Sjkim BN_CTX *ctx; 114280297Sjkim EC_POINT *tmp = NULL; 115280297Sjkim BIGNUM *x = NULL, *y = NULL; 116280297Sjkim const BIGNUM *priv_key; 117280297Sjkim const EC_GROUP *group; 118280297Sjkim int ret = -1; 119280297Sjkim size_t buflen, len; 120280297Sjkim unsigned char *buf = NULL; 121160814Ssimon 122280297Sjkim if (outlen > INT_MAX) { 123280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); /* sort of, 124280297Sjkim * anyway */ 125280297Sjkim return -1; 126280297Sjkim } 127160814Ssimon 128280297Sjkim if ((ctx = BN_CTX_new()) == NULL) 129280297Sjkim goto err; 130280297Sjkim BN_CTX_start(ctx); 131280297Sjkim x = BN_CTX_get(ctx); 132280297Sjkim y = BN_CTX_get(ctx); 133160814Ssimon 134280297Sjkim priv_key = EC_KEY_get0_private_key(ecdh); 135280297Sjkim if (priv_key == NULL) { 136280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_NO_PRIVATE_VALUE); 137280297Sjkim goto err; 138280297Sjkim } 139160814Ssimon 140280297Sjkim group = EC_KEY_get0_group(ecdh); 141290207Sjkim 142290207Sjkim if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { 143290207Sjkim if (!EC_GROUP_get_cofactor(group, x, ctx) || 144290207Sjkim !BN_mul(x, x, priv_key, ctx)) { 145290207Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); 146290207Sjkim goto err; 147290207Sjkim } 148290207Sjkim priv_key = x; 149290207Sjkim } 150290207Sjkim 151280297Sjkim if ((tmp = EC_POINT_new(group)) == NULL) { 152280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); 153280297Sjkim goto err; 154280297Sjkim } 155280297Sjkim 156280297Sjkim if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { 157280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); 158280297Sjkim goto err; 159280297Sjkim } 160280297Sjkim 161280297Sjkim if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == 162280297Sjkim NID_X9_62_prime_field) { 163280297Sjkim if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { 164280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); 165280297Sjkim goto err; 166280297Sjkim } 167280297Sjkim } 168238405Sjkim#ifndef OPENSSL_NO_EC2M 169280297Sjkim else { 170280297Sjkim if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { 171280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); 172280297Sjkim goto err; 173280297Sjkim } 174280297Sjkim } 175238405Sjkim#endif 176160814Ssimon 177280297Sjkim buflen = (EC_GROUP_get_degree(group) + 7) / 8; 178280297Sjkim len = BN_num_bytes(x); 179280297Sjkim if (len > buflen) { 180280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); 181280297Sjkim goto err; 182280297Sjkim } 183280297Sjkim if ((buf = OPENSSL_malloc(buflen)) == NULL) { 184280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); 185280297Sjkim goto err; 186280297Sjkim } 187160814Ssimon 188280297Sjkim memset(buf, 0, buflen - len); 189280297Sjkim if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { 190280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB); 191280297Sjkim goto err; 192280297Sjkim } 193280297Sjkim 194280297Sjkim if (KDF != 0) { 195280297Sjkim if (KDF(buf, buflen, out, &outlen) == NULL) { 196280297Sjkim ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_KDF_FAILED); 197280297Sjkim goto err; 198280297Sjkim } 199280297Sjkim ret = outlen; 200280297Sjkim } else { 201280297Sjkim /* no KDF, just copy as much as we can */ 202280297Sjkim if (outlen > buflen) 203280297Sjkim outlen = buflen; 204280297Sjkim memcpy(out, buf, outlen); 205280297Sjkim ret = outlen; 206280297Sjkim } 207280297Sjkim 208280297Sjkim err: 209280297Sjkim if (tmp) 210348343Sjkim EC_POINT_clear_free(tmp); 211280297Sjkim if (ctx) 212280297Sjkim BN_CTX_end(ctx); 213280297Sjkim if (ctx) 214280297Sjkim BN_CTX_free(ctx); 215312826Sjkim if (buf) { 216312826Sjkim OPENSSL_cleanse(buf, buflen); 217280297Sjkim OPENSSL_free(buf); 218312826Sjkim } 219280297Sjkim return (ret); 220280297Sjkim} 221