Switching to new style.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
158
src/hsm/sc_hsm.c
158
src/hsm/sc_hsm.c
@@ -78,9 +78,8 @@ extern int cmd_pso();
|
||||
|
||||
extern const uint8_t *ccid_atr;
|
||||
|
||||
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]))) {
|
||||
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]))) {
|
||||
a->aid = sc_hsm_aid;
|
||||
a->process_apdu = sc_hsm_process_apdu;
|
||||
a->unload = sc_hsm_unload;
|
||||
@@ -90,14 +89,12 @@ app_t *sc_hsm_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __attribute__((constructor)) sc_hsm_ctor()
|
||||
{
|
||||
void __attribute__((constructor)) sc_hsm_ctor() {
|
||||
ccid_atr = atr_sc_hsm;
|
||||
register_app(sc_hsm_select_aid);
|
||||
}
|
||||
|
||||
void scan_files()
|
||||
{
|
||||
void scan_files() {
|
||||
file_pin1 = search_by_fid(0x1081, NULL, SPECIFY_EF);
|
||||
if (file_pin1) {
|
||||
if (!file_pin1->data) {
|
||||
@@ -105,7 +102,8 @@ void scan_files()
|
||||
const uint8_t empty[33] = { 0 };
|
||||
flash_write_data_to_file(file_pin1, empty, sizeof(empty));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: PIN1 not found in memory!\r\n");
|
||||
}
|
||||
file_sopin = search_by_fid(0x1088, NULL, SPECIFY_EF);
|
||||
@@ -115,7 +113,8 @@ void scan_files()
|
||||
const uint8_t empty[33] = { 0 };
|
||||
flash_write_data_to_file(file_sopin, empty, sizeof(empty));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: SOPIN not found in memory!\r\n");
|
||||
}
|
||||
file_retries_pin1 = search_by_fid(0x1083, NULL, SPECIFY_EF);
|
||||
@@ -125,7 +124,8 @@ void scan_files()
|
||||
const uint8_t retries = 3;
|
||||
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");
|
||||
}
|
||||
file_retries_sopin = search_by_fid(0x108A, NULL, SPECIFY_EF);
|
||||
@@ -135,7 +135,8 @@ void scan_files()
|
||||
const uint8_t retries = 15;
|
||||
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");
|
||||
}
|
||||
file_t *tf = NULL;
|
||||
@@ -147,7 +148,8 @@ void scan_files()
|
||||
const uint8_t retries = 3;
|
||||
flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: Max Retries PIN1 not found in memory!\r\n");
|
||||
}
|
||||
tf = search_by_fid(0x1089, NULL, SPECIFY_EF);
|
||||
@@ -157,14 +159,14 @@ void scan_files()
|
||||
const uint8_t retries = 15;
|
||||
flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
printf("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
|
||||
void scan_all()
|
||||
{
|
||||
void scan_all() {
|
||||
scan_flash();
|
||||
scan_files();
|
||||
}
|
||||
@@ -174,8 +176,7 @@ int puk_store_entries = 0;
|
||||
PUK *current_puk = NULL;
|
||||
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) {
|
||||
return CCID_ERR_NULL_PARAM;
|
||||
}
|
||||
@@ -188,7 +189,8 @@ int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy)
|
||||
uint8_t *tmp = (uint8_t *) calloc(data_len, sizeof(uint8_t));
|
||||
memcpy(tmp, data, data_len);
|
||||
puk_store[puk_store_entries].cvcert = tmp;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
puk_store[puk_store_entries].cvcert = data;
|
||||
}
|
||||
puk_store[puk_store_entries].cvcert_len = data_len;
|
||||
@@ -206,8 +208,7 @@ int add_cert_puk_store(const uint8_t *data, size_t data_len, bool copy)
|
||||
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++) {
|
||||
if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) {
|
||||
current_puk = &puk_store[i];
|
||||
@@ -217,8 +218,7 @@ int puk_store_select_chr(const uint8_t *chr)
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
void init_sc_hsm()
|
||||
{
|
||||
void init_sc_hsm() {
|
||||
scan_all();
|
||||
has_session_pin = has_session_sopin = false;
|
||||
isUserAuthenticated = false;
|
||||
@@ -246,27 +246,24 @@ void init_sc_hsm()
|
||||
memset(puk_status, 0, sizeof(puk_status));
|
||||
}
|
||||
|
||||
int sc_hsm_unload()
|
||||
{
|
||||
int sc_hsm_unload() {
|
||||
has_session_pin = has_session_sopin = false;
|
||||
isUserAuthenticated = false;
|
||||
sm_session_pin_len = 0;
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
uint16_t get_device_options()
|
||||
{
|
||||
uint16_t get_device_options() {
|
||||
file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_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;
|
||||
}
|
||||
|
||||
extern uint32_t board_button_read(void);
|
||||
|
||||
bool wait_button_pressed()
|
||||
{
|
||||
bool wait_button_pressed() {
|
||||
uint32_t val = EV_PRESS_BUTTON;
|
||||
#ifndef ENABLE_EMULATION
|
||||
uint16_t opts = get_device_options();
|
||||
@@ -280,8 +277,7 @@ bool wait_button_pressed()
|
||||
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 *manu = "Pol Henarejos";
|
||||
if (mode == 1) {
|
||||
@@ -297,19 +293,18 @@ int parse_token_info(const file_t *f, int mode)
|
||||
*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++ = 0x3; *p++ = 2; *p++ = 4; *p++ = 0x30;
|
||||
res_APDU_size = p-res_APDU;
|
||||
res_APDU[1] = res_APDU_size-2;
|
||||
res_APDU_size = p - res_APDU;
|
||||
res_APDU[1] = res_APDU_size - 2;
|
||||
}
|
||||
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) {
|
||||
return CCID_ERR_NULL_PARAM;
|
||||
}
|
||||
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 *max = search_by_fid(pin->fid + 1, NULL, SPECIFY_EF);
|
||||
const file_t *act = search_by_fid(pin->fid + 2, NULL, SPECIFY_EF);
|
||||
if (!max || !act) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@@ -323,12 +318,11 @@ int pin_reset_retries(const file_t *pin, bool force)
|
||||
return r;
|
||||
}
|
||||
|
||||
int pin_wrong_retry(const file_t *pin)
|
||||
{
|
||||
int pin_wrong_retry(const file_t *pin) {
|
||||
if (!pin) {
|
||||
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) {
|
||||
return CCID_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
@@ -348,14 +342,12 @@ int pin_wrong_retry(const file_t *pin)
|
||||
return CCID_ERR_BLOCKED;
|
||||
}
|
||||
|
||||
bool pka_enabled()
|
||||
{
|
||||
bool pka_enabled() {
|
||||
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;
|
||||
}
|
||||
|
||||
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)) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
@@ -371,13 +363,14 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len)
|
||||
}
|
||||
return set_res_sw(0x63, 0xc0 | retries);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
uint8_t dhash[32];
|
||||
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();
|
||||
}
|
||||
if (memcmp(file_get_data(pin)+1, dhash, sizeof(dhash)) != 0) {
|
||||
if (memcmp(file_get_data(pin) + 1, dhash, sizeof(dhash)) != 0) {
|
||||
int retries;
|
||||
if ((retries = pin_wrong_retry(pin)) < CCID_OK) {
|
||||
return SW_PIN_BLOCKED();
|
||||
@@ -398,15 +391,15 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len)
|
||||
if (pin == file_pin1) {
|
||||
hash_multi(data, len, session_pin);
|
||||
has_session_pin = true;
|
||||
} else if (pin == file_sopin) {
|
||||
}
|
||||
else if (pin == file_sopin) {
|
||||
hash_multi(data, len, session_sopin);
|
||||
has_session_sopin = true;
|
||||
}
|
||||
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) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -424,8 +417,7 @@ const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, size_t *tag_len)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t get_key_counter(file_t *fkey)
|
||||
{
|
||||
uint32_t get_key_counter(file_t *fkey) {
|
||||
size_t tag_len = 0;
|
||||
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
|
||||
if (meta_tag) {
|
||||
@@ -434,8 +426,7 @@ uint32_t get_key_counter(file_t *fkey)
|
||||
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;
|
||||
const uint8_t *meta_tag = get_meta_tag(ef, 0x91, &tag_len);
|
||||
if (meta_tag) {
|
||||
@@ -449,8 +440,7 @@ bool key_has_purpose(file_t *ef, uint8_t purpose)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t decrement_key_counter(file_t *fkey)
|
||||
{
|
||||
uint32_t decrement_key_counter(file_t *fkey) {
|
||||
if (!fkey) {
|
||||
return 0xffffff;
|
||||
}
|
||||
@@ -488,31 +478,35 @@ uint32_t decrement_key_counter(file_t *fkey)
|
||||
}
|
||||
|
||||
//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;
|
||||
uint8_t kdata[4096/8]; //worst case
|
||||
uint8_t kdata[4096 / 8]; //worst case
|
||||
if (type == HSM_KEY_RSA) {
|
||||
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
|
||||
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->Q, kdata+key_size/2, key_size/2);
|
||||
} else if (type == HSM_KEY_EC) {
|
||||
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->Q, kdata + key_size / 2, key_size / 2);
|
||||
}
|
||||
else if (type == HSM_KEY_EC) {
|
||||
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
|
||||
key_size = mbedtls_mpi_size(&ecdsa->d);
|
||||
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++;
|
||||
} else if (type & HSM_KEY_AES) {
|
||||
}
|
||||
else if (type & HSM_KEY_AES) {
|
||||
if (type == HSM_KEY_AES_128) {
|
||||
key_size = 16;
|
||||
} else if (type == HSM_KEY_AES_192) {
|
||||
}
|
||||
else if (type == HSM_KEY_AES_192) {
|
||||
key_size = 24;
|
||||
} else if (type == HSM_KEY_AES_256) {
|
||||
}
|
||||
else if (type == HSM_KEY_AES_256) {
|
||||
key_size = 32;
|
||||
}
|
||||
memcpy(kdata, key_ctx, key_size);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
|
||||
@@ -531,18 +525,17 @@ int store_keys(void *key_ctx, int type, uint8_t key_id)
|
||||
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 };
|
||||
uint8_t t90[4] = { 0xFF, 0xFF, 0xFF, 0xFE };
|
||||
for (int t = 0; t < 4; t++) {
|
||||
uint8_t *ptt = NULL;
|
||||
size_t ltt = 0;
|
||||
if (asn1_find_tag(apdu.data, apdu.nc, 0x90+t, <t, &ptt) && ptt != NULL && ltt > 0) {
|
||||
if (asn1_find_tag(apdu.data, apdu.nc, 0x90 + t, <t, &ptt) && ptt != NULL && ltt > 0) {
|
||||
lt[t] = ltt;
|
||||
pt[t] = ptt;
|
||||
meta_size += asn1_len_tag(0x90+t, lt[t]);
|
||||
meta_size += asn1_len_tag(0x90 + t, lt[t]);
|
||||
}
|
||||
}
|
||||
if (lt[0] == 0 && pt[0] == NULL) {
|
||||
@@ -557,7 +550,7 @@ int find_and_store_meta_key(uint8_t key_id)
|
||||
uint8_t *meta = (uint8_t *) calloc(1, meta_size), *m = meta;
|
||||
for (int t = 0; t < 4; t++) {
|
||||
if (lt[t] > 0 && pt[t] != NULL) {
|
||||
*m++ = 0x90+t;
|
||||
*m++ = 0x90 + t;
|
||||
m += format_tlv_len(lt[t], m);
|
||||
memcpy(m, pt[t], lt[t]);
|
||||
m += lt[t];
|
||||
@@ -572,24 +565,23 @@ int find_and_store_meta_key(uint8_t key_id)
|
||||
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
|
||||
return CCID_VERIFICATION_FAILED;
|
||||
}
|
||||
|
||||
int key_size = file_get_size(fkey);
|
||||
uint8_t kdata[4096/8];
|
||||
uint8_t kdata[4096 / 8];
|
||||
memcpy(kdata, file_get_data(fkey), key_size);
|
||||
if (mkek_decrypt(kdata, key_size) != 0) {
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) {
|
||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_rsa_free(ctx);
|
||||
return CCID_WRONG_DATA;
|
||||
}
|
||||
if (mbedtls_mpi_read_binary(&ctx->Q, kdata+key_size/2, key_size/2) != 0) {
|
||||
if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_rsa_free(ctx);
|
||||
return CCID_WRONG_DATA;
|
||||
@@ -617,8 +609,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey)
|
||||
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
|
||||
return CCID_VERIFICATION_FAILED;
|
||||
}
|
||||
@@ -630,7 +621,7 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey)
|
||||
return CCID_EXEC_ERROR;
|
||||
}
|
||||
mbedtls_ecp_group_id gid = kdata[0];
|
||||
int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1);
|
||||
int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1);
|
||||
if (r != 0) {
|
||||
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||
mbedtls_ecdsa_free(ctx);
|
||||
@@ -699,8 +690,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int sc_hsm_process_apdu()
|
||||
{
|
||||
int sc_hsm_process_apdu() {
|
||||
int r = sm_unwrap();
|
||||
if (r != CCID_OK) {
|
||||
return SW_DATA_INVALID();
|
||||
|
||||
Reference in New Issue
Block a user