diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index ca5b71a..8a22016 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -813,42 +813,53 @@ static int cmd_initialize() { return SW_OK(); } -uint8_t get_key_domain(file_t *fkey) { - if (!fkey) - return 0xff; +const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len) { + if (ef == NULL) + return NULL; uint8_t *meta_data = NULL; - uint8_t meta_size = meta_find(fkey->fid, &meta_data); + uint8_t meta_size = meta_find(ef->fid, &meta_data); if (meta_size > 0 && meta_data != NULL) { uint16_t tag = 0x0; uint8_t *tag_data = NULL, *p = NULL; - size_t tag_len = 0; - while (walk_tlv(meta_data, meta_size, &p, &tag, &tag_len, &tag_data)) { - if (tag == 0x92) { //ofset tag - return *tag_data; + while (walk_tlv(meta_data, meta_size, &p, &tag, tag_len, &tag_data)) { + if (tag == meta_tag) { + return tag_data; } } } + return NULL; +} + +uint8_t get_key_domain(file_t *fkey) { + size_t tag_len = 0; + const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len); + if (meta_tag) + return *meta_tag; return 0; } uint32_t get_key_counter(file_t *fkey) { - if (!fkey) - return 0xffffff; - uint8_t *meta_data = NULL; - uint8_t meta_size = meta_find(fkey->fid, &meta_data); - if (meta_size > 0 && meta_data != NULL) { - uint16_t tag = 0x0; - uint8_t *tag_data = NULL, *p = NULL; - size_t tag_len = 0; - while (walk_tlv(meta_data, meta_size, &p, &tag, &tag_len, &tag_data)) { - if (tag == 0x90) { //ofset tag - return (tag_data[0] << 24) | (tag_data[1] << 16) | (tag_data[2] << 8) | tag_data[3]; - } - } - } + size_t tag_len = 0; + const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len); + if (meta_tag) + return (meta_tag[0] << 24) | (meta_tag[1] << 16) | (meta_tag[2] << 8) | meta_tag[3]; return 0xffffffff; } +bool key_has_purpose(file_t *ef, uint8_t purpose) { + size_t tag_len = 0; + const uint8_t *meta_tag = get_meta_tag(ef, 0x91, &tag_len); + if (meta_tag) { + DEBUG_PAYLOAD(meta_tag,tag_len); + for (int i = 0; i < tag_len; i++) { + if (meta_tag[i] == purpose) + return true; + } + return false; + } + return true; +} + uint32_t decrement_key_counter(file_t *fkey) { if (!fkey) return 0xffffff; @@ -1441,6 +1452,8 @@ static int cmd_signature() { return SW_FILE_NOT_FOUND(); if (get_key_counter(fkey) == 0) return SW_FILE_FULL(); + if (key_has_purpose(fkey, p2) == false) + return SW_CONDITIONS_NOT_SATISFIED(); int key_size = file_get_size(fkey); if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1) md = MBEDTLS_MD_SHA1; @@ -1452,7 +1465,7 @@ static int cmd_signature() { generic_hash(md, apdu.data, apdu.nc, apdu.data); apdu.nc = mbedtls_md_get_size(mbedtls_md_info_from_type(md)); } - if (p2 == ALGO_RSA_RAW || p2 == ALGO_RSA_PKCS1 || p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_RSA_PSS_SHA256) { + if (p2 >= ALGO_RSA_RAW && p2 <= ALGO_RSA_PSS_SHA512) { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); @@ -1496,12 +1509,18 @@ static int cmd_signature() { else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA512, oid_len) == 0) md = MBEDTLS_MD_SHA512; } - if (p2 == ALGO_RSA_PSS || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_RSA_PSS_SHA256) { + if (p2 >= ALGO_RSA_PSS && p2 <= ALGO_RSA_PSS_SHA512) { if (p2 == ALGO_RSA_PSS && !oid) { if (apdu.nc == 20) //default is sha1 md = MBEDTLS_MD_SHA1; - else if (apdu.nc == 32) + else if (apdu.nc == 28) + md = MBEDTLS_MD_SHA224; + else if (apdu.nc == 32) md = MBEDTLS_MD_SHA256; + else if (apdu.nc == 48) + md = MBEDTLS_MD_SHA384; + else if (apdu.nc == 64) + md = MBEDTLS_MD_SHA512; } mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, md); } @@ -1525,7 +1544,7 @@ static int cmd_signature() { apdu.ne = key_size; mbedtls_rsa_free(&ctx); } - else if (p2 == ALGO_EC_RAW || p2 == ALGO_EC_SHA1 || p2 == ALGO_EC_SHA224 || p2 == ALGO_EC_SHA256) { + else if (p2 >= ALGO_EC_RAW && p2 <= ALGO_EC_SHA512) { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); md = MBEDTLS_MD_SHA256; @@ -1547,6 +1566,10 @@ static int cmd_signature() { md = MBEDTLS_MD_SHA224; else if (p2 == ALGO_EC_SHA256) md = MBEDTLS_MD_SHA256; + else if (p2 == ALGO_EC_SHA384) + md = MBEDTLS_MD_SHA384; + else if (p2 == ALGO_EC_SHA512) + md = MBEDTLS_MD_SHA512; int r; r = load_private_key_ecdsa(&ctx, fkey); if (r != CCID_OK) { @@ -1581,6 +1604,8 @@ static int cmd_key_wrap() { uint8_t kdom = get_key_domain(ef); if (!ef) return SW_FILE_NOT_FOUND(); + if (key_has_purpose(ef, ALGO_WRAP) == false) + return SW_CONDITIONS_NOT_SATISFIED(); file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id); if (!prkd) return SW_FILE_NOT_FOUND(); @@ -1711,6 +1736,7 @@ static int cmd_key_unwrap() { static int cmd_decrypt_asym() { int key_id = P1(apdu); + uint8_t p2 = P2(apdu); if (!isUserAuthenticated) return SW_SECURITY_STATUS_NOT_SATISFIED(); file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id); @@ -1718,7 +1744,9 @@ static int cmd_decrypt_asym() { return SW_FILE_NOT_FOUND(); if (get_key_counter(ef) == 0) return SW_FILE_FULL(); - if (P2(apdu) == ALGO_RSA_DECRYPT) { + if (key_has_purpose(ef, p2) == false) + return SW_CONDITIONS_NOT_SATISFIED(); + if (p2 == ALGO_RSA_DECRYPT) { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); int r = load_private_key_rsa(&ctx, ef); @@ -1739,7 +1767,7 @@ static int cmd_decrypt_asym() { res_APDU_size = key_size; mbedtls_rsa_free(&ctx); } - else if (P2(apdu) == ALGO_EC_DH) { + else if (p2 == ALGO_EC_DH) { mbedtls_ecdh_context ctx; if (wait_button() == true) //timeout return SW_SECURE_MESSAGE_EXEC_ERROR(); @@ -1795,6 +1823,8 @@ static int cmd_cipher_sym() { file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id); if (!ef) return SW_FILE_NOT_FOUND(); + if (key_has_purpose(ef, algo) == false) + return SW_CONDITIONS_NOT_SATISFIED(); if ((apdu.nc % 16) != 0) { return SW_WRONG_LENGTH(); } @@ -1890,7 +1920,12 @@ static int cmd_derive_asym() { return SW_SECURITY_STATUS_NOT_SATISFIED(); if (!(fkey = search_dynamic_file((KEY_PREFIX << 8) | key_id)) || !fkey->data || file_get_size(fkey) == 0) return SW_FILE_NOT_FOUND(); - +uint8_t *meta_data = NULL; + uint8_t meta_size = meta_find(fkey->fid, &meta_data); + printf("kid = %d\n",fkey->fid); + DEBUG_PAYLOAD(meta_data, meta_size); + if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) + return SW_CONDITIONS_NOT_SATISFIED(); if (apdu.nc == 0) return SW_WRONG_LENGTH(); if (apdu.data[0] == ALGO_EC_DERIVE) { diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index 9ba467a..153b792 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -26,21 +26,35 @@ extern const uint8_t sc_hsm_aid[]; #define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */ -#define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */ +#define ALGO_RSA_DECRYPT 0x21 /* RSA raw decrypt */ +#define ALGO_RSA_DECRYPT_V15 0x22 +#define ALGO_RSA_DECRYPT_OEP 0x23 #define ALGO_RSA_PKCS1 0x30 /* RSA signature with DigestInfo input and PKCS#1 V1.5 padding */ #define ALGO_RSA_PKCS1_SHA1 0x31 /* RSA signature with SHA-1 hash and PKCS#1 V1.5 padding */ +#define ALGO_RSA_PKCS1_SHA224 0x32 #define ALGO_RSA_PKCS1_SHA256 0x33 /* RSA signature with SHA-256 hash and PKCS#1 V1.5 padding */ +#define ALGO_RSA_PKCS1_SHA384 0x34 +#define ALGO_RSA_PKCS1_SHA512 0x35 #define ALGO_RSA_PSS 0x40 /* RSA signature with external hash and PKCS#1 PSS padding*/ #define ALGO_RSA_PSS_SHA1 0x41 /* RSA signature with SHA-1 hash and PKCS#1 PSS padding */ +#define ALGO_RSA_PSS_SHA224 0x42 #define ALGO_RSA_PSS_SHA256 0x43 /* RSA signature with SHA-256 hash and PKCS#1 PSS padding */ +#define ALGO_RSA_PSS_SHA384 0x44 +#define ALGO_RSA_PSS_SHA512 0x45 #define ALGO_EC_RAW 0x70 /* ECDSA signature with hash input */ #define ALGO_EC_SHA1 0x71 /* ECDSA signature with SHA-1 hash */ #define ALGO_EC_SHA224 0x72 /* ECDSA signature with SHA-224 hash */ #define ALGO_EC_SHA256 0x73 /* ECDSA signature with SHA-256 hash */ +#define ALGO_EC_SHA384 0x74 +#define ALGO_EC_SHA512 0x75 #define ALGO_EC_DH 0x80 /* ECDH key derivation */ +#define ALGO_WRAP 0x92 +#define ALGO_UNWRAP 0x93 +#define ALGO_REPLACE 0x94 + #define ALGO_EC_DERIVE 0x98 /* Derive EC key from EC key */ #define ALGO_AES_CBC_ENCRYPT 0x10