diff options
author | Nick Mathewson <nickm@torproject.org> | 2003-07-30 19:10:20 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2003-07-30 19:10:20 +0000 |
commit | f12fdd62aa9ac5561dc2133a2110c3f9dd42900c (patch) | |
tree | bf5ea7c1cea4a6a8e777418baac60915ea30fb2f /src/common | |
parent | ab0f263fb95d2c79fa0b245b854c507d9df81a1e (diff) | |
download | tor-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.c | 37 | ||||
-rw-r--r-- | src/common/crypto.h | 2 |
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 */ |