diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index b38b197..f9f2f0d 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -29,8 +29,8 @@ #include "mbedtls/ecdsa.h" #include "files.h" -extern bool has_session_pin; -extern uint8_t session_pin[32]; +extern bool has_session_pin, has_session_sopin; +extern uint8_t session_pin[32], session_sopin[32]; #define POLY 0xedb88320 @@ -46,13 +46,26 @@ uint32_t crc32c(const uint8_t *buf, size_t len) } int load_mkek(uint8_t *mkek) { - if (has_session_pin == false) + if (has_session_pin == false && has_session_sopin == false) return CCID_NO_LOGIN; - file_t *tf = search_dynamic_file(EF_MKEK); - if (!tf) - return CCID_ERR_FILE_NOT_FOUND; - memcpy(mkek, file_get_data(tf), MKEK_SIZE); - int ret = aes_decrypt_cfb_256(session_pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); + const uint8_t *pin = NULL; + if (pin == NULL && has_session_pin == true) { + file_t *tf = search_dynamic_file(EF_MKEK); + if (tf) { + memcpy(mkek, file_get_data(tf), MKEK_SIZE); + pin = session_pin; + } + } + if (pin == NULL && has_session_sopin == true) { + file_t *tf = search_dynamic_file(EF_MKEK_SO); + if (tf) { + memcpy(mkek, file_get_data(tf), MKEK_SIZE); + pin = session_sopin; + } + } + if (pin == NULL) //Should never happen + return CCID_EXEC_ERROR; + int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); if (ret != 0) return CCID_EXEC_ERROR; if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t*)MKEK_CHECKSUM(mkek)) @@ -73,7 +86,7 @@ void release_mkek(uint8_t *mkek) { } int store_mkek(const uint8_t *mkek) { - if (has_session_pin == false) + if (has_session_pin == false && has_session_sopin == false) return CCID_NO_LOGIN; uint8_t tmp_mkek[MKEK_SIZE]; if (mkek == NULL) { @@ -82,12 +95,21 @@ int store_mkek(const uint8_t *mkek) { } else memcpy(tmp_mkek, mkek, MKEK_SIZE); - file_t *tf = search_dynamic_file(EF_MKEK); - if (!tf) - return CCID_ERR_FILE_NOT_FOUND; *(uint32_t*)MKEK_CHECKSUM(tmp_mkek) = crc32c(MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE); - aes_encrypt_cfb_256(session_pin, MKEK_IV(tmp_mkek), MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); - flash_write_data_to_file(tf, tmp_mkek, MKEK_SIZE); + if (has_session_pin) { + file_t *tf = search_dynamic_file(EF_MKEK); + if (!tf) + return CCID_ERR_FILE_NOT_FOUND; + aes_encrypt_cfb_256(session_pin, MKEK_IV(tmp_mkek), MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); + flash_write_data_to_file(tf, tmp_mkek, MKEK_SIZE); + } + if (has_session_sopin) { + file_t *tf = search_dynamic_file(EF_MKEK_SO); + if (!tf) + return CCID_ERR_FILE_NOT_FOUND; + aes_encrypt_cfb_256(session_sopin, MKEK_IV(tmp_mkek), MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); + flash_write_data_to_file(tf, tmp_mkek, MKEK_SIZE); + } low_flash_available(); release_mkek(tmp_mkek); return CCID_OK; diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index ccc1f7f..6cf2d48 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -644,6 +644,16 @@ static int cmd_reset_retry() { flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); if (pin_reset_retries(file_pin1, true) != CCID_OK) return SW_MEMORY_FAILURE(); + uint8_t mkek[MKEK_SIZE]; + int r = load_mkek(mkek); //loads the MKEK with SO pin + if (r != CCID_OK) + return SW_EXEC_ERROR(); + hash_multi(apdu.data+(apdu.nc-newpin_len), newpin_len, session_pin); + has_session_pin = true; + r = store_mkek(mkek); + release_mkek(mkek); + if (r != CCID_OK) + return SW_EXEC_ERROR(); low_flash_available(); return SW_OK(); } @@ -656,6 +666,8 @@ static int cmd_reset_retry() { uint16_t r = check_pin(file_sopin, apdu.data, 8); if (r != 0x9000) return r; + has_session_sopin = true; + hash_multi(apdu.data, 8, session_sopin); } else if (P1(apdu) == 0x3) { if (!has_session_sopin) @@ -696,6 +708,7 @@ static int cmd_initialize() { if (apdu.nc > 0) { initialize_flash(true); scan_all(); + has_session_pin = has_session_sopin = false; uint16_t tag = 0x0; uint8_t *tag_data = NULL, *p = NULL, *kds = NULL, *dkeks = NULL; size_t tag_len = 0; @@ -711,6 +724,7 @@ static int cmd_initialize() { double_hash_pin(tag_data, tag_len, dhash+1); flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); hash_multi(tag_data, tag_len, session_pin); + has_session_pin = true; } } else if (tag == 0x82) { //sopin pin @@ -794,7 +808,6 @@ static int cmd_initialize() { return SW_EXEC_ERROR(); } /* When initialized, it has all credentials */ - has_session_pin = true; isUserAuthenticated = true; low_flash_available(); }