Harmonize coding style.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2023-02-14 23:13:46 +01:00
parent cab72f200a
commit daaa5bf402
35 changed files with 1832 additions and 1058 deletions

View File

@@ -21,10 +21,12 @@
uint8_t challenge[256]; uint8_t challenge[256];
uint8_t challenge_len = 0; uint8_t challenge_len = 0;
int cmd_challenge() { int cmd_challenge()
uint8_t *rb = (uint8_t *)random_bytes_get(apdu.ne); {
if (!rb) uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
if (!rb) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
memcpy(res_APDU, rb, apdu.ne); memcpy(res_APDU, rb, apdu.ne);
challenge_len = MIN(apdu.ne, sizeof(challenge)); challenge_len = MIN(apdu.ne, sizeof(challenge));
memcpy(challenge, rb, challenge_len); memcpy(challenge, rb, challenge_len);

View File

@@ -19,14 +19,16 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "kek.h" #include "kek.h"
int cmd_change_pin() { int cmd_change_pin()
{
if (P1(apdu) == 0x0) { if (P1(apdu) == 0x0) {
if (P2(apdu) == 0x81 || P2(apdu) == 0x88) { if (P2(apdu) == 0x81 || P2(apdu) == 0x88) {
file_t *file_pin = NULL; file_t *file_pin = NULL;
if (P2(apdu) == 0x81) if (P2(apdu) == 0x81) {
file_pin = file_pin1; file_pin = file_pin1;
else if (P2(apdu) == 0x88) } else if (P2(apdu) == 0x88) {
file_pin = file_sopin; file_pin = file_sopin;
}
if (!file_pin) { if (!file_pin) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -35,26 +37,28 @@ int cmd_change_pin() {
} }
uint8_t pin_len = file_read_uint8(file_get_data(file_pin)); uint8_t pin_len = file_read_uint8(file_get_data(file_pin));
int r = check_pin(file_pin, apdu.data, pin_len); int r = check_pin(file_pin, apdu.data, pin_len);
if (r != 0x9000) if (r != 0x9000) {
return r; return r;
}
uint8_t mkek[MKEK_SIZE]; uint8_t mkek[MKEK_SIZE];
r = load_mkek(mkek); //loads the MKEK with old pin r = load_mkek(mkek); //loads the MKEK with old pin
if (r != CCID_OK) if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
//encrypt MKEK with new pin //encrypt MKEK with new pin
if (P2(apdu) == 0x81) { if (P2(apdu) == 0x81) {
hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_pin); hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_pin);
has_session_pin = true; has_session_pin = true;
} } else if (P2(apdu) == 0x88) {
else if (P2(apdu) == 0x88) {
hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_sopin); hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
r = store_mkek(mkek); r = store_mkek(mkek);
release_mkek(mkek); release_mkek(mkek);
if (r != CCID_OK) if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
uint8_t dhash[33]; uint8_t dhash[33];
dhash[0] = apdu.nc-pin_len; dhash[0] = apdu.nc-pin_len;
double_hash_pin(apdu.data+pin_len, apdu.nc-pin_len, dhash+1); double_hash_pin(apdu.data+pin_len, apdu.nc-pin_len, dhash+1);

View File

@@ -36,18 +36,19 @@
/* This is copied from pkcs5.c Mbedtls */ /* This is copied from pkcs5.c Mbedtls */
/** Unfortunately it is declared as static, so I cannot call it. **/ /** Unfortunately it is declared as static, so I cannot call it. **/
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations, mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type ) int *keylen, mbedtls_md_type_t *md_type)
{ {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf prf_alg_oid; mbedtls_asn1_buf prf_alg_oid;
unsigned char *p = params->p; unsigned char *p = params->p;
const unsigned char *end = params->p + params->len; const unsigned char *end = params->p + params->len;
if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
}
/* /*
* PBKDF2-params ::= SEQUENCE { * PBKDF2-params ::= SEQUENCE {
* salt OCTET STRING, * salt OCTET STRING,
@@ -57,42 +58,57 @@ static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
* } * }
* *
*/ */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) MBEDTLS_ASN1_OCTET_STRING)) != 0) {
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
salt->p = p; salt->p = p;
p += salt->len; p += salt->len;
if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
if( p == end )
return( 0 );
if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) {
if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
} }
if( p == end ) if (p == end) {
return( 0 ); return 0;
}
if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
}
if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) if (p == end) {
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); return 0;
}
if( p != end ) if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); }
return( 0 ); if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
}
if (p != end) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
return 0;
} }
/* Taken from https://github.com/Mbed-TLS/mbedtls/issues/2335 */ /* Taken from https://github.com/Mbed-TLS/mbedtls/issues/2335 */
int mbedtls_ansi_x936_kdf(mbedtls_md_type_t md_type, size_t input_len, uint8_t *input, size_t shared_info_len, uint8_t *shared_info, size_t output_len, uint8_t *output) { int mbedtls_ansi_x936_kdf(mbedtls_md_type_t md_type,
size_t input_len,
uint8_t *input,
size_t shared_info_len,
uint8_t *shared_info,
size_t output_len,
uint8_t *output)
{
mbedtls_md_context_t md_ctx; mbedtls_md_context_t md_ctx;
const mbedtls_md_info_t *md_info = NULL; const mbedtls_md_info_t *md_info = NULL;
int hashlen = 0, exit_code = MBEDTLS_ERR_MD_BAD_INPUT_DATA; int hashlen = 0, exit_code = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -143,18 +159,23 @@ int mbedtls_ansi_x936_kdf(mbedtls_md_type_t md_type, size_t input_len, uint8_t *
return 0; return 0;
} }
int cmd_cipher_sym() { int cmd_cipher_sym()
{
int key_id = P1(apdu); int key_id = P1(apdu);
int algo = P2(apdu); int algo = P2(apdu);
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); 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();
if (key_has_purpose(ef, algo) == false) }
if (key_has_purpose(ef, algo) == false) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
if (wait_button_pressed() == true) // timeout }
if (wait_button_pressed() == true) { // timeout
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int key_size = file_get_size(ef); int key_size = file_get_size(ef);
uint8_t kdata[32]; //maximum AES key size uint8_t kdata[32]; //maximum AES key size
memcpy(kdata, file_get_data(ef), key_size); memcpy(kdata, file_get_data(ef), key_size);
@@ -176,21 +197,30 @@ int cmd_cipher_sym() {
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, apdu.nc, tmp_iv, apdu.data, res_APDU); r = mbedtls_aes_crypt_cbc(&aes,
MBEDTLS_AES_ENCRYPT,
apdu.nc,
tmp_iv,
apdu.data,
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} } else if (algo == ALGO_AES_CBC_DECRYPT) {
else if (algo == ALGO_AES_CBC_DECRYPT) {
int r = mbedtls_aes_setkey_dec(&aes, kdata, key_size*8); int r = mbedtls_aes_setkey_dec(&aes, kdata, key_size*8);
if (r != 0) { if (r != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, apdu.nc, tmp_iv, apdu.data, res_APDU); r = mbedtls_aes_crypt_cbc(&aes,
MBEDTLS_AES_DECRYPT,
apdu.nc,
tmp_iv,
apdu.data,
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
@@ -199,36 +229,44 @@ int cmd_cipher_sym() {
} }
res_APDU_size = apdu.nc; res_APDU_size = apdu.nc;
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
} } else if (algo == ALGO_AES_CMAC) {
else if (algo == ALGO_AES_CMAC) {
const mbedtls_cipher_info_t *cipher_info; const mbedtls_cipher_info_t *cipher_info;
if (key_size == 16) if (key_size == 16) {
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
else if (key_size == 24) } else if (key_size == 24) {
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB); cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_192_ECB);
else if (key_size == 32) } else if (key_size == 32) {
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB); cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB);
else { } else {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size*8, apdu.data, apdu.nc, res_APDU); int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size*8, apdu.data, apdu.nc, res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU_size = 16; res_APDU_size = 16;
} } else if (algo == ALGO_AES_DERIVE) {
else if (algo == ALGO_AES_DERIVE) { int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, file_get_data(ef), key_size, apdu.data, apdu.nc, res_APDU, apdu.nc); NULL,
0,
file_get_data(ef),
key_size,
apdu.data,
apdu.nc,
res_APDU,
apdu.nc);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU_size = apdu.nc; res_APDU_size = apdu.nc;
} } else if (algo == ALGO_EXT_CIPHER_ENCRYPT || algo == ALGO_EXT_CIPHER_DECRYPT) {
else if (algo == ALGO_EXT_CIPHER_ENCRYPT || algo == ALGO_EXT_CIPHER_DECRYPT) {
size_t oid_len = 0, aad_len = 0, iv_len = 0, enc_len = 0; size_t oid_len = 0, aad_len = 0, iv_len = 0, enc_len = 0;
uint8_t *oid = NULL, *aad = NULL, *iv = NULL, *enc = NULL; uint8_t *oid = NULL, *aad = NULL, *iv = NULL, *enc = NULL;
if (!asn1_find_tag(apdu.data, apdu.nc, 0x6, &oid_len, &oid) || oid_len == 0 || oid == NULL) { if (!asn1_find_tag(apdu.data, apdu.nc, 0x6, &oid_len,
&oid) || oid_len == 0 || oid == NULL) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
@@ -246,57 +284,88 @@ int cmd_cipher_sym() {
mbedtls_chachapoly_context ctx; mbedtls_chachapoly_context ctx;
mbedtls_chachapoly_init(&ctx); mbedtls_chachapoly_init(&ctx);
if (algo == ALGO_EXT_CIPHER_ENCRYPT) { if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
r = mbedtls_chachapoly_encrypt_and_tag(&ctx, enc_len, iv ? iv : tmp_iv, aad, aad_len, enc, res_APDU, res_APDU + enc_len); r = mbedtls_chachapoly_encrypt_and_tag(&ctx,
} enc_len,
else if (algo == ALGO_EXT_CIPHER_DECRYPT) { iv ? iv : tmp_iv,
r = mbedtls_chachapoly_auth_decrypt(&ctx, enc_len - 16, iv ? iv : tmp_iv, aad, aad_len, enc + enc_len - 16, enc, res_APDU); aad,
aad_len,
enc,
res_APDU,
res_APDU + enc_len);
} else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
r = mbedtls_chachapoly_auth_decrypt(&ctx,
enc_len - 16,
iv ? iv : tmp_iv,
aad,
aad_len,
enc + enc_len - 16,
enc,
res_APDU);
} }
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_chachapoly_free(&ctx); mbedtls_chachapoly_free(&ctx);
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
if (algo == ALGO_EXT_CIPHER_ENCRYPT) }
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
res_APDU_size = enc_len + 16; res_APDU_size = enc_len + 16;
else if (algo == ALGO_EXT_CIPHER_DECRYPT) } else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
res_APDU_size = enc_len - 16; res_APDU_size = enc_len - 16;
} }
else if (memcmp(oid, OID_DIGEST, 7) == 0) { } else if (memcmp(oid, OID_DIGEST, 7) == 0) {
const mbedtls_md_info_t *md_info = NULL; const mbedtls_md_info_t *md_info = NULL;
if (memcmp(oid, OID_HMAC_SHA1, oid_len) == 0) if (memcmp(oid, OID_HMAC_SHA1, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
else if (memcmp(oid, OID_HMAC_SHA224, oid_len) == 0) } else if (memcmp(oid, OID_HMAC_SHA224, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA224); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
else if (memcmp(oid, OID_HMAC_SHA256, oid_len) == 0) } else if (memcmp(oid, OID_HMAC_SHA256, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
else if (memcmp(oid, OID_HMAC_SHA384, oid_len) == 0) } else if (memcmp(oid, OID_HMAC_SHA384, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
else if (memcmp(oid, OID_HMAC_SHA512, oid_len) == 0) } else if (memcmp(oid, OID_HMAC_SHA512, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
if (md_info == NULL) }
if (md_info == NULL) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
int r = mbedtls_md_hmac(md_info, kdata, key_size, apdu.data, apdu.nc, res_APDU); int r = mbedtls_md_hmac(md_info, kdata, key_size, apdu.data, apdu.nc, res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU_size = md_info->size; res_APDU_size = md_info->size;
} } else if (memcmp(oid, OID_HKDF_SHA256,
else if (memcmp(oid, OID_HKDF_SHA256, oid_len) == 0 || memcmp(oid, OID_HKDF_SHA384, oid_len) == 0 || memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) { oid_len) == 0 ||
memcmp(oid, OID_HKDF_SHA384,
oid_len) == 0 || memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) {
const mbedtls_md_info_t *md_info = NULL; const mbedtls_md_info_t *md_info = NULL;
if (memcmp(oid, OID_HKDF_SHA256, oid_len) == 0) if (memcmp(oid, OID_HKDF_SHA256, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
else if (memcmp(oid, OID_HKDF_SHA384, oid_len) == 0) } else if (memcmp(oid, OID_HKDF_SHA384, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
else if (memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) } else if (memcmp(oid, OID_HKDF_SHA512, oid_len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
int r = mbedtls_hkdf(md_info, iv, iv_len, kdata, key_size, enc, enc_len, res_APDU, apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info)); }
int r = mbedtls_hkdf(md_info,
iv,
iv_len,
kdata,
key_size,
enc,
enc_len,
res_APDU,
apdu.ne > 0 &&
apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info));
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne :mbedtls_md_get_size(md_info); }
} res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info);
else if (memcmp(oid, OID_PKCS5_PBKDF2, oid_len) == 0) { } else if (memcmp(oid, OID_PKCS5_PBKDF2, oid_len) == 0) {
int iterations = 0, keylen = 0; int iterations = 0, keylen = 0;
mbedtls_asn1_buf salt, params = { .p = enc, .len = enc_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) }; mbedtls_asn1_buf salt,
params =
{ .p = enc, .len = enc_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) };
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
mbedtls_md_context_t md_ctx; mbedtls_md_context_t md_ctx;
@@ -312,43 +381,63 @@ int cmd_cipher_sym() {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
r = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, kdata, key_size, salt.p, salt.len, iterations, keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32), res_APDU); r = mbedtls_pkcs5_pbkdf2_hmac(&md_ctx,
kdata,
key_size,
salt.p,
salt.len,
iterations,
keylen ? keylen : (apdu.ne > 0 &&
apdu.ne < 65536 ? apdu.ne : 32),
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_md_free(&md_ctx); mbedtls_md_free(&md_ctx);
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32); res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32);
} } else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) { mbedtls_asn1_buf params =
mbedtls_asn1_buf params = { .p = aad, .len = aad_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) }; { .p = aad, .len = aad_len, .tag = (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) };
int r = mbedtls_pkcs5_pbes2(&params, algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_PKCS5_ENCRYPT : MBEDTLS_PKCS5_DECRYPT, kdata, key_size, enc, enc_len, res_APDU); int r = mbedtls_pkcs5_pbes2(&params,
algo == ALGO_EXT_CIPHER_ENCRYPT ? MBEDTLS_PKCS5_ENCRYPT : MBEDTLS_PKCS5_DECRYPT,
kdata,
key_size,
enc,
enc_len,
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
res_APDU_size = enc_len; res_APDU_size = enc_len;
} } else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) {
else if (memcmp(oid, OID_KDF_X963, oid_len) == 0) {
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
if (memcmp(enc, OID_HMAC_SHA1, enc_len) == 0) if (memcmp(enc, OID_HMAC_SHA1, enc_len) == 0) {
md_type = MBEDTLS_MD_SHA1; md_type = MBEDTLS_MD_SHA1;
else if (memcmp(enc, OID_HMAC_SHA224, enc_len) == 0) } else if (memcmp(enc, OID_HMAC_SHA224, enc_len) == 0) {
md_type = MBEDTLS_MD_SHA224; md_type = MBEDTLS_MD_SHA224;
else if (memcmp(enc, OID_HMAC_SHA256, enc_len) == 0) } else if (memcmp(enc, OID_HMAC_SHA256, enc_len) == 0) {
md_type = MBEDTLS_MD_SHA256; md_type = MBEDTLS_MD_SHA256;
else if (memcmp(enc, OID_HMAC_SHA384, enc_len) == 0) } else if (memcmp(enc, OID_HMAC_SHA384, enc_len) == 0) {
md_type = MBEDTLS_MD_SHA384; md_type = MBEDTLS_MD_SHA384;
else if (memcmp(enc, OID_HMAC_SHA512, enc_len) == 0) } else if (memcmp(enc, OID_HMAC_SHA512, enc_len) == 0) {
md_type = MBEDTLS_MD_SHA512; md_type = MBEDTLS_MD_SHA512;
int r = mbedtls_ansi_x936_kdf(md_type, key_size, kdata, aad_len, aad, apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32, res_APDU); }
int r = mbedtls_ansi_x936_kdf(md_type,
key_size,
kdata,
aad_len,
aad,
apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32,
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32; res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32;
} }
} } else {
else {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
} }

View File

@@ -26,56 +26,65 @@
#include "random.h" #include "random.h"
#include "oid.h" #include "oid.h"
int cmd_decrypt_asym() { int cmd_decrypt_asym()
{
int key_id = P1(apdu); int key_id = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
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); 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();
if (get_key_counter(ef) == 0) }
if (get_key_counter(ef) == 0) {
return SW_FILE_FULL(); return SW_FILE_FULL();
if (key_has_purpose(ef, p2) == false) }
if (key_has_purpose(ef, p2) == false) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
if (p2 >= ALGO_RSA_DECRYPT && p2 <= ALGO_RSA_DECRYPT_OEP) { if (p2 >= ALGO_RSA_DECRYPT && p2 <= ALGO_RSA_DECRYPT_OEP) {
mbedtls_rsa_context ctx; mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx); mbedtls_rsa_init(&ctx);
if (p2 == ALGO_RSA_DECRYPT_OEP) if (p2 == ALGO_RSA_DECRYPT_OEP) {
mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
}
int r = load_private_key_rsa(&ctx, ef); int r = load_private_key_rsa(&ctx, ef);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED) if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
int key_size = file_get_size(ef); int key_size = file_get_size(ef);
if (apdu.nc < key_size) //needs padding if (apdu.nc < key_size) { //needs padding
memset(apdu.data+apdu.nc, 0, key_size-apdu.nc); memset(apdu.data+apdu.nc, 0, key_size-apdu.nc);
}
if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) { if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) {
size_t olen = apdu.nc; size_t olen = apdu.nc;
r = mbedtls_rsa_pkcs1_decrypt(&ctx, random_gen, NULL, &olen, apdu.data, res_APDU, 512); r = mbedtls_rsa_pkcs1_decrypt(&ctx, random_gen, NULL, &olen, apdu.data, res_APDU, 512);
if (r == 0) if (r == 0) {
res_APDU_size = olen; res_APDU_size = olen;
} }
else { } else {
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU); r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
if (r == 0) if (r == 0) {
res_APDU_size = key_size; res_APDU_size = key_size;
}
} }
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
} } else if (p2 == ALGO_EC_DH || p2 == ALGO_EC_DH_XKEK) {
else if (p2 == ALGO_EC_DH || p2 == ALGO_EC_DH_XKEK) {
mbedtls_ecdh_context ctx; mbedtls_ecdh_context ctx;
if (wait_button_pressed() == true) //timeout if (wait_button_pressed() == true) { //timeout
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int key_size = file_get_size(ef); int key_size = file_get_size(ef);
uint8_t *kdata = (uint8_t *)calloc(1,key_size); uint8_t *kdata = (uint8_t *) calloc(1, key_size);
memcpy(kdata, file_get_data(ef), key_size); memcpy(kdata, file_get_data(ef), key_size);
if (mkek_decrypt(kdata, key_size) != 0) { if (mkek_decrypt(kdata, key_size) != 0) {
mbedtls_platform_zeroize(kdata, key_size); mbedtls_platform_zeroize(kdata, key_size);
@@ -100,9 +109,9 @@ int cmd_decrypt_asym() {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
r = -1; r = -1;
if (p2 == ALGO_EC_DH) if (p2 == ALGO_EC_DH) {
r = mbedtls_ecdh_read_public(&ctx, apdu.data-1, apdu.nc+1); r = mbedtls_ecdh_read_public(&ctx, apdu.data-1, apdu.nc+1);
else if (p2 == ALGO_EC_DH_XKEK) { } else if (p2 == ALGO_EC_DH_XKEK) {
size_t pub_len = 0; size_t pub_len = 0;
const uint8_t *pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len); const uint8_t *pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len);
if (pub) { if (pub) {
@@ -118,19 +127,22 @@ int cmd_decrypt_asym() {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
size_t olen = 0; size_t olen = 0;
r = mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL); r =
mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU, MBEDTLS_ECP_MAX_BYTES, random_gen,
NULL);
mbedtls_ecdh_free(&ctx); mbedtls_ecdh_free(&ctx);
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (p2 == ALGO_EC_DH) if (p2 == ALGO_EC_DH) {
res_APDU_size = olen; res_APDU_size = olen;
else { } else {
res_APDU_size = 0; res_APDU_size = 0;
size_t ext_len = 0; size_t ext_len = 0;
const uint8_t *ext = NULL; const uint8_t *ext = NULL;
if ((ext = cvc_get_ext(apdu.data, apdu.nc, &ext_len)) == NULL) if ((ext = cvc_get_ext(apdu.data, apdu.nc, &ext_len)) == NULL) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
uint8_t *p = NULL, *tag_data = NULL, *kdom_uid = NULL; uint8_t *p = NULL, *tag_data = NULL, *kdom_uid = NULL;
uint16_t tag = 0; uint16_t tag = 0;
size_t tag_len = 0, kdom_uid_len = 0; size_t tag_len = 0, kdom_uid_len = 0;
@@ -138,31 +150,40 @@ int cmd_decrypt_asym() {
if (tag == 0x73) { if (tag == 0x73) {
size_t oid_len = 0; size_t oid_len = 0;
uint8_t *oid_data = NULL; uint8_t *oid_data = NULL;
if (asn1_find_tag(tag_data, tag_len, 0x6, &oid_len, &oid_data) == true && oid_len == strlen(OID_ID_KEY_DOMAIN_UID) && memcmp(oid_data, OID_ID_KEY_DOMAIN_UID, strlen(OID_ID_KEY_DOMAIN_UID)) == 0) { if (asn1_find_tag(tag_data, tag_len, 0x6, &oid_len,
if (asn1_find_tag(tag_data, tag_len, 0x80, &kdom_uid_len, &kdom_uid) == false) &oid_data) == true &&
oid_len == strlen(OID_ID_KEY_DOMAIN_UID) &&
memcmp(oid_data, OID_ID_KEY_DOMAIN_UID,
strlen(OID_ID_KEY_DOMAIN_UID)) == 0) {
if (asn1_find_tag(tag_data, tag_len, 0x80, &kdom_uid_len,
&kdom_uid) == false) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
break; break;
} }
} }
} }
if (kdom_uid_len == 0 || kdom_uid == NULL) if (kdom_uid_len == 0 || kdom_uid == NULL) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
for (int n = 0; n < MAX_KEY_DOMAINS; n++) { for (int n = 0; n < MAX_KEY_DOMAINS; n++) {
file_t *tf = search_dynamic_file(EF_XKEK+n); file_t *tf = search_dynamic_file(EF_XKEK+n);
if (tf) { if (tf) {
if (file_get_size(tf) == kdom_uid_len && memcmp(file_get_data(tf), kdom_uid, kdom_uid_len) == 0) { if (file_get_size(tf) == kdom_uid_len &&
memcmp(file_get_data(tf), kdom_uid, kdom_uid_len) == 0) {
file_new(EF_DKEK+n); file_new(EF_DKEK+n);
if (store_dkek_key(n, res_APDU) != CCID_OK) if (store_dkek_key(n, res_APDU) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
return SW_OK(); return SW_OK();
} }
} }
} }
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
} } else {
else
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
}
decrement_key_counter(ef); decrement_key_counter(ef);
return SW_OK(); return SW_OK();
} }

View File

@@ -17,24 +17,29 @@
#include "sc_hsm.h" #include "sc_hsm.h"
int cmd_delete_file() { int cmd_delete_file()
{
file_t *ef = NULL; file_t *ef = NULL;
if (!isUserAuthenticated) if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
}
if (apdu.nc == 0) { if (apdu.nc == 0) {
ef = currentEF; ef = currentEF;
if (!(ef = search_dynamic_file(ef->fid))) if (!(ef = search_dynamic_file(ef->fid))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
else { } else {
uint16_t fid = (apdu.data[0] << 8) | apdu.data[1]; uint16_t fid = (apdu.data[0] << 8) | apdu.data[1];
if (!(ef = search_dynamic_file(fid))) if (!(ef = search_dynamic_file(fid))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
}
} }
if (!authenticate_action(ef, ACL_OP_DELETE_SELF)) if (!authenticate_action(ef, ACL_OP_DELETE_SELF)) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
if (delete_file(ef) != CCID_OK) }
if (delete_file(ef) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
return SW_OK(); return SW_OK();
} }

View File

@@ -22,33 +22,38 @@
#include "cvc.h" #include "cvc.h"
#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E #define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E
#define MOD_ADD( N ) \ #define MOD_ADD(N) \
while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \ while (mbedtls_mpi_cmp_mpi(&(N), &grp->P) >= 0) \
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) ) MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&(N), &(N), &grp->P))
static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp, static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp,
mbedtls_mpi *X, mbedtls_mpi *X,
const mbedtls_mpi *A, const mbedtls_mpi *A,
const mbedtls_mpi *B ) const mbedtls_mpi *B)
{ {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) ); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B));
MOD_ADD( *X ); MOD_ADD(*X);
cleanup: cleanup:
return( ret ); return ret;
} }
int cmd_derive_asym() { int cmd_derive_asym()
{
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t dest_id = P2(apdu); uint8_t dest_id = P2(apdu);
file_t *fkey; file_t *fkey;
if (!isUserAuthenticated) if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
if (!(fkey = search_dynamic_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) }
if (!(fkey = search_dynamic_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) }
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
if (apdu.nc == 0) }
if (apdu.nc == 0) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
if (apdu.data[0] == ALGO_EC_DERIVE) { if (apdu.data[0] == ALGO_EC_DERIVE) {
mbedtls_ecdsa_context ctx; mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx); mbedtls_ecdsa_init(&ctx);
@@ -57,8 +62,9 @@ int cmd_derive_asym() {
r = load_private_key_ecdsa(&ctx, fkey); r = load_private_key_ecdsa(&ctx, fkey);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx); mbedtls_ecdsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED) if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_mpi a, nd; mbedtls_mpi a, nd;
@@ -90,8 +96,8 @@ int cmd_derive_asym() {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_ecdsa_free(&ctx); mbedtls_ecdsa_free(&ctx);
} } else {
else
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
return SW_OK(); return SW_OK();
} }

View File

@@ -24,29 +24,42 @@ extern file_t *ef_puk_aut;
extern uint8_t challenge[256]; extern uint8_t challenge[256];
extern uint8_t challenge_len; extern uint8_t challenge_len;
int cmd_external_authenticate() { int cmd_external_authenticate()
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
if (ef_puk_aut == NULL) }
if (ef_puk_aut == NULL) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
if (apdu.nc == 0) }
if (apdu.nc == 0) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF); file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
if (!file_has_data(ef_puk)) if (!file_has_data(ef_puk)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
}
uint8_t *puk_data = file_get_data(ef_puk); uint8_t *puk_data = file_get_data(ef_puk);
uint8_t *input = (uint8_t *)calloc(dev_name_len+challenge_len, sizeof(uint8_t)), hash[32]; uint8_t *input = (uint8_t *) calloc(dev_name_len+challenge_len, sizeof(uint8_t)), hash[32];
memcpy(input, dev_name, dev_name_len); memcpy(input, dev_name, dev_name_len);
memcpy(input+dev_name_len, challenge, challenge_len); memcpy(input+dev_name_len, challenge, challenge_len);
hash256(input, dev_name_len+challenge_len, hash); hash256(input, dev_name_len+challenge_len, hash);
int r = puk_verify(apdu.data, apdu.nc, hash, 32, file_get_data(ef_puk_aut), file_get_size(ef_puk_aut)); int r =
puk_verify(apdu.data,
apdu.nc,
hash,
32,
file_get_data(ef_puk_aut),
file_get_size(ef_puk_aut));
free(input); free(input);
if (r != 0) if (r != 0) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
puk_status[ef_puk_aut->fid & (MAX_PUK-1)] = 1; puk_status[ef_puk_aut->fid & (MAX_PUK-1)] = 1;
uint8_t auts = 0; uint8_t auts = 0;
for (int i = 0; i < puk_data[0]; i++) for (int i = 0; i < puk_data[0]; i++) {
auts += puk_status[i]; auts += puk_status[i];
}
if (auts >= puk_data[2]) { if (auts >= puk_data[2]) {
isUserAuthenticated = true; isUserAuthenticated = true;
} }

View File

@@ -27,15 +27,18 @@
#include "mbedtls/hkdf.h" #include "mbedtls/hkdf.h"
#include "mbedtls/chachapoly.h" #include "mbedtls/chachapoly.h"
int cmd_extras() { int cmd_extras()
{
if (P1(apdu) == 0xA) { //datetime operations if (P1(apdu) == 0xA) { //datetime operations
if (P2(apdu) != 0x0) if (P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
if (apdu.nc == 0) { if (apdu.nc == 0) {
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
datetime_t dt; datetime_t dt;
if (!rtc_get_datetime(&dt)) if (!rtc_get_datetime(&dt)) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU[res_APDU_size++] = dt.year >> 8; res_APDU[res_APDU_size++] = dt.year >> 8;
res_APDU[res_APDU_size++] = dt.year & 0xff; res_APDU[res_APDU_size++] = dt.year & 0xff;
res_APDU[res_APDU_size++] = dt.month; res_APDU[res_APDU_size++] = dt.month;
@@ -45,10 +48,10 @@ int cmd_extras() {
res_APDU[res_APDU_size++] = dt.min; res_APDU[res_APDU_size++] = dt.min;
res_APDU[res_APDU_size++] = dt.sec; res_APDU[res_APDU_size++] = dt.sec;
#endif #endif
} } else {
else { if (apdu.nc != 8) {
if (apdu.nc != 8)
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
datetime_t dt; datetime_t dt;
dt.year = (apdu.data[0] << 8) | (apdu.data[1]); dt.year = (apdu.data[0] << 8) | (apdu.data[1]);
@@ -58,29 +61,29 @@ int cmd_extras() {
dt.hour = apdu.data[5]; dt.hour = apdu.data[5];
dt.min = apdu.data[6]; dt.min = apdu.data[6];
dt.sec = apdu.data[7]; dt.sec = apdu.data[7];
if (!rtc_set_datetime(&dt)) if (!rtc_set_datetime(&dt)) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
#endif #endif
} }
} } else if (P1(apdu) == 0x6) { //dynamic options
else if (P1(apdu) == 0x6) { //dynamic options if (P2(apdu) != 0x0) {
if (P2(apdu) != 0x0)
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
if (apdu.nc > sizeof(uint8_t)) }
if (apdu.nc > sizeof(uint8_t)) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
if (apdu.nc == 0) { if (apdu.nc == 0) {
res_APDU[res_APDU_size++] = opts >> 8; res_APDU[res_APDU_size++] = opts >> 8;
res_APDU[res_APDU_size++] = opts & 0xff; res_APDU[res_APDU_size++] = opts & 0xff;
} } else {
else {
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) }; uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
flash_write_data_to_file(tf, newopts, sizeof(newopts)); flash_write_data_to_file(tf, newopts, sizeof(newopts));
low_flash_available(); low_flash_available();
} }
} } else if (P1(apdu) == 0x3A) { // secure lock
else if (P1(apdu) == 0x3A) { // secure lock
if (apdu.nc == 0) { if (apdu.nc == 0) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
@@ -88,9 +91,16 @@ int cmd_extras() {
mbedtls_ecdh_context hkey; mbedtls_ecdh_context hkey;
mbedtls_ecdh_init(&hkey); mbedtls_ecdh_init(&hkey);
mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1); mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1);
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_gen, NULL); int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp,
&hkey.ctx.mbed_ecdh.d,
&hkey.ctx.mbed_ecdh.Q,
random_gen,
NULL);
mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1); mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1);
ret = mbedtls_ecp_point_read_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Qp, apdu.data, apdu.nc); ret = mbedtls_ecp_point_read_binary(&hkey.ctx.mbed_ecdh.grp,
&hkey.ctx.mbed_ecdh.Qp,
apdu.data,
apdu.nc);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdh_free(&hkey); mbedtls_ecdh_free(&hkey);
return SW_WRONG_DATA(); return SW_WRONG_DATA();
@@ -99,30 +109,48 @@ int cmd_extras() {
uint8_t buf[MBEDTLS_ECP_MAX_BYTES]; uint8_t buf[MBEDTLS_ECP_MAX_BYTES];
size_t olen = 0; size_t olen = 0;
ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL); ret = mbedtls_ecdh_calc_secret(&hkey,
&olen,
buf,
MBEDTLS_ECP_MAX_BYTES,
random_gen,
NULL);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdh_free(&hkey); mbedtls_ecdh_free(&hkey);
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(buf, sizeof(buf));
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
ret = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0, buf, olen, mse.Qpt, sizeof(mse.Qpt), mse.key_enc, sizeof(mse.key_enc)); ret = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
NULL,
0,
buf,
olen,
mse.Qpt,
sizeof(mse.Qpt),
mse.key_enc,
sizeof(mse.key_enc));
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(buf, sizeof(buf));
if (ret != 0) { if (ret != 0) {
mbedtls_ecdh_free(&hkey); mbedtls_ecdh_free(&hkey);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = mbedtls_ecp_point_write_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, res_APDU, 4096); ret = mbedtls_ecp_point_write_binary(&hkey.ctx.mbed_ecdh.grp,
&hkey.ctx.mbed_ecdh.Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&olen,
res_APDU,
4096);
mbedtls_ecdh_free(&hkey); mbedtls_ecdh_free(&hkey);
if (ret != 0) { if (ret != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mse.init = true; mse.init = true;
res_APDU_size = olen; res_APDU_size = olen;
} } else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) {
else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) { if (mse.init == false) {
if (mse.init == false)
return SW_COMMAND_NOT_ALLOWED(); return SW_COMMAND_NOT_ALLOWED();
}
int ret = mse_decrypt_ct(apdu.data, apdu.nc); int ret = mse_decrypt_ct(apdu.data, apdu.nc);
if (ret != 0) { if (ret != 0) {
@@ -131,12 +159,13 @@ int cmd_extras() {
if (P2(apdu) == 0x02 || P2(apdu) == 0x04) { // Enable if (P2(apdu) == 0x02 || P2(apdu) == 0x04) { // Enable
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
uint8_t newopts[] = { opts >> 8, (opts & 0xff) }; uint8_t newopts[] = { opts >> 8, (opts & 0xff) };
if ((P2(apdu) == 0x02 && !(opts & HSM_OPT_SECURE_LOCK)) || (P2(apdu) == 0x04 && (opts & HSM_OPT_SECURE_LOCK))) { if ((P2(apdu) == 0x02 && !(opts & HSM_OPT_SECURE_LOCK)) ||
(P2(apdu) == 0x04 && (opts & HSM_OPT_SECURE_LOCK))) {
uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO }; uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO };
for (int t = 0; t < sizeof(tfids)/sizeof(uint16_t); t++) { for (int t = 0; t < sizeof(tfids)/sizeof(uint16_t); t++) {
file_t *tf = search_by_fid(tfids[t], NULL, SPECIFY_EF); file_t *tf = search_by_fid(tfids[t], NULL, SPECIFY_EF);
if (tf) { if (tf) {
uint8_t *tmp = (uint8_t *)calloc(1, file_get_size(tf)); uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(tf));
memcpy(tmp, file_get_data(tf), file_get_size(tf)); memcpy(tmp, file_get_data(tf), file_get_size(tf));
for (int i = 0; i < MKEK_KEY_SIZE; i++) { for (int i = 0; i < MKEK_KEY_SIZE; i++) {
MKEK_KEY(tmp)[i] ^= apdu.data[i]; MKEK_KEY(tmp)[i] ^= apdu.data[i];
@@ -146,21 +175,21 @@ int cmd_extras() {
} }
} }
} }
if (P2(apdu) == 0x02) if (P2(apdu) == 0x02) {
newopts[0] |= HSM_OPT_SECURE_LOCK >> 8; newopts[0] |= HSM_OPT_SECURE_LOCK >> 8;
else if (P2(apdu) == 0x04) } else if (P2(apdu) == 0x04) {
newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8; newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8;
}
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
flash_write_data_to_file(tf, newopts, sizeof(newopts)); flash_write_data_to_file(tf, newopts, sizeof(newopts));
low_flash_available(); low_flash_available();
} } else if (P2(apdu) == 0x03) {
else if (P2(apdu) == 0x03) {
memcpy(mkek_mask, apdu.data, apdu.nc); memcpy(mkek_mask, apdu.data, apdu.nc);
has_mkek_mask = true; has_mkek_mask = true;
} }
} }
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
return SW_OK(); return SW_OK();
} }

View File

@@ -24,7 +24,8 @@
#include "eac.h" #include "eac.h"
#include "files.h" #include "files.h"
int cmd_general_authenticate() { int cmd_general_authenticate()
{
if (P1(apdu) == 0x0 && P2(apdu) == 0x0) { if (P1(apdu) == 0x0 && P2(apdu) == 0x0) {
if (apdu.data[0] == 0x7C) { if (apdu.data[0] == 0x7C) {
int r = 0; int r = 0;
@@ -40,8 +41,9 @@ int cmd_general_authenticate() {
} }
} }
file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
if (!fkey) if (!fkey) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
mbedtls_ecdsa_context ectx; mbedtls_ecdsa_context ectx;
mbedtls_ecdsa_init(&ectx); mbedtls_ecdsa_init(&ectx);
r = load_private_key_ecdsa(&ectx, fkey); r = load_private_key_ecdsa(&ectx, fkey);
@@ -71,7 +73,12 @@ int cmd_general_authenticate() {
} }
size_t olen = 0; size_t olen = 0;
uint8_t derived[MBEDTLS_ECP_MAX_BYTES]; uint8_t derived[MBEDTLS_ECP_MAX_BYTES];
r = mbedtls_ecdh_calc_secret(&ctx, &olen, derived, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL); r = mbedtls_ecdh_calc_secret(&ctx,
&olen,
derived,
MBEDTLS_ECP_MAX_BYTES,
random_gen,
NULL);
mbedtls_ecdh_free(&ctx); mbedtls_ecdh_free(&ctx);
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -79,10 +86,11 @@ int cmd_general_authenticate() {
sm_derive_all_keys(derived, olen); sm_derive_all_keys(derived, olen);
uint8_t *t = (uint8_t *)calloc(1, pubkey_len+16); uint8_t *t = (uint8_t *) calloc(1, pubkey_len+16);
memcpy(t, "\x7F\x49\x4F\x06\x0A", 5); memcpy(t, "\x7F\x49\x4F\x06\x0A", 5);
if (sm_get_protocol() == MSE_AES) if (sm_get_protocol() == MSE_AES) {
memcpy(t+5, OID_ID_CA_ECDH_AES_CBC_CMAC_128, 10); memcpy(t+5, OID_ID_CA_ECDH_AES_CBC_CMAC_128, 10);
}
t[15] = 0x86; t[15] = 0x86;
memcpy(t+16, pubkey, pubkey_len); memcpy(t+16, pubkey, pubkey_len);
@@ -98,8 +106,9 @@ int cmd_general_authenticate() {
r = sm_sign(t, pubkey_len+16, res_APDU+res_APDU_size); r = sm_sign(t, pubkey_len+16, res_APDU+res_APDU_size);
free(t); free(t);
if (r != CCID_OK) if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU_size += 8; res_APDU_size += 8;
} }
} }

View File

@@ -27,7 +27,8 @@
extern void scan_all(); extern void scan_all();
extern char __StackLimit; extern char __StackLimit;
int heapLeft() { int heapLeft()
{
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
char *p = malloc(256); // try to avoid undue fragmentation char *p = malloc(256); // try to avoid undue fragmentation
int left = &__StackLimit - p; int left = &__StackLimit - p;
@@ -38,7 +39,8 @@ int heapLeft() {
return left; return left;
} }
int cmd_initialize() { int cmd_initialize()
{
if (apdu.nc > 0) { if (apdu.nc > 0) {
uint8_t mkek[MKEK_SIZE]; uint8_t mkek[MKEK_SIZE];
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
@@ -52,8 +54,7 @@ int cmd_initialize() {
if (tag == 0x80) { //options if (tag == 0x80) { //options
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
flash_write_data_to_file(tf, tag_data, tag_len); flash_write_data_to_file(tf, tag_data, tag_len);
} } else if (tag == 0x81) { //user pin
else if (tag == 0x81) { //user pin
if (file_pin1 && file_pin1->data) { if (file_pin1 && file_pin1->data) {
uint8_t dhash[33]; uint8_t dhash[33];
dhash[0] = tag_len; dhash[0] = tag_len;
@@ -62,8 +63,7 @@ int cmd_initialize() {
hash_multi(tag_data, tag_len, session_pin); hash_multi(tag_data, tag_len, session_pin);
has_session_pin = true; has_session_pin = true;
} }
} } else if (tag == 0x82) { //sopin pin
else if (tag == 0x82) { //sopin pin
if (file_sopin && file_sopin->data) { if (file_sopin && file_sopin->data) {
uint8_t dhash[33]; uint8_t dhash[33];
dhash[0] = tag_len; dhash[0] = tag_len;
@@ -72,8 +72,7 @@ int cmd_initialize() {
hash_multi(tag_data, tag_len, session_sopin); hash_multi(tag_data, tag_len, session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
} } else if (tag == 0x91) { //retries user pin
else if (tag == 0x91) { //retries user pin
file_t *tf = search_by_fid(0x1082, NULL, SPECIFY_EF); file_t *tf = search_by_fid(0x1082, NULL, SPECIFY_EF);
if (tf && tf->data) { if (tf && tf->data) {
flash_write_data_to_file(tf, tag_data, tag_len); flash_write_data_to_file(tf, tag_data, tag_len);
@@ -81,8 +80,7 @@ int cmd_initialize() {
if (file_retries_pin1 && file_retries_pin1->data) { if (file_retries_pin1 && file_retries_pin1->data) {
flash_write_data_to_file(file_retries_pin1, tag_data, tag_len); flash_write_data_to_file(file_retries_pin1, tag_data, tag_len);
} }
} } else if (tag == 0x92) {
else if (tag == 0x92) {
dkeks = tag_data; dkeks = tag_data;
file_t *tf = file_new(EF_DKEK); file_t *tf = file_new(EF_DKEK);
if (!tf) { if (!tf) {
@@ -90,14 +88,13 @@ int cmd_initialize() {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
flash_write_data_to_file(tf, NULL, 0); flash_write_data_to_file(tf, NULL, 0);
} } else if (tag == 0x93) {
else if (tag == 0x93) {
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF); file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
if (!ef_puk) { if (!ef_puk) {
release_mkek(mkek); release_mkek(mkek);
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
uint8_t pk_status[4], puks = MIN(tag_data[0],MAX_PUK); uint8_t pk_status[4], puks = MIN(tag_data[0], MAX_PUK);
memset(pk_status, 0, sizeof(pk_status)); memset(pk_status, 0, sizeof(pk_status));
pk_status[0] = puks; pk_status[0] = puks;
pk_status[1] = puks; pk_status[1] = puks;
@@ -111,17 +108,16 @@ int cmd_initialize() {
} }
flash_write_data_to_file(tf, NULL, 0); flash_write_data_to_file(tf, NULL, 0);
} }
} } else if (tag == 0x97) {
else if (tag == 0x97) {
kds = tag_data; kds = tag_data;
/* /*
for (int i = 0; i < MIN(*kds,MAX_KEY_DOMAINS); i++) { for (int i = 0; i < MIN(*kds,MAX_KEY_DOMAINS); i++) {
file_t *tf = file_new(EF_DKEK+i); file_t *tf = file_new(EF_DKEK+i);
if (!tf) if (!tf)
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
flash_write_data_to_file(tf, NULL, 0); flash_write_data_to_file(tf, NULL, 0);
} }
*/ */
} }
} }
file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF); file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF);
@@ -129,8 +125,9 @@ int cmd_initialize() {
release_mkek(mkek); release_mkek(mkek);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (ret_mkek != CCID_OK) if (ret_mkek != CCID_OK) {
ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same
}
if (store_mkek(ret_mkek == CCID_OK ? mkek : NULL) != CCID_OK) { if (store_mkek(ret_mkek == CCID_OK ? mkek : NULL) != CCID_OK) {
release_mkek(mkek); release_mkek(mkek);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -139,35 +136,39 @@ int cmd_initialize() {
if (dkeks) { if (dkeks) {
if (*dkeks > 0) { if (*dkeks > 0) {
uint16_t d = *dkeks; uint16_t d = *dkeks;
if (flash_write_data_to_file(tf_kd, (const uint8_t *)&d, sizeof(d)) != CCID_OK) if (flash_write_data_to_file(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
else { } else {
int r = save_dkek_key(0, random_bytes_get(32)); int r = save_dkek_key(0, random_bytes_get(32));
if (r != CCID_OK) if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
uint16_t d = 0x0101; uint16_t d = 0x0101;
if (flash_write_data_to_file(tf_kd, (const uint8_t *)&d, sizeof(d)) != CCID_OK) if (flash_write_data_to_file(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
} }
} } else {
else {
uint16_t d = 0x0000; uint16_t d = 0x0000;
if (flash_write_data_to_file(tf_kd, (const uint8_t *)&d, sizeof(d)) != CCID_OK) if (flash_write_data_to_file(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
} }
if (kds) { if (kds) {
uint8_t t[MAX_KEY_DOMAINS*2], k = MIN(*kds,MAX_KEY_DOMAINS); uint8_t t[MAX_KEY_DOMAINS*2], k = MIN(*kds, MAX_KEY_DOMAINS);
memset(t, 0xff, 2*k); memset(t, 0xff, 2*k);
if (flash_write_data_to_file(tf_kd, t, 2*k) != CCID_OK) if (flash_write_data_to_file(tf_kd, t, 2*k) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
} }
/* When initialized, it has all credentials */ /* When initialized, it has all credentials */
isUserAuthenticated = true; isUserAuthenticated = true;
/* Create terminal private key */ /* Create terminal private key */
file_t *fdkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); file_t *fdkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
if (!fdkey) if (!fdkey) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
int ret = 0; int ret = 0;
if (ret_mkek != CCID_OK || !file_has_data(fdkey)) { if (ret_mkek != CCID_OK || !file_has_data(fdkey)) {
mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_context ecdsa;
@@ -193,19 +194,28 @@ int cmd_initialize() {
file_t *fpk = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF); file_t *fpk = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF);
ret = flash_write_data_to_file(fpk, res_APDU, cvc_len); ret = flash_write_data_to_file(fpk, res_APDU, cvc_len);
if (ret != 0) if (ret != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
const uint8_t *keyid = (const uint8_t *)"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", *label = (const uint8_t *)"ESTERMHSM"; const uint8_t *keyid =
size_t prkd_len = asn1_build_prkd_ecc(label, strlen((const char *)label), keyid, 20, 192, res_APDU, 4096); (const uint8_t *) "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0",
*label = (const uint8_t *) "ESTERMHSM";
size_t prkd_len = asn1_build_prkd_ecc(label,
strlen((const char *) label),
keyid,
20,
192,
res_APDU,
4096);
fpk = search_by_fid(EF_PRKD_DEV, NULL, SPECIFY_EF); fpk = search_by_fid(EF_PRKD_DEV, NULL, SPECIFY_EF);
ret = flash_write_data_to_file(fpk, res_APDU, prkd_len); ret = flash_write_data_to_file(fpk, res_APDU, prkd_len);
} }
if (ret != 0) if (ret != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
low_flash_available(); low_flash_available();
} } else { //free memory bytes request
else { //free memory bytes request
int heap_left = heapLeft(); int heap_left = heapLeft();
res_APDU[0] = ((heap_left >> 24) & 0xff); res_APDU[0] = ((heap_left >> 24) & 0xff);
res_APDU[1] = ((heap_left >> 16) & 0xff); res_APDU[1] = ((heap_left >> 16) & 0xff);

View File

@@ -21,36 +21,47 @@
#include "kek.h" #include "kek.h"
#include "files.h" #include "files.h"
uint8_t get_key_domain(file_t *fkey) { uint8_t get_key_domain(file_t *fkey)
{
size_t tag_len = 0; size_t tag_len = 0;
const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len); const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len);
if (meta_tag) if (meta_tag) {
return *meta_tag; return *meta_tag;
}
return 0xff; return 0xff;
} }
int cmd_key_domain() { int cmd_key_domain()
{
//if (dkeks == 0) //if (dkeks == 0)
// return SW_COMMAND_NOT_ALLOWED(); // return SW_COMMAND_NOT_ALLOWED();
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
if ((has_session_pin == false || isUserAuthenticated == false) && apdu.nc > 0 && !(p1 == 0x0 && p2 == 0x0)) if ((has_session_pin == false || isUserAuthenticated == false) && apdu.nc > 0 &&
!(p1 == 0x0 && p2 == 0x0)) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
if (p2 >= MAX_KEY_DOMAINS) }
if (p2 >= MAX_KEY_DOMAINS) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
}
file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF); file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF);
if (!tf_kd) if (!tf_kd) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
uint16_t tf_kd_size = file_get_size(tf_kd); uint16_t tf_kd_size = file_get_size(tf_kd);
if (tf_kd_size == 0) if (tf_kd_size == 0) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2*p2] : 0, current_dkeks = kdata ? kdata[2*p2+1] : 0; }
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2*p2] : 0,
current_dkeks = kdata ? kdata[2*p2+1] : 0;
if (p1 == 0x0) { //dkek import if (p1 == 0x0) { //dkek import
if (apdu.nc > 0) { if (apdu.nc > 0) {
file_t *tf = file_new(EF_DKEK+p2); file_t *tf = file_new(EF_DKEK+p2);
if (!tf) if (!tf) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
if (apdu.nc < 32) }
if (apdu.nc < 32) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
if (current_dkeks == dkeks) { if (current_dkeks == dkeks) {
return SW_COMMAND_NOT_ALLOWED(); return SW_COMMAND_NOT_ALLOWED();
} }
@@ -65,25 +76,28 @@ int cmd_key_domain() {
uint8_t t[MAX_KEY_DOMAINS*2]; uint8_t t[MAX_KEY_DOMAINS*2];
memcpy(t, kdata, tf_kd_size); memcpy(t, kdata, tf_kd_size);
t[2*p2+1] = current_dkeks; t[2*p2+1] = current_dkeks;
if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
low_flash_available(); low_flash_available();
} } else {
else {
file_t *tf = search_dynamic_file(EF_XKEK+p2); file_t *tf = search_dynamic_file(EF_XKEK+p2);
if (2*p2 >= tf_kd_size) if (2*p2 >= tf_kd_size) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
if (current_dkeks == 0xff && !tf) //XKEK have always 0xff }
if (current_dkeks == 0xff && !tf) { //XKEK have always 0xff
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
}
} }
} } else if (p1 == 0x1 || p1 == 0x3 || p1 == 0x4) { //key domain setup
else if (p1 == 0x1 || p1 == 0x3 || p1 == 0x4) { //key domain setup if (p1 == 0x1 && apdu.nc != 1) {
if (p1 == 0x1 && apdu.nc != 1)
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
if (p1 == 0x3) { //if key domain is not empty, command is denied if (p1 == 0x3) { //if key domain is not empty, command is denied
for (int i = 0; i < dynamic_files; i++) { for (int i = 0; i < dynamic_files; i++) {
if (get_key_domain(&dynamic_file[i]) == p2) if (get_key_domain(&dynamic_file[i]) == p2) {
return SW_FILE_EXISTS(); return SW_FILE_EXISTS();
}
} }
} }
uint8_t t[MAX_KEY_DOMAINS*2]; uint8_t t[MAX_KEY_DOMAINS*2];
@@ -91,57 +105,64 @@ int cmd_key_domain() {
if (p1 == 0x1) { if (p1 == 0x1) {
t[2*p2] = dkeks = apdu.data[0]; t[2*p2] = dkeks = apdu.data[0];
t[2*p2+1] = current_dkeks = 0; t[2*p2+1] = current_dkeks = 0;
} } else if (p1 == 0x3) {
else if (p1 == 0x3) {
t[2*p2] = dkeks = 0xff; t[2*p2] = dkeks = 0xff;
t[2*p2+1] = 0xff; t[2*p2+1] = 0xff;
} } else if (p1 == 0x4) {
else if (p1 == 0x4) {
t[2*p2+1] = current_dkeks = 0; t[2*p2+1] = current_dkeks = 0;
} }
if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) if (flash_write_data_to_file(tf_kd, t, tf_kd_size) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
file_t *tf = NULL; file_t *tf = NULL;
if ((tf = search_dynamic_file(EF_DKEK+p2))) { if ((tf = search_dynamic_file(EF_DKEK+p2))) {
if (delete_file(tf) != CCID_OK) if (delete_file(tf) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
} }
if (p1 == 0x3 && (tf = search_dynamic_file(EF_XKEK+p2))) { if (p1 == 0x3 && (tf = search_dynamic_file(EF_XKEK+p2))) {
if (delete_file(tf) != CCID_OK) if (delete_file(tf) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
} }
low_flash_available(); low_flash_available();
if (p1 == 0x3) if (p1 == 0x3) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
else if (p1 == 0x2) { //XKEK Key Domain creation } else if (p1 == 0x2) { //XKEK Key Domain creation
if (apdu.nc > 0) { if (apdu.nc > 0) {
size_t pub_len = 0; size_t pub_len = 0;
file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF); file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF);
if (!fterm) if (!fterm) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
const uint8_t *pub = cvc_get_pub(file_get_data(fterm), file_get_size(fterm), &pub_len); const uint8_t *pub = cvc_get_pub(file_get_data(fterm), file_get_size(fterm), &pub_len);
if (!pub) if (!pub) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
size_t t86_len = 0; size_t t86_len = 0;
const uint8_t *t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86); const uint8_t *t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86);
if (!t86 || t86[0] != 0x4) if (!t86 || t86[0] != 0x4) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
size_t t54_len = 0; size_t t54_len = 0;
const uint8_t *t54 = cvc_get_field(apdu.data, apdu.nc, &t54_len, 0x54); const uint8_t *t54 = cvc_get_field(apdu.data, apdu.nc, &t54_len, 0x54);
if (!t54) if (!t54) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
uint8_t hash[32], *input = (uint8_t *)calloc(1, (t86_len-1)/2+1); }
uint8_t hash[32], *input = (uint8_t *) calloc(1, (t86_len-1)/2+1);
input[0] = 0x54; input[0] = 0x54;
memcpy(input+1, t86+1, (t86_len-1)/2); memcpy(input+1, t86+1, (t86_len-1)/2);
hash256(input, (t86_len-1)/2+1, hash); hash256(input, (t86_len-1)/2+1, hash);
free(input); free(input);
int r = puk_verify(t54, t54_len, hash, 32, apdu.data, apdu.nc); int r = puk_verify(t54, t54_len, hash, 32, apdu.data, apdu.nc);
if (r != 0) if (r != 0) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
file_t *tf = file_new(EF_XKEK+p2); file_t *tf = file_new(EF_XKEK+p2);
if (!tf) if (!tf) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
}
//All checks done. Get Key Domain UID //All checks done. Get Key Domain UID
pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len); pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len);
@@ -154,10 +175,10 @@ int cmd_key_domain() {
} }
} }
} }
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
memset(res_APDU,0,10); }
memset(res_APDU, 0, 10);
res_APDU[0] = dkeks; res_APDU[0] = dkeks;
res_APDU[1] = dkeks > current_dkeks ? dkeks-current_dkeks : 0; res_APDU[1] = dkeks > current_dkeks ? dkeks-current_dkeks : 0;
dkek_kcv(p2, res_APDU+2); dkek_kcv(p2, res_APDU+2);

View File

@@ -19,34 +19,40 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "random.h" #include "random.h"
int cmd_key_gen() { int cmd_key_gen()
{
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
uint8_t key_size = 32; uint8_t key_size = 32;
int r; int r;
if (!isUserAuthenticated) if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
if (p2 == 0xB2) }
if (p2 == 0xB2) {
key_size = 32; key_size = 32;
else if (p2 == 0xB1) } else if (p2 == 0xB1) {
key_size = 24; key_size = 24;
else if (p2 == 0xB0) } else if (p2 == 0xB0) {
key_size = 16; key_size = 16;
}
//at this moment, we do not use the template, as only CBC is supported by the driver (encrypt, decrypt and CMAC) //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 uint8_t aes_key[32]; //maximum AES key size
memcpy(aes_key, random_bytes_get(key_size), key_size); memcpy(aes_key, random_bytes_get(key_size), key_size);
int aes_type = 0x0; int aes_type = 0x0;
if (key_size == 16) if (key_size == 16) {
aes_type = HSM_KEY_AES_128; aes_type = HSM_KEY_AES_128;
else if (key_size == 24) } else if (key_size == 24) {
aes_type = HSM_KEY_AES_192; aes_type = HSM_KEY_AES_192;
else if (key_size == 32) } else if (key_size == 32) {
aes_type = HSM_KEY_AES_256; aes_type = HSM_KEY_AES_256;
}
r = store_keys(aes_key, aes_type, key_id); r = store_keys(aes_key, aes_type, key_id);
if (r != CCID_OK) if (r != CCID_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
if (find_and_store_meta_key(key_id) != CCID_OK) }
if (find_and_store_meta_key(key_id) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
low_flash_available(); low_flash_available();
return SW_OK(); return SW_OK();
} }

View File

@@ -20,17 +20,21 @@
#include "kek.h" #include "kek.h"
#include "cvc.h" #include "cvc.h"
int cmd_key_unwrap() { int cmd_key_unwrap()
{
int key_id = P1(apdu), r = 0; 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();
}
int key_type = dkek_type_key(apdu.data); int key_type = dkek_type_key(apdu.data);
uint8_t kdom = -1, *allowed = NULL; uint8_t kdom = -1, *allowed = NULL;
size_t allowed_len = 0; 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);
@@ -50,13 +54,12 @@ int cmd_key_unwrap() {
if (r != CCID_OK) { if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} } else if (key_type == HSM_KEY_EC) {
else if (key_type == HSM_KEY_EC) {
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, &allowed, &allowed_len); 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);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -70,24 +73,30 @@ int cmd_key_unwrap() {
if (r != CCID_OK) { if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} } else if (key_type == HSM_KEY_AES) {
else if (key_type == HSM_KEY_AES) {
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, &allowed, &allowed_len); r = dkek_decode_key(++kdom,
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); 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) { if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (key_size == 32) if (key_size == 32) {
aes_type = HSM_KEY_AES_256; aes_type = HSM_KEY_AES_256;
else if (key_size == 24) } else if (key_size == 24) {
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;
else } else {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
r = store_keys(aes_key, aes_type, key_id); r = store_keys(aes_key, aes_type, key_id);
if (r != CCID_OK) { if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -95,7 +104,7 @@ int cmd_key_unwrap() {
} }
if ((allowed != NULL && allowed_len > 0) || kdom >= 0) { if ((allowed != NULL && allowed_len > 0) || kdom >= 0) {
size_t meta_len = (allowed_len > 0 ? 2+allowed_len : 0) + (kdom >= 0 ? 3 : 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; uint8_t *meta = (uint8_t *) calloc(1, meta_len), *m = meta;
if (allowed_len > 0) { if (allowed_len > 0) {
*m++ = 0x91; *m++ = 0x91;
*m++ = allowed_len; *m++ = allowed_len;
@@ -108,14 +117,16 @@ int cmd_key_unwrap() {
} }
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len); r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
free(meta); free(meta);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
} }
if (res_APDU_size > 0) { if (res_APDU_size > 0) {
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id); file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
r = flash_write_data_to_file(fpk, res_APDU, res_APDU_size); r = flash_write_data_to_file(fpk, res_APDU, res_APDU_size);
if (r != 0) if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
low_flash_available(); low_flash_available();
res_APDU_size = 0; res_APDU_size = 0;
} }

View File

@@ -22,21 +22,28 @@
extern uint8_t get_key_domain(file_t *fkey); extern uint8_t get_key_domain(file_t *fkey);
int cmd_key_wrap() { int cmd_key_wrap()
{
int key_id = P1(apdu), r = 0; int key_id = P1(apdu), r = 0;
if (P2(apdu) != 0x92) if (P2(apdu) != 0x92) {
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); file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
printf("%d %p\n", key_id, ef);
uint8_t kdom = get_key_domain(ef); uint8_t kdom = get_key_domain(ef);
if (!ef) if (!ef) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
if (key_has_purpose(ef, ALGO_WRAP) == false) }
if (key_has_purpose(ef, ALGO_WRAP) == false) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id); file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id);
if (!prkd) if (!prkd) {
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; size_t tag_len = 0;
@@ -47,47 +54,50 @@ int cmd_key_wrap() {
r = load_private_key_rsa(&ctx, ef); r = load_private_key_rsa(&ctx, ef);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED) if (r == CCID_VERIFICATION_FAILED) {
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, meta_tag, tag_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) {
mbedtls_ecdsa_context ctx; mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx); mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef); r = load_private_key_ecdsa(&ctx, ef);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx); mbedtls_ecdsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED) if (r == CCID_VERIFICATION_FAILED) {
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, meta_tag, tag_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) {
uint8_t kdata[32]; //maximum AES key size uint8_t kdata[32]; //maximum AES key size
if (wait_button_pressed() == true) //timeout if (wait_button_pressed() == true) { //timeout
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int key_size = file_get_size(ef), aes_type = HSM_KEY_AES; int key_size = file_get_size(ef), aes_type = HSM_KEY_AES;
memcpy(kdata, file_get_data(ef), key_size); memcpy(kdata, file_get_data(ef), key_size);
if (mkek_decrypt(kdata, key_size) != 0) { if (mkek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (key_size == 32) if (key_size == 32) {
aes_type = HSM_KEY_AES_256; aes_type = HSM_KEY_AES_256;
else if (key_size == 24) } else if (key_size == 24) {
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, meta_tag, tag_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) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
res_APDU_size = wrap_len; res_APDU_size = wrap_len;
return SW_OK(); return SW_OK();
} }

View File

@@ -24,15 +24,18 @@
#include "random.h" #include "random.h"
#include "kek.h" #include "kek.h"
int cmd_keypair_gen() { int cmd_keypair_gen()
{
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
if (!isUserAuthenticated) if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
}
int ret = 0; int ret = 0;
size_t tout = 0; size_t tout = 0;
//sc_asn1_print_tags(apdu.data, apdu.nc); //sc_asn1_print_tags(apdu.data, apdu.nc);
uint8_t *p = NULL; uint8_t *p = NULL;
//DEBUG_DATA(apdu.data,apdu.nc);
if (asn1_find_tag(apdu.data, apdu.nc, 0x7f49, &tout, &p) && tout > 0 && p != NULL) { if (asn1_find_tag(apdu.data, apdu.nc, 0x7f49, &tout, &p) && tout > 0 && p != NULL) {
size_t oid_len = 0; size_t oid_len = 0;
uint8_t *oid = NULL; uint8_t *oid = NULL;
@@ -55,32 +58,35 @@ int cmd_keypair_gen() {
key_size = (key_size << 8) | *dt++; key_size = (key_size << 8) | *dt++;
} }
} }
printf("KEYPAIR RSA %lu (%lx)\r\n",(unsigned long)key_size,(unsigned long)exponent); printf("KEYPAIR RSA %lu (%lx)\r\n",
(unsigned long) key_size,
(unsigned long) exponent);
mbedtls_rsa_context rsa; mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa); mbedtls_rsa_init(&rsa);
uint8_t index = 0; uint8_t index = 0;
ret = mbedtls_rsa_gen_key(&rsa, random_gen, &index, key_size, exponent); ret = mbedtls_rsa_gen_key(&rsa, random_gen, &index, key_size, exponent);
if (ret != 0) { if (ret != 0) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if ((res_APDU_size = asn1_cvc_aut(&rsa, HSM_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) { if ((res_APDU_size =
asn1_cvc_aut(&rsa, HSM_KEY_RSA, res_APDU, 4096, NULL, 0)) == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = store_keys(&rsa, HSM_KEY_RSA, key_id); ret = store_keys(&rsa, HSM_KEY_RSA, key_id);
if (ret != CCID_OK) { if (ret != CCID_OK) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
} } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, MIN(oid_len, 10)) == 0) { //ECC
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256,MIN(oid_len,10)) == 0) { //ECC
size_t prime_len; size_t prime_len;
uint8_t *prime = NULL; uint8_t *prime = NULL;
if (asn1_find_tag(p, tout, 0x81, &prime_len, &prime) != true) if (asn1_find_tag(p, tout, 0x81, &prime_len, &prime) != true) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(prime, prime_len); mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(prime, prime_len);
printf("KEYPAIR ECC %d\r\n",ec_id); printf("KEYPAIR ECC %d\r\n", ec_id);
if (ec_id == MBEDTLS_ECP_DP_NONE) { if (ec_id == MBEDTLS_ECP_DP_NONE) {
return SW_FUNC_NOT_SUPPORTED(); return SW_FUNC_NOT_SUPPORTED();
} }
@@ -99,15 +105,19 @@ int cmd_keypair_gen() {
if (p91[n] == ALGO_EC_DH_XKEK) { if (p91[n] == ALGO_EC_DH_XKEK) {
size_t l92 = 0; size_t l92 = 0;
uint8_t *p92 = NULL; uint8_t *p92 = NULL;
if (!asn1_find_tag(apdu.data, apdu.nc, 0x92, &l92, &p92) || p92 == NULL || l92 == 0) if (!asn1_find_tag(apdu.data, apdu.nc, 0x92, &l92,
&p92) || p92 == NULL || l92 == 0) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
if (p92[0] > MAX_KEY_DOMAINS) }
if (p92[0] > MAX_KEY_DOMAINS) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
file_t *tf_xkek = search_dynamic_file(EF_XKEK+p92[0]); file_t *tf_xkek = search_dynamic_file(EF_XKEK+p92[0]);
if (!tf_xkek) if (!tf_xkek) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
ext_len = 2+2+strlen(OID_ID_KEY_DOMAIN_UID)+2+file_get_size(tf_xkek); ext_len = 2+2+strlen(OID_ID_KEY_DOMAIN_UID)+2+file_get_size(tf_xkek);
ext = (uint8_t *)calloc(1, ext_len); ext = (uint8_t *) calloc(1, ext_len);
uint8_t *pe = ext; uint8_t *pe = ext;
*pe++ = 0x73; *pe++ = 0x73;
*pe++ = ext_len-2; *pe++ = ext_len-2;
@@ -121,33 +131,39 @@ int cmd_keypair_gen() {
} }
} }
} }
if ((res_APDU_size = asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096, ext, ext_len)) == 0) { if ((res_APDU_size =
if (ext) asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096, ext, ext_len)) == 0) {
if (ext) {
free(ext); free(ext);
}
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (ext) if (ext) {
free(ext); free(ext);
}
ret = store_keys(&ecdsa, HSM_KEY_EC, key_id); ret = store_keys(&ecdsa, HSM_KEY_EC, key_id);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
if (ret != CCID_OK) { if (ret != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
} }
} } else {
else
return SW_WRONG_DATA(); return SW_WRONG_DATA();
if (find_and_store_meta_key(key_id) != CCID_OK) }
if (find_and_store_meta_key(key_id) != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id); file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
ret = flash_write_data_to_file(fpk, res_APDU, res_APDU_size); ret = flash_write_data_to_file(fpk, res_APDU, res_APDU_size);
if (ret != 0) if (ret != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
//if (apdu.ne == 0) }
// apdu.ne = res_APDU_size; if (apdu.ne == 0) {
apdu.ne = res_APDU_size;
}
low_flash_available(); low_flash_available();
return SW_OK(); return SW_OK();
} }

View File

@@ -33,16 +33,14 @@ int cmd_list_keys()
//first CC //first CC
for (int i = 0; i < dynamic_files; i++) { for (int i = 0; i < dynamic_files; i++) {
file_t *f = &dynamic_file[i]; file_t *f = &dynamic_file[i];
if ((f->fid & 0xff00) == (KEY_PREFIX << 8)) if ((f->fid & 0xff00) == (KEY_PREFIX << 8)) {
{
res_APDU[res_APDU_size++] = KEY_PREFIX; res_APDU[res_APDU_size++] = KEY_PREFIX;
res_APDU[res_APDU_size++] = f->fid & 0xff; res_APDU[res_APDU_size++] = f->fid & 0xff;
} }
} }
for (int i = 0; i < dynamic_files; i++) { for (int i = 0; i < dynamic_files; i++) {
file_t *f = &dynamic_file[i]; file_t *f = &dynamic_file[i];
if ((f->fid & 0xff00) == (PRKD_PREFIX << 8)) if ((f->fid & 0xff00) == (PRKD_PREFIX << 8)) {
{
res_APDU[res_APDU_size++] = PRKD_PREFIX; res_APDU[res_APDU_size++] = PRKD_PREFIX;
res_APDU[res_APDU_size++] = f->fid & 0xff; res_APDU[res_APDU_size++] = f->fid & 0xff;
} }

View File

@@ -24,11 +24,13 @@
file_t *ef_puk_aut = NULL; file_t *ef_puk_aut = NULL;
int cmd_mse() { int cmd_mse()
{
int p1 = P1(apdu); int p1 = P1(apdu);
int p2 = P2(apdu); int p2 = P2(apdu);
if (p2 != 0xA4 && p2 != 0xA6 && p2 != 0xAA && p2 != 0xB4 && p2 != 0xB6 && p2 != 0xB8) if (p2 != 0xA4 && p2 != 0xA6 && p2 != 0xAA && p2 != 0xB4 && p2 != 0xB6 && p2 != 0xB8) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
if (p1 & 0x1) { //SET if (p1 & 0x1) { //SET
uint16_t tag = 0x0; uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL; uint8_t *tag_data = NULL, *p = NULL;
@@ -36,28 +38,32 @@ int cmd_mse() {
while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) { while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) {
if (tag == 0x80) { if (tag == 0x80) {
if (p2 == 0xA4) { if (p2 == 0xA4) {
if (tag_len == 10 && memcmp(tag_data, OID_ID_CA_ECDH_AES_CBC_CMAC_128, tag_len) == 0) if (tag_len == 10 &&
memcmp(tag_data, OID_ID_CA_ECDH_AES_CBC_CMAC_128, tag_len) == 0) {
sm_set_protocol(MSE_AES); sm_set_protocol(MSE_AES);
}
} }
} } else if (tag == 0x83) {
else if (tag == 0x83) {
if (tag_len == 1) { if (tag_len == 1) {
} } else {
else {
if (p2 == 0xB6) { if (p2 == 0xB6) {
if (puk_store_select_chr(tag_data) == CCID_OK) if (puk_store_select_chr(tag_data) == CCID_OK) {
return SW_OK(); return SW_OK();
} }
else if (p2 == 0xA4) { /* Aut */ } else if (p2 == 0xA4) { /* Aut */
for (int i = 0; i < MAX_PUK; i++) { for (int i = 0; i < MAX_PUK; i++) {
file_t *ef = search_dynamic_file(EF_PUK+i); file_t *ef = search_dynamic_file(EF_PUK+i);
if (!ef) if (!ef) {
break; break;
if (!file_has_data(ef)) }
if (!file_has_data(ef)) {
break; break;
}
size_t chr_len = 0; size_t chr_len = 0;
const uint8_t *chr = cvc_get_chr(file_get_data(ef), file_get_size(ef), &chr_len); const uint8_t *chr = cvc_get_chr(file_get_data(ef),
file_get_size(ef),
&chr_len);
if (memcmp(chr, tag_data, chr_len) == 0) { if (memcmp(chr, tag_data, chr_len) == 0) {
ef_puk_aut = ef; ef_puk_aut = ef;
return SW_OK(); return SW_OK();
@@ -68,8 +74,8 @@ int cmd_mse() {
} }
} }
} }
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
return SW_OK(); return SW_OK();
} }

View File

@@ -23,13 +23,16 @@
extern int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy); extern int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy);
extern PUK *current_puk; extern PUK *current_puk;
int cmd_pso() { int cmd_pso()
{
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
if (p1 == 0x0 && (p2 == 0x92 || p2 == 0xAE || p2 == 0xBE)) { /* Verify certificate */ if (p1 == 0x0 && (p2 == 0x92 || p2 == 0xAE || p2 == 0xBE)) { /* Verify certificate */
if (apdu.nc == 0) if (apdu.nc == 0) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
if (current_puk == NULL) }
if (current_puk == NULL) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
}
if (apdu.data[0] != 0x7F || apdu.data[1] != 0x21) { if (apdu.data[0] != 0x7F || apdu.data[1] != 0x21) {
uint8_t tlv_len = 2+format_tlv_len(apdu.nc, NULL); uint8_t tlv_len = 2+format_tlv_len(apdu.nc, NULL);
memmove(apdu.data+tlv_len, apdu.data, apdu.nc); memmove(apdu.data+tlv_len, apdu.data, apdu.nc);
@@ -39,10 +42,11 @@ int cmd_pso() {
} }
int r = cvc_verify(apdu.data, apdu.nc, current_puk->cvcert, current_puk->cvcert_len); int r = cvc_verify(apdu.data, apdu.nc, current_puk->cvcert, current_puk->cvcert_len);
if (r != CCID_OK) { if (r != CCID_OK) {
if (r == CCID_WRONG_DATA) if (r == CCID_WRONG_DATA) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
else if (r == CCID_WRONG_SIGNATURE) } else if (r == CCID_WRONG_SIGNATURE) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
for (int i = 0; i < 0xfe; i++) { for (int i = 0; i < 0xfe; i++) {
@@ -51,27 +55,32 @@ int cmd_pso() {
if (!ca_ef) { if (!ca_ef) {
ca_ef = file_new(fid); ca_ef = file_new(fid);
flash_write_data_to_file(ca_ef, apdu.data, apdu.nc); flash_write_data_to_file(ca_ef, apdu.data, apdu.nc);
if (add_cert_puk_store(file_get_data(ca_ef), file_get_size(ca_ef), false) != CCID_OK) if (add_cert_puk_store(file_get_data(ca_ef), file_get_size(ca_ef),
false) != CCID_OK) {
return SW_FILE_FULL(); return SW_FILE_FULL();
}
size_t chr_len = 0; size_t chr_len = 0;
const uint8_t *chr = cvc_get_chr(apdu.data, apdu.nc, &chr_len); const uint8_t *chr = cvc_get_chr(apdu.data, apdu.nc, &chr_len);
if (chr == NULL) if (chr == NULL) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
size_t puk_len = 0, puk_bin_len = 0; size_t puk_len = 0, puk_bin_len = 0;
const uint8_t *puk = cvc_get_pub(apdu.data, apdu.nc, &puk_len), *puk_bin = NULL; const uint8_t *puk = cvc_get_pub(apdu.data, apdu.nc, &puk_len), *puk_bin = NULL;
if (puk == NULL) if (puk == NULL) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
size_t oid_len = 0; size_t oid_len = 0;
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6); const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
if (oid == NULL) if (oid == NULL) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
puk_bin = cvc_get_field(puk, puk_len, &puk_bin_len, 0x81); puk_bin = cvc_get_field(puk, puk_len, &puk_bin_len, 0x81);
if (!puk_bin) if (!puk_bin) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC } else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(apdu.data, apdu.nc); mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(apdu.data, apdu.nc);
mbedtls_ecp_group grp; mbedtls_ecp_group grp;
mbedtls_ecp_group_init(&grp); mbedtls_ecp_group_init(&grp);
@@ -89,21 +98,18 @@ int cmd_pso() {
} }
puk_bin = t86; puk_bin = t86;
puk_bin_len = t86_len; puk_bin_len = t86_len;
} } else if (mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
else if (mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
if (t86[0] == 0x2 || t86[0] == 0x3) { if (t86[0] == 0x2 || t86[0] == 0x3) {
if (t86_len != plen+1) { if (t86_len != plen+1) {
mbedtls_ecp_group_free(&grp); mbedtls_ecp_group_free(&grp);
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
} } else if (t86[0] == 0x4) {
else if (t86[0] == 0x4) {
if (t86_len != 2*plen+1) { if (t86_len != 2*plen+1) {
mbedtls_ecp_group_free(&grp); mbedtls_ecp_group_free(&grp);
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
} } else {
else {
mbedtls_ecp_group_free(&grp); mbedtls_ecp_group_free(&grp);
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
@@ -111,26 +117,41 @@ int cmd_pso() {
puk_bin_len = plen; puk_bin_len = plen;
} }
mbedtls_ecp_group_free(&grp); mbedtls_ecp_group_free(&grp);
if (!puk_bin) if (!puk_bin) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
} }
file_t *cd_ef = file_new((CD_PREFIX << 8) | i); file_t *cd_ef = file_new((CD_PREFIX << 8) | i);
size_t cd_len = asn1_build_cert_description(chr, chr_len, puk_bin, puk_bin_len, fid, NULL, 0); size_t cd_len = asn1_build_cert_description(chr,
if (cd_len == 0) chr_len,
puk_bin,
puk_bin_len,
fid,
NULL,
0);
if (cd_len == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
uint8_t *buf = (uint8_t *)calloc(cd_len, sizeof(uint8_t)); }
int r = asn1_build_cert_description(chr, chr_len, puk_bin, puk_bin_len, fid, buf, cd_len); uint8_t *buf = (uint8_t *) calloc(cd_len, sizeof(uint8_t));
int r = asn1_build_cert_description(chr,
chr_len,
puk_bin,
puk_bin_len,
fid,
buf,
cd_len);
flash_write_data_to_file(cd_ef, buf, cd_len); flash_write_data_to_file(cd_ef, buf, cd_len);
free(buf); free(buf);
if (r == 0) if (r == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
low_flash_available(); low_flash_available();
break; break;
} }
} }
return SW_OK(); return SW_OK();
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
return SW_OK(); return SW_OK();
} }

View File

@@ -19,53 +19,62 @@
#include "files.h" #include "files.h"
#include "cvc.h" #include "cvc.h"
int cmd_puk_auth() { int cmd_puk_auth()
{
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF); file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
if (!file_has_data(ef_puk)) if (!file_has_data(ef_puk)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
}
uint8_t *puk_data = file_get_data(ef_puk); uint8_t *puk_data = file_get_data(ef_puk);
if (apdu.nc > 0) { if (apdu.nc > 0) {
if (p1 == 0x0 || p1 == 0x1) { if (p1 == 0x0 || p1 == 0x1) {
file_t *ef = NULL; file_t *ef = NULL;
if (p1 == 0x0) { /* Add */ if (p1 == 0x0) { /* Add */
if (p2 != 0x0) if (p2 != 0x0) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
for (int i = 0; i < puk_data[0]; i++) { for (int i = 0; i < puk_data[0]; i++) {
ef = search_dynamic_file(EF_PUK+i); ef = search_dynamic_file(EF_PUK+i);
if (!ef) /* Never should not happen */ if (!ef) { /* Never should not happen */
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
if (!file_has_data(ef)) /* found first empty slot */ }
if (!file_has_data(ef)) { /* found first empty slot */
break; break;
}
} }
uint8_t *tmp = (uint8_t *)calloc(file_get_size(ef_puk), sizeof(uint8_t)); uint8_t *tmp = (uint8_t *) calloc(file_get_size(ef_puk), sizeof(uint8_t));
memcpy(tmp, puk_data, file_get_size(ef_puk)); memcpy(tmp, puk_data, file_get_size(ef_puk));
tmp[1] = puk_data[1]-1; tmp[1] = puk_data[1]-1;
flash_write_data_to_file(ef_puk, tmp, file_get_size(ef_puk)); flash_write_data_to_file(ef_puk, tmp, file_get_size(ef_puk));
puk_data = file_get_data(ef_puk); puk_data = file_get_data(ef_puk);
free(tmp); free(tmp);
} } else if (p1 == 0x1) { /* Replace */
else if (p1 == 0x1) { /* Replace */ if (p2 >= puk_data[0]) {
if (p2 >= puk_data[0])
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
ef = search_dynamic_file(EF_PUK+p2); ef = search_dynamic_file(EF_PUK+p2);
if (!ef) /* Never should not happen */ if (!ef) { /* Never should not happen */
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
}
} }
flash_write_data_to_file(ef, apdu.data, apdu.nc); flash_write_data_to_file(ef, apdu.data, apdu.nc);
low_flash_available(); low_flash_available();
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
} }
if (p1 == 0x2) { if (p1 == 0x2) {
if (p2 >= puk_data[0]) if (p2 >= puk_data[0]) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
file_t *ef = search_dynamic_file(EF_PUK+p2); file_t *ef = search_dynamic_file(EF_PUK+p2);
if (!ef) if (!ef) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
if (!file_has_data(ef)) }
if (!file_has_data(ef)) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
}
size_t chr_len = 0; size_t chr_len = 0;
const uint8_t *chr = cvc_get_chr(file_get_data(ef), file_get_size(ef), &chr_len); const uint8_t *chr = cvc_get_chr(file_get_data(ef), file_get_size(ef), &chr_len);
if (chr) { if (chr) {
@@ -73,12 +82,12 @@ int cmd_puk_auth() {
res_APDU_size = chr_len; res_APDU_size = chr_len;
} }
return set_res_sw(0x90, puk_status[p2]); return set_res_sw(0x90, puk_status[p2]);
} } else {
else {
memcpy(res_APDU, puk_data, 3); memcpy(res_APDU, puk_data, 3);
res_APDU[3] = 0; res_APDU[3] = 0;
for (int i = 0; i < puk_data[0]; i++) for (int i = 0; i < puk_data[0]; i++) {
res_APDU[3] += puk_status[i]; res_APDU[3] += puk_status[i];
}
res_APDU_size = 4; res_APDU_size = 4;
} }
return SW_OK(); return SW_OK();

View File

@@ -17,42 +17,46 @@
#include "sc_hsm.h" #include "sc_hsm.h"
int cmd_read_binary() { int cmd_read_binary()
{
uint16_t fid = 0x0; uint16_t fid = 0x0;
uint32_t offset = 0; uint32_t offset = 0;
uint8_t ins = INS(apdu), p1 = P1(apdu), p2 = P2(apdu); uint8_t ins = INS(apdu), p1 = P1(apdu), p2 = P2(apdu);
const file_t *ef = NULL; const file_t *ef = NULL;
if ((ins & 0x1) == 0) if ((ins & 0x1) == 0) {
{
if ((p1 & 0x80) != 0) { if ((p1 & 0x80) != 0) {
if (!(ef = search_by_fid(p1&0x1f, NULL, SPECIFY_EF))) if (!(ef = search_by_fid(p1&0x1f, NULL, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND (); return SW_FILE_NOT_FOUND();
}
offset = p2; offset = p2;
} } else {
else {
offset = make_uint16_t(p1, p2) & 0x7fff; offset = make_uint16_t(p1, p2) & 0x7fff;
ef = currentEF; ef = currentEF;
} }
} } else {
else {
if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) { if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) {
if (!(ef = search_by_fid(p2&0x1f, NULL, SPECIFY_EF))) if (!(ef = search_by_fid(p2&0x1f, NULL, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND (); return SW_FILE_NOT_FOUND();
} }
else { } else {
uint16_t file_id = make_uint16_t(p1, p2); // & 0x7fff; uint16_t file_id = make_uint16_t(p1, p2); // & 0x7fff;
if (file_id == 0x0) if (file_id == 0x0) {
ef = currentEF; ef = currentEF;
else if (!(ef = search_by_fid(file_id, NULL, SPECIFY_EF)) && !(ef = search_dynamic_file(file_id))) } else if (!(ef =
return SW_FILE_NOT_FOUND (); search_by_fid(file_id, NULL,
SPECIFY_EF)) && !(ef = search_dynamic_file(file_id))) {
return SW_FILE_NOT_FOUND();
}
if (apdu.data[0] != 0x54) if (apdu.data[0] != 0x54) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
}
offset = 0; offset = 0;
for (int d = 0; d < apdu.data[1]; d++) for (int d = 0; d < apdu.data[1]; d++) {
offset |= apdu.data[2+d]<<(apdu.data[1]-1-d)*8; offset |= apdu.data[2+d]<<(apdu.data[1]-1-d)*8;
}
} }
} }
@@ -61,26 +65,29 @@ int cmd_read_binary() {
} }
if (ef->data) { if (ef->data) {
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) { if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
uint16_t data_len = ((int (*)(const file_t *, int))(ef->data))((const file_t *)ef, 1); //already copies content to res_APDU uint16_t data_len = ((int (*)(const file_t *, int))(ef->data))((const file_t *) ef, 1); //already copies content to res_APDU
if (offset > data_len) if (offset > data_len) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
}
uint16_t maxle = data_len-offset; uint16_t maxle = data_len-offset;
if (apdu.ne > maxle) if (apdu.ne > maxle) {
apdu.ne = maxle; apdu.ne = maxle;
}
if (offset) { if (offset) {
memmove(res_APDU, res_APDU+offset, res_APDU_size-offset); memmove(res_APDU, res_APDU+offset, res_APDU_size-offset);
//res_APDU += offset; //res_APDU += offset;
res_APDU_size -= offset; res_APDU_size -= offset;
} }
} } else {
else {
uint16_t data_len = file_get_size(ef); uint16_t data_len = file_get_size(ef);
if (offset > data_len) if (offset > data_len) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
}
uint16_t maxle = data_len-offset; uint16_t maxle = data_len-offset;
if (apdu.ne > maxle) if (apdu.ne > maxle) {
apdu.ne = maxle; apdu.ne = maxle;
}
memcpy(res_APDU, file_get_data(ef)+offset, data_len-offset); memcpy(res_APDU, file_get_data(ef)+offset, data_len-offset);
res_APDU_size = data_len-offset; res_APDU_size = data_len-offset;
} }

View File

@@ -19,9 +19,11 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "kek.h" #include "kek.h"
int cmd_reset_retry() { int cmd_reset_retry()
if (P2(apdu) != 0x81) {
if (P2(apdu) != 0x81) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
}
if (!file_sopin || !file_pin1) { if (!file_sopin || !file_pin1) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -29,66 +31,77 @@ int cmd_reset_retry() {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
if (!(opts & HSM_OPT_RRC)) if (!(opts & HSM_OPT_RRC)) {
return SW_COMMAND_NOT_ALLOWED(); return SW_COMMAND_NOT_ALLOWED();
}
if (P1(apdu) == 0x0 || P1(apdu) == 0x2) { if (P1(apdu) == 0x0 || P1(apdu) == 0x2) {
int newpin_len = 0; int newpin_len = 0;
if (P1(apdu) == 0x0) { if (P1(apdu) == 0x0) {
if (apdu.nc <= 8) if (apdu.nc <= 8) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
uint16_t r = check_pin(file_sopin, apdu.data, 8); uint16_t r = check_pin(file_sopin, apdu.data, 8);
if (r != 0x9000) if (r != 0x9000) {
return r; return r;
}
newpin_len = apdu.nc-8; newpin_len = apdu.nc-8;
has_session_sopin = true; has_session_sopin = true;
hash_multi(apdu.data, 8, session_sopin); hash_multi(apdu.data, 8, session_sopin);
} } else if (P1(apdu) == 0x2) {
else if (P1(apdu) == 0x2) { if (!has_session_sopin) {
if (!has_session_sopin)
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
if (apdu.nc > 16) }
if (apdu.nc > 16) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
newpin_len = apdu.nc; newpin_len = apdu.nc;
} }
uint8_t dhash[33]; uint8_t dhash[33];
dhash[0] = newpin_len; dhash[0] = newpin_len;
double_hash_pin(apdu.data+(apdu.nc-newpin_len), newpin_len, dhash+1); double_hash_pin(apdu.data+(apdu.nc-newpin_len), newpin_len, dhash+1);
flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); flash_write_data_to_file(file_pin1, dhash, sizeof(dhash));
if (pin_reset_retries(file_pin1, true) != CCID_OK) if (pin_reset_retries(file_pin1, true) != CCID_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
}
uint8_t mkek[MKEK_SIZE]; uint8_t mkek[MKEK_SIZE];
int r = load_mkek(mkek); //loads the MKEK with SO pin int r = load_mkek(mkek); //loads the MKEK with SO pin
if (r != CCID_OK) if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
hash_multi(apdu.data+(apdu.nc-newpin_len), newpin_len, session_pin); hash_multi(apdu.data+(apdu.nc-newpin_len), newpin_len, session_pin);
has_session_pin = true; has_session_pin = true;
r = store_mkek(mkek); r = store_mkek(mkek);
release_mkek(mkek); release_mkek(mkek);
if (r != CCID_OK) if (r != CCID_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
low_flash_available(); low_flash_available();
return SW_OK(); return SW_OK();
} } else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) {
else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) { if (!(opts & HSM_OPT_RRC_RESET_ONLY)) {
if (!(opts & HSM_OPT_RRC_RESET_ONLY))
return SW_COMMAND_NOT_ALLOWED(); return SW_COMMAND_NOT_ALLOWED();
}
if (P1(apdu) == 0x1) { if (P1(apdu) == 0x1) {
if (apdu.nc != 8) if (apdu.nc != 8) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
uint16_t r = check_pin(file_sopin, apdu.data, 8); uint16_t r = check_pin(file_sopin, apdu.data, 8);
if (r != 0x9000) if (r != 0x9000) {
return r; return r;
}
has_session_sopin = true; has_session_sopin = true;
hash_multi(apdu.data, 8, session_sopin); hash_multi(apdu.data, 8, session_sopin);
} } else if (P1(apdu) == 0x3) {
else if (P1(apdu) == 0x3) { if (!has_session_sopin) {
if (!has_session_sopin)
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
if (apdu.nc != 0) }
if (apdu.nc != 0) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
}
} }
if (pin_reset_retries(file_pin1, true) != CCID_OK) if (pin_reset_retries(file_pin1, true) != CCID_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
}
return SW_OK(); return SW_OK();
} }
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();

View File

@@ -18,17 +18,15 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "version.h" #include "version.h"
void select_file(file_t *pe) { void select_file(file_t *pe)
if (!pe) {
{ if (!pe) {
currentDF = (file_t *)MF; currentDF = (file_t *) MF;
currentEF = NULL; currentEF = NULL;
} } else if (pe->type & FILE_TYPE_INTERNAL_EF) {
else if (pe->type & FILE_TYPE_INTERNAL_EF) {
currentEF = pe; currentEF = pe;
currentDF = &file_entries[pe->parent]; currentDF = &file_entries[pe->parent];
} } else {
else {
currentDF = pe; currentDF = pe;
} }
if (currentEF == file_openpgp || currentEF == file_sc_hsm) { if (currentEF == file_openpgp || currentEF == file_sc_hsm) {
@@ -37,7 +35,8 @@ void select_file(file_t *pe) {
} }
} }
int cmd_select() { int cmd_select()
{
uint8_t p1 = P1(apdu); uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
file_t *pe = NULL; file_t *pe = NULL;
@@ -48,8 +47,9 @@ int cmd_select() {
// return SW_INCORRECT_P1P2(); // return SW_INCORRECT_P1P2();
//} //}
if (apdu.nc >= 2) if (apdu.nc >= 2) {
fid = get_uint16_t(apdu.data, 0); fid = get_uint16_t(apdu.data, 0);
}
//if ((fid & 0xff00) == (KEY_PREFIX << 8)) //if ((fid & 0xff00) == (KEY_PREFIX << 8))
// fid = (PRKD_PREFIX << 8) | (fid & 0xff); // fid = (PRKD_PREFIX << 8) | (fid & 0xff);
@@ -63,56 +63,51 @@ int cmd_select() {
pfx == DCOD_PREFIX || pfx == DCOD_PREFIX ||
pfx == DATA_PREFIX || pfx == DATA_PREFIX ||
pfx == PROT_DATA_PREFIX) { pfx == PROT_DATA_PREFIX) {
if (!(pe = search_dynamic_file(fid)) && !(pe = search_by_fid(fid, NULL, SPECIFY_EF))) if (!(pe = search_dynamic_file(fid)) && !(pe = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
}
} }
if (!pe) { if (!pe) {
if (p1 == 0x0) { //Select MF, DF or EF - File identifier or absent if (p1 == 0x0) { //Select MF, DF or EF - File identifier or absent
if (apdu.nc == 0) { if (apdu.nc == 0) {
pe = (file_t *)MF; pe = (file_t *) MF;
//ac_fini(); //ac_fini();
} } else if (apdu.nc == 2) {
else if (apdu.nc == 2) {
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) { if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
} } else if (p1 == 0x01) { //Select child DF - DF identifier
else if (p1 == 0x01) { //Select child DF - DF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) { if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} } else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) { if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} } else if (p1 == 0x03) { //Select parent DF of the current DF - Absent
else if (p1 == 0x03) { //Select parent DF of the current DF - Absent if (apdu.nc != 0) {
if (apdu.nc != 0)
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier } else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
if (!(pe = search_by_name(apdu.data, apdu.nc))) { if (!(pe = search_by_name(apdu.data, apdu.nc))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
if (card_terminated) { if (card_terminated) {
return set_res_sw(0x62, 0x85); return set_res_sw(0x62, 0x85);
} }
} } else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
if (!(pe = search_by_path(apdu.data, apdu.nc, MF))) { if (!(pe = search_by_path(apdu.data, apdu.nc, MF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} } else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
if (!(pe = search_by_path(apdu.data, apdu.nc, currentDF))) { if (!(pe = search_by_path(apdu.data, apdu.nc, currentDF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
} }
if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) { if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) {
process_fci(pe,0); process_fci(pe, 0);
if (pe == file_sc_hsm) { if (pe == file_sc_hsm) {
res_APDU[res_APDU_size++] = 0x85; res_APDU[res_APDU_size++] = 0x85;
res_APDU[res_APDU_size++] = 5; res_APDU[res_APDU_size++] = 5;
@@ -124,9 +119,9 @@ int cmd_select() {
res_APDU[res_APDU_size++] = HSM_VERSION_MINOR; res_APDU[res_APDU_size++] = HSM_VERSION_MINOR;
res_APDU[1] = res_APDU_size-2; res_APDU[1] = res_APDU_size-2;
} }
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
select_file(pe); select_file(pe);
return SW_OK (); return SW_OK();
} }

View File

@@ -19,7 +19,8 @@
#include "random.h" #include "random.h"
#include "eac.h" #include "eac.h"
int cmd_session_pin() { int cmd_session_pin()
{
if (P1(apdu) == 0x01 && P2(apdu) == 0x81) { if (P1(apdu) == 0x01 && P2(apdu) == 0x81) {
memcpy(sm_session_pin, random_bytes_get(8), 8); memcpy(sm_session_pin, random_bytes_get(8), 8);
sm_session_pin_len = 8; sm_session_pin_len = 8;
@@ -27,8 +28,8 @@ int cmd_session_pin() {
memcpy(res_APDU, sm_session_pin, sm_session_pin_len); memcpy(res_APDU, sm_session_pin, sm_session_pin_len);
res_APDU_size = sm_session_pin_len; res_APDU_size = sm_session_pin_len;
apdu.ne = sm_session_pin_len; apdu.ne = sm_session_pin_len;
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
return SW_OK(); return SW_OK();
} }

View File

@@ -24,94 +24,111 @@
//----- //-----
/* From OpenSC */ /* From OpenSC */
static const uint8_t hdr_md5[] = { static const uint8_t hdr_md5[] = {
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
}; };
static const uint8_t hdr_sha1[] = { static const uint8_t hdr_sha1[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
0x05, 0x00, 0x04, 0x14 0x05, 0x00, 0x04, 0x14
}; };
static const uint8_t hdr_sha256[] = { static const uint8_t hdr_sha256[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
}; };
static const uint8_t hdr_sha384[] = { static const uint8_t hdr_sha384[] = {
0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
}; };
static const uint8_t hdr_sha512[] = { static const uint8_t hdr_sha512[] = {
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
}; };
static const uint8_t hdr_sha224[] = { static const uint8_t hdr_sha224[] = {
0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c
}; };
static const uint8_t hdr_ripemd160[] = { static const uint8_t hdr_ripemd160[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01,
0x05, 0x00, 0x04, 0x14 0x05, 0x00, 0x04, 0x14
}; };
static const struct digest_info_prefix { static const struct digest_info_prefix {
mbedtls_md_type_t algorithm; mbedtls_md_type_t algorithm;
const uint8_t * hdr; const uint8_t *hdr;
size_t hdr_len; size_t hdr_len;
size_t hash_len; size_t hash_len;
} digest_info_prefix[] = { } digest_info_prefix[] = {
{ MBEDTLS_MD_MD5, hdr_md5, sizeof(hdr_md5), 16 }, { MBEDTLS_MD_MD5, hdr_md5, sizeof(hdr_md5), 16 },
{ MBEDTLS_MD_SHA1, hdr_sha1, sizeof(hdr_sha1), 20 }, { MBEDTLS_MD_SHA1, hdr_sha1, sizeof(hdr_sha1), 20 },
{ MBEDTLS_MD_SHA256, hdr_sha256, sizeof(hdr_sha256), 32 }, { MBEDTLS_MD_SHA256, hdr_sha256, sizeof(hdr_sha256), 32 },
{ MBEDTLS_MD_SHA384, hdr_sha384, sizeof(hdr_sha384), 48 }, { MBEDTLS_MD_SHA384, hdr_sha384, sizeof(hdr_sha384), 48 },
{ MBEDTLS_MD_SHA512, hdr_sha512, sizeof(hdr_sha512), 64 }, { MBEDTLS_MD_SHA512, hdr_sha512, sizeof(hdr_sha512), 64 },
{ MBEDTLS_MD_SHA224, hdr_sha224, sizeof(hdr_sha224), 28 }, { MBEDTLS_MD_SHA224, hdr_sha224, sizeof(hdr_sha224), 28 },
{ MBEDTLS_MD_RIPEMD160,hdr_ripemd160, sizeof(hdr_ripemd160), 20 }, { MBEDTLS_MD_RIPEMD160, hdr_ripemd160, sizeof(hdr_ripemd160), 20 },
{ 0, NULL, 0, 0 } { 0, NULL, 0, 0 }
}; };
int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm, const uint8_t *in_dat, size_t in_len, uint8_t *out_dat, size_t *out_len) int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm,
const uint8_t *in_dat,
size_t in_len,
uint8_t *out_dat,
size_t *out_len)
{ {
for (int i = 0; digest_info_prefix[i].algorithm != 0; i++) { for (int i = 0; digest_info_prefix[i].algorithm != 0; i++) {
size_t hdr_len = digest_info_prefix[i].hdr_len, hash_len = digest_info_prefix[i].hash_len; size_t hdr_len = digest_info_prefix[i].hdr_len, hash_len = digest_info_prefix[i].hash_len;
const uint8_t *hdr = digest_info_prefix[i].hdr; const uint8_t *hdr = digest_info_prefix[i].hdr;
if (in_len == (hdr_len + hash_len) && !memcmp(in_dat, hdr, hdr_len)) { if (in_len == (hdr_len + hash_len) && !memcmp(in_dat, hdr, hdr_len)) {
if (algorithm) if (algorithm) {
*algorithm = digest_info_prefix[i].algorithm; *algorithm = digest_info_prefix[i].algorithm;
if (out_dat == NULL) }
return CCID_OK; if (out_dat == NULL) {
if (*out_len < hash_len) return CCID_OK;
return CCID_WRONG_DATA; }
memmove(out_dat, in_dat + hdr_len, hash_len); if (*out_len < hash_len) {
*out_len = hash_len; return CCID_WRONG_DATA;
return CCID_OK; }
} memmove(out_dat, in_dat + hdr_len, hash_len);
} *out_len = hash_len;
return CCID_EXEC_ERROR; return CCID_OK;
}
}
return CCID_EXEC_ERROR;
} }
//----- //-----
int cmd_signature() { int cmd_signature()
{
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
mbedtls_md_type_t md = MBEDTLS_MD_NONE; mbedtls_md_type_t md = MBEDTLS_MD_NONE;
file_t *fkey; file_t *fkey;
if (!isUserAuthenticated) if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
if (!(fkey = search_dynamic_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) }
if (!(fkey = search_dynamic_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
if (get_key_counter(fkey) == 0) }
if (get_key_counter(fkey) == 0) {
return SW_FILE_FULL(); return SW_FILE_FULL();
if (key_has_purpose(fkey, p2) == false) }
if (key_has_purpose(fkey, p2) == false) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
int key_size = file_get_size(fkey); int key_size = file_get_size(fkey);
if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1) if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS_SHA256 || p2 == ALGO_EC_SHA256) } else if (p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS_SHA256 || p2 == ALGO_EC_SHA256) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (p2 == ALGO_EC_SHA224 || p2 == ALGO_RSA_PKCS1_SHA224 || p2 == ALGO_RSA_PSS_SHA224) } else if (p2 == ALGO_EC_SHA224 || p2 == ALGO_RSA_PKCS1_SHA224 || p2 == ALGO_RSA_PSS_SHA224) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (p2 == ALGO_EC_SHA384 || p2 == ALGO_RSA_PKCS1_SHA384 || p2 == ALGO_RSA_PSS_SHA384) } else if (p2 == ALGO_EC_SHA384 || p2 == ALGO_RSA_PKCS1_SHA384 || p2 == ALGO_RSA_PSS_SHA384) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (p2 == ALGO_EC_SHA512 || p2 == ALGO_RSA_PKCS1_SHA512 || p2 == ALGO_RSA_PSS_SHA512) } else if (p2 == ALGO_EC_SHA512 || p2 == ALGO_RSA_PKCS1_SHA512 || p2 == ALGO_RSA_PSS_SHA512) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1 || p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS_SHA256 || p2 == ALGO_EC_SHA256 || p2 == ALGO_EC_SHA224 || p2 == ALGO_EC_SHA384 || p2 == ALGO_EC_SHA512 || p2 == ALGO_RSA_PKCS1_SHA224 || p2 == ALGO_RSA_PKCS1_SHA384 || p2 == ALGO_RSA_PKCS1_SHA512 || p2 == ALGO_RSA_PSS_SHA224 || p2 == ALGO_RSA_PSS_SHA384 || p2 == ALGO_RSA_PSS_SHA512) { }
if (p2 == ALGO_RSA_PKCS1_SHA1 || p2 == ALGO_RSA_PSS_SHA1 || p2 == ALGO_EC_SHA1 ||
p2 == ALGO_RSA_PKCS1_SHA256 || p2 == ALGO_RSA_PSS_SHA256 || p2 == ALGO_EC_SHA256 ||
p2 == ALGO_EC_SHA224 || p2 == ALGO_EC_SHA384 || p2 == ALGO_EC_SHA512 ||
p2 == ALGO_RSA_PKCS1_SHA224 || p2 == ALGO_RSA_PKCS1_SHA384 || p2 == ALGO_RSA_PKCS1_SHA512 ||
p2 == ALGO_RSA_PSS_SHA224 || p2 == ALGO_RSA_PSS_SHA384 || p2 == ALGO_RSA_PSS_SHA512) {
generic_hash(md, apdu.data, apdu.nc, apdu.data); generic_hash(md, apdu.data, apdu.nc, apdu.data);
apdu.nc = mbedtls_md_get_size(mbedtls_md_info_from_type(md)); apdu.nc = mbedtls_md_get_size(mbedtls_md_info_from_type(md));
} }
@@ -122,19 +139,21 @@ int cmd_signature() {
int r = load_private_key_rsa(&ctx, fkey); int r = load_private_key_rsa(&ctx, fkey);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED) if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
uint8_t *hash = apdu.data; uint8_t *hash = apdu.data;
size_t hash_len = apdu.nc; size_t hash_len = apdu.nc;
if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached
size_t nc = apdu.nc; size_t nc = apdu.nc;
if (pkcs1_strip_digest_info_prefix(&md, apdu.data, apdu.nc, apdu.data, &nc) != CCID_OK) //gets the MD algo id and strips it off if (pkcs1_strip_digest_info_prefix(&md, apdu.data, apdu.nc, apdu.data,
&nc) != CCID_OK) { //gets the MD algo id and strips it off
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
}
apdu.nc = nc; apdu.nc = nc;
} } else {
else {
//sc_asn1_print_tags(apdu.data, apdu.nc); //sc_asn1_print_tags(apdu.data, apdu.nc);
size_t tout = 0, oid_len = 0; size_t tout = 0, oid_len = 0;
uint8_t *p = NULL, *oid = NULL; uint8_t *p = NULL, *oid = NULL;
@@ -147,40 +166,42 @@ int cmd_signature() {
asn1_find_tag(p, tout, 0x4, &hash_len, &hash); asn1_find_tag(p, tout, 0x4, &hash_len, &hash);
} }
if (oid && oid_len > 0) { if (oid && oid_len > 0) {
if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA1, oid_len) == 0) if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA224, oid_len) == 0) } else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA224, oid_len) == 0) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA256, oid_len) == 0) } else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA384, oid_len) == 0) } else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA384, oid_len) == 0) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA512, oid_len) == 0) } else if (memcmp(oid, MBEDTLS_OID_DIGEST_ALG_SHA512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
}
} }
if (p2 >= ALGO_RSA_PSS && p2 <= ALGO_RSA_PSS_SHA512) { if (p2 >= ALGO_RSA_PSS && p2 <= ALGO_RSA_PSS_SHA512) {
if (p2 == ALGO_RSA_PSS && !oid) { if (p2 == ALGO_RSA_PSS && !oid) {
if (apdu.nc == 20) //default is sha1 if (apdu.nc == 20) { //default is sha1
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (apdu.nc == 28) } else if (apdu.nc == 28) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (apdu.nc == 32) } else if (apdu.nc == 32) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (apdu.nc == 48) } else if (apdu.nc == 48) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (apdu.nc == 64) } else if (apdu.nc == 64) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
}
} }
mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, md); mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, md);
} }
} }
if (md == MBEDTLS_MD_NONE) { if (md == MBEDTLS_MD_NONE) {
if (apdu.nc < key_size) //needs padding if (apdu.nc < key_size) { //needs padding
memset(apdu.data+apdu.nc, 0, key_size-apdu.nc); memset(apdu.data+apdu.nc, 0, key_size-apdu.nc);
}
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU); r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
} } else {
else { uint8_t *signature = (uint8_t *) calloc(key_size, sizeof(uint8_t));
uint8_t *signature = (uint8_t *)calloc(key_size, sizeof(uint8_t));
r = mbedtls_rsa_pkcs1_sign(&ctx, random_gen, NULL, md, hash_len, hash, signature); r = mbedtls_rsa_pkcs1_sign(&ctx, random_gen, NULL, md, hash_len, hash, signature);
memcpy(res_APDU, signature, key_size); memcpy(res_APDU, signature, key_size);
free(signature); free(signature);
@@ -192,52 +213,55 @@ int cmd_signature() {
res_APDU_size = key_size; res_APDU_size = key_size;
apdu.ne = key_size; apdu.ne = key_size;
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
} } else if (p2 >= ALGO_EC_RAW && p2 <= ALGO_EC_SHA512) {
else if (p2 >= ALGO_EC_RAW && p2 <= ALGO_EC_SHA512) {
mbedtls_ecdsa_context ctx; mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx); mbedtls_ecdsa_init(&ctx);
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
if (p2 == ALGO_EC_RAW) { if (p2 == ALGO_EC_RAW) {
if (apdu.nc == 32) if (apdu.nc == 32) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (apdu.nc == 20) } else if (apdu.nc == 20) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (apdu.nc == 28) } else if (apdu.nc == 28) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (apdu.nc == 48) } else if (apdu.nc == 48) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (apdu.nc == 64) } else if (apdu.nc == 64) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
}
} }
if (p2 == ALGO_EC_SHA1) if (p2 == ALGO_EC_SHA1) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (p2 == ALGO_EC_SHA224) } else if (p2 == ALGO_EC_SHA224) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (p2 == ALGO_EC_SHA256) } else if (p2 == ALGO_EC_SHA256) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (p2 == ALGO_EC_SHA384) } else if (p2 == ALGO_EC_SHA384) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (p2 == ALGO_EC_SHA512) } else if (p2 == ALGO_EC_SHA512) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
}
int r = load_private_key_ecdsa(&ctx, fkey); int r = load_private_key_ecdsa(&ctx, fkey);
if (r != CCID_OK) { if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx); mbedtls_ecdsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED) if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
size_t olen = 0; size_t olen = 0;
uint8_t buf[MBEDTLS_ECDSA_MAX_LEN]; uint8_t buf[MBEDTLS_ECDSA_MAX_LEN];
if (mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, &olen, random_gen, NULL) != 0) { if (mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN,
&olen, random_gen, NULL) != 0) {
mbedtls_ecdsa_free(&ctx); mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
memcpy(res_APDU, buf, olen); memcpy(res_APDU, buf, olen);
res_APDU_size = olen; res_APDU_size = olen;
mbedtls_ecdsa_free(&ctx); mbedtls_ecdsa_free(&ctx);
} } else {
else
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
decrement_key_counter(fkey); decrement_key_counter(fkey);
return SW_OK(); return SW_OK();
} }

View File

@@ -20,32 +20,38 @@
extern void select_file(file_t *pe); extern void select_file(file_t *pe);
int cmd_update_ef() { int cmd_update_ef()
{
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
uint16_t fid = (p1 << 8) | p2; uint16_t fid = (p1 << 8) | p2;
uint8_t *data = NULL; uint8_t *data = NULL;
uint16_t offset = 0; uint16_t offset = 0;
uint16_t data_len = 0; uint16_t data_len = 0;
file_t *ef = NULL; file_t *ef = NULL;
if (!isUserAuthenticated) if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
if (fid == 0x0) }
if (fid == 0x0) {
ef = currentEF; ef = currentEF;
else if (p1 != EE_CERTIFICATE_PREFIX && p1 != PRKD_PREFIX && p1 != CA_CERTIFICATE_PREFIX && p1 != CD_PREFIX && p1 != DATA_PREFIX && p1 != DCOD_PREFIX && p1 != PROT_DATA_PREFIX) } else if (p1 != EE_CERTIFICATE_PREFIX && p1 != PRKD_PREFIX && p1 != CA_CERTIFICATE_PREFIX &&
p1 != CD_PREFIX && p1 != DATA_PREFIX && p1 != DCOD_PREFIX &&
p1 != PROT_DATA_PREFIX) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
}
if (ef && !authenticate_action(ef, ACL_OP_UPDATE_ERASE)) if (ef && !authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
}
uint16_t tag = 0x0; uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL; uint8_t *tag_data = NULL, *p = NULL;
size_t tag_len = 0; size_t tag_len = 0;
while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) { while (walk_tlv(apdu.data, apdu.nc, &p, &tag, &tag_len, &tag_data)) {
if (tag == 0x54) { //ofset tag if (tag == 0x54) { //ofset tag
for (int i = 1; i <= tag_len; i++) for (int i = 1; i <= tag_len; i++) {
offset |= (*tag_data++ << (8*(tag_len-i))); offset |= (*tag_data++ << (8*(tag_len-i)));
} }
else if (tag == 0x53) { //data } else if (tag == 0x53) { //data
data_len = tag_len; data_len = tag_len;
data = tag_data; data = tag_data;
} }
@@ -55,30 +61,34 @@ int cmd_update_ef() {
//if ((fid & 0xff00) == (EE_CERTIFICATE_PREFIX << 8)) //if ((fid & 0xff00) == (EE_CERTIFICATE_PREFIX << 8))
// add_file_to_chain(ef, &ef_pukdf); // add_file_to_chain(ef, &ef_pukdf);
select_file(ef); select_file(ef);
} } else {
else { if (fid == 0x0 && !ef) {
if (fid == 0x0 && !ef)
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
else if (fid != 0x0 && !(ef = search_by_fid(fid, NULL, SPECIFY_EF)) && !(ef = search_dynamic_file(fid))) { //if does not exist, create it } else if (fid != 0x0 &&
!(ef =
search_by_fid(fid, NULL,
SPECIFY_EF)) && !(ef = search_dynamic_file(fid))) { //if does not exist, create it
//return SW_FILE_NOT_FOUND(); //return SW_FILE_NOT_FOUND();
ef = file_new(fid); ef = file_new(fid);
} }
if (offset == 0) { if (offset == 0) {
int r = flash_write_data_to_file(ef, data, data_len); int r = flash_write_data_to_file(ef, data, data_len);
if (r != CCID_OK) if (r != CCID_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
else { } else {
if (!file_has_data(ef)) if (!file_has_data(ef)) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
}
uint8_t *data_merge = (uint8_t *)calloc(1, offset+data_len); uint8_t *data_merge = (uint8_t *) calloc(1, offset+data_len);
memcpy(data_merge, file_get_data(ef), offset); memcpy(data_merge, file_get_data(ef), offset);
memcpy(data_merge+offset, data, data_len); memcpy(data_merge+offset, data, data_len);
int r = flash_write_data_to_file(ef, data_merge, offset+data_len); int r = flash_write_data_to_file(ef, data_merge, offset+data_len);
free(data_merge); free(data_merge);
if (r != CCID_OK) if (r != CCID_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
}
} }
low_flash_available(); low_flash_available();
} }

View File

@@ -17,41 +17,48 @@
#include "sc_hsm.h" #include "sc_hsm.h"
int cmd_verify() { int cmd_verify()
{
uint8_t p1 = P1(apdu); uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
if (p1 != 0x0 || (p2 & 0x60) != 0x0) if (p1 != 0x0 || (p2 & 0x60) != 0x0) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
}
if (p2 == 0x81) { //UserPin if (p2 == 0x81) { //UserPin
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
if (opts & HSM_OPT_TRANSPORT_PIN) if (opts & HSM_OPT_TRANSPORT_PIN) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
if (has_session_pin && apdu.nc == 0) }
if (has_session_pin && apdu.nc == 0) {
return SW_OK(); return SW_OK();
if (*file_get_data(file_pin1) == 0 && pka_enabled() == false) //not initialized }
if (*file_get_data(file_pin1) == 0 && pka_enabled() == false) { //not initialized
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
}
if (apdu.nc > 0) { if (apdu.nc > 0) {
return check_pin(file_pin1, apdu.data, apdu.nc); return check_pin(file_pin1, apdu.data, apdu.nc);
} }
if (file_read_uint8(file_get_data(file_retries_pin1)) == 0) if (file_read_uint8(file_get_data(file_retries_pin1)) == 0) {
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
}
return set_res_sw(0x63, 0xc0 | file_read_uint8(file_get_data(file_retries_pin1))); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_get_data(file_retries_pin1)));
} } else if (p2 == 0x88) { //SOPin
else if (p2 == 0x88) { //SOPin if (file_read_uint8(file_get_data(file_sopin)) == 0) { //not initialized
if (file_read_uint8(file_get_data(file_sopin)) == 0) //not initialized
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
}
if (apdu.nc > 0) { if (apdu.nc > 0) {
return check_pin(file_sopin, apdu.data, apdu.nc); return check_pin(file_sopin, apdu.data, apdu.nc);
} }
if (file_read_uint8(file_get_data(file_retries_sopin)) == 0) if (file_read_uint8(file_get_data(file_retries_sopin)) == 0) {
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
if (has_session_sopin) }
if (has_session_sopin) {
return SW_OK(); return SW_OK();
}
return set_res_sw(0x63, 0xc0 | file_read_uint8(file_get_data(file_retries_sopin))); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_get_data(file_retries_sopin)));
} } else if (p2 == 0x85) {
else if (p2 == 0x85) {
return SW_OK(); return SW_OK();
} }
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();

View File

@@ -31,125 +31,178 @@
extern const uint8_t *dev_name; extern const uint8_t *dev_name;
extern size_t dev_name_len; extern size_t dev_name_len;
size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t buf_len) { size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t buf_len)
{
const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 }; const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 };
size_t n_size = mbedtls_mpi_size(&rsa->N), e_size = mbedtls_mpi_size(&rsa->E); size_t n_size = mbedtls_mpi_size(&rsa->N), e_size = mbedtls_mpi_size(&rsa->E);
size_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size); size_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size);
size_t oid_len = asn1_len_tag(0x6, sizeof(oid_rsa)); size_t oid_len = asn1_len_tag(0x6, sizeof(oid_rsa));
size_t tot_len = asn1_len_tag(0x7f49, oid_len+ntot_size+etot_size); size_t tot_len = asn1_len_tag(0x7f49, oid_len+ntot_size+etot_size);
if (buf == NULL || buf_len == 0) if (buf == NULL || buf_len == 0) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf; uint8_t *p = buf;
memcpy(p, "\x7F\x49", 2); p += 2; memcpy(p, "\x7F\x49", 2); p += 2;
p += format_tlv_len(oid_len+ntot_size+etot_size, p); p += format_tlv_len(oid_len+ntot_size+etot_size, p);
//oid //oid
*p++ = 0x6; p += format_tlv_len(sizeof(oid_rsa), p); memcpy(p, oid_rsa, sizeof(oid_rsa)); p += sizeof(oid_rsa); *p++ = 0x6; p += format_tlv_len(sizeof(oid_rsa), p); memcpy(p, oid_rsa, sizeof(oid_rsa));
p += sizeof(oid_rsa);
//n //n
*p++ = 0x81; p += format_tlv_len(n_size, p); mbedtls_mpi_write_binary(&rsa->N, p, n_size); p += n_size; *p++ = 0x81; p += format_tlv_len(n_size, p); mbedtls_mpi_write_binary(&rsa->N, p, n_size);
p += n_size;
//n //n
*p++ = 0x82; p += format_tlv_len(e_size, p); mbedtls_mpi_write_binary(&rsa->E, p, e_size); p += e_size; *p++ = 0x82; p += format_tlv_len(e_size, p); mbedtls_mpi_write_binary(&rsa->E, p, e_size);
p += e_size;
return tot_len; return tot_len;
} }
const uint8_t *pointA[] = { const uint8_t *pointA[] = {
NULL, NULL,
(uint8_t *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", (uint8_t *)
(uint8_t *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC",
(uint8_t *)"\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\xFC", (uint8_t *)
(uint8_t *)"\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\xFC", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE",
(uint8_t *)"\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\xFC", (uint8_t *)
"\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\xFC",
(uint8_t *)
"\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\xFC",
(uint8_t *)
"\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\xFC",
}; };
size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len) { size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len)
{
uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN]; uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN];
const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 }; const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 };
size_t p_size = mbedtls_mpi_size(&ecdsa->grp.P), a_size = mbedtls_mpi_size(&ecdsa->grp.A); size_t p_size = mbedtls_mpi_size(&ecdsa->grp.P), a_size = mbedtls_mpi_size(&ecdsa->grp.A);
size_t b_size = mbedtls_mpi_size(&ecdsa->grp.B), g_size = 1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.X); size_t b_size = mbedtls_mpi_size(&ecdsa->grp.B),
g_size = 1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.X);
size_t o_size = mbedtls_mpi_size(&ecdsa->grp.N), y_size = 0; size_t o_size = mbedtls_mpi_size(&ecdsa->grp.N), y_size = 0;
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &y_size, Y_buf, sizeof(Y_buf)); mbedtls_ecp_point_write_binary(&ecdsa->grp,
&ecdsa->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&y_size,
Y_buf,
sizeof(Y_buf));
size_t c_size = 1; size_t c_size = 1;
size_t ptot_size = asn1_len_tag(0x81, p_size), atot_size = asn1_len_tag(0x82, a_size ? a_size : (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6 ? p_size : 1)); size_t ptot_size = asn1_len_tag(0x81, p_size), atot_size = asn1_len_tag(0x82,
a_size ? a_size : (
pointA[ecdsa->grp.id
] &&
ecdsa->grp.id <
6 ? p_size : 1));
size_t btot_size = asn1_len_tag(0x83, b_size), gtot_size = asn1_len_tag(0x84, g_size); size_t btot_size = asn1_len_tag(0x83, b_size), gtot_size = asn1_len_tag(0x84, g_size);
size_t otot_size = asn1_len_tag(0x85, o_size), ytot_size = asn1_len_tag(0x86, y_size); size_t otot_size = asn1_len_tag(0x85, o_size), ytot_size = asn1_len_tag(0x86, y_size);
size_t ctot_size = asn1_len_tag(0x87, c_size); size_t ctot_size = asn1_len_tag(0x87, c_size);
size_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa)); size_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa));
size_t tot_len = asn1_len_tag(0x7f49, oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size); size_t tot_len = asn1_len_tag(0x7f49,
if (buf == NULL || buf_len == 0) oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+
ctot_size);
if (buf == NULL || buf_len == 0) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf; uint8_t *p = buf;
memcpy(p, "\x7F\x49", 2); p += 2; memcpy(p, "\x7F\x49", 2); p += 2;
p += format_tlv_len(oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size, p); p += format_tlv_len(
oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size,
p);
//oid //oid
*p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid_ecdsa, sizeof(oid_ecdsa)); p += sizeof(oid_ecdsa); *p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid_ecdsa, sizeof(oid_ecdsa));
p += sizeof(oid_ecdsa);
//p //p
*p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); p += p_size; *p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size);
p += p_size;
//A //A
if (a_size) { if (a_size) {
*p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, p, a_size); p += a_size; *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A,
} p,
else { //mbedtls does not set point A for some curves a_size); p += a_size;
} else { //mbedtls does not set point A for some curves
if (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6) { if (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6) {
*p++ = 0x82; p += format_tlv_len(p_size, p); memcpy(p, pointA[ecdsa->grp.id], p_size); p += p_size; *p++ = 0x82; p += format_tlv_len(p_size, p); memcpy(p, pointA[ecdsa->grp.id], p_size);
} p += p_size;
else { } else {
*p++ = 0x82; p += format_tlv_len(1, p); *p++ = 0x82; p += format_tlv_len(1, p);
*p++ = 0x0; *p++ = 0x0;
} }
} }
//B //B
*p++ = 0x83; p += format_tlv_len(b_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.B, p, b_size); p += b_size; *p++ = 0x83; p += format_tlv_len(b_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.B, p, b_size);
p += b_size;
//G //G
size_t g_new_size = 0; size_t g_new_size = 0;
*p++ = 0x84; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &g_new_size, p, g_size); p += g_size; *p++ = 0x84; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp,
&ecdsa->grp.G,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&g_new_size,
p,
g_size);
p += g_size;
//order //order
*p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); p += o_size; *p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size);
p += o_size;
//Y //Y
*p++ = 0x86; p += format_tlv_len(y_size, p); memcpy(p, Y_buf, y_size); p += y_size; *p++ = 0x86; p += format_tlv_len(y_size, p); memcpy(p, Y_buf, y_size); p += y_size;
//cofactor //cofactor
*p++ = 0x87; p += format_tlv_len(c_size, p); *p++ = 0x87; p += format_tlv_len(c_size, p);
if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE448) if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE448) {
*p++ = 4; *p++ = 4;
else if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE25519) } else if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE25519) {
*p++ = 8; *p++ = 8;
else } else {
*p++ = 1; *p++ = 1;
}
return tot_len; return tot_len;
} }
size_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len, const uint8_t *ext, size_t ext_len) { size_t asn1_cvc_cert_body(void *rsa_ecdsa,
uint8_t key_type,
uint8_t *buf,
size_t buf_len,
const uint8_t *ext,
size_t ext_len)
{
size_t pubkey_size = 0; size_t pubkey_size = 0;
if (key_type == HSM_KEY_RSA) if (key_type == HSM_KEY_RSA) {
pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0); pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0);
else if (key_type == HSM_KEY_EC) } else if (key_type == HSM_KEY_EC) {
pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0); pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0);
}
size_t cpi_size = 4; size_t cpi_size = 4;
size_t ext_size = 0; size_t ext_size = 0;
if (ext && ext_len > 0) if (ext && ext_len > 0) {
ext_size = asn1_len_tag(0x65, ext_len); ext_size = asn1_len_tag(0x65, ext_len);
}
uint8_t *car = NULL, *chr = NULL; uint8_t *car = NULL, *chr = NULL;
size_t lencar = 0, lenchr = 0; size_t lencar = 0, lenchr = 0;
if (asn1_find_tag(apdu.data, apdu.nc, 0x42, &lencar, &car) == false || lencar == 0 || car == NULL) { if (asn1_find_tag(apdu.data, apdu.nc, 0x42, &lencar,
car = (uint8_t *)dev_name; &car) == false || lencar == 0 || car == NULL) {
car = (uint8_t *) dev_name;
lencar = dev_name_len; lencar = dev_name_len;
} }
if (asn1_find_tag(apdu.data, apdu.nc, 0x5f20, &lenchr, &chr) == false || lenchr == 0 || chr == NULL) { if (asn1_find_tag(apdu.data, apdu.nc, 0x5f20, &lenchr,
chr = (uint8_t *)dev_name; &chr) == false || lenchr == 0 || chr == NULL) {
chr = (uint8_t *) dev_name;
lenchr = dev_name_len; lenchr = dev_name_len;
} }
size_t car_size = asn1_len_tag(0x42, lencar), chr_size = asn1_len_tag(0x5f20, lenchr); size_t car_size = asn1_len_tag(0x42, lencar), chr_size = asn1_len_tag(0x5f20, lenchr);
size_t tot_len = asn1_len_tag(0x7f4e, cpi_size+car_size+pubkey_size+chr_size+ext_size); size_t tot_len = asn1_len_tag(0x7f4e, cpi_size+car_size+pubkey_size+chr_size+ext_size);
if (buf_len == 0 || buf == NULL) if (buf_len == 0 || buf == NULL) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf; uint8_t *p = buf;
memcpy(p, "\x7F\x4E", 2); p += 2; memcpy(p, "\x7F\x4E", 2); p += 2;
p += format_tlv_len(cpi_size+car_size+pubkey_size+chr_size+ext_size, p); p += format_tlv_len(cpi_size+car_size+pubkey_size+chr_size+ext_size, p);
@@ -158,10 +211,11 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_
//car //car
*p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar; *p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar;
//pubkey //pubkey
if (key_type == HSM_KEY_RSA) if (key_type == HSM_KEY_RSA) {
p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size); p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size);
else if (key_type == HSM_KEY_EC) } else if (key_type == HSM_KEY_EC) {
p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size); p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size);
}
//chr //chr
*p++ = 0x5f; *p++ = 0x20; p += format_tlv_len(lenchr, p); memcpy(p, chr, lenchr); p += lenchr; *p++ = 0x5f; *p++ = 0x20; p += format_tlv_len(lenchr, p); memcpy(p, chr, lenchr); p += lenchr;
if (ext && ext_len > 0) { if (ext && ext_len > 0) {
@@ -173,18 +227,31 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_
return tot_len; return tot_len;
} }
size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len, const uint8_t *ext, size_t ext_len) { size_t asn1_cvc_cert(void *rsa_ecdsa,
uint8_t key_type,
uint8_t *buf,
size_t buf_len,
const uint8_t *ext,
size_t ext_len)
{
size_t key_size = 0; size_t key_size = 0;
if (key_type == HSM_KEY_RSA) if (key_type == HSM_KEY_RSA) {
key_size = mbedtls_mpi_size(&((mbedtls_rsa_context *)rsa_ecdsa)->N); key_size = mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N);
else if (key_type == HSM_KEY_EC) } else if (key_type == HSM_KEY_EC) {
key_size = 2*(int)((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *)rsa_ecdsa)->grp.id)->bit_size + 7)/8); key_size = 2*
size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len), sig_size = asn1_len_tag(0x5f37, key_size); (int) ((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)
->grp.id)->
bit_size + 7)/8);
}
size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len),
sig_size = asn1_len_tag(0x5f37, key_size);
size_t tot_len = asn1_len_tag(0x7f21, body_size+sig_size); size_t tot_len = asn1_len_tag(0x7f21, body_size+sig_size);
if (buf_len == 0 || buf == NULL) if (buf_len == 0 || buf == NULL) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf, *body = NULL; uint8_t *p = buf, *body = NULL;
memcpy(p, "\x7F\x21", 2); p += 2; memcpy(p, "\x7F\x21", 2); p += 2;
p += format_tlv_len(body_size+sig_size, p); p += format_tlv_len(body_size+sig_size, p);
@@ -195,22 +262,23 @@ size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf
memcpy(p, "\x5F\x37", 2); p += 2; memcpy(p, "\x5F\x37", 2); p += 2;
p += format_tlv_len(key_size, p); p += format_tlv_len(key_size, p);
if (key_type == HSM_KEY_RSA) { if (key_type == HSM_KEY_RSA) {
if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_gen, NULL, MBEDTLS_MD_SHA256, 32, hsh, p) != 0) if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_gen, NULL, MBEDTLS_MD_SHA256, 32,
hsh, p) != 0) {
memset(p, 0, key_size); memset(p, 0, key_size);
}
p += key_size; p += key_size;
} } else if (key_type == HSM_KEY_EC) {
else if (key_type == HSM_KEY_EC) {
mbedtls_mpi r, s; mbedtls_mpi r, s;
int ret = 0; int ret = 0;
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)rsa_ecdsa; mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) rsa_ecdsa;
mbedtls_mpi_init(&r); mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s); mbedtls_mpi_init(&s);
ret = mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL); ret =
mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL);
if (ret == 0) { if (ret == 0) {
mbedtls_mpi_write_binary(&r, p, key_size/2); p += key_size/2; mbedtls_mpi_write_binary(&r, p, key_size/2); p += key_size/2;
mbedtls_mpi_write_binary(&s, p, key_size/2); p += key_size/2; mbedtls_mpi_write_binary(&s, p, key_size/2); p += key_size/2;
} } else {
else {
memset(p, 0, key_size); memset(p, 0, key_size);
p += key_size; p += key_size;
} }
@@ -220,14 +288,21 @@ size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf
return p-buf; return p-buf;
} }
size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len, const uint8_t *ext, size_t ext_len) { size_t asn1_cvc_aut(void *rsa_ecdsa,
uint8_t key_type,
uint8_t *buf,
size_t buf_len,
const uint8_t *ext,
size_t ext_len)
{
size_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len); size_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len);
size_t outcar_len = dev_name_len; size_t outcar_len = dev_name_len;
const uint8_t *outcar = dev_name; const uint8_t *outcar = dev_name;
size_t outcar_size = asn1_len_tag(0x42, outcar_len); size_t outcar_size = asn1_len_tag(0x42, outcar_len);
file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
if (!fkey) if (!fkey) {
return 0; return 0;
}
mbedtls_ecdsa_context ectx; mbedtls_ecdsa_context ectx;
mbedtls_ecdsa_init(&ectx); mbedtls_ecdsa_init(&ectx);
if (load_private_key_ecdsa(&ectx, fkey) != CCID_OK) { if (load_private_key_ecdsa(&ectx, fkey) != CCID_OK) {
@@ -235,11 +310,15 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_
return 0; return 0;
} }
int ret = 0, key_size = 2*mbedtls_mpi_size(&ectx.d); int ret = 0, key_size = 2*mbedtls_mpi_size(&ectx.d);
size_t outsig_size = asn1_len_tag(0x5f37, key_size), tot_len = asn1_len_tag(0x67, cvcert_size+outcar_size+outsig_size); size_t outsig_size = asn1_len_tag(0x5f37, key_size), tot_len = asn1_len_tag(0x67,
if (buf_len == 0 || buf == NULL) cvcert_size+outcar_size+
outsig_size);
if (buf_len == 0 || buf == NULL) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf; uint8_t *p = buf;
*p++ = 0x67; *p++ = 0x67;
p += format_tlv_len(cvcert_size+outcar_size+outsig_size, p); p += format_tlv_len(cvcert_size+outcar_size+outsig_size, p);
@@ -269,16 +348,27 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_
return p-buf; return p-buf;
} }
size_t asn1_build_cert_description(const uint8_t *label, size_t label_len, const uint8_t *puk, size_t puk_len, uint16_t fid, uint8_t *buf, size_t buf_len) { size_t asn1_build_cert_description(const uint8_t *label,
size_t label_len,
const uint8_t *puk,
size_t puk_len,
uint16_t fid,
uint8_t *buf,
size_t buf_len)
{
size_t opt_len = 2; size_t opt_len = 2;
size_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len)+asn1_len_tag(0x3, opt_len)); size_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len)+asn1_len_tag(0x3, opt_len));
size_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */ size_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */
size_t seq3_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t))))); size_t seq3_size =
asn1_len_tag(0xA1,
asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))));
size_t tot_len = asn1_len_tag(0x30, seq1_size+seq2_size+seq3_size); size_t tot_len = asn1_len_tag(0x30, seq1_size+seq2_size+seq3_size);
if (buf_len == 0 || buf == NULL) if (buf_len == 0 || buf == NULL) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf; uint8_t *p = buf;
*p++ = 0x30; *p++ = 0x30;
p += format_tlv_len(seq1_size+seq2_size+seq3_size, p); p += format_tlv_len(seq1_size+seq2_size+seq3_size, p);
@@ -301,7 +391,8 @@ size_t asn1_build_cert_description(const uint8_t *label, size_t label_len, const
//Seq 3 //Seq 3
*p++ = 0xA1; *p++ = 0xA1;
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))), p); p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))),
p);
*p++ = 0x30; *p++ = 0x30;
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t))), p); p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t))), p);
*p++ = 0x30; *p++ = 0x30;
@@ -313,15 +404,29 @@ size_t asn1_build_cert_description(const uint8_t *label, size_t label_len, const
return p-buf; return p-buf;
} }
size_t asn1_build_prkd_generic(const uint8_t *label, size_t label_len, const uint8_t *keyid, size_t keyid_len, size_t keysize, const uint8_t *seq, size_t seq_len, uint8_t *buf, size_t buf_len) { size_t asn1_build_prkd_generic(const uint8_t *label,
size_t label_len,
const uint8_t *keyid,
size_t keyid_len,
size_t keysize,
const uint8_t *seq,
size_t seq_len,
uint8_t *buf,
size_t buf_len)
{
size_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len)); size_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len));
size_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len)+asn1_len_tag(0x3, seq_len)); size_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len)+asn1_len_tag(0x3, seq_len));
size_t seq3_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2,2))); size_t seq3_size =
asn1_len_tag(0xA1,
asn1_len_tag(0x30,
asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2, 2)));
size_t tot_len = asn1_len_tag(0xA0, seq1_size+seq2_size+seq3_size); size_t tot_len = asn1_len_tag(0xA0, seq1_size+seq2_size+seq3_size);
if (buf_len == 0 || buf == NULL) if (buf_len == 0 || buf == NULL) {
return tot_len; return tot_len;
if (buf_len < tot_len) }
if (buf_len < tot_len) {
return 0; return 0;
}
uint8_t *p = buf; uint8_t *p = buf;
*p++ = 0xA0; *p++ = 0xA0;
p += format_tlv_len(seq1_size+seq2_size+seq3_size, p); p += format_tlv_len(seq1_size+seq2_size+seq3_size, p);
@@ -344,9 +449,12 @@ size_t asn1_build_prkd_generic(const uint8_t *label, size_t label_len, const uin
//Seq 3 //Seq 3
*p++ = 0xA1; *p++ = 0xA1;
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2,2)), p); p +=
format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2,
2)),
p);
*p++ = 0x30; *p++ = 0x30;
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2,2), p); p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x4, 0))+asn1_len_tag(0x2, 2), p);
*p++ = 0x30; *p++ = 0x30;
p += format_tlv_len(asn1_len_tag(0x4, 0), p); p += format_tlv_len(asn1_len_tag(0x4, 0), p);
*p++ = 0x4; *p++ = 0x4;
@@ -358,65 +466,106 @@ size_t asn1_build_prkd_generic(const uint8_t *label, size_t label_len, const uin
return p-buf; return p-buf;
} }
size_t asn1_build_prkd_ecc(const uint8_t *label, size_t label_len, const uint8_t *keyid, size_t keyid_len, size_t keysize, uint8_t *buf, size_t buf_len) { size_t asn1_build_prkd_ecc(const uint8_t *label,
return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, (const uint8_t *)"\x07\x20\x80", 3, buf, buf_len); size_t label_len,
const uint8_t *keyid,
size_t keyid_len,
size_t keysize,
uint8_t *buf,
size_t buf_len)
{
return asn1_build_prkd_generic(label,
label_len,
keyid,
keyid_len,
keysize,
(const uint8_t *) "\x07\x20\x80",
3,
buf,
buf_len);
} }
size_t asn1_build_prkd_rsa(const uint8_t *label, size_t label_len, const uint8_t *keyid, size_t keyid_len, size_t keysize, uint8_t *buf, size_t buf_len) { size_t asn1_build_prkd_rsa(const uint8_t *label,
return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, (const uint8_t *)"\x02\x74", 2, buf, buf_len); size_t label_len,
const uint8_t *keyid,
size_t keyid_len,
size_t keysize,
uint8_t *buf,
size_t buf_len)
{
return asn1_build_prkd_generic(label,
label_len,
keyid,
keyid_len,
keysize,
(const uint8_t *) "\x02\x74",
2,
buf,
buf_len);
} }
const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint16_t tag) { const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint16_t tag)
{
uint8_t *rdata = NULL; uint8_t *rdata = NULL;
if (data == NULL || len == 0) if (data == NULL || len == 0) {
return NULL; return NULL;
if (asn1_find_tag(data, len, tag, olen, &rdata) == false) }
if (asn1_find_tag(data, len, tag, olen, &rdata) == false) {
return NULL; return NULL;
}
return rdata; return rdata;
} }
const uint8_t *cvc_get_body(const uint8_t *data, size_t len, size_t *olen) { const uint8_t *cvc_get_body(const uint8_t *data, size_t len, size_t *olen)
{
const uint8_t *bkdata = data; const uint8_t *bkdata = data;
if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) /* Check for CSR */ if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */
data = bkdata; data = bkdata;
}
if ((data = cvc_get_field(data, len, olen, 0x7F21)) != NULL) { if ((data = cvc_get_field(data, len, olen, 0x7F21)) != NULL) {
return cvc_get_field(data, len, olen, 0x7F4E); return cvc_get_field(data, len, olen, 0x7F4E);
} }
return NULL; return NULL;
} }
const uint8_t *cvc_get_sig(const uint8_t *data, size_t len, size_t *olen) { const uint8_t *cvc_get_sig(const uint8_t *data, size_t len, size_t *olen)
{
const uint8_t *bkdata = data; const uint8_t *bkdata = data;
if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) /* Check for CSR */ if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */
data = bkdata; data = bkdata;
}
if ((data = cvc_get_field(data, len, olen, 0x7F21)) != NULL) { if ((data = cvc_get_field(data, len, olen, 0x7F21)) != NULL) {
return cvc_get_field(data, len, olen, 0x5F37); return cvc_get_field(data, len, olen, 0x5F37);
} }
return NULL; return NULL;
} }
const uint8_t *cvc_get_car(const uint8_t *data, size_t len, size_t *olen) { const uint8_t *cvc_get_car(const uint8_t *data, size_t len, size_t *olen)
{
if ((data = cvc_get_body(data, len, olen)) != NULL) { if ((data = cvc_get_body(data, len, olen)) != NULL) {
return cvc_get_field(data, len, olen, 0x42); return cvc_get_field(data, len, olen, 0x42);
} }
return NULL; return NULL;
} }
const uint8_t *cvc_get_chr(const uint8_t *data, size_t len, size_t *olen) { const uint8_t *cvc_get_chr(const uint8_t *data, size_t len, size_t *olen)
{
if ((data = cvc_get_body(data, len, olen)) != NULL) { if ((data = cvc_get_body(data, len, olen)) != NULL) {
return cvc_get_field(data, len, olen, 0x5F20); return cvc_get_field(data, len, olen, 0x5F20);
} }
return NULL; return NULL;
} }
const uint8_t *cvc_get_pub(const uint8_t *data, size_t len, size_t *olen) { const uint8_t *cvc_get_pub(const uint8_t *data, size_t len, size_t *olen)
{
if ((data = cvc_get_body(data, len, olen)) != NULL) { if ((data = cvc_get_body(data, len, olen)) != NULL) {
return cvc_get_field(data, len, olen, 0x7F49); return cvc_get_field(data, len, olen, 0x7F49);
} }
return NULL; return NULL;
} }
const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen) { const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen)
{
if ((data = cvc_get_body(data, len, olen)) != NULL) { if ((data = cvc_get_body(data, len, olen)) != NULL) {
return cvc_get_field(data, len, olen, 0x65); return cvc_get_field(data, len, olen, 0x65);
} }
@@ -426,15 +575,18 @@ const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen) {
extern PUK puk_store[MAX_PUK_STORE_ENTRIES]; extern PUK puk_store[MAX_PUK_STORE_ENTRIES];
extern int puk_store_entries; extern int puk_store_entries;
int puk_store_index(const uint8_t *chr, size_t chr_len) { int puk_store_index(const uint8_t *chr, size_t chr_len)
{
for (int i = 0; i < puk_store_entries; i++) { for (int i = 0; i < puk_store_entries; i++) {
if (memcmp(puk_store[i].chr, chr, chr_len) == 0) if (memcmp(puk_store[i].chr, chr, chr_len) == 0) {
return i; return i;
}
} }
return -1; return -1;
} }
mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len) { mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len)
{
size_t chr_len = 0, car_len = 0; size_t chr_len = 0, car_len = 0;
const uint8_t *chr = NULL, *car = NULL; const uint8_t *chr = NULL, *car = NULL;
int eq = -1; int eq = -1;
@@ -447,55 +599,67 @@ mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len) {
if (idx != -1) { if (idx != -1) {
ca = puk_store[idx].cvcert; ca = puk_store[idx].cvcert;
ca_len = puk_store[idx].cvcert_len; ca_len = puk_store[idx].cvcert_len;
} } else {
else
ca = NULL; ca = NULL;
}
} }
} while (car && chr && eq != 0); } while (car && chr && eq != 0);
size_t ca_puk_len = 0; size_t ca_puk_len = 0;
const uint8_t *ca_puk = cvc_get_pub(ca, ca_len, &ca_puk_len); const uint8_t *ca_puk = cvc_get_pub(ca, ca_len, &ca_puk_len);
if (!ca_puk) if (!ca_puk) {
return MBEDTLS_ECP_DP_NONE; return MBEDTLS_ECP_DP_NONE;
}
size_t t81_len = 0; size_t t81_len = 0;
const uint8_t *t81 = cvc_get_field(ca_puk, ca_puk_len, &t81_len, 0x81); const uint8_t *t81 = cvc_get_field(ca_puk, ca_puk_len, &t81_len, 0x81);
if (!t81) if (!t81) {
return MBEDTLS_ECP_DP_NONE; return MBEDTLS_ECP_DP_NONE;
}
return ec_get_curve_from_prime(t81, t81_len); return ec_get_curve_from_prime(t81, t81_len);
} }
int puk_verify(const uint8_t *sig, size_t sig_len, const uint8_t *hash, size_t hash_len, const uint8_t *ca, size_t ca_len) { int puk_verify(const uint8_t *sig,
size_t sig_len,
const uint8_t *hash,
size_t hash_len,
const uint8_t *ca,
size_t ca_len)
{
size_t puk_len = 0; size_t puk_len = 0;
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len); const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
if (!puk) if (!puk) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
size_t oid_len = 0; size_t oid_len = 0;
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6); const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
if (!oid) if (!oid) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
size_t t81_len = 0, t82_len = 0; size_t t81_len = 0, t82_len = 0;
const uint8_t *t81 = cvc_get_field(puk, puk_len, &t81_len, 0x81), *t82 = cvc_get_field(puk, puk_len, &t81_len, 0x82); const uint8_t *t81 = cvc_get_field(puk, puk_len, &t81_len, 0x81), *t82 = cvc_get_field(puk,
if (!t81 || !t82) puk_len,
&t81_len,
0x82);
if (!t81 || !t82) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
mbedtls_rsa_context rsa; mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa); mbedtls_rsa_init(&rsa);
mbedtls_md_type_t md = MBEDTLS_MD_NONE; mbedtls_md_type_t md = MBEDTLS_MD_NONE;
if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_1, oid_len) == 0) if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) { } else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md); mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md);
} } else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md); mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md);
} } else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md); mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, md);
} }
@@ -525,31 +689,35 @@ int puk_verify(const uint8_t *sig, size_t sig_len, const uint8_t *hash, size_t h
} }
r = mbedtls_rsa_pkcs1_verify(&rsa, md, hash_len, hash, sig); r = mbedtls_rsa_pkcs1_verify(&rsa, md, hash_len, hash, sig);
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
if (r != 0) if (r != 0) {
return CCID_WRONG_SIGNATURE; return CCID_WRONG_SIGNATURE;
} }
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC } else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
mbedtls_md_type_t md = MBEDTLS_MD_NONE; mbedtls_md_type_t md = MBEDTLS_MD_NONE;
if (memcmp(oid, OID_ID_TA_ECDSA_SHA_1, oid_len) == 0) if (memcmp(oid, OID_ID_TA_ECDSA_SHA_1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
if (md == MBEDTLS_MD_NONE) }
if (md == MBEDTLS_MD_NONE) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
size_t t86_len = 0; size_t t86_len = 0;
const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86); const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86);
if (!t86) if (!t86) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len); mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len);
if (ec_id == MBEDTLS_ECP_DP_NONE) if (ec_id == MBEDTLS_ECP_DP_NONE) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa); mbedtls_ecdsa_init(&ecdsa);
int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id); int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id);
@@ -588,64 +756,74 @@ int puk_verify(const uint8_t *sig, size_t sig_len, const uint8_t *hash, size_t h
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
if (ret != 0) if (ret != 0) {
return CCID_WRONG_SIGNATURE; return CCID_WRONG_SIGNATURE;
}
} }
return CCID_OK; return CCID_OK;
} }
int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t ca_len) { int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t ca_len)
{
size_t puk_len = 0; size_t puk_len = 0;
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len); const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
if (!puk) if (!puk) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
size_t oid_len = 0, cv_body_len = 0, sig_len = 0; size_t oid_len = 0, cv_body_len = 0, sig_len = 0;
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6); const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
const uint8_t *cv_body = cvc_get_body(cert, cert_len, &cv_body_len); const uint8_t *cv_body = cvc_get_body(cert, cert_len, &cv_body_len);
const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len); const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len);
if (!sig) if (!sig) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
if (!cv_body) }
if (!cv_body) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
if (!oid) }
if (!oid) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
mbedtls_md_type_t md = MBEDTLS_MD_NONE; mbedtls_md_type_t md = MBEDTLS_MD_NONE;
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_1, oid_len) == 0) if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_V1_5_SHA_512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_RSA_PSS_SHA_512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
} }
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC } else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
if (memcmp(oid, OID_ID_TA_ECDSA_SHA_1, oid_len) == 0) if (memcmp(oid, OID_ID_TA_ECDSA_SHA_1, oid_len) == 0) {
md = MBEDTLS_MD_SHA1; md = MBEDTLS_MD_SHA1;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_224, oid_len) == 0) {
md = MBEDTLS_MD_SHA224; md = MBEDTLS_MD_SHA224;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_256, oid_len) == 0) {
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_384, oid_len) == 0) {
md = MBEDTLS_MD_SHA384; md = MBEDTLS_MD_SHA384;
else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) } else if (memcmp(oid, OID_ID_TA_ECDSA_SHA_512, oid_len) == 0) {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
}
} }
if (md == MBEDTLS_MD_NONE) if (md == MBEDTLS_MD_NONE) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info); uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info);
uint8_t tlv_body = 2+format_tlv_len(cv_body_len, NULL); uint8_t tlv_body = 2+format_tlv_len(cv_body_len, NULL);
int r = mbedtls_md(md_info, cv_body-tlv_body, cv_body_len+tlv_body, hash); int r = mbedtls_md(md_info, cv_body-tlv_body, cv_body_len+tlv_body, hash);
if (r != 0) if (r != 0) {
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
}
r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len); r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len);
if (r != 0) if (r != 0) {
return CCID_WRONG_SIGNATURE; return CCID_WRONG_SIGNATURE;
}
return CCID_OK; return CCID_OK;
} }

View File

@@ -40,9 +40,25 @@ typedef struct PUK {
#define MAX_PUK_STORE_ENTRIES 4 #define MAX_PUK_STORE_ENTRIES 4
extern size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len, const uint8_t *ext, size_t ext_len); extern size_t asn1_cvc_cert(void *rsa_ecdsa,
extern size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len, const uint8_t *ext, size_t ext_len); uint8_t key_type,
extern size_t asn1_build_cert_description(const uint8_t *label, size_t label_len, const uint8_t *puk, size_t puk_len, uint16_t fid, uint8_t *buf, size_t buf_len); uint8_t *buf,
size_t buf_len,
const uint8_t *ext,
size_t ext_len);
extern size_t asn1_cvc_aut(void *rsa_ecdsa,
uint8_t key_type,
uint8_t *buf,
size_t buf_len,
const uint8_t *ext,
size_t ext_len);
extern size_t asn1_build_cert_description(const uint8_t *label,
size_t label_len,
const uint8_t *puk,
size_t puk_len,
uint16_t fid,
uint8_t *buf,
size_t buf_len);
extern const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint16_t tag); extern const uint8_t *cvc_get_field(const uint8_t *data, size_t len, size_t *olen, uint16_t tag);
extern const uint8_t *cvc_get_car(const uint8_t *data, size_t len, size_t *olen); extern const uint8_t *cvc_get_car(const uint8_t *data, size_t len, size_t *olen);
extern const uint8_t *cvc_get_chr(const uint8_t *data, size_t len, size_t *olen); extern const uint8_t *cvc_get_chr(const uint8_t *data, size_t len, size_t *olen);
@@ -50,7 +66,24 @@ extern const uint8_t *cvc_get_pub(const uint8_t *data, size_t len, size_t *olen)
extern const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen); extern const uint8_t *cvc_get_ext(const uint8_t *data, size_t len, size_t *olen);
extern int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t ca_len); extern int cvc_verify(const uint8_t *cert, size_t cert_len, const uint8_t *ca, size_t ca_len);
extern mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len); extern mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, size_t ca_len);
extern int puk_verify(const uint8_t *sig, size_t sig_len, const uint8_t *hash, size_t hash_len, const uint8_t *ca, size_t ca_len); extern int puk_verify(const uint8_t *sig,
extern size_t asn1_build_prkd_ecc(const uint8_t *label, size_t label_len, const uint8_t *keyid, size_t keyid_len, size_t keysize, uint8_t *buf, size_t buf_len); size_t sig_len,
extern size_t asn1_build_prkd_rsa(const uint8_t *label, size_t label_len, const uint8_t *keyid, size_t keyid_len, size_t keysize, uint8_t *buf, size_t buf_len); const uint8_t *hash,
size_t hash_len,
const uint8_t *ca,
size_t ca_len);
extern size_t asn1_build_prkd_ecc(const uint8_t *label,
size_t label_len,
const uint8_t *keyid,
size_t keyid_len,
size_t keysize,
uint8_t *buf,
size_t buf_len);
extern size_t asn1_build_prkd_rsa(const uint8_t *label,
size_t label_len,
const uint8_t *keyid,
size_t keyid_len,
size_t keysize,
uint8_t *buf,
size_t buf_len);
#endif #endif

View File

@@ -21,39 +21,88 @@ extern const uint8_t sc_hsm_aid[];
extern int parse_token_info(const file_t *f, int mode); extern int parse_token_info(const file_t *f, int mode);
file_t file_entries[] = { file_t file_entries[] = {
/* 0 */ { .fid = 0x3f00 , .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, // MF /* 0 */ { .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL,
/* 1 */ { .fid = 0x2f00 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DIR .ef_structure = 0, .acl = { 0 } }, // MF
/* 2 */ { .fid = 0x2f01 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ATR /* 1 */ { .fid = 0x2f00, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL,
/* 3 */ { .fid = EF_TERMCA , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.GDO .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.DIR
/* 4 */ { .fid = 0x2f03 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,.data = (uint8_t *)parse_token_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo /* 2 */ { .fid = 0x2f01, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL,
/* 5 */ { .fid = 0x5015 , .parent = 0, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, //DF.PKCS15 .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.ATR
/* 6 */ { .fid = 0x5031 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ODF /* 3 */ { .fid = EF_TERMCA, .parent = 0, .name = NULL,
/* 7 */ { .fid = 0x5032 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
/* 8 */ { .fid = 0x5033 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.UnusedSpace .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.GDO
/* 9 */ { .fid = 0x1081 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (PIN1) /* 4 */ { .fid = 0x2f03, .parent = 5, .name = NULL,
/* 10 */ { .fid = 0x1082 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (PIN1) .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_token_info,
/* 11 */ { .fid = 0x1083 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (PIN1) .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.TokenInfo
/* 12 */ { .fid = 0x1088 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (SOPIN) /* 5 */ { .fid = 0x5015, .parent = 0, .name = NULL, .type = FILE_TYPE_DF, .data = NULL,
/* 13 */ { .fid = 0x1089 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (SOPIN) .ef_structure = 0, .acl = { 0 } }, //DF.PKCS15
/* 14 */ { .fid = 0x108A , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (SOPIN) /* 6 */ { .fid = 0x5031, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL,
/* 15 */ { .fid = EF_DEVOPS , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //Device options .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.ODF
/* 16 */ { .fid = EF_PRKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PrKDFs /* 7 */ { .fid = 0x5032, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL,
/* 17 */ { .fid = EF_PUKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PuKDFs .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.TokenInfo
/* 18 */ { .fid = EF_CDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.CDFs /* 8 */ { .fid = 0x5033, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL,
/* 19 */ { .fid = EF_AODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.AODFs .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.UnusedSpace
/* 20 */ { .fid = EF_DODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DODFs /* 9 */ { .fid = 0x1081, .parent = 5, .name = NULL,
/* 21 */ { .fid = EF_SKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.SKDFs .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
/* 22 */ { .fid = EF_KEY_DOMAIN, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //Key domain options .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //PIN (PIN1)
/* 23 */ { .fid = EF_META , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //EF.CDFs /* 10 */ { .fid = 0x1082, .parent = 5, .name = NULL,
/* 24 */ { .fid = EF_PUKAUT, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //Public Key Authentication .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
/* 25 */ { .fid = EF_KEY_DEV, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //Device Key .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //max retries PIN (PIN1)
/* 26 */ { .fid = EF_PRKD_DEV, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PrKD Device /* 11 */ { .fid = 0x1083, .parent = 5, .name = NULL,
/* 27 */ { .fid = EF_EE_DEV, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //End Entity Certificate Device .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
/* 28 */ { .fid = EF_MKEK , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //MKEK .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //retries PIN (PIN1)
/* 29 */ { .fid = EF_MKEK_SO , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //MKEK with SO-PIN /* 12 */ { .fid = 0x1088, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //PIN (SOPIN)
/* 13 */ { .fid = 0x1089, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //max retries PIN (SOPIN)
/* 14 */ { .fid = 0x108A, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //retries PIN (SOPIN)
/* 15 */ { .fid = EF_DEVOPS, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Device options
/* 16 */ { .fid = EF_PRKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.PrKDFs
/* 17 */ { .fid = EF_PUKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.PuKDFs
/* 18 */ { .fid = EF_CDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.CDFs
/* 19 */ { .fid = EF_AODFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.AODFs
/* 20 */ { .fid = EF_DODFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.DODFs
/* 21 */ { .fid = EF_SKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.SKDFs
/* 22 */ { .fid = EF_KEY_DOMAIN, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Key domain options
/* 23 */ { .fid = EF_META, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //EF.CDFs
/* 24 */ { .fid = EF_PUKAUT, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Public Key Authentication
/* 25 */ { .fid = EF_KEY_DEV, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Device Key
/* 26 */ { .fid = EF_PRKD_DEV, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //PrKD Device
/* 27 */ { .fid = EF_EE_DEV, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //End Entity Certificate Device
/* 28 */ { .fid = EF_MKEK, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //MKEK
/* 29 */ { .fid = EF_MKEK_SO, .parent = 5, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //MKEK with SO-PIN
///* 30 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, ///* 30 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} },
/* 31 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, /* 31 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF,
/* 32 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } },
/* 32 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL,
.ef_structure = 0, .acl = { 0 } } //end
}; };
const file_t *MF = &file_entries[0]; const file_t *MF = &file_entries[0];

View File

@@ -44,15 +44,18 @@ uint32_t crc32c(const uint8_t *buf, size_t len)
uint32_t crc = ~0; uint32_t crc = ~0;
while (len--) { while (len--) {
crc ^= *buf++; crc ^= *buf++;
for (int k = 0; k < 8; k++) for (int k = 0; k < 8; k++) {
crc = (crc >> 1) ^ (POLY & (0 - (crc & 1))); crc = (crc >> 1) ^ (POLY & (0 - (crc & 1)));
}
} }
return ~crc; return ~crc;
} }
int load_mkek(uint8_t *mkek) { int load_mkek(uint8_t *mkek)
if (has_session_pin == false && has_session_sopin == false) {
if (has_session_pin == false && has_session_sopin == false) {
return CCID_NO_LOGIN; return CCID_NO_LOGIN;
}
const uint8_t *pin = NULL; const uint8_t *pin = NULL;
if (pin == NULL && has_session_pin == true) { if (pin == NULL && has_session_pin == true) {
file_t *tf = search_by_fid(EF_MKEK, NULL, SPECIFY_EF); file_t *tf = search_by_fid(EF_MKEK, NULL, SPECIFY_EF);
@@ -68,56 +71,73 @@ int load_mkek(uint8_t *mkek) {
pin = session_sopin; pin = session_sopin;
} }
} }
if (pin == NULL) //Should never happen if (pin == NULL) { //Should never happen
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
}
if (has_mkek_mask) { if (has_mkek_mask) {
for (int i = 0; i < MKEK_KEY_SIZE; i++) { for (int i = 0; i < MKEK_KEY_SIZE; i++) {
MKEK_KEY(mkek)[i] ^= mkek_mask[i]; MKEK_KEY(mkek)[i] ^= mkek_mask[i];
} }
} }
int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); int ret =
if (ret != 0) aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE);
if (ret != 0) {
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t *)MKEK_CHECKSUM(mkek)) }
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t *) MKEK_CHECKSUM(mkek)) {
return CCID_WRONG_DKEK; return CCID_WRONG_DKEK;
}
return CCID_OK; return CCID_OK;
} }
mse_t mse = {.init = false}; mse_t mse = { .init = false };
int mse_decrypt_ct(uint8_t *data, size_t len) { int mse_decrypt_ct(uint8_t *data, size_t len)
{
mbedtls_chachapoly_context chatx; mbedtls_chachapoly_context chatx;
mbedtls_chachapoly_init(&chatx); mbedtls_chachapoly_init(&chatx);
mbedtls_chachapoly_setkey(&chatx, mse.key_enc + 12); mbedtls_chachapoly_setkey(&chatx, mse.key_enc + 12);
int ret = mbedtls_chachapoly_auth_decrypt(&chatx, len - 16, mse.key_enc, mse.Qpt, 65, data + len - 16, data, data); int ret = mbedtls_chachapoly_auth_decrypt(&chatx,
len - 16,
mse.key_enc,
mse.Qpt,
65,
data + len - 16,
data,
data);
mbedtls_chachapoly_free(&chatx); mbedtls_chachapoly_free(&chatx);
return ret; return ret;
} }
int load_dkek(uint8_t id, uint8_t *dkek) { int load_dkek(uint8_t id, uint8_t *dkek)
{
file_t *tf = search_dynamic_file(EF_DKEK+id); file_t *tf = search_dynamic_file(EF_DKEK+id);
if (!tf) if (!tf) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
}
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
return mkek_decrypt(dkek, DKEK_KEY_SIZE); return mkek_decrypt(dkek, DKEK_KEY_SIZE);
} }
void release_mkek(uint8_t *mkek) { void release_mkek(uint8_t *mkek)
{
mbedtls_platform_zeroize(mkek, MKEK_SIZE); mbedtls_platform_zeroize(mkek, MKEK_SIZE);
} }
int store_mkek(const uint8_t *mkek) { int store_mkek(const uint8_t *mkek)
if (has_session_pin == false && has_session_sopin == false) {
if (has_session_pin == false && has_session_sopin == false) {
return CCID_NO_LOGIN; return CCID_NO_LOGIN;
}
uint8_t tmp_mkek[MKEK_SIZE]; uint8_t tmp_mkek[MKEK_SIZE];
if (mkek == NULL) { if (mkek == NULL) {
const uint8_t *rd = random_bytes_get(MKEK_IV_SIZE+MKEK_KEY_SIZE); const uint8_t *rd = random_bytes_get(MKEK_IV_SIZE+MKEK_KEY_SIZE);
memcpy(tmp_mkek, rd, MKEK_IV_SIZE+MKEK_KEY_SIZE); memcpy(tmp_mkek, rd, MKEK_IV_SIZE+MKEK_KEY_SIZE);
} } else {
else
memcpy(tmp_mkek, mkek, MKEK_SIZE); memcpy(tmp_mkek, mkek, MKEK_SIZE);
*(uint32_t*)MKEK_CHECKSUM(tmp_mkek) = crc32c(MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE); }
*(uint32_t *) MKEK_CHECKSUM(tmp_mkek) = crc32c(MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE);
if (has_session_pin) { if (has_session_pin) {
uint8_t tmp_mkek_pin[MKEK_SIZE]; uint8_t tmp_mkek_pin[MKEK_SIZE];
memcpy(tmp_mkek_pin, tmp_mkek, MKEK_SIZE); memcpy(tmp_mkek_pin, tmp_mkek, MKEK_SIZE);
@@ -127,7 +147,10 @@ int store_mkek(const uint8_t *mkek) {
release_mkek(tmp_mkek_pin); release_mkek(tmp_mkek_pin);
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
} }
aes_encrypt_cfb_256(session_pin, MKEK_IV(tmp_mkek_pin), MKEK_KEY(tmp_mkek_pin), MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE); aes_encrypt_cfb_256(session_pin,
MKEK_IV(tmp_mkek_pin),
MKEK_KEY(tmp_mkek_pin),
MKEK_KEY_SIZE+MKEK_KEY_CS_SIZE);
flash_write_data_to_file(tf, tmp_mkek_pin, MKEK_SIZE); flash_write_data_to_file(tf, tmp_mkek_pin, MKEK_SIZE);
release_mkek(tmp_mkek_pin); release_mkek(tmp_mkek_pin);
} }
@@ -140,7 +163,10 @@ int store_mkek(const uint8_t *mkek) {
release_mkek(tmp_mkek_sopin); release_mkek(tmp_mkek_sopin);
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
} }
aes_encrypt_cfb_256(session_sopin, MKEK_IV(tmp_mkek_sopin), MKEK_KEY(tmp_mkek_sopin), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); aes_encrypt_cfb_256(session_sopin,
MKEK_IV(tmp_mkek_sopin),
MKEK_KEY(tmp_mkek_sopin),
MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
flash_write_data_to_file(tf, tmp_mkek_sopin, MKEK_SIZE); flash_write_data_to_file(tf, tmp_mkek_sopin, MKEK_SIZE);
release_mkek(tmp_mkek_sopin); release_mkek(tmp_mkek_sopin);
} }
@@ -149,106 +175,133 @@ int store_mkek(const uint8_t *mkek) {
return CCID_OK; return CCID_OK;
} }
int store_dkek_key(uint8_t id, uint8_t *dkek) { int store_dkek_key(uint8_t id, uint8_t *dkek)
{
file_t *tf = search_dynamic_file(EF_DKEK+id); file_t *tf = search_dynamic_file(EF_DKEK+id);
if (!tf) if (!tf) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
}
int r = mkek_encrypt(dkek, DKEK_KEY_SIZE); int r = mkek_encrypt(dkek, DKEK_KEY_SIZE);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
flash_write_data_to_file(tf, dkek, DKEK_KEY_SIZE); flash_write_data_to_file(tf, dkek, DKEK_KEY_SIZE);
low_flash_available(); low_flash_available();
return CCID_OK; return CCID_OK;
} }
int save_dkek_key(uint8_t id, const uint8_t *key) { int save_dkek_key(uint8_t id, const uint8_t *key)
{
uint8_t dkek[DKEK_KEY_SIZE]; uint8_t dkek[DKEK_KEY_SIZE];
if (!key) { if (!key) {
file_t *tf = search_dynamic_file(EF_DKEK+id); file_t *tf = search_dynamic_file(EF_DKEK+id);
if (!tf) if (!tf) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
}
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
} } else {
else
memcpy(dkek, key, DKEK_KEY_SIZE); memcpy(dkek, key, DKEK_KEY_SIZE);
}
return store_dkek_key(id, dkek); return store_dkek_key(id, dkek);
} }
int import_dkek_share(uint8_t id, const uint8_t *share) { int import_dkek_share(uint8_t id, const uint8_t *share)
{
uint8_t tmp_dkek[DKEK_KEY_SIZE]; uint8_t tmp_dkek[DKEK_KEY_SIZE];
file_t *tf = search_dynamic_file(EF_DKEK+id); file_t *tf = search_dynamic_file(EF_DKEK+id);
if (!tf) if (!tf) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
}
memset(tmp_dkek, 0, sizeof(tmp_dkek)); memset(tmp_dkek, 0, sizeof(tmp_dkek));
if (file_get_size(tf) == DKEK_KEY_SIZE) if (file_get_size(tf) == DKEK_KEY_SIZE) {
memcpy(tmp_dkek, file_get_data(tf),DKEK_KEY_SIZE); memcpy(tmp_dkek, file_get_data(tf), DKEK_KEY_SIZE);
for (int i = 0; i < DKEK_KEY_SIZE; i++) }
for (int i = 0; i < DKEK_KEY_SIZE; i++) {
tmp_dkek[i] ^= share[i]; tmp_dkek[i] ^= share[i];
}
flash_write_data_to_file(tf, tmp_dkek, DKEK_KEY_SIZE); flash_write_data_to_file(tf, tmp_dkek, DKEK_KEY_SIZE);
low_flash_available(); low_flash_available();
return CCID_OK; return CCID_OK;
} }
int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes int dkek_kcv(uint8_t id, uint8_t *kcv) //kcv 8 bytes
{
uint8_t hsh[32], dkek[DKEK_KEY_SIZE]; uint8_t hsh[32], dkek[DKEK_KEY_SIZE];
memset(kcv, 0, 8); memset(kcv, 0, 8);
memset(hsh, 0, sizeof(hsh)); memset(hsh, 0, sizeof(hsh));
int r = load_dkek(id, dkek); int r = load_dkek(id, dkek);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
hash256(dkek, DKEK_KEY_SIZE, hsh); hash256(dkek, DKEK_KEY_SIZE, hsh);
mbedtls_platform_zeroize(dkek, sizeof(dkek)); mbedtls_platform_zeroize(dkek, sizeof(dkek));
memcpy(kcv, hsh, 8); memcpy(kcv, hsh, 8);
return CCID_OK; return CCID_OK;
} }
int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes int dkek_kenc(uint8_t id, uint8_t *kenc) //kenc 32 bytes
{
uint8_t dkek[DKEK_KEY_SIZE+4]; uint8_t dkek[DKEK_KEY_SIZE+4];
memset(kenc, 0, 32); memset(kenc, 0, 32);
int r = load_dkek(id, dkek); int r = load_dkek(id, dkek);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4); memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
hash256(dkek, sizeof(dkek), kenc); hash256(dkek, sizeof(dkek), kenc);
mbedtls_platform_zeroize(dkek, sizeof(dkek)); mbedtls_platform_zeroize(dkek, sizeof(dkek));
return CCID_OK; return CCID_OK;
} }
int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes int dkek_kmac(uint8_t id, uint8_t *kmac) //kmac 32 bytes
{
uint8_t dkek[DKEK_KEY_SIZE+4]; uint8_t dkek[DKEK_KEY_SIZE+4];
memset(kmac, 0, 32); memset(kmac, 0, 32);
int r = load_dkek(id, dkek); int r = load_dkek(id, dkek);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4); memcpy(dkek+DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
hash256(dkek, DKEK_KEY_SIZE+4, kmac); hash256(dkek, DKEK_KEY_SIZE+4, kmac);
mbedtls_platform_zeroize(dkek, sizeof(dkek)); mbedtls_platform_zeroize(dkek, sizeof(dkek));
return CCID_OK; return CCID_OK;
} }
int mkek_encrypt(uint8_t *data, size_t len) { int mkek_encrypt(uint8_t *data, size_t len)
{
int r; int r;
uint8_t mkek[MKEK_SIZE+4]; uint8_t mkek[MKEK_SIZE+4];
if ((r = load_mkek(mkek)) != CCID_OK) if ((r = load_mkek(mkek)) != CCID_OK) {
return r; return r;
}
r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
release_mkek(mkek); release_mkek(mkek);
return r; return r;
} }
int mkek_decrypt(uint8_t *data, size_t len) { int mkek_decrypt(uint8_t *data, size_t len)
{
int r; int r;
uint8_t mkek[MKEK_SIZE+4]; uint8_t mkek[MKEK_SIZE+4];
if ((r = load_mkek(mkek)) != CCID_OK) if ((r = load_mkek(mkek)) != CCID_OK) {
return r; return r;
}
r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
release_mkek(mkek); release_mkek(mkek);
return r; return r;
} }
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) { int dkek_encode_key(uint8_t id,
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES)) 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; return CCID_WRONG_DATA;
}
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));
@@ -258,84 +311,104 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_
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);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
uint8_t kcv[8]; uint8_t kcv[8];
memset(kcv, 0, sizeof(kcv)); memset(kcv, 0, sizeof(kcv));
r = dkek_kcv(id, kcv); r = dkek_kcv(id, kcv);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
uint8_t kmac[32]; uint8_t kmac[32];
memset(kmac, 0, sizeof(kmac)); memset(kmac, 0, sizeof(kmac));
r = dkek_kmac(id, kmac); r = dkek_kmac(id, kmac);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
if (key_type & HSM_KEY_AES) { if (key_type & HSM_KEY_AES) {
if (key_type & HSM_KEY_AES_128) if (key_type & HSM_KEY_AES_128) {
kb_len = 16; kb_len = 16;
else if (key_type & HSM_KEY_AES_192) } else if (key_type & HSM_KEY_AES_192) {
kb_len = 24; kb_len = 24;
else if (key_type & HSM_KEY_AES_256) } else if (key_type & HSM_KEY_AES_256) {
kb_len = 32; kb_len = 32;
}
if (kb_len != 16 && kb_len != 24 && kb_len != 32) if (kb_len != 16 && kb_len != 24 && kb_len != 32) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
if (*out_len < 8+1+10+6+4+(2+32+14)+16) }
if (*out_len < 8+1+10+6+4+(2+32+14)+16) {
return CCID_WRONG_LENGTH; return CCID_WRONG_LENGTH;
}
put_uint16_t(kb_len, kb+8); put_uint16_t(kb_len, kb+8);
memcpy(kb+10, key_ctx, kb_len); memcpy(kb+10, key_ctx, kb_len);
kb_len += 2; kb_len += 2;
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;
} } 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
return CCID_WRONG_LENGTH; return CCID_WRONG_LENGTH;
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; }
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
kb_len = 0; kb_len = 0;
put_uint16_t(mbedtls_rsa_get_len(rsa)*8, kb+8+kb_len); kb_len += 2; 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; 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); 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; 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); 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; 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); mbedtls_mpi_write_binary(&rsa->E, kb+8+kb_len, mbedtls_mpi_size(&rsa->E));
kb_len += mbedtls_mpi_size(&rsa->E);
algo = (uint8_t *)"\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02"; algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02";
algo_len = 12; algo_len = 12;
} } else if (key_type & HSM_KEY_EC) {
else if (key_type & HSM_KEY_EC) { if (*out_len < 8+1+12+6+(8+2*8+9*66+2+4)+16) { //4 bytes pading
if (*out_len < 8+1+12+6+(8+2*8+9*66+2+4)+16) //4 bytes pading
return CCID_WRONG_LENGTH; return CCID_WRONG_LENGTH;
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx; }
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
kb_len = 0; 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.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; 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); 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; 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); 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; 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); 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; 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); mbedtls_mpi_write_binary(&ecdsa->grp.N, kb+8+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_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; 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.X, kb+8+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); 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; 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); mbedtls_mpi_write_binary(&ecdsa->d, kb+8+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_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; 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.X, kb+8+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); 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 = (uint8_t *)"\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03"; algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
algo_len = 12; algo_len = 12;
} }
memset(out, 0, *out_len); memset(out, 0, *out_len);
@@ -344,107 +417,142 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, size_
memcpy(out+*out_len, kcv, 8); memcpy(out+*out_len, kcv, 8);
*out_len += 8; *out_len += 8;
if (key_type & HSM_KEY_AES) if (key_type & HSM_KEY_AES) {
out[*out_len] = 15; out[*out_len] = 15;
else if (key_type & HSM_KEY_RSA) } else if (key_type & HSM_KEY_RSA) {
out[*out_len] = 5; out[*out_len] = 5;
else if (key_type & HSM_KEY_EC) } else if (key_type & HSM_KEY_EC) {
out[*out_len] = 12; out[*out_len] = 12;
}
*out_len += 1; *out_len += 1;
if (algo) { if (algo) {
memcpy(out+*out_len, algo, algo_len); memcpy(out+*out_len, algo, algo_len);
*out_len += algo_len; *out_len += algo_len;
} } else {
else
*out_len += 2; *out_len += 2;
}
if (allowed && allowed_len > 0) { if (allowed && allowed_len > 0) {
put_uint16_t(allowed_len, out+*out_len); *out_len += 2; 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;
} } else {
else
*out_len += 2; *out_len += 2;
}
//add 4 zeros //add 4 zeros
*out_len += 4; *out_len += 4;
memcpy(kb, random_bytes_get(8), 8); memcpy(kb, random_bytes_get(8), 8);
kb_len += 8; //8 random bytes kb_len += 8; //8 random bytes
int kb_len_pad = ((int)(kb_len/16))*16; int kb_len_pad = ((int) (kb_len/16))*16;
if (kb_len % 16 > 0) if (kb_len % 16 > 0) {
kb_len_pad = ((int)(kb_len/16)+1)*16; kb_len_pad = ((int) (kb_len/16)+1)*16;
}
//key already copied at kb+10 //key already copied at kb+10
if (kb_len < kb_len_pad) { if (kb_len < kb_len_pad) {
kb[kb_len] = 0x80; kb[kb_len] = 0x80;
} }
r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad); r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
memcpy(out+*out_len, kb, kb_len_pad); memcpy(out+*out_len, kb, kb_len_pad);
*out_len += kb_len_pad; *out_len += kb_len_pad;
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), 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; *out_len += 16;
if (r != 0) if (r != 0) {
return r; return r;
}
return CCID_OK; return CCID_OK;
} }
int dkek_type_key(const uint8_t *in) { int dkek_type_key(const uint8_t *in)
if (in[8] == 5 || in[8] == 6) {
if (in[8] == 5 || in[8] == 6) {
return HSM_KEY_RSA; return HSM_KEY_RSA;
else if (in[8] == 12) } else if (in[8] == 12) {
return HSM_KEY_EC; return HSM_KEY_EC;
else if (in[8] == 15) } else if (in[8] == 15) {
return HSM_KEY_AES; return HSM_KEY_AES;
}
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, uint8_t **allowed, size_t *allowed_len) { 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));
r = dkek_kcv(id, kcv); r = dkek_kcv(id, kcv);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
uint8_t kmac[32]; uint8_t kmac[32];
memset(kmac, 0, sizeof(kmac)); memset(kmac, 0, sizeof(kmac));
r = dkek_kmac(id, kmac); r = dkek_kmac(id, kmac);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
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);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
if (memcmp(kcv, in, 8) != 0) if (memcmp(kcv, in, 8) != 0) {
return CCID_WRONG_DKEK; return CCID_WRONG_DKEK;
}
uint8_t signature[16]; uint8_t signature[16];
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len-16, signature); r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB),
if (r != 0) kmac,
256,
in,
in_len-16,
signature);
if (r != 0) {
return CCID_WRONG_SIGNATURE; return CCID_WRONG_SIGNATURE;
if (memcmp(signature, in+in_len-16, 16) != 0) }
if (memcmp(signature, in+in_len-16, 16) != 0) {
return CCID_WRONG_SIGNATURE; return CCID_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 CCID_WRONG_DATA; return CCID_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) 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 CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
if (key_type == 12 && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) if (key_type == 12 &&
memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) {
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
size_t ofs = 9; size_t ofs = 9;
@@ -454,7 +562,7 @@ 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 = (uint8_t *) (in+ofs+2);
*allowed_len = len; *allowed_len = len;
ofs += len+2; ofs += len+2;
@@ -466,21 +574,24 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len,
len = get_uint16_t(in, ofs); len = get_uint16_t(in, ofs);
ofs += len+2; ofs += len+2;
if ((in_len-16-ofs) % 16 != 0) if ((in_len-16-ofs) % 16 != 0) {
return CCID_WRONG_PADDING; return CCID_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));
memcpy(kb, in+ofs, 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); r = aes_decrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
int key_size = get_uint16_t(kb, 8); int key_size = get_uint16_t(kb, 8);
if (key_size_out) if (key_size_out) {
*key_size_out = key_size; *key_size_out = key_size;
}
ofs = 10; ofs = 10;
if (key_type == 5 || key_type == 6) { if (key_type == 5 || key_type == 6) {
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
mbedtls_rsa_init(rsa); mbedtls_rsa_init(rsa);
if (key_type == 5) { if (key_type == 5) {
len = get_uint16_t(kb, ofs); ofs += 2; len = get_uint16_t(kb, ofs); ofs += 2;
@@ -496,8 +607,7 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len,
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
} }
} } else if (key_type == 6) {
else if (key_type == 6) {
//DP-1 //DP-1
len = get_uint16_t(kb, ofs); ofs += len+2; len = get_uint16_t(kb, ofs); ofs += len+2;
@@ -537,8 +647,7 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len,
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
} }
} } else if (key_type == 6) {
else if (key_type == 6) {
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E); r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
@@ -556,9 +665,8 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len,
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
} }
} } else if (key_type == 12) {
else if (key_type == 12) { mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
mbedtls_ecdsa_init(ecdsa); mbedtls_ecdsa_init(ecdsa);
//A //A
@@ -603,8 +711,7 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, size_t in_len,
mbedtls_ecdsa_free(ecdsa); mbedtls_ecdsa_free(ecdsa);
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
} }
} } else if (key_type == 15) {
else if (key_type == 15) {
memcpy(key_ctx, kb+ofs, key_size); memcpy(key_ctx, kb+ofs, key_size);
} }
return CCID_OK; return CCID_OK;

View File

@@ -33,9 +33,21 @@ 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, const uint8_t *, size_t); 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, uint8_t **, size_t *); 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)

View File

@@ -29,12 +29,13 @@
const uint8_t sc_hsm_aid[] = { const uint8_t sc_hsm_aid[] = {
11, 11,
0xE8,0x2B,0x06,0x01,0x04,0x01,0x81,0xC3,0x1F,0x02,0x01 0xE8, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x81, 0xC3, 0x1F, 0x02, 0x01
}; };
const uint8_t atr_sc_hsm[] = { const uint8_t atr_sc_hsm[] = {
24, 24,
0x3B,0xFE,0x18,0x00,0x00,0x81,0x31,0xFE,0x45,0x80,0x31,0x81,0x54,0x48,0x53,0x4D,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0xFA 0x3B, 0xFE, 0x18, 0x00, 0x00, 0x81, 0x31, 0xFE, 0x45, 0x80, 0x31, 0x81, 0x54, 0x48, 0x53, 0x4D,
0x31, 0x73, 0x80, 0x21, 0x40, 0x81, 0x07, 0xFA
}; };
uint8_t session_pin[32], session_sopin[32]; uint8_t session_pin[32], session_sopin[32];
@@ -77,8 +78,9 @@ extern int cmd_pso();
extern const uint8_t *ccid_atr; extern const uint8_t *ccid_atr;
app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len) { app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len)
if (!memcmp(aid, sc_hsm_aid+1, MIN(aid_len,sc_hsm_aid[0]))) { {
if (!memcmp(aid, sc_hsm_aid+1, MIN(aid_len, sc_hsm_aid[0]))) {
a->aid = sc_hsm_aid; a->aid = sc_hsm_aid;
a->process_apdu = sc_hsm_process_apdu; a->process_apdu = sc_hsm_process_apdu;
a->unload = sc_hsm_unload; a->unload = sc_hsm_unload;
@@ -88,12 +90,14 @@ app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len) {
return NULL; return NULL;
} }
void __attribute__ ((constructor)) sc_hsm_ctor() { void __attribute__((constructor)) sc_hsm_ctor()
{
ccid_atr = atr_sc_hsm; ccid_atr = atr_sc_hsm;
register_app(sc_hsm_select_aid); register_app(sc_hsm_select_aid);
} }
void scan_files() { void scan_files()
{
file_pin1 = search_by_fid(0x1081, NULL, SPECIFY_EF); file_pin1 = search_by_fid(0x1081, NULL, SPECIFY_EF);
if (file_pin1) { if (file_pin1) {
if (!file_pin1->data) { if (!file_pin1->data) {
@@ -101,8 +105,7 @@ void scan_files() {
const uint8_t empty[33] = { 0 }; const uint8_t empty[33] = { 0 };
flash_write_data_to_file(file_pin1, empty, sizeof(empty)); flash_write_data_to_file(file_pin1, empty, sizeof(empty));
} }
} } else {
else {
printf("FATAL ERROR: PIN1 not found in memory!\r\n"); printf("FATAL ERROR: PIN1 not found in memory!\r\n");
} }
file_sopin = search_by_fid(0x1088, NULL, SPECIFY_EF); file_sopin = search_by_fid(0x1088, NULL, SPECIFY_EF);
@@ -112,8 +115,7 @@ void scan_files() {
const uint8_t empty[33] = { 0 }; const uint8_t empty[33] = { 0 };
flash_write_data_to_file(file_sopin, empty, sizeof(empty)); flash_write_data_to_file(file_sopin, empty, sizeof(empty));
} }
} } else {
else {
printf("FATAL ERROR: SOPIN not found in memory!\r\n"); printf("FATAL ERROR: SOPIN not found in memory!\r\n");
} }
file_retries_pin1 = search_by_fid(0x1083, NULL, SPECIFY_EF); file_retries_pin1 = search_by_fid(0x1083, NULL, SPECIFY_EF);
@@ -123,8 +125,7 @@ void scan_files() {
const uint8_t retries = 3; const uint8_t retries = 3;
flash_write_data_to_file(file_retries_pin1, &retries, sizeof(uint8_t)); flash_write_data_to_file(file_retries_pin1, &retries, sizeof(uint8_t));
} }
} } else {
else {
printf("FATAL ERROR: Retries PIN1 not found in memory!\r\n"); printf("FATAL ERROR: Retries PIN1 not found in memory!\r\n");
} }
file_retries_sopin = search_by_fid(0x108A, NULL, SPECIFY_EF); file_retries_sopin = search_by_fid(0x108A, NULL, SPECIFY_EF);
@@ -134,8 +135,7 @@ void scan_files() {
const uint8_t retries = 15; const uint8_t retries = 15;
flash_write_data_to_file(file_retries_sopin, &retries, sizeof(uint8_t)); flash_write_data_to_file(file_retries_sopin, &retries, sizeof(uint8_t));
} }
} } else {
else {
printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n"); printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
} }
file_t *tf = NULL; file_t *tf = NULL;
@@ -147,8 +147,7 @@ void scan_files() {
const uint8_t retries = 3; const uint8_t retries = 3;
flash_write_data_to_file(tf, &retries, sizeof(uint8_t)); flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
} }
} } else {
else {
printf("FATAL ERROR: Max Retries PIN1 not found in memory!\r\n"); printf("FATAL ERROR: Max Retries PIN1 not found in memory!\r\n");
} }
tf = search_by_fid(0x1089, NULL, SPECIFY_EF); tf = search_by_fid(0x1089, NULL, SPECIFY_EF);
@@ -158,14 +157,14 @@ void scan_files() {
const uint8_t retries = 15; const uint8_t retries = 15;
flash_write_data_to_file(tf, &retries, sizeof(uint8_t)); flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
} }
} } else {
else {
printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n"); printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
} }
low_flash_available(); low_flash_available();
} }
void scan_all() { void scan_all()
{
scan_flash(); scan_flash();
scan_files(); scan_files();
} }
@@ -175,30 +174,40 @@ int puk_store_entries = 0;
PUK *current_puk = NULL; PUK *current_puk = NULL;
uint8_t puk_status[MAX_PUK]; uint8_t puk_status[MAX_PUK];
int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy) { int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy)
if (data == NULL || data_len == 0) {
if (data == NULL || data_len == 0) {
return CCID_ERR_NULL_PARAM; return CCID_ERR_NULL_PARAM;
if (puk_store_entries == MAX_PUK_STORE_ENTRIES) }
if (puk_store_entries == MAX_PUK_STORE_ENTRIES) {
return CCID_ERR_MEMORY_FATAL; return CCID_ERR_MEMORY_FATAL;
}
puk_store[puk_store_entries].copied = copy; puk_store[puk_store_entries].copied = copy;
if (copy == true) { if (copy == true) {
uint8_t *tmp = (uint8_t *)calloc(data_len, sizeof(uint8_t)); uint8_t *tmp = (uint8_t *) calloc(data_len, sizeof(uint8_t));
memcpy(tmp, data, data_len); memcpy(tmp, data, data_len);
puk_store[puk_store_entries].cvcert = tmp; puk_store[puk_store_entries].cvcert = tmp;
} } else {
else
puk_store[puk_store_entries].cvcert = data; puk_store[puk_store_entries].cvcert = data;
}
puk_store[puk_store_entries].cvcert_len = data_len; puk_store[puk_store_entries].cvcert_len = data_len;
puk_store[puk_store_entries].chr = cvc_get_chr(puk_store[puk_store_entries].cvcert, data_len, &puk_store[puk_store_entries].chr_len); puk_store[puk_store_entries].chr = cvc_get_chr(puk_store[puk_store_entries].cvcert,
puk_store[puk_store_entries].car = cvc_get_car(puk_store[puk_store_entries].cvcert, data_len, &puk_store[puk_store_entries].car_len); data_len,
puk_store[puk_store_entries].puk = cvc_get_pub(puk_store[puk_store_entries].cvcert, data_len, &puk_store[puk_store_entries].puk_len); &puk_store[puk_store_entries].chr_len);
puk_store[puk_store_entries].car = cvc_get_car(puk_store[puk_store_entries].cvcert,
data_len,
&puk_store[puk_store_entries].car_len);
puk_store[puk_store_entries].puk = cvc_get_pub(puk_store[puk_store_entries].cvcert,
data_len,
&puk_store[puk_store_entries].puk_len);
puk_store_entries++; puk_store_entries++;
return CCID_OK; return CCID_OK;
} }
int puk_store_select_chr(const uint8_t *chr) { int puk_store_select_chr(const uint8_t *chr)
{
for (int i = 0; i < puk_store_entries; i++) { for (int i = 0; i < puk_store_entries; i++) {
if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) { if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) {
current_puk = &puk_store[i]; current_puk = &puk_store[i];
@@ -208,48 +217,56 @@ int puk_store_select_chr(const uint8_t *chr) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
} }
void init_sc_hsm() { void init_sc_hsm()
{
scan_all(); scan_all();
has_session_pin = has_session_sopin = false; has_session_pin = has_session_sopin = false;
isUserAuthenticated = false; isUserAuthenticated = false;
cmd_select(); cmd_select();
if (puk_store_entries > 0) { /* From previous session */ if (puk_store_entries > 0) { /* From previous session */
for (int i = 0; i < puk_store_entries; i++) { for (int i = 0; i < puk_store_entries; i++) {
if (puk_store[i].copied == true) if (puk_store[i].copied == true) {
free((uint8_t *)puk_store[i].cvcert); free((uint8_t *) puk_store[i].cvcert);
}
} }
} }
memset(puk_store, 0, sizeof(puk_store)); memset(puk_store, 0, sizeof(puk_store));
puk_store_entries = 0; puk_store_entries = 0;
file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF); file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF);
if (fterm) if (fterm) {
add_cert_puk_store(file_get_data(fterm), file_get_size(fterm), false); add_cert_puk_store(file_get_data(fterm), file_get_size(fterm), false);
}
for (int i = 0; i < 0xfe; i++) { for (int i = 0; i < 0xfe; i++) {
file_t *ef = search_dynamic_file((CA_CERTIFICATE_PREFIX << 8) | i); file_t *ef = search_dynamic_file((CA_CERTIFICATE_PREFIX << 8) | i);
if (ef && file_get_size(ef) > 0) if (ef && file_get_size(ef) > 0) {
add_cert_puk_store(file_get_data(ef), file_get_size(ef), false); add_cert_puk_store(file_get_data(ef), file_get_size(ef), false);
}
} }
dev_name = cvc_get_chr(file_get_data(fterm), file_get_size(fterm), &dev_name_len); dev_name = cvc_get_chr(file_get_data(fterm), file_get_size(fterm), &dev_name_len);
memset(puk_status, 0, sizeof(puk_status)); memset(puk_status, 0, sizeof(puk_status));
} }
int sc_hsm_unload() { int sc_hsm_unload()
{
has_session_pin = has_session_sopin = false; has_session_pin = has_session_sopin = false;
isUserAuthenticated = false; isUserAuthenticated = false;
sm_session_pin_len = 0; sm_session_pin_len = 0;
return CCID_OK; return CCID_OK;
} }
uint16_t get_device_options() { uint16_t get_device_options()
{
file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
if (file_has_data(ef)) if (file_has_data(ef)) {
return (file_read_uint8(file_get_data(ef)) << 8) | file_read_uint8(file_get_data(ef)+1); return (file_read_uint8(file_get_data(ef)) << 8) | file_read_uint8(file_get_data(ef)+1);
}
return 0x0; return 0x0;
} }
extern uint32_t board_button_read(void); extern uint32_t board_button_read(void);
bool wait_button_pressed() { bool wait_button_pressed()
{
uint32_t val = EV_PRESS_BUTTON; uint32_t val = EV_PRESS_BUTTON;
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
@@ -257,14 +274,14 @@ bool wait_button_pressed() {
queue_try_add(&card_to_usb_q, &val); queue_try_add(&card_to_usb_q, &val);
do { do {
queue_remove_blocking(&usb_to_card_q, &val); queue_remove_blocking(&usb_to_card_q, &val);
} } while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT);
while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT);
} }
#endif #endif
return val == EV_BUTTON_TIMEOUT; return val == EV_BUTTON_TIMEOUT;
} }
int parse_token_info(const file_t *f, int mode) { int parse_token_info(const file_t *f, int mode)
{
char *label = "SmartCard-HSM"; char *label = "SmartCard-HSM";
char *manu = "Pol Henarejos"; char *manu = "Pol Henarejos";
if (mode == 1) { if (mode == 1) {
@@ -273,12 +290,12 @@ int parse_token_info(const file_t *f, int mode) {
*p++ = 0; //set later *p++ = 0; //set later
*p++ = 0x2; *p++ = 1; *p++ = HSM_VERSION_MAJOR; *p++ = 0x2; *p++ = 1; *p++ = HSM_VERSION_MAJOR;
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
*p++ = 0x4; *p++ = 8; pico_get_unique_board_id((pico_unique_board_id_t *)p); p += 8; *p++ = 0x4; *p++ = 8; pico_get_unique_board_id((pico_unique_board_id_t *) p); p += 8;
#else #else
*p++ = 0x4; *p++ = 8; memset(p, 0, 8); p += 8; *p++ = 0x4; *p++ = 8; memset(p, 0, 8); p += 8;
#endif #endif
*p++ = 0xC; *p++ = strlen(manu); strcpy((char *)p, manu); p += strlen(manu); *p++ = 0xC; *p++ = strlen(manu); strcpy((char *) p, manu); p += strlen(manu);
*p++ = 0x80; *p++ = strlen(label); strcpy((char *)p, label); p += strlen(label); *p++ = 0x80; *p++ = strlen(label); strcpy((char *) p, label); p += strlen(label);
*p++ = 0x3; *p++ = 2; *p++ = 4; *p++ = 0x30; *p++ = 0x3; *p++ = 2; *p++ = 4; *p++ = 0x30;
res_APDU_size = p-res_APDU; res_APDU_size = p-res_APDU;
res_APDU[1] = res_APDU_size-2; res_APDU[1] = res_APDU_size-2;
@@ -286,95 +303,113 @@ int parse_token_info(const file_t *f, int mode) {
return 2+(2+1)+(2+8)+(2+strlen(manu))+(2+strlen(label))+(2+2); return 2+(2+1)+(2+8)+(2+strlen(manu))+(2+strlen(label))+(2+2);
} }
int pin_reset_retries(const file_t *pin, bool force) { int pin_reset_retries(const file_t *pin, bool force)
if (!pin) {
if (!pin) {
return CCID_ERR_NULL_PARAM; return CCID_ERR_NULL_PARAM;
}
const file_t *max = search_by_fid(pin->fid+1, NULL, SPECIFY_EF); const file_t *max = search_by_fid(pin->fid+1, NULL, SPECIFY_EF);
const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF); const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF);
if (!max || !act) if (!max || !act) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
}
uint8_t retries = file_read_uint8(file_get_data(act)); uint8_t retries = file_read_uint8(file_get_data(act));
if (retries == 0 && force == false) //blocked if (retries == 0 && force == false) { //blocked
return CCID_ERR_BLOCKED; return CCID_ERR_BLOCKED;
}
retries = file_read_uint8(file_get_data(max)); retries = file_read_uint8(file_get_data(max));
int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); int r = flash_write_data_to_file((file_t *) act, &retries, sizeof(retries));
low_flash_available(); low_flash_available();
return r; return r;
} }
int pin_wrong_retry(const file_t *pin) { int pin_wrong_retry(const file_t *pin)
if (!pin) {
if (!pin) {
return CCID_ERR_NULL_PARAM; return CCID_ERR_NULL_PARAM;
}
const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF); const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF);
if (!act) if (!act) {
return CCID_ERR_FILE_NOT_FOUND; return CCID_ERR_FILE_NOT_FOUND;
}
uint8_t retries = file_read_uint8(file_get_data(act)); uint8_t retries = file_read_uint8(file_get_data(act));
if (retries > 0) { if (retries > 0) {
retries -= 1; retries -= 1;
int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); int r = flash_write_data_to_file((file_t *) act, &retries, sizeof(retries));
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
low_flash_available(); low_flash_available();
if (retries == 0) if (retries == 0) {
return CCID_ERR_BLOCKED; return CCID_ERR_BLOCKED;
}
return retries; return retries;
} }
return CCID_ERR_BLOCKED; return CCID_ERR_BLOCKED;
} }
bool pka_enabled() { bool pka_enabled()
{
file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF); file_t *ef_puk = search_by_fid(EF_PUKAUT, NULL, SPECIFY_EF);
return file_has_data(ef_puk) && file_read_uint8(file_get_data(ef_puk)) > 0; return file_has_data(ef_puk) && file_read_uint8(file_get_data(ef_puk)) > 0;
} }
int check_pin(const file_t *pin, const uint8_t *data, size_t len) { int check_pin(const file_t *pin, const uint8_t *data, size_t len)
if (!file_has_data((file_t *)pin)) { {
if (!file_has_data((file_t *) pin)) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
if (pka_enabled() == false) if (pka_enabled() == false) {
isUserAuthenticated = false; isUserAuthenticated = false;
}
has_session_pin = has_session_sopin = false; has_session_pin = has_session_sopin = false;
if (is_secured_apdu() && sm_session_pin_len > 0 && pin == file_pin1) { if (is_secured_apdu() && sm_session_pin_len > 0 && pin == file_pin1) {
if (len == sm_session_pin_len && memcmp(data, sm_session_pin, len) != 0) { if (len == sm_session_pin_len && memcmp(data, sm_session_pin, len) != 0) {
int retries; int retries;
if ((retries = pin_wrong_retry(pin)) < CCID_OK) if ((retries = pin_wrong_retry(pin)) < CCID_OK) {
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
}
return set_res_sw(0x63, 0xc0 | retries); return set_res_sw(0x63, 0xc0 | retries);
} }
} } else {
else {
uint8_t dhash[32]; uint8_t dhash[32];
double_hash_pin(data, len, dhash); double_hash_pin(data, len, dhash);
if (sizeof(dhash) != file_get_size(pin)-1) //1 byte for pin len if (sizeof(dhash) != file_get_size(pin)-1) { //1 byte for pin len
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
}
if (memcmp(file_get_data(pin)+1, dhash, sizeof(dhash)) != 0) { if (memcmp(file_get_data(pin)+1, dhash, sizeof(dhash)) != 0) {
int retries; int retries;
if ((retries = pin_wrong_retry(pin)) < CCID_OK) if ((retries = pin_wrong_retry(pin)) < CCID_OK) {
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
}
return set_res_sw(0x63, 0xc0 | retries); return set_res_sw(0x63, 0xc0 | retries);
} }
} }
int r = pin_reset_retries(pin, false); int r = pin_reset_retries(pin, false);
if (r == CCID_ERR_BLOCKED) if (r == CCID_ERR_BLOCKED) {
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
if (r != CCID_OK) }
if (r != CCID_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
if (pka_enabled() == false) }
if (pka_enabled() == false) {
isUserAuthenticated = true; isUserAuthenticated = true;
}
if (pin == file_pin1) { if (pin == file_pin1) {
hash_multi(data, len, session_pin); hash_multi(data, len, session_pin);
has_session_pin = true; has_session_pin = true;
} } else if (pin == file_sopin) {
else if (pin == file_sopin) {
hash_multi(data, len, session_sopin); hash_multi(data, len, session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
return SW_OK(); return SW_OK();
} }
const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len) { const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len)
if (ef == NULL) {
if (ef == NULL) {
return NULL; return NULL;
}
uint8_t *meta_data = NULL; uint8_t *meta_data = NULL;
uint8_t meta_size = meta_find(ef->fid, &meta_data); uint8_t meta_size = meta_find(ef->fid, &meta_data);
if (meta_size > 0 && meta_data != NULL) { if (meta_size > 0 && meta_data != NULL) {
@@ -389,42 +424,49 @@ const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len) {
return NULL; return NULL;
} }
uint32_t get_key_counter(file_t *fkey) { uint32_t get_key_counter(file_t *fkey)
{
size_t tag_len = 0; size_t tag_len = 0;
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len); const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
if (meta_tag) if (meta_tag) {
return (meta_tag[0] << 24) | (meta_tag[1] << 16) | (meta_tag[2] << 8) | meta_tag[3]; return (meta_tag[0] << 24) | (meta_tag[1] << 16) | (meta_tag[2] << 8) | meta_tag[3];
}
return 0xffffffff; return 0xffffffff;
} }
bool key_has_purpose(file_t *ef, uint8_t purpose) { bool key_has_purpose(file_t *ef, uint8_t purpose)
{
size_t tag_len = 0; size_t tag_len = 0;
const uint8_t *meta_tag = get_meta_tag(ef, 0x91, &tag_len); const uint8_t *meta_tag = get_meta_tag(ef, 0x91, &tag_len);
if (meta_tag) { if (meta_tag) {
for (int i = 0; i < tag_len; i++) { for (int i = 0; i < tag_len; i++) {
if (meta_tag[i] == purpose) if (meta_tag[i] == purpose) {
return true; return true;
}
} }
return false; return false;
} }
return true; return true;
} }
uint32_t decrement_key_counter(file_t *fkey) { uint32_t decrement_key_counter(file_t *fkey)
if (!fkey) {
if (!fkey) {
return 0xffffff; return 0xffffff;
}
uint8_t *meta_data = NULL; uint8_t *meta_data = NULL;
uint8_t meta_size = meta_find(fkey->fid, &meta_data); uint8_t meta_size = meta_find(fkey->fid, &meta_data);
if (meta_size > 0 && meta_data != NULL) { if (meta_size > 0 && meta_data != NULL) {
uint16_t tag = 0x0; uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL; uint8_t *tag_data = NULL, *p = NULL;
size_t tag_len = 0; size_t tag_len = 0;
uint8_t *cmeta = (uint8_t *)calloc(1, meta_size); uint8_t *cmeta = (uint8_t *) calloc(1, meta_size);
/* We cannot modify meta_data, as it comes from flash memory. It must be cpied to an aux buffer */ /* We cannot modify meta_data, as it comes from flash memory. It must be cpied to an aux buffer */
memcpy(cmeta, meta_data, meta_size); memcpy(cmeta, meta_data, meta_size);
while (walk_tlv(cmeta, meta_size, &p, &tag, &tag_len, &tag_data)) { while (walk_tlv(cmeta, meta_size, &p, &tag, &tag_len, &tag_data)) {
if (tag == 0x90) { //ofset tag if (tag == 0x90) { //ofset tag
uint32_t val = (tag_data[0] << 24) | (tag_data[1] << 16) | (tag_data[2] << 8) | tag_data[3]; uint32_t val =
(tag_data[0] << 24) | (tag_data[1] << 16) | (tag_data[2] << 8) | tag_data[3];
val--; val--;
tag_data[0] = (val >> 24) & 0xff; tag_data[0] = (val >> 24) & 0xff;
tag_data[1] = (val >> 16) & 0xff; tag_data[1] = (val >> 16) & 0xff;
@@ -433,8 +475,9 @@ uint32_t decrement_key_counter(file_t *fkey) {
int r = meta_add(fkey->fid, cmeta, meta_size); int r = meta_add(fkey->fid, cmeta, meta_size);
free(cmeta); free(cmeta);
if (r != 0) if (r != 0) {
return 0xffffffff; return 0xffffffff;
}
low_flash_available(); low_flash_available();
return val; return val;
} }
@@ -445,50 +488,53 @@ uint32_t decrement_key_counter(file_t *fkey) {
} }
//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) { int store_keys(void *key_ctx, int type, uint8_t key_id)
{
int r, key_size = 0; int r, key_size = 0;
uint8_t kdata[4096/8]; //worst case uint8_t kdata[4096/8]; //worst case
if (type == HSM_KEY_RSA) { if (type == HSM_KEY_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);
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 if (type == HSM_KEY_EC) {
else if (type == HSM_KEY_EC) { 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[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++;
} } else if (type & HSM_KEY_AES) {
else if (type & HSM_KEY_AES) { if (type == HSM_KEY_AES_128) {
if (type == HSM_KEY_AES_128)
key_size = 16; key_size = 16;
else if (type == HSM_KEY_AES_192) } else if (type == HSM_KEY_AES_192) {
key_size = 24; key_size = 24;
else if (type == HSM_KEY_AES_256) } else if (type == HSM_KEY_AES_256) {
key_size = 32; key_size = 32;
}
memcpy(kdata, key_ctx, key_size); memcpy(kdata, key_ctx, key_size);
} } else {
else
return CCID_WRONG_DATA; return CCID_WRONG_DATA;
}
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
if (!fpk) if (!fpk) {
return CCID_ERR_MEMORY_FATAL; return CCID_ERR_MEMORY_FATAL;
}
r = mkek_encrypt(kdata, key_size); r = mkek_encrypt(kdata, key_size);
if (r != CCID_OK) { if (r != CCID_OK) {
return r; return r;
} }
r = flash_write_data_to_file(fpk, kdata, key_size); r = flash_write_data_to_file(fpk, kdata, key_size);
if (r != CCID_OK) if (r != CCID_OK) {
return r; return r;
}
low_flash_available(); low_flash_available();
return CCID_OK; return CCID_OK;
} }
int find_and_store_meta_key(uint8_t key_id) { int find_and_store_meta_key(uint8_t key_id)
size_t lt[4] = { 0,0,0,0 }, meta_size = 0; {
uint8_t *pt[4] = { NULL,NULL,NULL,NULL }; size_t lt[4] = { 0, 0, 0, 0 }, meta_size = 0;
uint8_t *pt[4] = { NULL, NULL, NULL, NULL };
uint8_t t90[4] = { 0xFF, 0xFF, 0xFF, 0xFE }; uint8_t t90[4] = { 0xFF, 0xFF, 0xFF, 0xFE };
for (int t = 0; t < 4; t++) { for (int t = 0; t < 4; t++) {
uint8_t *ptt = NULL; uint8_t *ptt = NULL;
@@ -508,7 +554,7 @@ int find_and_store_meta_key(uint8_t key_id) {
} }
} }
if (meta_size) { if (meta_size) {
uint8_t *meta = (uint8_t *)calloc(1, meta_size), *m = meta; uint8_t *meta = (uint8_t *) calloc(1, meta_size), *m = meta;
for (int t = 0; t < 4; t++) { for (int t = 0; t < 4; t++) {
if (lt[t] > 0 && pt[t] != NULL) { if (lt[t] > 0 && pt[t] != NULL) {
*m++ = 0x90+t; *m++ = 0x90+t;
@@ -519,15 +565,18 @@ int find_and_store_meta_key(uint8_t key_id) {
} }
int r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_size); int r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_size);
free(meta); free(meta);
if (r != 0) if (r != 0) {
return CCID_EXEC_ERROR; return CCID_EXEC_ERROR;
}
} }
return CCID_OK; return CCID_OK;
} }
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey)
if (wait_button_pressed() == true) //timeout {
if (wait_button_pressed() == true) { //timeout
return CCID_VERIFICATION_FAILED; return CCID_VERIFICATION_FAILED;
}
int key_size = file_get_size(fkey); int key_size = file_get_size(fkey);
uint8_t kdata[4096/8]; uint8_t kdata[4096/8];
@@ -568,9 +617,11 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
return CCID_OK; return CCID_OK;
} }
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey)
if (wait_button_pressed() == true) //timeout {
if (wait_button_pressed() == true) { //timeout
return CCID_VERIFICATION_FAILED; return CCID_VERIFICATION_FAILED;
}
int key_size = file_get_size(fkey); int key_size = file_get_size(fkey);
uint8_t kdata[67]; //Worst case, 521 bit + 1byte uint8_t kdata[67]; //Worst case, 521 bit + 1byte
@@ -611,8 +662,8 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
#define INS_EXTERNAL_AUTHENTICATE 0x82 #define INS_EXTERNAL_AUTHENTICATE 0x82
#define INS_CHALLENGE 0x84 #define INS_CHALLENGE 0x84
#define INS_GENERAL_AUTHENTICATE 0x86 #define INS_GENERAL_AUTHENTICATE 0x86
#define INS_SELECT_FILE 0xA4 #define INS_SELECT_FILE 0xA4
#define INS_READ_BINARY 0xB0 #define INS_READ_BINARY 0xB0
#define INS_READ_BINARY_ODD 0xB1 #define INS_READ_BINARY_ODD 0xB1
#define INS_UPDATE_EF 0xD7 #define INS_UPDATE_EF 0xD7
#define INS_DELETE_FILE 0xE4 #define INS_DELETE_FILE 0xE4
@@ -645,13 +696,15 @@ static const cmd_t cmds[] = {
{ INS_PUK_AUTH, cmd_puk_auth }, { INS_PUK_AUTH, cmd_puk_auth },
{ INS_PSO, cmd_pso }, { INS_PSO, cmd_pso },
{ INS_EXTERNAL_AUTHENTICATE, cmd_external_authenticate }, { INS_EXTERNAL_AUTHENTICATE, cmd_external_authenticate },
{ 0x00, 0x0} { 0x00, 0x0 }
}; };
int sc_hsm_process_apdu() { int sc_hsm_process_apdu()
{
int r = sm_unwrap(); int r = sm_unwrap();
if (r != CCID_OK) if (r != CCID_OK) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
}
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
if (cmd->ins == INS(apdu)) { if (cmd->ins == INS(apdu)) {
int r = cmd->cmd_handler(); int r = cmd->cmd_handler();

View File

@@ -31,31 +31,31 @@
extern const uint8_t sc_hsm_aid[]; extern const uint8_t sc_hsm_aid[];
#define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */ #define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */
#define ALGO_RSA_DECRYPT 0x21 /* RSA raw decrypt */ #define ALGO_RSA_DECRYPT 0x21 /* RSA raw decrypt */
#define ALGO_RSA_DECRYPT_PKCS1 0x22 #define ALGO_RSA_DECRYPT_PKCS1 0x22
#define ALGO_RSA_DECRYPT_OEP 0x23 #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 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_SHA1 0x31 /* RSA signature with SHA-1 hash and PKCS#1 V1.5 padding */
#define ALGO_RSA_PKCS1_SHA224 0x32 #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_SHA256 0x33 /* RSA signature with SHA-256 hash and PKCS#1 V1.5 padding */
#define ALGO_RSA_PKCS1_SHA384 0x34 #define ALGO_RSA_PKCS1_SHA384 0x34
#define ALGO_RSA_PKCS1_SHA512 0x35 #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 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_SHA1 0x41 /* RSA signature with SHA-1 hash and PKCS#1 PSS padding */
#define ALGO_RSA_PSS_SHA224 0x42 #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_SHA256 0x43 /* RSA signature with SHA-256 hash and PKCS#1 PSS padding */
#define ALGO_RSA_PSS_SHA384 0x44 #define ALGO_RSA_PSS_SHA384 0x44
#define ALGO_RSA_PSS_SHA512 0x45 #define ALGO_RSA_PSS_SHA512 0x45
#define ALGO_EC_RAW 0x70 /* ECDSA signature with hash input */ #define ALGO_EC_RAW 0x70 /* ECDSA signature with hash input */
#define ALGO_EC_SHA1 0x71 /* ECDSA signature with SHA-1 hash */ #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_SHA224 0x72 /* ECDSA signature with SHA-224 hash */
#define ALGO_EC_SHA256 0x73 /* ECDSA signature with SHA-256 hash */ #define ALGO_EC_SHA256 0x73 /* ECDSA signature with SHA-256 hash */
#define ALGO_EC_SHA384 0x74 #define ALGO_EC_SHA384 0x74
#define ALGO_EC_SHA512 0x75 #define ALGO_EC_SHA512 0x75
#define ALGO_EC_DH 0x80 /* ECDH key derivation */ #define ALGO_EC_DH 0x80 /* ECDH key derivation */
#define ALGO_EC_DH_AUTPUK 0x83 #define ALGO_EC_DH_AUTPUK 0x83
#define ALGO_EC_DH_XKEK 0x84 #define ALGO_EC_DH_XKEK 0x84
@@ -63,14 +63,14 @@ extern const uint8_t sc_hsm_aid[];
#define ALGO_UNWRAP 0x93 #define ALGO_UNWRAP 0x93
#define ALGO_REPLACE 0x94 #define ALGO_REPLACE 0x94
#define ALGO_EC_DERIVE 0x98 /* Derive EC key from EC key */ #define ALGO_EC_DERIVE 0x98 /* Derive EC key from EC key */
#define ALGO_AES_CBC_ENCRYPT 0x10 #define ALGO_AES_CBC_ENCRYPT 0x10
#define ALGO_AES_CBC_DECRYPT 0x11 #define ALGO_AES_CBC_DECRYPT 0x11
#define ALGO_AES_CMAC 0x18 #define ALGO_AES_CMAC 0x18
#define ALGO_EXT_CIPHER_ENCRYPT 0x51 /* Extended ciphering Encrypt */ #define ALGO_EXT_CIPHER_ENCRYPT 0x51 /* Extended ciphering Encrypt */
#define ALGO_EXT_CIPHER_DECRYPT 0x52 /* Extended ciphering Decrypt */ #define ALGO_EXT_CIPHER_DECRYPT 0x52 /* Extended ciphering Decrypt */
#define ALGO_AES_DERIVE 0x99 #define ALGO_AES_DERIVE 0x99
#define HSM_OPT_RRC 0x0001 #define HSM_OPT_RRC 0x0001
#define HSM_OPT_TRANSPORT_PIN 0x0002 #define HSM_OPT_TRANSPORT_PIN 0x0002
@@ -83,14 +83,14 @@ extern const uint8_t sc_hsm_aid[];
#define HSM_OPT_KEY_COUNTER_ALL 0x0200 #define HSM_OPT_KEY_COUNTER_ALL 0x0200
#define HSM_OPT_SECURE_LOCK 0x0400 #define HSM_OPT_SECURE_LOCK 0x0400
#define PRKD_PREFIX 0xC4 /* Hi byte in file identifier for PKCS#15 PRKD objects */ #define PRKD_PREFIX 0xC4 /* Hi byte in file identifier for PKCS#15 PRKD objects */
#define CD_PREFIX 0xC8 /* Hi byte in file identifier for PKCS#15 CD objects */ #define CD_PREFIX 0xC8 /* Hi byte in file identifier for PKCS#15 CD objects */
#define DCOD_PREFIX 0xC9 /* Hi byte in file identifier for PKCS#15 DCOD objects */ #define DCOD_PREFIX 0xC9 /* Hi byte in file identifier for PKCS#15 DCOD objects */
#define CA_CERTIFICATE_PREFIX 0xCA /* Hi byte in file identifier for CA certificates */ #define CA_CERTIFICATE_PREFIX 0xCA /* Hi byte in file identifier for CA certificates */
#define KEY_PREFIX 0xCC /* Hi byte in file identifier for key objects */ #define KEY_PREFIX 0xCC /* Hi byte in file identifier for key objects */
#define PROT_DATA_PREFIX 0xCD /* Hi byte in file identifier for PIN protected data objects */ #define PROT_DATA_PREFIX 0xCD /* Hi byte in file identifier for PIN protected data objects */
#define EE_CERTIFICATE_PREFIX 0xCE /* Hi byte in file identifier for EE certificates */ #define EE_CERTIFICATE_PREFIX 0xCE /* Hi byte in file identifier for EE certificates */
#define DATA_PREFIX 0xCF /* Hi byte in file identifier for readable data objects */ #define DATA_PREFIX 0xCF /* Hi byte in file identifier for readable data objects */
#define P15_KEYTYPE_RSA 0x30 #define P15_KEYTYPE_RSA 0x30
#define P15_KEYTYPE_ECC 0xA0 #define P15_KEYTYPE_ECC 0xA0

View File

@@ -24,4 +24,3 @@
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff) #define HSM_VERSION_MINOR (HSM_VERSION & 0xff)
#endif #endif