Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update crypto API to use a Microship secure element such as ATECC608A #236

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,9 @@ CMakeFiles
tinydtls.dir
Debug
Release

compile_commands.json

.cache/

libtinydtls.so*
27 changes: 25 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,25 @@ project(tinydtls)

include (AutoConf.cmake)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Include the toolchain file
if (CMAKE_SYSTEM_NAME STREQUAL "Generic" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm")
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()

if(NOT ZEPHYR_BASE)
option(BUILD_SHARED_LIBS "Link using shared libs" OFF)
option(BUILD_SHARED_LIBS "Link using shared libs" ON)
else()
# provided by the zephyr build system
endif()
Expand Down Expand Up @@ -72,8 +89,14 @@ target_sources(tinydtls PRIVATE
sha2/sha2.c
ecc/ecc.c)

target_include_directories(tinydtls PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_CRYPTOAUTHLIB_PATH "/usr/include/cryptoauthlib")

# Link cryptoauthlib to your project
target_link_libraries(tinydtls cryptoauth)
target_include_directories(tinydtls PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CRYPTOAUTHLIB_PATH} ${CMAKE_PLATFORM_SPE})
target_compile_definitions(tinydtls PUBLIC DTLSv12 WITH_SHA256 SHA2_USE_INTTYPES_H DTLS_CHECK_CONTENTTYPE)
# Add the preprocessor definition
target_compile_definitions(tinydtls PRIVATE DTLS_ATECC608A)

if(CMAKE_GENERATOR MATCHES "Visual Studio")
option(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS "Export all symbols when compiling to a .dll" ON)
Expand Down
132 changes: 130 additions & 2 deletions crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@
*
*******************************************************************************/

#include <stdbool.h>
#include <stdio.h>

#include "tinydtls.h"

#ifdef DTLS_ATECC608A
#include "cryptoauthlib.h"
#endif
#ifdef HAVE_ASSERT_H
#include <assert.h>
#else
Expand Down Expand Up @@ -56,6 +59,11 @@ memarray_t security_storage;

#endif /* RIOT_VERSION */

#ifdef DTLS_ATECC608A
ecdhe_slot_id_t *ecdhe_slots_id;
uint8_t ecdhe_nb_slots;
#endif

#define HMAC_UPDATE_SEED(Context,Seed,Length) \
if (Seed) dtls_hmac_update(Context, (Seed), (Length))

Expand All @@ -74,9 +82,11 @@ static void dtls_cipher_context_release(void)
}

#if !(defined (WITH_CONTIKI)) && !(defined (RIOT_VERSION))
#ifndef DTLS_ATECC608A
void crypto_init(void)
{
}
#endif

static dtls_handshake_parameters_t *dtls_handshake_malloc(void) {
return malloc(sizeof(dtls_handshake_parameters_t));
Expand Down Expand Up @@ -121,11 +131,32 @@ static void dtls_security_dealloc(dtls_security_parameters_t *security) {
}

#elif defined (RIOT_VERSION)

#ifndef DTLS_ATECC608A
void crypto_init(void) {
memarray_init(&handshake_storage, handshake_storage_data, sizeof(dtls_handshake_parameters_t), DTLS_HANDSHAKE_MAX);
memarray_init(&security_storage, security_storage_data, sizeof(dtls_security_parameters_t), DTLS_SECURITY_MAX);
}
#else
static ATCAIfaceCfg atecc608a;

void crypto_init(ATCAIfaceCfg *config)
{
printf("Using ATECC608A\n");
memarray_init(&handshake_storage, handshake_storage_data, sizeof(dtls_handshake_parameters_t), DTLS_HANDSHAKE_MAX);
memarray_init(&security_storage, security_storage_data, sizeof(dtls_security_parameters_t), DTLS_SECURITY_MAX);
atecc608a = *config;
ATCA_STATUS status = atcab_init(config);
if (status != ATCA_SUCCESS)
{
dtls_alert("atcab_init failed with ret=0x%08x\n", status);
return;
}
else
{
dtls_alert("atcab_init success\n");
}
}
#endif /* DTLS_ATECC608A */

static dtls_handshake_parameters_t *dtls_handshake_malloc(void) {
return memarray_alloc(&handshake_storage);
Expand Down Expand Up @@ -438,6 +469,18 @@ int dtls_ecdh_pre_master_secret(unsigned char *priv_key,
size_t key_size,
unsigned char *result,
size_t result_len) {
#if defined (DTLS_ATECC608A)
(void)result_len;
(void)priv_key;
unsigned char pub_key[2 * ATCA_KEY_SIZE];
memcpy(pub_key, pub_key_x, ATCA_KEY_SIZE);
memcpy(pub_key + ATCA_KEY_SIZE, pub_key_y, ATCA_KEY_SIZE);
ATCA_STATUS status = atcab_ecdh(priv_key[1], pub_key, result);
if (status != ATCA_SUCCESS) {
dtls_alert("Failed to generate pre-master secret\n");
return -1;
}
#else
uint32_t priv[8];
uint32_t pub_x[8];
uint32_t pub_y[8];
Expand All @@ -456,14 +499,55 @@ int dtls_ecdh_pre_master_secret(unsigned char *priv_key,
ecc_ecdh(pub_x, pub_y, priv, result_x, result_y);

dtls_ec_key_from_uint32(result_x, key_size, result);
#endif /* DTLS_ATECC608A */
return key_size;
}

#ifdef DTLS_ATECC608A
static ecdhe_slot_id_t get_ecdhe_slot_id(void)
{
for (int i = 0 ; i < ecdhe_nb_slots ; i++)
{
if (!(ecdhe_slots_id[i].usage))
{
ecdhe_slots_id[i].usage = 1;
return ecdhe_slots_id[i];
}
}
// No slot available
dtls_crit("No slot available\n");
ecdhe_slot_id_t slot_id = {0, 0};
return slot_id;
}
#endif

void
dtls_ecdsa_generate_key(unsigned char *priv_key,
unsigned char *pub_key_x,
unsigned char *pub_key_y,
size_t key_size) {
#if defined (DTLS_ATECC608A)
// We fill the private key with the slot id
(void)key_size;
ecdhe_slot_id_t slot_id = get_ecdhe_slot_id();
if (!slot_id.usage)
{
dtls_crit("No slot available\n");
return;
}

unsigned char pub_key[2 * key_size];
ATCA_STATUS status = atcab_genkey(slot_id.slot, pub_key);
if (status != ATCA_SUCCESS) {
dtls_crit("Failed to generate key\n");
}
else
{
memcpy(priv_key + 1, &(slot_id.slot), 1);
memcpy(pub_key_x, pub_key, key_size);
memcpy(pub_key_y, pub_key + key_size, key_size);
}
#else
uint32_t priv[8];
uint32_t pub_x[8];
uint32_t pub_y[8];
Expand All @@ -477,13 +561,30 @@ dtls_ecdsa_generate_key(unsigned char *priv_key,
dtls_ec_key_from_uint32(priv, key_size, priv_key);
dtls_ec_key_from_uint32(pub_x, key_size, pub_key_x);
dtls_ec_key_from_uint32(pub_y, key_size, pub_key_y);
#endif /* DTLS_ATECC608A */
}

/* rfc4492#section-5.4 */
void
dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
const unsigned char *sign_hash, size_t sign_hash_size,
uint32_t point_r[9], uint32_t point_s[9]) {
#if defined (DTLS_ATECC608A)
(void)sign_hash_size;
(void)priv_key;
ATCA_STATUS status;
unsigned char signature[2*key_size];

status = atcab_sign(priv_key[1], sign_hash, signature);
if (status != ATCA_SUCCESS) {
dtls_crit("Failed to sign hash\n");
}
else
{
dtls_ec_key_to_uint32(signature, key_size, point_r);
dtls_ec_key_to_uint32(signature + key_size, key_size, point_s);
}
#else
int ret;
uint32_t priv[8];
uint32_t hash[8];
Expand All @@ -495,6 +596,7 @@ dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
dtls_prng((unsigned char *)randv, key_size);
ret = ecc_ecdsa_sign(priv, hash, randv, point_r, point_s);
} while (ret);
#endif /* DTLS_ATECC608A */
}

void
Expand Down Expand Up @@ -522,6 +624,31 @@ dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x,
const unsigned char *pub_key_y, size_t key_size,
const unsigned char *sign_hash, size_t sign_hash_size,
unsigned char *result_r, unsigned char *result_s) {
#if defined (DTLS_ATECC608A)
(void)sign_hash_size;
unsigned char pub_key[2 * key_size];
memcpy(pub_key, pub_key_x, key_size);
memcpy(pub_key + key_size, pub_key_y, key_size);
unsigned char signature[2 * key_size];
memcpy(signature, result_r, key_size);
memcpy(signature + key_size, result_s, key_size);

int is_verified = 0;

ATCA_STATUS status = atcab_verify_extern(sign_hash, signature, pub_key, (bool*)&is_verified);
if (status != ATCA_SUCCESS) {
dtls_alert("Failed to verify signature : %x\n", status);
is_verified = -1;
}
else
{
if (is_verified == 0) {
dtls_alert("Signature is not verified\n");
is_verified = -1;
}
}
return is_verified;
#else
uint32_t pub_x[8];
uint32_t pub_y[8];
uint32_t hash[8];
Expand All @@ -535,6 +662,7 @@ dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x,
dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash);

return ecc_ecdsa_validate(pub_x, pub_y, hash, point_r, point_s);
#endif /* DTLS_ATECC608A */
}

int
Expand Down
33 changes: 33 additions & 0 deletions crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#include "hmac.h"
#include "ccm.h"

#ifdef DTLS_ATECC608A
#include "cryptoauthlib.h"
#endif /* ATECC608A */

/* TLS_PSK_WITH_AES_128_CCM_8 */
#define DTLS_MAC_KEY_LENGTH 0
#define DTLS_KEY_LENGTH 16 /* AES-128 */
Expand Down Expand Up @@ -220,6 +224,30 @@ typedef struct {
/* just for consistency */
#define dtls_kb_digest_size(Param, Role) DTLS_MAC_LENGTH

#ifdef DTLS_ATECC608A
/**
* @brief Structure used to store if a slot is already used by ECDHE operation or not.
*
*/
typedef struct
{
bool usage;
uint8_t slot;
} ecdhe_slot_id_t;

/**
* @brief List of slots used to perform ECDHE operation.
*
*/
extern ecdhe_slot_id_t *ecdhe_slots_id;

/**
* @brief Number of slots capable to perform ECDHE operation.
*
*/
extern uint8_t ecdhe_nb_slots;
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As short term work around, maybe.
But I guess, if a peer executes 2 handshakes simultaneously, that will fail.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CryptoAuthLib offers a mutex implementation. However, I suspect that if the handshake takes too long, a connection might fail due to timeout?


/**
* Expands the secret and key to a block of DTLS_HMAC_MAX
* size according to the algorithm specified in section 5 of
Expand Down Expand Up @@ -467,7 +495,12 @@ void dtls_handshake_free(dtls_handshake_parameters_t *handshake);
dtls_security_parameters_t *dtls_security_new(void);

void dtls_security_free(dtls_security_parameters_t *security);

#ifndef DTLS_ATECC608A
void crypto_init(void);
#else
void crypto_init(ATCAIfaceCfg *config);
#endif /* ATECC608A */

#endif /* _DTLS_CRYPTO_H_ */

Loading