Fix wrap/unwrap keys with specific allowed algorithms.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -212,7 +212,7 @@ int mkek_decrypt(uint8_t *data, size_t len) {
|
|||||||
return r;
|
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))
|
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES))
|
||||||
return CCID_WRONG_DATA;
|
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;
|
int kb_len = 0, r = 0;
|
||||||
uint8_t *algo = NULL;
|
uint8_t *algo = NULL;
|
||||||
uint8_t algo_len = 0;
|
uint8_t algo_len = 0;
|
||||||
uint8_t *allowed = NULL;
|
|
||||||
uint8_t allowed_len = 0;
|
|
||||||
uint8_t kenc[32];
|
uint8_t kenc[32];
|
||||||
memset(kenc, 0, sizeof(kenc));
|
memset(kenc, 0, sizeof(kenc));
|
||||||
r = dkek_kenc(id, 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 = (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;
|
algo_len = 10;
|
||||||
allowed = (uint8_t *)"\x00\x04\x10\x11\x18\x99"; //(2+4)
|
|
||||||
allowed_len = 6;
|
|
||||||
}
|
}
|
||||||
else if (key_type & HSM_KEY_RSA) {
|
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
|
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
|
else
|
||||||
*out_len += 2;
|
*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);
|
memcpy(out+*out_len, allowed, allowed_len);
|
||||||
*out_len += allowed_len;
|
*out_len += allowed_len;
|
||||||
}
|
}
|
||||||
@@ -372,7 +369,7 @@ int dkek_type_key(const uint8_t *in) {
|
|||||||
return 0x0;
|
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];
|
uint8_t kcv[8];
|
||||||
int r = 0;
|
int r = 0;
|
||||||
memset(kcv, 0, sizeof(kcv));
|
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
|
//Allowed algorithms
|
||||||
len = get_uint16_t(in, ofs);
|
len = get_uint16_t(in, ofs);
|
||||||
|
*allowed = (uint8_t *)(in+ofs+2);
|
||||||
|
*allowed_len = len;
|
||||||
ofs += len+2;
|
ofs += len+2;
|
||||||
|
|
||||||
//Access conditions
|
//Access conditions
|
||||||
|
|||||||
@@ -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 dkek_kcv(uint8_t, uint8_t *kcv);
|
||||||
extern int mkek_encrypt(uint8_t *data, size_t len);
|
extern int mkek_encrypt(uint8_t *data, size_t len);
|
||||||
extern int mkek_decrypt(uint8_t *data, size_t len);
|
extern int 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_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)
|
#define MAX_DKEK_ENCODE_KEY_BUFFER (8+1+12+6+(8+2*4+2*4096/8+3+13)+16)
|
||||||
|
|
||||||
|
|||||||
@@ -1709,6 +1709,8 @@ static int cmd_key_wrap() {
|
|||||||
return SW_FILE_NOT_FOUND();
|
return SW_FILE_NOT_FOUND();
|
||||||
const uint8_t *dprkd = file_get_data(prkd);
|
const uint8_t *dprkd = file_get_data(prkd);
|
||||||
size_t wrap_len = MAX_DKEK_ENCODE_KEY_BUFFER;
|
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) {
|
if (*dprkd == P15_KEYTYPE_RSA) {
|
||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
@@ -1719,7 +1721,7 @@ static int cmd_key_wrap() {
|
|||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
return SW_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);
|
mbedtls_rsa_free(&ctx);
|
||||||
}
|
}
|
||||||
else if (*dprkd == P15_KEYTYPE_ECC) {
|
else if (*dprkd == P15_KEYTYPE_ECC) {
|
||||||
@@ -1732,7 +1734,7 @@ static int cmd_key_wrap() {
|
|||||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||||
return SW_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);
|
mbedtls_ecdsa_free(&ctx);
|
||||||
}
|
}
|
||||||
else if (*dprkd == P15_KEYTYPE_AES) {
|
else if (*dprkd == P15_KEYTYPE_AES) {
|
||||||
@@ -1751,7 +1753,7 @@ static int cmd_key_wrap() {
|
|||||||
aes_type = HSM_KEY_AES_192;
|
aes_type = HSM_KEY_AES_192;
|
||||||
else if (key_size == 16)
|
else if (key_size == 16)
|
||||||
aes_type = HSM_KEY_AES_128;
|
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));
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
}
|
}
|
||||||
if (r != CCID_OK)
|
if (r != CCID_OK)
|
||||||
@@ -1767,14 +1769,15 @@ static int cmd_key_unwrap() {
|
|||||||
if (!isUserAuthenticated)
|
if (!isUserAuthenticated)
|
||||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||||
int key_type = dkek_type_key(apdu.data);
|
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)
|
if (key_type == 0x0)
|
||||||
return SW_DATA_INVALID();
|
return SW_DATA_INVALID();
|
||||||
if (key_type == HSM_KEY_RSA) {
|
if (key_type == HSM_KEY_RSA) {
|
||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
do {
|
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);
|
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
@@ -1790,7 +1793,7 @@ static int cmd_key_unwrap() {
|
|||||||
mbedtls_ecdsa_context ctx;
|
mbedtls_ecdsa_context ctx;
|
||||||
mbedtls_ecdsa_init(&ctx);
|
mbedtls_ecdsa_init(&ctx);
|
||||||
do {
|
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);
|
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_ecdsa_free(&ctx);
|
mbedtls_ecdsa_free(&ctx);
|
||||||
@@ -1806,7 +1809,7 @@ static int cmd_key_unwrap() {
|
|||||||
uint8_t aes_key[32];
|
uint8_t aes_key[32];
|
||||||
int key_size = 0, aes_type = 0;
|
int key_size = 0, aes_type = 0;
|
||||||
do {
|
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);
|
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1824,9 +1827,21 @@ static int cmd_key_unwrap() {
|
|||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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) {
|
if (kdom >= 0) {
|
||||||
uint8_t meta[3] = {0x92,1,kdom};
|
*m++ = 0x92;
|
||||||
r = meta_add((KEY_PREFIX << 8) | key_id, meta, sizeof(meta));
|
*m++ = 1;
|
||||||
|
*m++ = kdom;
|
||||||
|
}
|
||||||
|
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
|
||||||
|
free(meta);
|
||||||
if (r != CCID_OK)
|
if (r != CCID_OK)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user