Home | History | Annotate | Download | only in ecdh
      1 /* crypto/ecdh/ech_ossl.c */
      2 /* ====================================================================
      3  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
      4  *
      5  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
      6  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
      7  * to the OpenSSL project.
      8  *
      9  * The ECC Code is licensed pursuant to the OpenSSL open source
     10  * license provided below.
     11  *
     12  * The ECDH software is originally written by Douglas Stebila of
     13  * Sun Microsystems Laboratories.
     14  *
     15  */
     16 /* ====================================================================
     17  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
     18  *
     19  * Redistribution and use in source and binary forms, with or without
     20  * modification, are permitted provided that the following conditions
     21  * are met:
     22  *
     23  * 1. Redistributions of source code must retain the above copyright
     24  *    notice, this list of conditions and the following disclaimer.
     25  *
     26  * 2. Redistributions in binary form must reproduce the above copyright
     27  *    notice, this list of conditions and the following disclaimer in
     28  *    the documentation and/or other materials provided with the
     29  *    distribution.
     30  *
     31  * 3. All advertising materials mentioning features or use of this
     32  *    software must display the following acknowledgment:
     33  *    "This product includes software developed by the OpenSSL Project
     34  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
     35  *
     36  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
     37  *    endorse or promote products derived from this software without
     38  *    prior written permission. For written permission, please contact
     39  *    openssl-core (at) OpenSSL.org.
     40  *
     41  * 5. Products derived from this software may not be called "OpenSSL"
     42  *    nor may "OpenSSL" appear in their names without prior written
     43  *    permission of the OpenSSL Project.
     44  *
     45  * 6. Redistributions of any form whatsoever must retain the following
     46  *    acknowledgment:
     47  *    "This product includes software developed by the OpenSSL Project
     48  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
     49  *
     50  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
     51  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
     54  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     56  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     59  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     60  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     61  * OF THE POSSIBILITY OF SUCH DAMAGE.
     62  * ====================================================================
     63  *
     64  * This product includes cryptographic software written by Eric Young
     65  * (eay (at) cryptsoft.com).  This product includes software written by Tim
     66  * Hudson (tjh (at) cryptsoft.com).
     67  *
     68  */
     69 
     70 
     71 #include <string.h>
     72 #include <limits.h>
     73 
     74 #include "cryptlib.h"
     75 
     76 #include "ech_locl.h"
     77 #include <openssl/err.h>
     78 #include <openssl/sha.h>
     79 #include <openssl/obj_mac.h>
     80 #include <openssl/bn.h>
     81 
     82 static int ecdh_compute_key(void *out, size_t len, const EC_POINT *pub_key,
     83 	EC_KEY *ecdh,
     84 	void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
     85 
     86 static ECDH_METHOD openssl_ecdh_meth = {
     87 	"OpenSSL ECDH method",
     88 	ecdh_compute_key,
     89 #if 0
     90 	NULL, /* init     */
     91 	NULL, /* finish   */
     92 #endif
     93 	0,    /* flags    */
     94 	NULL  /* app_data */
     95 };
     96 
     97 const ECDH_METHOD *ECDH_OpenSSL(void)
     98 	{
     99 	return &openssl_ecdh_meth;
    100 	}
    101 
    102 
    103 /* This implementation is based on the following primitives in the IEEE 1363 standard:
    104  *  - ECKAS-DH1
    105  *  - ECSVDP-DH
    106  * Finally an optional KDF is applied.
    107  */
    108 static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
    109 	EC_KEY *ecdh,
    110 	void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
    111 	{
    112 	BN_CTX *ctx;
    113 	EC_POINT *tmp=NULL;
    114 	BIGNUM *x=NULL, *y=NULL;
    115 	const BIGNUM *priv_key;
    116 	const EC_GROUP* group;
    117 	int ret= -1;
    118 	size_t buflen, len;
    119 	unsigned char *buf=NULL;
    120 
    121 	if (outlen > INT_MAX)
    122 		{
    123 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */
    124 		return -1;
    125 		}
    126 
    127 	if ((ctx = BN_CTX_new()) == NULL) goto err;
    128 	BN_CTX_start(ctx);
    129 	x = BN_CTX_get(ctx);
    130 	y = BN_CTX_get(ctx);
    131 
    132 	priv_key = EC_KEY_get0_private_key(ecdh);
    133 	if (priv_key == NULL)
    134 		{
    135 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE);
    136 		goto err;
    137 		}
    138 
    139 	group = EC_KEY_get0_group(ecdh);
    140 	if ((tmp=EC_POINT_new(group)) == NULL)
    141 		{
    142 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
    143 		goto err;
    144 		}
    145 
    146 	if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx))
    147 		{
    148 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
    149 		goto err;
    150 		}
    151 
    152 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
    153 		{
    154 		if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx))
    155 			{
    156 			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
    157 			goto err;
    158 			}
    159 		}
    160 	else
    161 		{
    162 		if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx))
    163 			{
    164 			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
    165 			goto err;
    166 			}
    167 		}
    168 
    169 	buflen = (EC_GROUP_get_degree(group) + 7)/8;
    170 	len = BN_num_bytes(x);
    171 	if (len > buflen)
    172 		{
    173 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR);
    174 		goto err;
    175 		}
    176 	if ((buf = OPENSSL_malloc(buflen)) == NULL)
    177 		{
    178 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
    179 		goto err;
    180 		}
    181 
    182 	memset(buf, 0, buflen - len);
    183 	if (len != (size_t)BN_bn2bin(x, buf + buflen - len))
    184 		{
    185 		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB);
    186 		goto err;
    187 		}
    188 
    189 	if (KDF != 0)
    190 		{
    191 		if (KDF(buf, buflen, out, &outlen) == NULL)
    192 			{
    193 			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED);
    194 			goto err;
    195 			}
    196 		ret = outlen;
    197 		}
    198 	else
    199 		{
    200 		/* no KDF, just copy as much as we can */
    201 		if (outlen > buflen)
    202 			outlen = buflen;
    203 		memcpy(out, buf, outlen);
    204 		ret = outlen;
    205 		}
    206 
    207 err:
    208 	if (tmp) EC_POINT_free(tmp);
    209 	if (ctx) BN_CTX_end(ctx);
    210 	if (ctx) BN_CTX_free(ctx);
    211 	if (buf) OPENSSL_free(buf);
    212 	return(ret);
    213 	}
    214