From d061958f90bcd8a651e365276ca8d16d1a828acb Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 16:02:28 +0200 Subject: [PATCH 01/21] Moving hash to other file. Signed-off-by: Pol Henarejos --- CMakeLists.txt | 1 + src/hsm/hash_utils.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ src/hsm/hash_utils.h | 26 ++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/hsm/hash_utils.c create mode 100644 src/hsm/hash_utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 79ecbfa..577a5f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ target_sources(pico_hsm PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c ${CMAKE_CURRENT_LIST_DIR}/src/rng/random.c ${CMAKE_CURRENT_LIST_DIR}/src/rng/neug.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/hash_utils.c ${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha256.c ${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aes.c diff --git a/src/hsm/hash_utils.c b/src/hsm/hash_utils.c new file mode 100644 index 0000000..28228f0 --- /dev/null +++ b/src/hsm/hash_utils.c @@ -0,0 +1,73 @@ +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "mbedtls/md.h" +#include "mbedtls/sha256.h" +#include "hash_utils.h" + +void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) { + uint8_t o1[32]; + hash_multi(pin, len, o1); + for (int i = 0; i < sizeof(o1); i++) + o1[i] ^= pin[i%len]; + hash_multi(o1, sizeof(o1), output); +} + +void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]) { + mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + int iters = 256; + pico_unique_board_id_t unique_id; + + pico_get_unique_board_id(&unique_id); + + mbedtls_sha256_starts (&ctx, 0); + mbedtls_sha256_update (&ctx, unique_id.id, sizeof(unique_id.id)); + + while (iters > len) + { + mbedtls_sha256_update (&ctx, input, len); + iters -= len; + } + if (iters > 0) // remaining iterations + mbedtls_sha256_update (&ctx, input, iters); + mbedtls_sha256_finish (&ctx, output); + mbedtls_sha256_free (&ctx); +} + +void hash256(const uint8_t *input, size_t len, uint8_t output[32]) { + mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + + mbedtls_sha256_starts (&ctx, 0); + mbedtls_sha256_update (&ctx, input, len); + + mbedtls_sha256_finish (&ctx, output); + mbedtls_sha256_free (&ctx); +} + +void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output) { + mbedtls_md_context_t ctx; + mbedtls_md_init(&ctx); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md); + mbedtls_md_setup(&ctx, md_info, 0); + mbedtls_md_starts(&ctx); + mbedtls_md_update(&ctx, input, len); + mbedtls_md_finish(&ctx, output); + mbedtls_md_free(&ctx); +} diff --git a/src/hsm/hash_utils.h b/src/hsm/hash_utils.h new file mode 100644 index 0000000..cb0b067 --- /dev/null +++ b/src/hsm/hash_utils.h @@ -0,0 +1,26 @@ +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _HASH_UTILS_H_ +#define _HASH_UTILS_H_ + +extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]); +extern void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]); +extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]); +extern void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output); + +#endif From 6fe7d7991b5f2919e27d21b835a03d75c0f726e8 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 17:37:24 +0200 Subject: [PATCH 02/21] Len of CMAC is always 16. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 60 ++++-------------------------------------------- 1 file changed, 5 insertions(+), 55 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 060833d..014ecc1 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -30,6 +30,7 @@ #include "mbedtls/hkdf.h" #include "version.h" #include "cvcerts.h" +#include "hash_utils.h" const uint8_t sc_hsm_aid[] = { 11, @@ -73,6 +74,7 @@ int sc_hsm_unload() { return HSM_OK; } +//AES CBC encryption with a 256 bit key static int encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { mbedtls_aes_context aes; @@ -86,6 +88,7 @@ static int encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data); } +//AES CBC decryption with a 256 bit key static int decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { mbedtls_aes_context aes; @@ -268,7 +271,7 @@ int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_ free(cvcbin); return r; } - hash(cvcbin, cvclen, hsh); + hash256(cvcbin, cvclen, hsh); free(cvcbin); return HSM_OK; } @@ -606,59 +609,6 @@ static int cmd_initialize() { return SW_OK(); } -void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) { - uint8_t o1[32]; - hash_multi(pin, len, o1); - for (int i = 0; i < sizeof(o1); i++) - o1[i] ^= pin[i%len]; - hash_multi(o1, sizeof(o1), output); -} - -void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]) -{ - mbedtls_sha256_context ctx; - mbedtls_sha256_init(&ctx); - int iters = 256; - - pico_get_unique_board_id(&unique_id); - - mbedtls_sha256_starts (&ctx, 0); - mbedtls_sha256_update (&ctx, unique_id.id, sizeof(unique_id.id)); - - while (iters > len) - { - mbedtls_sha256_update (&ctx, input, len); - iters -= len; - } - if (iters > 0) // remaining iterations - mbedtls_sha256_update (&ctx, input, iters); - mbedtls_sha256_finish (&ctx, output); - mbedtls_sha256_free (&ctx); -} - -void hash(const uint8_t *input, size_t len, uint8_t output[32]) -{ - mbedtls_sha256_context ctx; - mbedtls_sha256_init(&ctx); - - mbedtls_sha256_starts (&ctx, 0); - mbedtls_sha256_update (&ctx, input, len); - - mbedtls_sha256_finish (&ctx, output); - mbedtls_sha256_free (&ctx); -} - -void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output) { - mbedtls_md_context_t ctx; - mbedtls_md_init(&ctx); - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md); - mbedtls_md_setup(&ctx, md_info, 0); - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, input, len); - mbedtls_md_finish(&ctx, output); - mbedtls_md_free(&ctx); -} - static int cmd_import_dkek() { //if (dkeks == 0) // return SW_COMMAND_NOT_ALLOWED(); @@ -1610,7 +1560,7 @@ static int cmd_cipher_sym() { int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size*8, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU); if (r != 0) return SW_EXEC_ERROR(); - res_APDU_size = apdu.cmd_apdu_data_len; + res_APDU_size = 16; } else if (algo == ALGO_AES_DERIVE) { int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, file_read(ef->data+2), key_size, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU, apdu.cmd_apdu_data_len); From 2535d0e53758823ff9e2eef4ec683264630532e0 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 17:37:53 +0200 Subject: [PATCH 03/21] Adding generic aes encryption/decryption. Signed-off-by: Pol Henarejos --- src/hsm/hash_utils.c | 30 ++++++++++++++++++++++++++++++ src/hsm/hash_utils.h | 6 ++++++ src/hsm/sc_hsm.h | 2 ++ 3 files changed, 38 insertions(+) diff --git a/src/hsm/hash_utils.c b/src/hsm/hash_utils.c index 28228f0..9659174 100644 --- a/src/hsm/hash_utils.c +++ b/src/hsm/hash_utils.c @@ -18,7 +18,9 @@ #include #include "mbedtls/md.h" #include "mbedtls/sha256.h" +#include "mbedtls/aes.h" #include "hash_utils.h" +#include "sc_hsm.h" void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) { uint8_t o1[32]; @@ -71,3 +73,31 @@ void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_ mbedtls_md_finish(&ctx, output); mbedtls_md_free(&ctx); } + +int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len) { + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + uint8_t tmp_iv[IV_SIZE]; + size_t iv_offset = 0; + memset(tmp_iv, 0, IV_SIZE); + if (iv) + memcpy(tmp_iv, iv, IV_SIZE); + int r = mbedtls_aes_setkey_enc(&aes, key, key_size); + if (r != 0) + return HSM_EXEC_ERROR; + return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data); +} + +int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len) { + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + uint8_t tmp_iv[IV_SIZE]; + size_t iv_offset = 0; + memset(tmp_iv, 0, IV_SIZE); + if (iv) + memcpy(tmp_iv, iv, IV_SIZE); + int r = mbedtls_aes_setkey_enc(&aes, key, key_size); + if (r != 0) + return HSM_EXEC_ERROR; + return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data); +} \ No newline at end of file diff --git a/src/hsm/hash_utils.h b/src/hsm/hash_utils.h index cb0b067..0f15eb8 100644 --- a/src/hsm/hash_utils.h +++ b/src/hsm/hash_utils.h @@ -18,9 +18,15 @@ #ifndef _HASH_UTILS_H_ #define _HASH_UTILS_H_ +#include "stdlib.h" +#include "pico/stdlib.h" +#include "mbedtls/md.h" + extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]); extern void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]); extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]); extern void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output); +extern int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len); +extern int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len); #endif diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index 20113c9..ff6a07d 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -60,6 +60,8 @@ extern const uint8_t sc_hsm_aid[]; #define HSM_ERR_BLOCKED -1004 #define HSM_NO_LOGIN -1005 #define HSM_EXEC_ERROR -1006 +#define HSM_WRONG_LENGTH -1007 +#define HSM_WRONG_DATA -1008 #define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */ #define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */ From 7a9ee8145d51918e926c6280f514e1140afe63ad Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 17:38:02 +0200 Subject: [PATCH 04/21] Adding headers to random.h Signed-off-by: Pol Henarejos --- src/rng/random.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rng/random.h b/src/rng/random.h index 0bd11ad..d13c415 100644 --- a/src/rng/random.h +++ b/src/rng/random.h @@ -19,6 +19,9 @@ #ifndef _RANDOM_H_ #define _RANDOM_H_ +#include "stdlib.h" +#include "pico/stdlib.h" + void random_init (void); void random_fini (void); From 047a443536baca19ae80e83ca34f14375b4c3949 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 17:38:15 +0200 Subject: [PATCH 05/21] Adding dkek procedures to wrap/unwrap. Signed-off-by: Pol Henarejos --- CMakeLists.txt | 1 + src/hsm/dkek.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ src/hsm/dkek.h | 21 ++++++++ 3 files changed, 151 insertions(+) create mode 100644 src/hsm/dkek.c create mode 100644 src/hsm/dkek.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 577a5f0..49b0567 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ target_sources(pico_hsm PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/rng/random.c ${CMAKE_CURRENT_LIST_DIR}/src/rng/neug.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/hash_utils.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c ${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha256.c ${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aes.c diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c new file mode 100644 index 0000000..5453fba --- /dev/null +++ b/src/hsm/dkek.c @@ -0,0 +1,129 @@ +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "stdlib.h" +#include "pico/stdlib.h" +#include "dkek.h" +#include "hash_utils.h" +#include "random.h" +#include "sc_hsm.h" +#include "mbedtls/md.h" +#include "mbedtls/cmac.h" + +static uint8_t dkek[32]; + +void init_dkek() { + memset(dkek, 0, sizeof(dkek)); +} + +void import_dkek_share(const uint8_t *share) { + for (int i = 0; i < 32; i++) + dkek[i] ^= share[i]; +} + +void dkek_kcv(uint8_t *kcv) { //kcv 8 bytes + uint8_t hsh[32]; + hash256(dkek, sizeof(dkek), hsh); + memcpy(kcv, hsh, 8); +} + +void dkek_kenc(uint8_t *kenc) { //kenc 32 bytes + uint8_t buf[32+4]; + memcpy(buf, dkek, sizeof(dkek)); + memcpy(buf, "\x0\x0\x0\x1", 4); + hash256(dkek, sizeof(dkek), kenc); +} + +void dkek_kmac(uint8_t *kmac) { //kmac 32 bytes + uint8_t buf[32+4]; + memcpy(buf, dkek, sizeof(dkek)); + memcpy(buf, "\x0\x0\x0\x2", 4); + hash256(dkek, sizeof(dkek), kmac); +} + +int dkek_encode_aes_key(uint8_t *key, int key_size, uint8_t *out, size_t *out_len) { //out has to be 93 bytes at least + if (key_size != 16 || key_size != 24 || key_size != 32) + return HSM_WRONG_DATA; + if (*out_len < 8+1+10+6+4+48+16) + return HSM_WRONG_LENGTH; + uint8_t kb[48]; //worst case (8+2+key_size+padding) + memset(kb, 0, sizeof(kb)); + + uint8_t kenc[32]; + memset(kenc, 0, sizeof(kenc)); + dkek_kenc(kenc); + + uint8_t kcv[8]; + memset(kcv, 0, sizeof(kcv)); + dkek_kcv(kcv); + + uint8_t kmac[32]; + memset(kmac, 0, sizeof(kmac)); + dkek_kmac(kmac); + + int kb_len = 8+2+key_size; + int kb_len_pad = ((int)(kb_len/16))*16; + if (kb_len % 16 > 0) + kb_len_pad = ((int)(kb_len/16)+1)*16; + memcpy(kb, random_bytes_get(8), 8); + put_uint16_t(key_size, kb+8); + memcpy(kb+8+2, key, key_size); + if (kb_len < kb_len_pad) { + kb[kb_len] = 0x80; + } + int r = aes_encrypt(kenc, NULL, 32, kb, kb_len_pad); + if (r != HSM_OK) + return r; + + memset(out, 0, *out_len); + *out_len = 0; + uint8_t *aes_oid = "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8) + uint8_t *aes_algo = "\x00\x04\x10\x11\x18\x99"; //(2+4) + + memcpy(out+*out_len, kcv, 8); + *out_len += 8; + + out[*out_len] = 15; + *out_len += 1; + + memcpy(out+*out_len, aes_oid, 10); + *out_len += 10; + + memcpy(out+*out_len, aes_algo, 6); + *out_len += 6; + + //add 4 zeros + *out_len += 4; + + memcpy(out+*out_len, kb, kb_len_pad); + *out_len += kb_len_pad; + + const mbedtls_cipher_info_t *cipher_info; + if (key_size == 16) + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); + else if (key_size == 24) + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB); + else if (key_size == 32) + cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB); + r = mbedtls_cipher_cmac(cipher_info, kmac, 256, out, *out_len, out+*out_len); + + *out_len += 16; + if (r != 0) + return r; + return HSM_OK; +} \ No newline at end of file diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h new file mode 100644 index 0000000..aa6ca53 --- /dev/null +++ b/src/hsm/dkek.h @@ -0,0 +1,21 @@ +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _DKEK_H_ +#define _DKEK_H_ + +#endif From 427260663f80661ba9e4f909482f0da7b20d64f1 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 09:34:44 +0200 Subject: [PATCH 06/21] Replacing CFB to CBC AES proc Signed-off-by: Pol Henarejos --- src/hsm/hash_utils.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hsm/hash_utils.c b/src/hsm/hash_utils.c index 9659174..bd25654 100644 --- a/src/hsm/hash_utils.c +++ b/src/hsm/hash_utils.c @@ -78,26 +78,24 @@ int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *da mbedtls_aes_context aes; mbedtls_aes_init(&aes); uint8_t tmp_iv[IV_SIZE]; - size_t iv_offset = 0; memset(tmp_iv, 0, IV_SIZE); if (iv) memcpy(tmp_iv, iv, IV_SIZE); int r = mbedtls_aes_setkey_enc(&aes, key, key_size); if (r != 0) return HSM_EXEC_ERROR; - return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data); + return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, len, tmp_iv, data, data); } int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len) { mbedtls_aes_context aes; mbedtls_aes_init(&aes); uint8_t tmp_iv[IV_SIZE]; - size_t iv_offset = 0; memset(tmp_iv, 0, IV_SIZE); if (iv) memcpy(tmp_iv, iv, IV_SIZE); - int r = mbedtls_aes_setkey_enc(&aes, key, key_size); + int r = mbedtls_aes_setkey_dec(&aes, key, key_size); if (r != 0) return HSM_EXEC_ERROR; - return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data); + return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data); } \ No newline at end of file From 7b0d5a6700118b6599e9565bd679e34e4af7c8e6 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 09:35:06 +0200 Subject: [PATCH 07/21] Fix loading aes key in decrypt function Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 014ecc1..85195f9 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -74,7 +74,7 @@ int sc_hsm_unload() { return HSM_OK; } -//AES CBC encryption with a 256 bit key +//AES CFB encryption with a 256 bit key static int encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { mbedtls_aes_context aes; @@ -82,13 +82,13 @@ static int encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len uint8_t tmp_iv[IV_SIZE]; size_t iv_offset = 0; memcpy(tmp_iv, iv, IV_SIZE); - int r = mbedtls_aes_setkey_enc (&aes, key, 256); + int r = mbedtls_aes_setkey_enc(&aes, key, 256); if (r != 0) return HSM_EXEC_ERROR; return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data); } -//AES CBC decryption with a 256 bit key +//AES CFB decryption with a 256 bit key static int decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { mbedtls_aes_context aes; @@ -96,7 +96,7 @@ static int decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len uint8_t tmp_iv[IV_SIZE]; size_t iv_offset = 0; memcpy(tmp_iv, iv, IV_SIZE); - int r = mbedtls_aes_setkey_enc (&aes, key, 256); + int r = mbedtls_aes_setkey_dec(&aes, key, 256); if (r != 0) return HSM_EXEC_ERROR; return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data); From 5eb74d8ca30e451d017c7c8896d4151b7ef77488 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 13:45:07 +0200 Subject: [PATCH 08/21] Adding encode_key with dkek (for wrapping). Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 206 ++++++++++++++++++++++++++++++++++++++--------- src/hsm/sc_hsm.h | 10 +++ 2 files changed, 176 insertions(+), 40 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 5453fba..08f3b98 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -16,6 +16,7 @@ */ #include +#include "common.h" #include "stdlib.h" #include "pico/stdlib.h" #include "dkek.h" @@ -24,16 +25,59 @@ #include "sc_hsm.h" #include "mbedtls/md.h" #include "mbedtls/cmac.h" +#include "mbedtls/rsa.h" +#include "mbedtls/ecdsa.h" -static uint8_t dkek[32]; +static uint8_t dkek[IV_SIZE+32]; +static uint8_t tmp_dkek[32]; +extern bool has_session_pin; +extern uint8_t session_pin[32]; + +int load_dkek() { + if (has_session_pin == false) + return HSM_NO_LOGIN; + file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); + if (!tf) + return HSM_ERR_FILE_NOT_FOUND; + memcpy(dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32); + int ret = aes_decrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32); + if (ret != 0) + return HSM_EXEC_ERROR; + return HSM_OK; +} + +void release_dkek() { + memset(dkek, 0, sizeof(dkek)); +} void init_dkek() { - memset(dkek, 0, sizeof(dkek)); + release_dkek(); + memset(tmp_dkek, 0, sizeof(tmp_dkek)); +} + +int store_dkek_key() { + aes_encrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32); + file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); + if (!tf) + return HSM_ERR_FILE_NOT_FOUND; + flash_write_data_to_file(tf, dkek, sizeof(dkek)); + low_flash_available(); + release_dkek(); + return HSM_OK; +} + +int save_dkek_key(const uint8_t *key) { + const uint8_t *iv = random_bytes_get(32); + memcpy(dkek, iv, IV_SIZE); + if (!key) + key = tmp_dkek; + memcpy(dkek+IV_SIZE, key, 32); + return store_dkek_key(); } void import_dkek_share(const uint8_t *share) { for (int i = 0; i < 32; i++) - dkek[i] ^= share[i]; + tmp_dkek[i] ^= share[i]; } void dkek_kcv(uint8_t *kcv) { //kcv 8 bytes @@ -56,15 +100,37 @@ void dkek_kmac(uint8_t *kmac) { //kmac 32 bytes hash256(dkek, sizeof(dkek), kmac); } -int dkek_encode_aes_key(uint8_t *key, int key_size, uint8_t *out, size_t *out_len) { //out has to be 93 bytes at least - if (key_size != 16 || key_size != 24 || key_size != 32) +int dkek_encrypt(uint8_t *data, size_t len) { + int r; + if ((r = load_dkek()) != HSM_OK) + return r; + r = aes_encrypt_cfb_256(dkek+IV_SIZE, dkek, data, len); + release_dkek(); + return r; +} + +int dkek_decrypt(uint8_t *data, size_t len) { + int r; + if ((r = load_dkek()) != HSM_OK) + return r; + r = aes_decrypt_cfb_256(dkek+IV_SIZE, dkek, data, len); + release_dkek(); + return r; +} + +int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) { + if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES)) return HSM_WRONG_DATA; - if (*out_len < 8+1+10+6+4+48+16) - return HSM_WRONG_LENGTH; - uint8_t kb[48]; //worst case (8+2+key_size+padding) + + uint8_t kb[2*4096/8+3+8+5]; //worst case: RSA-4096 (ECC is 596 max) (plus, 5 bytes padding) memset(kb, 0, sizeof(kb)); - + int kb_len = 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(kenc); @@ -76,54 +142,114 @@ int dkek_encode_aes_key(uint8_t *key, int key_size, uint8_t *out, size_t *out_le memset(kmac, 0, sizeof(kmac)); dkek_kmac(kmac); - int kb_len = 8+2+key_size; - int kb_len_pad = ((int)(kb_len/16))*16; - if (kb_len % 16 > 0) - kb_len_pad = ((int)(kb_len/16)+1)*16; - memcpy(kb, random_bytes_get(8), 8); - put_uint16_t(key_size, kb+8); - memcpy(kb+8+2, key, key_size); - if (kb_len < kb_len_pad) { - kb[kb_len] = 0x80; + if (key_type & HSM_KEY_AES) { + if (key_type & HSM_KEY_AES_128) + kb_len = 16; + else if (key_type & HSM_KEY_AES_192) + kb_len = 24; + else if (key_type & HSM_KEY_AES_256) + kb_len = 32; + + if (kb_len != 16 && kb_len != 24 && kb_len != 32) + return HSM_WRONG_DATA; + if (*out_len < 8+1+10+6+4+48+16) + return HSM_WRONG_LENGTH; + + memcpy(kb+10, key_ctx, kb_len); + put_uint16_t(kb_len, kb+8); + kb_len += 2; + + algo = "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8) + algo_len = 10; + allowed = "\x00\x04\x10\x11\x18\x99"; //(2+4) + allowed_len = 6; + } + else if (key_type & HSM_KEY_RSA) { + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; + kb_len = 0; + put_uint16_t(mbedtls_rsa_get_len(rsa)*8, kb+8+kb_len); kb_len += 2; + + put_uint16_t(mbedtls_mpi_size(&rsa->D), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&rsa->D, kb+8+kb_len, mbedtls_mpi_size(&rsa->D)); kb_len += mbedtls_mpi_size(&rsa->D); + put_uint16_t(mbedtls_mpi_size(&rsa->N), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&rsa->N, kb+8+kb_len, mbedtls_mpi_size(&rsa->N)); kb_len += mbedtls_mpi_size(&rsa->N); + put_uint16_t(mbedtls_mpi_size(&rsa->E), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&rsa->E, kb+8+kb_len, mbedtls_mpi_size(&rsa->E)); kb_len += mbedtls_mpi_size(&rsa->E); + } + else if (key_type & HSM_KEY_EC) { + mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; + kb_len = 0; + put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P)*8, kb+8+kb_len); kb_len += 2; + put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.A), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&ecdsa->grp.A, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.A)); kb_len += mbedtls_mpi_size(&ecdsa->grp.A); + put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.B), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&ecdsa->grp.B, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.B)); kb_len += mbedtls_mpi_size(&ecdsa->grp.B); + put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&ecdsa->grp.P, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.P)); kb_len += mbedtls_mpi_size(&ecdsa->grp.P); + put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.N), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&ecdsa->grp.N, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.N)); kb_len += mbedtls_mpi_size(&ecdsa->grp.N); + put_uint16_t(1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.Y), kb+8+kb_len); kb_len += 2; + kb[8+kb_len++] = 0x4; + mbedtls_mpi_write_binary(&ecdsa->grp.G.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.G.X)); kb_len += mbedtls_mpi_size(&ecdsa->grp.G.X); + mbedtls_mpi_write_binary(&ecdsa->grp.G.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->grp.G.Y)); kb_len += mbedtls_mpi_size(&ecdsa->grp.G.Y); + put_uint16_t(mbedtls_mpi_size(&ecdsa->d), kb+8+kb_len); kb_len += 2; + mbedtls_mpi_write_binary(&ecdsa->d, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->d)); kb_len += mbedtls_mpi_size(&ecdsa->d); + put_uint16_t(1+mbedtls_mpi_size(&ecdsa->Q.X)+mbedtls_mpi_size(&ecdsa->Q.Y), kb+8+kb_len); kb_len += 2; + kb[8+kb_len++] = 0x4; + mbedtls_mpi_write_binary(&ecdsa->Q.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.X)); kb_len += mbedtls_mpi_size(&ecdsa->Q.X); + mbedtls_mpi_write_binary(&ecdsa->Q.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.Y)); kb_len += mbedtls_mpi_size(&ecdsa->Q.Y); } - int r = aes_encrypt(kenc, NULL, 32, kb, kb_len_pad); - if (r != HSM_OK) - return r; - memset(out, 0, *out_len); *out_len = 0; - uint8_t *aes_oid = "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8) - uint8_t *aes_algo = "\x00\x04\x10\x11\x18\x99"; //(2+4) memcpy(out+*out_len, kcv, 8); *out_len += 8; - out[*out_len] = 15; + if (key_type == HSM_KEY_AES) + out[*out_len] = 15; + else if (key_type == HSM_KEY_RSA) + out[*out_len] = 5; + else if (key_type == HSM_KEY_EC) + out[*out_len] = 12; *out_len += 1; - memcpy(out+*out_len, aes_oid, 10); - *out_len += 10; - - memcpy(out+*out_len, aes_algo, 6); - *out_len += 6; + if (algo) { + memcpy(out+*out_len, algo, algo_len); + *out_len += algo_len; + } + else + *out_len += 2; + if (allowed) { + memcpy(out+*out_len, allowed, allowed_len); + *out_len += allowed_len; + } + else + *out_len += 2; //add 4 zeros *out_len += 4; + + memcpy(kb, random_bytes_get(8), 8); + kb_len += 8; //8 random bytes + int kb_len_pad = ((int)(kb_len/16))*16; + if (kb_len % 16 > 0) + kb_len_pad = ((int)(kb_len/16)+1)*16; + //key already copied at kb+10 + if (kb_len < kb_len_pad) { + kb[kb_len] = 0x80; + } + int r = aes_encrypt(kenc, NULL, 32, HSM_AES_MODE_CBC, kb, kb_len_pad); + if (r != HSM_OK) + return r; memcpy(out+*out_len, kb, kb_len_pad); *out_len += kb_len_pad; - - const mbedtls_cipher_info_t *cipher_info; - if (key_size == 16) - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); - else if (key_size == 24) - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB); - else if (key_size == 32) - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB); - r = mbedtls_cipher_cmac(cipher_info, kmac, 256, out, *out_len, out+*out_len); + + r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, out, *out_len, out+*out_len); *out_len += 16; if (r != 0) return r; return HSM_OK; -} \ No newline at end of file +} + diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index ff6a07d..4158ce1 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -94,6 +94,16 @@ extern const uint8_t sc_hsm_aid[]; #define HSM_OPT_COMBINED_AUTH 0x10 #define HSM_OPT_RRC_RESET_ONLY 0x20 +#define HSM_KEY_RSA 0x1 +#define HSM_KEY_EC 0x10 +#define HSM_KEY_AES 0x100 +#define HSM_KEY_AES_128 0x300 +#define HSM_KEY_AES_192 0x500 +#define HSM_KEY_AES_256 0x900 + +#define HSM_AES_MODE_CBC 1 +#define HSM_AES_MODE_CFB 2 + extern int pin_reset_retries(const file_t *pin, bool); extern int pin_wrong_retry(const file_t *pin); From 2f4cca19c441c673cb0ce38b7f04b81e646716d9 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 13:45:28 +0200 Subject: [PATCH 09/21] Moving some dkek crypt stuff to dkek. Signed-off-by: Pol Henarejos --- src/hsm/dkek.h | 9 ++++ src/hsm/hash_utils.c | 21 ++++++-- src/hsm/hash_utils.h | 6 ++- src/hsm/sc_hsm.c | 118 +++++++++---------------------------------- 4 files changed, 55 insertions(+), 99 deletions(-) diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h index aa6ca53..12f9248 100644 --- a/src/hsm/dkek.h +++ b/src/hsm/dkek.h @@ -18,4 +18,13 @@ #ifndef _DKEK_H_ #define _DKEK_H_ +extern int load_dkek(); +extern int save_dkek_key(const uint8_t *key); +extern int store_dkek_key(); +extern void release_dkek(); +extern void import_dkek_share(const uint8_t *share); +extern void dkek_kcv(uint8_t *kcv); +extern int dkek_encrypt(uint8_t *data, size_t len); +extern int dkek_decrypt(uint8_t *data, size_t len); + #endif diff --git a/src/hsm/hash_utils.c b/src/hsm/hash_utils.c index bd25654..e7e81eb 100644 --- a/src/hsm/hash_utils.c +++ b/src/hsm/hash_utils.c @@ -74,28 +74,41 @@ void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_ mbedtls_md_free(&ctx); } -int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len) { +int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len) { mbedtls_aes_context aes; mbedtls_aes_init(&aes); uint8_t tmp_iv[IV_SIZE]; + size_t iv_offset = 0; memset(tmp_iv, 0, IV_SIZE); if (iv) memcpy(tmp_iv, iv, IV_SIZE); int r = mbedtls_aes_setkey_enc(&aes, key, key_size); if (r != 0) return HSM_EXEC_ERROR; - return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, len, tmp_iv, data, data); + if (mode == HSM_AES_MODE_CBC) + return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, len, tmp_iv, data, data); + return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data); } -int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len) { +int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len) { mbedtls_aes_context aes; mbedtls_aes_init(&aes); uint8_t tmp_iv[IV_SIZE]; + size_t iv_offset = 0; memset(tmp_iv, 0, IV_SIZE); if (iv) memcpy(tmp_iv, iv, IV_SIZE); int r = mbedtls_aes_setkey_dec(&aes, key, key_size); if (r != 0) return HSM_EXEC_ERROR; - return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data); + if (mode == HSM_AES_MODE_CBC) + return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data); + return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data); +} + +int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { + return aes_encrypt(key, iv, 32, HSM_AES_MODE_CFB, data, len); +} +int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { + return aes_decrypt(key, iv, 32, HSM_AES_MODE_CFB, data, len); } \ No newline at end of file diff --git a/src/hsm/hash_utils.h b/src/hsm/hash_utils.h index 0f15eb8..013c86d 100644 --- a/src/hsm/hash_utils.h +++ b/src/hsm/hash_utils.h @@ -26,7 +26,9 @@ extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]); extern void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]); extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]); extern void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_t *output); -extern int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len); -extern int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, uint8_t *data, int len); +extern int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len); +extern int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len); +extern int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len); +extern int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len); #endif diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 85195f9..98484e2 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -31,6 +31,7 @@ #include "version.h" #include "cvcerts.h" #include "hash_utils.h" +#include "dkek.h" const uint8_t sc_hsm_aid[] = { 11, @@ -40,7 +41,6 @@ const uint8_t sc_hsm_aid[] = { uint8_t session_pin[32], session_sopin[32]; bool has_session_pin = false, has_session_sopin = false; static uint8_t dkeks = 0, current_dkeks = 0; -static uint8_t tmp_dkek[IV_SIZE+32]; static int sc_hsm_process_apdu(); @@ -74,51 +74,6 @@ int sc_hsm_unload() { return HSM_OK; } -//AES CFB encryption with a 256 bit key -static int encrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) -{ - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - uint8_t tmp_iv[IV_SIZE]; - size_t iv_offset = 0; - memcpy(tmp_iv, iv, IV_SIZE); - int r = mbedtls_aes_setkey_enc(&aes, key, 256); - if (r != 0) - return HSM_EXEC_ERROR; - return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data); -} - -//AES CFB decryption with a 256 bit key -static int decrypt(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) -{ - mbedtls_aes_context aes; - mbedtls_aes_init(&aes); - uint8_t tmp_iv[IV_SIZE]; - size_t iv_offset = 0; - memcpy(tmp_iv, iv, IV_SIZE); - int r = mbedtls_aes_setkey_dec(&aes, key, 256); - if (r != 0) - return HSM_EXEC_ERROR; - return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data); -} - -int load_dkek() { - if (has_session_pin == false) - return HSM_NO_LOGIN; - file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); - if (!tf) - return HSM_ERR_FILE_NOT_FOUND; - memcpy(tmp_dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32); - int ret = decrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); - if (ret != 0) - return HSM_EXEC_ERROR; - return HSM_OK; -} - -void release_dkek() { - memset(tmp_dkek, 0, sizeof(tmp_dkek)); -} - void select_file(file_t *pe) { if (!pe) { @@ -583,17 +538,11 @@ static int cmd_initialize() { } p += tag_len; } - p = random_bytes_get(32); - memset(tmp_dkek, 0, sizeof(tmp_dkek)); - memcpy(tmp_dkek, p, IV_SIZE); if (dkeks == 0) { - p = random_bytes_get(32); - memcpy(tmp_dkek+IV_SIZE, p, 32); - encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); - file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); - flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek)); + int r = save_dkek_key(random_bytes_get(32)); + if (r != HSM_OK) + return SW_EXEC_ERROR(); } - low_flash_available(); } else { //free memory bytes request int heap_left = heapLeft(); @@ -621,28 +570,19 @@ static int cmd_import_dkek() { return SW_SECURITY_STATUS_NOT_SATISFIED(); } if (apdu.cmd_apdu_data_len > 0) { - for (int i = 0; i < apdu.cmd_apdu_data_len; i++) - tmp_dkek[IV_SIZE+i] ^= apdu.cmd_apdu_data[i]; + if (apdu.cmd_apdu_data_len < 32) + return SW_WRONG_LENGTH(); + import_dkek_share(apdu.cmd_apdu_data); if (++current_dkeks == dkeks) { - encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); - flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek)); - memset(tmp_dkek, 0, sizeof(tmp_dkek)); - low_flash_available(); + if (save_dkek_key(NULL) != HSM_OK) + return SW_FILE_NOT_FOUND(); + } } res_APDU[0] = dkeks; res_APDU[1] = dkeks-current_dkeks; - //FNV hash - uint64_t hash = 0xcbf29ce484222325; - memcpy(tmp_dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32); - decrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); - for (int i = 0; i < 32; i++) { - hash ^= tmp_dkek[IV_SIZE+i]; - hash *= 0x00000100000001B3; - } - memset(tmp_dkek, 0, sizeof(tmp_dkek)); - memcpy(res_APDU+2,&hash,sizeof(hash)); - res_APDU_size = 2+sizeof(hash); + dkek_kcv(res_APDU+2); + res_APDU_size = 2+8; return SW_OK(); } @@ -683,11 +623,11 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) { mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size); key_size++; } - if ((r = load_dkek()) != HSM_OK) + r = dkek_encrypt(kdata, key_size); + if (r != HSM_OK) { + free(kdata); return r; - if ((r = encrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size)) != 0) - return r; - release_dkek(); + } file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); r = flash_write_data_to_file(fpk, kdata, key_size); free(kdata); @@ -1141,10 +1081,8 @@ static int cmd_change_pin() { //encrypt DKEK with new pin hash_multi(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, session_pin); has_session_pin = true; - encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); - file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); - flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek)); - release_dkek(); + if (store_dkek_key() != HSM_OK) + return SW_EXEC_ERROR(); uint8_t dhash[33]; dhash[0] = apdu.cmd_apdu_data_len-pin_len; double_hash_pin(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, dhash+1); @@ -1171,11 +1109,9 @@ static int cmd_key_gen() { //at this moment, we do not use the template, as only CBC is supported by the driver (encrypt, decrypt and CMAC) uint8_t aes_key[32]; //maximum AES key size memcpy(aes_key, random_bytes_get(key_size), key_size); - if ((r = load_dkek()) != HSM_OK) - return SW_EXEC_ERROR() ; - if ((r = encrypt(tmp_dkek+IV_SIZE, tmp_dkek, aes_key, key_size)) != 0) - return SW_EXEC_ERROR() ; - release_dkek(); + r = dkek_encrypt(aes_key, key_size); + if (r != HSM_OK) + return SW_EXEC_ERROR(); file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); if (!fpk) return SW_MEMORY_FAILURE(); @@ -1198,11 +1134,10 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { return SW_EXEC_ERROR(); uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(fkey->data+2), key_size); - if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) { + if (dkek_decrypt(kdata, key_size) != 0) { free(kdata); return SW_EXEC_ERROR(); } - release_dkek(); if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) { mbedtls_rsa_free(ctx); free(kdata); @@ -1239,11 +1174,10 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { return HSM_EXEC_ERROR; uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(fkey->data+2), key_size); - if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) { + if (dkek_decrypt(kdata, key_size) != 0) { free(kdata); return HSM_EXEC_ERROR; } - release_dkek(); mbedtls_ecp_group_id gid = kdata[0]; int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1); if (r != 0) { @@ -1454,11 +1388,10 @@ static int cmd_decrypt_asym() { return SW_EXEC_ERROR(); uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(ef->data+2), key_size); - if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) { + if (dkek_decrypt(kdata, key_size) != 0) { free(kdata); return SW_EXEC_ERROR(); } - release_dkek(); mbedtls_ecdh_init(&ctx); mbedtls_ecp_group_id gid = kdata[0]; int r = 0; @@ -1511,10 +1444,9 @@ static int cmd_cipher_sym() { return SW_EXEC_ERROR(); uint8_t kdata[32]; //maximum AES key size memcpy(kdata, file_read(ef->data+2), key_size); - if (decrypt(tmp_dkek+IV_SIZE, tmp_dkek, kdata, key_size) != 0) { + if (dkek_decrypt(kdata, key_size) != 0) { return SW_EXEC_ERROR(); } - release_dkek(); if (algo == ALGO_AES_CBC_ENCRYPT || algo == ALGO_AES_CBC_DECRYPT) { mbedtls_aes_context aes; mbedtls_aes_init(&aes); From 2e655d63410012ec68036df7735f0bd30fc46e54 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 18:25:47 +0200 Subject: [PATCH 10/21] Fixes with AES encryption Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 2 +- src/hsm/hash_utils.c | 5 +++-- src/hsm/sc_hsm.c | 8 -------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 08f3b98..3126e42 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -238,7 +238,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) if (kb_len < kb_len_pad) { kb[kb_len] = 0x80; } - int r = aes_encrypt(kenc, NULL, 32, HSM_AES_MODE_CBC, kb, kb_len_pad); + int r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad); if (r != HSM_OK) return r; diff --git a/src/hsm/hash_utils.c b/src/hsm/hash_utils.c index e7e81eb..f9ff93a 100644 --- a/src/hsm/hash_utils.c +++ b/src/hsm/hash_utils.c @@ -103,12 +103,13 @@ int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, u return HSM_EXEC_ERROR; if (mode == HSM_AES_MODE_CBC) return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data); + r = mbedtls_aes_setkey_enc(&aes, key, key_size); //CFB requires set_enc instead set_dec return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_DECRYPT, len, &iv_offset, tmp_iv, data, data); } int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { - return aes_encrypt(key, iv, 32, HSM_AES_MODE_CFB, data, len); + return aes_encrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len); } int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { - return aes_decrypt(key, iv, 32, HSM_AES_MODE_CFB, data, len); + return aes_decrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len); } \ No newline at end of file diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 98484e2..6ecbad3 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -1130,8 +1130,6 @@ static int cmd_key_gen() { int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { int key_size = file_read_uint16(fkey->data); - if (load_dkek() != HSM_OK) - return SW_EXEC_ERROR(); uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(fkey->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { @@ -1170,8 +1168,6 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { int key_size = file_read_uint16(fkey->data); - if (load_dkek() != HSM_OK) - return HSM_EXEC_ERROR; uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(fkey->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { @@ -1384,8 +1380,6 @@ static int cmd_decrypt_asym() { else if (P2(apdu) == ALGO_EC_DH) { mbedtls_ecdh_context ctx; int key_size = file_read_uint16(ef->data); - if (load_dkek() != HSM_OK) - return SW_EXEC_ERROR(); uint8_t *kdata = (uint8_t *)calloc(1,key_size); memcpy(kdata, file_read(ef->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { @@ -1440,8 +1434,6 @@ static int cmd_cipher_sym() { return SW_WRONG_LENGTH(); } int key_size = file_read_uint16(ef->data); - if (load_dkek() != HSM_OK) - return SW_EXEC_ERROR(); uint8_t kdata[32]; //maximum AES key size memcpy(kdata, file_read(ef->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { From 6876edea5a01bd2809748b402d4d640f5d6bebe3 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 19:06:00 +0200 Subject: [PATCH 11/21] Some fix in encode key Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 3126e42..7610f6a 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -175,8 +175,13 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) mbedtls_mpi_write_binary(&rsa->N, kb+8+kb_len, mbedtls_mpi_size(&rsa->N)); kb_len += mbedtls_mpi_size(&rsa->N); put_uint16_t(mbedtls_mpi_size(&rsa->E), kb+8+kb_len); kb_len += 2; mbedtls_mpi_write_binary(&rsa->E, kb+8+kb_len, mbedtls_mpi_size(&rsa->E)); kb_len += mbedtls_mpi_size(&rsa->E); + + algo = "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02"; + algo_len = 12; } else if (key_type & HSM_KEY_EC) { + if (*out_len < 8+1+10+6+4+48+16) + return HSM_WRONG_LENGTH; mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; kb_len = 0; put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P)*8, kb+8+kb_len); kb_len += 2; @@ -198,6 +203,9 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) kb[8+kb_len++] = 0x4; mbedtls_mpi_write_binary(&ecdsa->Q.X, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.X)); kb_len += mbedtls_mpi_size(&ecdsa->Q.X); mbedtls_mpi_write_binary(&ecdsa->Q.Y, kb+8+kb_len, mbedtls_mpi_size(&ecdsa->Q.Y)); kb_len += mbedtls_mpi_size(&ecdsa->Q.Y); + + algo = "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03"; + algo_len = 12; } memset(out, 0, *out_len); *out_len = 0; @@ -205,11 +213,11 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) memcpy(out+*out_len, kcv, 8); *out_len += 8; - if (key_type == HSM_KEY_AES) + if (key_type & HSM_KEY_AES) out[*out_len] = 15; - else if (key_type == HSM_KEY_RSA) + else if (key_type & HSM_KEY_RSA) out[*out_len] = 5; - else if (key_type == HSM_KEY_EC) + else if (key_type & HSM_KEY_EC) out[*out_len] = 12; *out_len += 1; From e7d8695394ad1b12a2ea6a809f70ed1af5bf72d6 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 19:16:15 +0200 Subject: [PATCH 12/21] Added length checks. Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 7610f6a..3593d54 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -122,7 +122,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES)) return HSM_WRONG_DATA; - uint8_t kb[2*4096/8+3+8+5]; //worst case: RSA-4096 (ECC is 596 max) (plus, 5 bytes padding) + 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; uint8_t *algo = NULL; @@ -152,7 +152,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) if (kb_len != 16 && kb_len != 24 && kb_len != 32) return HSM_WRONG_DATA; - if (*out_len < 8+1+10+6+4+48+16) + if (*out_len < 8+1+10+6+4+(2+32+14)+16) return HSM_WRONG_LENGTH; memcpy(kb+10, key_ctx, kb_len); @@ -165,6 +165,8 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) allowed_len = 6; } else if (key_type & HSM_KEY_RSA) { + if (*out_len < 8+1+12+6+(8+2*4+2*4096/8+3+13)+16) //13 bytes pading + return HSM_WRONG_LENGTH; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; kb_len = 0; put_uint16_t(mbedtls_rsa_get_len(rsa)*8, kb+8+kb_len); kb_len += 2; @@ -180,7 +182,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) algo_len = 12; } else if (key_type & HSM_KEY_EC) { - if (*out_len < 8+1+10+6+4+48+16) + if (*out_len < 8+1+12+6+(8+2*8+9*66+2+4)+16) //4 bytes pading return HSM_WRONG_LENGTH; mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; kb_len = 0; From 0141e0ab4e1e14d8f434ea2b3f7c6fbfd8d9d503 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 20:17:42 +0200 Subject: [PATCH 13/21] Adding ec curve find from prime. Signed-off-by: Pol Henarejos --- src/hsm/hash_utils.c | 27 +++++++++++++++++++++++++++ src/hsm/hash_utils.h | 2 ++ src/hsm/sc_hsm.c | 38 ++++---------------------------------- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/hsm/hash_utils.c b/src/hsm/hash_utils.c index f9ff93a..9a665df 100644 --- a/src/hsm/hash_utils.c +++ b/src/hsm/hash_utils.c @@ -21,6 +21,7 @@ #include "mbedtls/aes.h" #include "hash_utils.h" #include "sc_hsm.h" +#include "libopensc/card-sc-hsm.h" void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]) { uint8_t o1[32]; @@ -112,4 +113,30 @@ int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, in } int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len) { return aes_decrypt(key, iv, 256, HSM_AES_MODE_CFB, data, len); +} + +struct ec_curve_mbed_id { + struct sc_lv_data curve; + mbedtls_ecp_group_id id; +}; +struct ec_curve_mbed_id ec_curves_mbed[] = { + { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, MBEDTLS_ECP_DP_SECP192R1 }, + { { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, MBEDTLS_ECP_DP_SECP256R1 }, + { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, MBEDTLS_ECP_DP_SECP384R1 }, + { { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 66}, MBEDTLS_ECP_DP_SECP521R1 }, + { { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, MBEDTLS_ECP_DP_BP256R1 }, + { { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, MBEDTLS_ECP_DP_BP384R1 }, + { { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, MBEDTLS_ECP_DP_BP512R1 }, + { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, MBEDTLS_ECP_DP_SECP192K1 }, + { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, MBEDTLS_ECP_DP_SECP256K1 }, + { { NULL, 0 }, MBEDTLS_ECP_DP_NONE } +}; + +mbedtls_ecp_group_id ec_get_curve_from_prime(const uint8_t *prime, size_t prime_len) { + for (struct ec_curve_mbed_id *ec = ec_curves_mbed; ec->id != MBEDTLS_ECP_DP_NONE; ec++) { + if (prime_len == ec->curve.len && memcmp(prime, ec->curve.value, prime_len) == 0) { + return ec->id; + } + } + return MBEDTLS_ECP_DP_NONE; } \ No newline at end of file diff --git a/src/hsm/hash_utils.h b/src/hsm/hash_utils.h index 013c86d..64b9454 100644 --- a/src/hsm/hash_utils.h +++ b/src/hsm/hash_utils.h @@ -20,6 +20,7 @@ #include "stdlib.h" #include "pico/stdlib.h" +#include "mbedtls/ecp.h" #include "mbedtls/md.h" extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]); @@ -30,5 +31,6 @@ extern int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int extern int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, uint8_t *data, int len); extern int aes_encrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len); extern int aes_decrypt_cfb_256(const uint8_t *key, const uint8_t *iv, uint8_t *data, int len); +extern mbedtls_ecp_group_id ec_get_curve_from_prime(const uint8_t *prime, size_t prime_len); #endif diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 6ecbad3..dca3a1c 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -232,7 +232,7 @@ int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_ } int parse_token_info(const file_t *f, int mode) { - char *label = "Pico-HSM"; + char *label = "SmartCard-HSM"; char *manu = "Pol Henarejos"; sc_pkcs15_tokeninfo_t *ti = (sc_pkcs15_tokeninfo_t *)calloc(1, sizeof(sc_pkcs15_tokeninfo_t)); ti->version = HSM_VERSION_MAJOR; @@ -586,23 +586,6 @@ static int cmd_import_dkek() { return SW_OK(); } -struct ec_curve_mbed_id { - struct sc_lv_data curve; - mbedtls_ecp_group_id id; -}; -struct ec_curve_mbed_id ec_curves_mbed[] = { - { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, MBEDTLS_ECP_DP_SECP192R1 }, - { { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, MBEDTLS_ECP_DP_SECP256R1 }, - { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, MBEDTLS_ECP_DP_SECP384R1 }, - { { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 66}, MBEDTLS_ECP_DP_SECP521R1 }, - { { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, MBEDTLS_ECP_DP_BP256R1 }, - { { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, MBEDTLS_ECP_DP_BP384R1 }, - { { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, MBEDTLS_ECP_DP_BP512R1 }, - { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, MBEDTLS_ECP_DP_SECP192K1 }, - { { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, MBEDTLS_ECP_DP_SECP256K1 }, - { { NULL, 0 }, MBEDTLS_ECP_DP_NONE } -}; - //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 r, key_size; @@ -793,13 +776,7 @@ static int cmd_keypair_gen() { else if (memcmp(oid, "\x4\x0\x7F\x0\x7\x2\x2\x2\x2\x3",MIN(oid_len,10)) == 0) { //ECC size_t prime_len; const uint8_t *prime = sc_asn1_find_tag(ctx, p, tout, 0x81, &prime_len); - mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_NONE; - for (struct ec_curve_mbed_id *ec = ec_curves_mbed; ec->id != MBEDTLS_ECP_DP_NONE; ec++) { - if (prime_len == ec->curve.len && memcmp(prime, ec->curve.value, prime_len) == 0) { - ec_id = ec->id; - break; - } - } + mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(prime, prime_len); printf("KEYPAIR ECC %d\r\n",ec_id); if (ec_id == MBEDTLS_ECP_DP_NONE) { sc_pkcs15emu_sc_hsm_free_cvc(&cvc); @@ -1130,23 +1107,19 @@ static int cmd_key_gen() { int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { int key_size = file_read_uint16(fkey->data); - uint8_t *kdata = (uint8_t *)calloc(1,key_size); + uint8_t kdata[4096/8]; memcpy(kdata, file_read(fkey->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { - free(kdata); return SW_EXEC_ERROR(); } if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) { mbedtls_rsa_free(ctx); - free(kdata); return SW_DATA_INVALID(); } if (mbedtls_mpi_read_binary(&ctx->Q, kdata+key_size/2, key_size/2) != 0) { mbedtls_rsa_free(ctx); - free(kdata); return SW_DATA_INVALID(); } - free(kdata); if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) { mbedtls_rsa_free(ctx); return SW_EXEC_ERROR(); @@ -1168,20 +1141,17 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { int key_size = file_read_uint16(fkey->data); - uint8_t *kdata = (uint8_t *)calloc(1,key_size); + uint8_t kdata[67]; //Worst case, 521 bit + 1byte memcpy(kdata, file_read(fkey->data+2), key_size); if (dkek_decrypt(kdata, key_size) != 0) { - free(kdata); return HSM_EXEC_ERROR; } mbedtls_ecp_group_id gid = kdata[0]; int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1); if (r != 0) { - free(kdata); mbedtls_ecdsa_free(ctx); return HSM_EXEC_ERROR; } - free(kdata); return HSM_OK; } From 1c272842a79c5efb77995f3811f77147d4eefdbb Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 29 Mar 2022 20:18:08 +0200 Subject: [PATCH 14/21] Adding dkek_decode_key for unwrapping. Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++- src/hsm/sc_hsm.h | 3 + 2 files changed, 187 insertions(+), 3 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 3593d54..a70d3aa 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -130,7 +130,6 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) uint8_t *allowed = NULL; uint8_t allowed_len = 0; uint8_t kenc[32]; - memset(kenc, 0, sizeof(kenc)); dkek_kenc(kenc); @@ -155,8 +154,8 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) if (*out_len < 8+1+10+6+4+(2+32+14)+16) return HSM_WRONG_LENGTH; - memcpy(kb+10, key_ctx, kb_len); put_uint16_t(kb_len, kb+8); + memcpy(kb+10, key_ctx, kb_len); kb_len += 2; algo = "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8) @@ -261,5 +260,187 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) if (r != 0) return r; return HSM_OK; -} +} +int dkek_type_key(const uint8_t *in) { + if (in[8] == 5) + return HSM_KEY_RSA; + else if (in[8] == 12) + return HSM_KEY_EC; + else if (in[8] == 15) + return HSM_KEY_AES; + return 0x0; +} + +int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { + uint8_t kcv[8]; + memset(kcv, 0, sizeof(kcv)); + dkek_kcv(kcv); + + uint8_t kmac[32]; + memset(kmac, 0, sizeof(kmac)); + dkek_kmac(kmac); + + uint8_t kenc[32]; + memset(kenc, 0, sizeof(kenc)); + dkek_kenc(kenc); + + if (memcmp(kcv, in, 8) != 0) + return HSM_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); + if (r != 0) + return HSM_WRONG_SIGNATURE; + if (memcmp(signature, in+in_len-16, 16) != 0) + return HSM_WRONG_SIGNATURE; + + int key_type = in[8]; + + if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) + return HSM_WRONG_DATA; + + if ((key_type == 5 || key_type == 6) && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) + return HSM_WRONG_DATA; + + if (key_type == 12 && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) + return HSM_WRONG_DATA; + + if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) + return HSM_WRONG_DATA; + + size_t ofs = 9; + + //OID + size_t len = get_uint16_t(in, ofs); + ofs += len+2; + + //Allowed algorithms + len = get_uint16_t(in, ofs); + ofs += len+2; + + //Access conditions + len = get_uint16_t(in, ofs); + ofs += len+2; + + //Key OID + len = get_uint16_t(in, ofs); + ofs += len+2; + + if ((in_len-16-ofs) % 16 != 0) + return HSM_WRONG_PADDING; + uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding) + memset(kb, 0, sizeof(kb)); + r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs); + if (r != HSM_OK) + return r; + + int key_size = get_uint16_t(kb, 8); + ofs = 10; + if (key_type == 5 || key_type == 6) { + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; + mbedtls_rsa_init(rsa); + if (key_type == 5) { + len = get_uint16_t(kb, ofs); ofs += 2; + r = mbedtls_mpi_read_binary(&rsa->D, kb+ofs, len); ofs += len; + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_WRONG_DATA; + } + } + else if (key_type == 6) { + //DP-1 + len = get_uint16_t(kb, ofs); ofs += len+2; + + //DQ-1 + len = get_uint16_t(kb, ofs); ofs += len+2; + + r = mbedtls_mpi_read_binary(&rsa->P, kb+ofs, len); ofs += len; + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_WRONG_DATA; + } + + //PQ + len = get_uint16_t(kb, ofs); ofs += len+2; + + r = mbedtls_mpi_read_binary(&rsa->Q, kb+ofs, len); ofs += len; + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_WRONG_DATA; + } + } + len = get_uint16_t(kb, ofs); ofs += 2; + r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len; + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_WRONG_DATA; + } + + len = get_uint16_t(kb, ofs); ofs += 2; + r = mbedtls_mpi_read_binary(&rsa->E, kb+ofs, len); ofs += len; + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_WRONG_DATA; + } + + if (key_type == 5) { + r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E); + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_EXEC_ERROR; + } + } + else if (key_type == 6) { + r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E); + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_EXEC_ERROR; + } + } + + if (mbedtls_rsa_complete(rsa) != 0) { + mbedtls_rsa_free(rsa); + return HSM_EXEC_ERROR; + } + if (mbedtls_rsa_check_privkey(rsa) != 0) { + mbedtls_rsa_free(rsa); + return HSM_EXEC_ERROR; + } + } + else if (key_type == 12) { + mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; + mbedtls_ecdsa_init(ecdsa); + + //A + len = get_uint16_t(kb, ofs); ofs += len+2; + + //B + len = get_uint16_t(kb, ofs); ofs += len+2; + + //P + len = get_uint16_t(kb, ofs); ofs += 2; + mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb+ofs, len); + if (ec_id == MBEDTLS_ECP_DP_NONE) { + mbedtls_ecdsa_free(ecdsa); + return HSM_WRONG_DATA; + } + + //N + len = get_uint16_t(kb, ofs); ofs += len+2; + + //G + len = get_uint16_t(kb, ofs); ofs += len+2; + + //d + r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len); + if (r != 0) { + mbedtls_ecdsa_free(ecdsa); + return HSM_EXEC_ERROR; + } + } + else if (key_type == 15) { + memcpy(key_ctx, kb+ofs, key_size); + } + return HSM_OK; +} \ No newline at end of file diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index 4158ce1..7953eda 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -62,6 +62,9 @@ extern const uint8_t sc_hsm_aid[]; #define HSM_EXEC_ERROR -1006 #define HSM_WRONG_LENGTH -1007 #define HSM_WRONG_DATA -1008 +#define HSM_WRONG_DKEK -1009 +#define HSM_WRONG_SIGNATURE -1010 +#define HSM_WRONG_PADDING -1011 #define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */ #define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */ From d018e3b9b91bfea94e187eeda7c1c5b5cc434b18 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 30 Mar 2022 00:59:37 +0200 Subject: [PATCH 15/21] Adding RSA and EC wrap/unwrap, compatible with SC HSM wrap format. Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 6 ++-- src/hsm/dkek.h | 5 +++ src/hsm/hash_utils.h | 10 ++++++ src/hsm/sc_hsm.c | 79 +++++++++++++++++++++++++++++++++++--------- src/hsm/sc_hsm.h | 12 ++----- 5 files changed, 86 insertions(+), 26 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index a70d3aa..f7bc63a 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -296,7 +296,6 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { return HSM_WRONG_SIGNATURE; int key_type = in[8]; - if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) return HSM_WRONG_DATA; @@ -331,7 +330,8 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { return HSM_WRONG_PADDING; uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding) memset(kb, 0, sizeof(kb)); - r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs); + memcpy(kb, in+ofs, in_len-16-ofs); + r = aes_decrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs); if (r != HSM_OK) return r; @@ -425,6 +425,7 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { mbedtls_ecdsa_free(ecdsa); return HSM_WRONG_DATA; } + ofs += len; //N len = get_uint16_t(kb, ofs); ofs += len+2; @@ -433,6 +434,7 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { len = get_uint16_t(kb, ofs); ofs += len+2; //d + len = get_uint16_t(kb, ofs); ofs += 2; r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len); if (r != 0) { mbedtls_ecdsa_free(ecdsa); diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h index 12f9248..2219c6d 100644 --- a/src/hsm/dkek.h +++ b/src/hsm/dkek.h @@ -26,5 +26,10 @@ extern void import_dkek_share(const uint8_t *share); extern void dkek_kcv(uint8_t *kcv); extern int dkek_encrypt(uint8_t *data, size_t len); extern int dkek_decrypt(uint8_t *data, size_t len); +extern int dkek_encode_key(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(void *key_ctx, const uint8_t *in, size_t in_len); + +#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16) #endif diff --git a/src/hsm/hash_utils.h b/src/hsm/hash_utils.h index 64b9454..c411812 100644 --- a/src/hsm/hash_utils.h +++ b/src/hsm/hash_utils.h @@ -23,6 +23,16 @@ #include "mbedtls/ecp.h" #include "mbedtls/md.h" +#define HSM_KEY_RSA 0x1 +#define HSM_KEY_EC 0x10 +#define HSM_KEY_AES 0x100 +#define HSM_KEY_AES_128 0x300 +#define HSM_KEY_AES_192 0x500 +#define HSM_KEY_AES_256 0x900 + +#define HSM_AES_MODE_CBC 1 +#define HSM_AES_MODE_CFB 2 + extern void double_hash_pin(const uint8_t *pin, size_t len, uint8_t output[32]); extern void hash_multi(const uint8_t *input, size_t len, uint8_t output[32]); extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]); diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index dca3a1c..af8df2b 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -589,31 +589,28 @@ static int cmd_import_dkek() { //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 r, key_size; - uint8_t *asn1bin, *kdata; + uint8_t *asn1bin; size_t asn1len = 0; + uint8_t kdata[4096/8]; //worst case if (type == SC_PKCS15_TYPE_PRKEY_RSA) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; key_size = mbedtls_mpi_size(&rsa->P)+mbedtls_mpi_size(&rsa->Q); - kdata = (uint8_t *)calloc(1, key_size); mbedtls_mpi_write_binary(&rsa->P, kdata, key_size/2); mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2); } else { mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; key_size = mbedtls_mpi_size(&ecdsa->d); - kdata = (uint8_t *)calloc(1, key_size+1); kdata[0] = ecdsa->grp.id & 0xff; mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size); key_size++; } r = dkek_encrypt(kdata, key_size); if (r != HSM_OK) { - free(kdata); return r; } file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); r = flash_write_data_to_file(fpk, kdata, key_size); - free(kdata); if (r != HSM_OK) return r; //add_file_to_chain(fpk, &ef_kf); @@ -1295,7 +1292,7 @@ static int cmd_signature() { } static int cmd_key_wrap() { - int key_id = P1(apdu); + int key_id = P1(apdu), r = 0, key_type = 0x0; if (P2(apdu) != 0x92) return SW_WRONG_P1P2(); if (!isUserAuthenticated) @@ -1303,23 +1300,75 @@ static int cmd_key_wrap() { file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id); if (!ef) return SW_FILE_NOT_FOUND(); - int key_len = file_read_uint16(ef->data); - memcpy(res_APDU, file_read(ef->data+2), key_len); - res_APDU_size = key_len; + file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id); + if (!prkd) + return SW_FILE_NOT_FOUND(); + const uint8_t *dprkd = file_read(prkd->data+2); + size_t wrap_len = MAX_DKEK_ENCODE_KEY_BUFFER; + if (*dprkd == P15_KEYTYPE_RSA) { + mbedtls_rsa_context ctx; + mbedtls_rsa_init(&ctx); + r = load_private_key_rsa(&ctx, ef); + if (r != HSM_OK) { + mbedtls_rsa_free(&ctx); + return SW_EXEC_ERROR(); + } + r = dkek_encode_key(&ctx, HSM_KEY_RSA, res_APDU, &wrap_len); + mbedtls_rsa_free(&ctx); + } + else if (*dprkd == P15_KEYTYPE_ECC) { + mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_init(&ctx); + r = load_private_key_ecdsa(&ctx, ef); + if (r != HSM_OK) { + mbedtls_ecdsa_free(&ctx); + return SW_EXEC_ERROR(); + } + r = dkek_encode_key(&ctx, HSM_KEY_EC, res_APDU, &wrap_len); + mbedtls_ecdsa_free(&ctx); + } + if (r != HSM_OK) + return SW_EXEC_ERROR(); + res_APDU_size = wrap_len; return SW_OK(); } static int cmd_key_unwrap() { - int key_id = P1(apdu); + int key_id = P1(apdu), r = 0; if (P2(apdu) != 0x93) return SW_WRONG_P1P2(); if (!isUserAuthenticated) return SW_SECURITY_STATUS_NOT_SATISFIED(); - file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id); - if (!ef) - ef = file_new((KEY_PREFIX << 8) | key_id); - flash_write_data_to_file(ef, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); - low_flash_available(); + int key_type = dkek_type_key(apdu.cmd_apdu_data); + 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(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); + printf("r %d\r\n",r); + if (r != HSM_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); + free(card_ctx); + mbedtls_rsa_free(&ctx); + } + else if (key_type == HSM_KEY_EC) { + mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_init(&ctx); + r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); + if (r != HSM_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); + free(card_ctx); + mbedtls_ecdsa_free(&ctx); + } return SW_OK(); } diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index 7953eda..c2a4f9f 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -97,15 +97,9 @@ extern const uint8_t sc_hsm_aid[]; #define HSM_OPT_COMBINED_AUTH 0x10 #define HSM_OPT_RRC_RESET_ONLY 0x20 -#define HSM_KEY_RSA 0x1 -#define HSM_KEY_EC 0x10 -#define HSM_KEY_AES 0x100 -#define HSM_KEY_AES_128 0x300 -#define HSM_KEY_AES_192 0x500 -#define HSM_KEY_AES_256 0x900 - -#define HSM_AES_MODE_CBC 1 -#define HSM_AES_MODE_CFB 2 +#define P15_KEYTYPE_RSA 0x30 +#define P15_KEYTYPE_ECC 0xA0 +#define P15_KEYTYPE_AES 0xA8 extern int pin_reset_retries(const file_t *pin, bool); extern int pin_wrong_retry(const file_t *pin); From 4651a0e224546da6472d50c05d9d2d0bd94b3d73 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 30 Mar 2022 01:33:54 +0200 Subject: [PATCH 16/21] Adding AES wrapping/unwrapping Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 4 +- src/hsm/dkek.h | 2 +- src/hsm/sc_hsm.c | 128 +++++++++++++++++++++++++++++++---------------- 3 files changed, 89 insertions(+), 45 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index f7bc63a..4247cc9 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -272,7 +272,7 @@ int dkek_type_key(const uint8_t *in) { return 0x0; } -int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { +int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) { uint8_t kcv[8]; memset(kcv, 0, sizeof(kcv)); dkek_kcv(kcv); @@ -336,6 +336,8 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) { return r; int key_size = get_uint16_t(kb, 8); + if (key_size_out) + *key_size_out = key_size; ofs = 10; if (key_type == 5 || key_type == 6) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h index 2219c6d..8c17a7c 100644 --- a/src/hsm/dkek.h +++ b/src/hsm/dkek.h @@ -28,7 +28,7 @@ extern int dkek_encrypt(uint8_t *data, size_t len); extern int dkek_decrypt(uint8_t *data, size_t len); extern int dkek_encode_key(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(void *key_ctx, const uint8_t *in, size_t in_len); +extern int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out); #define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index af8df2b..77f9f14 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -232,7 +232,7 @@ int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_ } int parse_token_info(const file_t *f, int mode) { - char *label = "SmartCard-HSM"; + char *label = "Pico-HSM"; char *manu = "Pol Henarejos"; sc_pkcs15_tokeninfo_t *ti = (sc_pkcs15_tokeninfo_t *)calloc(1, sizeof(sc_pkcs15_tokeninfo_t)); ti->version = HSM_VERSION_MAJOR; @@ -589,7 +589,7 @@ static int cmd_import_dkek() { //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 r, key_size; - uint8_t *asn1bin; + uint8_t *asn1bin = NULL; size_t asn1len = 0; uint8_t kdata[4096/8]; //worst case if (type == SC_PKCS15_TYPE_PRKEY_RSA) { @@ -598,50 +598,64 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) { mbedtls_mpi_write_binary(&rsa->P, kdata, key_size/2); mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2); } - else { + else if (type == SC_PKCS15_TYPE_PRKEY_EC) { mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; key_size = mbedtls_mpi_size(&ecdsa->d); kdata[0] = ecdsa->grp.id & 0xff; mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size); key_size++; } + else if (type & HSM_KEY_AES) { + if (type == HSM_KEY_AES_128) + key_size = 16; + else if (type == HSM_KEY_AES_192) + key_size = 24; + else if (type == HSM_KEY_AES_256) + key_size = 32; + memcpy(kdata, key_ctx, key_size); + } r = dkek_encrypt(kdata, key_size); if (r != HSM_OK) { return r; } file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); + if (!fpk) + return SW_MEMORY_FAILURE(); r = flash_write_data_to_file(fpk, kdata, key_size); if (r != HSM_OK) return r; //add_file_to_chain(fpk, &ef_kf); + if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == SC_PKCS15_TYPE_PRKEY_EC) { + struct sc_pkcs15_object *p15o = (struct sc_pkcs15_object *)calloc(1,sizeof (struct sc_pkcs15_object)); - struct sc_pkcs15_object *p15o = (struct sc_pkcs15_object *)calloc(1,sizeof (struct sc_pkcs15_object)); + sc_pkcs15_prkey_info_t *prkd = (sc_pkcs15_prkey_info_t *)calloc(1, sizeof (sc_pkcs15_prkey_info_t)); + memset(prkd, 0, sizeof(sc_pkcs15_prkey_info_t)); + prkd->id.len = 1; + prkd->id.value[0] = key_id; + prkd->usage = SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_UNWRAP; + prkd->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_LOCAL; + prkd->native = 1; + prkd->key_reference = key_id; + prkd->path.value[0] = PRKD_PREFIX; + prkd->path.value[1] = key_id; + prkd->path.len = 2; + if (type == SC_PKCS15_TYPE_PRKEY_RSA) + prkd->modulus_length = key_size; + else + prkd->field_length = key_size-1; //contains 1 byte for the grp id + + p15o->data = prkd; + p15o->type = SC_PKCS15_TYPE_PRKEY | (type & 0xff); + + r = sc_pkcs15_encode_prkdf_entry(ctx, p15o, &asn1bin, &asn1len); + free(prkd); + //sc_asn1_print_tags(asn1bin, asn1len); + } - sc_pkcs15_prkey_info_t *prkd = (sc_pkcs15_prkey_info_t *)calloc(1, sizeof (sc_pkcs15_prkey_info_t)); - memset(prkd, 0, sizeof(sc_pkcs15_prkey_info_t)); - prkd->id.len = 1; - prkd->id.value[0] = key_id; - prkd->usage = SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_UNWRAP; - prkd->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_LOCAL; - prkd->native = 1; - prkd->key_reference = key_id; - prkd->path.value[0] = PRKD_PREFIX; - prkd->path.value[1] = key_id; - prkd->path.len = 2; - if (type == SC_PKCS15_TYPE_PRKEY_RSA) - prkd->modulus_length = key_size; - else - prkd->field_length = key_size-1; //contains 1 byte for the grp id - - p15o->data = prkd; - p15o->type = SC_PKCS15_TYPE_PRKEY | (type & 0xff); - - r = sc_pkcs15_encode_prkdf_entry(ctx, p15o, &asn1bin, &asn1len); - free(prkd); - //sc_asn1_print_tags(asn1bin, asn1len); fpk = file_new((PRKD_PREFIX << 8) | key_id); r = flash_write_data_to_file(fpk, asn1bin, asn1len); - free(asn1bin); + if (asn1bin) + free(asn1bin); if (r != HSM_OK) return r; //add_file_to_chain(fpk, &ef_prkdf); @@ -1083,19 +1097,16 @@ static int cmd_key_gen() { //at this moment, we do not use the template, as only CBC is supported by the driver (encrypt, decrypt and CMAC) uint8_t aes_key[32]; //maximum AES key size memcpy(aes_key, random_bytes_get(key_size), key_size); - r = dkek_encrypt(aes_key, key_size); - if (r != HSM_OK) - return SW_EXEC_ERROR(); - file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); - if (!fpk) - return SW_MEMORY_FAILURE(); - r = flash_write_data_to_file(fpk, aes_key, key_size); - if (r != HSM_OK) - return SW_MEMORY_FAILURE(); - fpk = file_new((PRKD_PREFIX << 8) | key_id); - if (!fpk) - return SW_MEMORY_FAILURE(); - r = flash_write_data_to_file(fpk, NULL, 0); + int aes_type = 0x0; + if (key_size == 16) + aes_type = HSM_KEY_AES_128; + else if (key_size == 24) + aes_type = HSM_KEY_AES_192; + 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); + free(card_ctx); if (r != HSM_OK) return SW_MEMORY_FAILURE(); low_flash_available(); @@ -1327,6 +1338,21 @@ static int cmd_key_wrap() { r = dkek_encode_key(&ctx, HSM_KEY_EC, res_APDU, &wrap_len); mbedtls_ecdsa_free(&ctx); } + else if (*dprkd == P15_KEYTYPE_AES) { + uint8_t kdata[32]; //maximum AES key size + int key_size = file_read_uint16(ef->data), aes_type = HSM_KEY_AES; + memcpy(kdata, file_read(ef->data+2), key_size); + if (dkek_decrypt(kdata, key_size) != 0) { + return SW_EXEC_ERROR(); + } + if (key_size == 32) + aes_type = HSM_KEY_AES_256; + else if (key_size == 24) + aes_type = HSM_KEY_AES_192; + else if (key_size == 16) + aes_type = HSM_KEY_AES_128; + r = dkek_encode_key(kdata, aes_type, res_APDU, &wrap_len); + } if (r != HSM_OK) return SW_EXEC_ERROR(); res_APDU_size = wrap_len; @@ -1345,8 +1371,7 @@ static int cmd_key_unwrap() { if (key_type == HSM_KEY_RSA) { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); - r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); - printf("r %d\r\n",r); + r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL); if (r != HSM_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); @@ -1359,7 +1384,7 @@ static int cmd_key_unwrap() { else if (key_type == HSM_KEY_EC) { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); - r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); + r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL); if (r != HSM_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); @@ -1369,6 +1394,23 @@ static int cmd_key_unwrap() { free(card_ctx); mbedtls_ecdsa_free(&ctx); } + else if (key_type == HSM_KEY_AES) { + uint8_t aes_key[32]; + int key_size = 0, aes_type; + r = dkek_decode_key(aes_key, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &key_size); + if (r != HSM_OK) { + return SW_EXEC_ERROR(); + } + if (key_size == 32) + aes_type = HSM_KEY_AES_256; + else if (key_size == 24) + aes_type = HSM_KEY_AES_192; + else if (key_size == 16) + aes_type = HSM_KEY_AES_128; + sc_context_t *card_ctx = create_context(); + r = store_keys(aes_key, aes_type, key_id, card_ctx); + free(card_ctx); + } return SW_OK(); } From 7aca7b323ae1e0ec1a5ba30380a410090b31594f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 30 Mar 2022 23:21:23 +0200 Subject: [PATCH 17/21] Fix loading kcv, kenc and kmac. Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 32 ++++++++++++++++++++++++-------- src/hsm/dkek.h | 3 ++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 4247cc9..f54693a 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -80,24 +80,40 @@ void import_dkek_share(const uint8_t *share) { tmp_dkek[i] ^= share[i]; } -void dkek_kcv(uint8_t *kcv) { //kcv 8 bytes +int dkek_kcv(uint8_t *kcv) { //kcv 8 bytes uint8_t hsh[32]; - hash256(dkek, sizeof(dkek), hsh); + int r = load_dkek(); + if (r != HSM_OK) + return r; + hash256(dkek+IV_SIZE, 32, hsh); + release_dkek(); memcpy(kcv, hsh, 8); } -void dkek_kenc(uint8_t *kenc) { //kenc 32 bytes +int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes uint8_t buf[32+4]; - memcpy(buf, dkek, sizeof(dkek)); + int r = load_dkek(); + if (r != HSM_OK) + return r; + memcpy(buf, dkek+IV_SIZE, 32); + release_dkek(); memcpy(buf, "\x0\x0\x0\x1", 4); - hash256(dkek, sizeof(dkek), kenc); + hash256(buf, sizeof(buf), kenc); + memset(buf, 0, sizeof(buf)); + return HSM_OK; } -void dkek_kmac(uint8_t *kmac) { //kmac 32 bytes +int dkek_kmac(uint8_t *kmac) { //kmac 32 bytes uint8_t buf[32+4]; - memcpy(buf, dkek, sizeof(dkek)); + int r = load_dkek(); + if (r != HSM_OK) + return r; + memcpy(buf, dkek+IV_SIZE, 32); + release_dkek(); memcpy(buf, "\x0\x0\x0\x2", 4); - hash256(dkek, sizeof(dkek), kmac); + hash256(buf, sizeof(buf), kmac); + memset(buf, 0, sizeof(buf)); + return HSM_OK; } int dkek_encrypt(uint8_t *data, size_t len) { diff --git a/src/hsm/dkek.h b/src/hsm/dkek.h index 8c17a7c..0fe7501 100644 --- a/src/hsm/dkek.h +++ b/src/hsm/dkek.h @@ -21,9 +21,10 @@ extern int load_dkek(); extern int save_dkek_key(const uint8_t *key); extern int store_dkek_key(); +extern void init_dkek(); extern void release_dkek(); extern void import_dkek_share(const uint8_t *share); -extern void dkek_kcv(uint8_t *kcv); +extern int dkek_kcv(uint8_t *kcv); extern int dkek_encrypt(uint8_t *data, size_t len); extern int dkek_decrypt(uint8_t *data, size_t len); extern int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len); From 7aee18110ed9093d3be5a1184b72ecb5a7177349 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 30 Mar 2022 23:59:06 +0200 Subject: [PATCH 18/21] Fix kmac and kenc computation. Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index f54693a..a64d112 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -97,7 +97,7 @@ int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes return r; memcpy(buf, dkek+IV_SIZE, 32); release_dkek(); - memcpy(buf, "\x0\x0\x0\x1", 4); + memcpy(buf+32, "\x0\x0\x0\x1", 4); hash256(buf, sizeof(buf), kenc); memset(buf, 0, sizeof(buf)); return HSM_OK; @@ -110,7 +110,7 @@ int dkek_kmac(uint8_t *kmac) { //kmac 32 bytes return r; memcpy(buf, dkek+IV_SIZE, 32); release_dkek(); - memcpy(buf, "\x0\x0\x0\x2", 4); + memcpy(buf+32, "\x0\x0\x0\x2", 4); hash256(buf, sizeof(buf), kmac); memset(buf, 0, sizeof(buf)); return HSM_OK; From 7410498df1d4c46e490d8623453cb27502047e12 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 00:24:50 +0200 Subject: [PATCH 19/21] Fix with RSA CRT import mode (keytype 6). In RSA CRT import, the N parameter shall not be imported. Otherwise, mbedtls will fail (it is deduced from N=PQ). Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index a64d112..0cd5f06 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -279,7 +279,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) } int dkek_type_key(const uint8_t *in) { - if (in[8] == 5) + if (in[8] == 5 || in[8] == 6) return HSM_KEY_RSA; else if (in[8] == 12) return HSM_KEY_EC; @@ -365,6 +365,13 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si mbedtls_rsa_free(rsa); return HSM_WRONG_DATA; } + + len = get_uint16_t(kb, ofs); ofs += 2; + r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len; + if (r != 0) { + mbedtls_rsa_free(rsa); + return HSM_WRONG_DATA; + } } else if (key_type == 6) { //DP-1 @@ -373,6 +380,7 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si //DQ-1 len = get_uint16_t(kb, ofs); ofs += len+2; + len = get_uint16_t(kb, ofs); ofs += 2; r = mbedtls_mpi_read_binary(&rsa->P, kb+ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); @@ -382,17 +390,14 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si //PQ len = get_uint16_t(kb, ofs); ofs += len+2; + len = get_uint16_t(kb, ofs); ofs += 2; r = mbedtls_mpi_read_binary(&rsa->Q, kb+ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); return HSM_WRONG_DATA; } - } - len = get_uint16_t(kb, ofs); ofs += 2; - r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len; - if (r != 0) { - mbedtls_rsa_free(rsa); - return HSM_WRONG_DATA; + //N + len = get_uint16_t(kb, ofs); ofs += len+2; } len = get_uint16_t(kb, ofs); ofs += 2; @@ -417,11 +422,13 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si } } - if (mbedtls_rsa_complete(rsa) != 0) { + r = mbedtls_rsa_complete(rsa); + if (r != 0) { mbedtls_rsa_free(rsa); return HSM_EXEC_ERROR; } - if (mbedtls_rsa_check_privkey(rsa) != 0) { + r = mbedtls_rsa_check_privkey(rsa); + if (r != 0) { mbedtls_rsa_free(rsa); return HSM_EXEC_ERROR; } From 413c3e02084f9749d1b44c0058b36409054254c6 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 01:08:39 +0200 Subject: [PATCH 20/21] Fix update ef when offset is required. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 77f9f14..c0a12f9 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -543,6 +543,8 @@ static int cmd_initialize() { if (r != HSM_OK) return SW_EXEC_ERROR(); } + else + init_dkek(); } else { //free memory bytes request int heap_left = heapLeft(); @@ -1014,9 +1016,9 @@ static int cmd_update_ef() { if (!ef->data) return SW_DATA_INVALID(); uint8_t *data_merge = (uint8_t *)calloc(1, offset+data_len); - memcpy(data_merge, file_read(ef->data), offset); + memcpy(data_merge, file_read(ef->data+2), offset); memcpy(data_merge+offset, data, data_len); - int r = flash_write_data_to_file(ef, data_merge, data_len); + int r = flash_write_data_to_file(ef, data_merge, offset+data_len); free(data_merge); if (r != HSM_OK) return SW_MEMORY_FAILURE(); @@ -1380,6 +1382,9 @@ static int cmd_key_unwrap() { r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_RSA, key_id, card_ctx); free(card_ctx); mbedtls_rsa_free(&ctx); + if (r != HSM_OK) { + return SW_EXEC_ERROR(); + } } else if (key_type == HSM_KEY_EC) { mbedtls_ecdsa_context ctx; @@ -1393,6 +1398,9 @@ static int cmd_key_unwrap() { r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, key_id, card_ctx); free(card_ctx); mbedtls_ecdsa_free(&ctx); + if (r != HSM_OK) { + return SW_EXEC_ERROR(); + } } else if (key_type == HSM_KEY_AES) { uint8_t aes_key[32]; @@ -1410,6 +1418,9 @@ static int cmd_key_unwrap() { sc_context_t *card_ctx = create_context(); r = store_keys(aes_key, aes_type, key_id, card_ctx); free(card_ctx); + if (r != HSM_OK) { + return SW_EXEC_ERROR(); + } } return SW_OK(); } From 7cf166d6158cb9c6cffb03cf62edd91396a8d042 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 11:18:52 +0200 Subject: [PATCH 21/21] Upgrading to version 1.8 Signed-off-by: Pol Henarejos --- src/hsm/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hsm/version.h b/src/hsm/version.h index 23a5d22..5534f9c 100644 --- a/src/hsm/version.h +++ b/src/hsm/version.h @@ -18,7 +18,7 @@ #ifndef __VERSION_H_ #define __VERSION_H_ -#define HSM_VERSION 0x0106 +#define HSM_VERSION 0x0108 #define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff) #define HSM_VERSION_MINOR (HSM_VERSION & 0xff)