key exchange complete, nearing encrypted streams, mac invalid
This commit is contained in:
parent
e092a0e974
commit
05cc6e9bd3
5 changed files with 79 additions and 74 deletions
|
@ -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)
|
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)pers, strlen(pers)) != 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// generate public key
|
// Prepare to generate the public key
|
||||||
if (mbedtls_ecp_group_load(&private_key->ctx.grp, selected_curve) != 0)
|
if (mbedtls_ecp_group_load(&private_key->ctx.grp, selected_curve) != 0)
|
||||||
goto exit;
|
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)
|
// create and marshal public key
|
||||||
goto exit;
|
public_key->bytes_size = 66;
|
||||||
|
|
||||||
public_key->bytes_size = 32;
|
|
||||||
public_key->bytes = (unsigned char*)malloc(public_key->bytes_size);
|
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;
|
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
|
// ship all this stuff back to the caller
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||||
mbedtls_entropy_free(&entropy);
|
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);
|
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
|
* Generate a shared secret
|
||||||
* @param private key
|
* @param private_key the context, also where it puts the shared secret
|
||||||
* @param results
|
* @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) {
|
int libp2p_crypto_ephemeral_generate_shared_secret(struct EphemeralPrivateKey* private_key, const unsigned char* remote_public_key, size_t remote_public_key_size) {
|
||||||
// grab a scalar mult
|
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
|
// seed random number generator
|
||||||
// for the points
|
mbedtls_entropy_init(&entropy);
|
||||||
/*
|
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||||
* Multiplication R = m * P
|
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char*)pers, strlen(pers)) != 0)
|
||||||
*/
|
goto exit;
|
||||||
/*
|
|
||||||
int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
|
// read the remote key
|
||||||
const mbedtls_mpi *m, const mbedtls_ecp_point *P,
|
if (mbedtls_ecdh_read_public(&private_key->ctx, remote_public_key, remote_public_key_size) < 0)
|
||||||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
|
goto exit;
|
||||||
*/
|
|
||||||
// turn it into bytes
|
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,15 @@ struct EphemeralPrivateKey {
|
||||||
*/
|
*/
|
||||||
int libp2p_crypto_ephemeral_keypair_generate(char* curve, struct EphemeralPrivateKey** private_key);
|
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
|
* Remove resources used by generation of ephemeral private key
|
||||||
* @param in the key to destroy
|
* @param in the key to destroy
|
||||||
|
|
|
@ -27,16 +27,15 @@ struct SecureSession {
|
||||||
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];
|
char local_nonce[16];
|
||||||
unsigned char* ephemeral_public_key; // bytes of x and y
|
struct EphemeralPrivateKey* ephemeral_private_key;
|
||||||
size_t ephemeral_public_key_size;
|
|
||||||
struct StretchedKey* local_stretched_key;
|
struct StretchedKey* local_stretched_key;
|
||||||
// remote stuff
|
// remote stuff
|
||||||
char remote_nonce[16];
|
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;
|
||||||
unsigned char* remote_ephemeral_public_key;
|
unsigned char* remote_ephemeral_public_key;
|
||||||
size_t remote_ephemeral_public_key_size;
|
size_t remote_ephemeral_public_key_size;
|
||||||
struct StretchedKey* remote_stretched_key;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|
|
@ -328,7 +328,7 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
|
||||||
if (temp != NULL)
|
if (temp != NULL)
|
||||||
free(temp);
|
free(temp);
|
||||||
temp = result;
|
temp = result;
|
||||||
k1->mac_size = hash_size;
|
k1->mac_size = hmac_size;
|
||||||
k1->iv = malloc(k1->iv_size);
|
k1->iv = malloc(k1->iv_size);
|
||||||
memcpy(k1->iv, temp, k1->iv_size);
|
memcpy(k1->iv, temp, k1->iv_size);
|
||||||
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);
|
memcpy(k1->mac_key, temp, k1->mac_size);
|
||||||
temp += k1->mac_size;
|
temp += k1->mac_size;
|
||||||
|
|
||||||
k2->mac_size = hash_size;
|
k2->mac_size = hmac_size;
|
||||||
k2->iv = malloc(k2->iv_size);
|
k2->iv = malloc(k2->iv_size);
|
||||||
memcpy(k2->iv, temp, k2->iv_size);
|
memcpy(k2->iv, temp, k2->iv_size);
|
||||||
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 PrivateKey* priv = NULL;
|
||||||
struct PublicKey pub_key = {0};
|
struct PublicKey pub_key = {0};
|
||||||
char* remote_peer_id = NULL;
|
char* remote_peer_id = NULL;
|
||||||
struct EphemeralPrivateKey* e_private_key = NULL;
|
|
||||||
|
|
||||||
//TODO: make sure we're not talking to ourself
|
//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;
|
goto exit;
|
||||||
|
|
||||||
// generate EphemeralPubKey
|
// 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;
|
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
|
// 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);
|
char_buffer = malloc(char_buffer_length);
|
||||||
if (char_buffer == NULL)
|
if (char_buffer == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
memcpy(&char_buffer[0], propose_in_bytes, propose_in_size);
|
memcpy(&char_buffer[0], propose_out_bytes, propose_out_size);
|
||||||
memcpy(&char_buffer[propose_in_size], 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_public_key, local_session->ephemeral_public_key_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
|
// send Exchange packet
|
||||||
exchange_out = libp2p_secio_exchange_new();
|
exchange_out = libp2p_secio_exchange_new();
|
||||||
if (exchange_out == NULL)
|
if (exchange_out == NULL)
|
||||||
goto exit;
|
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)
|
if (exchange_out->epubkey == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
memcpy(exchange_out->epubkey, local_session->ephemeral_public_key, 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_public_key_size;
|
exchange_out->epubkey_size = local_session->ephemeral_private_key->public_key->bytes_size - 1;
|
||||||
|
|
||||||
priv = libp2p_crypto_private_key_new();
|
priv = libp2p_crypto_private_key_new();
|
||||||
priv->type = KEYTYPE_RSA;
|
priv->type = KEYTYPE_RSA;
|
||||||
|
@ -836,25 +830,31 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
// end of receive Exchange packet
|
// end of receive Exchange packet
|
||||||
|
|
||||||
// parse and verify
|
// parse and verify
|
||||||
local_session->remote_ephemeral_public_key = exchange_in->epubkey;
|
local_session->remote_ephemeral_public_key_size = exchange_in->epubkey_size + 1;
|
||||||
local_session->remote_ephemeral_public_key_size = exchange_in->epubkey_size;
|
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)
|
if (char_buffer == NULL)
|
||||||
goto exit;
|
goto exit;
|
||||||
memcpy(&char_buffer[0], propose_in_bytes, propose_in_size);
|
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_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);
|
memcpy(&char_buffer[propose_in_size + propose_out_size], &local_session->remote_ephemeral_public_key[1], local_session->remote_ephemeral_public_key_size - 1);
|
||||||
// TODO: signature verification
|
if (!libp2p_secio_verify_signature(public_key, (unsigned char*)char_buffer, char_buffer_length, exchange_in->signature))
|
||||||
//if (!libp2p_secio_verify_signature(public_key, char_buffer->buffer, char_buffer->buffer_size, exchange_in->signature))
|
goto exit;
|
||||||
// goto exit;
|
|
||||||
free(char_buffer);
|
free(char_buffer);
|
||||||
char_buffer = NULL;
|
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)
|
// 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) {
|
if (order > 1) {
|
||||||
local_session->local_stretched_key = k1;
|
local_session->local_stretched_key = k1;
|
||||||
|
@ -908,8 +908,6 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
free(remote_peer_id);
|
free(remote_peer_id);
|
||||||
if (exchange_out != NULL)
|
if (exchange_out != NULL)
|
||||||
libp2p_secio_exchange_free(exchange_out);
|
libp2p_secio_exchange_free(exchange_out);
|
||||||
if (e_private_key != NULL)
|
|
||||||
libp2p_crypto_ephemeral_key_free(e_private_key);
|
|
||||||
if (exchange_out_protobuf != NULL)
|
if (exchange_out_protobuf != NULL)
|
||||||
free(exchange_out_protobuf);
|
free(exchange_out_protobuf);
|
||||||
if (exchange_in != NULL)
|
if (exchange_in != NULL)
|
||||||
|
|
|
@ -43,7 +43,7 @@ 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 = "10.0.1.11";
|
||||||
//secure_session.host = "127.0.0.1";
|
//secure_session.host = "127.0.0.1";
|
||||||
secure_session.port = 4001;
|
secure_session.port = 4001;
|
||||||
secure_session.traffic_type = TCP;
|
secure_session.traffic_type = TCP;
|
||||||
|
@ -68,8 +68,8 @@ int test_secio_handshake() {
|
||||||
libp2p_crypto_ephemeral_stretched_key_free(secure_session.local_stretched_key);
|
libp2p_crypto_ephemeral_stretched_key_free(secure_session.local_stretched_key);
|
||||||
if (secure_session.remote_stretched_key != NULL)
|
if (secure_session.remote_stretched_key != NULL)
|
||||||
libp2p_crypto_ephemeral_stretched_key_free(secure_session.remote_stretched_key);
|
libp2p_crypto_ephemeral_stretched_key_free(secure_session.remote_stretched_key);
|
||||||
if (secure_session.ephemeral_public_key != NULL)
|
if (secure_session.ephemeral_private_key != NULL)
|
||||||
free(secure_session.ephemeral_public_key);
|
libp2p_crypto_ephemeral_key_free(secure_session.ephemeral_private_key);
|
||||||
if (secure_session.chosen_cipher != NULL)
|
if (secure_session.chosen_cipher != NULL)
|
||||||
free(secure_session.chosen_cipher);
|
free(secure_session.chosen_cipher);
|
||||||
if (secure_session.chosen_curve != NULL)
|
if (secure_session.chosen_curve != NULL)
|
||||||
|
|
Loading…
Reference in a new issue