Adding RSA and EC wrap/unwrap, compatible with SC HSM wrap format.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -296,7 +296,6 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len) {
|
|||||||
return HSM_WRONG_SIGNATURE;
|
return HSM_WRONG_SIGNATURE;
|
||||||
|
|
||||||
int key_type = in[8];
|
int key_type = in[8];
|
||||||
|
|
||||||
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15)
|
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15)
|
||||||
return HSM_WRONG_DATA;
|
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;
|
return HSM_WRONG_PADDING;
|
||||||
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 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));
|
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)
|
if (r != HSM_OK)
|
||||||
return r;
|
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);
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
return HSM_WRONG_DATA;
|
return HSM_WRONG_DATA;
|
||||||
}
|
}
|
||||||
|
ofs += len;
|
||||||
|
|
||||||
//N
|
//N
|
||||||
len = get_uint16_t(kb, ofs); ofs += len+2;
|
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;
|
len = get_uint16_t(kb, ofs); ofs += len+2;
|
||||||
|
|
||||||
//d
|
//d
|
||||||
|
len = get_uint16_t(kb, ofs); ofs += 2;
|
||||||
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len);
|
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
mbedtls_ecdsa_free(ecdsa);
|
mbedtls_ecdsa_free(ecdsa);
|
||||||
|
|||||||
@@ -26,5 +26,10 @@ extern void import_dkek_share(const uint8_t *share);
|
|||||||
extern void dkek_kcv(uint8_t *kcv);
|
extern void dkek_kcv(uint8_t *kcv);
|
||||||
extern int dkek_encrypt(uint8_t *data, size_t len);
|
extern int dkek_encrypt(uint8_t *data, size_t len);
|
||||||
extern int dkek_decrypt(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
|
#endif
|
||||||
|
|||||||
@@ -23,6 +23,16 @@
|
|||||||
#include "mbedtls/ecp.h"
|
#include "mbedtls/ecp.h"
|
||||||
#include "mbedtls/md.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 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 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 hash256(const uint8_t *input, size_t len, uint8_t output[32]);
|
||||||
|
|||||||
@@ -589,31 +589,28 @@ static int cmd_import_dkek() {
|
|||||||
//Stores the private and public keys in flash
|
//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) {
|
||||||
int r, key_size;
|
int r, key_size;
|
||||||
uint8_t *asn1bin, *kdata;
|
uint8_t *asn1bin;
|
||||||
size_t asn1len = 0;
|
size_t asn1len = 0;
|
||||||
|
uint8_t kdata[4096/8]; //worst case
|
||||||
if (type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
if (type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
||||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
|
||||||
key_size = mbedtls_mpi_size(&rsa->P)+mbedtls_mpi_size(&rsa->Q);
|
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->P, kdata, key_size/2);
|
||||||
mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2);
|
mbedtls_mpi_write_binary(&rsa->Q, kdata+key_size/2, key_size/2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
|
||||||
key_size = mbedtls_mpi_size(&ecdsa->d);
|
key_size = mbedtls_mpi_size(&ecdsa->d);
|
||||||
kdata = (uint8_t *)calloc(1, key_size+1);
|
|
||||||
kdata[0] = ecdsa->grp.id & 0xff;
|
kdata[0] = ecdsa->grp.id & 0xff;
|
||||||
mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size);
|
mbedtls_mpi_write_binary(&ecdsa->d, kdata+1, key_size);
|
||||||
key_size++;
|
key_size++;
|
||||||
}
|
}
|
||||||
r = dkek_encrypt(kdata, key_size);
|
r = dkek_encrypt(kdata, key_size);
|
||||||
if (r != HSM_OK) {
|
if (r != HSM_OK) {
|
||||||
free(kdata);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
||||||
r = flash_write_data_to_file(fpk, kdata, key_size);
|
r = flash_write_data_to_file(fpk, kdata, key_size);
|
||||||
free(kdata);
|
|
||||||
if (r != HSM_OK)
|
if (r != HSM_OK)
|
||||||
return r;
|
return r;
|
||||||
//add_file_to_chain(fpk, &ef_kf);
|
//add_file_to_chain(fpk, &ef_kf);
|
||||||
@@ -1295,7 +1292,7 @@ static int cmd_signature() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_key_wrap() {
|
static int cmd_key_wrap() {
|
||||||
int key_id = P1(apdu);
|
int key_id = P1(apdu), r = 0, key_type = 0x0;
|
||||||
if (P2(apdu) != 0x92)
|
if (P2(apdu) != 0x92)
|
||||||
return SW_WRONG_P1P2();
|
return SW_WRONG_P1P2();
|
||||||
if (!isUserAuthenticated)
|
if (!isUserAuthenticated)
|
||||||
@@ -1303,23 +1300,75 @@ static int cmd_key_wrap() {
|
|||||||
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
|
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
|
||||||
if (!ef)
|
if (!ef)
|
||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
int key_len = file_read_uint16(ef->data);
|
file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id);
|
||||||
memcpy(res_APDU, file_read(ef->data+2), key_len);
|
if (!prkd)
|
||||||
res_APDU_size = key_len;
|
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();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_key_unwrap() {
|
static int cmd_key_unwrap() {
|
||||||
int key_id = P1(apdu);
|
int key_id = P1(apdu), r = 0;
|
||||||
if (P2(apdu) != 0x93)
|
if (P2(apdu) != 0x93)
|
||||||
return SW_WRONG_P1P2();
|
return SW_WRONG_P1P2();
|
||||||
if (!isUserAuthenticated)
|
if (!isUserAuthenticated)
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
|
int key_type = dkek_type_key(apdu.cmd_apdu_data);
|
||||||
if (!ef)
|
if (key_type == 0x0)
|
||||||
ef = file_new((KEY_PREFIX << 8) | key_id);
|
return SW_DATA_INVALID();
|
||||||
flash_write_data_to_file(ef, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
|
if (key_type == HSM_KEY_RSA) {
|
||||||
low_flash_available();
|
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();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,15 +97,9 @@ extern const uint8_t sc_hsm_aid[];
|
|||||||
#define HSM_OPT_COMBINED_AUTH 0x10
|
#define HSM_OPT_COMBINED_AUTH 0x10
|
||||||
#define HSM_OPT_RRC_RESET_ONLY 0x20
|
#define HSM_OPT_RRC_RESET_ONLY 0x20
|
||||||
|
|
||||||
#define HSM_KEY_RSA 0x1
|
#define P15_KEYTYPE_RSA 0x30
|
||||||
#define HSM_KEY_EC 0x10
|
#define P15_KEYTYPE_ECC 0xA0
|
||||||
#define HSM_KEY_AES 0x100
|
#define P15_KEYTYPE_AES 0xA8
|
||||||
#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_reset_retries(const file_t *pin, bool);
|
||||||
extern int pin_wrong_retry(const file_t *pin);
|
extern int pin_wrong_retry(const file_t *pin);
|
||||||
|
|||||||
Reference in New Issue
Block a user