[Nils Gura and Douglas Stebila (Sun Microsystems Laboratories)]
*) Add ECDH in new directory crypto/ecdh/.
-TODO: more general interface (return x coordinate, not its hash)
-TODO: bug: pad x with leading zeros if necessary
[Douglas Stebila (Sun Microsystems Laboratories)]
*) Let BN_rand_range() abort with an error after 100 iterations
#endif
}
+
+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 MAIN(int, char **);
int MAIN(int argc, char **argv)
}
else
{
- secret_size_a = ECDH_compute_key(secret_a,
+ secret_size_a = ECDH_compute_key(secret_a, KDF1_SHA1_len,
ecdh_b[j]->pub_key,
- ecdh_a[j]);
- secret_size_b = ECDH_compute_key(secret_b,
+ ecdh_a[j], KDF1_SHA1);
+ secret_size_b = ECDH_compute_key(secret_b, KDF1_SHA1_len,
ecdh_a[j]->pub_key,
- ecdh_b[j]);
+ ecdh_b[j], KDF1_SHA1);
if (secret_size_a != secret_size_b)
ecdh_checks = 0;
else
Time_F(START);
for (count=0,run=1; COND(ecdh_c[j][0]); count++)
{
- ECDH_compute_key(secret_a,
+ ECDH_compute_key(secret_a, KDF1_SHA1_len,
ecdh_b[j]->pub_key,
- ecdh_a[j]);
+ ecdh_a[j], KDF1_SHA1);
}
d=Time_F(STOP);
BIO_printf(bio_err, mr ? "+R7:%ld:%d:%.2f\n" :"%ld %d-bit ECDH ops in %.2fs\n",
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);
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);
#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
}
*
*/
/* ====================================================================
- * 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
#include <openssl/ec.h>
#include <openssl/objects.h>
#include <openssl/rand.h>
+#include <openssl/sha.h>
#include <openssl/err.h>
#ifdef OPENSSL_NO_ECDH
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)
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 =");
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 =");
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}
};
*
*/
/* ====================================================================
- * 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
#include "ecdh.h"
#include <openssl/engine.h>
-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);
}
*
*/
/* ====================================================================
- * 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
}
-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)
{
*
*/
/* ====================================================================
- * 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
*/
-#include "ecdh.h"
+#include <limits.h>
+
+#include <openssl/ecdh.h>
#include <openssl/err.h>
#include <openssl/sha.h>
#include <openssl/obj_mac.h>
-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",
/* 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);
}
}
- 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);
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * 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
return(ret);
}
+
+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
+ }
+
static int ssl3_send_client_key_exchange(SSL *s)
{
unsigned char *p,*d;
* make sure to clear it out afterwards
*/
- n=ECDH_compute_key(p, srvr_ecpoint, clnt_ecdh);
+ n=ECDH_compute_key(p, KDF1_SHA1_len, srvr_ecpoint, clnt_ecdh, KDF1_SHA1);
if (n <= 0)
{
SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
* [including the GNU Public Licence.]
*/
/* ====================================================================
- * 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
return(-1);
}
+
+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
+ }
+
static int ssl3_get_client_key_exchange(SSL *s)
{
int i,al,ok;
}
/* Compute the shared pre-master secret */
- i = ECDH_compute_key(p, clnt_ecpoint, srvr_ecdh);
+ i = ECDH_compute_key(p, KDF1_SHA1_len, clnt_ecpoint, srvr_ecdh, KDF1_SHA1);
if (i <= 0)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,