1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-23 14:58:09 +00:00

refactor(core): Clean up Optiga error handling.

[no changelog]
This commit is contained in:
Andrew Kozlik 2024-06-26 10:09:38 +02:00 committed by Andrew Kozlik
parent 99c3d35e07
commit fc09379877
6 changed files with 305 additions and 242 deletions

View File

@ -90,11 +90,12 @@ STATIC mp_obj_t mod_trezorcrypto_optiga_sign(mp_obj_t key_index,
vstr_t sig = {0}; vstr_t sig = {0};
vstr_init_len(&sig, MAX_DER_SIGNATURE_SIZE); vstr_init_len(&sig, MAX_DER_SIGNATURE_SIZE);
size_t sig_size = 0; size_t sig_size = 0;
int ret = optiga_sign(idx, (const uint8_t *)dig.buf, dig.len, optiga_sign_result ret =
((uint8_t *)sig.buf), sig.alloc, &sig_size); optiga_sign(idx, (const uint8_t *)dig.buf, dig.len, ((uint8_t *)sig.buf),
if (ret != 0) { sig.alloc, &sig_size);
if (ret != OPTIGA_SIGN_SUCCESS) {
vstr_clear(&sig); vstr_clear(&sig);
if (ret == OPTIGA_ERR_ACCESS_COND_NOT_SAT) { if (ret == OPTIGA_SIGN_INACCESSIBLE) {
mp_raise_msg(&mp_type_SigningInaccessible, "Signing inaccessible."); mp_raise_msg(&mp_type_SigningInaccessible, "Signing inaccessible.");
} else { } else {
mp_raise_msg(&mp_type_OptigaError, "Signing failed."); mp_raise_msg(&mp_type_OptigaError, "Signing failed.");

View File

@ -28,16 +28,20 @@
#define OPTIGA_DEVICE_CERT_INDEX 1 #define OPTIGA_DEVICE_CERT_INDEX 1
#define OPTIGA_DEVICE_ECC_KEY_INDEX 0 #define OPTIGA_DEVICE_ECC_KEY_INDEX 0
#define OPTIGA_COMMAND_ERROR_OFFSET 0x100
// Error code 0x07: Access conditions not satisfied typedef enum _optiga_pin_result {
#define OPTIGA_ERR_ACCESS_COND_NOT_SAT (OPTIGA_COMMAND_ERROR_OFFSET + 0x07) OPTIGA_PIN_SUCCESS = 0, // The operation completed successfully.
OPTIGA_PIN_INVALID, // The PIN is invalid.
OPTIGA_PIN_COUNTER_EXCEEDED, // The PIN try counter limit was exceeded.
OPTIGA_PIN_ERROR, // Optiga processing or communication error.
} optiga_pin_result;
// Error code 0x0E: Counter threshold limit exceeded typedef enum _optiga_sign_result {
#define OPTIGA_ERR_COUNTER_EXCEEDED (OPTIGA_COMMAND_ERROR_OFFSET + 0x0E) OPTIGA_SIGN_SUCCESS = 0, // The operation completed successfully.
OPTIGA_SIGN_INACCESSIBLE, // The signing key is inaccessible.
// Error code 0x2F: Authorization failure OPTIGA_SIGN_ERROR, // Invalid parameters or Optiga processing or
#define OPTIGA_ERR_AUTH_FAIL (OPTIGA_COMMAND_ERROR_OFFSET + 0x2F) // communication error.
} optiga_sign_result;
// Size of secrets used in PIN processing, e.g. salted PIN, master secret etc. // Size of secrets used in PIN processing, e.g. salted PIN, master secret etc.
#define OPTIGA_PIN_SECRET_SIZE 32 #define OPTIGA_PIN_SECRET_SIZE 32
@ -50,9 +54,9 @@
typedef secbool (*OPTIGA_UI_PROGRESS)(uint32_t elapsed_ms); typedef secbool (*OPTIGA_UI_PROGRESS)(uint32_t elapsed_ms);
int __wur optiga_sign(uint8_t index, const uint8_t *digest, size_t digest_size, optiga_sign_result __wur optiga_sign(uint8_t index, const uint8_t *digest,
uint8_t *signature, size_t max_sig_size, size_t digest_size, uint8_t *signature,
size_t *sig_size); size_t max_sig_size, size_t *sig_size);
bool __wur optiga_cert_size(uint8_t index, size_t *cert_size); bool __wur optiga_cert_size(uint8_t index, size_t *cert_size);
@ -63,13 +67,15 @@ bool __wur optiga_read_sec(uint8_t *sec);
bool __wur optiga_random_buffer(uint8_t *dest, size_t size); bool __wur optiga_random_buffer(uint8_t *dest, size_t size);
int __wur optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress, bool __wur optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]); uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]);
int __wur optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress, optiga_pin_result __wur
optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]); uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]);
int __wur optiga_pin_verify_v4(OPTIGA_UI_PROGRESS ui_progress, optiga_pin_result __wur
optiga_pin_verify_v4(OPTIGA_UI_PROGRESS ui_progress,
const uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE], const uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE],
uint8_t out_secret[OPTIGA_PIN_SECRET_SIZE]); uint8_t out_secret[OPTIGA_PIN_SECRET_SIZE]);

View File

@ -89,34 +89,36 @@ static const optiga_metadata_item ACCESS_PIN_HMAC_CTR =
// Size of the CMAC/HMAC prefix returned by Optiga. // Size of the CMAC/HMAC prefix returned by Optiga.
#define ENCRYPT_SYM_PREFIX_SIZE 3 #define ENCRYPT_SYM_PREFIX_SIZE 3
int optiga_sign(uint8_t index, const uint8_t *digest, size_t digest_size, optiga_sign_result optiga_sign(uint8_t index, const uint8_t *digest,
uint8_t *signature, size_t max_sig_size, size_t *sig_size) { size_t digest_size, uint8_t *signature,
size_t max_sig_size, size_t *sig_size) {
if (index >= OPTIGA_ECC_KEY_COUNT) { if (index >= OPTIGA_ECC_KEY_COUNT) {
return OPTIGA_ERR_PARAM; return OPTIGA_SIGN_ERROR;
} }
optiga_result ret = optiga_result res =
optiga_calc_sign(OPTIGA_OID_ECC_KEY + index, digest, digest_size, optiga_calc_sign(OPTIGA_OID_ECC_KEY + index, digest, digest_size,
&signature[2], max_sig_size - 2, sig_size); &signature[2], max_sig_size - 2, sig_size);
if (ret == OPTIGA_ERR_CMD) { if (res != OPTIGA_SUCCESS) {
uint8_t error_code = 0; uint8_t error_code = 0;
(void)optiga_get_error_code(&error_code); if (res == OPTIGA_ERR_CMD &&
return error_code + OPTIGA_COMMAND_ERROR_OFFSET; optiga_get_error_code(&error_code) == OPTIGA_SUCCESS &&
error_code == OPTIGA_ERR_CODE_ACCESS_COND) {
return OPTIGA_SIGN_INACCESSIBLE;
} else {
return OPTIGA_SIGN_ERROR;
} }
if (ret != OPTIGA_SUCCESS) {
return ret;
} }
// Add sequence tag and length. // Add sequence tag and length.
if (*sig_size >= 0x80) { if (*sig_size >= 0x80) {
// Length not supported. // Length not supported.
return OPTIGA_ERR_SIZE; return OPTIGA_SIGN_ERROR;
} }
signature[0] = 0x30; signature[0] = 0x30;
signature[1] = *sig_size; signature[1] = *sig_size;
*sig_size += 2; *sig_size += 2;
return OPTIGA_SUCCESS; return OPTIGA_SIGN_SUCCESS;
} }
bool optiga_cert_size(uint8_t index, size_t *cert_size) { bool optiga_cert_size(uint8_t index, size_t *cert_size) {
@ -188,28 +190,24 @@ bool optiga_random_buffer(uint8_t *dest, size_t size) {
static bool read_metadata(uint16_t oid, optiga_metadata *metadata) { static bool read_metadata(uint16_t oid, optiga_metadata *metadata) {
static uint8_t serialized[OPTIGA_MAX_METADATA_SIZE] = {0}; static uint8_t serialized[OPTIGA_MAX_METADATA_SIZE] = {0};
size_t size = 0; size_t size = 0;
optiga_result ret = if (optiga_get_data_object(oid, true, serialized, sizeof(serialized),
optiga_get_data_object(oid, true, serialized, sizeof(serialized), &size); &size) != OPTIGA_SUCCESS) {
if (OPTIGA_SUCCESS != ret) {
return false; return false;
} }
ret = optiga_parse_metadata(serialized, size, metadata); return optiga_parse_metadata(serialized, size, metadata) == OPTIGA_SUCCESS;
return OPTIGA_SUCCESS == ret;
} }
static bool write_metadata(uint16_t oid, const optiga_metadata *metadata) { static bool write_metadata(uint16_t oid, const optiga_metadata *metadata) {
uint8_t serialized[OPTIGA_MAX_METADATA_SIZE] = {0}; uint8_t serialized[OPTIGA_MAX_METADATA_SIZE] = {0};
size_t size = 0; size_t size = 0;
optiga_result ret = optiga_serialize_metadata(metadata, serialized, if (optiga_serialize_metadata(metadata, serialized, sizeof(serialized),
sizeof(serialized), &size); &size) != OPTIGA_SUCCESS) {
if (OPTIGA_SUCCESS != ret) {
return false; return false;
} }
ret = optiga_set_data_object(oid, true, serialized, size); return optiga_set_data_object(oid, true, serialized, size) == OPTIGA_SUCCESS;
return OPTIGA_SUCCESS == ret;
} }
bool optiga_set_metadata(uint16_t oid, const optiga_metadata *metadata) { bool optiga_set_metadata(uint16_t oid, const optiga_metadata *metadata) {
@ -353,28 +351,22 @@ static bool optiga_pin_init_metadata(void) {
return true; return true;
} }
static int optiga_pin_init_stretch(void) { static bool optiga_pin_init_stretch(void) {
// Generate a new key in OID_PIN_CMAC. // Generate a new key in OID_PIN_CMAC.
optiga_result res = if (optiga_gen_sym_key(OPTIGA_AES_256, OPTIGA_KEY_USAGE_ENC, OID_PIN_CMAC) !=
optiga_gen_sym_key(OPTIGA_AES_256, OPTIGA_KEY_USAGE_ENC, OID_PIN_CMAC); OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { return false;
return res;
} }
// Generate a new key in OID_PIN_ECDH. // Generate a new key in OID_PIN_ECDH.
uint8_t public_key[6 + 65] = {0}; uint8_t public_key[6 + 65] = {0};
size_t size = 0; size_t size = 0;
res = return optiga_gen_key_pair(OPTIGA_CURVE_P256, OPTIGA_KEY_USAGE_KEYAGREE,
optiga_gen_key_pair(OPTIGA_CURVE_P256, OPTIGA_KEY_USAGE_KEYAGREE, OID_PIN_ECDH, public_key, sizeof(public_key),
OID_PIN_ECDH, public_key, sizeof(public_key), &size); &size) == OPTIGA_SUCCESS;
if (res != OPTIGA_SUCCESS) {
return res;
}
return OPTIGA_SUCCESS;
} }
static int optiga_pin_stretch_common( static bool optiga_pin_stretch_common(
OPTIGA_UI_PROGRESS ui_progress, HMAC_SHA256_CTX *ctx, OPTIGA_UI_PROGRESS ui_progress, HMAC_SHA256_CTX *ctx,
const uint8_t input[OPTIGA_PIN_SECRET_SIZE], bool version4) { const uint8_t input[OPTIGA_PIN_SECRET_SIZE], bool version4) {
// Implements the functionality that is common to // Implements the functionality that is common to
@ -383,26 +375,25 @@ static int optiga_pin_stretch_common(
uint8_t buffer[ENCRYPT_SYM_PREFIX_SIZE + OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t buffer[ENCRYPT_SYM_PREFIX_SIZE + OPTIGA_PIN_SECRET_SIZE] = {0};
size_t size = 0; size_t size = 0;
bool ret = true;
// Combine intermediate result with OID_PIN_CMAC. // Combine intermediate result with OID_PIN_CMAC.
optiga_result res = if (optiga_encrypt_sym(OPTIGA_SYM_MODE_CMAC, OID_PIN_CMAC, input,
optiga_encrypt_sym(OPTIGA_SYM_MODE_CMAC, OID_PIN_CMAC, input, OPTIGA_PIN_SECRET_SIZE, buffer, sizeof(buffer),
OPTIGA_PIN_SECRET_SIZE, buffer, sizeof(buffer), &size); &size) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
memzero(buffer, sizeof(buffer)); goto end;
return res;
} }
hmac_sha256_Update(ctx, buffer, size); hmac_sha256_Update(ctx, buffer, size);
if (version4) { if (version4) {
// Combine intermediate result with OID_PIN_HMAC // Combine intermediate result with OID_PIN_HMAC
res = optiga_encrypt_sym(OPTIGA_SYM_MODE_HMAC_SHA256, OID_PIN_HMAC_V4, if (optiga_encrypt_sym(OPTIGA_SYM_MODE_HMAC_SHA256, OID_PIN_HMAC_V4, input,
input, OPTIGA_PIN_SECRET_SIZE, buffer, OPTIGA_PIN_SECRET_SIZE, buffer, sizeof(buffer),
sizeof(buffer), &size); &size) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
memzero(buffer, sizeof(buffer)); goto end;
return res;
} }
hmac_sha256_Update(ctx, buffer, size); hmac_sha256_Update(ctx, buffer, size);
@ -411,25 +402,28 @@ static int optiga_pin_stretch_common(
// Combine intermediate result with OID_PIN_ECDH // Combine intermediate result with OID_PIN_ECDH
uint8_t encoded_point[BIT_STRING_HEADER_SIZE + 65] = {0x03, 0x42, 0x00}; uint8_t encoded_point[BIT_STRING_HEADER_SIZE + 65] = {0x03, 0x42, 0x00};
if (!hash_to_curve_optiga(input, &encoded_point[BIT_STRING_HEADER_SIZE])) { if (!hash_to_curve_optiga(input, &encoded_point[BIT_STRING_HEADER_SIZE])) {
memzero(buffer, sizeof(buffer)); ret = false;
return -1; goto end;
} }
res = optiga_calc_ssec(OPTIGA_CURVE_P256, OID_PIN_ECDH, encoded_point,
sizeof(encoded_point), buffer, sizeof(buffer), &size); if (optiga_calc_ssec(OPTIGA_CURVE_P256, OID_PIN_ECDH, encoded_point,
memzero(encoded_point, sizeof(encoded_point)); sizeof(encoded_point), buffer, sizeof(buffer),
if (res != OPTIGA_SUCCESS) { &size) != OPTIGA_SUCCESS) {
memzero(buffer, sizeof(buffer)); ret = false;
return res; goto end;
} }
ui_progress(250); ui_progress(250);
hmac_sha256_Update(ctx, buffer, size); hmac_sha256_Update(ctx, buffer, size);
end:
memzero(encoded_point, sizeof(encoded_point));
memzero(buffer, sizeof(buffer)); memzero(buffer, sizeof(buffer));
return OPTIGA_SUCCESS; return ret;
} }
static int optiga_pin_stretch_secret_v4( static bool optiga_pin_stretch_secret_v4(
OPTIGA_UI_PROGRESS ui_progress, uint8_t secret[OPTIGA_PIN_SECRET_SIZE]) { OPTIGA_UI_PROGRESS ui_progress, uint8_t secret[OPTIGA_PIN_SECRET_SIZE]) {
// Legacy PIN verification method used in storage versions 3 and 4. // Legacy PIN verification method used in storage versions 3 and 4.
@ -451,19 +445,16 @@ static int optiga_pin_stretch_secret_v4(
HMAC_SHA256_CTX ctx = {0}; HMAC_SHA256_CTX ctx = {0};
hmac_sha256_Init(&ctx, secret, OPTIGA_PIN_SECRET_SIZE); hmac_sha256_Init(&ctx, secret, OPTIGA_PIN_SECRET_SIZE);
optiga_result res = bool ret = optiga_pin_stretch_common(ui_progress, &ctx, secret, true);
optiga_pin_stretch_common(ui_progress, &ctx, secret, true); if (ret) {
if (res != OPTIGA_SUCCESS) { hmac_sha256_Final(&ctx, secret);
memzero(&ctx, sizeof(ctx));
return res;
} }
hmac_sha256_Final(&ctx, secret);
memzero(&ctx, sizeof(ctx)); memzero(&ctx, sizeof(ctx));
return OPTIGA_SUCCESS; return ret;
} }
static int optiga_pin_stretch_cmac_ecdh( static bool optiga_pin_stretch_cmac_ecdh(
OPTIGA_UI_PROGRESS ui_progress, OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) { uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) {
// This step hardens the PIN verification process in case an attacker is able // This step hardens the PIN verification process in case an attacker is able
@ -483,6 +474,7 @@ static int optiga_pin_stretch_cmac_ecdh(
// ecdh_out = ECDH(OID_PIN_ECDH, digest) // ecdh_out = ECDH(OID_PIN_ECDH, digest)
// stretched_pin = HMAC-SHA256(stretched_pin, cmac_out || ecdh_out) // stretched_pin = HMAC-SHA256(stretched_pin, cmac_out || ecdh_out)
bool ret = true;
uint8_t digest[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t digest[OPTIGA_PIN_SECRET_SIZE] = {0};
HMAC_SHA256_CTX ctx = {0}; HMAC_SHA256_CTX ctx = {0};
for (int i = 0; i < PIN_STRETCH_ITERATIONS; ++i) { for (int i = 0; i < PIN_STRETCH_ITERATIONS; ++i) {
@ -493,32 +485,25 @@ static int optiga_pin_stretch_cmac_ecdh(
hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, NULL, 0, digest); hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, NULL, 0, digest);
hmac_sha256_Init(&ctx, stretched_pin, OPTIGA_PIN_SECRET_SIZE); hmac_sha256_Init(&ctx, stretched_pin, OPTIGA_PIN_SECRET_SIZE);
optiga_result res = if (!optiga_pin_stretch_common(ui_progress, &ctx, digest, false)) {
optiga_pin_stretch_common(ui_progress, &ctx, digest, false); ret = false;
if (res != OPTIGA_SUCCESS) { goto end;
memzero(digest, sizeof(digest));
memzero(&ctx, sizeof(ctx));
return res;
} }
hmac_sha256_Final(&ctx, stretched_pin); hmac_sha256_Final(&ctx, stretched_pin);
} }
end:
memzero(digest, sizeof(digest)); memzero(digest, sizeof(digest));
memzero(&ctx, sizeof(ctx)); memzero(&ctx, sizeof(ctx));
return OPTIGA_SUCCESS; return ret;
} }
int optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress, bool optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) { uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) {
int res = OPTIGA_SUCCESS; bool ret = true;
if (!optiga_pin_init_metadata()) { if (!optiga_pin_init_metadata() || !optiga_pin_init_stretch()) {
res = -1; ret = false;
goto end;
}
res = optiga_pin_init_stretch();
if (res != OPTIGA_SUCCESS) {
goto end; goto end;
} }
@ -528,38 +513,38 @@ int optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
// ensures that if an attacker extracts the value of OID_STRETCHED_PIN or // ensures that if an attacker extracts the value of OID_STRETCHED_PIN or
// OID_PIN_SECRET, then it cannot be used to conduct an offline brute-force // OID_PIN_SECRET, then it cannot be used to conduct an offline brute-force
// search for the PIN. // search for the PIN.
res = optiga_pin_stretch_cmac_ecdh(ui_progress, stretched_pin); if (!optiga_pin_stretch_cmac_ecdh(ui_progress, stretched_pin)) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
// Generate and store the counter-protected PIN secret. // Generate and store the counter-protected PIN secret.
uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE] = {0};
res = optiga_get_random(pin_secret, sizeof(pin_secret)); if (optiga_get_random(pin_secret, sizeof(pin_secret)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
random_xor(pin_secret, sizeof(pin_secret)); random_xor(pin_secret, sizeof(pin_secret));
res = optiga_set_data_object(OID_PIN_SECRET, false, pin_secret, if (optiga_set_data_object(OID_PIN_SECRET, false, pin_secret,
sizeof(pin_secret)); sizeof(pin_secret)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
// Generate the key for the HMAC-SHA256 PIN stretching step. // Generate the key for the HMAC-SHA256 PIN stretching step.
uint8_t pin_hmac[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t pin_hmac[OPTIGA_PIN_SECRET_SIZE] = {0};
res = optiga_get_random(pin_hmac, sizeof(pin_hmac)); if (optiga_get_random(pin_hmac, sizeof(pin_hmac)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
random_xor(pin_hmac, sizeof(pin_hmac)); random_xor(pin_hmac, sizeof(pin_hmac));
// Authorise using OID_PIN_SECRET so that we can write to OID_STRETCHED_PIN // Authorise using OID_PIN_SECRET so that we can write to OID_STRETCHED_PIN
// and OID_STRETCHED_PIN_CTR. // and OID_STRETCHED_PIN_CTR.
res = optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_PIN_SECRET, if (optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_PIN_SECRET, pin_secret,
pin_secret, sizeof(pin_secret)); sizeof(pin_secret)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
@ -587,17 +572,17 @@ int optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, NULL, 0, digest); hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, NULL, 0, digest);
// Store the digest of the stretched PIN in OID_STRETCHED_PIN. // Store the digest of the stretched PIN in OID_STRETCHED_PIN.
res = if (optiga_set_data_object(OID_STRETCHED_PIN, false, digest,
optiga_set_data_object(OID_STRETCHED_PIN, false, digest, sizeof(digest)); sizeof(digest)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
// Initialize the counter which limits the guesses at OID_STRETCHED_PIN so // Initialize the counter which limits the guesses at OID_STRETCHED_PIN so
// that we can authorise using OID_STRETCHED_PIN. // that we can authorise using OID_STRETCHED_PIN.
res = optiga_set_data_object(OID_STRETCHED_PIN_CTR, false, COUNTER_RESET, if (optiga_set_data_object(OID_STRETCHED_PIN_CTR, false, COUNTER_RESET,
sizeof(COUNTER_RESET)); sizeof(COUNTER_RESET)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
@ -605,31 +590,31 @@ int optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
// Authorise using OID_STRETCHED_PIN so that we can write to OID_PIN_HMAC and // Authorise using OID_STRETCHED_PIN so that we can write to OID_PIN_HMAC and
// OID_PIN_HMAC_CTR. // OID_PIN_HMAC_CTR.
res = optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_STRETCHED_PIN, digest, if (optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_STRETCHED_PIN, digest,
sizeof(digest)); sizeof(digest)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
// Initialize the key for HMAC-SHA256 PIN stretching. // Initialize the key for HMAC-SHA256 PIN stretching.
res = optiga_set_data_object(OID_PIN_HMAC, false, pin_hmac, sizeof(pin_hmac)); if (optiga_set_data_object(OID_PIN_HMAC, false, pin_hmac, sizeof(pin_hmac)) !=
if (res != OPTIGA_SUCCESS) { OPTIGA_SUCCESS) {
ret = false;
goto end; goto end;
} }
// Initialize the counter which limits the guesses at OID_STRETCHED_PIN again, // Initialize the counter which limits the guesses at OID_STRETCHED_PIN again,
// since we just depleted one attempt. // since we just depleted one attempt.
res = optiga_set_data_object(OID_STRETCHED_PIN_CTR, false, COUNTER_RESET, if (optiga_set_data_object(OID_STRETCHED_PIN_CTR, false, COUNTER_RESET,
sizeof(COUNTER_RESET)); sizeof(COUNTER_RESET)) != OPTIGA_SUCCESS) {
optiga_clear_auto_state(OID_PIN_SECRET); ret = false;
if (res != OPTIGA_SUCCESS) {
goto end; goto end;
} }
// Initialize the PIN counter which limits the use of OID_PIN_HMAC. // Initialize the PIN counter which limits the use of OID_PIN_HMAC.
res = optiga_set_data_object(OID_PIN_HMAC_CTR, false, COUNTER_RESET, if (optiga_set_data_object(OID_PIN_HMAC_CTR, false, COUNTER_RESET,
sizeof(COUNTER_RESET)); sizeof(COUNTER_RESET)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = false;
goto end; goto end;
} }
@ -642,9 +627,6 @@ int optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
// integrated into the device in the first place. // integrated into the device in the first place.
hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, pin_secret, hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, pin_secret,
sizeof(pin_secret), stretched_pin); sizeof(pin_secret), stretched_pin);
if (res != OPTIGA_SUCCESS) {
goto end;
}
end: end:
memzero(hmac_buffer, sizeof(hmac_buffer)); memzero(hmac_buffer, sizeof(hmac_buffer));
@ -653,60 +635,69 @@ end:
memzero(digest, sizeof(digest)); memzero(digest, sizeof(digest));
optiga_clear_auto_state(OID_PIN_SECRET); optiga_clear_auto_state(OID_PIN_SECRET);
optiga_clear_auto_state(OID_STRETCHED_PIN); optiga_clear_auto_state(OID_STRETCHED_PIN);
return res; return ret;
} }
int optiga_pin_verify_v4(OPTIGA_UI_PROGRESS ui_progress, optiga_pin_result optiga_pin_verify_v4(
OPTIGA_UI_PROGRESS ui_progress,
const uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE], const uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE],
uint8_t out_secret[OPTIGA_PIN_SECRET_SIZE]) { uint8_t out_secret[OPTIGA_PIN_SECRET_SIZE]) {
// Legacy PIN verification method used in storage version 3 and 4. // Legacy PIN verification method used in storage version 3 and 4.
optiga_pin_result ret = OPTIGA_PIN_SUCCESS;
// Process the PIN-derived secret using a one-way function before sending it // Process the PIN-derived secret using a one-way function before sending it
// to the Optiga. // to the Optiga.
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE] = {0};
hmac_sha256(pin_secret, OPTIGA_PIN_SECRET_SIZE, NULL, 0, stretched_pin); hmac_sha256(pin_secret, OPTIGA_PIN_SECRET_SIZE, NULL, 0, stretched_pin);
// Combine the result with stretching secrets from the Optiga. // Combine the result with stretching secrets from the Optiga.
optiga_result res = optiga_pin_stretch_secret_v4(ui_progress, stretched_pin); if (!optiga_pin_stretch_secret_v4(ui_progress, stretched_pin)) {
if (res != OPTIGA_SUCCESS) { ret = OPTIGA_PIN_ERROR;
memzero(stretched_pin, sizeof(stretched_pin)); goto end;
return res;
} }
// Authorise using OID_STRETCHED_PIN so that we can read from OID_PIN_SECRET. // Authorise using OID_STRETCHED_PIN so that we can read from OID_PIN_SECRET.
res = optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_STRETCHED_PIN, optiga_result res =
optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_STRETCHED_PIN,
stretched_pin, sizeof(stretched_pin)); stretched_pin, sizeof(stretched_pin));
memzero(stretched_pin, sizeof(stretched_pin)); if (res != OPTIGA_SUCCESS) {
if (res == OPTIGA_ERR_CMD) {
uint8_t error_code = 0; uint8_t error_code = 0;
(void)optiga_get_error_code(&error_code); if (res != OPTIGA_ERR_CMD ||
return error_code + OPTIGA_COMMAND_ERROR_OFFSET; optiga_get_error_code(&error_code) != OPTIGA_SUCCESS) {
ret = OPTIGA_PIN_ERROR;
goto end;
} }
if (res != OPTIGA_SUCCESS) { switch (error_code) {
return res; case OPTIGA_ERR_CODE_CTR_LIMIT:
ret = OPTIGA_PIN_COUNTER_EXCEEDED;
break;
case OPTIGA_ERR_CODE_AUTH_FAIL:
ret = OPTIGA_PIN_INVALID;
break;
default:
ret = OPTIGA_PIN_ERROR;
}
goto end;
} }
// Read the master secret from OID_PIN_SECRET. // Read the master secret from OID_PIN_SECRET.
size_t size = 0; size_t size = 0;
res = optiga_get_data_object(OID_PIN_SECRET, false, out_secret, if (optiga_get_data_object(OID_PIN_SECRET, false, out_secret,
OPTIGA_PIN_SECRET_SIZE, &size); OPTIGA_PIN_SECRET_SIZE, &size) != OPTIGA_SUCCESS ||
optiga_clear_auto_state(OID_STRETCHED_PIN); size != OPTIGA_PIN_SECRET_SIZE) {
if (res != OPTIGA_SUCCESS) { ret = OPTIGA_PIN_ERROR;
return res; goto end;
}
if (size != OPTIGA_PIN_SECRET_SIZE) {
return OPTIGA_ERR_SIZE;
} }
ui_progress(200); ui_progress(200);
// Authorise using OID_PIN_SECRET so that we can write to OID_PIN_COUNTER. // Authorise using OID_PIN_SECRET so that we can write to OID_PIN_COUNTER.
res = optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_PIN_SECRET, if (optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_PIN_SECRET, out_secret,
out_secret, OPTIGA_PIN_SECRET_SIZE); OPTIGA_PIN_SECRET_SIZE) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = OPTIGA_PIN_ERROR;
return res; goto end;
} }
ui_progress(200); ui_progress(200);
@ -715,20 +706,26 @@ int optiga_pin_verify_v4(OPTIGA_UI_PROGRESS ui_progress,
// stretching secrets from the Optiga. // stretching secrets from the Optiga.
hmac_sha256(pin_secret, OPTIGA_PIN_SECRET_SIZE, out_secret, hmac_sha256(pin_secret, OPTIGA_PIN_SECRET_SIZE, out_secret,
OPTIGA_PIN_SECRET_SIZE, out_secret); OPTIGA_PIN_SECRET_SIZE, out_secret);
res = optiga_pin_stretch_secret_v4(ui_progress, out_secret); if (!optiga_pin_stretch_secret_v4(ui_progress, out_secret)) {
if (res != OPTIGA_SUCCESS) { ret = OPTIGA_PIN_ERROR;
return res; goto end;
} }
// Combine the stretched master secret with the PIN-derived secret to derive // Combine the stretched master secret with the PIN-derived secret to derive
// the output secret. // the output secret.
hmac_sha256(pin_secret, OPTIGA_PIN_SECRET_SIZE, out_secret, hmac_sha256(pin_secret, OPTIGA_PIN_SECRET_SIZE, out_secret,
OPTIGA_PIN_SECRET_SIZE, out_secret); OPTIGA_PIN_SECRET_SIZE, out_secret);
return OPTIGA_SUCCESS;
end:
memzero(stretched_pin, sizeof(stretched_pin));
optiga_clear_auto_state(OID_STRETCHED_PIN);
return ret;
} }
static int optiga_pin_stretch_hmac( static optiga_pin_result optiga_pin_stretch_hmac(
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) { uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) {
optiga_pin_result ret = OPTIGA_PIN_SUCCESS;
// Process the stretched PIN using a one-way function before sending it to the // Process the stretched PIN using a one-way function before sending it to the
// Optiga. // Optiga.
uint8_t digest[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t digest[OPTIGA_PIN_SECRET_SIZE] = {0};
@ -740,36 +737,42 @@ static int optiga_pin_stretch_hmac(
optiga_result res = optiga_encrypt_sym( optiga_result res = optiga_encrypt_sym(
OPTIGA_SYM_MODE_HMAC_SHA256, OID_PIN_HMAC, digest, sizeof(digest), OPTIGA_SYM_MODE_HMAC_SHA256, OID_PIN_HMAC, digest, sizeof(digest),
hmac_buffer, sizeof(hmac_buffer), &size); hmac_buffer, sizeof(hmac_buffer), &size);
memzero(digest, sizeof(digest));
if (res != OPTIGA_SUCCESS) { if (res != OPTIGA_SUCCESS) {
uint8_t error_code = 0; uint8_t error_code = 0;
(void)optiga_get_error_code(&error_code); if (res == OPTIGA_ERR_CMD &&
if (error_code + OPTIGA_COMMAND_ERROR_OFFSET == optiga_get_error_code(&error_code) == OPTIGA_SUCCESS &&
OPTIGA_ERR_ACCESS_COND_NOT_SAT) { error_code == OPTIGA_ERR_CODE_ACCESS_COND) {
return OPTIGA_ERR_COUNTER_EXCEEDED; ret = OPTIGA_PIN_COUNTER_EXCEEDED;
} else { } else {
return error_code + OPTIGA_COMMAND_ERROR_OFFSET; ret = OPTIGA_PIN_ERROR;
} }
goto end;
} }
// Stretch the PIN with the result. // Stretch the PIN with the result.
hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, hmac_buffer, size, hmac_sha256(stretched_pin, OPTIGA_PIN_SECRET_SIZE, hmac_buffer, size,
stretched_pin); stretched_pin);
end:
memzero(digest, sizeof(digest));
memzero(hmac_buffer, sizeof(hmac_buffer)); memzero(hmac_buffer, sizeof(hmac_buffer));
return OPTIGA_SUCCESS; return ret;
} }
int optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress, optiga_pin_result optiga_pin_verify(
OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) { uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) {
optiga_pin_result ret = OPTIGA_PIN_SUCCESS;
// Stretch the PIN more with stretching secrets from the Optiga. // Stretch the PIN more with stretching secrets from the Optiga.
optiga_result res = optiga_pin_stretch_cmac_ecdh(ui_progress, stretched_pin); if (!optiga_pin_stretch_cmac_ecdh(ui_progress, stretched_pin)) {
if (res != OPTIGA_SUCCESS) { ret = OPTIGA_PIN_ERROR;
return res; goto end;
} }
res = optiga_pin_stretch_hmac(stretched_pin); ret = optiga_pin_stretch_hmac(stretched_pin);
if (res != OPTIGA_SUCCESS) { if (ret != OPTIGA_PIN_SUCCESS) {
return res; goto end;
} }
// Process the stretched PIN using a one-way function before sending it to the // Process the stretched PIN using a one-way function before sending it to the
@ -779,33 +782,45 @@ int optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress,
// Authorise using OID_STRETCHED_PIN so that we can read from OID_PIN_SECRET // Authorise using OID_STRETCHED_PIN so that we can read from OID_PIN_SECRET
// and reset OID_PIN_HMAC_CTR. // and reset OID_PIN_HMAC_CTR.
res = optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_STRETCHED_PIN, digest, optiga_result res = optiga_set_auto_state(
sizeof(digest)); OPTIGA_OID_SESSION_CTX, OID_STRETCHED_PIN, digest, sizeof(digest));
memzero(digest, sizeof(digest)); if (res != OPTIGA_SUCCESS) {
if (res == OPTIGA_ERR_CMD) {
uint8_t error_code = 0; uint8_t error_code = 0;
(void)optiga_get_error_code(&error_code); if (res != OPTIGA_ERR_CMD ||
return error_code + OPTIGA_COMMAND_ERROR_OFFSET; optiga_get_error_code(&error_code) != OPTIGA_SUCCESS) {
ret = OPTIGA_PIN_ERROR;
goto end;
}
switch (error_code) {
case OPTIGA_ERR_CODE_CTR_LIMIT:
ret = OPTIGA_PIN_COUNTER_EXCEEDED;
break;
case OPTIGA_ERR_CODE_AUTH_FAIL:
ret = OPTIGA_PIN_INVALID;
break;
default:
ret = OPTIGA_PIN_ERROR;
}
goto end;
} }
ui_progress(200); ui_progress(200);
// Reset the counter which limits the use of OID_PIN_HMAC. // Reset the counter which limits the use of OID_PIN_HMAC.
res = optiga_set_data_object(OID_PIN_HMAC_CTR, false, COUNTER_RESET, if (optiga_set_data_object(OID_PIN_HMAC_CTR, false, COUNTER_RESET,
sizeof(COUNTER_RESET)); sizeof(COUNTER_RESET)) != OPTIGA_SUCCESS) {
if (res != OPTIGA_SUCCESS) { ret = OPTIGA_PIN_ERROR;
optiga_clear_auto_state(OID_STRETCHED_PIN); goto end;
return res;
} }
// Read the counter-protected PIN secret from OID_PIN_SECRET. // Read the counter-protected PIN secret from OID_PIN_SECRET.
uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE] = {0};
size_t size = 0; size_t size = 0;
res = optiga_get_data_object(OID_PIN_SECRET, false, pin_secret, if (optiga_get_data_object(OID_PIN_SECRET, false, pin_secret,
OPTIGA_PIN_SECRET_SIZE, &size); OPTIGA_PIN_SECRET_SIZE, &size) != OPTIGA_SUCCESS) {
optiga_clear_auto_state(OID_STRETCHED_PIN); ret = OPTIGA_PIN_ERROR;
if (res != OPTIGA_SUCCESS) { goto end;
return res;
} }
// Stretch the PIN more with the counter-protected PIN secret. // Stretch the PIN more with the counter-protected PIN secret.
@ -813,24 +828,27 @@ int optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress,
stretched_pin); stretched_pin);
// Authorise using OID_PIN_SECRET so that we can reset OID_STRETCHED_PIN_CTR. // Authorise using OID_PIN_SECRET so that we can reset OID_STRETCHED_PIN_CTR.
res = optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_PIN_SECRET, if (optiga_set_auto_state(OPTIGA_OID_SESSION_CTX, OID_PIN_SECRET, pin_secret,
pin_secret, sizeof(pin_secret)); sizeof(pin_secret)) != OPTIGA_SUCCESS) {
memzero(pin_secret, sizeof(pin_secret)); ret = OPTIGA_PIN_ERROR;
if (res != OPTIGA_SUCCESS) { goto end;
return res;
} }
// Reset the counter which limits the guesses at OID_STRETCHED_PIN. // Reset the counter which limits the guesses at OID_STRETCHED_PIN.
res = optiga_set_data_object(OID_STRETCHED_PIN_CTR, false, COUNTER_RESET, if (optiga_set_data_object(OID_STRETCHED_PIN_CTR, false, COUNTER_RESET,
sizeof(COUNTER_RESET)); sizeof(COUNTER_RESET)) != OPTIGA_SUCCESS) {
optiga_clear_auto_state(OID_PIN_SECRET); ret = OPTIGA_PIN_ERROR;
if (res != OPTIGA_SUCCESS) { goto end;
return res;
} }
ui_progress(200); ui_progress(200);
return OPTIGA_SUCCESS; end:
memzero(pin_secret, sizeof(pin_secret));
memzero(digest, sizeof(digest));
optiga_clear_auto_state(OID_STRETCHED_PIN);
optiga_clear_auto_state(OID_PIN_SECRET);
return ret;
} }
static int optiga_get_counter(uint16_t oid, uint32_t *ctr) { static int optiga_get_counter(uint16_t oid, uint32_t *ctr) {

View File

@ -113,6 +113,40 @@ typedef enum {
OPTIGA_LCS_TE = 0x0f, // Termination state. OPTIGA_LCS_TE = 0x0f, // Termination state.
} optiga_lcs; } optiga_lcs;
// Error codes returned by optiga_get_error_code().
typedef enum {
OPTIGA_ERR_CODE_NONE = 0x00, // No Error.
OPTIGA_ERR_CODE_INVAL_OID = 0x01, // Invalid OID.
OPTIGA_ERR_CODE_INVAL_CMD_PARAM = 0x03, // Invalid param field in command.
OPTIGA_ERR_CODE_INVAL_CMD_LEN = 0x04, // Invalid length field in command.
OPTIGA_ERR_CODE_INVAL_CMD_DATA = 0x05, // Invalid parameter in command data.
OPTIGA_ERR_CODE_PROCESS = 0x06, // Internal process error.
OPTIGA_ERR_CODE_ACCESS_COND = 0x07, // Access conditions not satisfied.
OPTIGA_ERR_CODE_OBJ_BOUNDARY = 0x08, // Data object boundary exceeded.
OPTIGA_ERR_CODE_META_TRUNC = 0x09, // Metadata truncation error.
OPTIGA_ERR_CODE_INVAL_CMD_FIELD = 0x0A, // Invalid command field.
OPTIGA_ERR_CODE_CMD_SEQ = 0x0B, // Command out of sequence.
OPTIGA_ERR_CODE_CMD_UNAVAIL = 0x0C, // Command not available.
OPTIGA_ERR_CODE_MEMORY = 0x0D, // Insufficient memory to process the
// command.
OPTIGA_ERR_CODE_CTR_LIMIT = 0x0E, // Counter threshold limit exceeded.
OPTIGA_ERR_CODE_INVAL_MANIFEST = 0x0F, // Invalid manifest.
OPTIGA_ERR_CODE_PAYLOAD_VER = 0x10, // Wrong payload version.
OPTIGA_ERR_CODE_INVAL_OBJ_META = 0x11, // Invalid data object metadata.
OPTIGA_ERR_CODE_UNSUP_EXT_ID = 0x24, // Unsupported key usage, extension
// or algorithm identifier.
OPTIGA_ERR_CODE_UNSUP_PARAM = 0x25, // Unsupported parameters in
// handshake or command APDU InData.
OPTIGA_ERR_CODE_INVAL_CERT = 0x29, // Invalid certificate format or
// signature.
OPTIGA_ERR_CODE_UNSUP_CERT = 0x2A, // Unsupported certificate.
OPTIGA_ERR_CODE_SIG_FAIL = 0x2C, // Signature verification failure.
OPTIGA_ERR_CODE_INT_FAIL = 0x2D, // Message integrity validation failed
// (e.g. during CCM decryption).
OPTIGA_ERR_CODE_DECRYPT_FAIL = 0x2E, // Decryption failure
OPTIGA_ERR_CODE_AUTH_FAIL = 0x2F, // Authorization failure
} optiga_err_code;
typedef struct { typedef struct {
const uint8_t *ptr; const uint8_t *ptr;
uint16_t len; uint16_t len;

View File

@ -34,27 +34,28 @@
#error "Cert chain for specified model is not available." #error "Cert chain for specified model is not available."
#endif #endif
int optiga_sign(uint8_t index, const uint8_t *digest, size_t digest_size, optiga_sign_result optiga_sign(uint8_t index, const uint8_t *digest,
uint8_t *signature, size_t max_sig_size, size_t *sig_size) { size_t digest_size, uint8_t *signature,
size_t max_sig_size, size_t *sig_size) {
const uint8_t DEVICE_PRIV_KEY[32] = {1}; const uint8_t DEVICE_PRIV_KEY[32] = {1};
if (index != OPTIGA_DEVICE_ECC_KEY_INDEX) { if (index != OPTIGA_DEVICE_ECC_KEY_INDEX) {
return false; return OPTIGA_SIGN_ERROR;
} }
if (max_sig_size < 72) { if (max_sig_size < 72) {
return OPTIGA_ERR_SIZE; return OPTIGA_SIGN_ERROR;
} }
uint8_t raw_signature[64] = {0}; uint8_t raw_signature[64] = {0};
int ret = ecdsa_sign_digest(&nist256p1, DEVICE_PRIV_KEY, digest, int ret = ecdsa_sign_digest(&nist256p1, DEVICE_PRIV_KEY, digest,
raw_signature, NULL, NULL); raw_signature, NULL, NULL);
if (ret != 0) { if (ret != 0) {
return OPTIGA_ERR_CMD; return OPTIGA_SIGN_ERROR;
} }
*sig_size = ecdsa_sig_to_der(raw_signature, signature); *sig_size = ecdsa_sig_to_der(raw_signature, signature);
return OPTIGA_SUCCESS; return OPTIGA_SIGN_SUCCESS;
} }
bool optiga_cert_size(uint8_t index, size_t *cert_size) { bool optiga_cert_size(uint8_t index, size_t *cert_size) {
@ -91,24 +92,26 @@ bool optiga_random_buffer(uint8_t *dest, size_t size) {
return true; return true;
} }
int optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress, bool optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) { uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) {
ui_progress(OPTIGA_PIN_SET_MS); ui_progress(OPTIGA_PIN_SET_MS);
return OPTIGA_SUCCESS; return true;
} }
int optiga_pin_verify_v4(OPTIGA_UI_PROGRESS ui_progress, optiga_pin_result optiga_pin_verify_v4(
OPTIGA_UI_PROGRESS ui_progress,
const uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE], const uint8_t pin_secret[OPTIGA_PIN_SECRET_SIZE],
uint8_t out_secret[OPTIGA_PIN_SECRET_SIZE]) { uint8_t out_secret[OPTIGA_PIN_SECRET_SIZE]) {
memcpy(out_secret, pin_secret, OPTIGA_PIN_SECRET_SIZE); memcpy(out_secret, pin_secret, OPTIGA_PIN_SECRET_SIZE);
ui_progress(OPTIGA_PIN_VERIFY_MS); ui_progress(OPTIGA_PIN_VERIFY_MS);
return OPTIGA_SUCCESS; return OPTIGA_PIN_SUCCESS;
} }
int optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress, optiga_pin_result optiga_pin_verify(
OPTIGA_UI_PROGRESS ui_progress,
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) { uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE]) {
ui_progress(OPTIGA_PIN_VERIFY_MS); ui_progress(OPTIGA_PIN_VERIFY_MS);
return OPTIGA_SUCCESS; return OPTIGA_PIN_SUCCESS;
} }
int optiga_pin_get_fails_v4(uint32_t *ctr) { int optiga_pin_get_fails_v4(uint32_t *ctr) {

View File

@ -609,7 +609,7 @@ static secbool __wur derive_kek_set(
const uint8_t *ext_salt, uint8_t stretched_pin[SHA256_DIGEST_LENGTH]) { const uint8_t *ext_salt, uint8_t stretched_pin[SHA256_DIGEST_LENGTH]) {
stretch_pin(pin, pin_len, storage_salt, ext_salt, stretched_pin); stretch_pin(pin, pin_len, storage_salt, ext_salt, stretched_pin);
#if USE_OPTIGA #if USE_OPTIGA
if (optiga_pin_set(ui_progress, stretched_pin) != OPTIGA_SUCCESS) { if (!optiga_pin_set(ui_progress, stretched_pin)) {
memzero(stretched_pin, SHA256_DIGEST_LENGTH); memzero(stretched_pin, SHA256_DIGEST_LENGTH);
return secfalse; return secfalse;
} }
@ -627,16 +627,17 @@ static secbool __wur derive_kek_unlock_v4(const uint8_t *pin, size_t pin_len,
uint8_t optiga_secret[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t optiga_secret[OPTIGA_PIN_SECRET_SIZE] = {0};
uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE] = {0}; uint8_t stretched_pin[OPTIGA_PIN_SECRET_SIZE] = {0};
stretch_pin(pin, pin_len, storage_salt, ext_salt, stretched_pin); stretch_pin(pin, pin_len, storage_salt, ext_salt, stretched_pin);
int ret = optiga_pin_verify_v4(ui_progress, stretched_pin, optiga_secret); optiga_pin_result ret =
optiga_pin_verify_v4(ui_progress, stretched_pin, optiga_secret);
memzero(stretched_pin, sizeof(stretched_pin)); memzero(stretched_pin, sizeof(stretched_pin));
if (ret != OPTIGA_SUCCESS) { if (ret != OPTIGA_PIN_SUCCESS) {
memzero(optiga_secret, sizeof(optiga_secret)); memzero(optiga_secret, sizeof(optiga_secret));
if (ret == OPTIGA_ERR_COUNTER_EXCEEDED) { if (ret == OPTIGA_PIN_COUNTER_EXCEEDED) {
// Unreachable code. Wipe should have already been triggered in unlock(). // Unreachable code. Wipe should have already been triggered in unlock().
storage_wipe(); storage_wipe();
show_pin_too_many_screen(); show_pin_too_many_screen();
} }
ensure(ret == OPTIGA_ERR_AUTH_FAIL ? sectrue : secfalse, ensure(ret == OPTIGA_PIN_INVALID ? sectrue : secfalse,
"optiga_pin_verify failed"); "optiga_pin_verify failed");
return secfalse; return secfalse;
} }
@ -653,16 +654,16 @@ static secbool __wur derive_kek_unlock(
const uint8_t *ext_salt, uint8_t stretched_pin[SHA256_DIGEST_LENGTH]) { const uint8_t *ext_salt, uint8_t stretched_pin[SHA256_DIGEST_LENGTH]) {
stretch_pin(pin, pin_len, storage_salt, ext_salt, stretched_pin); stretch_pin(pin, pin_len, storage_salt, ext_salt, stretched_pin);
#if USE_OPTIGA #if USE_OPTIGA
int ret = optiga_pin_verify(ui_progress, stretched_pin); optiga_pin_result ret = optiga_pin_verify(ui_progress, stretched_pin);
if (ret != OPTIGA_SUCCESS) { if (ret != OPTIGA_PIN_SUCCESS) {
memzero(stretched_pin, SHA256_DIGEST_LENGTH); memzero(stretched_pin, SHA256_DIGEST_LENGTH);
if (ret == OPTIGA_ERR_COUNTER_EXCEEDED) { if (ret == OPTIGA_PIN_COUNTER_EXCEEDED) {
// Unreachable code. Wipe should have already been triggered in unlock(). // Unreachable code. Wipe should have already been triggered in unlock().
storage_wipe(); storage_wipe();
show_pin_too_many_screen(); show_pin_too_many_screen();
} }
ensure(ret == OPTIGA_ERR_AUTH_FAIL ? sectrue : secfalse, ensure(ret == OPTIGA_PIN_INVALID ? sectrue : secfalse,
"optiga_pin_verify failed"); "optiga_pin_verify failed");
return secfalse; return secfalse;
} }