diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 0e7a753..747cfa9 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -149,22 +149,28 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_ uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding) memset(kb, 0, sizeof(kb)); - int kb_len = 0; + int kb_len = 0, r = 0; uint8_t *algo = NULL; uint8_t algo_len = 0; uint8_t *allowed = NULL; uint8_t allowed_len = 0; uint8_t kenc[32]; memset(kenc, 0, sizeof(kenc)); - dkek_kenc(id, kenc); + r = dkek_kenc(id, kenc); + if (r != CCID_OK) + return r; uint8_t kcv[8]; memset(kcv, 0, sizeof(kcv)); - dkek_kcv(id, kcv); + r = dkek_kcv(id, kcv); + if (r != CCID_OK) + return r; uint8_t kmac[32]; memset(kmac, 0, sizeof(kmac)); - dkek_kmac(id, kmac); + r = dkek_kmac(id, kmac); + if (r != CCID_OK) + return r; if (key_type & HSM_KEY_AES) { if (key_type & HSM_KEY_AES_128) @@ -272,7 +278,7 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_ if (kb_len < kb_len_pad) { kb[kb_len] = 0x80; } - int r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad); + r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad); if (r != CCID_OK) return r; @@ -299,22 +305,29 @@ int dkek_type_key(const uint8_t *in) { int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) { uint8_t kcv[8]; + int r = 0; memset(kcv, 0, sizeof(kcv)); - dkek_kcv(id, kcv); + r = dkek_kcv(id, kcv); + if (r != CCID_OK) + return r; uint8_t kmac[32]; memset(kmac, 0, sizeof(kmac)); - dkek_kmac(id, kmac); + r = dkek_kmac(id, kmac); + if (r != CCID_OK) + return r; uint8_t kenc[32]; memset(kenc, 0, sizeof(kenc)); - dkek_kenc(id, kenc); + r = dkek_kenc(id, kenc); + if (r != CCID_OK) + return r; if (memcmp(kcv, in, 8) != 0) return CCID_WRONG_DKEK; uint8_t signature[16]; - int r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len-16, signature); + r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len-16, signature); if (r != 0) return CCID_WRONG_SIGNATURE; if (memcmp(signature, in+in_len-16, 16) != 0) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index c2193e2..6b2ab97 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -846,8 +846,26 @@ static int cmd_key_domain() { return SW_OK(); } +uint8_t get_key_domain(file_t *fkey) { + if (!fkey) + return 0xff; + uint8_t *meta_data = NULL; + uint8_t meta_size = meta_find(fkey->fid, &meta_data); + DEBUG_PAYLOAD(meta_data,meta_size); + if (meta_size > 0 && meta_data != NULL) { + uint8_t tag = 0x0, *tag_data = NULL, *p = NULL; + size_t tag_len = 0; + while (walk_tlv(meta_data, meta_size, &p, &tag, &tag_len, &tag_data)) { + if (tag == 0x92) { //ofset tag + return *tag_data; + } + } + } + return 0; +} + //Stores the private and public keys in flash -int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) { +int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx, uint8_t kdom) { int r, key_size = 0; uint8_t *asn1bin = NULL; size_t asn1len = 0; @@ -876,13 +894,13 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) { } else return CCID_WRONG_DATA; - r = dkek_encrypt(0, kdata, key_size); - if (r != CCID_OK) { - return r; - } file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); if (!fpk) return SW_MEMORY_FAILURE(); + r = dkek_encrypt(kdom, kdata, key_size); + if (r != CCID_OK) { + return r; + } r = flash_write_data_to_file(fpk, kdata, key_size); if (r != CCID_OK) return r; @@ -958,7 +976,7 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) { } static int cmd_keypair_gen() { - uint8_t key_id = P1(apdu); + uint8_t key_id = P1(apdu), kdom = 0; if (!isUserAuthenticated) return SW_SECURITY_STATUS_NOT_SATISFIED(); sc_context_t *ctx = create_context(); @@ -976,6 +994,10 @@ static int cmd_keypair_gen() { size_t oid_len = 0; const uint8_t *oid = sc_asn1_find_tag(ctx, p, tout, 0x6, &oid_len); if (oid) { + size_t kdom_size = 0; + const uint8_t *kdomd = sc_asn1_find_tag(ctx, (const uint8_t *)apdu.data, apdu.nc, 0x92, &kdom_size); + if (kdomd && kdom_size > 0) + kdom = *kdomd; if (memcmp(oid, "\x4\x0\x7F\x0\x7\x2\x2\x2\x1\x2",MIN(oid_len,10)) == 0) { //RSA size_t ex_len, ks_len; const uint8_t *ex = sc_asn1_find_tag(ctx, p, tout, 0x82, &ex_len); @@ -1035,7 +1057,7 @@ static int cmd_keypair_gen() { free(p15card.card); return SW_EXEC_ERROR(); } - ret = store_keys(&rsa, SC_PKCS15_TYPE_PRKEY_RSA, key_id, ctx); + ret = store_keys(&rsa, SC_PKCS15_TYPE_PRKEY_RSA, key_id, ctx, kdom); if (ret != CCID_OK) { sc_pkcs15emu_sc_hsm_free_cvc(&cvc); mbedtls_rsa_free(&rsa); @@ -1161,7 +1183,7 @@ static int cmd_keypair_gen() { return SW_EXEC_ERROR(); } - ret = store_keys(&ecdsa, SC_PKCS15_TYPE_PRKEY_EC, key_id, ctx); + ret = store_keys(&ecdsa, SC_PKCS15_TYPE_PRKEY_EC, key_id, ctx, kdom); if (ret != CCID_OK) { sc_pkcs15emu_sc_hsm_free_cvc(&cvc); mbedtls_ecdsa_free(&ecdsa); @@ -1337,18 +1359,24 @@ static int cmd_change_pin() { } uint8_t pin_len = file_read_uint8(file_get_data(file_pin1)); uint16_t r = check_pin(file_pin1, apdu.data, pin_len); - uint8_t dkek[DKEK_SIZE]; if (r != 0x9000) return r; - if (load_dkek(0, dkek) != CCID_OK) //loads the DKEK with old pin - 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(0, dkek); - release_dkek(dkek); - if (r != CCID_OK) - return SW_EXEC_ERROR(); + 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)); + if (load_dkek(kdom, dkek) != CCID_OK) //loads the DKEK with old pin + 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(); + } + memset(old_session_pin, 0, sizeof(old_session_pin)); uint8_t dhash[33]; dhash[0] = apdu.nc-pin_len; double_hash_pin(apdu.data+pin_len, apdu.nc-pin_len, dhash+1); @@ -1384,7 +1412,7 @@ static int cmd_key_gen() { else if (key_size == 32) aes_type = HSM_KEY_AES_256; sc_context_t *card_ctx = create_context(); - r = store_keys(aes_key, aes_type, key_id, card_ctx); + r = store_keys(aes_key, aes_type, key_id, card_ctx, 0); free(card_ctx); if (r != CCID_OK) return SW_MEMORY_FAILURE(); @@ -1397,9 +1425,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]; + uint8_t kdata[4096/8], kdom = get_key_domain(fkey); memcpy(kdata, file_get_data(fkey), key_size); - if (dkek_decrypt(0, kdata, key_size) != 0) { + if (dkek_decrypt(kdom, kdata, key_size) != 0) { return CCID_EXEC_ERROR; } if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) { @@ -1433,10 +1461,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); + int key_size = file_get_size(fkey), kdom = get_key_domain(fkey); uint8_t kdata[67]; //Worst case, 521 bit + 1byte memcpy(kdata, file_get_data(fkey), key_size); - if (dkek_decrypt(0, kdata, key_size) != 0) { + if (dkek_decrypt(kdom, kdata, key_size) != 0) { return CCID_EXEC_ERROR; } mbedtls_ecp_group_id gid = kdata[0]; @@ -1604,6 +1632,7 @@ static int cmd_key_wrap() { if (!isUserAuthenticated) return SW_SECURITY_STATUS_NOT_SATISFIED(); file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id); + uint8_t kdom = get_key_domain(ef); if (!ef) return SW_FILE_NOT_FOUND(); file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id); @@ -1621,7 +1650,7 @@ static int cmd_key_wrap() { return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_EXEC_ERROR(); } - r = dkek_encode_key(0, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len); + r = dkek_encode_key(kdom, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len); mbedtls_rsa_free(&ctx); } else if (*dprkd == P15_KEYTYPE_ECC) { @@ -1634,7 +1663,7 @@ static int cmd_key_wrap() { return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_EXEC_ERROR(); } - r = dkek_encode_key(0, &ctx, HSM_KEY_EC, res_APDU, &wrap_len); + r = dkek_encode_key(kdom, &ctx, HSM_KEY_EC, res_APDU, &wrap_len); mbedtls_ecdsa_free(&ctx); } else if (*dprkd == P15_KEYTYPE_AES) { @@ -1644,7 +1673,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(0, kdata, key_size) != 0) { + if (dkek_decrypt(kdom, kdata, key_size) != 0) { return SW_EXEC_ERROR(); } if (key_size == 32) @@ -1653,7 +1682,7 @@ static int cmd_key_wrap() { aes_type = HSM_KEY_AES_192; else if (key_size == 16) aes_type = HSM_KEY_AES_128; - r = dkek_encode_key(0, kdata, aes_type, res_APDU, &wrap_len); + r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len); } if (r != CCID_OK) return SW_EXEC_ERROR(); @@ -1668,18 +1697,21 @@ static int cmd_key_unwrap() { if (!isUserAuthenticated) return SW_SECURITY_STATUS_NOT_SATISFIED(); int key_type = dkek_type_key(apdu.data); + uint8_t kdom = -1; if (key_type == 0x0) return SW_DATA_INVALID(); if (key_type == HSM_KEY_RSA) { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); - r = dkek_decode_key(0, &ctx, apdu.data, apdu.nc, NULL); + do { + r = dkek_decode_key(++kdom, &ctx, apdu.data, apdu.nc, NULL); + } while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); if (r != CCID_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } sc_context_t *card_ctx = create_context(); - r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_RSA, key_id, card_ctx); + r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_RSA, key_id, card_ctx, kdom); free(card_ctx); mbedtls_rsa_free(&ctx); if (r != CCID_OK) { @@ -1689,13 +1721,15 @@ static int cmd_key_unwrap() { else if (key_type == HSM_KEY_EC) { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); - r = dkek_decode_key(0, &ctx, apdu.data, apdu.nc, NULL); + do { + r = dkek_decode_key(++kdom, &ctx, apdu.data, apdu.nc, NULL); + } while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); if (r != CCID_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } sc_context_t *card_ctx = create_context(); - r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, key_id, card_ctx); + r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, key_id, card_ctx, kdom); free(card_ctx); mbedtls_ecdsa_free(&ctx); if (r != CCID_OK) { @@ -1705,7 +1739,9 @@ static int cmd_key_unwrap() { else if (key_type == HSM_KEY_AES) { uint8_t aes_key[32]; int key_size = 0, aes_type = 0; - r = dkek_decode_key(0, aes_key, apdu.data, apdu.nc, &key_size); + do { + r = dkek_decode_key(++kdom, aes_key, apdu.data, apdu.nc, &key_size); + } while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); if (r != CCID_OK) { return SW_EXEC_ERROR(); } @@ -1718,12 +1754,18 @@ static int cmd_key_unwrap() { else return SW_EXEC_ERROR(); sc_context_t *card_ctx = create_context(); - r = store_keys(aes_key, aes_type, key_id, card_ctx); + r = store_keys(aes_key, aes_type, key_id, card_ctx, kdom); free(card_ctx); if (r != CCID_OK) { return SW_EXEC_ERROR(); } } + if (kdom > 0) { + uint8_t meta[3] = {0x92,1,kdom}; + r = meta_add((KEY_PREFIX << 8) | key_id, meta, sizeof(meta)); + if (r != CCID_OK) + return r; + } return SW_OK(); } @@ -1760,9 +1802,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); + uint8_t *kdata = (uint8_t *)calloc(1,key_size), kdom = get_key_domain(ef); memcpy(kdata, file_get_data(ef), key_size); - if (dkek_decrypt(0, kdata, key_size) != 0) { + if (dkek_decrypt(kdom, kdata, key_size) != 0) { free(kdata); return SW_EXEC_ERROR(); } @@ -1817,8 +1859,9 @@ 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(0, kdata, key_size) != 0) { + if (dkek_decrypt(kdom, kdata, key_size) != 0) { return SW_EXEC_ERROR(); } if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) { @@ -1944,7 +1987,8 @@ static int cmd_derive_asym() { return SW_EXEC_ERROR(); } sc_context_t *card_ctx = create_context(); - r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, dest_id, card_ctx); + uint8_t kdom = get_key_domain(fkey); + r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, dest_id, card_ctx, kdom); free(card_ctx); if (r != CCID_OK) { mbedtls_ecdsa_free(&ctx);