diff --git a/crypto/ephemeral.c b/crypto/ephemeral.c index 549cbc5..4ceab12 100644 --- a/crypto/ephemeral.c +++ b/crypto/ephemeral.c @@ -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; } + diff --git a/include/libp2p/crypto/ephemeral.h b/include/libp2p/crypto/ephemeral.h index 08128e3..ad44527 100644 --- a/include/libp2p/crypto/ephemeral.h +++ b/include/libp2p/crypto/ephemeral.h @@ -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 diff --git a/include/libp2p/secio/secio.h b/include/libp2p/secio/secio.h index 5d371ca..a96723d 100644 --- a/include/libp2p/secio/secio.h +++ b/include/libp2p/secio/secio.h @@ -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; }; /*** diff --git a/secio/secio.c b/secio/secio.c index 9f7d483..931a948 100644 --- a/secio/secio.c +++ b/secio/secio.c @@ -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) diff --git a/test/test_secio.h b/test/test_secio.h index 0e603d9..d454403 100644 --- a/test/test_secio.h +++ b/test/test_secio.h @@ -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)