fixup! feat(core): Implement OPTIGA provisioning in prodtest.

Andrew Kozlik 11 months ago
parent fe5ca60637
commit 4a61ce9469

@ -132,31 +132,39 @@ static void vcp_write_as_hex(uint8_t *data, uint16_t len) {
} }
#ifdef USE_OPTIGA #ifdef USE_OPTIGA
static uint16_t get_byte_from_hex(const char *hex) { static uint16_t get_byte_from_hex(const char **hex) {
uint8_t result = 0; uint8_t result = 0;
// Skip whitespace.
while (**hex == ' ') {
*hex += 1;
}
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
result <<= 4; result <<= 4;
if (hex[i] >= '0' && hex[i] <= '9') { char c = **hex;
result |= hex[i] - '0'; if (c >= '0' && c <= '9') {
} else if (hex[i] >= 'A' && hex[i] <= 'F') { result |= c - '0';
result |= hex[i] - 'A' + 10; } else if (c >= 'A' && c <= 'F') {
} else if (hex[i] >= 'a' && hex[i] <= 'f') { result |= c - 'A' + 10;
result |= hex[i] - 'a' + 10; } else if (c >= 'a' && c <= 'f') {
} else if (hex[i] == '\0') { result |= c - 'a' + 10;
} else if (c == '\0') {
return 0x100; return 0x100;
} else { } else {
return 0xFFFF; return 0xFFFF;
} }
*hex += 1;
} }
return result; return result;
} }
static int get_from_hex(uint8_t *buf, uint16_t buf_len, const char *hex) { static int get_from_hex(uint8_t *buf, uint16_t buf_len, const char *hex) {
int len = 0; int len = 0;
uint16_t b = get_byte_from_hex(hex); uint16_t b = get_byte_from_hex(&hex);
for (len = 0; len < buf_len && b <= 0xff; ++len) { for (len = 0; len < buf_len && b <= 0xff; ++len) {
buf[len] = b; buf[len] = b;
b = get_byte_from_hex(hex + len * 2); b = get_byte_from_hex(&hex);
} }
if (b == 0x100) { if (b == 0x100) {
@ -650,6 +658,15 @@ bool set_metadata(uint16_t oid, const optiga_metadata *metadata) {
} }
bool pair_optiga(void) { bool pair_optiga(void) {
// The pairing key may already be written and locked. The success of the
// pairing procedure is determined by optiga_sec_chan_handshake(). Therefore
// it is OK for some of the intermediate operations to fail.
// Enable writing the pairing secret to OPTIGA.
optiga_metadata metadata = {0};
metadata.change = OPTIGA_ACCESS_ALWAYS;
set_metadata(OID_KEY_PAIRING, &metadata); // Ignore result.
// Generate pairing secret. // Generate pairing secret.
uint8_t secret[SECRET_OPTIGA_KEY_LEN] = {0}; uint8_t secret[SECRET_OPTIGA_KEY_LEN] = {0};
optiga_result ret = optiga_get_random(secret, sizeof(secret)); optiga_result ret = optiga_get_random(secret, sizeof(secret));
@ -692,7 +709,8 @@ void optiga_lock(void) {
} }
// Delete trust anchor. // Delete trust anchor.
optiga_result ret = optiga_set_data_object(0xe0e8, false, NULL, 0); optiga_result ret =
optiga_set_data_object(0xe0e8, false, (const uint8_t *)"\0", 1);
if (OPTIGA_SUCCESS != ret) { if (OPTIGA_SUCCESS != ret) {
vcp_printf("ERROR: optiga_set_data error %d for 0xe0e8.", ret); vcp_printf("ERROR: optiga_set_data error %d for 0xe0e8.", ret);
return; return;
@ -757,6 +775,8 @@ void optiga_lock(void) {
if (!set_metadata(OID_KEY_PAIRING, &metadata)) { if (!set_metadata(OID_KEY_PAIRING, &metadata)) {
return; return;
} }
vcp_printf("OK");
} }
void optigaid_read(void) { void optigaid_read(void) {
@ -790,6 +810,11 @@ void cert_read(uint16_t oid) {
} }
void cert_write(uint16_t oid, char *data) { void cert_write(uint16_t oid, char *data) {
// Enable writing to the certificate slot.
optiga_metadata metadata = {0};
metadata.change = OPTIGA_ACCESS_ALWAYS;
set_metadata(oid, &metadata); // Ignore result.
uint8_t data_bytes[1024]; uint8_t data_bytes[1024];
int len = get_from_hex(data_bytes, sizeof(data_bytes), data); int len = get_from_hex(data_bytes, sizeof(data_bytes), data);
@ -814,6 +839,7 @@ void pubkey_read(uint16_t oid) {
uint8_t key_usage = OPTIGA_KEY_USAGE_KEYAGREE; uint8_t key_usage = OPTIGA_KEY_USAGE_KEYAGREE;
metadata.key_usage.ptr = &key_usage; metadata.key_usage.ptr = &key_usage;
metadata.key_usage.len = 1; metadata.key_usage.len = 1;
metadata.execute = OPTIGA_ACCESS_ALWAYS;
if (!set_metadata(oid, &metadata)) { if (!set_metadata(oid, &metadata)) {
return; return;
@ -853,6 +879,7 @@ void keyfido_write(char *data) {
uint8_t key_usage = OPTIGA_KEY_USAGE_KEYAGREE; uint8_t key_usage = OPTIGA_KEY_USAGE_KEYAGREE;
metadata.key_usage.ptr = &key_usage; metadata.key_usage.ptr = &key_usage;
metadata.key_usage.len = 1; metadata.key_usage.len = 1;
metadata.execute = OPTIGA_ACCESS_ALWAYS;
if (!set_metadata(OID_KEY_DEV, &metadata)) { if (!set_metadata(OID_KEY_DEV, &metadata)) {
return; return;
@ -883,7 +910,7 @@ void keyfido_write(char *data) {
bn_write_be(&pub.y, public_key + 4 + 32); bn_write_be(&pub.y, public_key + 4 + 32);
// Execute ECDH with device private key. // Execute ECDH with device private key.
uint8_t secret[64] = {0}; uint8_t secret[32] = {0};
size_t secret_size = 0; size_t secret_size = 0;
optiga_result ret = optiga_calc_ssec(OPTIGA_CURVE_P256, OID_KEY_DEV, optiga_result ret = optiga_calc_ssec(OPTIGA_CURVE_P256, OID_KEY_DEV,
public_key, sizeof(public_key), secret, public_key, sizeof(public_key), secret,

Loading…
Cancel
Save