From 7bd1aa8fcf52b24b6a8876d6ccee2f03f4190097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Wed, 20 Dec 2023 09:51:23 +0100 Subject: [PATCH] Delete hotp secret before setting it. The Nitrokey 3 version 1.6.0 firmware prevents overwriting credentials. Therefore the credential needs to be explicitely deleted prior to it being overwritten. --- src/operations_ccid.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/operations_ccid.c b/src/operations_ccid.c index 6b0ffe4..87fe990 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -99,6 +99,36 @@ int authenticate_ccid(struct Device *dev, const char *admin_PIN) { return RET_NO_ERROR; } +int delete_secret_on_device_ccid(struct Device *dev) { + TLV tlvs[] = { + { + .tag = Tag_CredentialId, + .length = SLOT_NAME_LEN, + .type = 'S', + .v_str = SLOT_NAME, + } + }; + + clean_buffers(dev); + // encode + uint32_t icc_actual_length = icc_pack_tlvs_for_sending(dev->ccid_buffer_out, sizeof dev->ccid_buffer_out, + tlvs, ARR_LEN(tlvs), Ins_Delete); + // send + IccResult iccResult; + int r = ccid_process_single(dev->mp_devhandle_ccid, dev->ccid_buffer_in, sizeof dev->ccid_buffer_in, + dev->ccid_buffer_out, icc_actual_length, &iccResult); + if (r != 0) { + return r; + } + + // check status code + if (iccResult.data_status_code == 0x6a82 || iccResult.data_status_code == 0x9000) { + return 0; + } else { + return RET_VALIDATION_FAILED; + } + return r; +} int set_secret_on_device_ccid(struct Device *dev, const char *OTP_secret_base32, const uint64_t hotp_counter) { // Decode base32 secret @@ -115,6 +145,11 @@ int set_secret_on_device_ccid(struct Device *dev, const char *OTP_secret_base32, rassert(hotp_counter < 0xFFFFFFFF); uint32_t initial_counter_value = hotp_counter; + int r = delete_secret_on_device_ccid(dev); + if (r != 0) { + return r; + } + TLV tlvs[] = { { .tag = Tag_CredentialId, @@ -150,7 +185,7 @@ int set_secret_on_device_ccid(struct Device *dev, const char *OTP_secret_base32, // send IccResult iccResult; - int r = ccid_process_single(dev->mp_devhandle_ccid, dev->ccid_buffer_in, sizeof dev->ccid_buffer_in, + r = ccid_process_single(dev->mp_devhandle_ccid, dev->ccid_buffer_in, sizeof dev->ccid_buffer_in, dev->ccid_buffer_out, icc_actual_length, &iccResult);