Extract the shared part of crypto_dh_compute_secret.

This commit is contained in:
Nick Mathewson 2018-07-17 09:16:11 -04:00
parent 60a5b78480
commit ac9a470c64
3 changed files with 66 additions and 22 deletions

View File

@ -42,3 +42,50 @@ const char OAKLEY_PRIME_2[] =
"302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
"A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
"49286651ECE65381FFFFFFFFFFFFFFFF"; "49286651ECE65381FFFFFFFFFFFFFFFF";
/** Given a DH key exchange object, and our peer's value of g^y (as a
* <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
* <b>secret_bytes_out</b> bytes of shared key material and write them
* to <b>secret_out</b>. Return the number of bytes generated on success,
* or -1 on failure.
*
* (We generate key material by computing
* SHA1( g^xy || "\x00" ) || SHA1( g^xy || "\x01" ) || ...
* where || is concatenation.)
*/
ssize_t
crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len,
char *secret_out, size_t secret_bytes_out)
{
tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
unsigned char *secret_tmp = NULL;
size_t secret_len=0, secret_tmp_len=0;
secret_tmp_len = crypto_dh_get_bytes(dh);
secret_tmp = tor_malloc(secret_tmp_len);
ssize_t result = crypto_dh_handshake(severity, dh, pubkey, pubkey_len,
secret_tmp, secret_tmp_len);
if (result < 0)
goto error;
secret_len = result;
if (crypto_expand_key_material_TAP(secret_tmp, secret_len,
(uint8_t*)secret_out, secret_bytes_out)<0)
goto error;
secret_len = secret_bytes_out;
goto done;
error:
result = -1;
done:
if (secret_tmp) {
memwipe(secret_tmp, 0, secret_tmp_len);
tor_free(secret_tmp);
}
if (result < 0)
return result;
else
return secret_len;
}

View File

@ -40,7 +40,11 @@ ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
void crypto_dh_free_(crypto_dh_t *dh); void crypto_dh_free_(crypto_dh_t *dh);
#define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh)) #define crypto_dh_free(dh) FREE_AND_NULL(crypto_dh_t, crypto_dh_free_, (dh))
/* Crypto DH free */ ssize_t crypto_dh_handshake(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len,
unsigned char *secret_out,
size_t secret_bytes_out);
void crypto_dh_free_all(void); void crypto_dh_free_all(void);
/* Prototypes for private functions only used by tortls.c, crypto.c, and the /* Prototypes for private functions only used by tortls.c, crypto.c, and the
@ -48,4 +52,5 @@ void crypto_dh_free_all(void);
struct dh_st; struct dh_st;
struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh); struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
#endif /* !defined(TOR_CRYPTO_DH_H) */ #endif /* !defined(TOR_CRYPTO_DH_H) */

View File

@ -405,27 +405,29 @@ tor_check_dh_key(int severity, const BIGNUM *bn)
/** Given a DH key exchange object, and our peer's value of g^y (as a /** Given a DH key exchange object, and our peer's value of g^y (as a
* <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate * <b>pubkey_len</b>-byte value in <b>pubkey</b>) generate
* <b>secret_bytes_out</b> bytes of shared key material and write them * g^xy as a big-endian integer in <b>secret_out</b>.
* to <b>secret_out</b>. Return the number of bytes generated on success, * Return the number of bytes generated on success,
* or -1 on failure. * or -1 on failure.
* *
* (We generate key material by computing * This function MUST validate that g^y is actually in the group.
* SHA1( g^xy || "\x00" ) || SHA1( g^xy || "\x01" ) || ...
* where || is concatenation.)
*/ */
ssize_t ssize_t
crypto_dh_compute_secret(int severity, crypto_dh_t *dh, crypto_dh_handshake(int severity, crypto_dh_t *dh,
const char *pubkey, size_t pubkey_len, const char *pubkey, size_t pubkey_len,
char *secret_out, size_t secret_bytes_out) unsigned char *secret_out, size_t secret_bytes_out)
{ {
char *secret_tmp = NULL;
BIGNUM *pubkey_bn = NULL; BIGNUM *pubkey_bn = NULL;
size_t secret_len=0, secret_tmp_len=0; size_t secret_len=0;
int result=0; int result=0;
tor_assert(dh); tor_assert(dh);
tor_assert(secret_bytes_out/DIGEST_LEN <= 255); tor_assert(secret_bytes_out/DIGEST_LEN <= 255);
tor_assert(pubkey_len < INT_MAX); tor_assert(pubkey_len < INT_MAX);
if (BUG(crypto_dh_get_bytes(dh) > (int)secret_bytes_out)) {
goto error;
}
if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey, if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey,
(int)pubkey_len, NULL))) (int)pubkey_len, NULL)))
goto error; goto error;
@ -434,18 +436,12 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
log_fn(severity, LD_CRYPTO,"Rejected invalid g^x"); log_fn(severity, LD_CRYPTO,"Rejected invalid g^x");
goto error; goto error;
} }
secret_tmp_len = crypto_dh_get_bytes(dh); result = DH_compute_key(secret_out, pubkey_bn, dh->dh);
secret_tmp = tor_malloc(secret_tmp_len);
result = DH_compute_key((unsigned char*)secret_tmp, pubkey_bn, dh->dh);
if (result < 0) { if (result < 0) {
log_warn(LD_CRYPTO,"DH_compute_key() failed."); log_warn(LD_CRYPTO,"DH_compute_key() failed.");
goto error; goto error;
} }
secret_len = result; secret_len = result;
if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len,
(uint8_t*)secret_out, secret_bytes_out)<0)
goto error;
secret_len = secret_bytes_out;
goto done; goto done;
error: error:
@ -454,10 +450,6 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh,
crypto_openssl_log_errors(LOG_WARN, "completing DH handshake"); crypto_openssl_log_errors(LOG_WARN, "completing DH handshake");
if (pubkey_bn) if (pubkey_bn)
BN_clear_free(pubkey_bn); BN_clear_free(pubkey_bn);
if (secret_tmp) {
memwipe(secret_tmp, 0, secret_tmp_len);
tor_free(secret_tmp);
}
if (result < 0) if (result < 0)
return result; return result;
else else