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
+5 -3
View File
@@ -21,10 +21,12 @@
uint8_t challenge[256];
uint8_t challenge_len = 0;
int cmd_challenge() {
uint8_t *rb = (uint8_t *)random_bytes_get(apdu.ne);
if (!rb)
int cmd_challenge()
{
uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
if (!rb) {
return SW_WRONG_LENGTH();
}
memcpy(res_APDU, rb, apdu.ne);
challenge_len = MIN(apdu.ne, sizeof(challenge));
memcpy(challenge, rb, challenge_len);
+12 -8
View File
@@ -19,14 +19,16 @@
#include "sc_hsm.h"
#include "kek.h"
int cmd_change_pin() {
int cmd_change_pin()
{
if (P1(apdu) == 0x0) {
if (P2(apdu) == 0x81 || P2(apdu) == 0x88) {
file_t *file_pin = NULL;
if (P2(apdu) == 0x81)
if (P2(apdu) == 0x81) {
file_pin = file_pin1;
else if (P2(apdu) == 0x88)
} else if (P2(apdu) == 0x88) {
file_pin = file_sopin;
}
if (!file_pin) {
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));
int r = check_pin(file_pin, apdu.data, pin_len);
if (r != 0x9000)
if (r != 0x9000) {
return r;
}
uint8_t mkek[MKEK_SIZE];
r = load_mkek(mkek); //loads the MKEK with old pin
if (r != CCID_OK)
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
//encrypt MKEK with new pin
if (P2(apdu) == 0x81) {
hash_multi(apdu.data+pin_len, apdu.nc-pin_len, session_pin);
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);
has_session_sopin = true;
}
r = store_mkek(mkek);
release_mkek(mkek);
if (r != CCID_OK)
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
uint8_t dhash[33];
dhash[0] = apdu.nc-pin_len;
double_hash_pin(apdu.data+pin_len, apdu.nc-pin_len, dhash+1);
+184 -95
View File
@@ -36,18 +36,19 @@
/* This is copied from pkcs5.c Mbedtls */
/** Unfortunately it is declared as static, so I cannot call it. **/
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type )
static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf prf_alg_oid;
unsigned char *p = params->p;
const unsigned char *end = params->p + params->len;
if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE))
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) );
if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
}
/*
* PBKDF2-params ::= SEQUENCE {
* 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,
MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
MBEDTLS_ASN1_OCTET_STRING)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
salt->p = p;
p += salt->len;
if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 )
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 ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
if( p == end )
return( 0 );
if (p == end) {
return 0;
}
if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 )
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) );
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( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 )
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
if (p == end) {
return 0;
}
if( p != end )
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
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 */
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;
const mbedtls_md_info_t *md_info = NULL;
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;
}
int cmd_cipher_sym() {
int cmd_cipher_sym()
{
int key_id = P1(apdu);
int algo = P2(apdu);
if (!isUserAuthenticated)
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
if (!ef)
if (!ef) {
return SW_FILE_NOT_FOUND();
if (key_has_purpose(ef, algo) == false)
}
if (key_has_purpose(ef, algo) == false) {
return SW_CONDITIONS_NOT_SATISFIED();
if (wait_button_pressed() == true) // timeout
}
if (wait_button_pressed() == true) { // timeout
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int key_size = file_get_size(ef);
uint8_t kdata[32]; //maximum AES key size
memcpy(kdata, file_get_data(ef), key_size);
@@ -176,21 +197,30 @@ int cmd_cipher_sym() {
mbedtls_aes_free(&aes);
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));
if (r != 0) {
mbedtls_aes_free(&aes);
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);
if (r != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_aes_free(&aes);
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));
if (r != 0) {
mbedtls_aes_free(&aes);
@@ -199,36 +229,44 @@ int cmd_cipher_sym() {
}
res_APDU_size = apdu.nc;
mbedtls_aes_free(&aes);
}
else if (algo == ALGO_AES_CMAC) {
} else if (algo == ALGO_AES_CMAC) {
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);
else if (key_size == 24)
} else if (key_size == 24) {
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);
else {
} else {
mbedtls_platform_zeroize(kdata, sizeof(kdata));
return SW_WRONG_DATA();
}
int r = mbedtls_cipher_cmac(cipher_info, kdata, key_size*8, apdu.data, apdu.nc, res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = 16;
}
else if (algo == ALGO_AES_DERIVE) {
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);
} else if (algo == ALGO_AES_DERIVE) {
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);
mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
}
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;
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));
return SW_WRONG_DATA();
}
@@ -246,57 +284,88 @@ int cmd_cipher_sym() {
mbedtls_chachapoly_context ctx;
mbedtls_chachapoly_init(&ctx);
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);
}
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);
r = mbedtls_chachapoly_encrypt_and_tag(&ctx,
enc_len,
iv ? iv : tmp_iv,
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_chachapoly_free(&ctx);
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
if (algo == ALGO_EXT_CIPHER_ENCRYPT)
}
if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
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;
}
else if (memcmp(oid, OID_DIGEST, 7) == 0) {
}
} else if (memcmp(oid, OID_DIGEST, 7) == 0) {
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);
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);
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);
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);
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);
if (md_info == NULL)
}
if (md_info == NULL) {
return SW_WRONG_DATA();
}
int r = mbedtls_md_hmac(md_info, kdata, key_size, apdu.data, apdu.nc, res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = md_info->size;
}
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) {
} 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) {
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);
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);
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);
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));
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
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) {
}
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) {
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_context_t md_ctx;
@@ -312,43 +381,63 @@ int cmd_cipher_sym() {
mbedtls_platform_zeroize(kdata, sizeof(kdata));
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_md_free(&md_ctx);
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32);
}
else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
mbedtls_asn1_buf params = { .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);
} else if (memcmp(oid, OID_PKCS5_PBES2, oid_len) == 0) {
mbedtls_asn1_buf params =
{ .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);
mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) {
return SW_WRONG_DATA();
}
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;
if (memcmp(enc, OID_HMAC_SHA1, enc_len) == 0)
if (memcmp(enc, OID_HMAC_SHA1, enc_len) == 0) {
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;
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;
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;
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;
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));
if (r != 0) {
return SW_WRONG_DATA();
}
res_APDU_size = apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32;
}
}
else {
} else {
mbedtls_platform_zeroize(kdata, sizeof(kdata));
return SW_WRONG_P1P2();
}
+50 -29
View File
@@ -26,56 +26,65 @@
#include "random.h"
#include "oid.h"
int cmd_decrypt_asym() {
int cmd_decrypt_asym()
{
int key_id = P1(apdu);
uint8_t p2 = P2(apdu);
if (!isUserAuthenticated)
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
file_t *ef = search_dynamic_file((KEY_PREFIX << 8) | key_id);
if (!ef)
if (!ef) {
return SW_FILE_NOT_FOUND();
if (get_key_counter(ef) == 0)
}
if (get_key_counter(ef) == 0) {
return SW_FILE_FULL();
if (key_has_purpose(ef, p2) == false)
}
if (key_has_purpose(ef, p2) == false) {
return SW_CONDITIONS_NOT_SATISFIED();
}
if (p2 >= ALGO_RSA_DECRYPT && p2 <= ALGO_RSA_DECRYPT_OEP) {
mbedtls_rsa_context 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);
}
int r = load_private_key_rsa(&ctx, ef);
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED)
if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR();
}
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);
}
if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) {
size_t olen = apdu.nc;
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;
}
else {
}
} else {
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU);
if (r == 0)
if (r == 0) {
res_APDU_size = key_size;
}
}
if (r != 0) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
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;
if (wait_button_pressed() == true) //timeout
if (wait_button_pressed() == true) { //timeout
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
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);
if (mkek_decrypt(kdata, key_size) != 0) {
mbedtls_platform_zeroize(kdata, key_size);
@@ -100,9 +109,9 @@ int cmd_decrypt_asym() {
return SW_DATA_INVALID();
}
r = -1;
if (p2 == ALGO_EC_DH)
if (p2 == ALGO_EC_DH) {
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;
const uint8_t *pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len);
if (pub) {
@@ -118,19 +127,22 @@ int cmd_decrypt_asym() {
return SW_DATA_INVALID();
}
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);
if (r != 0) {
return SW_EXEC_ERROR();
}
if (p2 == ALGO_EC_DH)
if (p2 == ALGO_EC_DH) {
res_APDU_size = olen;
else {
} else {
res_APDU_size = 0;
size_t ext_len = 0;
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();
}
uint8_t *p = NULL, *tag_data = NULL, *kdom_uid = NULL;
uint16_t tag = 0;
size_t tag_len = 0, kdom_uid_len = 0;
@@ -138,31 +150,40 @@ int cmd_decrypt_asym() {
if (tag == 0x73) {
size_t oid_len = 0;
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, 0x80, &kdom_uid_len, &kdom_uid) == false)
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, 0x80, &kdom_uid_len,
&kdom_uid) == false) {
return SW_WRONG_DATA();
}
break;
}
}
}
if (kdom_uid_len == 0 || kdom_uid == NULL)
if (kdom_uid_len == 0 || kdom_uid == NULL) {
return SW_WRONG_DATA();
}
for (int n = 0; n < MAX_KEY_DOMAINS; n++) {
file_t *tf = search_dynamic_file(EF_XKEK+n);
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);
if (store_dkek_key(n, res_APDU) != CCID_OK)
if (store_dkek_key(n, res_APDU) != CCID_OK) {
return SW_EXEC_ERROR();
}
return SW_OK();
}
}
}
return SW_REFERENCE_NOT_FOUND();
}
}
else
} else {
return SW_WRONG_P1P2();
}
decrement_key_counter(ef);
return SW_OK();
}
+13 -8
View File
@@ -17,24 +17,29 @@
#include "sc_hsm.h"
int cmd_delete_file() {
int cmd_delete_file()
{
file_t *ef = NULL;
if (!isUserAuthenticated)
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
if (apdu.nc == 0) {
ef = currentEF;
if (!(ef = search_dynamic_file(ef->fid)))
if (!(ef = search_dynamic_file(ef->fid))) {
return SW_FILE_NOT_FOUND();
}
else {
}
} else {
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();
}
}
if (!authenticate_action(ef, ACL_OP_DELETE_SELF))
if (!authenticate_action(ef, ACL_OP_DELETE_SELF)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
if (delete_file(ef) != CCID_OK)
}
if (delete_file(ef) != CCID_OK) {
return SW_EXEC_ERROR();
}
return SW_OK();
}
+24 -18
View File
@@ -22,33 +22,38 @@
#include "cvc.h"
#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E
#define MOD_ADD( N ) \
while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp,
mbedtls_mpi *X,
const mbedtls_mpi *A,
const mbedtls_mpi *B )
#define MOD_ADD(N) \
while (mbedtls_mpi_cmp_mpi(&(N), &grp->P) >= 0) \
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&(N), &(N), &grp->P))
static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp,
mbedtls_mpi *X,
const mbedtls_mpi *A,
const mbedtls_mpi *B)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) );
MOD_ADD( *X );
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B));
MOD_ADD(*X);
cleanup:
return( ret );
return ret;
}
int cmd_derive_asym() {
int cmd_derive_asym()
{
uint8_t key_id = P1(apdu);
uint8_t dest_id = P2(apdu);
file_t *fkey;
if (!isUserAuthenticated)
if (!isUserAuthenticated) {
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();
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false)
}
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) {
return SW_CONDITIONS_NOT_SATISFIED();
if (apdu.nc == 0)
}
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
}
if (apdu.data[0] == ALGO_EC_DERIVE) {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
@@ -57,8 +62,9 @@ int cmd_derive_asym() {
r = load_private_key_ecdsa(&ctx, fkey);
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED)
if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR();
}
mbedtls_mpi a, nd;
@@ -90,8 +96,8 @@ int cmd_derive_asym() {
return SW_EXEC_ERROR();
}
mbedtls_ecdsa_free(&ctx);
}
else
} else {
return SW_WRONG_DATA();
}
return SW_OK();
}
+22 -9
View File
@@ -24,29 +24,42 @@ extern file_t *ef_puk_aut;
extern uint8_t challenge[256];
extern uint8_t challenge_len;
int cmd_external_authenticate() {
if (P1(apdu) != 0x0 || P2(apdu) != 0x0)
int cmd_external_authenticate()
{
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2();
if (ef_puk_aut == NULL)
}
if (ef_puk_aut == NULL) {
return SW_REFERENCE_NOT_FOUND();
if (apdu.nc == 0)
}
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
}
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();
}
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_len, challenge, challenge_len);
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);
if (r != 0)
if (r != 0) {
return SW_CONDITIONS_NOT_SATISFIED();
}
puk_status[ef_puk_aut->fid & (MAX_PUK-1)] = 1;
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];
}
if (auts >= puk_data[2]) {
isUserAuthenticated = true;
}
+60 -31
View File
@@ -27,15 +27,18 @@
#include "mbedtls/hkdf.h"
#include "mbedtls/chachapoly.h"
int cmd_extras() {
int cmd_extras()
{
if (P1(apdu) == 0xA) { //datetime operations
if (P2(apdu) != 0x0)
if (P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2();
}
if (apdu.nc == 0) {
#ifndef ENABLE_EMULATION
datetime_t dt;
if (!rtc_get_datetime(&dt))
if (!rtc_get_datetime(&dt)) {
return SW_EXEC_ERROR();
}
res_APDU[res_APDU_size++] = dt.year >> 8;
res_APDU[res_APDU_size++] = dt.year & 0xff;
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.sec;
#endif
}
else {
if (apdu.nc != 8)
} else {
if (apdu.nc != 8) {
return SW_WRONG_LENGTH();
}
#ifndef ENABLE_EMULATION
datetime_t dt;
dt.year = (apdu.data[0] << 8) | (apdu.data[1]);
@@ -58,29 +61,29 @@ int cmd_extras() {
dt.hour = apdu.data[5];
dt.min = apdu.data[6];
dt.sec = apdu.data[7];
if (!rtc_set_datetime(&dt))
if (!rtc_set_datetime(&dt)) {
return SW_WRONG_DATA();
}
#endif
}
}
else if (P1(apdu) == 0x6) { //dynamic options
if (P2(apdu) != 0x0)
} else if (P1(apdu) == 0x6) { //dynamic options
if (P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2();
if (apdu.nc > sizeof(uint8_t))
}
if (apdu.nc > sizeof(uint8_t)) {
return SW_WRONG_LENGTH();
}
uint16_t opts = get_device_options();
if (apdu.nc == 0) {
res_APDU[res_APDU_size++] = opts >> 8;
res_APDU[res_APDU_size++] = opts & 0xff;
}
else {
} else {
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
flash_write_data_to_file(tf, newopts, sizeof(newopts));
low_flash_available();
}
}
else if (P1(apdu) == 0x3A) { // secure lock
} else if (P1(apdu) == 0x3A) { // secure lock
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
}
@@ -88,9 +91,16 @@ int cmd_extras() {
mbedtls_ecdh_context hkey;
mbedtls_ecdh_init(&hkey);
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);
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) {
mbedtls_ecdh_free(&hkey);
return SW_WRONG_DATA();
@@ -99,30 +109,48 @@ int cmd_extras() {
uint8_t buf[MBEDTLS_ECP_MAX_BYTES];
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) {
mbedtls_ecdh_free(&hkey);
mbedtls_platform_zeroize(buf, sizeof(buf));
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));
if (ret != 0) {
mbedtls_ecdh_free(&hkey);
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);
if (ret != 0) {
return SW_EXEC_ERROR();
}
mse.init = true;
res_APDU_size = olen;
}
else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) {
if (mse.init == false)
} else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) {
if (mse.init == false) {
return SW_COMMAND_NOT_ALLOWED();
}
int ret = mse_decrypt_ct(apdu.data, apdu.nc);
if (ret != 0) {
@@ -131,12 +159,13 @@ int cmd_extras() {
if (P2(apdu) == 0x02 || P2(apdu) == 0x04) { // Enable
uint16_t opts = get_device_options();
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 };
for (int t = 0; t < sizeof(tfids)/sizeof(uint16_t); t++) {
file_t *tf = search_by_fid(tfids[t], NULL, SPECIFY_EF);
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));
for (int i = 0; i < MKEK_KEY_SIZE; 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;
else if (P2(apdu) == 0x04)
} else if (P2(apdu) == 0x04) {
newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8;
}
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
flash_write_data_to_file(tf, newopts, sizeof(newopts));
low_flash_available();
}
else if (P2(apdu) == 0x03) {
} else if (P2(apdu) == 0x03) {
memcpy(mkek_mask, apdu.data, apdu.nc);
has_mkek_mask = true;
}
}
}
else
} else {
return SW_INCORRECT_P1P2();
}
return SW_OK();
}
+15 -6
View File
@@ -24,7 +24,8 @@
#include "eac.h"
#include "files.h"
int cmd_general_authenticate() {
int cmd_general_authenticate()
{
if (P1(apdu) == 0x0 && P2(apdu) == 0x0) {
if (apdu.data[0] == 0x7C) {
int r = 0;
@@ -40,8 +41,9 @@ int cmd_general_authenticate() {
}
}
file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
if (!fkey)
if (!fkey) {
return SW_EXEC_ERROR();
}
mbedtls_ecdsa_context ectx;
mbedtls_ecdsa_init(&ectx);
r = load_private_key_ecdsa(&ectx, fkey);
@@ -71,7 +73,12 @@ int cmd_general_authenticate() {
}
size_t olen = 0;
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);
if (r != 0) {
return SW_EXEC_ERROR();
@@ -79,10 +86,11 @@ int cmd_general_authenticate() {
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);
if (sm_get_protocol() == MSE_AES)
if (sm_get_protocol() == MSE_AES) {
memcpy(t+5, OID_ID_CA_ECDH_AES_CBC_CMAC_128, 10);
}
t[15] = 0x86;
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);
free(t);
if (r != CCID_OK)
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
res_APDU_size += 8;
}
}
+46 -36
View File
@@ -27,7 +27,8 @@
extern void scan_all();
extern char __StackLimit;
int heapLeft() {
int heapLeft()
{
#ifndef ENABLE_EMULATION
char *p = malloc(256); // try to avoid undue fragmentation
int left = &__StackLimit - p;
@@ -38,7 +39,8 @@ int heapLeft() {
return left;
}
int cmd_initialize() {
int cmd_initialize()
{
if (apdu.nc > 0) {
uint8_t mkek[MKEK_SIZE];
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
@@ -52,8 +54,7 @@ int cmd_initialize() {
if (tag == 0x80) { //options
file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF);
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) {
uint8_t dhash[33];
dhash[0] = tag_len;
@@ -62,8 +63,7 @@ int cmd_initialize() {
hash_multi(tag_data, tag_len, session_pin);
has_session_pin = true;
}
}
else if (tag == 0x82) { //sopin pin
} else if (tag == 0x82) { //sopin pin
if (file_sopin && file_sopin->data) {
uint8_t dhash[33];
dhash[0] = tag_len;
@@ -72,8 +72,7 @@ int cmd_initialize() {
hash_multi(tag_data, tag_len, session_sopin);
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);
if (tf && tf->data) {
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) {
flash_write_data_to_file(file_retries_pin1, tag_data, tag_len);
}
}
else if (tag == 0x92) {
} else if (tag == 0x92) {
dkeks = tag_data;
file_t *tf = file_new(EF_DKEK);
if (!tf) {
@@ -90,14 +88,13 @@ int cmd_initialize() {
return SW_MEMORY_FAILURE();
}
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);
if (!ef_puk) {
release_mkek(mkek);
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));
pk_status[0] = puks;
pk_status[1] = puks;
@@ -111,17 +108,16 @@ int cmd_initialize() {
}
flash_write_data_to_file(tf, NULL, 0);
}
}
else if (tag == 0x97) {
} else if (tag == 0x97) {
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);
if (!tf)
return SW_MEMORY_FAILURE();
flash_write_data_to_file(tf, NULL, 0);
}
*/
}
*/
}
}
file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF);
@@ -129,8 +125,9 @@ int cmd_initialize() {
release_mkek(mkek);
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
}
if (store_mkek(ret_mkek == CCID_OK ? mkek : NULL) != CCID_OK) {
release_mkek(mkek);
return SW_EXEC_ERROR();
@@ -139,35 +136,39 @@ int cmd_initialize() {
if (dkeks) {
if (*dkeks > 0) {
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();
}
else {
}
} else {
int r = save_dkek_key(0, random_bytes_get(32));
if (r != CCID_OK)
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
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();
}
}
}
else {
} else {
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();
}
}
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);
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();
}
}
/* When initialized, it has all credentials */
isUserAuthenticated = true;
/* Create terminal private key */
file_t *fdkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
if (!fdkey)
if (!fdkey) {
return SW_EXEC_ERROR();
}
int ret = 0;
if (ret_mkek != CCID_OK || !file_has_data(fdkey)) {
mbedtls_ecdsa_context ecdsa;
@@ -193,19 +194,28 @@ int cmd_initialize() {
file_t *fpk = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF);
ret = flash_write_data_to_file(fpk, res_APDU, cvc_len);
if (ret != 0)
if (ret != 0) {
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";
size_t prkd_len = asn1_build_prkd_ecc(label, strlen((const char *)label), keyid, 20, 192, res_APDU, 4096);
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";
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);
ret = flash_write_data_to_file(fpk, res_APDU, prkd_len);
}
if (ret != 0)
if (ret != 0) {
return SW_EXEC_ERROR();
}
low_flash_available();
}
else { //free memory bytes request
} else { //free memory bytes request
int heap_left = heapLeft();
res_APDU[0] = ((heap_left >> 24) & 0xff);
res_APDU[1] = ((heap_left >> 16) & 0xff);
+60 -39
View File
@@ -21,36 +21,47 @@
#include "kek.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;
const uint8_t *meta_tag = get_meta_tag(fkey, 0x92, &tag_len);
if (meta_tag)
if (meta_tag) {
return *meta_tag;
}
return 0xff;
}
int cmd_key_domain() {
int cmd_key_domain()
{
//if (dkeks == 0)
// return SW_COMMAND_NOT_ALLOWED();
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();
if (p2 >= MAX_KEY_DOMAINS)
}
if (p2 >= MAX_KEY_DOMAINS) {
return SW_WRONG_P1P2();
}
file_t *tf_kd = search_by_fid(EF_KEY_DOMAIN, NULL, SPECIFY_EF);
if (!tf_kd)
if (!tf_kd) {
return SW_EXEC_ERROR();
}
uint16_t tf_kd_size = file_get_size(tf_kd);
if (tf_kd_size == 0)
if (tf_kd_size == 0) {
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 (apdu.nc > 0) {
file_t *tf = file_new(EF_DKEK+p2);
if (!tf)
if (!tf) {
return SW_MEMORY_FAILURE();
if (apdu.nc < 32)
}
if (apdu.nc < 32) {
return SW_WRONG_LENGTH();
}
if (current_dkeks == dkeks) {
return SW_COMMAND_NOT_ALLOWED();
}
@@ -65,25 +76,28 @@ int cmd_key_domain() {
uint8_t t[MAX_KEY_DOMAINS*2];
memcpy(t, kdata, tf_kd_size);
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();
}
low_flash_available();
}
else {
} else {
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();
if (current_dkeks == 0xff && !tf) //XKEK have always 0xff
}
if (current_dkeks == 0xff && !tf) { //XKEK have always 0xff
return SW_REFERENCE_NOT_FOUND();
}
}
}
else if (p1 == 0x1 || p1 == 0x3 || p1 == 0x4) { //key domain setup
if (p1 == 0x1 && apdu.nc != 1)
} else if (p1 == 0x1 || p1 == 0x3 || p1 == 0x4) { //key domain setup
if (p1 == 0x1 && apdu.nc != 1) {
return SW_WRONG_LENGTH();
}
if (p1 == 0x3) { //if key domain is not empty, command is denied
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();
}
}
}
uint8_t t[MAX_KEY_DOMAINS*2];
@@ -91,57 +105,64 @@ int cmd_key_domain() {
if (p1 == 0x1) {
t[2*p2] = dkeks = apdu.data[0];
t[2*p2+1] = current_dkeks = 0;
}
else if (p1 == 0x3) {
} else if (p1 == 0x3) {
t[2*p2] = dkeks = 0xff;
t[2*p2+1] = 0xff;
}
else if (p1 == 0x4) {
} else if (p1 == 0x4) {
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();
}
file_t *tf = NULL;
if ((tf = search_dynamic_file(EF_DKEK+p2))) {
if (delete_file(tf) != CCID_OK)
if (delete_file(tf) != CCID_OK) {
return SW_EXEC_ERROR();
}
}
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();
}
}
low_flash_available();
if (p1 == 0x3)
if (p1 == 0x3) {
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) {
size_t pub_len = 0;
file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF);
if (!fterm)
if (!fterm) {
return SW_EXEC_ERROR();
}
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();
}
size_t t86_len = 0;
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();
}
size_t t54_len = 0;
const uint8_t *t54 = cvc_get_field(apdu.data, apdu.nc, &t54_len, 0x54);
if (!t54)
if (!t54) {
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;
memcpy(input+1, t86+1, (t86_len-1)/2);
hash256(input, (t86_len-1)/2+1, hash);
free(input);
int r = puk_verify(t54, t54_len, hash, 32, apdu.data, apdu.nc);
if (r != 0)
if (r != 0) {
return SW_CONDITIONS_NOT_SATISFIED();
}
file_t *tf = file_new(EF_XKEK+p2);
if (!tf)
if (!tf) {
return SW_MEMORY_FAILURE();
}
//All checks done. Get Key Domain UID
pub = cvc_get_pub(apdu.data, apdu.nc, &pub_len);
@@ -154,10 +175,10 @@ int cmd_key_domain() {
}
}
}
}
else
} else {
return SW_INCORRECT_P1P2();
memset(res_APDU,0,10);
}
memset(res_APDU, 0, 10);
res_APDU[0] = dkeks;
res_APDU[1] = dkeks > current_dkeks ? dkeks-current_dkeks : 0;
dkek_kcv(p2, res_APDU+2);
+16 -10
View File
@@ -19,34 +19,40 @@
#include "sc_hsm.h"
#include "random.h"
int cmd_key_gen() {
int cmd_key_gen()
{
uint8_t key_id = P1(apdu);
uint8_t p2 = P2(apdu);
uint8_t key_size = 32;
int r;
if (!isUserAuthenticated)
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
if (p2 == 0xB2)
}
if (p2 == 0xB2) {
key_size = 32;
else if (p2 == 0xB1)
} else if (p2 == 0xB1) {
key_size = 24;
else if (p2 == 0xB0)
} else if (p2 == 0xB0) {
key_size = 16;
}
//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
memcpy(aes_key, random_bytes_get(key_size), key_size);
int aes_type = 0x0;
if (key_size == 16)
if (key_size == 16) {
aes_type = HSM_KEY_AES_128;
else if (key_size == 24)
} else if (key_size == 24) {
aes_type = HSM_KEY_AES_192;
else if (key_size == 32)
} else if (key_size == 32) {
aes_type = HSM_KEY_AES_256;
}
r = store_keys(aes_key, aes_type, key_id);
if (r != CCID_OK)
if (r != CCID_OK) {
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();
}
low_flash_available();
return SW_OK();
}
+29 -18
View File
@@ -20,17 +20,21 @@
#include "kek.h"
#include "cvc.h"
int cmd_key_unwrap() {
int cmd_key_unwrap()
{
int key_id = P1(apdu), r = 0;
if (P2(apdu) != 0x93)
if (P2(apdu) != 0x93) {
return SW_WRONG_P1P2();
if (!isUserAuthenticated)
}
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
int key_type = dkek_type_key(apdu.data);
uint8_t kdom = -1, *allowed = NULL;
size_t allowed_len = 0;
if (key_type == 0x0)
if (key_type == 0x0) {
return SW_DATA_INVALID();
}
if (key_type == HSM_KEY_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
@@ -50,13 +54,12 @@ int cmd_key_unwrap() {
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
}
else if (key_type == HSM_KEY_EC) {
} else if (key_type == HSM_KEY_EC) {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
do {
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) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
@@ -70,24 +73,30 @@ int cmd_key_unwrap() {
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
}
else if (key_type == HSM_KEY_AES) {
} else if (key_type == HSM_KEY_AES) {
uint8_t aes_key[32];
int key_size = 0, aes_type = 0;
do {
r = dkek_decode_key(++kdom, aes_key, apdu.data, apdu.nc, &key_size, &allowed, &allowed_len);
} while((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
r = dkek_decode_key(++kdom,
aes_key,
apdu.data,
apdu.nc,
&key_size,
&allowed,
&allowed_len);
} while ((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
if (key_size == 32)
if (key_size == 32) {
aes_type = HSM_KEY_AES_256;
else if (key_size == 24)
} else if (key_size == 24) {
aes_type = HSM_KEY_AES_192;
else if (key_size == 16)
} else if (key_size == 16) {
aes_type = HSM_KEY_AES_128;
else
} else {
return SW_EXEC_ERROR();
}
r = store_keys(aes_key, aes_type, key_id);
if (r != CCID_OK) {
return SW_EXEC_ERROR();
@@ -95,7 +104,7 @@ int cmd_key_unwrap() {
}
if ((allowed != NULL && allowed_len > 0) || kdom >= 0) {
size_t meta_len = (allowed_len > 0 ? 2+allowed_len : 0) + (kdom >= 0 ? 3 : 0);
uint8_t *meta = (uint8_t *)calloc(1,meta_len), *m = meta;
uint8_t *meta = (uint8_t *) calloc(1, meta_len), *m = meta;
if (allowed_len > 0) {
*m++ = 0x91;
*m++ = allowed_len;
@@ -108,14 +117,16 @@ int cmd_key_unwrap() {
}
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
free(meta);
if (r != CCID_OK)
if (r != CCID_OK) {
return r;
}
}
if (res_APDU_size > 0) {
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
r = flash_write_data_to_file(fpk, res_APDU, res_APDU_size);
if (r != 0)
if (r != 0) {
return SW_EXEC_ERROR();
}
low_flash_available();
res_APDU_size = 0;
}
+27 -17
View File
@@ -22,21 +22,28 @@
extern uint8_t get_key_domain(file_t *fkey);
int cmd_key_wrap() {
int cmd_key_wrap()
{
int key_id = P1(apdu), r = 0;
if (P2(apdu) != 0x92)
if (P2(apdu) != 0x92) {
return SW_WRONG_P1P2();
if (!isUserAuthenticated)
}
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
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);
if (!ef)
if (!ef) {
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();
}
file_t *prkd = search_dynamic_file((PRKD_PREFIX << 8) | key_id);
if (!prkd)
if (!prkd) {
return SW_FILE_NOT_FOUND();
}
const uint8_t *dprkd = file_get_data(prkd);
size_t wrap_len = MAX_DKEK_ENCODE_KEY_BUFFER;
size_t tag_len = 0;
@@ -47,47 +54,50 @@ int cmd_key_wrap() {
r = load_private_key_rsa(&ctx, ef);
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED)
if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR();
}
r = dkek_encode_key(kdom, &ctx, HSM_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_rsa_free(&ctx);
}
else if (*dprkd == P15_KEYTYPE_ECC) {
} else if (*dprkd == P15_KEYTYPE_ECC) {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef);
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
if (r == CCID_VERIFICATION_FAILED)
if (r == CCID_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
return SW_EXEC_ERROR();
}
r = dkek_encode_key(kdom, &ctx, HSM_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_ecdsa_free(&ctx);
}
else if (*dprkd == P15_KEYTYPE_AES) {
} else if (*dprkd == P15_KEYTYPE_AES) {
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();
}
int key_size = file_get_size(ef), aes_type = HSM_KEY_AES;
memcpy(kdata, file_get_data(ef), key_size);
if (mkek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR();
}
if (key_size == 32)
if (key_size == 32) {
aes_type = HSM_KEY_AES_256;
else if (key_size == 24)
} else if (key_size == 24) {
aes_type = HSM_KEY_AES_192;
else if (key_size == 16)
} else if (key_size == 16) {
aes_type = HSM_KEY_AES_128;
}
r = dkek_encode_key(kdom, kdata, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_platform_zeroize(kdata, sizeof(kdata));
}
if (r != CCID_OK)
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
res_APDU_size = wrap_len;
return SW_OK();
}
+41 -25
View File
@@ -24,15 +24,18 @@
#include "random.h"
#include "kek.h"
int cmd_keypair_gen() {
int cmd_keypair_gen()
{
uint8_t key_id = P1(apdu);
if (!isUserAuthenticated)
if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
int ret = 0;
size_t tout = 0;
//sc_asn1_print_tags(apdu.data, apdu.nc);
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) {
size_t oid_len = 0;
uint8_t *oid = NULL;
@@ -55,32 +58,35 @@ int cmd_keypair_gen() {
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_init(&rsa);
uint8_t index = 0;
ret = mbedtls_rsa_gen_key(&rsa, random_gen, &index, key_size, exponent);
if (ret != 0) {
mbedtls_rsa_free(&rsa);
mbedtls_rsa_free(&rsa);
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();
}
ret = store_keys(&rsa, HSM_KEY_RSA, key_id);
if (ret != CCID_OK) {
ret = store_keys(&rsa, HSM_KEY_RSA, key_id);
if (ret != CCID_OK) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
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;
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();
}
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) {
return SW_FUNC_NOT_SUPPORTED();
}
@@ -99,15 +105,19 @@ int cmd_keypair_gen() {
if (p91[n] == ALGO_EC_DH_XKEK) {
size_t l92 = 0;
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();
if (p92[0] > MAX_KEY_DOMAINS)
}
if (p92[0] > MAX_KEY_DOMAINS) {
return SW_WRONG_DATA();
}
file_t *tf_xkek = search_dynamic_file(EF_XKEK+p92[0]);
if (!tf_xkek)
if (!tf_xkek) {
return SW_WRONG_DATA();
}
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;
*pe++ = 0x73;
*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 (ext)
if ((res_APDU_size =
asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096, ext, ext_len)) == 0) {
if (ext) {
free(ext);
}
mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR();
}
if (ext)
if (ext) {
free(ext);
}
ret = store_keys(&ecdsa, HSM_KEY_EC, key_id);
mbedtls_ecdsa_free(&ecdsa);
if (ret != CCID_OK) {
if (ret != CCID_OK) {
return SW_EXEC_ERROR();
}
}
}
}
else
} else {
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();
}
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
ret = flash_write_data_to_file(fpk, res_APDU, res_APDU_size);
if (ret != 0)
if (ret != 0) {
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();
return SW_OK();
}
+2 -4
View File
@@ -33,16 +33,14 @@ int cmd_list_keys()
//first CC
for (int i = 0; i < dynamic_files; 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++] = f->fid & 0xff;
}
}
for (int i = 0; i < dynamic_files; 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++] = f->fid & 0xff;
}
+21 -15
View File
@@ -24,11 +24,13 @@
file_t *ef_puk_aut = NULL;
int cmd_mse() {
int cmd_mse()
{
int p1 = P1(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();
}
if (p1 & 0x1) { //SET
uint16_t tag = 0x0;
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)) {
if (tag == 0x80) {
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);
}
}
}
else if (tag == 0x83) {
} else if (tag == 0x83) {
if (tag_len == 1) {
}
else {
} else {
if (p2 == 0xB6) {
if (puk_store_select_chr(tag_data) == CCID_OK)
if (puk_store_select_chr(tag_data) == CCID_OK) {
return SW_OK();
}
else if (p2 == 0xA4) { /* Aut */
}
} else if (p2 == 0xA4) { /* Aut */
for (int i = 0; i < MAX_PUK; i++) {
file_t *ef = search_dynamic_file(EF_PUK+i);
if (!ef)
if (!ef) {
break;
if (!file_has_data(ef))
}
if (!file_has_data(ef)) {
break;
}
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) {
ef_puk_aut = ef;
return SW_OK();
@@ -68,8 +74,8 @@ int cmd_mse() {
}
}
}
}
else
} else {
return SW_INCORRECT_P1P2();
}
return SW_OK();
}
+47 -26
View File
@@ -23,13 +23,16 @@
extern int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy);
extern PUK *current_puk;
int cmd_pso() {
int cmd_pso()
{
uint8_t p1 = P1(apdu), p2 = P2(apdu);
if (p1 == 0x0 && (p2 == 0x92 || p2 == 0xAE || p2 == 0xBE)) { /* Verify certificate */
if (apdu.nc == 0)
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
if (current_puk == NULL)
}
if (current_puk == NULL) {
return SW_REFERENCE_NOT_FOUND();
}
if (apdu.data[0] != 0x7F || apdu.data[1] != 0x21) {
uint8_t tlv_len = 2+format_tlv_len(apdu.nc, NULL);
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);
if (r != CCID_OK) {
if (r == CCID_WRONG_DATA)
if (r == CCID_WRONG_DATA) {
return SW_DATA_INVALID();
else if (r == CCID_WRONG_SIGNATURE)
} else if (r == CCID_WRONG_SIGNATURE) {
return SW_CONDITIONS_NOT_SATISFIED();
}
return SW_EXEC_ERROR();
}
for (int i = 0; i < 0xfe; i++) {
@@ -51,27 +55,32 @@ int cmd_pso() {
if (!ca_ef) {
ca_ef = file_new(fid);
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();
}
size_t chr_len = 0;
const uint8_t *chr = cvc_get_chr(apdu.data, apdu.nc, &chr_len);
if (chr == NULL)
if (chr == NULL) {
return SW_WRONG_DATA();
}
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;
if (puk == NULL)
if (puk == NULL) {
return SW_WRONG_DATA();
}
size_t oid_len = 0;
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
if (oid == NULL)
if (oid == NULL) {
return SW_WRONG_DATA();
}
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
puk_bin = cvc_get_field(puk, puk_len, &puk_bin_len, 0x81);
if (!puk_bin)
if (!puk_bin) {
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 grp;
mbedtls_ecp_group_init(&grp);
@@ -89,21 +98,18 @@ int cmd_pso() {
}
puk_bin = t86;
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_len != plen+1) {
mbedtls_ecp_group_free(&grp);
return SW_WRONG_DATA();
}
}
else if (t86[0] == 0x4) {
} else if (t86[0] == 0x4) {
if (t86_len != 2*plen+1) {
mbedtls_ecp_group_free(&grp);
return SW_WRONG_DATA();
}
}
else {
} else {
mbedtls_ecp_group_free(&grp);
return SW_WRONG_DATA();
}
@@ -111,26 +117,41 @@ int cmd_pso() {
puk_bin_len = plen;
}
mbedtls_ecp_group_free(&grp);
if (!puk_bin)
if (!puk_bin) {
return SW_WRONG_DATA();
}
}
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);
if (cd_len == 0)
size_t cd_len = asn1_build_cert_description(chr,
chr_len,
puk_bin,
puk_bin_len,
fid,
NULL,
0);
if (cd_len == 0) {
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);
free(buf);
if (r == 0)
if (r == 0) {
return SW_EXEC_ERROR();
}
low_flash_available();
break;
}
}
return SW_OK();
}
else
} else {
return SW_INCORRECT_P1P2();
}
return SW_OK();
}
+27 -18
View File
@@ -19,53 +19,62 @@
#include "files.h"
#include "cvc.h"
int cmd_puk_auth() {
int cmd_puk_auth()
{
uint8_t p1 = P1(apdu), p2 = P2(apdu);
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();
}
uint8_t *puk_data = file_get_data(ef_puk);
if (apdu.nc > 0) {
if (p1 == 0x0 || p1 == 0x1) {
file_t *ef = NULL;
if (p1 == 0x0) { /* Add */
if (p2 != 0x0)
if (p2 != 0x0) {
return SW_INCORRECT_P1P2();
}
for (int i = 0; i < puk_data[0]; i++) {
ef = search_dynamic_file(EF_PUK+i);
if (!ef) /* Never should not happen */
if (!ef) { /* Never should not happen */
return SW_MEMORY_FAILURE();
if (!file_has_data(ef)) /* found first empty slot */
}
if (!file_has_data(ef)) { /* found first empty slot */
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));
tmp[1] = puk_data[1]-1;
flash_write_data_to_file(ef_puk, tmp, file_get_size(ef_puk));
puk_data = file_get_data(ef_puk);
free(tmp);
}
else if (p1 == 0x1) { /* Replace */
if (p2 >= puk_data[0])
} else if (p1 == 0x1) { /* Replace */
if (p2 >= puk_data[0]) {
return SW_INCORRECT_P1P2();
}
ef = search_dynamic_file(EF_PUK+p2);
if (!ef) /* Never should not happen */
if (!ef) { /* Never should not happen */
return SW_MEMORY_FAILURE();
}
}
flash_write_data_to_file(ef, apdu.data, apdu.nc);
low_flash_available();
}
else
} else {
return SW_INCORRECT_P1P2();
}
}
if (p1 == 0x2) {
if (p2 >= puk_data[0])
if (p2 >= puk_data[0]) {
return SW_INCORRECT_P1P2();
}
file_t *ef = search_dynamic_file(EF_PUK+p2);
if (!ef)
if (!ef) {
return SW_INCORRECT_P1P2();
if (!file_has_data(ef))
}
if (!file_has_data(ef)) {
return SW_REFERENCE_NOT_FOUND();
}
size_t chr_len = 0;
const uint8_t *chr = cvc_get_chr(file_get_data(ef), file_get_size(ef), &chr_len);
if (chr) {
@@ -73,12 +82,12 @@ int cmd_puk_auth() {
res_APDU_size = chr_len;
}
return set_res_sw(0x90, puk_status[p2]);
}
else {
} else {
memcpy(res_APDU, puk_data, 3);
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_size = 4;
}
return SW_OK();
+32 -25
View File
@@ -17,42 +17,46 @@
#include "sc_hsm.h"
int cmd_read_binary() {
int cmd_read_binary()
{
uint16_t fid = 0x0;
uint32_t offset = 0;
uint8_t ins = INS(apdu), p1 = P1(apdu), p2 = P2(apdu);
const file_t *ef = NULL;
if ((ins & 0x1) == 0)
{
if ((ins & 0x1) == 0) {
if ((p1 & 0x80) != 0) {
if (!(ef = search_by_fid(p1&0x1f, NULL, SPECIFY_EF)))
return SW_FILE_NOT_FOUND ();
if (!(ef = search_by_fid(p1&0x1f, NULL, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND();
}
offset = p2;
}
else {
} else {
offset = make_uint16_t(p1, p2) & 0x7fff;
ef = currentEF;
}
}
else {
} else {
if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) {
if (!(ef = search_by_fid(p2&0x1f, NULL, SPECIFY_EF)))
return SW_FILE_NOT_FOUND ();
}
else {
if (!(ef = search_by_fid(p2&0x1f, NULL, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND();
}
} else {
uint16_t file_id = make_uint16_t(p1, p2); // & 0x7fff;
if (file_id == 0x0)
if (file_id == 0x0) {
ef = currentEF;
else if (!(ef = search_by_fid(file_id, NULL, SPECIFY_EF)) && !(ef = search_dynamic_file(file_id)))
return SW_FILE_NOT_FOUND ();
} else if (!(ef =
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();
}
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;
}
}
}
@@ -61,26 +65,29 @@ int cmd_read_binary() {
}
if (ef->data) {
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
if (offset > data_len)
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) {
return SW_WRONG_P1P2();
}
uint16_t maxle = data_len-offset;
if (apdu.ne > maxle)
if (apdu.ne > maxle) {
apdu.ne = maxle;
}
if (offset) {
memmove(res_APDU, res_APDU+offset, res_APDU_size-offset);
//res_APDU += offset;
res_APDU_size -= offset;
}
}
else {
} else {
uint16_t data_len = file_get_size(ef);
if (offset > data_len)
if (offset > data_len) {
return SW_WRONG_P1P2();
}
uint16_t maxle = data_len-offset;
if (apdu.ne > maxle)
if (apdu.ne > maxle) {
apdu.ne = maxle;
}
memcpy(res_APDU, file_get_data(ef)+offset, data_len-offset);
res_APDU_size = data_len-offset;
}

Some files were not shown because too many files have changed in this diff Show More