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)
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/***
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue