Fix wrap/unwrap keys with specific allowed algorithms.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos 2022-08-13 02:58:36 +02:00
parent 2e88422c86
commit 55c8a66613
No known key found for this signature in database
GPG key ID: C0095B7870A4CCD3
3 changed files with 33 additions and 19 deletions

View file

@ -212,7 +212,7 @@ int mkek_decrypt(uint8_t *data, size_t len) {
return r;
}
int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_t *out_len) {
int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_t *out_len, const uint8_t *allowed, size_t allowed_len) {
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES))
return CCID_WRONG_DATA;
@ -221,8 +221,6 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_
int kb_len = 0, r = 0;
uint8_t *algo = NULL;
uint8_t algo_len = 0;
uint8_t *allowed = NULL;
uint8_t allowed_len = 0;
uint8_t kenc[32];
memset(kenc, 0, sizeof(kenc));
r = dkek_kenc(id, kenc);
@ -260,8 +258,6 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_
algo = (uint8_t *)"\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
algo_len = 10;
allowed = (uint8_t *)"\x00\x04\x10\x11\x18\x99"; //(2+4)
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
@ -329,7 +325,8 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_
else
*out_len += 2;
if (allowed) {
if (allowed && allowed_len > 0) {
put_uint16_t(allowed_len, out+*out_len); *out_len += 2;
memcpy(out+*out_len, allowed, allowed_len);
*out_len += allowed_len;
}
@ -372,7 +369,7 @@ int dkek_type_key(const uint8_t *in) {
return 0x0;
}
int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out) {
int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out, uint8_t **allowed, size_t *allowed_len) {
uint8_t kcv[8];
int r = 0;
memset(kcv, 0, sizeof(kcv));
@ -423,6 +420,8 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len,
//Allowed algorithms
len = get_uint16_t(in, ofs);
*allowed = (uint8_t *)(in+ofs+2);
*allowed_len = len;
ofs += len+2;
//Access conditions

View file

@ -28,9 +28,9 @@ extern int import_dkek_share(uint8_t, const uint8_t *share);
extern int dkek_kcv(uint8_t, uint8_t *kcv);
extern int mkek_encrypt(uint8_t *data, size_t len);
extern int mkek_decrypt(uint8_t *data, size_t len);
extern int dkek_encode_key(uint8_t, void *key_ctx, int key_type, uint8_t *out, size_t *out_len);
extern int dkek_encode_key(uint8_t, void *key_ctx, int key_type, uint8_t *out, size_t *out_len, const uint8_t *, size_t);
extern int dkek_type_key(const uint8_t *in);
extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out);
extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, size_t in_len, int *key_size_out, uint8_t **, size_t *);
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)

View file

@ -1709,6 +1709,8 @@ static int cmd_key_wrap() {
return SW_FILE_NOT_FOUND();
const uint8_t *dprkd = file_get_data(prkd);
size_t wrap_len = MAX_DKEK_ENCODE_KEY_BUFFER;
size_t tag_len = 0;
const uint8_t *meta_tag = get_meta_tag(ef, 0x91, &tag_len);
if (*dprkd == P15_KEYTYPE_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
@ -1719,7 +1721,7 @@ static int cmd_key_wrap() {
return SW_SECURE_MESSAGE_EXEC_ERROR();
return SW_EXEC_ERROR();
}
r = dkek_encode_key(kdom, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len);
r = dkek_encode_key(kdom, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_rsa_free(&ctx);
}
else if (*dprkd == P15_KEYTYPE_ECC) {
@ -1732,7 +1734,7 @@ static int cmd_key_wrap() {
return SW_SECURE_MESSAGE_EXEC_ERROR();
return SW_EXEC_ERROR();
}
r = dkek_encode_key(kdom, &ctx, HSM_KEY_EC, res_APDU, &wrap_len);
r = dkek_encode_key(kdom, &ctx, HSM_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_ecdsa_free(&ctx);
}
else if (*dprkd == P15_KEYTYPE_AES) {
@ -1751,7 +1753,7 @@ static int cmd_key_wrap() {
aes_type = HSM_KEY_AES_192;
else if (key_size == 16)
aes_type = HSM_KEY_AES_128;
r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len);
r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_platform_zeroize(kdata, sizeof(kdata));
}
if (r != CCID_OK)
@ -1767,14 +1769,15 @@ static int cmd_key_unwrap() {
if (!isUserAuthenticated)
return SW_SECURITY_STATUS_NOT_SATISFIED();
int key_type = dkek_type_key(apdu.data);
uint8_t kdom = -1;
uint8_t kdom = -1, *allowed = NULL;
size_t allowed_len = 0;
if (key_type == 0x0)
return SW_DATA_INVALID();
if (key_type == HSM_KEY_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
do {
r = dkek_decode_key(++kdom, &ctx, apdu.data, apdu.nc, NULL);
r = dkek_decode_key(++kdom, &ctx, apdu.data, apdu.nc, NULL, &allowed, &allowed_len);
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
@ -1790,7 +1793,7 @@ static int cmd_key_unwrap() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
do {
r = dkek_decode_key(++kdom, &ctx, apdu.data, apdu.nc, NULL);
r = dkek_decode_key(++kdom, &ctx, apdu.data, apdu.nc, NULL, &allowed, &allowed_len);
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
@ -1806,7 +1809,7 @@ static int cmd_key_unwrap() {
uint8_t aes_key[32];
int key_size = 0, aes_type = 0;
do {
r = dkek_decode_key(++kdom, aes_key, apdu.data, apdu.nc, &key_size);
r = dkek_decode_key(++kdom, aes_key, apdu.data, apdu.nc, &key_size, &allowed, &allowed_len);
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != CCID_OK) {
return SW_EXEC_ERROR();
@ -1824,9 +1827,21 @@ static int cmd_key_unwrap() {
return SW_EXEC_ERROR();
}
}
if (kdom >= 0) {
uint8_t meta[3] = {0x92,1,kdom};
r = meta_add((KEY_PREFIX << 8) | key_id, meta, sizeof(meta));
if ((allowed != NULL && allowed_len > 0) || kdom >= 0) {
size_t meta_len = (allowed_len > 0 ? 2+allowed_len : 0) + (kdom >= 0 ? 3 : 0);
uint8_t *meta = (uint8_t *)calloc(1,meta_len), *m = meta;
if (allowed_len > 0) {
*m++ = 0x91;
*m++ = allowed_len;
memcpy(m, allowed, allowed_len); m += allowed_len;
}
if (kdom >= 0) {
*m++ = 0x92;
*m++ = 1;
*m++ = kdom;
}
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
free(meta);
if (r != CCID_OK)
return r;
}