diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 747cfa9..a818d69 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -32,6 +32,19 @@ extern bool has_session_pin; extern uint8_t session_pin[32]; +#define POLY 0xedb88320 + +uint32_t crc32c(const uint8_t *buf, size_t len) +{ + uint32_t crc = ~0; + while (len--) { + crc ^= *buf++; + for (int k = 0; k < 8; k++) + crc = (crc >> 1) ^ (POLY & (0 - (crc & 1))); + } + return ~crc; +} + int load_dkek(uint8_t id, uint8_t *dkek) { if (has_session_pin == false) return CCID_NO_LOGIN; @@ -39,9 +52,11 @@ int load_dkek(uint8_t id, uint8_t *dkek) { if (!tf) return CCID_ERR_FILE_NOT_FOUND; memcpy(dkek, file_get_data(tf), DKEK_SIZE); - int ret = aes_decrypt_cfb_256(session_pin, DKEK_IV(dkek), DKEK_KEY(dkek), DKEK_KEY_SIZE); + int ret = aes_decrypt_cfb_256(session_pin, DKEK_IV(dkek), DKEK_KEY(dkek), DKEK_KEY_SIZE+DKEK_KEY_CS_SIZE); if (ret != 0) return CCID_EXEC_ERROR; + if (crc32c(DKEK_KEY(dkek), DKEK_KEY_SIZE) != *(uint32_t*)DKEK_CHECKSUM(dkek)) + return CCID_WRONG_DKEK; return CCID_OK; } @@ -53,7 +68,8 @@ int store_dkek_key(uint8_t id, uint8_t *dkek) { file_t *tf = search_dynamic_file(EF_DKEK+id); if (!tf) return CCID_ERR_FILE_NOT_FOUND; - aes_encrypt_cfb_256(session_pin, DKEK_IV(dkek), DKEK_KEY(dkek), DKEK_KEY_SIZE); + *(uint32_t*)DKEK_CHECKSUM(dkek) = crc32c(DKEK_KEY(dkek), DKEK_KEY_SIZE); + aes_encrypt_cfb_256(session_pin, DKEK_IV(dkek), DKEK_KEY(dkek), DKEK_KEY_SIZE+DKEK_KEY_CS_SIZE); flash_write_data_to_file(tf, dkek, DKEK_SIZE); low_flash_available(); release_dkek(dkek); diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h index 3047694..36c173d 100644 --- a/src/hsm/dkek.h +++ b/src/hsm/dkek.h @@ -37,8 +37,10 @@ extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, size_t in_ #define DKEK_IV_SIZE (IV_SIZE) #define DKEK_KEY_SIZE (32) -#define DKEK_SIZE (DKEK_IV_SIZE+DKEK_KEY_SIZE) +#define DKEK_KEY_CS_SIZE (4) +#define DKEK_SIZE (DKEK_IV_SIZE+DKEK_KEY_SIZE+DKEK_KEY_CS_SIZE) #define DKEK_KEY(p) (p+DKEK_IV_SIZE) #define DKEK_IV(p) (p) +#define DKEK_CHECKSUM(p) (p+DKEK_IV_SIZE+DKEK_KEY_SIZE) #endif diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 9db249b..f4a281b 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -695,7 +695,8 @@ static int cmd_initialize() { } uint8_t t[DKEK_SIZE]; memset(t, 0, sizeof(t)); - flash_write_data_to_file(tf, t, sizeof(t)); + if (store_dkek_key(0, t) != CCID_OK) + return SW_EXEC_ERROR(); if (dkeks) { if (*dkeks > 0) { uint16_t d = *dkeks; @@ -817,12 +818,10 @@ static int cmd_key_domain() { } if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) return SW_EXEC_ERROR(); - file_t *tf = file_new(EF_DKEK+p2); - if (!tf) - return SW_MEMORY_FAILURE(); uint8_t dk[DKEK_SIZE]; memset(dk, 0, sizeof(dk)); - flash_write_data_to_file(tf, dk, sizeof(dk)); + if (store_dkek_key(p2, dk) != CCID_OK) + return SW_EXEC_ERROR(); low_flash_available(); return SW_OK(); }