aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2003-07-30 19:10:20 +0000
committerNick Mathewson <nickm@torproject.org>2003-07-30 19:10:20 +0000
commitf12fdd62aa9ac5561dc2133a2110c3f9dd42900c (patch)
treebf5ea7c1cea4a6a8e777418baac60915ea30fb2f /src/common
parentab0f263fb95d2c79fa0b245b854c507d9df81a1e (diff)
downloadtor-f12fdd62aa9ac5561dc2133a2110c3f9dd42900c.tar
tor-f12fdd62aa9ac5561dc2133a2110c3f9dd42900c.tar.gz
Be smarter about getting key matter from DH.
Formerly, once we had g^xy, we took the last N bytes from g^xy. Now, we take SHA(g^xy || [0]) || SHA1(g^xy || [1]) || ... , in order to use all bits from g^xy equally, and generate as much key material as we need. svn:r370
Diffstat (limited to 'src/common')
-rw-r--r--src/common/crypto.c37
-rw-r--r--src/common/crypto.h2
2 files changed, 29 insertions, 10 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 5365502fd..130ecac85 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -798,22 +798,41 @@ int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey, int pubkey_len)
return 0;
}
+
+#undef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
int crypto_dh_compute_secret(crypto_dh_env_t *dh,
char *pubkey, int pubkey_len,
- char *secret_out)
+ char *secret_out, int secret_bytes_out)
{
- BIGNUM *pubkey_bn;
+ unsigned char hash[20];
+ unsigned char *secret_tmp = NULL;
+ BIGNUM *pubkey_bn = NULL;
int secret_len;
+ int i;
assert(dh);
-
+ assert(secret_bytes_out/20 <= 255);
+
if (!(pubkey_bn = BN_bin2bn(pubkey, pubkey_len, NULL)))
- return -1;
-
- secret_len = DH_compute_key(secret_out, pubkey_bn, dh->dh);
- BN_free(pubkey_bn);
- if (secret_len == -1)
- return -1;
+ goto error;
+ secret_tmp = tor_malloc(crypto_dh_get_bytes(dh)+1);
+ secret_len = DH_compute_key(secret_tmp, pubkey_bn, dh->dh);
+ for (i = 0; i < secret_bytes_out; i += 20) {
+ secret_tmp[secret_len] = (unsigned char) i/20;
+ if (crypto_SHA_digest(secret_tmp, secret_len+1, hash))
+ goto error;
+ memcpy(secret_out+i, hash, MIN(20, secret_bytes_out-i));
+ }
+ secret_len = secret_bytes_out;
+ goto done;
+ error:
+ secret_len = -1;
+ done:
+ if (pubkey_bn)
+ BN_free(pubkey_bn);
+ if (secret_tmp)
+ free(secret_tmp);
return secret_len;
}
void crypto_dh_free(crypto_dh_env_t *dh)
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 50b2c9540..181101b59 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -81,7 +81,7 @@ int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey_out,
int pubkey_out_len);
int crypto_dh_compute_secret(crypto_dh_env_t *dh,
char *pubkey, int pubkey_len,
- char *secret_out);
+ char *secret_out, int secret_out_len);
void crypto_dh_free(crypto_dh_env_t *dh);
/* symmetric crypto */