From 44b4efe34d4f6bd6a39703c065a075cb9ddb4656 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 5 May 2003 04:27:00 +0000 Subject: [PATCH] Tests, headers, and debugging for onion skin backend svn:r263 --- src/or/onion.c | 51 +++++++++++++++++++++++++++++++++++++++++--------- src/or/or.h | 15 +++++++++++++++ src/or/test.c | 44 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 100 insertions(+), 10 deletions(-) diff --git a/src/or/onion.c b/src/or/onion.c index 87c42ee2fc..35343ea1b1 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -855,7 +855,7 @@ onion_skin_create(crypto_pk_env_t *router_key, *handshake_state_out = NULL; memset(onion_skin_out, 0, 208); - memset(iv, 0, 16); /* XXXX This can't be safe, can it? */ + memset(iv, 0, 16); if (!(dh = crypto_dh_new())) goto err; @@ -863,29 +863,51 @@ onion_skin_create(crypto_pk_env_t *router_key, dhbytes = crypto_dh_get_bytes(dh); pkbytes = crypto_pk_keysize(router_key); assert(dhbytes+16 == 208); - if (!(pubkey = malloc(dhbytes))) + if (!(pubkey = malloc(dhbytes+16))) goto err; if (crypto_rand(16, pubkey)) goto err; + + /* XXXX You can't just run around RSA-encrypting any bitstream: if it's + * greater than the RSA key, then OpenSSL will happily encrypt, + * and later decrypt to the wrong value. So we set the first bit + * of 'pubkey' to 0. This means that our symmetric key is really only + * 127 bits long, but since it shouldn't be necessary to encrypt + * DH public keys values in the first place, we should be fine. + */ + pubkey[0] &= 0x7f; 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; +#if 0 + printf("Client DH sent: %x %x %x ... %x %x %x\n", + (int) pubkey[16], (int) pubkey[17], (int) pubkey[18], + (int) pubkey[205], (int) pubkey[206], (int) pubkey[207]); + + printf("Client key sent: %x %x %x ... %x %x %x\n", + pubkey[0],pubkey[1],pubkey[2], + pubkey[13],pubkey[14],pubkey[15]); +#endif cipher = crypto_create_init_cipher(CRYPTO_CIPHER_3DES, pubkey, iv, 1); - - if (crypto_cipher_encrypt(cipher, pubkey+pkbytes, dhbytes-16-pkbytes, + + if (!cipher) + goto err; + + if (crypto_pk_public_encrypt(router_key, pubkey, pkbytes, + onion_skin_out, RSA_NO_PADDING)==-1) + goto err; + + 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); @@ -916,14 +938,25 @@ onion_skin_server_handshake(char *onion_skin, /* 208 bytes long */ if (crypto_pk_private_decrypt(private_key, onion_skin, pkbytes, - buf, RSA_NO_PADDING)) + buf, RSA_NO_PADDING) == -1) goto err; + +#if 0 + printf("Client key got: %x %x %x ... %x %x %x\n", + buf[0],buf[1],buf[2], buf[13],buf[14],buf[15]); +#endif 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; + +#if 0 + printf("Client DH got: %x %x %x ... %x %x %x\n", + (int) buf[16], (int) buf[17], (int) buf[18], + (int) buf[205], (int) buf[206], (int) buf[207]); +#endif dh = crypto_dh_new(); if (crypto_dh_get_public(dh, handshake_reply_out, 192)) diff --git a/src/or/or.h b/src/or/or.h index 3dab7ad9f1..b2079af31a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -793,6 +793,21 @@ void init_tracked_tree(void); void onion_pack(char *dest, onion_layer_t *src); void onion_unpack(onion_layer_t *dest, char *src); +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 */ + +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); + +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); + /********************************* routers.c ***************************/ int learn_my_address(struct sockaddr_in *me); diff --git a/src/or/test.c b/src/or/test.c index 1bcec568ba..0d77b601af 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -460,6 +460,46 @@ test_util() { } +void +test_onion_handshake() { + int i; + + /* client-side */ + crypto_dh_env_t *c_dh = NULL; + char c_buf[208]; + char c_keys[40]; + + /* server-side */ + char s_buf[192]; + char s_keys[40]; + + /* shared */ + crypto_pk_env_t *pk = NULL; + + pk = crypto_new_pk_env(CRYPTO_PK_RSA); + test_assert(! crypto_pk_generate_key(pk)); + + /* client handshake 1. */ + memset(c_buf, 0, 208); + test_assert(! onion_skin_create(pk, &c_dh, c_buf)); + + /* server handshake */ + memset(s_buf, 0, 192); + memset(s_keys, 0, 40); + test_assert(! onion_skin_server_handshake(c_buf, pk, s_buf, s_keys, 40)); + + /* client handshake 2 */ + memset(c_keys, 0, 40); + test_assert(! onion_skin_client_handshake(c_dh, s_buf, c_keys, 40)); + + crypto_dh_free(c_dh); + crypto_free_pk_env(pk); + + test_memeq(c_keys, s_keys, 40); + memset(s_buf, 0, 40); + test_memneq(c_keys, s_buf, 40); +} + int main(int c, char**v) { #if 0 @@ -476,8 +516,10 @@ main(int c, char**v) { puts("========================== Crypto =========================="); test_crypto_dh(); test_crypto(); - puts("\n========================== Util ============================"); + puts("\n========================= Util ============================"); test_util(); + puts("\n========================= Onion Skins======================"); + test_onion_handshake(); puts(""); return 0; }