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,
|
||||
* i.e. SC_SEC_OPERATION_AUTHENTICATE etc. */
|
||||
unsigned int fix_digestInfo;
|
||||
unsigned int pin_encoding;
|
||||
} 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) \
|
||||
do { \
|
||||
if ((card)->type == SC_CARD_TYPE_STARCOS_V3_4) { \
|
||||
@ -102,6 +116,171 @@ static int starcos_match_card(sc_card_t *card)
|
||||
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)
|
||||
{
|
||||
unsigned int flags;
|
||||
@ -114,6 +293,7 @@ static int starcos_init(sc_card_t *card)
|
||||
card->name = "STARCOS";
|
||||
card->cla = 0x00;
|
||||
card->drv_data = (void *)ex_data;
|
||||
ex_data->pin_encoding = PIN_ENCODING_DETERMINE;
|
||||
|
||||
flags = SC_ALGORITHM_RSA_PAD_PKCS1
|
||||
| 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;
|
||||
}
|
||||
|
||||
@ -1854,11 +2039,12 @@ static int starcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
starcos_ex_data * ex_data = (starcos_ex_data*)card->drv_data;
|
||||
switch (card->type) {
|
||||
case SC_CARD_TYPE_STARCOS_V3_4:
|
||||
case SC_CARD_TYPE_STARCOS_V3_5:
|
||||
data->flags |= SC_PIN_CMD_NEED_PADDING;
|
||||
data->pin1.encoding = SC_PIN_ENCODING_GLP;
|
||||
data->pin1.encoding = ex_data->pin_encoding;
|
||||
/* fall through */
|
||||
default:
|
||||
r = iso_ops->pin_cmd(card, data, tries_left);
|
||||
|
Loading…
Reference in New Issue
Block a user