mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-20 10:12:15 +01:00
Implement core of onion-skin-based handshake
svn:r259
This commit is contained in:
parent
0560008497
commit
1eeb3f65fc
141
src/or/onion.c
141
src/or/onion.c
@ -833,6 +833,147 @@ onion_unpack(onion_layer_t *dest, char *src)
|
|||||||
inet_ntoa(*((struct in_addr *)(src+3))), dest->expire);
|
inet_ntoa(*((struct in_addr *)(src+3))), dest->expire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Given a router's public key, generates a 208-byte encrypted DH pubkey,
|
||||||
|
* and stores it into onion_skin out. Stores the DH private key into
|
||||||
|
* handshake_state_out for later completion of the handshake.
|
||||||
|
*
|
||||||
|
* The encrypted pubkey is formed as follows:
|
||||||
|
* 16 bytes of symmetric key
|
||||||
|
* 192 bytes of g^x for DH.
|
||||||
|
* The first 128 bytes are RSA-encrypted with the server's public key,
|
||||||
|
* and the last 80 are encrypted with the symmetric key.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
onion_skin_create(crypto_pk_env_t *router_key,
|
||||||
|
crypto_dh_env_t **handshake_state_out,
|
||||||
|
char *onion_skin_out) /* Must be 208 bytes long */
|
||||||
|
{
|
||||||
|
char iv[16];
|
||||||
|
char *pubkey = NULL;
|
||||||
|
crypto_dh_env_t *dh = NULL;
|
||||||
|
crypto_cipher_env_t *cipher = NULL;
|
||||||
|
int dhbytes, pkbytes;
|
||||||
|
|
||||||
|
*handshake_state_out = NULL;
|
||||||
|
memset(onion_skin_out, 0, 208);
|
||||||
|
memset(iv, 0, 16); /* XXXX This can't be safe, can it? */
|
||||||
|
|
||||||
|
if (!(dh = crypto_dh_new()))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
dhbytes = crypto_dh_get_bytes(dh);
|
||||||
|
pkbytes = crypto_pk_keysize(router_key);
|
||||||
|
assert(dhbytes+16 == 208);
|
||||||
|
if (!(pubkey = malloc(dhbytes)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (crypto_rand(16, pubkey))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (crypto_dh_get_public(dh, pubkey+16, dhbytes))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (crypto_pk_public_encrypt(router_key, pubkey, pkbytes,
|
||||||
|
onion_skin_out, RSA_NO_PADDING))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cipher = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, pubkey, iv, 1);
|
||||||
|
|
||||||
|
if (crypto_cipher_encrypt(cipher, pubkey+pkbytes, dhbytes-16-pkbytes,
|
||||||
|
onion_skin_out+pkbytes))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
free(pubkey);
|
||||||
|
crypto_free_cipher_env(cipher);
|
||||||
|
*handshake_state_out = dh;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
if (pubkey) free(pubkey);
|
||||||
|
if (dh) crypto_dh_free(dh);
|
||||||
|
if (cipher) crypto_free_cipher_env(cipher);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given an encrypted DH public key as generated by onion_skin_create,
|
||||||
|
* and the private key for this onion router, generate the 192-byte DH
|
||||||
|
* reply, and key_out_len bytes of key material, stored in key_out.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
onion_skin_server_handshake(char *onion_skin, /* 208 bytes long */
|
||||||
|
crypto_pk_env_t *private_key,
|
||||||
|
char *handshake_reply_out, /* 192 bytes long */
|
||||||
|
char *key_out,
|
||||||
|
int key_out_len)
|
||||||
|
{
|
||||||
|
char buf[208];
|
||||||
|
char iv[16];
|
||||||
|
crypto_dh_env_t *dh = NULL;
|
||||||
|
crypto_cipher_env_t *cipher = NULL;
|
||||||
|
int pkbytes;
|
||||||
|
|
||||||
|
memset(iv, 0, 16);
|
||||||
|
pkbytes = crypto_pk_keysize(private_key);
|
||||||
|
|
||||||
|
if (crypto_pk_private_decrypt(private_key,
|
||||||
|
onion_skin, pkbytes,
|
||||||
|
buf, RSA_NO_PADDING))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cipher = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, buf, iv, 0);
|
||||||
|
|
||||||
|
if (crypto_cipher_decrypt(cipher, onion_skin+pkbytes, 208-pkbytes,
|
||||||
|
buf+pkbytes))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
dh = crypto_dh_new();
|
||||||
|
if (crypto_dh_get_public(dh, handshake_reply_out, 192))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (crypto_dh_compute_secret(dh, buf+16, 192, buf))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
memcpy(key_out, buf+192-key_out_len, key_out_len);
|
||||||
|
|
||||||
|
crypto_free_cipher_env(cipher);
|
||||||
|
crypto_dh_free(dh);
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
if (cipher) crypto_free_cipher_env(cipher);
|
||||||
|
if (dh) crypto_dh_free(dh);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finish the client side of the DH handshake.
|
||||||
|
* Given the 192 byte DH reply as generated by onion_skin_server_handshake
|
||||||
|
* and the handshake state generated by onion_skin_create, generate
|
||||||
|
* key_out_len bytes of shared key material and store them in key_out.
|
||||||
|
*
|
||||||
|
* After the invocation, call crypto_dh_free on handshake_state.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
||||||
|
char *handshake_reply,/* Must be 192 bytes long*/
|
||||||
|
char *key_out,
|
||||||
|
int key_out_len)
|
||||||
|
{
|
||||||
|
char key_material[192];
|
||||||
|
assert(crypto_dh_get_bytes(handshake_state) == 192);
|
||||||
|
|
||||||
|
memset(key_material, 0, 192);
|
||||||
|
|
||||||
|
if (crypto_dh_compute_secret(handshake_state, handshake_reply, 192,
|
||||||
|
key_material))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(key_out, key_material+192-key_out_len, key_out_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Local Variables:
|
Local Variables:
|
||||||
mode:c
|
mode:c
|
||||||
|
@ -475,7 +475,7 @@ main(int c, char**v) {
|
|||||||
test_buffers();
|
test_buffers();
|
||||||
puts("========================== Crypto ==========================");
|
puts("========================== Crypto ==========================");
|
||||||
test_crypto_dh();
|
test_crypto_dh();
|
||||||
test_crypto(); /* this seg faults :( */
|
test_crypto(); /* this seg faults :( */ /* Still? -NM 2003/04/30 */
|
||||||
puts("\n========================== Util ============================");
|
puts("\n========================== Util ============================");
|
||||||
test_util();
|
test_util();
|
||||||
puts("");
|
puts("");
|
||||||
|
Loading…
Reference in New Issue
Block a user