Add PIN encoding detection for StarCOS 3x cards
This commit is contained in:
parent
5fa633075d
commit
c99d62c04a
|
@ -80,8 +80,22 @@ typedef struct starcos_ex_data_st {
|
||||||
int sec_ops; /* the currently selected security operation,
|
int sec_ops; /* the currently selected security operation,
|
||||||
* i.e. SC_SEC_OPERATION_AUTHENTICATE etc. */
|
* i.e. SC_SEC_OPERATION_AUTHENTICATE etc. */
|
||||||
unsigned int fix_digestInfo;
|
unsigned int fix_digestInfo;
|
||||||
|
unsigned int pin_encoding;
|
||||||
} starcos_ex_data;
|
} starcos_ex_data;
|
||||||
|
|
||||||
|
#define PIN_ENCODING_DETERMINE 0
|
||||||
|
#define PIN_ENCODING_DEFAULT SC_PIN_ENCODING_GLP
|
||||||
|
|
||||||
|
// known pin formats for StarCOS 3.x cards
|
||||||
|
#define PIN_FORMAT_F1 0x11
|
||||||
|
#define PIN_FORMAT_F2 0x12
|
||||||
|
#define PIN_FORMAT_RSA 0x1230
|
||||||
|
#define PIN_FORMAT_BCD 0x13
|
||||||
|
#define PIN_FORMAT_ASCII 0x14
|
||||||
|
#define PIN_FORMAT_PW_ASCII 0x21
|
||||||
|
// default is the Format 2 PIN Block which is GLP in OpenSC
|
||||||
|
#define PIN_FORMAT_DEFAULT PIN_FORMAT_F2
|
||||||
|
|
||||||
#define CHECK_NOT_SUPPORTED_V3_4(card) \
|
#define CHECK_NOT_SUPPORTED_V3_4(card) \
|
||||||
do { \
|
do { \
|
||||||
if ((card)->type == SC_CARD_TYPE_STARCOS_V3_4) { \
|
if ((card)->type == SC_CARD_TYPE_STARCOS_V3_4) { \
|
||||||
|
@ -102,6 +116,171 @@ static int starcos_match_card(sc_card_t *card)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct starcos_ctrl_ref_template_st {
|
||||||
|
unsigned int transmission_format;
|
||||||
|
#if 0
|
||||||
|
// not relevant values for now
|
||||||
|
unsigned int se_reference;
|
||||||
|
unsigned int ssec_initial_value;
|
||||||
|
#endif
|
||||||
|
} starcos_ctrl_ref_template;
|
||||||
|
|
||||||
|
// tags
|
||||||
|
#define TAG_STARCOS35_PIN_REFERENCE 0x88
|
||||||
|
#define TAG_STARCOS3X_SUPPORTED_SEC_MECHANISMS_tag 0x7B
|
||||||
|
#define TAG_STARCOS3X_CTRL_REF_TEMPLATE 0xA4
|
||||||
|
#define TAG_STARCOS3X_TRANSMISSION_FORMAT 0x89
|
||||||
|
|
||||||
|
static const char * starcos_ef_pwdd = "3F000015";
|
||||||
|
static const char * starcos_ef_keyd = "3F000013";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses supported securiy mechanisms record data.
|
||||||
|
* It returns SC_SUCCESS and the ctrl_ref_template structure data on success
|
||||||
|
*/
|
||||||
|
static int starcos_parse_supported_sec_mechanisms(struct sc_card *card, const unsigned char * buf, size_t buflen, starcos_ctrl_ref_template * ctrl_ref_template)
|
||||||
|
{
|
||||||
|
struct sc_context *ctx = card->ctx;
|
||||||
|
const unsigned char *supported_sec_mechanisms_tag = NULL;
|
||||||
|
size_t taglen;
|
||||||
|
|
||||||
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
|
||||||
|
supported_sec_mechanisms_tag = sc_asn1_find_tag(ctx, buf, buflen, TAG_STARCOS3X_SUPPORTED_SEC_MECHANISMS_tag, &taglen);
|
||||||
|
if (supported_sec_mechanisms_tag != NULL && taglen >= 1) {
|
||||||
|
const unsigned char *tx_fmt_tag = NULL;
|
||||||
|
const unsigned char *ctrl_ref_template_tag = NULL;
|
||||||
|
size_t supported_sec_mechanisms_taglen = taglen;
|
||||||
|
|
||||||
|
// control-reference template is either included in the supported security mechanisms tag or it can be the CRT tag itself (EF.PWDD)
|
||||||
|
ctrl_ref_template_tag = sc_asn1_find_tag(ctx, supported_sec_mechanisms_tag, taglen, TAG_STARCOS3X_CTRL_REF_TEMPLATE, &taglen);
|
||||||
|
if ( ctrl_ref_template_tag == NULL || taglen == 0 ) {
|
||||||
|
ctrl_ref_template_tag = supported_sec_mechanisms_tag;
|
||||||
|
taglen = supported_sec_mechanisms_taglen;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_fmt_tag = sc_asn1_find_tag(ctx, ctrl_ref_template_tag, taglen, TAG_STARCOS3X_TRANSMISSION_FORMAT, &taglen);
|
||||||
|
if ( tx_fmt_tag != NULL && taglen >= 1 ) {
|
||||||
|
ctrl_ref_template->transmission_format = *(tx_fmt_tag + 0);
|
||||||
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_FUNC_RETURN(ctx, SC_ERROR_TEMPLATE_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int starcos_determine_pin_format34(sc_card_t *card, unsigned int * pin_format)
|
||||||
|
{
|
||||||
|
struct sc_context *ctx = card->ctx;
|
||||||
|
struct sc_path path;
|
||||||
|
struct sc_file *file;
|
||||||
|
unsigned char buf[256];
|
||||||
|
int rv;
|
||||||
|
int retval = SC_SUCCESS;
|
||||||
|
int rec_no=1;
|
||||||
|
|
||||||
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
|
||||||
|
sc_format_path(starcos_ef_pwdd, &path);
|
||||||
|
rv = sc_select_file(card, &path, &file);
|
||||||
|
LOG_TEST_RET(ctx, rv, "Cannot select EF.PWDD file");
|
||||||
|
|
||||||
|
if ( (rv = sc_read_record(card, rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR)) > 0 ) {
|
||||||
|
starcos_ctrl_ref_template ctrl_ref_template;
|
||||||
|
memset((void*)&ctrl_ref_template, 0, sizeof(ctrl_ref_template));
|
||||||
|
rv = starcos_parse_supported_sec_mechanisms(card, buf, rv, &ctrl_ref_template);
|
||||||
|
if ( rv == SC_SUCCESS ) {
|
||||||
|
*pin_format = ctrl_ref_template.transmission_format;
|
||||||
|
sc_log(ctx, "Determined StarCOS 3.4 PIN format: 0x%x", *pin_format);
|
||||||
|
} else {
|
||||||
|
sc_log(ctx, "Failed to parse record %d of EF.PWD, err=%d", rec_no, rv);
|
||||||
|
retval = rv;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sc_log(ctx, "Failed to read record %d of EF.PWDD, err=%d", rec_no, rv);
|
||||||
|
retval = rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_file_free(file);
|
||||||
|
LOG_FUNC_RETURN(ctx, retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int starcos_determine_pin_format35(sc_card_t *card, unsigned int * pin_format)
|
||||||
|
{
|
||||||
|
struct sc_context *ctx = card->ctx;
|
||||||
|
struct sc_path path;
|
||||||
|
struct sc_file *file;
|
||||||
|
unsigned char buf[256];
|
||||||
|
int rv;
|
||||||
|
int retval = SC_ERROR_RECORD_NOT_FOUND;
|
||||||
|
int rec_no=1;
|
||||||
|
starcos_ctrl_ref_template ctrl_ref_template;
|
||||||
|
|
||||||
|
LOG_FUNC_CALLED(ctx);
|
||||||
|
|
||||||
|
sc_format_path(starcos_ef_keyd, &path);
|
||||||
|
rv = sc_select_file(card, &path, &file);
|
||||||
|
LOG_TEST_RET(ctx, rv, "Cannot select EF.KEYD file");
|
||||||
|
|
||||||
|
while ( (rv = sc_read_record(card, rec_no++, buf, sizeof(buf), SC_RECORD_BY_REC_NR)) > 0 ) {
|
||||||
|
if ( buf[0] != TAG_STARCOS35_PIN_REFERENCE ) continue;
|
||||||
|
|
||||||
|
memset((void*)&ctrl_ref_template, 0, sizeof(ctrl_ref_template));
|
||||||
|
rv = starcos_parse_supported_sec_mechanisms(card, buf, rv, &ctrl_ref_template);
|
||||||
|
if ( rv == SC_SUCCESS ) {
|
||||||
|
*pin_format = ctrl_ref_template.transmission_format;
|
||||||
|
sc_log(ctx, "Determined StarCOS 3.5 PIN format: 0x%x", *pin_format);
|
||||||
|
retval = rv;
|
||||||
|
// assuming that all PINs and PUKs have the same transmission format
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sc_log(ctx, "Failed to parse record %d of EF.KEYD, err=%d", rec_no-1, rv);
|
||||||
|
retval = rv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_file_free(file);
|
||||||
|
LOG_FUNC_RETURN(ctx, retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine v3.x PIN encoding by parsing either
|
||||||
|
* EF.PWDD (for v3.4) or EF.KEYD (for v3.5)
|
||||||
|
*
|
||||||
|
* It returns an OpenSC PIN encoding, using the default value on failure
|
||||||
|
*/
|
||||||
|
static unsigned int starcos_determine_pin_encoding(sc_card_t *card)
|
||||||
|
{
|
||||||
|
unsigned int pin_format = PIN_FORMAT_DEFAULT;
|
||||||
|
unsigned int encoding = PIN_ENCODING_DETERMINE;
|
||||||
|
|
||||||
|
if ( card->type == SC_CARD_TYPE_STARCOS_V3_4 ) {
|
||||||
|
starcos_determine_pin_format34(card, &pin_format);
|
||||||
|
} else if ( card->type == SC_CARD_TYPE_STARCOS_V3_5 ) {
|
||||||
|
starcos_determine_pin_format35(card, &pin_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pin_format) {
|
||||||
|
case PIN_FORMAT_PW_ASCII:
|
||||||
|
case PIN_FORMAT_ASCII:
|
||||||
|
encoding = SC_PIN_ENCODING_ASCII;
|
||||||
|
break;
|
||||||
|
case PIN_FORMAT_BCD:
|
||||||
|
encoding = SC_PIN_ENCODING_BCD;
|
||||||
|
break;
|
||||||
|
case PIN_FORMAT_F1:
|
||||||
|
case PIN_FORMAT_F2:
|
||||||
|
encoding = SC_PIN_ENCODING_GLP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_log(card->ctx, "Determined PIN encoding: %d", encoding);
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int starcos_init(sc_card_t *card)
|
static int starcos_init(sc_card_t *card)
|
||||||
{
|
{
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
@ -114,6 +293,7 @@ static int starcos_init(sc_card_t *card)
|
||||||
card->name = "STARCOS";
|
card->name = "STARCOS";
|
||||||
card->cla = 0x00;
|
card->cla = 0x00;
|
||||||
card->drv_data = (void *)ex_data;
|
card->drv_data = (void *)ex_data;
|
||||||
|
ex_data->pin_encoding = PIN_ENCODING_DETERMINE;
|
||||||
|
|
||||||
flags = SC_ALGORITHM_RSA_PAD_PKCS1
|
flags = SC_ALGORITHM_RSA_PAD_PKCS1
|
||||||
| SC_ALGORITHM_ONBOARD_KEY_GEN
|
| SC_ALGORITHM_ONBOARD_KEY_GEN
|
||||||
|
@ -168,6 +348,11 @@ static int starcos_init(sc_card_t *card)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ex_data->pin_encoding == PIN_ENCODING_DETERMINE ) {
|
||||||
|
// about to determine PIN encoding
|
||||||
|
ex_data->pin_encoding = starcos_determine_pin_encoding(card);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1854,11 +2039,12 @@ static int starcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
LOG_FUNC_CALLED(card->ctx);
|
LOG_FUNC_CALLED(card->ctx);
|
||||||
|
starcos_ex_data * ex_data = (starcos_ex_data*)card->drv_data;
|
||||||
switch (card->type) {
|
switch (card->type) {
|
||||||
case SC_CARD_TYPE_STARCOS_V3_4:
|
case SC_CARD_TYPE_STARCOS_V3_4:
|
||||||
case SC_CARD_TYPE_STARCOS_V3_5:
|
case SC_CARD_TYPE_STARCOS_V3_5:
|
||||||
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
||||||
data->pin1.encoding = SC_PIN_ENCODING_GLP;
|
data->pin1.encoding = ex_data->pin_encoding;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
r = iso_ops->pin_cmd(card, data, tries_left);
|
r = iso_ops->pin_cmd(card, data, tries_left);
|
||||||
|
|
Loading…
Reference in New Issue