diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 47b1085..b38b197 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -45,49 +45,76 @@ uint32_t crc32c(const uint8_t *buf, size_t len) return ~crc; } -int load_dkek(uint8_t id, uint8_t *dkek) { +int load_mkek(uint8_t *mkek) { if (has_session_pin == false) return CCID_NO_LOGIN; - file_t *tf = search_dynamic_file(EF_DKEK+id); + file_t *tf = search_dynamic_file(EF_MKEK); 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+DKEK_KEY_CS_SIZE); + 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); if (ret != 0) return CCID_EXEC_ERROR; - if (crc32c(DKEK_KEY(dkek), DKEK_KEY_SIZE) != *(uint32_t*)DKEK_CHECKSUM(dkek)) + if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t*)MKEK_CHECKSUM(mkek)) return CCID_WRONG_DKEK; return CCID_OK; } -void release_dkek(uint8_t *dkek) { - memset(dkek, 0, DKEK_SIZE); +int load_dkek(uint8_t id, uint8_t *dkek) { + file_t *tf = search_dynamic_file(EF_DKEK+id); + if (!tf) + return CCID_ERR_FILE_NOT_FOUND; + memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); + return mkek_decrypt(dkek, DKEK_KEY_SIZE); +} + +void release_mkek(uint8_t *mkek) { + memset(mkek, 0, MKEK_SIZE); +} + +int store_mkek(const uint8_t *mkek) { + if (has_session_pin == false) + return CCID_NO_LOGIN; + uint8_t tmp_mkek[MKEK_SIZE]; + if (mkek == NULL) { + const uint8_t *rd = random_bytes_get(MKEK_IV_SIZE+MKEK_KEY_SIZE); + memcpy(tmp_mkek, rd, MKEK_IV_SIZE+MKEK_KEY_SIZE); + } + 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); + low_flash_available(); + release_mkek(tmp_mkek); + return CCID_OK; } 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; - *(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); + int r = mkek_encrypt(dkek, DKEK_KEY_SIZE); + if (r != CCID_OK) + return r; + flash_write_data_to_file(tf, dkek, DKEK_KEY_SIZE); low_flash_available(); - release_dkek(dkek); return CCID_OK; } int save_dkek_key(uint8_t id, const uint8_t *key) { - uint8_t dkek[DKEK_SIZE]; - const uint8_t *iv = random_bytes_get(32); - memcpy(dkek, iv, DKEK_IV_SIZE); + uint8_t dkek[DKEK_KEY_SIZE]; if (!key) { file_t *tf = search_dynamic_file(EF_DKEK+id); if (!tf) return CCID_ERR_FILE_NOT_FOUND; - memcpy(DKEK_KEY(dkek), file_get_data(tf), DKEK_KEY_SIZE); + memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); } else - memcpy(DKEK_KEY(dkek), key, DKEK_KEY_SIZE); + memcpy(dkek, key, DKEK_KEY_SIZE); return store_dkek_key(id, dkek); } @@ -107,58 +134,58 @@ int import_dkek_share(uint8_t id, const uint8_t *share) { } int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes - uint8_t hsh[32], dkek[DKEK_SIZE]; + uint8_t hsh[32], dkek[DKEK_KEY_SIZE]; memset(kcv, 0, 8); int r = load_dkek(id, dkek); if (r != CCID_OK) return r; - hash256(DKEK_KEY(dkek), DKEK_KEY_SIZE, hsh); - release_dkek(dkek); + hash256(dkek, DKEK_KEY_SIZE, hsh); + memset(dkek, 0, sizeof(dkek)); memcpy(kcv, hsh, 8); return CCID_OK; } int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes - uint8_t dkek[DKEK_SIZE+4]; + uint8_t dkek[DKEK_KEY_SIZE+4]; memset(kenc, 0, 32); int r = load_dkek(id, dkek); if (r != CCID_OK) return r; - memcpy(DKEK_KEY(dkek)+DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4); - hash256(DKEK_KEY(dkek), DKEK_KEY_SIZE+4, kenc); - release_dkek(dkek); + memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4); + hash256(dkek, sizeof(dkek), kenc); + memset(dkek, 0, sizeof(dkek)); return CCID_OK; } int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes - uint8_t dkek[DKEK_SIZE+4]; + uint8_t dkek[DKEK_KEY_SIZE+4]; memset(kmac, 0, 32); int r = load_dkek(id, dkek); if (r != CCID_OK) return r; - memcpy(DKEK_KEY(dkek)+DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4); - hash256(DKEK_KEY(dkek), DKEK_KEY_SIZE+4, kmac); - release_dkek(dkek); + memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4); + hash256(dkek, DKEK_KEY_SIZE+4, kmac); + memset(dkek, 0, sizeof(dkek)); return CCID_OK; } -int dkek_encrypt(uint8_t id, uint8_t *data, size_t len) { +int mkek_encrypt(uint8_t *data, size_t len) { int r; - uint8_t dkek[DKEK_SIZE+4]; - if ((r = load_dkek(id, dkek)) != CCID_OK) + uint8_t mkek[MKEK_SIZE+4]; + if ((r = load_mkek(mkek)) != CCID_OK) return r; - r = aes_encrypt_cfb_256(DKEK_KEY(dkek), DKEK_IV(dkek), data, len); - release_dkek(dkek); + r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); + release_mkek(mkek); return r; } -int dkek_decrypt(uint8_t id, uint8_t *data, size_t len) { +int mkek_decrypt(uint8_t *data, size_t len) { int r; - uint8_t dkek[DKEK_SIZE+4]; - if ((r = load_dkek(id, dkek)) != CCID_OK) + uint8_t mkek[MKEK_SIZE+4]; + if ((r = load_mkek(mkek)) != CCID_OK) return r; - r = aes_decrypt_cfb_256(DKEK_KEY(dkek), DKEK_IV(dkek), data, len); - release_dkek(dkek); + r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); + release_mkek(mkek); return r; } diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h index 36c173d..0d7fbfb 100644 --- a/src/hsm/dkek.h +++ b/src/hsm/dkek.h @@ -18,15 +18,16 @@ #ifndef _DKEK_H_ #define _DKEK_H_ -extern int load_dkek(uint8_t, uint8_t *); +extern int load_mkek(uint8_t *); +extern int store_mkek(const uint8_t *); extern int save_dkek_key(uint8_t, const uint8_t *key); extern int store_dkek_key(uint8_t, uint8_t *); -extern void init_dkek(); -extern void release_dkek(uint8_t *); +extern void init_mkek(); +extern void release_mkek(uint8_t *); extern int import_dkek_share(uint8_t, const uint8_t *share); extern int dkek_kcv(uint8_t, uint8_t *kcv); -extern int dkek_encrypt(uint8_t, uint8_t *data, size_t len); -extern int dkek_decrypt(uint8_t, uint8_t *data, size_t len); +extern int mkek_encrypt(uint8_t *data, size_t len); +extern int mkek_decrypt(uint8_t *data, size_t len); extern int dkek_encode_key(uint8_t, void *key_ctx, int key_type, uint8_t *out, size_t *out_len); extern int dkek_type_key(const uint8_t *in); extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out); @@ -35,12 +36,13 @@ extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, size_t in_ #define MAX_KEY_DOMAINS 16 -#define DKEK_IV_SIZE (IV_SIZE) +#define MKEK_IV_SIZE (IV_SIZE) +#define MKEK_KEY_SIZE (32) +#define MKEK_KEY_CS_SIZE (4) +#define MKEK_SIZE (MKEK_IV_SIZE+MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE) +#define MKEK_IV(p) (p) +#define MKEK_KEY(p) (MKEK_IV(p)+MKEK_IV_SIZE) +#define MKEK_CHECKSUM(p) (MKEK_KEY(p)+MKEK_KEY_SIZE) #define DKEK_KEY_SIZE (32) -#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 fa9e98b..8642264 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -768,15 +768,7 @@ static int cmd_initialize() { file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF); if (!tf_kd) return SW_EXEC_ERROR(); - file_t *tf = search_dynamic_file(EF_DKEK); - if (!tf) { - tf = file_new(EF_DKEK); - if (!tf) - return SW_MEMORY_FAILURE(); - } - uint8_t t[DKEK_SIZE]; - memset(t, 0, sizeof(t)); - if (store_dkek_key(0, t) != CCID_OK) + if (store_mkek(NULL) != CCID_OK) return SW_EXEC_ERROR(); if (dkeks) { if (*dkeks > 0) { @@ -964,7 +956,7 @@ static int cmd_key_domain() { } if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) return SW_EXEC_ERROR(); - uint8_t dk[DKEK_SIZE]; + uint8_t dk[DKEK_KEY_SIZE]; memset(dk, 0, sizeof(dk)); if (store_dkek_key(p2, dk) != CCID_OK) return SW_EXEC_ERROR(); @@ -997,7 +989,7 @@ static int cmd_key_domain() { } //Stores the private and public keys in flash -int store_keys(void *key_ctx, int type, uint8_t key_id, uint8_t kdom) { +int store_keys(void *key_ctx, int type, uint8_t key_id) { int r, key_size = 0; uint8_t kdata[4096/8]; //worst case if (type == HSM_KEY_RSA) { @@ -1027,7 +1019,7 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, uint8_t kdom) { file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); if (!fpk) return SW_MEMORY_FAILURE(); - r = dkek_encrypt(kdom, kdata, key_size); + r = mkek_encrypt(kdata, key_size); if (r != CCID_OK) { return r; } @@ -1078,7 +1070,7 @@ int find_and_store_meta_key(uint8_t key_id) { } static int cmd_keypair_gen() { - uint8_t key_id = P1(apdu), kdom = 0; + uint8_t key_id = P1(apdu); if (!isUserAuthenticated) return SW_SECURITY_STATUS_NOT_SATISFIED(); int ret = 0; @@ -1090,10 +1082,6 @@ static int cmd_keypair_gen() { size_t oid_len = 0; uint8_t *oid = NULL; if (asn1_find_tag(p, tout, 0x6, &oid_len, &oid) && oid_len > 0 && oid != NULL) { - size_t kdom_size = 0; - uint8_t *kdomd = NULL; - if (asn1_find_tag(apdu.data, apdu.nc, 0x92, &kdom_size, &kdomd) && kdom_size > 0 && kdomd != NULL) - kdom = *kdomd; if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) { //RSA size_t ex_len = 3, ks_len = 2; uint8_t *ex = NULL, *ks = NULL; @@ -1124,7 +1112,7 @@ static int cmd_keypair_gen() { if ((res_APDU_size = asn1_cvc_aut(&rsa, HSM_KEY_RSA, res_APDU, 4096)) == 0) { return SW_EXEC_ERROR(); } - ret = store_keys(&rsa, HSM_KEY_RSA, key_id, kdom); + ret = store_keys(&rsa, HSM_KEY_RSA, key_id); if (ret != CCID_OK) { mbedtls_rsa_free(&rsa); return SW_EXEC_ERROR(); @@ -1152,7 +1140,7 @@ static int cmd_keypair_gen() { if ((res_APDU_size = asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096)) == 0) { return SW_EXEC_ERROR(); } - ret = store_keys(&ecdsa, HSM_KEY_EC, key_id, kdom); + ret = store_keys(&ecdsa, HSM_KEY_EC, key_id); if (ret != CCID_OK) { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); @@ -1281,22 +1269,18 @@ static int cmd_change_pin() { return r; uint8_t old_session_pin[32]; memcpy(old_session_pin, session_pin, sizeof(old_session_pin)); - for (uint8_t kdom = 0; kdom < MAX_KEY_DOMAINS; kdom++) { - uint8_t dkek[DKEK_SIZE]; - memcpy(session_pin, old_session_pin, sizeof(session_pin)); - r = load_dkek(kdom, dkek); //loads the DKEK with old pin - if (r == CCID_ERR_FILE_NOT_FOUND) - break; - else if (r != CCID_OK) - return SW_EXEC_ERROR(); - //encrypt DKEK with new pin - hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_pin); - has_session_pin = true; - r = store_dkek_key(kdom, dkek); - release_dkek(dkek); - if (r != CCID_OK) - return SW_EXEC_ERROR(); - } + uint8_t mkek[MKEK_SIZE]; + memcpy(session_pin, old_session_pin, sizeof(session_pin)); + r = load_mkek(mkek); //loads the MKEK with old pin + if (r != CCID_OK) + return SW_EXEC_ERROR(); + //encrypt MKEK with new pin + hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_pin); + has_session_pin = true; + r = store_mkek(mkek); + release_mkek(mkek); + if (r != CCID_OK) + return SW_EXEC_ERROR(); memset(old_session_pin, 0, sizeof(old_session_pin)); uint8_t dhash[33]; dhash[0] = apdu.nc-pin_len; @@ -1332,7 +1316,7 @@ static int cmd_key_gen() { aes_type = HSM_KEY_AES_192; else if (key_size == 32) aes_type = HSM_KEY_AES_256; - r = store_keys(aes_key, aes_type, key_id, 0); + r = store_keys(aes_key, aes_type, key_id); if (r != CCID_OK) return SW_MEMORY_FAILURE(); if (find_and_store_meta_key(key_id) != CCID_OK) @@ -1346,9 +1330,9 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { return CCID_VERIFICATION_FAILED; int key_size = file_get_size(fkey); - uint8_t kdata[4096/8], kdom = get_key_domain(fkey); + uint8_t kdata[4096/8]; memcpy(kdata, file_get_data(fkey), key_size); - if (dkek_decrypt(kdom, kdata, key_size) != 0) { + if (mkek_decrypt(kdata, key_size) != 0) { return CCID_EXEC_ERROR; } if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) { @@ -1382,10 +1366,10 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { if (wait_button() == true) //timeout return CCID_VERIFICATION_FAILED; - int key_size = file_get_size(fkey), kdom = get_key_domain(fkey); + int key_size = file_get_size(fkey); uint8_t kdata[67]; //Worst case, 521 bit + 1byte memcpy(kdata, file_get_data(fkey), key_size); - if (dkek_decrypt(kdom, kdata, key_size) != 0) { + if (mkek_decrypt(kdata, key_size) != 0) { return CCID_EXEC_ERROR; } mbedtls_ecp_group_id gid = kdata[0]; @@ -1666,7 +1650,7 @@ static int cmd_key_wrap() { int key_size = file_get_size(ef), aes_type = HSM_KEY_AES; memcpy(kdata, file_get_data(ef), key_size); - if (dkek_decrypt(kdom, kdata, key_size) != 0) { + if (mkek_decrypt(kdata, key_size) != 0) { return SW_EXEC_ERROR(); } if (key_size == 32) @@ -1703,7 +1687,7 @@ static int cmd_key_unwrap() { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } - r = store_keys(&ctx, HSM_KEY_RSA, key_id, kdom); + r = store_keys(&ctx, HSM_KEY_RSA, key_id); mbedtls_rsa_free(&ctx); if (r != CCID_OK) { return SW_EXEC_ERROR(); @@ -1719,7 +1703,7 @@ static int cmd_key_unwrap() { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } - r = store_keys(&ctx, HSM_KEY_EC, key_id, kdom); + r = store_keys(&ctx, HSM_KEY_EC, key_id); mbedtls_ecdsa_free(&ctx); if (r != CCID_OK) { return SW_EXEC_ERROR(); @@ -1742,7 +1726,7 @@ static int cmd_key_unwrap() { aes_type = HSM_KEY_AES_128; else return SW_EXEC_ERROR(); - r = store_keys(aes_key, aes_type, key_id, kdom); + r = store_keys(aes_key, aes_type, key_id); if (r != CCID_OK) { return SW_EXEC_ERROR(); } @@ -1805,9 +1789,9 @@ static int cmd_decrypt_asym() { if (wait_button() == true) //timeout return SW_SECURE_MESSAGE_EXEC_ERROR(); int key_size = file_get_size(ef); - uint8_t *kdata = (uint8_t *)calloc(1,key_size), kdom = get_key_domain(ef); + uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_get_data(ef), key_size); - if (dkek_decrypt(kdom, kdata, key_size) != 0) { + if (mkek_decrypt(kdata, key_size) != 0) { free(kdata); return SW_EXEC_ERROR(); } @@ -1878,9 +1862,8 @@ static int cmd_cipher_sym() { return SW_SECURE_MESSAGE_EXEC_ERROR(); int key_size = file_get_size(ef); uint8_t kdata[32]; //maximum AES key size - uint8_t kdom = get_key_domain(ef); memcpy(kdata, file_get_data(ef), key_size); - if (dkek_decrypt(kdom, kdata, key_size) != 0) { + if (mkek_decrypt(kdata, key_size) != 0) { return SW_EXEC_ERROR(); } if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) { @@ -2006,8 +1989,7 @@ static int cmd_derive_asym() { mbedtls_mpi_free(&nd); return SW_EXEC_ERROR(); } - uint8_t kdom = get_key_domain(fkey); - r = store_keys(&ctx, HSM_KEY_EC, dest_id, kdom); + r = store_keys(&ctx, HSM_KEY_EC, dest_id); if (r != CCID_OK) { mbedtls_ecdsa_free(&ctx); mbedtls_mpi_free(&a);