From 176f31ddec84a51d35871dc021a013df9f3cbccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bodo=20M=C3=B6ller?= Date: Fri, 28 Feb 2003 15:37:10 +0000 Subject: - new ECDH_compute_key interface (KDF is no longer a fixed built-in) - bugfix: in ECDH_compute_key, pad x coordinate with leading zeros if necessary --- crypto/ecdh/ecdh.h | 10 +++++----- crypto/ecdh/ecdhtest.c | 25 ++++++++++++++++++----- crypto/ecdh/ech_err.c | 2 +- crypto/ecdh/ech_key.c | 7 ++++--- crypto/ecdh/ech_lib.c | 8 +------- crypto/ecdh/ech_ossl.c | 54 ++++++++++++++++++++++++++++++++++++++------------ 6 files changed, 72 insertions(+), 34 deletions(-) (limited to 'crypto/ecdh') diff --git a/crypto/ecdh/ecdh.h b/crypto/ecdh/ecdh.h index 1ab131cde9..cc6d858d61 100644 --- a/crypto/ecdh/ecdh.h +++ b/crypto/ecdh/ecdh.h @@ -84,7 +84,8 @@ extern "C" { typedef struct ecdh_method { const char *name; - int (*compute_key)(unsigned char *key,const EC_POINT *pub_key, EC_KEY *ecdh); + int (*compute_key)(void *key, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, + void *(*KDF)(void *in, size_t inlen, void *out, size_t outlen)); #if 0 int (*init)(EC_KEY *eckey); int (*finish)(EC_KEY *eckey); @@ -118,9 +119,8 @@ void ECDH_set_default_method(const ECDH_METHOD *); const ECDH_METHOD *ECDH_get_default_method(void); int ECDH_set_method(EC_KEY *, const ECDH_METHOD *); -int ECDH_size(const EC_KEY *); -int ECDH_compute_key(unsigned char *key,const EC_POINT *pub_key, EC_KEY *ecdh); - +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, + void *(*KDF)(void *in, size_t inlen, void *out, size_t outlen)); int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); @@ -141,9 +141,9 @@ void ERR_load_ECDH_strings(void); #define ECDH_F_ECDH_DATA_NEW 101 /* Reason codes. */ +#define ECDH_R_KDF_FAILED 102 #define ECDH_R_NO_PRIVATE_VALUE 100 #define ECDH_R_POINT_ARITHMETIC_FAILURE 101 -#define ECDH_R_SHA1_DIGEST_FAILED 102 #ifdef __cplusplus } diff --git a/crypto/ecdh/ecdhtest.c b/crypto/ecdh/ecdhtest.c index 6e0c14dc13..f9162b7e8b 100644 --- a/crypto/ecdh/ecdhtest.c +++ b/crypto/ecdh/ecdhtest.c @@ -14,7 +14,7 @@ * */ /* ==================================================================== - * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -79,6 +79,7 @@ #include #include #include +#include #include #ifdef OPENSSL_NO_ECDH @@ -102,6 +103,20 @@ static void MS_CALLBACK cb(int p, int n, void *arg); static const char rnd_seed[] = "string to make the random number generator think it has entropy"; + +static const int KDF1_SHA1_len = 20; +static void *KDF1_SHA1(void *in, size_t inlen, void *out, size_t outlen) + { +#ifndef OPENSSL_NO_SHA + if (outlen != SHA_DIGEST_LENGTH) + return NULL; + return SHA1(in, inlen, out); +#else + return NULL; +#endif + } + + int test_ecdh_curve(int , char *, BN_CTX *, BIO *); int test_ecdh_curve(int nid, char *text, BN_CTX *ctx, BIO *out) @@ -180,9 +195,9 @@ int test_ecdh_curve(int nid, char *text, BN_CTX *ctx, BIO *out) BIO_flush(out); #endif - alen=ECDH_size(a); + alen=KDF1_SHA1_len; abuf=(unsigned char *)OPENSSL_malloc(alen); - aout=ECDH_compute_key(abuf,b->pub_key,a); + aout=ECDH_compute_key(abuf,alen,b->pub_key,a,KDF1_SHA1); #ifdef NOISY BIO_puts(out," key1 ="); @@ -197,9 +212,9 @@ int test_ecdh_curve(int nid, char *text, BN_CTX *ctx, BIO *out) BIO_flush(out); #endif - blen=ECDH_size(b); + blen=KDF1_SHA1_len; bbuf=(unsigned char *)OPENSSL_malloc(blen); - bout=ECDH_compute_key(bbuf,a->pub_key,b); + bout=ECDH_compute_key(bbuf,blen,a->pub_key,b,KDF1_SHA1); #ifdef NOISY BIO_puts(out," key2 ="); diff --git a/crypto/ecdh/ech_err.c b/crypto/ecdh/ech_err.c index 819b8abf4d..76fbe38387 100644 --- a/crypto/ecdh/ech_err.c +++ b/crypto/ecdh/ech_err.c @@ -73,9 +73,9 @@ static ERR_STRING_DATA ECDH_str_functs[]= static ERR_STRING_DATA ECDH_str_reasons[]= { +{ECDH_R_KDF_FAILED ,"KDF failed"}, {ECDH_R_NO_PRIVATE_VALUE ,"no private value"}, {ECDH_R_POINT_ARITHMETIC_FAILURE ,"point arithmetic failure"}, -{ECDH_R_SHA1_DIGEST_FAILED ,"sha1 digest failed"}, {0,NULL} }; diff --git a/crypto/ecdh/ech_key.c b/crypto/ecdh/ech_key.c index f000b8c8ad..923a7e9dd9 100644 --- a/crypto/ecdh/ech_key.c +++ b/crypto/ecdh/ech_key.c @@ -14,7 +14,7 @@ * */ /* ==================================================================== - * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -70,10 +70,11 @@ #include "ecdh.h" #include -int ECDH_compute_key(unsigned char *key, const EC_POINT *pub_key, EC_KEY *eckey) +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *eckey, + void *(*KDF)(void *in, size_t inlen, void *out, size_t outlen)) { ECDH_DATA *ecdh = ecdh_check(eckey); if (ecdh == NULL) return 0; - return ecdh->meth->compute_key(key, pub_key, eckey); + return ecdh->meth->compute_key(out, outlen, pub_key, eckey, KDF); } diff --git a/crypto/ecdh/ech_lib.c b/crypto/ecdh/ech_lib.c index 59526f33bd..8b3e5f1ddc 100644 --- a/crypto/ecdh/ech_lib.c +++ b/crypto/ecdh/ech_lib.c @@ -14,7 +14,7 @@ * */ /* ==================================================================== - * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -203,12 +203,6 @@ static void ecdh_finish(EC_KEY *key) } -int ECDH_size(const EC_KEY *ecdh) - { - return 20; - } - - int ECDH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { diff --git a/crypto/ecdh/ech_ossl.c b/crypto/ecdh/ech_ossl.c index 182e825b74..b00c6c431a 100644 --- a/crypto/ecdh/ech_ossl.c +++ b/crypto/ecdh/ech_ossl.c @@ -14,7 +14,7 @@ * */ /* ==================================================================== - * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -68,12 +68,15 @@ */ -#include "ecdh.h" +#include + +#include #include #include #include -static int ecdh_compute_key(unsigned char *key, const EC_POINT *pub_key, EC_KEY *ecdh); +static int ecdh_compute_key(void *out, size_t len, const EC_POINT *pub_key, EC_KEY *ecdh, + void *(*KDF)(void *in, size_t inlen, void *out, size_t outlen)); static ECDH_METHOD openssl_ecdh_meth = { "OpenSSL ECDH method", @@ -95,16 +98,23 @@ const ECDH_METHOD *ECDH_OpenSSL(void) /* This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH - * - KDF1 with SHA-1 + * Finally an optional KDF is applied. */ -static int ecdh_compute_key(unsigned char *key, const EC_POINT *pub_key, EC_KEY *ecdh) +static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh, + void *(*KDF)(void *in, size_t inlen, void *out, size_t outlen)) { BN_CTX *ctx; EC_POINT *tmp=NULL; BIGNUM *x=NULL, *y=NULL; - int ret= -1, len; + int ret= -1, buflen, len; unsigned char *buf=NULL; + if (outlen > INT_MAX) + { + ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */ + return -1; + } + if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); @@ -145,26 +155,44 @@ static int ecdh_compute_key(unsigned char *key, const EC_POINT *pub_key, EC_KEY } } - if ((buf = (unsigned char *)OPENSSL_malloc(sizeof(unsigned char) * BN_num_bytes(x))) == NULL) + buflen = (EC_GROUP_get_degree(ecdh->group) + 7)/8; + len = BN_num_bytes(x); + if (len > buflen) + { + ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR); + goto err; + } + if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); goto err; } - if ((len = BN_bn2bin(x,buf)) <= 0) + memset(buf, 0, buflen - len); + if (len != BN_bn2bin(x, buf + buflen - len)) { ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB); goto err; } - if ((SHA1(buf, len, key) == NULL)) + if (KDF != 0) { - ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_SHA1_DIGEST_FAILED); - goto err; + if (KDF(buf, buflen, out, outlen) == NULL) + { + ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED); + goto err; + } + ret = outlen; + } + else + { + /* no KDF, just copy as much as we can */ + if (outlen > buflen) + outlen = buflen; + memcpy(out, buf, outlen); + ret = outlen; } - ret = 20; - err: if (tmp) EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); -- cgit v1.2.3