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
For #560
  • Loading branch information
howjmay committed Jul 31, 2020
1 parent 6d83549 commit 94840cd
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 1 deletion.
8 changes: 8 additions & 0 deletions common/ta_errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ const char* ta_error_to_string(status_t err) {
case SC_ENDPOINT_DNS_RESOLVE_ERROR:
return "Error occurred when resolving the domain name";

// Crypto
case SC_CRYPTO_RAND_INIT:
return "Failed to generate random number generator";
case SC_CRYPTO_GEN_PKEY:
return "Failed to generate ECDH public key";
case SC_CRYPTO_COMPUTE_SECRET:
return "Failed to compute ECDH shared secret";

default:
return "Unknown error.";
}
Expand Down
9 changes: 9 additions & 0 deletions common/ta_errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ extern "C" {
#define SC_MODULE_STORAGE (0x0A << SC_MODULE_SHIFT)
#define SC_MODULE_CORE (0x0B << SC_MODULE_SHIFT)
#define SC_MODULE_ENDPOINT (0x0C << SC_MODULE_SHIFT)
#define SC_MODULE_CRYPTO (0x0D << SC_MODULE_SHIFT)
/** @} */

/** @name serverity code */
Expand Down Expand Up @@ -255,6 +256,14 @@ typedef enum {
SC_ENDPOINT_DNS_RESOLVE_ERROR = 0x0B | SC_MODULE_ENDPOINT | SC_SEVERITY_FATAL,
/**< Failed to resolve the domain name address */

// Crypto module
SC_CRYPTO_RAND_INIT = 0x01 | SC_MODULE_CRYPTO | SC_SEVERITY_FATAL,
/**< Failed to generate random number generator */
SC_CRYPTO_GEN_PKEY = 0x02 | SC_MODULE_CRYPTO | SC_SEVERITY_FATAL,
/**< Failed to generate ECDH public key */
SC_CRYPTO_COMPUTE_SECRET = 0x03 | SC_MODULE_CRYPTO | SC_SEVERITY_FATAL,
/**< Failed to compute ECDH shared secret */

} status_t;

typedef enum {
Expand Down
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",
],
)
90 changes: 90 additions & 0 deletions crypto/ecdh.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#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 rand_num_gen_init(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_ctr_drbg_init(ctr_drbg);
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);
sc = SC_CRYPTO_RAND_INIT;
}

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);
sc = SC_CRYPTO_GEN_PKEY;
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);
sc = SC_CRYPTO_GEN_PKEY;
goto exit;
}

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

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);
sc = SC_CRYPTO_COMPUTE_SECRET;
goto exit;
}

ret = mbedtls_mpi_read_binary(&ctx->Qp.X, input_shared_data, SHARE_DATA_LEN);
if (ret != 0) {
ta_log_error("mbedtls_mpi_read_binary returned %d\n", ret);
sc = SC_CRYPTO_COMPUTE_SECRET;
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);
sc = SC_CRYPTO_COMPUTE_SECRET;
}

exit:
return sc;
}

void rand_num_gen_release(mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg) {
mbedtls_ctr_drbg_free(ctr_drbg);
mbedtls_entropy_free(entropy);
}
103 changes: 103 additions & 0 deletions crypto/ecdh.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* 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

#define SHARE_DATA_LEN 32

typedef struct rand_gen_s {
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
} rand_gen_t;

/**
* Initialize logger for ECDH
*/
void ecdh_logger_init();

/**
* Release logger
*
* @return
* - zero on success
* - EXIT_FAILURE on error
*/
int ecdh_logger_release();

/**
* @brief Initialize mbedtls random number generator
*
* @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 rand_num_gen_init(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 random number generator
*
* @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 rand_num_gen_release(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",
],
)
57 changes: 57 additions & 0 deletions tests/unit-test/test_ecdh.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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.
*/

#include "crypto/ecdh.h"
#include "tests/test_define.h"

void test_srv_cli_communication(void) {
rand_gen_t rand_gen;
mbedtls_ecdh_context ecdh_srv, ecdh_cli;
unsigned char cli_to_srv[SHARE_DATA_LEN], srv_to_cli[SHARE_DATA_LEN];

// initialize ECDH object for server side and client side
mbedtls_ecdh_init(&ecdh_srv);
mbedtls_ecdh_init(&ecdh_cli);

TEST_ASSERT_EQUAL_INT32(SC_OK,
rand_num_gen_init(&rand_gen.entropy, &rand_gen.ctr_drbg, TEST_UUID, strlen(TEST_UUID) + 1));

// [client] initialize ECDH context and generate public key
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_gen_public_key(&ecdh_cli, &rand_gen.ctr_drbg, cli_to_srv));

// [server] initialize ECDH context and generate public key
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_gen_public_key(&ecdh_srv, &rand_gen.ctr_drbg, srv_to_cli));

// [server] compute shared secret with peer's public key
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_compute_shared_secret(&ecdh_srv, &rand_gen.ctr_drbg, cli_to_srv));

// [client] compute shared secret with peer's public key
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_compute_shared_secret(&ecdh_cli, &rand_gen.ctr_drbg, srv_to_cli));

// Check if the two shared secret are the same
TEST_ASSERT_EQUAL_INT32(0, mbedtls_mpi_cmp_mpi(&ecdh_cli.z, &ecdh_srv.z));

rand_num_gen_release(&rand_gen.entropy, &rand_gen.ctr_drbg);
mbedtls_ecdh_free(&ecdh_srv);
mbedtls_ecdh_free(&ecdh_cli);
}

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 94840cd

Please sign in to comment.