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

Commit 94840cd

Browse files
committed
feat(mam): Implement ECDH for MAM key exchange
For #560
1 parent 6d83549 commit 94840cd

File tree

8 files changed

+288
-1
lines changed

8 files changed

+288
-1
lines changed

common/ta_errors.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ const char* ta_error_to_string(status_t err) {
197197
case SC_ENDPOINT_DNS_RESOLVE_ERROR:
198198
return "Error occurred when resolving the domain name";
199199

200+
// Crypto
201+
case SC_CRYPTO_RAND_INIT:
202+
return "Failed to generate random number generator";
203+
case SC_CRYPTO_GEN_PKEY:
204+
return "Failed to generate ECDH public key";
205+
case SC_CRYPTO_COMPUTE_SECRET:
206+
return "Failed to compute ECDH shared secret";
207+
200208
default:
201209
return "Unknown error.";
202210
}

common/ta_errors.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ extern "C" {
5757
#define SC_MODULE_STORAGE (0x0A << SC_MODULE_SHIFT)
5858
#define SC_MODULE_CORE (0x0B << SC_MODULE_SHIFT)
5959
#define SC_MODULE_ENDPOINT (0x0C << SC_MODULE_SHIFT)
60+
#define SC_MODULE_CRYPTO (0x0D << SC_MODULE_SHIFT)
6061
/** @} */
6162

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

259+
// Crypto module
260+
SC_CRYPTO_RAND_INIT = 0x01 | SC_MODULE_CRYPTO | SC_SEVERITY_FATAL,
261+
/**< Failed to generate random number generator */
262+
SC_CRYPTO_GEN_PKEY = 0x02 | SC_MODULE_CRYPTO | SC_SEVERITY_FATAL,
263+
/**< Failed to generate ECDH public key */
264+
SC_CRYPTO_COMPUTE_SECRET = 0x03 | SC_MODULE_CRYPTO | SC_SEVERITY_FATAL,
265+
/**< Failed to compute ECDH shared secret */
266+
258267
} status_t;
259268

260269
typedef enum {

crypto/BUILD

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
cc_library(
2+
name = "ecdh",
3+
srcs = ["ecdh.c"],
4+
hdrs = ["ecdh.h"],
5+
visibility = ["//visibility:public"],
6+
deps = [
7+
"//common",
8+
"@mbedtls",
9+
],
10+
)

crypto/ecdh.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#include "ecdh.h"
2+
3+
#define ECDH_LOGGER "ecdh"
4+
static logger_id_t logger_id;
5+
6+
void ecdh_logger_init() { logger_id = logger_helper_enable(ECDH_LOGGER, LOGGER_DEBUG, true); }
7+
8+
int ecdh_logger_release() {
9+
logger_helper_release(logger_id);
10+
return 0;
11+
}
12+
13+
status_t rand_num_gen_init(mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg, char *rand_seed,
14+
uint16_t seed_len) {
15+
int ret = 1;
16+
status_t sc = SC_OK;
17+
18+
mbedtls_ctr_drbg_init(ctr_drbg);
19+
mbedtls_entropy_init(entropy);
20+
21+
if ((ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)rand_seed,
22+
seed_len)) != 0) {
23+
ta_log_error("mbedtls_ctr_drbg_seed returned %d\n", ret);
24+
sc = SC_CRYPTO_RAND_INIT;
25+
}
26+
27+
return sc;
28+
}
29+
30+
status_t ecdh_gen_public_key(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg, unsigned char *pkey) {
31+
int ret = 1;
32+
status_t sc = SC_OK;
33+
34+
ret = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_CURVE25519);
35+
if (ret != 0) {
36+
ta_log_error("mbedtls_ecp_group_load returned %d\n", ret);
37+
sc = SC_CRYPTO_GEN_PKEY;
38+
goto exit;
39+
}
40+
41+
ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, mbedtls_ctr_drbg_random, ctr_drbg);
42+
if (ret != 0) {
43+
ta_log_error("mbedtls_ecdh_gen_public returned %d\n", ret);
44+
sc = SC_CRYPTO_GEN_PKEY;
45+
goto exit;
46+
}
47+
48+
ret = mbedtls_mpi_write_binary(&ctx->Q.X, pkey, SHARE_DATA_LEN);
49+
if (ret != 0) {
50+
ta_log_error("mbedtls_mpi_write_binary returned %d\n", ret);
51+
sc = SC_CRYPTO_GEN_PKEY;
52+
}
53+
54+
exit:
55+
return sc;
56+
}
57+
58+
status_t ecdh_compute_shared_secret(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg,
59+
unsigned char *input_shared_data) {
60+
int ret = 1;
61+
status_t sc = SC_OK;
62+
63+
ret = mbedtls_mpi_lset(&ctx->Qp.Z, 1);
64+
if (ret != 0) {
65+
ta_log_error("mbedtls_mpi_lset returned %d\n", ret);
66+
sc = SC_CRYPTO_COMPUTE_SECRET;
67+
goto exit;
68+
}
69+
70+
ret = mbedtls_mpi_read_binary(&ctx->Qp.X, input_shared_data, SHARE_DATA_LEN);
71+
if (ret != 0) {
72+
ta_log_error("mbedtls_mpi_read_binary returned %d\n", ret);
73+
sc = SC_CRYPTO_COMPUTE_SECRET;
74+
goto exit;
75+
}
76+
77+
ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, mbedtls_ctr_drbg_random, ctr_drbg);
78+
if (ret != 0) {
79+
ta_log_error("mbedtls_ecdh_compute_shared returned %d\n", ret);
80+
sc = SC_CRYPTO_COMPUTE_SECRET;
81+
}
82+
83+
exit:
84+
return sc;
85+
}
86+
87+
void rand_num_gen_release(mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg) {
88+
mbedtls_ctr_drbg_free(ctr_drbg);
89+
mbedtls_entropy_free(entropy);
90+
}

crypto/ecdh.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (C) 2020 BiiLabs Co., Ltd. and Contributors
3+
* All Rights Reserved.
4+
* This is free software; you can redistribute it and/or modify it under the
5+
* terms of the MIT license. A copy of the license can be found in the file
6+
* "LICENSE" at the root of this distribution.
7+
*/
8+
9+
#ifndef ECDH_COMMON_H
10+
#define ECDH_COMMON_H
11+
12+
#include "common/logger.h"
13+
#include "common/ta_errors.h"
14+
#include "mbedtls/config.h"
15+
#include "mbedtls/ctr_drbg.h"
16+
#include "mbedtls/ecdh.h"
17+
#include "mbedtls/entropy.h"
18+
#include "mbedtls/platform.h"
19+
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
#define SHARE_DATA_LEN 32
25+
26+
typedef struct rand_gen_s {
27+
mbedtls_entropy_context entropy;
28+
mbedtls_ctr_drbg_context ctr_drbg;
29+
} rand_gen_t;
30+
31+
/**
32+
* Initialize logger for ECDH
33+
*/
34+
void ecdh_logger_init();
35+
36+
/**
37+
* Release logger
38+
*
39+
* @return
40+
* - zero on success
41+
* - EXIT_FAILURE on error
42+
*/
43+
int ecdh_logger_release();
44+
45+
/**
46+
* @brief Initialize mbedtls random number generator
47+
*
48+
* @param[in] entropy Entropy contrext for randomess
49+
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
50+
* @param[in] rand_seed Random seed for random number generator
51+
* @param[in] seed_len The length of random seed
52+
*
53+
* @return
54+
* - SC_OK on success
55+
* - non-zero on error
56+
*/
57+
status_t rand_num_gen_init(mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg, char *rand_seed,
58+
uint16_t seed_len);
59+
60+
/**
61+
* @brief Initialize ECDH context and generate ECDH keypair
62+
*
63+
* @param[in] ctx ECDH context
64+
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
65+
* @param[out] pkey Output public key which would be sent to counterpart
66+
*
67+
* @return
68+
* - SC_OK on success
69+
* - non-zero on error
70+
*/
71+
status_t ecdh_gen_public_key(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg, unsigned char *pkey);
72+
73+
/**
74+
* @brief Compute the shared secret by Diffie–Hellman key exchange protocol
75+
*
76+
* @param[in] ctx ECDH context
77+
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
78+
* @param[in] input_shared_data The public key sent by counterpart
79+
*
80+
* @return
81+
* - SC_OK on success
82+
* - non-zero on error
83+
*/
84+
status_t ecdh_compute_shared_secret(mbedtls_ecdh_context *ctx, mbedtls_ctr_drbg_context *ctr_drbg,
85+
unsigned char *input_shared_data);
86+
87+
/**
88+
* @brief Release random number generator
89+
*
90+
* @param[in] entropy Entropy contrext for randomess
91+
* @param[in] ctr_drbg Counter-mode block-cipher-based Deterministic Random Bit Generator object
92+
*
93+
* @return
94+
* - SC_OK on success
95+
* - non-zero on error
96+
*/
97+
void rand_num_gen_release(mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg);
98+
99+
#ifdef __cplusplus
100+
}
101+
#endif
102+
103+
#endif // ECDH_COMMON_H

tests/endpoint/common.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function validate_host() {
3434
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
3535
return 0
3636
fi
37-
if host "$1" > /dev/null 2>&1; then
37+
if host "$1" >/dev/null 2>&1; then
3838
return 0
3939
fi
4040
echo "Please enter a valid host or ip address"

tests/unit-test/BUILD

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,13 @@ cc_test(
9898
"//utils:tryte_byte_conv",
9999
],
100100
)
101+
102+
cc_binary(
103+
name = "test_ecdh",
104+
srcs = ["test_ecdh.c"],
105+
deps = [
106+
"//crypto:ecdh",
107+
"//tests:test_define",
108+
"@mbedtls",
109+
],
110+
)

tests/unit-test/test_ecdh.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (C) 2020 BiiLabs Co., Ltd. and Contributors
3+
* All Rights Reserved.
4+
* This is free software; you can redistribute it and/or modify it under the
5+
* terms of the MIT license. A copy of the license can be found in the file
6+
* "LICENSE" at the root of this distribution.
7+
*/
8+
9+
#include "crypto/ecdh.h"
10+
#include "tests/test_define.h"
11+
12+
void test_srv_cli_communication(void) {
13+
rand_gen_t rand_gen;
14+
mbedtls_ecdh_context ecdh_srv, ecdh_cli;
15+
unsigned char cli_to_srv[SHARE_DATA_LEN], srv_to_cli[SHARE_DATA_LEN];
16+
17+
// initialize ECDH object for server side and client side
18+
mbedtls_ecdh_init(&ecdh_srv);
19+
mbedtls_ecdh_init(&ecdh_cli);
20+
21+
TEST_ASSERT_EQUAL_INT32(SC_OK,
22+
rand_num_gen_init(&rand_gen.entropy, &rand_gen.ctr_drbg, TEST_UUID, strlen(TEST_UUID) + 1));
23+
24+
// [client] initialize ECDH context and generate public key
25+
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_gen_public_key(&ecdh_cli, &rand_gen.ctr_drbg, cli_to_srv));
26+
27+
// [server] initialize ECDH context and generate public key
28+
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_gen_public_key(&ecdh_srv, &rand_gen.ctr_drbg, srv_to_cli));
29+
30+
// [server] compute shared secret with peer's public key
31+
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_compute_shared_secret(&ecdh_srv, &rand_gen.ctr_drbg, cli_to_srv));
32+
33+
// [client] compute shared secret with peer's public key
34+
TEST_ASSERT_EQUAL_INT32(SC_OK, ecdh_compute_shared_secret(&ecdh_cli, &rand_gen.ctr_drbg, srv_to_cli));
35+
36+
// Check if the two shared secret are the same
37+
TEST_ASSERT_EQUAL_INT32(0, mbedtls_mpi_cmp_mpi(&ecdh_cli.z, &ecdh_srv.z));
38+
39+
rand_num_gen_release(&rand_gen.entropy, &rand_gen.ctr_drbg);
40+
mbedtls_ecdh_free(&ecdh_srv);
41+
mbedtls_ecdh_free(&ecdh_cli);
42+
}
43+
44+
int main(void) {
45+
UNITY_BEGIN();
46+
47+
// Initialize logger
48+
if (ta_logger_init() != SC_OK) {
49+
return EXIT_FAILURE;
50+
}
51+
52+
ecdh_logger_init();
53+
RUN_TEST(test_srv_cli_communication);
54+
ecdh_logger_release();
55+
56+
return UNITY_END();
57+
}

0 commit comments

Comments
 (0)