diff --git a/crypto/ephemeral.c b/crypto/ephemeral.c index 896c304..f78bd70 100644 --- a/crypto/ephemeral.c +++ b/crypto/ephemeral.c @@ -7,10 +7,11 @@ #include "mbedtls/ctr_drbg.h" #include "libp2p/crypto/ephemeral.h" -struct EphemeralPrivateKey* libp2p_crypto_ephemeral_key_new(uint64_t priv, uint64_t x, uint64_t y) { +struct EphemeralPrivateKey* libp2p_crypto_ephemeral_key_new(uint64_t priv, uint64_t x, uint64_t y, size_t num_bits) { struct EphemeralPrivateKey* results = (struct EphemeralPrivateKey*)malloc(sizeof(struct EphemeralPrivateKey)); if (results != NULL) { results->secret_key = priv; + results->num_bits = num_bits; results->public_key = (struct EphemeralPublicKey*)malloc(sizeof(struct EphemeralPublicKey)); if (results->public_key == NULL) { free(results); @@ -18,6 +19,7 @@ struct EphemeralPrivateKey* libp2p_crypto_ephemeral_key_new(uint64_t priv, uint6 } else { results->public_key->x = x; results->public_key->y = y; + results->public_key->num_bits = num_bits; } } return results; @@ -31,13 +33,77 @@ void libp2p_crypto_ephemeral_key_free(struct EphemeralPrivateKey* in) { } } +void serialize_uint64(const uint64_t in, unsigned char out[8]) { + out[0] = in >> 56; + out[1] = in >> 48; + out[2] = in >> 40; + out[3] = in >> 32; + out[4] = in >> 24; + out[5] = in >> 16; + out[6] = in >> 8; + out[7] = in; +} + +uint64_t unserialize_uint64(unsigned char in[8]) { + uint64_t out = 0; + + out = (out << 8) | in[0]; + out = (out << 8) | in[1]; + out = (out << 8) | in[2]; + out = (out << 8) | in[3]; + out = (out << 8) | in[4]; + out = (out << 8) | in[5]; + out = (out << 8) | in[6]; + out = (out << 8) | in[7]; + return out; +} + +/*** + * Take the public pieces of an ephemeral key and turn them into a byte stream + * @param bit_size the curve bit size + * @param x the x parameter of the ephemeral key + * @param y the y parameter of the ephemeral key + * @param results where to put the bytes + * @param bytes_written how many bytes were written to results + * @returns true(1) on success, otherwise false(0) + */ +int libp2p_crypto_ephemeral_point_marshal(int bit_size, uint64_t x, uint64_t y, unsigned char** results, size_t* bytes_written) { + int byteLen = (bit_size + 7) >> 3; + + *results = (unsigned char*)malloc(2*byteLen+1); + *results[0] = 4; // uncompressed point + int uint64_len = 8; + unsigned char buffer[8]; + serialize_uint64(x, &buffer[0]); + memcpy(&(*results)[1 + byteLen - uint64_len], &buffer[0], 8); + serialize_uint64(y, &buffer[0]); + memcpy(&(*results)[1 + 2*byteLen - uint64_len], &buffer[0], 8); + *bytes_written = 2 * byteLen + 1; + return 1; +} + +int libp2p_crypto_ephemeral_point_unmarshal(int bit_size, unsigned char* buffer, size_t buffer_length, uint64_t* x, uint64_t* y) { + int byteLen = (bit_size + 7) >> 3; + + if (buffer_length != 2 * byteLen + 1) + return 0; + if (buffer[0] != 4) + return 0; + unsigned char temp[8]; + memcpy((char*)temp, &buffer[1], 8); + *x = unserialize_uint64(temp); + memcpy((char*)temp, &buffer[9], 8); + *y = unserialize_uint64(temp); + return 1; +} + /** - * Generate a Ephemeral Public Key as well as a shared key + * Generate a Ephemeral keypair * @param curve the curve to use (P-256, P-384, or P-521) * @param private_key the struct to store the generated key * @returns true(1) on success, otherwise false(0) */ -int libp2p_crypto_ephemeral_key_generate(char* curve, struct EphemeralPrivateKey** private_key) { +int libp2p_crypto_ephemeral_keypair_generate(char* curve, struct EphemeralPrivateKey** private_key) { int retVal = 0; mbedtls_ecdsa_context ctx; mbedtls_entropy_context entropy; @@ -64,10 +130,45 @@ int libp2p_crypto_ephemeral_key_generate(char* curve, struct EphemeralPrivateKey if (mbedtls_ecdsa_genkey(&ctx, selected_curve, mbedtls_ctr_drbg_random, &ctr_drbg) != 0) goto exit; - *private_key = libp2p_crypto_ephemeral_key_new(*ctx.d.p, *ctx.Q.X.p, *ctx.Q.Y.p); + *private_key = libp2p_crypto_ephemeral_key_new(*ctx.d.p, *ctx.Q.X.p, *ctx.Q.Y.p, ctx.grp.nbits); retVal = 1; exit: return retVal; } + +/** + * Generate a public key from a private key + * @param public key + * @param results the results + * @param bytes_written the number of bytes written + * @returns true(1) on success, otherwise false(0) + */ +int libp2p_crypto_ephemeral_keypair_to_public_bytes(struct EphemeralPublicKey* public_key, unsigned char** results, size_t* 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 + * @param private key + * @param results + */ +int libp2p_crypto_ephemeral_keypair_to_shared_secret(struct EphemeralPrivateKey* private_key, unsigned char** results, size_t* bytes_written) { + // grab a scalar mult + + // 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 + + //TODO: implement + return 0; +} diff --git a/include/libp2p/crypto/ephemeral.h b/include/libp2p/crypto/ephemeral.h index 04c273c..57ed3c5 100644 --- a/include/libp2p/crypto/ephemeral.h +++ b/include/libp2p/crypto/ephemeral.h @@ -7,11 +7,13 @@ */ struct EphemeralPublicKey { + size_t num_bits; uint64_t x; uint64_t y; }; struct EphemeralPrivateKey { + size_t num_bits; uint64_t secret_key; struct EphemeralPublicKey* public_key; }; @@ -22,4 +24,4 @@ struct EphemeralPrivateKey { * @param private_key where to store the private key * @reutrns true(1) on success, otherwise false(0) */ -int libp2p_crypto_ephemeral_key_generate(char* curve, struct EphemeralPrivateKey** private_key); +int libp2p_crypto_ephemeral_keypair_generate(char* curve, struct EphemeralPrivateKey** private_key); diff --git a/secio/secio.c b/secio/secio.c index 95c2111..b1da8be 100644 --- a/secio/secio.c +++ b/secio/secio.c @@ -345,7 +345,7 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat // generate EphemeralPubKey struct EphemeralPrivateKey* e_private_key; - libp2p_crypto_ephemeral_key_generate(local_session->chosen_curve, &e_private_key); + libp2p_crypto_ephemeral_keypair_generate(local_session->chosen_curve, &e_private_key); // build buffer to sign char_buffer = libp2p_utils_vector_new(); if (char_buffer == NULL) diff --git a/test/crypto/test_ephemeral.h b/test/crypto/test_ephemeral.h index 2a43999..5959fc2 100644 --- a/test/crypto/test_ephemeral.h +++ b/test/crypto/test_ephemeral.h @@ -6,7 +6,7 @@ */ int test_ephemeral_key_generate() { struct EphemeralPrivateKey* private_key; - int retVal = libp2p_crypto_ephemeral_key_generate("P-256", &private_key); + int retVal = libp2p_crypto_ephemeral_keypair_generate("P-256", &private_key); if (retVal && private_key->secret_key > 0 && private_key->public_key->x > 0 && private_key->public_key->y > 0) return 1; return 0;