Incremental commit for secio fixes and connecting to swarms
This commit is contained in:
parent
e32837031f
commit
cff0e4d6aa
5 changed files with 234 additions and 54 deletions
|
@ -29,6 +29,11 @@ struct SessionContext {
|
||||||
size_t shared_key_size;
|
size_t shared_key_size;
|
||||||
unsigned char* mac;
|
unsigned char* mac;
|
||||||
size_t mac_size;
|
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
|
* The mac function to use
|
||||||
* @param 1 the incoming data bytes
|
* @param 1 the incoming data bytes
|
||||||
|
@ -38,11 +43,11 @@ struct SessionContext {
|
||||||
*/
|
*/
|
||||||
int (*mac_function)(const unsigned char*, size_t, unsigned char*);
|
int (*mac_function)(const unsigned char*, size_t, unsigned char*);
|
||||||
// local only stuff
|
// local only stuff
|
||||||
char local_nonce[16];
|
unsigned char local_nonce[16];
|
||||||
struct EphemeralPrivateKey* ephemeral_private_key;
|
struct EphemeralPrivateKey* ephemeral_private_key;
|
||||||
struct StretchedKey* local_stretched_key;
|
struct StretchedKey* local_stretched_key;
|
||||||
// remote stuff
|
// remote stuff
|
||||||
char remote_nonce[16];
|
unsigned char remote_nonce[16];
|
||||||
struct PublicKey remote_key;
|
struct PublicKey remote_key;
|
||||||
char* remote_peer_id;
|
char* remote_peer_id;
|
||||||
struct StretchedKey* remote_stretched_key;
|
struct StretchedKey* remote_stretched_key;
|
||||||
|
|
148
secio/secio.c
148
secio/secio.c
|
@ -22,6 +22,7 @@
|
||||||
#include "mbedtls/md.h"
|
#include "mbedtls/md.h"
|
||||||
#include "mbedtls/cipher.h"
|
#include "mbedtls/cipher.h"
|
||||||
#include "mbedtls/md_internal.h"
|
#include "mbedtls/md_internal.h"
|
||||||
|
#include "mbedtls/aes.h"
|
||||||
|
|
||||||
const char* SupportedExchanges = "P-256,P-384,P-521";
|
const char* SupportedExchanges = "P-256,P-384,P-521";
|
||||||
const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
|
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
|
* @param length the length of the nonce
|
||||||
* @returns true(1) on success, otherwise false(0)
|
* @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");
|
FILE* fd = fopen("/dev/urandom", "r");
|
||||||
fread(results, 1, length, fd);
|
fread(results, 1, length, fd);
|
||||||
fclose(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
|
* @param length the length of a and b
|
||||||
* @returns a -1, 0, or 1
|
* @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++) {
|
for(int i = 0; i < length; i++) {
|
||||||
if (b[i] > a[i])
|
if (b[i] > a[i])
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -96,6 +97,20 @@ int libp2p_secio_bytes_compare(const char* a, const char* b, int length) {
|
||||||
return 0;
|
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) {
|
int libp2p_secio_string_allocate(char* in, char** out) {
|
||||||
*out = (char*)malloc(strlen(in) + 1);
|
*out = (char*)malloc(strlen(in) + 1);
|
||||||
strcpy(*out, in);
|
strcpy(*out, in);
|
||||||
|
@ -518,6 +533,19 @@ int libp2p_secio_unencrypted_read(struct SessionContext* session, unsigned char*
|
||||||
return buffer_size;
|
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
|
* Encrypt data before being sent out an insecure stream
|
||||||
* @param session the session information
|
* @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
|
* @param outgoing_size the amount of memory allocated
|
||||||
* @returns true(1) on success, otherwise false(0)
|
* @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;
|
unsigned char* buffer = NULL;
|
||||||
size_t buffer_size = 0, original_buffer_size = 0;
|
size_t buffer_size = 0, original_buffer_size = 0;
|
||||||
|
|
||||||
//TODO switch between ciphers
|
//TODO switch between ciphers
|
||||||
mbedtls_cipher_context_t cipher_ctx;
|
mbedtls_aes_context cipher_ctx;
|
||||||
mbedtls_cipher_init(&cipher_ctx);
|
mbedtls_aes_init(&cipher_ctx);
|
||||||
mbedtls_cipher_setup(&cipher_ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CTR));
|
if (mbedtls_aes_setkey_enc(&cipher_ctx, session->local_stretched_key->cipher_key, session->local_stretched_key->cipher_size * 8)) {
|
||||||
mbedtls_cipher_setkey(&cipher_ctx, session->local_stretched_key->cipher_key, session->local_stretched_key->cipher_size * 8, MBEDTLS_ENCRYPT);
|
fprintf(stderr, "Unable to set key for cipher\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
original_buffer_size = incoming_size;
|
original_buffer_size = incoming_size;
|
||||||
original_buffer_size += 32;
|
original_buffer_size += 32;
|
||||||
buffer_size = original_buffer_size;
|
buffer_size = original_buffer_size;
|
||||||
buffer = malloc(original_buffer_size);
|
buffer = malloc(original_buffer_size);
|
||||||
memset(buffer, 0, 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
|
// 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
|
// 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
|
// mac the data
|
||||||
mbedtls_md_context_t ctx;
|
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
|
* @param outgoing_size the amount of memory allocated for the results
|
||||||
* @returns number of unencrypted bytes
|
* @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;
|
size_t data_section_size = incoming_size - 32;
|
||||||
*outgoing_size = 0;
|
*outgoing_size = 0;
|
||||||
unsigned char* buffer;
|
unsigned char* buffer;
|
||||||
size_t buffer_size;
|
|
||||||
|
|
||||||
// verify MAC
|
// verify MAC
|
||||||
//TODO make this more generic to use more than SHA256
|
//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);
|
mbedtls_md_free(&ctx);
|
||||||
// 2. check the mac to see if it is the same
|
// 2. check the mac to see if it is the same
|
||||||
int retVal = memcmp(&incoming[data_section_size], generated_mac, 32);
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
mbedtls_cipher_context_t cipher_ctx;
|
// The MAC checks out. Now decipher the data section
|
||||||
mbedtls_cipher_init(&cipher_ctx);
|
|
||||||
mbedtls_cipher_setup(&cipher_ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_CTR));
|
mbedtls_aes_context cipher_ctx;
|
||||||
mbedtls_cipher_setkey(&cipher_ctx, session->remote_stretched_key->cipher_key, session->remote_stretched_key->cipher_size * 8, MBEDTLS_DECRYPT);
|
mbedtls_aes_init(&cipher_ctx);
|
||||||
mbedtls_cipher_set_iv(&cipher_ctx, session->remote_stretched_key->iv, session->remote_stretched_key->iv_size);
|
if (mbedtls_aes_setkey_enc(&cipher_ctx, session->remote_stretched_key->cipher_key, session->remote_stretched_key->cipher_size * 8)) {
|
||||||
buffer_size = data_section_size + mbedtls_cipher_get_block_size(&cipher_ctx);
|
fprintf(stderr, "Unable to set key for cipher\n");
|
||||||
buffer = malloc(buffer_size);
|
return 0;
|
||||||
mbedtls_cipher_update(&cipher_ctx, incoming, data_section_size, buffer, &buffer_size);
|
}
|
||||||
mbedtls_cipher_free(&cipher_ctx);
|
|
||||||
*outgoing = malloc(buffer_size);
|
buffer = malloc(data_section_size);
|
||||||
*outgoing_size = buffer_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)) {
|
||||||
memcpy(*outgoing, buffer, buffer_size);
|
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);
|
free(buffer);
|
||||||
|
|
||||||
return *outgoing_size;
|
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_out = NULL;
|
||||||
struct Propose* propose_in = NULL;
|
struct Propose* propose_in = NULL;
|
||||||
struct PublicKey* public_key = NULL;
|
struct PublicKey* public_key = NULL;
|
||||||
unsigned char order_hash_in[32] = {0};
|
|
||||||
unsigned char order_hash_out[32] = {0};
|
|
||||||
int order = 0;;
|
int order = 0;;
|
||||||
struct Exchange* exchange_in = NULL;
|
struct Exchange* exchange_in = NULL;
|
||||||
struct Exchange* exchange_out = 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, protocol_len);
|
||||||
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
|
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);
|
bytes_written = libp2p_net_multistream_write(local_session, total, protocol_len + propose_out_size);
|
||||||
free(total);
|
free(total);
|
||||||
if (bytes_written <= 0)
|
if (bytes_written <= 0)
|
||||||
|
@ -704,7 +748,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
||||||
|
|
||||||
if (!remote_requested) {
|
if (!remote_requested) {
|
||||||
// we should get back the secio confirmation
|
// 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);
|
bytes_written = libp2p_net_multistream_read(local_session, &results, &results_size, 20);
|
||||||
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
|
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -760,13 +804,13 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
||||||
goto exit;
|
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);
|
bytes_written = libp2p_secio_unencrypted_write(local_session, propose_out_bytes, propose_out_size);
|
||||||
if (bytes_written < propose_out_size)
|
if (bytes_written < propose_out_size)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// now receive the proposal from the new connection
|
// 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);
|
bytes_written = libp2p_secio_unencrypted_read(local_session, &propose_in_bytes, &propose_in_size, 10);
|
||||||
if (bytes_written <= 0)
|
if (bytes_written <= 0)
|
||||||
goto exit;
|
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
|
// negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
|
||||||
// first determine order
|
// 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);
|
order = libp2p_secio_determine_order(propose_in, propose_out);
|
||||||
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);
|
|
||||||
// curve
|
// 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)
|
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;
|
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);
|
libp2p_secio_exchange_protobuf_encode(exchange_out, exchange_out_protobuf, exchange_out_protobuf_size, &bytes_written);
|
||||||
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);
|
bytes_written = libp2p_secio_unencrypted_write(local_session, exchange_out_protobuf, exchange_out_protobuf_size);
|
||||||
if (exchange_out_protobuf_size != bytes_written)
|
if (exchange_out_protobuf_size != bytes_written)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -849,7 +891,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
||||||
// end of send Exchange packet
|
// end of send Exchange packet
|
||||||
|
|
||||||
// receive 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);
|
bytes_written = libp2p_secio_unencrypted_read(local_session, &results, &results_size, 10);
|
||||||
if (bytes_written == 0)
|
if (bytes_written == 0)
|
||||||
goto exit;
|
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->local_stretched_key);
|
||||||
libp2p_secio_make_mac_and_cipher(local_session, local_session->remote_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
|
// send expected message (their nonce) to verify encryption works
|
||||||
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Sending their nonce");
|
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)
|
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;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
// receive our nonce to verify encryption works
|
// 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);
|
int bytes_read = libp2p_secio_encrypted_read(local_session, &results, &results_size, 10);
|
||||||
if (bytes_read <= 0) {
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (results_size != 16) {
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (libp2p_secio_bytes_compare((char*)results, local_session->local_nonce, 16) != 0) {
|
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");
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -941,7 +997,7 @@ int libp2p_secio_handshake(struct SessionContext* local_session, struct RsaPriva
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
|
||||||
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete");
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake complete\n");
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
if (propose_in_bytes != NULL)
|
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);
|
libp2p_secio_propose_free(propose_in);
|
||||||
|
|
||||||
if (retVal == 1) {
|
if (retVal == 1) {
|
||||||
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake success!");
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake success!\n");
|
||||||
} else {
|
} else {
|
||||||
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake returning false");
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake returning false\n");
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ int test_multistream_get_list() {
|
||||||
char* filtered = NULL;
|
char* filtered = NULL;
|
||||||
|
|
||||||
struct SessionContext session;
|
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)
|
if (*((int*)session.insecure_stream->socket_descriptor) < 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
|
@ -6,14 +6,38 @@
|
||||||
#include "libp2p/net/p2pnet.h"
|
#include "libp2p/net/p2pnet.h"
|
||||||
#include "libp2p/utils/logger.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() {
|
int test_secio_handshake() {
|
||||||
|
|
||||||
|
libp2p_logger_add_class("secio");
|
||||||
|
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
size_t decode_base64_size = 0;
|
size_t decode_base64_size = 0;
|
||||||
unsigned char* decode_base64 = NULL;
|
unsigned char* decode_base64 = NULL;
|
||||||
// this is a base64 encoded private key. It makes it easier to test if it is in base64 form
|
// 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
|
// 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_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 = "QmZigcoDKaAafGSwot2tchJarCafxKapoRmnYTrZ69ckjb";
|
char* orig_peer_id = "QmRKm1d9kSCRpMFtLYpfhhCQ3DKuSSPJa3qn9wWXfwnWnY";
|
||||||
size_t orig_peer_id_size = strlen(orig_peer_id);
|
size_t orig_peer_id_size = strlen(orig_peer_id);
|
||||||
struct RsaPrivateKey* rsa_private_key = NULL;
|
struct RsaPrivateKey* rsa_private_key = NULL;
|
||||||
unsigned char hashed[32] = {0};
|
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))
|
if (!libp2p_crypto_rsa_private_key_fill_public_key(rsa_private_key))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
secure_session.host = "www.jmjatlanta.com";
|
//secure_session.host = "www.jmjatlanta.com";
|
||||||
//secure_session.host = "127.0.0.1";
|
secure_session.host = "10.211.55.2";
|
||||||
secure_session.port = 4001;
|
secure_session.port = 4001;
|
||||||
secure_session.traffic_type = TCP;
|
secure_session.traffic_type = TCP;
|
||||||
// connect to host
|
// connect to host
|
||||||
|
@ -55,12 +79,40 @@ int test_secio_handshake() {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!libp2p_secio_handshake(&secure_session, rsa_private_key, 0)) {
|
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");
|
fprintf(stderr, "test_secio_handshake: Unable to do handshake\n");
|
||||||
goto exit;
|
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;
|
retVal = 1;
|
||||||
exit:
|
exit:
|
||||||
if (secure_session.insecure_stream != NULL)
|
if (secure_session.insecure_stream != NULL)
|
||||||
|
@ -174,3 +226,68 @@ int test_secio_exchange_protobuf_encode() {
|
||||||
libp2p_secio_exchange_free(exch);
|
libp2p_secio_exchange_free(exch);
|
||||||
return retVal;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ const char* names[] = {
|
||||||
"test_secio_handshake",
|
"test_secio_handshake",
|
||||||
"test_secio_encrypt_decrypt",
|
"test_secio_encrypt_decrypt",
|
||||||
"test_secio_exchange_protobuf_encode",
|
"test_secio_exchange_protobuf_encode",
|
||||||
|
"test_secio_encrypt_like_go",
|
||||||
"test_multistream_connect",
|
"test_multistream_connect",
|
||||||
"test_multistream_get_list",
|
"test_multistream_get_list",
|
||||||
"test_ephemeral_key_generate",
|
"test_ephemeral_key_generate",
|
||||||
|
@ -84,6 +85,7 @@ int (*funcs[])(void) = {
|
||||||
test_secio_handshake,
|
test_secio_handshake,
|
||||||
test_secio_encrypt_decrypt,
|
test_secio_encrypt_decrypt,
|
||||||
test_secio_exchange_protobuf_encode,
|
test_secio_exchange_protobuf_encode,
|
||||||
|
test_secio_encrypt_like_go,
|
||||||
test_multistream_connect,
|
test_multistream_connect,
|
||||||
test_multistream_get_list,
|
test_multistream_get_list,
|
||||||
test_ephemeral_key_generate,
|
test_ephemeral_key_generate,
|
||||||
|
|
Loading…
Reference in a new issue