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/* ==================================================================== 17160814Ssimon * Copyright (c) 1998-2003 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 24296341Sdelphij * 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, 82296341Sdelphij EC_KEY *ecdh, 83296341Sdelphij void *(*KDF) (const void *in, size_t inlen, 84296341Sdelphij void *out, size_t *outlen)); 85160814Ssimon 86160814Ssimonstatic ECDH_METHOD openssl_ecdh_meth = { 87296341Sdelphij "OpenSSL ECDH method", 88296341Sdelphij ecdh_compute_key, 89160814Ssimon#if 0 90296341Sdelphij NULL, /* init */ 91296341Sdelphij NULL, /* finish */ 92160814Ssimon#endif 93296341Sdelphij 0, /* flags */ 94296341Sdelphij NULL /* app_data */ 95160814Ssimon}; 96160814Ssimon 97160814Ssimonconst ECDH_METHOD *ECDH_OpenSSL(void) 98296341Sdelphij{ 99296341Sdelphij return &openssl_ecdh_meth; 100296341Sdelphij} 101160814Ssimon 102296341Sdelphij/*- 103296341Sdelphij * 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, 109296341Sdelphij EC_KEY *ecdh, 110296341Sdelphij void *(*KDF) (const void *in, size_t inlen, 111296341Sdelphij void *out, size_t *outlen)) 112296341Sdelphij{ 113296341Sdelphij BN_CTX *ctx; 114296341Sdelphij EC_POINT *tmp = NULL; 115296341Sdelphij BIGNUM *x = NULL, *y = NULL; 116296341Sdelphij const BIGNUM *priv_key; 117296341Sdelphij const EC_GROUP *group; 118296341Sdelphij int ret = -1; 119296341Sdelphij size_t buflen, len; 120296341Sdelphij unsigned char *buf = NULL; 121160814Ssimon 122296341Sdelphij if (outlen > INT_MAX) { 123296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); /* sort of, 124296341Sdelphij * anyway */ 125296341Sdelphij return -1; 126296341Sdelphij } 127160814Ssimon 128296341Sdelphij if ((ctx = BN_CTX_new()) == NULL) 129296341Sdelphij goto err; 130296341Sdelphij BN_CTX_start(ctx); 131296341Sdelphij x = BN_CTX_get(ctx); 132296341Sdelphij y = BN_CTX_get(ctx); 133160814Ssimon 134296341Sdelphij priv_key = EC_KEY_get0_private_key(ecdh); 135296341Sdelphij if (priv_key == NULL) { 136296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_NO_PRIVATE_VALUE); 137296341Sdelphij goto err; 138296341Sdelphij } 139160814Ssimon 140296341Sdelphij group = EC_KEY_get0_group(ecdh); 141296341Sdelphij if ((tmp = EC_POINT_new(group)) == NULL) { 142296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); 143296341Sdelphij goto err; 144296341Sdelphij } 145296341Sdelphij 146296341Sdelphij if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { 147296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); 148296341Sdelphij goto err; 149296341Sdelphij } 150296341Sdelphij 151296341Sdelphij if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == 152296341Sdelphij NID_X9_62_prime_field) { 153296341Sdelphij if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { 154296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); 155296341Sdelphij goto err; 156296341Sdelphij } 157296341Sdelphij } 158238405Sjkim#ifndef OPENSSL_NO_EC2M 159296341Sdelphij else { 160296341Sdelphij if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { 161296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_POINT_ARITHMETIC_FAILURE); 162296341Sdelphij goto err; 163296341Sdelphij } 164296341Sdelphij } 165238405Sjkim#endif 166160814Ssimon 167296341Sdelphij buflen = (EC_GROUP_get_degree(group) + 7) / 8; 168296341Sdelphij len = BN_num_bytes(x); 169296341Sdelphij if (len > buflen) { 170296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); 171296341Sdelphij goto err; 172296341Sdelphij } 173296341Sdelphij if ((buf = OPENSSL_malloc(buflen)) == NULL) { 174296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); 175296341Sdelphij goto err; 176296341Sdelphij } 177160814Ssimon 178296341Sdelphij memset(buf, 0, buflen - len); 179296341Sdelphij if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { 180296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ERR_R_BN_LIB); 181296341Sdelphij goto err; 182296341Sdelphij } 183296341Sdelphij 184296341Sdelphij if (KDF != 0) { 185296341Sdelphij if (KDF(buf, buflen, out, &outlen) == NULL) { 186296341Sdelphij ECDHerr(ECDH_F_ECDH_COMPUTE_KEY, ECDH_R_KDF_FAILED); 187296341Sdelphij goto err; 188296341Sdelphij } 189296341Sdelphij ret = outlen; 190296341Sdelphij } else { 191296341Sdelphij /* no KDF, just copy as much as we can */ 192296341Sdelphij if (outlen > buflen) 193296341Sdelphij outlen = buflen; 194296341Sdelphij memcpy(out, buf, outlen); 195296341Sdelphij ret = outlen; 196296341Sdelphij } 197296341Sdelphij 198296341Sdelphij err: 199296341Sdelphij if (tmp) 200296341Sdelphij EC_POINT_free(tmp); 201296341Sdelphij if (ctx) 202296341Sdelphij BN_CTX_end(ctx); 203296341Sdelphij if (ctx) 204296341Sdelphij BN_CTX_free(ctx); 205296341Sdelphij if (buf) 206296341Sdelphij OPENSSL_free(buf); 207296341Sdelphij return (ret); 208296341Sdelphij} 209