Skip to content

Commit c38fa41

Browse files
benmaNickeZ
authored andcommitted
securechip: add initial Optiga implementation
This commit implements the securechip.h interface for the Optiga Trust M V3, with an interface and configuration roughly corresponding to how we use the ATECC608 secure chip: - An KDF key that is internally generated and cannot be read and written from the host MCU - A KDF key that is generated on the host - A monotonic counter attached to the first KDF key which limits the maxmium number of uses of the key over the lifetime of the device - Attestation key that is internally generated and used to sign attestation challenges The factory setup configures the metadata of each object we use, setting the state to Operational. After this, metadata cannot be changed, and the access conditions apply as specified. Shielded communication encrypts the communication with the chip and is active and enforced through the medata access configs. It roughly corresponds to IO protection in the ATECC608. In the ATECC608, we additionally authorize each command with the authorization_key, another pre-shared secret. The Optiga offers the same functionality, but we don't use it to authorize all commands, as it is reundnant to using the shielded communication in terms of enabling the host MCU to execute commands. Co-Authored-By: Niklas <niklas.dusenlund@bitbox.swiss>
1 parent 821a48f commit c38fa41

28 files changed

+2808
-161
lines changed

src/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,17 @@ set(PLATFORM-BITBOX02-SOURCES ${PLATFORM-BITBOX02-SOURCES} PARENT_SCOPE)
148148
set(SECURECHIP-SOURCES
149149
${CMAKE_SOURCE_DIR}/src/atecc/atecc.c
150150
${CMAKE_SOURCE_DIR}/src/securechip/securechip.c
151+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal.c
152+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_gpio.c
153+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_i2c.c
154+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_ifx_i2c_config.c
155+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_logger.c
156+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_os_datastore.c
157+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_os_event.c
158+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_os_lock.c
159+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_os_timer.c
160+
${CMAKE_SOURCE_DIR}/src/optiga/pal/pal_os_memory.c
161+
${CMAKE_SOURCE_DIR}/src/optiga/optiga.c
151162
)
152163
set(SECURECHIP-SOURCES ${SECURECHIP-SOURCES} PARENT_SCOPE)
153164

src/atecc/atecc.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ static ATCA_STATUS _lock_slot(atecc_slot_t slot)
234234
static ATCA_STATUS _factory_setup(void)
235235
{
236236
if (_interface_functions == NULL) {
237-
return (ATCA_STATUS)ATECC_ERR_IFS;
237+
return (ATCA_STATUS)SC_ERR_IFS;
238238
}
239239
bool is_config_locked = false;
240240
ATCA_STATUS result = atcab_is_locked(LOCK_ZONE_CONFIG, &is_config_locked);
@@ -336,14 +336,14 @@ static int _verify_config(void)
336336
return result;
337337
}
338338
if (!is_locked) {
339-
return ATECC_ERR_ZONE_UNLOCKED_CONFIG;
339+
return SC_ATECC_ERR_ZONE_UNLOCKED_CONFIG;
340340
}
341341
result = atcab_is_locked(LOCK_ZONE_DATA, &is_locked);
342342
if (result != ATCA_SUCCESS) {
343343
return result;
344344
}
345345
if (!is_locked) {
346-
return ATECC_ERR_ZONE_UNLOCKED_DATA;
346+
return SC_ATECC_ERR_ZONE_UNLOCKED_DATA;
347347
}
348348

349349
bool same_config = false;
@@ -352,7 +352,7 @@ static int _verify_config(void)
352352
return result;
353353
}
354354
if (!same_config) {
355-
return ATECC_ERR_CONFIG_MISMATCH;
355+
return SC_ERR_CONFIG_MISMATCH;
356356
}
357357

358358
// Check that the slots are individually locked.
@@ -361,29 +361,29 @@ static int _verify_config(void)
361361
return result;
362362
}
363363
if (!is_locked) {
364-
return ATECC_ERR_SLOT_UNLOCKED_IO;
364+
return SC_ATECC_ERR_SLOT_UNLOCKED_IO;
365365
}
366366
result = atcab_is_slot_locked(ATECC_SLOT_AUTHKEY, &is_locked);
367367
if (result != ATCA_SUCCESS) {
368368
return result;
369369
}
370370
if (!is_locked) {
371-
return ATECC_ERR_SLOT_UNLOCKED_AUTH;
371+
return SC_ATECC_ERR_SLOT_UNLOCKED_AUTH;
372372
}
373373
result = atcab_is_slot_locked(ATECC_SLOT_ENCRYPTION_KEY, &is_locked);
374374
if (result != ATCA_SUCCESS) {
375375
return result;
376376
}
377377
if (!is_locked) {
378-
return ATECC_ERR_SLOT_UNLOCKED_ENC;
378+
return SC_ATECC_ERR_SLOT_UNLOCKED_ENC;
379379
}
380380
return ATCA_SUCCESS;
381381
}
382382

383383
int atecc_setup(const securechip_interface_functions_t* ifs)
384384
{
385385
if (ifs == NULL) {
386-
return ATECC_ERR_IFS;
386+
return SC_ERR_IFS;
387387
}
388388
_interface_functions = ifs;
389389
ATCA_STATUS result = atcab_init(&cfg);
@@ -527,10 +527,10 @@ bool atecc_update_keys(void)
527527
static int _atecc_kdf(atecc_slot_t slot, const uint8_t* msg, size_t len, uint8_t* kdf_out)
528528
{
529529
if (len > 127 || (slot != ATECC_SLOT_ROLLKEY && slot != ATECC_SLOT_KDF)) {
530-
return ATECC_ERR_INVALID_ARGS;
530+
return SC_ERR_INVALID_ARGS;
531531
}
532532
if (msg == kdf_out) {
533-
return ATECC_ERR_INVALID_ARGS;
533+
return SC_ERR_INVALID_ARGS;
534534
}
535535

536536
ATCA_STATUS result = _authorize_key();

src/atecc/atecc.h

Lines changed: 3 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -15,112 +15,30 @@
1515
#ifndef _ATECC_H_
1616
#define _ATECC_H_
1717

18+
/* ATECC implementation of the secure chip functions. */
19+
/* See securechip.h for the docstrings of the individual functions. */
20+
1821
#include "compiler_util.h"
1922
#include "securechip/securechip.h"
2023
#include <platform/platform_config.h>
2124
#include <stdbool.h>
2225
#include <stddef.h>
2326
#include <stdint.h>
2427

25-
typedef enum {
26-
ATECC_ERR_ZONE_UNLOCKED_CONFIG = -1,
27-
ATECC_ERR_ZONE_UNLOCKED_DATA = -2,
28-
ATECC_ERR_CONFIG_MISMATCH = -3,
29-
ATECC_ERR_SLOT_UNLOCKED_IO = -4,
30-
ATECC_ERR_SLOT_UNLOCKED_AUTH = -5,
31-
ATECC_ERR_SLOT_UNLOCKED_ENC = -6,
32-
ATECC_ERR_IFS = -7,
33-
ATECC_ERR_INVALID_ARGS = -8,
34-
} atecc_error_t;
35-
36-
/**
37-
* Initializes the cryptoauthlib communication, by providing a custom i2c chip
38-
* communication interface/bridge to cryptoauthlib. On first call, the chip
39-
* is configured and locked.
40-
* @param[in] ifs Interface functions.
41-
* @return values of `atecc_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on
42-
* success.
43-
*/
4428
USE_RESULT int atecc_setup(const securechip_interface_functions_t* ifs);
45-
46-
/**
47-
* Updates the two KDF keys (rollkey and kdf key). The previous keys are lost
48-
* and cannot be restored. Calling this function does not increment the
49-
* monotonic counter Counter0.
50-
* @return true on success.
51-
*/
5229
USE_RESULT bool atecc_update_keys(void);
53-
54-
/**
55-
* Perform HMAC using the key in KDF slot with the input msg.
56-
* @param[in] msg Use this msg as input
57-
* @param[in] len Must be <= 127.
58-
* @param[out] kdf_out Must have size 32. Result of the kdf will be stored here.
59-
* Cannot be the same as `msg`.
60-
* @return values of `atecc_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on
61-
*/
6230
USE_RESULT int atecc_kdf(const uint8_t* msg, size_t len, uint8_t* kdf_out);
63-
64-
/**
65-
* Perform KDF using the key in rollkey slot with the input msg.
66-
* Calling this function increments the
67-
* monotonic counter Counter0.
68-
* @param[in] msg Use this msg as input
69-
* @param[in] len Must be <= 127.
70-
* @param[out] kdf_out Must have size 32. Result of the kdf will be stored here.
71-
* Cannot be the same as `msg`.
72-
* @return values of `securechip_error_t` if negative, values of `ATCA_STATUS` if positive, 0 on
73-
*/
7431
USE_RESULT int atecc_kdf_rollkey(const uint8_t* msg, size_t len, uint8_t* kdf_out);
75-
76-
/**
77-
* Generates a new attestation device key and outputs the public key.
78-
* @param[out] pubkey_out
79-
*/
8032
USE_RESULT bool atecc_gen_attestation_key(uint8_t* pubkey_out);
81-
82-
/**
83-
* @param[in] msg 32 byte message to sign.
84-
* @param[out] signature_out must be 64 bytes. R/S P256 signature.
85-
*/
8633
USE_RESULT bool atecc_attestation_sign(const uint8_t* challenge, uint8_t* signature_out);
87-
88-
/**
89-
* Retrieves the number of remaining possible counter increments (max value - Counter0).
90-
* The counter is increment when using `atecc_kdf()` (see its docstring).
91-
* @param[out] remaining_out current value of the monotonic counter.
92-
* @return false if there was a communication error with the SC.
93-
*/
9434
USE_RESULT bool atecc_monotonic_increments_remaining(uint32_t* remaining_out);
95-
96-
/**
97-
* @param[out] rand_out must be 32 bytes.
98-
*/
9935
USE_RESULT bool atecc_random(uint8_t* rand_out);
100-
10136
#if APP_U2F == 1 || FACTORYSETUP == 1
102-
/**
103-
* Set the u2f counter to `counter`. Should only be used for initialization.
104-
* @param[in] counter Value to set counter to
105-
* @return True if success
106-
*/
10737
USE_RESULT bool atecc_u2f_counter_set(uint32_t counter);
10838
#endif
109-
11039
#if APP_U2F == 1
111-
/**
112-
* Monotonically increase the U2F counter and return the current value
113-
* @param[out] counter Next counter value
114-
* @return True if success
115-
*/
11640
USE_RESULT bool atecc_u2f_counter_inc(uint32_t* counter);
11741
#endif
118-
119-
/**
120-
* Output the atecc model.
121-
* @param[out] model_out atecc model
122-
* @return True if success
123-
*/
12442
USE_RESULT bool atecc_model(securechip_model_t* model_out);
12543

12644
#endif

src/memory/memory_shared.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,14 @@ uint8_t memory_get_screen_type(void)
5454

5555
uint8_t memory_get_securechip_type(void)
5656
{
57-
return MEMORY_SECURECHIP_TYPE_ATECC;
57+
chunk_shared_t chunk = {0};
58+
memory_read_shared_bootdata(&chunk);
59+
uint8_t securechip_type = chunk.fields.securechip_type;
60+
util_zero(&chunk, sizeof(chunk));
61+
switch (securechip_type) {
62+
case MEMORY_SECURECHIP_TYPE_OPTIGA:
63+
return securechip_type;
64+
default:
65+
return MEMORY_SECURECHIP_TYPE_ATECC;
66+
}
5867
}

src/memory/memory_shared.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ typedef union {
7575
uint8_t auto_enter;
7676
uint8_t upside_down;
7777
uint8_t screen_type;
78+
uint8_t securechip_type;
7879
// Following are used by firmware only
79-
uint8_t reserved[1];
8080
uint8_t io_protection_key_split[32];
8181
uint8_t authorization_key_split[32];
8282
uint8_t encryption_key_split[32];

0 commit comments

Comments
 (0)