key exchange complete, nearing encrypted streams, mac invalid

This commit is contained in:
John Jones 2017-03-08 12:18:29 -05:00
parent e092a0e974
commit 05cc6e9bd3
5 changed files with 79 additions and 74 deletions

View file

@ -169,36 +169,19 @@ int libp2p_crypto_ephemeral_keypair_generate(char* curve, struct EphemeralPrivat
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)pers, strlen(pers)) != 0)
goto exit;
// generate public key
// Prepare to generate the public key
if (mbedtls_ecp_group_load(&private_key->ctx.grp, selected_curve) != 0)
goto exit;
if (mbedtls_ecdh_gen_public(&private_key->ctx.grp, &private_key->ctx.d, &private_key->ctx.Q, mbedtls_ctr_drbg_random, &ctr_drbg) != 0)
goto exit;
public_key->bytes_size = 32;
// create and marshal public key
public_key->bytes_size = 66;
public_key->bytes = (unsigned char*)malloc(public_key->bytes_size);
if (mbedtls_mpi_write_binary(&private_key->ctx.Q.X, (char*)public_key->bytes, public_key->bytes_size) != 0)
if (mbedtls_ecdh_make_public(&private_key->ctx, &public_key->bytes_size, (char*)public_key->bytes, public_key->bytes_size, mbedtls_ctr_drbg_random, &ctr_drbg) != 0)
goto exit;
// build shared key, another part of public_key
/*
//mbedtls_ecp_group grp;
mbedtls_ecp_point point;
//mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point_init(&point);
if (mbedtls_ecp_mul(&ctx.grp, &point, &ctx.d, &ctx.Q, mbedtls_ctr_drbg_random, &ctr_drbg) != 0)
goto exit;
public_key->shared_key_size = 8;
public_key->shared_key = (unsigned char*)malloc(8);
serialize_uint64(*point.X.p, public_key->shared_key);
*/
// ship all this stuff back to the caller
retVal = 1;
exit:
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
@ -216,26 +199,42 @@ int libp2p_crypto_ephemeral_keypair_to_public_bytes(struct EphemeralPublicKey* p
return libp2p_crypto_ephemeral_point_marshal(public_key->num_bits, public_key->x, public_key->y, results, bytes_written);
}
/***
* Generate a shared secret from a private key
* @param private key
* @param results
/**
* Generate a shared secret
* @param private_key the context, also where it puts the shared secret
* @param remote_public_key the key the remote gave us
* @param remote_public_key_size the size of the remote public key
* @reutrns true(1) on success, otherwise false(0)
*/
int libp2p_crypto_ephemeral_keypair_to_shared_secret(struct EphemeralPrivateKey* private_key, unsigned char** results, size_t* bytes_written) {
// grab a scalar mult
int libp2p_crypto_ephemeral_generate_shared_secret(struct EphemeralPrivateKey* private_key, const unsigned char* remote_public_key, size_t remote_public_key_size) {
int retVal = 0;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
char* pers = "bitShares"; // data for seeding random number generator
// in GO, ScalarMult turns the bytes of the private key into a multiplier
// for the points
/*
* Multiplication R = m * P
*/
/*
int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
*/
// turn it into bytes
// seed random number generator
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_init(&ctr_drbg);
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)pers, strlen(pers)) != 0)
goto exit;
// read the remote key
if (mbedtls_ecdh_read_public(&private_key->ctx, remote_public_key, remote_public_key_size) < 0)
goto exit;
// generate the shared key
// reserve some memory for the shared key
//TODO: set this to something reasonable
private_key->public_key->shared_key_size = 100;
private_key->public_key->shared_key = malloc(private_key->public_key->shared_key_size);
if (mbedtls_ecdh_calc_secret(&private_key->ctx,
&private_key->public_key->shared_key_size, private_key->public_key->shared_key, private_key->public_key->shared_key_size,
mbedtls_ctr_drbg_random, &ctr_drbg) != 0)
goto exit;
retVal = 1;
exit:
return retVal;
//TODO: implement
return 0;
}

View file

@ -41,6 +41,15 @@ struct EphemeralPrivateKey {
*/
int libp2p_crypto_ephemeral_keypair_generate(char* curve, struct EphemeralPrivateKey** private_key);
/**
* Generate a shared secret
* @param private_key the context, also where it puts the shared secret
* @param remote_public_key the key the remote gave us
* @param remote_public_key_size the size of the remote public key
* @reutrns true(1) on success, otherwise false(0)
*/
int libp2p_crypto_ephemeral_generate_shared_secret(struct EphemeralPrivateKey* private_key, const unsigned char* remote_public_key, size_t remote_public_key_size);
/***
* Remove resources used by generation of ephemeral private key
* @param in the key to destroy

View file

@ -27,16 +27,15 @@ struct SecureSession {
int (*mac_function)(const unsigned char*, size_t, unsigned char*);
// local only stuff
char local_nonce[16];
unsigned char* ephemeral_public_key; // bytes of x and y
size_t ephemeral_public_key_size;
struct EphemeralPrivateKey* ephemeral_private_key;
struct StretchedKey* local_stretched_key;
// remote stuff
char remote_nonce[16];
struct PublicKey remote_key;
char* remote_peer_id;
struct StretchedKey* remote_stretched_key;
unsigned char* remote_ephemeral_public_key;
size_t remote_ephemeral_public_key_size;
struct StretchedKey* remote_stretched_key;
};
/***

View file

@ -328,7 +328,7 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
if (temp != NULL)
free(temp);
temp = result;
k1->mac_size = hash_size;
k1->mac_size = hmac_size;
k1->iv = malloc(k1->iv_size);
memcpy(k1->iv, temp, k1->iv_size);
temp += k1->iv_size;
@ -339,7 +339,7 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
memcpy(k1->mac_key, temp, k1->mac_size);
temp += k1->mac_size;
k2->mac_size = hash_size;
k2->mac_size = hmac_size;
k2->iv = malloc(k2->iv_size);
memcpy(k2->iv, temp, k2->iv_size);
temp += k2->iv_size;
@ -663,7 +663,6 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
struct PrivateKey* priv = NULL;
struct PublicKey pub_key = {0};
char* remote_peer_id = NULL;
struct EphemeralPrivateKey* e_private_key = NULL;
//TODO: make sure we're not talking to ourself
@ -774,33 +773,28 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
goto exit;
// generate EphemeralPubKey
if (libp2p_crypto_ephemeral_keypair_generate(local_session->chosen_curve, &e_private_key) == 0)
if (libp2p_crypto_ephemeral_keypair_generate(local_session->chosen_curve, &local_session->ephemeral_private_key) == 0)
goto exit;
local_session->ephemeral_public_key_size = e_private_key->public_key->bytes_size;
local_session->ephemeral_public_key = malloc(local_session->ephemeral_public_key_size);
memcpy(local_session->ephemeral_public_key, e_private_key->public_key->bytes, local_session->ephemeral_public_key_size);
libp2p_crypto_ephemeral_key_free(e_private_key);
e_private_key = NULL;
// build buffer to sign
char_buffer_length = propose_in_size + propose_out_size + local_session->ephemeral_public_key_size;
char_buffer_length = propose_in_size + propose_out_size + local_session->ephemeral_private_key->public_key->bytes_size - 1;
char_buffer = malloc(char_buffer_length);
if (char_buffer == NULL)
goto exit;
memcpy(&char_buffer[0], propose_in_bytes, propose_in_size);
memcpy(&char_buffer[propose_in_size], propose_out_bytes, propose_out_size);
memcpy(&char_buffer[propose_in_size + propose_out_size], local_session->ephemeral_public_key, local_session->ephemeral_public_key_size);
memcpy(&char_buffer[0], propose_out_bytes, propose_out_size);
memcpy(&char_buffer[propose_out_size], propose_in_bytes, propose_in_size);
memcpy(&char_buffer[propose_in_size + propose_out_size], &local_session->ephemeral_private_key->public_key->bytes[1], local_session->ephemeral_private_key->public_key->bytes_size-1);
// send Exchange packet
exchange_out = libp2p_secio_exchange_new();
if (exchange_out == NULL)
goto exit;
exchange_out->epubkey = (unsigned char*)malloc(local_session->ephemeral_public_key_size);
// don't send the first byte (to stay compatible with GO version)
exchange_out->epubkey = (unsigned char*)malloc(local_session->ephemeral_private_key->public_key->bytes_size - 1);
if (exchange_out->epubkey == NULL)
goto exit;
memcpy(exchange_out->epubkey, local_session->ephemeral_public_key, local_session->ephemeral_public_key_size);
exchange_out->epubkey_size = local_session->ephemeral_public_key_size;
memcpy(exchange_out->epubkey, &local_session->ephemeral_private_key->public_key->bytes[1], local_session->ephemeral_private_key->public_key->bytes_size - 1);
exchange_out->epubkey_size = local_session->ephemeral_private_key->public_key->bytes_size - 1;
priv = libp2p_crypto_private_key_new();
priv->type = KEYTYPE_RSA;
@ -836,25 +830,31 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
// end of receive Exchange packet
// parse and verify
local_session->remote_ephemeral_public_key = exchange_in->epubkey;
local_session->remote_ephemeral_public_key_size = exchange_in->epubkey_size;
local_session->remote_ephemeral_public_key_size = exchange_in->epubkey_size + 1;
local_session->remote_ephemeral_public_key = malloc(local_session->remote_ephemeral_public_key_size);
local_session->remote_ephemeral_public_key[0] = exchange_in->epubkey_size;
memcpy(&local_session->remote_ephemeral_public_key[1], exchange_in->epubkey, exchange_in->epubkey_size);
char_buffer = malloc(propose_in_size + propose_out_size + local_session->remote_ephemeral_public_key_size);
// TODO: signature verification
char_buffer_length = propose_in_size + propose_out_size + local_session->remote_ephemeral_public_key_size - 1;
char_buffer = malloc(char_buffer_length);
if (char_buffer == NULL)
goto exit;
memcpy(&char_buffer[0], propose_in_bytes, propose_in_size);
memcpy(&char_buffer[propose_in_size], propose_out_bytes, propose_out_size);
memcpy(&char_buffer[propose_in_size + propose_out_size], local_session->remote_ephemeral_public_key, local_session->remote_ephemeral_public_key_size);
// TODO: signature verification
//if (!libp2p_secio_verify_signature(public_key, char_buffer->buffer, char_buffer->buffer_size, exchange_in->signature))
// goto exit;
memcpy(&char_buffer[propose_in_size + propose_out_size], &local_session->remote_ephemeral_public_key[1], local_session->remote_ephemeral_public_key_size - 1);
if (!libp2p_secio_verify_signature(public_key, (unsigned char*)char_buffer, char_buffer_length, exchange_in->signature))
goto exit;
free(char_buffer);
char_buffer = NULL;
// 2.2 generate shared key NOTE: this was done above
// 2.2 generate shared key
if (!libp2p_crypto_ephemeral_generate_shared_secret(local_session->ephemeral_private_key, local_session->remote_ephemeral_public_key, local_session->remote_ephemeral_public_key_size))
goto exit;
// generate 2 sets of keys (stretching)
libp2p_secio_stretch_keys(local_session->chosen_cipher, local_session->chosen_hash, local_session->shared_key, local_session->shared_key_size, &k1, &k2);
if (!libp2p_secio_stretch_keys(local_session->chosen_cipher, local_session->chosen_hash, local_session->shared_key, local_session->shared_key_size, &k1, &k2))
goto exit;
if (order > 1) {
local_session->local_stretched_key = k1;
@ -908,8 +908,6 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
free(remote_peer_id);
if (exchange_out != NULL)
libp2p_secio_exchange_free(exchange_out);
if (e_private_key != NULL)
libp2p_crypto_ephemeral_key_free(e_private_key);
if (exchange_out_protobuf != NULL)
free(exchange_out_protobuf);
if (exchange_in != NULL)

View file

@ -43,7 +43,7 @@ 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 = "10.0.1.11";
//secure_session.host = "127.0.0.1";
secure_session.port = 4001;
secure_session.traffic_type = TCP;
@ -68,8 +68,8 @@ int test_secio_handshake() {
libp2p_crypto_ephemeral_stretched_key_free(secure_session.local_stretched_key);
if (secure_session.remote_stretched_key != NULL)
libp2p_crypto_ephemeral_stretched_key_free(secure_session.remote_stretched_key);
if (secure_session.ephemeral_public_key != NULL)
free(secure_session.ephemeral_public_key);
if (secure_session.ephemeral_private_key != NULL)
libp2p_crypto_ephemeral_key_free(secure_session.ephemeral_private_key);
if (secure_session.chosen_cipher != NULL)
free(secure_session.chosen_cipher);
if (secure_session.chosen_curve != NULL)