fix(storage): correctly fail when Optiga operations fail

release/23.09
matejcik 9 months ago
parent c6c8d85200
commit 9d86352352

@ -41,22 +41,23 @@
typedef secbool (*OPTIGA_UI_PROGRESS)(uint32_t elapsed_ms); typedef secbool (*OPTIGA_UI_PROGRESS)(uint32_t elapsed_ms);
int optiga_sign(uint8_t index, const uint8_t *digest, size_t digest_size, int __wur optiga_sign(uint8_t index, const uint8_t *digest, size_t digest_size,
uint8_t *signature, size_t max_sig_size, size_t *sig_size); uint8_t *signature, size_t max_sig_size,
size_t *sig_size);
bool optiga_cert_size(uint8_t index, size_t *cert_size); bool __wur optiga_cert_size(uint8_t index, size_t *cert_size);
bool optiga_read_cert(uint8_t index, uint8_t *cert, size_t max_cert_size, bool __wur optiga_read_cert(uint8_t index, uint8_t *cert, size_t max_cert_size,
size_t *cert_size); size_t *cert_size);
bool optiga_random_buffer(uint8_t *dest, size_t size); bool __wur optiga_random_buffer(uint8_t *dest, size_t size);
bool optiga_pin_set(OPTIGA_UI_PROGRESS ui_progress, bool __wur optiga_pin_set(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]);
bool optiga_pin_verify(OPTIGA_UI_PROGRESS ui_progress, bool __wur optiga_pin_verify(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]);
#endif #endif

@ -593,39 +593,50 @@ static void derive_kek_optiga(
} }
#endif #endif
static void derive_kek_set(const uint8_t *pin, size_t pin_len, static secbool __wur derive_kek_set(const uint8_t *pin, size_t pin_len,
const uint8_t *storage_salt, const uint8_t *ext_salt, const uint8_t *storage_salt,
uint8_t kek[SHA256_DIGEST_LENGTH], const uint8_t *ext_salt,
uint8_t keiv[SHA256_DIGEST_LENGTH]) { uint8_t kek[SHA256_DIGEST_LENGTH],
uint8_t keiv[SHA256_DIGEST_LENGTH]) {
#if USE_OPTIGA #if USE_OPTIGA
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_optiga(pin, pin_len, storage_salt, ext_salt, stretched_pin); stretch_pin_optiga(pin, pin_len, storage_salt, ext_salt, stretched_pin);
optiga_pin_set(ui_progress, stretched_pin, optiga_secret); bool ret = optiga_pin_set(ui_progress, stretched_pin, optiga_secret);
memzero(stretched_pin, sizeof(stretched_pin)); memzero(stretched_pin, sizeof(stretched_pin));
if (!ret) {
memzero(optiga_secret, sizeof(optiga_secret));
return secfalse;
}
derive_kek_optiga(optiga_secret, kek, keiv); derive_kek_optiga(optiga_secret, kek, keiv);
memzero(optiga_secret, sizeof(optiga_secret)); memzero(optiga_secret, sizeof(optiga_secret));
#else #else
derive_kek(pin, pin_len, storage_salt, ext_salt, kek, keiv); derive_kek(pin, pin_len, storage_salt, ext_salt, kek, keiv);
#endif #endif
return sectrue;
} }
static void derive_kek_unlock(const uint8_t *pin, size_t pin_len, static secbool __wur derive_kek_unlock(const uint8_t *pin, size_t pin_len,
const uint8_t *storage_salt, const uint8_t *storage_salt,
const uint8_t *ext_salt, const uint8_t *ext_salt,
uint8_t kek[SHA256_DIGEST_LENGTH], uint8_t kek[SHA256_DIGEST_LENGTH],
uint8_t keiv[SHA256_DIGEST_LENGTH]) { uint8_t keiv[SHA256_DIGEST_LENGTH]) {
#if USE_OPTIGA #if USE_OPTIGA
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_optiga(pin, pin_len, storage_salt, ext_salt, stretched_pin); stretch_pin_optiga(pin, pin_len, storage_salt, ext_salt, stretched_pin);
optiga_pin_verify(ui_progress, stretched_pin, optiga_secret); bool ret = optiga_pin_verify(ui_progress, stretched_pin, optiga_secret);
memzero(stretched_pin, sizeof(stretched_pin)); memzero(stretched_pin, sizeof(stretched_pin));
if (!ret) {
memzero(optiga_secret, sizeof(optiga_secret));
return secfalse;
}
derive_kek_optiga(optiga_secret, kek, keiv); derive_kek_optiga(optiga_secret, kek, keiv);
memzero(optiga_secret, sizeof(optiga_secret)); memzero(optiga_secret, sizeof(optiga_secret));
#else #else
derive_kek(pin, pin_len, storage_salt, ext_salt, kek, keiv); derive_kek(pin, pin_len, storage_salt, ext_salt, kek, keiv);
#endif #endif
return sectrue;
} }
static secbool set_pin(const uint8_t *pin, size_t pin_len, static secbool set_pin(const uint8_t *pin, size_t pin_len,
@ -641,7 +652,8 @@ static secbool set_pin(const uint8_t *pin, size_t pin_len,
chacha20poly1305_ctx ctx = {0}; chacha20poly1305_ctx ctx = {0};
random_buffer(rand_salt, STORAGE_SALT_SIZE); random_buffer(rand_salt, STORAGE_SALT_SIZE);
ui_progress(0); ui_progress(0);
derive_kek_set(pin, pin_len, rand_salt, ext_salt, kek, keiv); ensure(derive_kek_set(pin, pin_len, rand_salt, ext_salt, kek, keiv),
"derive_kek_set failed");
rfc7539_init(&ctx, kek, keiv); rfc7539_init(&ctx, kek, keiv);
memzero(kek, sizeof(kek)); memzero(kek, sizeof(kek));
memzero(keiv, sizeof(keiv)); memzero(keiv, sizeof(keiv));
@ -1157,6 +1169,20 @@ static secbool unlock(const uint8_t *pin, size_t pin_len,
hal_delay(100); hal_delay(100);
} }
// First, we increase PIN fail counter in storage, even before checking the
// PIN. If the PIN is correct, we reset the counter afterwards. If not, we
// check if this is the last allowed attempt.
if (sectrue != storage_pin_fails_increase()) {
return secfalse;
}
// Check that the PIN fail counter was incremented.
uint32_t ctr_ck = 0;
if (sectrue != pin_get_fails(&ctr_ck) || ctr + 1 != ctr_ck) {
handle_fault("PIN counter increment");
return secfalse;
}
// Read the random salt from EDEK_PVC_KEY and use it to derive the KEK and // Read the random salt from EDEK_PVC_KEY and use it to derive the KEK and
// KEIV from the PIN. // KEIV from the PIN.
const void *rand_salt = NULL; const void *rand_salt = NULL;
@ -1170,23 +1196,12 @@ static secbool unlock(const uint8_t *pin, size_t pin_len,
} }
uint8_t kek[SHA256_DIGEST_LENGTH] = {0}; uint8_t kek[SHA256_DIGEST_LENGTH] = {0};
uint8_t keiv[SHA256_DIGEST_LENGTH] = {0}; uint8_t keiv[SHA256_DIGEST_LENGTH] = {0};
derive_kek_unlock(unlock_pin, unlock_pin_len, (const uint8_t *)rand_salt, if (sectrue != derive_kek_unlock(unlock_pin, unlock_pin_len,
ext_salt, kek, keiv); (const uint8_t *)rand_salt, ext_salt, kek,
memzero(&legacy_pin, sizeof(legacy_pin)); keiv)) {
// First, we increase PIN fail counter in storage, even before checking the
// PIN. If the PIN is correct, we reset the counter afterwards. If not, we
// check if this is the last allowed attempt.
if (sectrue != storage_pin_fails_increase()) {
return secfalse;
}
// Check that the PIN fail counter was incremented.
uint32_t ctr_ck = 0;
if (sectrue != pin_get_fails(&ctr_ck) || ctr + 1 != ctr_ck) {
handle_fault("PIN counter increment");
return secfalse; return secfalse;
} }
memzero(&legacy_pin, sizeof(legacy_pin));
// Check whether the entered PIN is correct. // Check whether the entered PIN is correct.
if (sectrue != decrypt_dek(kek, keiv)) { if (sectrue != decrypt_dek(kek, keiv)) {

Loading…
Cancel
Save