From cff0e4d6aab056211c93c5d33b5b5d0cc150ac62 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 13 Jul 2017 07:27:10 -0500 Subject: [PATCH] Incremental commit for secio fixes and connecting to swarms --- include/libp2p/conn/session.h | 9 ++- secio/secio.c | 148 +++++++++++++++++++++++----------- test/test_multistream.h | 2 +- test/test_secio.h | 127 +++++++++++++++++++++++++++-- test/testit.c | 2 + 5 files changed, 234 insertions(+), 54 deletions(-) diff --git a/include/libp2p/conn/session.h b/include/libp2p/conn/session.h index 69859f8..40ebc4f 100644 --- a/include/libp2p/conn/session.h +++ b/include/libp2p/conn/session.h @@ -29,6 +29,11 @@ struct SessionContext { size_t shared_key_size; unsigned char* mac; size_t mac_size; + // the following items carry state for the sha256 stream cipher. + size_t aes_encode_nonce_offset; + unsigned char aes_encode_stream_block[16]; + size_t aes_decode_nonce_offset; + unsigned char aes_decode_stream_block[16]; /** * The mac function to use * @param 1 the incoming data bytes @@ -38,11 +43,11 @@ struct SessionContext { */ int (*mac_function)(const unsigned char*, size_t, unsigned char*); // local only stuff - char local_nonce[16]; + unsigned char local_nonce[16]; struct EphemeralPrivateKey* ephemeral_private_key; struct StretchedKey* local_stretched_key; // remote stuff - char remote_nonce[16]; + unsigned char remote_nonce[16]; struct PublicKey remote_key; char* remote_peer_id; struct StretchedKey* remote_stretched_key; diff --git a/secio/secio.c b/secio/secio.c index eb6db66..d25a01f 100644 --- a/secio/secio.c +++ b/secio/secio.c @@ -22,6 +22,7 @@ #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/md_internal.h" +#include "mbedtls/aes.h" const char* SupportedExchanges = "P-256,P-384,P-521"; const char* SupportedCiphers = "AES-256,AES-128,Blowfish"; @@ -55,7 +56,7 @@ void libp2p_secio_secure_session_free(struct SessionContext* in) { * @param length the length of the nonce * @returns true(1) on success, otherwise false(0) */ -int libp2p_secio_generate_nonce(char* results, int length) { +int libp2p_secio_generate_nonce(unsigned char* results, int length) { FILE* fd = fopen("/dev/urandom", "r"); fread(results, 1, length, fd); fclose(fd); @@ -86,7 +87,7 @@ int libp2p_secio_hash(unsigned char* key, size_t key_size, unsigned char* nonce, * @param length the length of a and b * @returns a -1, 0, or 1 */ -int libp2p_secio_bytes_compare(const char* a, const char* b, int length) { +int libp2p_secio_bytes_compare(const unsigned char* a, const unsigned char* b, int length) { for(int i = 0; i < length; i++) { if (b[i] > a[i]) return -1; @@ -96,6 +97,20 @@ int libp2p_secio_bytes_compare(const char* a, const char* b, int length) { return 0; } +/*** + * Using values in the Propose struct, determine the order that will be used for the MACs + * @param remote the struct from the remote side + * @param local the struct from this side + * @returns -1 or 1 that will be used to determine who is first + */ +int libp2p_secio_determine_order(struct Propose*remote, struct Propose* local) { + unsigned char hash1[32]; + unsigned char hash2[32]; + libp2p_secio_hash(remote->public_key, remote->public_key_size, local->rand, local->rand_size, hash1); + libp2p_secio_hash(local->public_key, local->public_key_size, remote->rand, remote->rand_size, hash2); + return libp2p_secio_bytes_compare(hash1, hash2, 32); +} + int libp2p_secio_string_allocate(char* in, char** out) { *out = (char*)malloc(strlen(in) + 1); strcpy(*out, in); @@ -518,6 +533,19 @@ int libp2p_secio_unencrypted_read(struct SessionContext* session, unsigned char* return buffer_size; } +/** + * Initialize state for the sha256 stream cipher + * @param session the SessionContext struct that contains the variables to initialize + * @returns 1 + */ +int libp2p_secio_initialize_crypto(struct SessionContext* session) { + session->aes_decode_nonce_offset = 0; + session->aes_encode_nonce_offset = 0; + memset(session->aes_decode_stream_block, 0, 16); + memset(session->aes_encode_stream_block, 0, 16); + return 1; +} + /** * Encrypt data before being sent out an insecure stream * @param session the session information @@ -527,24 +555,33 @@ int libp2p_secio_unencrypted_read(struct SessionContext* session, unsigned char* * @param outgoing_size the amount of memory allocated * @returns true(1) on success, otherwise false(0) */ -int libp2p_secio_encrypt(const struct SessionContext* session, const unsigned char* incoming, size_t incoming_size, unsigned char** outgoing, size_t* outgoing_size) { +int libp2p_secio_encrypt(struct SessionContext* session, const unsigned char* incoming, size_t incoming_size, unsigned char** outgoing, size_t* outgoing_size) { unsigned char* buffer = NULL; size_t buffer_size = 0, original_buffer_size = 0; //TODO switch between ciphers - mbedtls_cipher_context_t cipher_ctx; - mbedtls_cipher_init(&cipher_ctx); - mbedtls_cipher_setup(&cipher_ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CTR)); - mbedtls_cipher_setkey(&cipher_ctx, session->local_stretched_key->cipher_key, session->local_stretched_key->cipher_size * 8, MBEDTLS_ENCRYPT); + mbedtls_aes_context cipher_ctx; + mbedtls_aes_init(&cipher_ctx); + if (mbedtls_aes_setkey_enc(&cipher_ctx, session->local_stretched_key->cipher_key, session->local_stretched_key->cipher_size * 8)) { + fprintf(stderr, "Unable to set key for cipher\n"); + return 0; + } + original_buffer_size = incoming_size; original_buffer_size += 32; buffer_size = original_buffer_size; buffer = malloc(original_buffer_size); memset(buffer, 0, original_buffer_size); - mbedtls_cipher_crypt(&cipher_ctx, session->local_stretched_key->iv, session->local_stretched_key->iv_size, incoming, incoming_size, buffer, &buffer_size); + + if (mbedtls_aes_crypt_ctr(&cipher_ctx, incoming_size, &session->aes_encode_nonce_offset, session->local_stretched_key->iv, session->aes_encode_stream_block, incoming, buffer)) { + fprintf(stderr, "Unable to update cipher\n"); + return 0; + } + buffer_size = incoming_size; + // Now, buffer size may be set differently than original_buffer_size // The "incoming" is now encrypted, and is in the first part of the buffer - mbedtls_cipher_free(&cipher_ctx); + mbedtls_aes_free(&cipher_ctx); // mac the data mbedtls_md_context_t ctx; @@ -593,11 +630,10 @@ int libp2p_secio_encrypted_write(void* stream_context, const unsigned char* byte * @param outgoing_size the amount of memory allocated for the results * @returns number of unencrypted bytes */ -int libp2p_secio_decrypt(const struct SessionContext* session, const unsigned char* incoming, size_t incoming_size, unsigned char** outgoing, size_t* outgoing_size) { +int libp2p_secio_decrypt(struct SessionContext* session, const unsigned char* incoming, size_t incoming_size, unsigned char** outgoing, size_t* outgoing_size) { size_t data_section_size = incoming_size - 32; *outgoing_size = 0; unsigned char* buffer; - size_t buffer_size; // verify MAC //TODO make this more generic to use more than SHA256 @@ -610,23 +646,33 @@ int libp2p_secio_decrypt(const struct SessionContext* session, const unsigned ch mbedtls_md_free(&ctx); // 2. check the mac to see if it is the same int retVal = memcmp(&incoming[data_section_size], generated_mac, 32); - // TODO: This MAC verification is failing. - if (retVal != 0) + if (retVal != 0) { + // MAC verification failed + libp2p_logger_error("secio", "libp2p_secio_decrypt: MAC verification failed"); return 0; + } - mbedtls_cipher_context_t cipher_ctx; - mbedtls_cipher_init(&cipher_ctx); - mbedtls_cipher_setup(&cipher_ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CTR)); - mbedtls_cipher_setkey(&cipher_ctx, session->remote_stretched_key->cipher_key, session->remote_stretched_key->cipher_size * 8, MBEDTLS_DECRYPT); - mbedtls_cipher_set_iv(&cipher_ctx, session->remote_stretched_key->iv, session->remote_stretched_key->iv_size); - buffer_size = data_section_size + mbedtls_cipher_get_block_size(&cipher_ctx); - buffer = malloc(buffer_size); - mbedtls_cipher_update(&cipher_ctx, incoming, data_section_size, buffer, &buffer_size); - mbedtls_cipher_free(&cipher_ctx); - *outgoing = malloc(buffer_size); - *outgoing_size = buffer_size; - memcpy(*outgoing, buffer, buffer_size); + // The MAC checks out. Now decipher the data section + + mbedtls_aes_context cipher_ctx; + mbedtls_aes_init(&cipher_ctx); + if (mbedtls_aes_setkey_enc(&cipher_ctx, session->remote_stretched_key->cipher_key, session->remote_stretched_key->cipher_size * 8)) { + fprintf(stderr, "Unable to set key for cipher\n"); + return 0; + } + + buffer = malloc(data_section_size); + if (mbedtls_aes_crypt_ctr(&cipher_ctx, data_section_size, &session->aes_decode_nonce_offset, session->remote_stretched_key->iv, session->aes_decode_stream_block, incoming, buffer)) { + fprintf(stderr, "Unable to update cipher\n"); + return 0; + } + + mbedtls_aes_free(&cipher_ctx); + *outgoing = malloc(data_section_size); + *outgoing_size = data_section_size; + memcpy(*outgoing, buffer, data_section_size); free(buffer); + return *outgoing_size; } @@ -673,8 +719,6 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva struct Propose* propose_out = NULL; struct Propose* propose_in = NULL; struct PublicKey* public_key = NULL; - unsigned char order_hash_in[32] = {0}; - unsigned char order_hash_out[32] = {0}; int order = 0;; struct Exchange* exchange_in = NULL; struct Exchange* exchange_out = NULL; @@ -696,7 +740,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva memcpy(total, protocol, protocol_len); memcpy(&total[protocol_len], propose_out_bytes, propose_out_size); - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing protocol"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing protocol\n"); bytes_written = libp2p_net_multistream_write(local_session, total, protocol_len + propose_out_size); free(total); if (bytes_written <= 0) @@ -704,7 +748,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva if (!remote_requested) { // we should get back the secio confirmation - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Reading protocol response"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Reading protocol response\n"); bytes_written = libp2p_net_multistream_read(local_session, &results, &results_size, 20); if (bytes_written < 5 || strstr((char*)results, "secio") == NULL) goto exit; @@ -760,13 +804,13 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva goto exit; - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing propose_out"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing propose_out\n"); bytes_written = libp2p_secio_unencrypted_write(local_session, propose_out_bytes, propose_out_size); if (bytes_written < propose_out_size) goto exit; // now receive the proposal from the new connection - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "receiving propose_in"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "receiving propose_in\n"); bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10); if (bytes_written <= 0) goto exit; @@ -786,9 +830,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva // negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work // first determine order - libp2p_secio_hash(propose_in->public_key, propose_in->public_key_size, propose_out->rand, propose_out->rand_size, order_hash_in); - libp2p_secio_hash(propose_out->public_key, propose_out->public_key_size, propose_in->rand, propose_in->rand_size, order_hash_out); - order = libp2p_secio_bytes_compare((char*)order_hash_in, (char*)order_hash_out, 32); + order = libp2p_secio_determine_order(propose_in, propose_out); // curve if (libp2p_secio_select_best(order, propose_out->exchanges, propose_out->exchanges_size, propose_in->exchanges, propose_in->exchanges_size, &local_session->chosen_curve) == 0) goto exit; @@ -840,7 +882,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva libp2p_secio_exchange_protobuf_encode(exchange_out, exchange_out_protobuf, exchange_out_protobuf_size, &bytes_written); exchange_out_protobuf_size = bytes_written; - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing exchange_out"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Writing exchange_out\n"); bytes_written = libp2p_secio_unencrypted_write(local_session, exchange_out_protobuf, exchange_out_protobuf_size); if (exchange_out_protobuf_size != bytes_written) goto exit; @@ -849,7 +891,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva // end of send Exchange packet // receive Exchange packet - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Reading exchagne packet"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Reading exchange packet\n"); bytes_written = libp2p_secio_unencrypted_read(local_session, &results, &results_size, 10); if (bytes_written == 0) goto exit; @@ -911,24 +953,38 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva libp2p_secio_make_mac_and_cipher(local_session, local_session->local_stretched_key); libp2p_secio_make_mac_and_cipher(local_session, local_session->remote_stretched_key); + // now we actually start encrypting things... + + libp2p_secio_initialize_crypto(local_session); + // send expected message (their nonce) to verify encryption works - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Sending their nonce"); - if (libp2p_secio_encrypted_write(local_session, (unsigned char*)local_session->remote_nonce, 16) <= 0) + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Sending their nonce\n"); + if (libp2p_secio_encrypted_write(local_session, (unsigned char*)local_session->remote_nonce, 16) <= 0) { + libp2p_logger_error("secio", "Encrytped write returned 0 or less.\n"); goto exit; + } // receive our nonce to verify encryption works - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Receiving our nonce"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Receiving our nonce\n"); int bytes_read = libp2p_secio_encrypted_read(local_session, &results, &results_size, 10); if (bytes_read <= 0) { - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Encrypted read returned %d", bytes_read); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Encrypted read returned %d\n", bytes_read); goto exit; } if (results_size != 16) { - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Results_size should be 16 but was %d", results_size); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Results_size should be 16 but was %d\n", results_size); goto exit; } - if (libp2p_secio_bytes_compare((char*)results, local_session->local_nonce, 16) != 0) { - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Bytes of nonce did not match"); + if (libp2p_secio_bytes_compare(results, (unsigned char*)local_session->local_nonce, 16) != 0) { + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Bytes of nonce did not match\n"); + // Debug JMJ + fprintf(stderr, "Expected: "); + for(int i = 0; i < 16; i++) + fprintf(stderr, "%03d ", local_session->local_nonce[i]); + fprintf(stderr, "\nActual : "); + for(int i = 0; i < 16; i++) + fprintf(stderr, "%03d ", results[i]); + fprintf(stderr, "\n"); goto exit; } @@ -941,7 +997,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva retVal = 1; - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete\n"); exit: if (propose_in_bytes != NULL) @@ -967,9 +1023,9 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva libp2p_secio_propose_free(propose_in); if (retVal == 1) { - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake success!"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake success!\n"); } else { - libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake returning false"); + libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake returning false\n"); } return retVal; } diff --git a/test/test_multistream.h b/test/test_multistream.h index 88d7245..641f0a9 100644 --- a/test/test_multistream.h +++ b/test/test_multistream.h @@ -35,7 +35,7 @@ int test_multistream_get_list() { char* filtered = NULL; struct SessionContext session; - session.insecure_stream = libp2p_net_multistream_connect("104.131.131.82", 4001); + session.insecure_stream = libp2p_net_multistream_connect("10.211.55.2", 4001); if (*((int*)session.insecure_stream->socket_descriptor) < 0) goto exit; diff --git a/test/test_secio.h b/test/test_secio.h index 1e83b53..dc6f636 100644 --- a/test/test_secio.h +++ b/test/test_secio.h @@ -6,14 +6,38 @@ #include "libp2p/net/p2pnet.h" #include "libp2p/utils/logger.h" +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/aes.h" + + +void print_stretched_key(struct StretchedKey* key) { + fprintf(stdout, "cipher key: "); + for(int i = 0; i < key->cipher_size; i++) { + fprintf(stdout, "%d ", key->cipher_key[i]); + } + fprintf(stdout, "\nIV: "); + for(int i = 0; i < key->iv_size; i++) { + fprintf(stdout, "%d ", key->iv[i]); + } + fprintf(stdout, "\nMAC: "); + for(int i = 0; i < key->mac_size; i++) { + fprintf(stdout, "%d ", key->mac_key[i]); + } +} + int test_secio_handshake() { + + libp2p_logger_add_class("secio"); + int retVal = 0; size_t decode_base64_size = 0; unsigned char* decode_base64 = NULL; // this is a base64 encoded private key. It makes it easier to test if it is in base64 form // these were pulled from the GO version of ipfs - char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQCo+BYd213u8PNHNcnXZ6TcUc7oXEoCtWL12XJEFqAiC7emadkp+WtujmuR993L6uCRPU/+mNXIvetodMQ5GORq0MxsPlKFNuVuqHS4PCdWYYFKeel4QsG17T3XMo72Kxm7/pQ1Dbs6tzWD4Ie4Zsa7ziyffjeak1/EExkFf0AKtj4UdXErNRI5gZhkDnWp6Si117Z2VVTslE+kKXWpLK0RYZ4w8DhhZa+ykt2tleOOJt8ocJ3s3yVZQxOafL1lwA8f10VEEeJLPGKJ1Y7mmW7OJhLmrq9tvdTLhum1H5kdYu/pheCm5b6/NSGKS+XbQztu5zedsKSPHsOlYhxYu3GJAgMBAAECggEAZIz93Fam14Jbw4ymyKDM4q9sSapiAKqgcV0tOoecU6ZVa5qhuPDMlcX7DapLOwZTDRtHd2LMFeGvLUIPY0sE4uvOOrv7r3qznd5xVxG09xqfLgrOfNp9HB5KJr3XhXawocclu0yolpBgMFJ1ca73pNtUgrVBsaLx4mTbBwJqwfQpQb/Xdkrdgc663bwXkSl4vApwhZGzi5CFJ6SFC6l6fMKoteWM1ay5e2VCfxi/1g41EINkrqm+QPWhy11bo21ScozxiFiywcxQ8Huo+I5GDHI5EUfIHP97NSRG24/IDSebxsGTukMdpLmiiwizV7hHP2eDlikHAhxBBAF2GkbkAQKBgQDg69jPHrETvHGlKjlEDE8sYQUrwpmGLHfsfZYqBxcz65jPYFAypG4icIU6f8Uhz9c42jLEBssNPT8LyLl2uY467hZZA2SkeWKS66Vi5wBGTN5qOBWUejhzTx8UzasYroWl/0RqFZhU9Xhwg4YqT9X8jYw5mXyOMLatp/d/Y96p0QKBgQDAUQodQZc9yc7olsmNvbuHZtBA+VndKCokFOuJ6YLRK69AL7y6n6eUjne6JqcEIKDC7vr33ryuOdFI+zNzMsdYykE8xcg2c5itWRqG7EdMxgR1dYLUqGC5ustRM/mmhmRzW8DXy88sS+vM4U84yPKv/rfeKAoYgE722R0kkpQCOQKBgQCKfm63yiw6/NP1YXR1hCbUKsFmWqLxzTvisMngAxG0dKNZPfLj2/+80RAYH0ihMztQ1Hph3dT1x/qkJOqeQk9j1eqI0OANrniWAueJaLfwkbB6MyKGlGNiDRwUUTfDMOM2fWIA+F8eITASB8p7D0GyCu6HIQ1i+HfjogNxu2sFoQKBgE4ZGthiqH6JE6NUiKks4ZjM4clg+WNcSjC45iXtVBiJevO/7w6Cg1VKvcg0piKA9Yfz8Kr0Iv9Fr33JtU0U0+t0xyVc1D94lgnfY2xjS1kcGPdyLx0Y+56xApwJVVqQvP4zxo5bz9gXRLzAyqEuyY87C4QGEoN8p5SK+tC9TanRAoGAbC+uVaBtqRqv3LY16+H58BW8lVfN+8dqtBOWluM2uImB1qL2EbKk0X/OChz3Dgzef5VTox6nHcMyYPwXLirS9aIYPggjdpDTjfbWPxUcwYmIB1U++F/mRk1IeDgl9g7t/OlPMg4snxQGEzMPPDVrj/KeLEKv5x+T5yFZ/y+8xNo="; - char* orig_peer_id = "QmZigcoDKaAafGSwot2tchJarCafxKapoRmnYTrZ69ckjb"; + char* orig_priv_key = "CAASqQkwggSlAgEAAoIBAQCuW+8vGUb2n4xOcfPZLmfVAy6GNJ0sYrD/hVXwxBU1aBas+8lfAuLwYJXPCVBg65wZWYEbbWCevLFjwB/oZyJA1J1g+HohggH8QvuDH164FtSbgyHFip2SPR7oUHgSWRqfKXRJsVW/SPCfEt59S8JH99Q747dU9fvZKpelE9aDLf5yI8nj29TDy3c1RpkxfUwfgnbeoCwsDnakFmVdoSEp3Lnt3JlI05qE0bgvkWAaelcXSNQCmZzDwXeMk9y221FnBkL4Vs3v2lKmjLx+Qr37P/t78T+VxsjnGHPhbZTIMIjwwON6568d0j25Bj9v6biiz8iXzBR4Fmz1CQ0mqU5BAgMBAAECggEAc6EYX/29Z/SrEaLUeiUiSsuPYQUnbrYMd4gvVDpVblOXJiTciJvbcFo9P04H9h6KKO2Ih23j86FjaqmQ/4jV2HSn4hUmuW4EbwzkyzJUmHTbjj5KeTzR/pd2Fc63skNROlg9fFmUagSvPm8/CYziTOP35bfAbyGqYXyzkJA1ZExVVSOi1zGVi+lnlI1fU2Aki5F7W7F/d2AQWsh7NXUwT7e6JP7TL+Gn4bWdn3NvluwAWTMgp6/It8OU1XPgu8OhdpZQWsMBqJwr79KGLbq2SZZXAw8O+ay1JQYmmmvYzwhdDgJwl+MOtf3NiqQWFzZP8RnlHGNcXlLHHPW0FB9H+QKBgQDirtBOqjCtND6m4hEfy6A24GcITYUBg1+AYQ7uM5uZl5u9AyxfG4bPxyrspz3yS0DOV4HNQ88iwmUE8+8ZHCLSY/YIp73Nk4m8t2s46CuI7Y5GrwCnh9xTMwaUrNx4IRTWyR3OxjQtUyrXtPR6uJ83FDenXvNi//Mrzp+myxX4wwKBgQDE6L8qiVA6n9k5dyUxxMUKJqynwPcBeC+wI85gr/9wwlRYDrgMYeH6/D5prZ3N5m8+zugVQQJKLfXBG0i8BRh5xLYFCZnV2O3NwvCdENlZJZrNNoz9jM3yRV+c7OdrclxDiN0bjGEBWv8GHutNFAwuUfMe0TMdfFYpM7gBHjEMqwKBgQCWHwOhNSCrdDARwSFqFyZxcUeKvhvZlrFGigCjS9Y+b6MaF+Ho0ogDTnlk5JUnwyKWBGnYEJI7CNZx40JzNKjzAHRN4xjV7mGHc0k1FLzQH9LbiMY8LMOC7gXrrFcNz4rHe8WbzLN9WNjEpfhK1b3Lcj4xP7ab17mpR1t/0HsqlQKBgQC3S6lYIUZLrCz7b0tyTqbU0jd6WQgVmBlcL5iXLH3uKxd0eQ8eh6diiZhXq0PwPQdlQhmMX12QS8QupAVK8Ltd7p05hzxqcmq7VTHCI8MPVxAI4zTPeVjko2tjmqu5u1TjkO2yDTTnnBs1SWbj8zt7itFz6G1ajzltVTV95OrnzQKBgQDEwZxnJA2vDJEDaJ82CiMiUAFzwsoK8hDvz63kOKeEW3/yESySnUbzpxDEjzYNsK74VaXHKCGI40fDRUqZxU/+qCrFf3xDfYS4r4wfFd2Jh+tn4NzSV/EhIr9KR/ZJW+TvGks+pWUJ3mhjPEvNtlt3M64/j2D0RP2aBQtoSpeezQ=="; + char* orig_peer_id = "QmRKm1d9kSCRpMFtLYpfhhCQ3DKuSSPJa3qn9wWXfwnWnY"; size_t orig_peer_id_size = strlen(orig_peer_id); struct RsaPrivateKey* rsa_private_key = NULL; unsigned char hashed[32] = {0}; @@ -44,8 +68,8 @@ int test_secio_handshake() { if (!libp2p_crypto_rsa_private_key_fill_public_key(rsa_private_key)) goto exit; - secure_session.host = "www.jmjatlanta.com"; - //secure_session.host = "127.0.0.1"; + //secure_session.host = "www.jmjatlanta.com"; + secure_session.host = "10.211.55.2"; secure_session.port = 4001; secure_session.traffic_type = TCP; // connect to host @@ -55,12 +79,40 @@ int test_secio_handshake() { goto exit; } - if (!libp2p_secio_handshake(&secure_session, rsa_private_key, 0)) { + /* + fprintf(stdout, "Shared key: "); + for(int i = 0; i < secure_session.shared_key_size; i++) + fprintf(stdout, "%d ", secure_session.shared_key[i]); + fprintf(stdout, "\nLocal stretched key: "); + print_stretched_key(secure_session.local_stretched_key); + fprintf(stdout, "\nRemote stretched key: "); + print_stretched_key(secure_session.remote_stretched_key); + fprintf(stdout, "\n"); + */ fprintf(stderr, "test_secio_handshake: Unable to do handshake\n"); goto exit; } + fprintf(stdout, "Shared key: "); + for(int i = 0; i < secure_session.shared_key_size; i++) + fprintf(stdout, "%d ", secure_session.shared_key[i]); + fprintf(stdout, "\nLocal stretched key: "); + print_stretched_key(secure_session.local_stretched_key); + fprintf(stdout, "\nRemote stretched key: "); + print_stretched_key(secure_session.remote_stretched_key); + fprintf(stdout, "\n"); + + // now attempt to do something with it... + secure_session.secure_stream->write(&secure_session, "/multistream/1.0.0\n", 3); + unsigned char* results; + size_t results_size; + secure_session.secure_stream->read(&secure_session, &results, &results_size, 10); + fprintf(stdout, "test_secio_handshake: Results from multistream: Size: %lu string: %s", results_size, results); + for(int i = 0; i < results_size; i++) + fprintf(stdout, "%d ", results[i]); + fprintf(stdout, "\n"); + retVal = 1; exit: if (secure_session.insecure_stream != NULL) @@ -174,3 +226,68 @@ int test_secio_exchange_protobuf_encode() { libp2p_secio_exchange_free(exch); return retVal; } + + +int test_secio_encrypt_like_go() { + // GO version keys: + // local keys + unsigned char keyIv[] = { 233, 20, 188, 79, 55, 204, 132, 231, 82, 167, 63, 211, 74, 253, 20, 109 }; + unsigned char keyMac[] = { 224, 94, 119, 190, 68, 213, 247, 204, 211, 25, 42, 154, 145, 96, 86, 8, 103, 187, 133, 15 }; + unsigned char keyCipher[] = { 137, 132, 0, 154, 131, 200, 29, 70, 88, 158, 170, 177, 220, 101, 113, 212, 98, 180, 25, 96, 15, 208, 210, 204, 167, 161, 238, 207, 229, 69, 83, 29 }; + + // with the above keys, the "nonce" below should give the expected result + unsigned char nonce_string[] = { 253, 17, 36, 85, 95, 130, 6, 14, 184, 204, 131, 114, 143, 245, 74, 51 }; + unsigned char expected_nonce[] = { 71, 244, 156, 168, 60, 181, 227, 199, 116, 155, 82, 29, 7, 237, 234, 27 }; + int incoming_size = 16; + + size_t result_size = 255; + unsigned char result[result_size]; + memset(result, 0, result_size); + + // do nonce + mbedtls_aes_context cipher_ctx; + mbedtls_aes_init(&cipher_ctx); + if (mbedtls_aes_setkey_enc(&cipher_ctx, keyCipher, 32 * 8)) { + fprintf(stderr, "Unable to set key for cipher\n"); + return 0; + } + + size_t nonce_offset = 0; + unsigned char stream_block[16]; + memset(stream_block, 0, 16); + if (mbedtls_aes_crypt_ctr(&cipher_ctx, incoming_size, &nonce_offset, keyIv, stream_block, nonce_string, result)) { + fprintf(stderr, "Unable to update cipher\n"); + return 0; + } + + // do comparison + for(int i = 0; i < incoming_size; i++) { + if (result[i] != expected_nonce[i]) { + fprintf(stderr, "Nonce: At position %d expected %u but got %u\n", i, expected_nonce[i], result[i]); + return 0; + } + } + + // now try multistream + result_size = 255; + memset(result, 0, result_size); + unsigned char multistream_string[] = { 19, 47, 109, 117, 108, 116, 105, 115, 116, 114, 101, 97, 109, 47, 49, 46, 48, 46, 48, 10 }; + unsigned char expected_multistream[] = { 105, 218, 190, 138, 115, 254, 188, 113, 192, 128, 162, 148, 118, 164, 178, 140, 239, 185, 53, 17 }; + incoming_size = 20; + + if (mbedtls_aes_crypt_ctr(&cipher_ctx, incoming_size, &nonce_offset, keyIv, stream_block, multistream_string, result)) { + fprintf(stderr, "Unable to update cipher\n"); + return 0; + } + mbedtls_aes_free(&cipher_ctx); + + // do comparison + for(int i = 0; i < incoming_size; i++) { + if (result[i] != expected_multistream[i]) { + fprintf(stderr, "Multistream: At position %d expected %d but got %d\n", i, expected_multistream[i], result[i]); + return 0; + } + } + + return 1; +} diff --git a/test/testit.c b/test/testit.c index f413145..4587ee9 100644 --- a/test/testit.c +++ b/test/testit.c @@ -41,6 +41,7 @@ const char* names[] = { "test_secio_handshake", "test_secio_encrypt_decrypt", "test_secio_exchange_protobuf_encode", + "test_secio_encrypt_like_go", "test_multistream_connect", "test_multistream_get_list", "test_ephemeral_key_generate", @@ -84,6 +85,7 @@ int (*funcs[])(void) = { test_secio_handshake, test_secio_encrypt_decrypt, test_secio_exchange_protobuf_encode, + test_secio_encrypt_like_go, test_multistream_connect, test_multistream_get_list, test_ephemeral_key_generate,