Skip to content
This repository has been archived by the owner on Dec 26, 2022. It is now read-only.

Commit

Permalink
feat(mam): Implement ECDH for MAM key exchange
Browse files Browse the repository at this point in the history
  • Loading branch information
howjmay committed Jul 31, 2020
1 parent 24f7021 commit 71c3435
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 1 deletion.
10 changes: 10 additions & 0 deletions crypto/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cc_library(
name = "ecdh",
srcs = ["ecdh.c"],
hdrs = ["ecdh.h"],
visibility = ["//visibility:public"],
deps = [
"//common",
"@mbedtls",
],
)
94 changes: 94 additions & 0 deletions crypto/ecdh.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "ecdh.h"

#define ECDH_LOGGER "ecdh"
static logger_id_t logger_id;

void ecdh_logger_init() { logger_id = logger_helper_enable(ECDH_LOGGER, LOGGER_DEBUG, true); }

int ecdh_logger_release() {
logger_helper_release(logger_id);
return 0;
}

status_t ecdh_ctx_init(ecdh_ctx_t *ecdh_ctx, mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg,
char *rand_seed, uint16_t seed_len) {
int ret = 1;
status_t sc = SC_OK;
mbedtls_ecdh_init(&ecdh_ctx->ctx);

if (entropy && ctr_drbg) {
mbedtls_ctr_drbg_init(ctr_drbg);

/*
* Initialize random number generation
*/
mbedtls_entropy_init(entropy);
if ((ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)rand_seed,
seed_len)) != 0) {
ta_log_error("mbedtls_ctr_drbg_seed returned %d\n", ret);
goto exit;
}
}

exit:
return sc;
}

status_t ecdh_gen_public_key(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg, unsigned char *pkey) {
int ret = 1;
status_t sc = SC_OK;

ret = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_CURVE25519);
if (ret != 0) {
ta_log_error("mbedtls_ecp_group_load returned %d\n", ret);
goto exit;
}

ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, mbedtls_ctr_drbg_random, ctr_drbg);
if (ret != 0) {
ta_log_error("mbedtls_ecdh_gen_public returned %d\n", ret);
goto exit;
}

ret = mbedtls_mpi_write_binary(&ctx->Q.X, pkey, 32);
if (ret != 0) {
ta_log_error("mbedtls_mpi_write_binary returned %d\n", ret);
goto exit;
}

exit:
return sc;
}

status_t ecdh_compute_shared_secret(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg,
unsigned char *input_shared_data) {
int ret = 1;
status_t sc = SC_OK;

ret = mbedtls_mpi_lset(&ctx->Qp.Z, 1);
if (ret != 0) {
ta_log_error("mbedtls_mpi_lset returned %d\n", ret);
goto exit;
}

ret = mbedtls_mpi_read_binary(&ctx->Qp.X, input_shared_data, 32);
if (ret != 0) {
ta_log_error("mbedtls_mpi_read_binary returned %d\n", ret);
goto exit;
}

ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, mbedtls_ctr_drbg_random, ctr_drbg);
if (ret != 0) {
ta_log_error("mbedtls_ecdh_compute_shared returned %d\n", ret);
goto exit;
}

exit:
return sc;
}

void ecdh_ctx_release(ecdh_ctx_t *ecdh_ctx, mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg) {
mbedtls_ecdh_free(&ecdh_ctx->ctx);
mbedtls_ctr_drbg_free(ctr_drbg);
mbedtls_entropy_free(entropy);
}
94 changes: 94 additions & 0 deletions crypto/ecdh.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (C) 2020 BiiLabs Co., Ltd. and Contributors
* All Rights Reserved.
* This is free software; you can redistribute it and/or modify it under the
* terms of the MIT license. A copy of the license can be found in the file
* "LICENSE" at the root of this distribution.
*/

#ifndef ECDH_COMMON_H
#define ECDH_COMMON_H

#include "common/logger.h"
#include "common/ta_errors.h"
#include "mbedtls/config.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/entropy.h"
#include "mbedtls/platform.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct ecdh_ctx_s {
mbedtls_ecdh_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
} ecdh_ctx_t;

void ecdh_logger_init();

int ecdh_logger_release();

/**
* @brief Initialize tangle-accelerator ECDH object and random number generator
*
* @param[in] ecdh_ctx tangle-accelerator ECDH object
* @param[in] entropy Entropy contrext for randomess
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
* @param[in] rand_seed Random seed for random number generator
* @param[in] seed_len The length of random seed
*
* @return
* - SC_OK on success
* - non-zero on error
*/
status_t ecdh_ctx_init(ecdh_ctx_t *ecdh_ctx, mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg,
char *rand_seed, uint16_t seed_len);

/**
* @brief Initialize ECDH context and generate ECDH keypair
*
* @param[in] ctx ECDH context
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
* @param[out] pkey Output public key which would be sent to counterpart
*
* @return
* - SC_OK on success
* - non-zero on error
*/
status_t ecdh_gen_public_key(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg, unsigned char *pkey);

/**
* @brief Compute the shared secret by Diffie–Hellman key exchange protocol
*
* @param[in] ctx ECDH context
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
* @param[in] input_shared_data The public key sent by counterpart
*
* @return
* - SC_OK on success
* - non-zero on error
*/
status_t ecdh_compute_shared_secret(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg,
unsigned char *input_shared_data);

/**
* @brief Release tangle-accelerator ECDH object and random number generator
*
* @param[in] ecdh_ctx tangle-accelerator ECDH object
* @param[in] entropy Entropy contrext for randomess
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
*
* @return
* - SC_OK on success
* - non-zero on error
*/
void ecdh_ctx_release(ecdh_ctx_t *ecdh_ctx, mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg);

#ifdef __cplusplus
}
#endif

#endif // ECDH_COMMON_H
2 changes: 1 addition & 1 deletion tests/endpoint/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function validate_host() {
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
return 0
fi
if host "$1" > /dev/null 2>&1; then
if host "$1" >/dev/null 2>&1; then
return 0
fi
echo "Please enter a valid host or ip address"
Expand Down
10 changes: 10 additions & 0 deletions tests/unit-test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,13 @@ cc_test(
"//utils:tryte_byte_conv",
],
)

cc_binary(
name = "test_ecdh",
srcs = ["test_ecdh.c"],
deps = [
"//crypto:ecdh",
"//tests:test_define",
"@mbedtls",
],
)
51 changes: 51 additions & 0 deletions tests/unit-test/test_ecdh.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "crypto/ecdh.h"
#include "tests/test_define.h"

void test_srv_cli_communication(void) {
ecdh_ctx_t ecdh_cli, ecdh_srv;
unsigned char cli_to_srv[32], srv_to_cli[32];

TEST_ASSERT_EQUAL_INT32(
SC_OK, ecdh_ctx_init(&ecdh_srv, &ecdh_srv.entropy, &ecdh_srv.ctr_drbg, TEST_UUID, strlen(TEST_UUID) + 1));
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_ctx_init(&ecdh_cli, NULL, NULL, NULL, 0));

TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_gen_public_key(&ecdh_cli.ctx, &ecdh_srv.ctr_drbg, cli_to_srv));

/*
* Server: initialize context and generate keypair
*/
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_gen_public_key(&ecdh_srv.ctx, &ecdh_srv.ctr_drbg, srv_to_cli));

/*
* Server: read peer's key and generate shared secret
*/
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_compute_shared_secret(&ecdh_srv.ctx, &ecdh_srv.ctr_drbg, cli_to_srv));

/*
* Client: read peer's key and generate shared secret
*/
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_compute_shared_secret(&ecdh_cli.ctx, &ecdh_srv.ctr_drbg, srv_to_cli));

/*
* Verification: are the computed secrets equal?
*/
TEST_ASSERT_EQUAL_INT32(0, mbedtls_mpi_cmp_mpi(&ecdh_cli.ctx.z, &ecdh_srv.ctx.z));

ecdh_ctx_release(&ecdh_srv, &ecdh_srv.entropy, &ecdh_srv.ctr_drbg);
mbedtls_ecdh_free(&ecdh_cli.ctx);
}

int main(void) {
UNITY_BEGIN();

// Initialize logger
if (ta_logger_init() != SC_OK) {
return EXIT_FAILURE;
}

ecdh_logger_init();
RUN_TEST(test_srv_cli_communication);
ecdh_logger_release();

return UNITY_END();
}

0 comments on commit 71c3435

Please sign in to comment.