From c4ff670b0a5453f262ccdd0f9c136f4109703be0 Mon Sep 17 00:00:00 2001 From: Niklas Dusenlund Date: Mon, 12 Feb 2024 12:43:40 +0100 Subject: [PATCH] Make securechip an interface --- src/CMakeLists.txt | 1 + src/atecc/atecc.c | 7 +- src/atecc/atecc.h | 27 +-- src/common_main.c | 9 +- src/factorysetup.c | 8 +- src/keystore.c | 10 +- src/memory/memory_shared.c | 5 + src/memory/memory_shared.h | 4 + src/random.c | 6 +- src/reset.c | 6 +- src/rust/bitbox02-sys/build.rs | 10 +- src/rust/bitbox02-sys/wrapper.h | 2 +- src/rust/bitbox02/src/securechip.rs | 10 +- src/securechip/securechip.c | 158 ++++++++++++++++ src/securechip/securechip.h | 174 ++++++++++++++++++ src/u2f.c | 10 +- test/simulator/CMakeLists.txt | 2 +- .../{mock_atecc.c => mock_securechip.c} | 28 +-- test/unit-test/CMakeLists.txt | 2 +- .../{mock_atecc.c => mock_securechip.c} | 28 +-- test/unit-test/test_keystore.c | 2 +- test/unit-test/test_keystore_functional.c | 2 +- 22 files changed, 418 insertions(+), 93 deletions(-) create mode 100644 src/securechip/securechip.c create mode 100644 src/securechip/securechip.h rename test/simulator/framework/{mock_atecc.c => mock_securechip.c} (70%) rename test/unit-test/framework/{mock_atecc.c => mock_securechip.c} (70%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e16195959..2fee7912b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -143,6 +143,7 @@ set(PLATFORM-BITBOX02-SOURCES ${PLATFORM-BITBOX02-SOURCES} PARENT_SCOPE) set(SECURECHIP-SOURCES ${CMAKE_SOURCE_DIR}/src/atecc/atecc.c + ${CMAKE_SOURCE_DIR}/src/securechip/securechip.c ) set(SECURECHIP-SOURCES ${SECURECHIP-SOURCES} PARENT_SCOPE) diff --git a/src/atecc/atecc.c b/src/atecc/atecc.c index 52bf33b41..9f3863d24 100644 --- a/src/atecc/atecc.c +++ b/src/atecc/atecc.c @@ -14,6 +14,7 @@ #include "atecc.h" #include "hardfault.h" +#include "securechip/securechip.h" #include #include @@ -90,7 +91,7 @@ typedef union { #pragma GCC diagnostic pop -static const atecc_interface_functions_t* _interface_functions = NULL; +static const securechip_interface_functions_t* _interface_functions = NULL; /** \brief initialize an I2C interface using given config. * \param[in] hal - opaque ptr to HAL data @@ -378,7 +379,7 @@ static int _verify_config(void) return ATCA_SUCCESS; } -int atecc_setup(const atecc_interface_functions_t* ifs) +int atecc_setup(const securechip_interface_functions_t* ifs) { if (ifs == NULL) { return ATECC_ERR_IFS; @@ -781,7 +782,7 @@ bool atecc_u2f_counter_inc(uint32_t* counter) } #endif -bool atecc_model(atecc_model_t* model_out) +bool atecc_model(securechip_model_t* model_out) { uint8_t revision[4] = {0}; if (atcab_info(revision) != ATCA_SUCCESS) { diff --git a/src/atecc/atecc.h b/src/atecc/atecc.h index f19ace310..443732609 100644 --- a/src/atecc/atecc.h +++ b/src/atecc/atecc.h @@ -16,6 +16,7 @@ #define _ATECC_H_ #include "compiler_util.h" +#include "securechip/securechip.h" #include #include #include @@ -32,23 +33,6 @@ typedef enum { ATECC_ERR_INVALID_ARGS = -8, } atecc_error_t; -typedef struct { - /** - * @param[out] key_out must be of size 32 - */ - void (*const get_auth_key)(uint8_t* key_out); - /** - * @param[out] key_out must be of size 32 - */ - void (*const get_io_protection_key)(uint8_t* key_out); - /** - * @param[out] key_out must be of size 32 - */ - void (*const get_encryption_key)(uint8_t* key_out); - - void (*const random_32_bytes)(uint8_t* buf); -} atecc_interface_functions_t; - /** * Initializes the cryptoauthlib communication, by providing a custom i2c chip * communication interface/bridge to cryptoauthlib. On first call, the chip @@ -57,7 +41,7 @@ typedef struct { * @return values of `atecc_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on * success. */ -USE_RESULT int atecc_setup(const atecc_interface_functions_t* ifs); +USE_RESULT int atecc_setup(const securechip_interface_functions_t* ifs); /** * Updates the two KDF keys (rollkey and kdf key). The previous keys are lost @@ -150,16 +134,11 @@ USE_RESULT bool atecc_u2f_counter_set(uint32_t counter); USE_RESULT bool atecc_u2f_counter_inc(uint32_t* counter); #endif -typedef enum { - ATECC_ATECC608A, - ATECC_ATECC608B, -} atecc_model_t; - /** * Output the atecc model. * @param[out] model_out atecc model * @return True if success */ -USE_RESULT bool atecc_model(atecc_model_t* model_out); +USE_RESULT bool atecc_model(securechip_model_t* model_out); #endif diff --git a/src/common_main.c b/src/common_main.c index 1d979cb9e..002254c5a 100644 --- a/src/common_main.c +++ b/src/common_main.c @@ -13,7 +13,6 @@ // limitations under the License. #include "common_main.h" -#include "atecc/atecc.h" #include "driver_init.h" #include "flags.h" #include "hardfault.h" @@ -23,6 +22,7 @@ #include "memory/smarteeprom.h" #include "random.h" #include "screen.h" +#include "securechip/securechip.h" #include "util.h" #include @@ -45,7 +45,7 @@ static const memory_interface_functions_t _memory_interface_functions = { .random_32_bytes = random_32_bytes_mcu, }; -static const atecc_interface_functions_t _securechip_interface_functions = { +static const securechip_interface_functions_t _securechip_interface_functions = { .get_auth_key = memory_get_authorization_key, .get_io_protection_key = memory_get_io_protection_key, .get_encryption_key = memory_get_encryption_key, @@ -83,9 +83,12 @@ void common_main(void) /* Enable/configure SmartEEPROM. */ smarteeprom_bb02_config(); + if (!securechip_init()) { + AbortAutoenter("Failed to detect securechip"); + } // securechip_setup must come after memory_setup, so the io/auth keys to be // used are already initialized. - int securechip_result = atecc_setup(&_securechip_interface_functions); + int securechip_result = securechip_setup(&_securechip_interface_functions); if (securechip_result) { char errmsg[100] = {0}; snprintf( diff --git a/src/factorysetup.c b/src/factorysetup.c index 274d750ae..a112e4b3f 100644 --- a/src/factorysetup.c +++ b/src/factorysetup.c @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "atecc/atecc.h" #include "common_main.h" #include "driver_init.h" #include "flags.h" @@ -20,6 +19,7 @@ #include "memory/memory.h" #include "platform_init.h" #include "screen.h" +#include "securechip/securechip.h" #include "usb/usb.h" #include "usb/usb_packet.h" #include "usb/usb_processing.h" @@ -210,7 +210,7 @@ static void _api_msg(const uint8_t* input, size_t in_len, uint8_t* output, size_ case OP_GENKEY: { screen_print_debug("generating pubkey...", 0); uint8_t pubkey[64]; - if (!atecc_gen_attestation_key(pubkey)) { + if (!securechip_gen_attestation_key(pubkey)) { screen_print_debug("generating pubkey\nfailed", 0); result = ERR_FAILED; break; @@ -277,13 +277,13 @@ static void _api_msg(const uint8_t* input, size_t in_len, uint8_t* output, size_ screen_print_debug("DONE", 0); break; case OP_SC_ROLLKEYS: - if (!atecc_update_keys()) { + if (!securechip_update_keys()) { screen_print_debug("rollkeys: failed", 0); result = ERR_FAILED; break; } screen_print_debug("rollkeys: success", 100); - if (!atecc_u2f_counter_set(0)) { + if (!securechip_u2f_counter_set(0)) { screen_print_debug("reset u2f counter", 0); result = ERR_FAILED; break; diff --git a/src/keystore.c b/src/keystore.c index c90abf66c..ef17bd488 100644 --- a/src/keystore.c +++ b/src/keystore.c @@ -14,7 +14,6 @@ #include -#include "atecc/atecc.h" #include "cipher/cipher.h" #include "hardfault.h" #include "keystore.h" @@ -23,6 +22,7 @@ #include "random.h" #include "reset.h" #include "salt.h" +#include "securechip/securechip.h" #include "util.h" #include @@ -72,7 +72,7 @@ USE_RESULT static keystore_error_t _stretch_retained_seed_encryption_key( if (!salt_hash_data(encryption_key, 32, purpose_in, salted_hashed)) { return KEYSTORE_ERR_SALT; } - if (atecc_kdf(salted_hashed, 32, out)) { + if (securechip_kdf(salted_hashed, 32, out)) { return KEYSTORE_ERR_SECURECHIP; } if (!salt_hash_data(encryption_key, 32, purpose_out, salted_hashed)) { @@ -188,7 +188,7 @@ static keystore_error_t _stretch_password( memcpy(kdf_in, password_salted_hashed, 32); // First KDF on rollkey increments the monotonic counter. Call only once! - int securechip_result = atecc_kdf_rollkey(kdf_in, 32, kdf_out); + int securechip_result = securechip_kdf_rollkey(kdf_in, 32, kdf_out); if (securechip_result) { if (securechip_result_out != NULL) { *securechip_result_out = securechip_result; @@ -198,7 +198,7 @@ static keystore_error_t _stretch_password( // Second KDF does not use the counter and we call it multiple times. for (int i = 0; i < KDF_NUM_ITERATIONS; i++) { memcpy(kdf_in, kdf_out, 32); - securechip_result = atecc_kdf(kdf_in, 32, kdf_out); + securechip_result = securechip_kdf(kdf_in, 32, kdf_out); if (securechip_result) { if (securechip_result_out != NULL) { *securechip_result_out = securechip_result; @@ -302,7 +302,7 @@ keystore_error_t keystore_encrypt_and_store_seed( // Update the two kdf keys before setting a new password. This already // happens on a device reset, but we do it here again anyway so the keys are // initialized also on first use, reducing trust in the factory setup. - if (!atecc_update_keys()) { + if (!securechip_update_keys()) { return KEYSTORE_ERR_SECURECHIP; } uint8_t secret[32] = {0}; diff --git a/src/memory/memory_shared.c b/src/memory/memory_shared.c index 55c9ddebe..9488183e5 100644 --- a/src/memory/memory_shared.c +++ b/src/memory/memory_shared.c @@ -51,3 +51,8 @@ uint8_t memory_get_screen_type(void) return MEMORY_SCREEN_TYPE_SH1107; } } + +uint8_t memory_get_securechip_type(void) +{ + return MEMORY_SECURECHIP_TYPE_ATECC; +} diff --git a/src/memory/memory_shared.h b/src/memory/memory_shared.h index 4a4468256..5e8f8f985 100644 --- a/src/memory/memory_shared.h +++ b/src/memory/memory_shared.h @@ -102,4 +102,8 @@ void memory_read_shared_bootdata(chunk_shared_t* chunk_out); */ USE_RESULT uint8_t memory_get_screen_type(void); +#define MEMORY_SECURECHIP_TYPE_ATECC 0xFF +#define MEMORY_SECURECHIP_TYPE_OPTIGA 0x01 +USE_RESULT uint8_t memory_get_securechip_type(void); + #endif diff --git a/src/random.c b/src/random.c index 466888a61..40206d375 100644 --- a/src/random.c +++ b/src/random.c @@ -15,9 +15,9 @@ #include #include #ifndef TESTING -#include "atecc/atecc.h" #include "driver_init.h" #include "flags.h" +#include "securechip/securechip.h" #include #endif #include "hardfault.h" @@ -72,8 +72,8 @@ static void random_32_bytes_sec(uint8_t* buf) random[i] = rand(); } #else - if (!atecc_random(random)) { - Abort("Abort: atecc_random"); + if (!securechip_random(random)) { + Abort("Abort: securechip_random"); } #endif for (size_t i = 0; i < sizeof(random); i++) { diff --git a/src/reset.c b/src/reset.c index b29164e0a..c843ba49d 100644 --- a/src/reset.c +++ b/src/reset.c @@ -20,7 +20,7 @@ #include "memory/smarteeprom.h" #ifndef TESTING -#include "atecc/atecc.h" +#include "securechip/securechip.h" #include #include #include @@ -50,7 +50,7 @@ void reset_reset(bool status) #if !defined(TESTING) bool sc_result_update_keys = false; for (int retries = 0; retries < 5; retries++) { - sc_result_update_keys = atecc_update_keys(); + sc_result_update_keys = securechip_update_keys(); if (sc_result_update_keys) { break; } @@ -61,7 +61,7 @@ void reset_reset(bool status) #if APP_U2F == 1 bool sc_result_u2f_counter_set = false; for (int retries = 0; retries < 5; retries++) { - sc_result_u2f_counter_set = atecc_u2f_counter_set(0); + sc_result_u2f_counter_set = securechip_u2f_counter_set(0); if (sc_result_u2f_counter_set) { break; } diff --git a/src/rust/bitbox02-sys/build.rs b/src/rust/bitbox02-sys/build.rs index 34ff74df1..7bc80b41e 100644 --- a/src/rust/bitbox02-sys/build.rs +++ b/src/rust/bitbox02-sys/build.rs @@ -125,10 +125,10 @@ const ALLOWLIST_FNS: &[&str] = &[ "sd_write_bin", "sdcard_create", "secp256k1_ecdsa_anti_exfil_host_commit", - "atecc_attestation_sign", - "atecc_model", - "atecc_monotonic_increments_remaining", - "atecc_u2f_counter_set", + "securechip_attestation_sign", + "securechip_model", + "securechip_monotonic_increments_remaining", + "securechip_u2f_counter_set", "smarteeprom_bb02_config", "status_create", "trinary_choice_create", @@ -150,7 +150,7 @@ const RUSTIFIED_ENUMS: &[&str] = &[ "memory_result_t", "multisig_script_type_t", "output_type_t", - "atecc_model_t", + "securechip_model_t", "simple_type_t", "trinary_choice_t", ]; diff --git a/src/rust/bitbox02-sys/wrapper.h b/src/rust/bitbox02-sys/wrapper.h index 4b1f7f8ec..189c35823 100644 --- a/src/rust/bitbox02-sys/wrapper.h +++ b/src/rust/bitbox02-sys/wrapper.h @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include #include #include @@ -24,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rust/bitbox02/src/securechip.rs b/src/rust/bitbox02/src/securechip.rs index 773608a82..4ea29948e 100644 --- a/src/rust/bitbox02/src/securechip.rs +++ b/src/rust/bitbox02/src/securechip.rs @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use bitbox02_sys::atecc_model_t as Model; +pub use bitbox02_sys::securechip_model_t as Model; pub fn attestation_sign(challenge: &[u8; 32], signature: &mut [u8; 64]) -> Result<(), ()> { match unsafe { - bitbox02_sys::atecc_attestation_sign(challenge.as_ptr(), signature.as_mut_ptr()) + bitbox02_sys::securechip_attestation_sign(challenge.as_ptr(), signature.as_mut_ptr()) } { true => Ok(()), false => Err(()), @@ -25,7 +25,7 @@ pub fn attestation_sign(challenge: &[u8; 32], signature: &mut [u8; 64]) -> Resul pub fn monotonic_increments_remaining() -> Result { let mut result: u32 = 0; - match unsafe { bitbox02_sys::atecc_monotonic_increments_remaining(&mut result as _) } { + match unsafe { bitbox02_sys::securechip_monotonic_increments_remaining(&mut result as _) } { true => Ok(result), false => Err(()), } @@ -34,7 +34,7 @@ pub fn monotonic_increments_remaining() -> Result { #[cfg(feature = "app-u2f")] #[cfg(not(feature = "testing"))] pub fn u2f_counter_set(counter: u32) -> Result<(), ()> { - match unsafe { bitbox02_sys::atecc_u2f_counter_set(counter) } { + match unsafe { bitbox02_sys::securechip_u2f_counter_set(counter) } { true => Ok(()), false => Err(()), } @@ -48,7 +48,7 @@ pub fn u2f_counter_set(_counter: u32) -> Result<(), ()> { pub fn model() -> Result { let mut ver = core::mem::MaybeUninit::uninit(); - match unsafe { bitbox02_sys::atecc_model(ver.as_mut_ptr()) } { + match unsafe { bitbox02_sys::securechip_model(ver.as_mut_ptr()) } { true => Ok(unsafe { ver.assume_init() }), false => Err(()), } diff --git a/src/securechip/securechip.c b/src/securechip/securechip.c new file mode 100644 index 000000000..155a4a978 --- /dev/null +++ b/src/securechip/securechip.c @@ -0,0 +1,158 @@ +// Copyright 2024 Shift Crypto AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "securechip.h" +#include "atecc/atecc.h" +#include "hardfault.h" +#include "memory/memory_shared.h" + +typedef struct { + int (*setup)(const securechip_interface_functions_t* fns); + bool (*update_keys)(void); + int (*kdf)(const uint8_t* msg, size_t msg_len, uint8_t* kdf_out); + int (*kdf_rollkey)(const uint8_t* msg, size_t msg_len, uint8_t* kdf_out); + bool (*gen_attestation_key)(uint8_t* pubkey_out); + bool (*attestation_sign)(const uint8_t* challenge, uint8_t* signature_out); + bool (*monotonic_increments_remaining)(uint32_t* remaining_out); + bool (*random)(uint8_t* rand_out); + bool (*ecc_generate_public_key)(uint8_t* priv_key, uint8_t* pub_key); + bool (*ecc_unsafe_sign)(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig); +#if APP_U2F == 1 || FACTORYSETUP == 1 + bool (*u2f_counter_set)(uint32_t counter); +#endif +#if APP_U2F == 1 + bool (*u2f_counter_inc)(uint32_t* counter); +#endif + bool (*model)(securechip_model_t* model_out); +} securechip_crypt_interface_t; + +static securechip_crypt_interface_t _fns = {0}; + +// Detect if we have atecc or optiga chip and set interface functions +bool securechip_init(void) +{ + switch (memory_get_securechip_type()) { + case MEMORY_SECURECHIP_TYPE_OPTIGA: + Abort("Not implemented"); + break; + case MEMORY_SECURECHIP_TYPE_ATECC: + default: + _fns.setup = atecc_setup; + _fns.update_keys = atecc_update_keys; + _fns.kdf = atecc_kdf; + _fns.kdf_rollkey = atecc_kdf_rollkey; + _fns.gen_attestation_key = atecc_gen_attestation_key; + _fns.attestation_sign = atecc_attestation_sign; + _fns.monotonic_increments_remaining = atecc_monotonic_increments_remaining; + _fns.random = atecc_random; + _fns.ecc_generate_public_key = atecc_ecc_generate_public_key; + _fns.ecc_unsafe_sign = atecc_ecc_unsafe_sign; +#if APP_U2F == 1 || FACTORYSETUP == 1 + _fns.u2f_counter_set = atecc_u2f_counter_set; +#endif +#if APP_U2F == 1 + _fns.u2f_counter_inc = atecc_u2f_counter_inc; +#endif + _fns.model = atecc_model; + break; + } + return true; +} + +#define ABORT_IF_NULL(fn) \ + do { \ + if (_fns.fn == 0) { \ + Abort("No " #fn " function"); \ + } \ + } while (0) + +int securechip_setup(const securechip_interface_functions_t* ifs) +{ + ABORT_IF_NULL(setup); + return _fns.setup(ifs); +} + +bool securechip_update_keys(void) +{ + ABORT_IF_NULL(update_keys); + return _fns.update_keys(); +} + +int securechip_kdf(const uint8_t* msg, size_t msg_len, uint8_t* mac_out) +{ + ABORT_IF_NULL(kdf); + return _fns.kdf(msg, msg_len, mac_out); +} + +int securechip_kdf_rollkey(const uint8_t* msg, size_t msg_len, uint8_t* mac_out) +{ + ABORT_IF_NULL(kdf_rollkey); + return _fns.kdf_rollkey(msg, msg_len, mac_out); +} + +bool securechip_gen_attestation_key(uint8_t* pubkey_out) +{ + ABORT_IF_NULL(gen_attestation_key); + return _fns.gen_attestation_key(pubkey_out); +} + +bool securechip_attestation_sign(const uint8_t* challenge, uint8_t* signature_out) +{ + ABORT_IF_NULL(attestation_sign); + return _fns.attestation_sign(challenge, signature_out); +} + +bool securechip_monotonic_increments_remaining(uint32_t* remaining_out) +{ + ABORT_IF_NULL(monotonic_increments_remaining); + return _fns.monotonic_increments_remaining(remaining_out); +} + +bool securechip_random(uint8_t* rand_out) +{ + ABORT_IF_NULL(random); + return _fns.random(rand_out); +} + +bool securechip_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key) +{ + ABORT_IF_NULL(ecc_generate_public_key); + return _fns.ecc_generate_public_key(priv_key, pub_key); +} + +bool securechip_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig) +{ + ABORT_IF_NULL(ecc_unsafe_sign); + return _fns.ecc_unsafe_sign(priv_key, msg, sig); +} + +#if APP_U2F == 1 || FACTORYSETUP == 1 +bool securechip_u2f_counter_set(uint32_t counter) +{ + ABORT_IF_NULL(u2f_counter_set); + return _fns.u2f_counter_set(counter); +} +#endif +#if APP_U2F == 1 +bool securechip_u2f_counter_inc(uint32_t* counter) +{ + ABORT_IF_NULL(u2f_counter_inc); + return _fns.u2f_counter_inc(counter); +} +#endif +bool securechip_model(securechip_model_t* model_out) +{ + ABORT_IF_NULL(model); + return _fns.model(model_out); +} diff --git a/src/securechip/securechip.h b/src/securechip/securechip.h new file mode 100644 index 000000000..6def21c8e --- /dev/null +++ b/src/securechip/securechip.h @@ -0,0 +1,174 @@ +// Copyright 2019 Shift Cryptosecurity AG +// Copyright 2024 Shift Crypto AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SECURECHIP_H_ +#define _SECURECHIP_H_ + +#include "compiler_util.h" +#include +#include +#include +#include + +typedef enum { + SC_ERR_ZONE_UNLOCKED_CONFIG = -1, + SC_ERR_ZONE_UNLOCKED_DATA = -2, + SC_ERR_CONFIG_MISMATCH = -3, + SC_ERR_SLOT_UNLOCKED_IO = -4, + SC_ERR_SLOT_UNLOCKED_AUTH = -5, + SC_ERR_SLOT_UNLOCKED_ENC = -6, + SC_ERR_IFS = -7, + SC_ERR_INVALID_ARGS = -8, +} securechip_error_t; + +typedef struct { + /** + * @param[out] key_out must be of size 32 + */ + void (*const get_auth_key)(uint8_t* key_out); + /** + * @param[out] key_out must be of size 32 + */ + void (*const get_io_protection_key)(uint8_t* key_out); + /** + * @param[out] key_out must be of size 32 + */ + void (*const get_encryption_key)(uint8_t* key_out); + + void (*const random_32_bytes)(uint8_t* buf); +} securechip_interface_functions_t; + +/** + * Discovers what secure chip is used and configures the module to communicate with it. + * @return True if success + */ +USE_RESULT bool securechip_init(void); + +/** + * Initializes the cryptoauthlib communication, by providing a custom i2c chip + * communication interface/bridge to cryptoauthlib. On first call, the chip + * is configured and locked. + * @param[in] ifs Interface functions. + * @return values of `securechip_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on + * success. + */ +USE_RESULT int securechip_setup(const securechip_interface_functions_t* ifs); + +/** + * Updates the two KDF keys (rollkey and kdf key). The previous keys are lost + * and cannot be restored. Calling this function does not increment the + * monotonic counter Counter0. + * @return true on success. + */ +USE_RESULT bool securechip_update_keys(void); + +/** + * Perform KDF using the key in kdf slot with the input msg. + * @param[in] msg Use this msg as input + * @param[in] len Must be <= 127. + * @param[out] kdf_out Must have size 32. Result of the kdf will be stored here. + * Cannot be the same as `msg`. + * @return values of `securechip_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on + */ +USE_RESULT int securechip_kdf(const uint8_t* msg, size_t len, uint8_t* kdf_out); + +/** + * Perform KDF using the key in rollkey slot with the input msg. + * Calling this function increments the monotonic counter. + * @param[in] msg Use this msg as input + * @param[in] len Must be <= 127. + * @param[out] kdf_out Must have size 32. Result of the kdf will be stored here. + * Cannot be the same as `msg`. + * @return values of `securechip_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on + */ +USE_RESULT int securechip_kdf_rollkey(const uint8_t* msg, size_t len, uint8_t* kdf_out); + +/** + * Generates a new attestation device key and outputs the public key. + * @param[out] pubkey_out + */ +USE_RESULT bool securechip_gen_attestation_key(uint8_t* pubkey_out); + +/** + * @param[in] msg 32 byte message to sign. + * @param[out] signature_out must be 64 bytes. R/S P256 signature. + */ +USE_RESULT bool securechip_attestation_sign(const uint8_t* challenge, uint8_t* signature_out); + +/** + * Retrieves the number of remaining possible counter increments (max value - Counter0). + * The counter is increment when using `securechip_kdf()` (see its docstring). + * @param[out] remaining_out current value of the monotonic counter. + * @return false if there was a communication error with the SC. + */ +USE_RESULT bool securechip_monotonic_increments_remaining(uint32_t* remaining_out); + +/** + * @param[out] rand_out must be 32 bytes. + */ +USE_RESULT bool securechip_random(uint8_t* rand_out); + +/** + * Generates the matching public key to the provided private key. Will put private key in unsafe + * ECC slot. + * @param[in] priv_key Private key (32 bytes). + * @param[out] pub_key Public key. Format will be the X and Y coordinates in big-endian (64 bytes). + * @return True if success + */ +USE_RESULT bool securechip_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key); + +/** + * Sign hash with private key. Will put private key in unsafe ECC slot. + * @param[in] priv_key Private key to use for signing (32 bytes) + * @param[in] msg Message to sign (32 bytes) + * @param[out] sig Signature (64 bytes) + * @return True if success + */ +USE_RESULT bool securechip_ecc_unsafe_sign( + const uint8_t* priv_key, + const uint8_t* msg, + uint8_t* sig); + +#if APP_U2F == 1 || FACTORYSETUP == 1 +/** + * Set the u2f counter to `counter`. Should only be used for initialization. + * @param[in] counter Value to set counter to + * @return True if success + */ +USE_RESULT bool securechip_u2f_counter_set(uint32_t counter); +#endif + +#if APP_U2F == 1 +/** + * Monotonically increase the U2F counter and return the current value + * @param[out] counter Next counter value + * @return True if success + */ +USE_RESULT bool securechip_u2f_counter_inc(uint32_t* counter); +#endif + +typedef enum { + ATECC_ATECC608A, + ATECC_ATECC608B, +} securechip_model_t; + +/** + * Output the securechip model. + * @param[out] model_out securechip model + * @return True if success + */ +USE_RESULT bool securechip_model(securechip_model_t* model_out); + +#endif diff --git a/src/u2f.c b/src/u2f.c index 59d11e8bd..2f1ea1d04 100644 --- a/src/u2f.c +++ b/src/u2f.c @@ -17,12 +17,12 @@ #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -480,7 +480,7 @@ static void _register_continue(const USB_APDU* apdu, Packet* out_packet) if (!_keyhandle_gen(reg_request->appId, nonce, privkey, mac)) { continue; } - if (atecc_ecc_generate_public_key(privkey, (uint8_t*)&response->pubKey.x)) { + if (securechip_ecc_generate_public_key(privkey, (uint8_t*)&response->pubKey.x)) { break; } } @@ -504,7 +504,7 @@ static void _register_continue(const USB_APDU* apdu, Packet* out_packet) uint8_t hash[SHA256_LEN] = {0}; wally_sha256((uint8_t*)&sig_base, sizeof(sig_base), hash, SHA256_LEN); - if (!atecc_ecc_unsafe_sign(U2F_ATT_PRIV_KEY, hash, sig)) { + if (!securechip_ecc_unsafe_sign(U2F_ATT_PRIV_KEY, hash, sig)) { _error(U2F_SW_CONDITIONS_NOT_SATISFIED, out_packet); return; } @@ -666,7 +666,7 @@ static void _authenticate_continue(const USB_APDU* apdu, Packet* out_packet) U2F_AUTHENTICATE_RESP* response = (U2F_AUTHENTICATE_RESP*)&buf; uint32_t counter; - if (!atecc_u2f_counter_inc(&counter)) { + if (!securechip_u2f_counter_inc(&counter)) { _error(U2F_SW_CONDITIONS_NOT_SATISFIED, out_packet); return; } @@ -687,7 +687,7 @@ static void _authenticate_continue(const USB_APDU* apdu, Packet* out_packet) uint8_t hash[SHA256_LEN] = {0}; wally_sha256((uint8_t*)&sig_base, sizeof(sig_base), hash, SHA256_LEN); - if (!atecc_ecc_unsafe_sign(privkey, hash, sig)) { + if (!securechip_ecc_unsafe_sign(privkey, hash, sig)) { _error(U2F_SW_WRONG_DATA, out_packet); return; } diff --git a/test/simulator/CMakeLists.txt b/test/simulator/CMakeLists.txt index 9f906f989..7ce2c01ef 100644 --- a/test/simulator/CMakeLists.txt +++ b/test/simulator/CMakeLists.txt @@ -63,7 +63,7 @@ add_library(bitbox_objects-simulator framework/mock_memory.c framework/mock_screen.c framework/mock_smarteeprom.c - framework/mock_atecc.c + framework/mock_securechip.c ) add_library(bitbox-simulator diff --git a/test/simulator/framework/mock_atecc.c b/test/simulator/framework/mock_securechip.c similarity index 70% rename from test/simulator/framework/mock_atecc.c rename to test/simulator/framework/mock_securechip.c index b9fb75d4d..608db8c78 100644 --- a/test/simulator/framework/mock_atecc.c +++ b/test/simulator/framework/mock_securechip.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -25,11 +25,11 @@ typedef enum { SECURECHIP_SLOT_ROLLKEY = 3, SECURECHIP_SLOT_KDF = 4, -} atecc_slot_t; +} securechip_slot_t; static uint32_t _u2f_counter; -bool atecc_update_keys(void) +bool securechip_update_keys(void) { return true; } @@ -44,7 +44,7 @@ static const uint8_t _kdfkey[32] = "\xd2\xe1\xe6\xb1\x8b\x6c\x6b\x08\x43\x3e\xdb\xc1\xd1\x68\xc1\xa0\x04\x37\x74\xa4\x22\x18\x77" "\xe7\x9e\xd5\x66\x84\xbe\x5a\xc0\x1b"; -static int _securechip_kdf(atecc_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out) +static int _securechip_kdf(securechip_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out) { const uint8_t* key; switch (slot) { @@ -55,54 +55,54 @@ static int _securechip_kdf(atecc_slot_t slot, const uint8_t* msg, size_t len, ui key = _kdfkey; break; default: - return ATECC_ERR_INVALID_ARGS; + return SC_ERR_INVALID_ARGS; } wally_hmac_sha256(key, 32, msg, len, kdf_out, 32); return 0; } -int atecc_kdf(const uint8_t* msg, size_t len, uint8_t* kdf_out) +int securechip_kdf(const uint8_t* msg, size_t len, uint8_t* kdf_out) { return _securechip_kdf(SECURECHIP_SLOT_KDF, msg, len, kdf_out); } -int atecc_kdf_rollkey(const uint8_t* msg, size_t len, uint8_t* kdf_out) +int securechip_kdf_rollkey(const uint8_t* msg, size_t len, uint8_t* kdf_out) { return _securechip_kdf(SECURECHIP_SLOT_ROLLKEY, msg, len, kdf_out); } -bool atecc_u2f_counter_set(uint32_t counter) +bool securechip_u2f_counter_set(uint32_t counter) { _u2f_counter = counter; return true; } -bool atecc_u2f_counter_inc(uint32_t* counter) +bool securechip_u2f_counter_inc(uint32_t* counter) { *counter = _u2f_counter++; return true; } -bool atecc_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig) +bool securechip_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig) { return false; } -bool atecc_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key) +bool securechip_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key) { return false; } -bool atecc_attestation_sign(const uint8_t* msg, uint8_t* signature_out) +bool securechip_attestation_sign(const uint8_t* msg, uint8_t* signature_out) { return false; } -bool atecc_monotonic_increments_remaining(uint32_t* remaining_out) +bool securechip_monotonic_increments_remaining(uint32_t* remaining_out) { *remaining_out = 1; return true; } -bool atecc_model(atecc_model_t* model_out) +bool securechip_model(securechip_model_t* model_out) { *model_out = ATECC_ATECC608B; return true; diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index 7584a31ae..cf2874ecc 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -68,7 +68,7 @@ add_library(bitbox_objects framework/mock_gestures.c framework/mock_component.c framework/mock_smarteeprom.c - framework/mock_atecc.c + framework/mock_securechip.c framework/mock_delay.c ) diff --git a/test/unit-test/framework/mock_atecc.c b/test/unit-test/framework/mock_securechip.c similarity index 70% rename from test/unit-test/framework/mock_atecc.c rename to test/unit-test/framework/mock_securechip.c index 5a53b8190..cefeb6932 100644 --- a/test/unit-test/framework/mock_atecc.c +++ b/test/unit-test/framework/mock_securechip.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -26,11 +26,11 @@ typedef enum { SECURECHIP_SLOT_ROLLKEY = 3, SECURECHIP_SLOT_KDF = 4, -} atecc_slot_t; +} securechip_slot_t; static uint32_t _u2f_counter; -bool atecc_update_keys(void) +bool securechip_update_keys(void) { return true; } @@ -45,7 +45,7 @@ static const uint8_t _kdfkey[32] = "\xd2\xe1\xe6\xb1\x8b\x6c\x6b\x08\x43\x3e\xdb\xc1\xd1\x68\xc1\xa0\x04\x37\x74\xa4\x22\x18\x77" "\xe7\x9e\xd5\x66\x84\xbe\x5a\xc0\x1b"; -static int _securechip_kdf(atecc_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out) +static int _securechip_kdf(securechip_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out) { const uint8_t* key; switch (slot) { @@ -56,54 +56,54 @@ static int _securechip_kdf(atecc_slot_t slot, const uint8_t* msg, size_t len, ui key = _kdfkey; break; default: - return ATECC_ERR_INVALID_ARGS; + return SC_ERR_INVALID_ARGS; } wally_hmac_sha256(key, 32, msg, len, kdf_out, 32); return 0; } -int atecc_kdf(const uint8_t* msg, size_t len, uint8_t* kdf_out) +int securechip_kdf(const uint8_t* msg, size_t len, uint8_t* kdf_out) { return _securechip_kdf(SECURECHIP_SLOT_KDF, msg, len, kdf_out); } -int atecc_kdf_rollkey(const uint8_t* msg, size_t len, uint8_t* kdf_out) +int securechip_kdf_rollkey(const uint8_t* msg, size_t len, uint8_t* kdf_out) { return _securechip_kdf(SECURECHIP_SLOT_ROLLKEY, msg, len, kdf_out); } -bool atecc_u2f_counter_set(uint32_t counter) +bool securechip_u2f_counter_set(uint32_t counter) { _u2f_counter = counter; return true; } -bool atecc_u2f_counter_inc(uint32_t* counter) +bool securechip_u2f_counter_inc(uint32_t* counter) { *counter = _u2f_counter++; return true; } -bool atecc_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig) +bool securechip_ecc_unsafe_sign(const uint8_t* priv_key, const uint8_t* msg, uint8_t* sig) { return false; } -bool atecc_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key) +bool securechip_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key) { return false; } -bool atecc_attestation_sign(const uint8_t* msg, uint8_t* signature_out) +bool securechip_attestation_sign(const uint8_t* msg, uint8_t* signature_out) { return false; } -bool atecc_monotonic_increments_remaining(uint32_t* remaining_out) +bool securechip_monotonic_increments_remaining(uint32_t* remaining_out) { *remaining_out = 1; return true; } -bool atecc_model(atecc_model_t* model_out) +bool securechip_model(securechip_model_t* model_out) { *model_out = ATECC_ATECC608B; return true; diff --git a/test/unit-test/test_keystore.c b/test/unit-test/test_keystore.c index 741dc2a09..1dc109a2f 100644 --- a/test/unit-test/test_keystore.c +++ b/test/unit-test/test_keystore.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include #include diff --git a/test/unit-test/test_keystore_functional.c b/test/unit-test/test_keystore_functional.c index 6a3a1abb4..9de48edc4 100644 --- a/test/unit-test/test_keystore_functional.c +++ b/test/unit-test/test_keystore_functional.c @@ -19,11 +19,11 @@ #include -#include #include #include #include #include +#include #include #include