sc-hsm: Added support for token label to be set via C_InitToken or sc-hsm-tool

This commit is contained in:
Andreas Schwier 2014-01-08 16:07:13 +01:00
parent abb48c8ba7
commit d1ba6164ad
5 changed files with 152 additions and 76 deletions

View File

@ -45,6 +45,7 @@
<para>Use <option>--pin</option> to define the initial user pin value.</para> <para>Use <option>--pin</option> to define the initial user pin value.</para>
<para>Use <option>--pin-retry</option> to define the maximum number of wrong user PIN presentations.</para> <para>Use <option>--pin-retry</option> to define the maximum number of wrong user PIN presentations.</para>
<para>Use with <option>--dkek-shares</option> to enable key wrap / unwrap.</para> <para>Use with <option>--dkek-shares</option> to enable key wrap / unwrap.</para>
<para>Use with <option>--label</option> to define a token label</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -180,6 +181,14 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>--label</option> <replaceable>label</replaceable>,
<option>-l</option> <replaceable>label</replaceable>
</term>
<listitem><para>Define the token label to be used in --initialize.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>--reader</option> <replaceable>num</replaceable>, <option>--reader</option> <replaceable>num</replaceable>,
@ -217,7 +226,7 @@
<para>Create a DKEK share with random password split up using a (3, 5) threshold scheme:</para> <para>Create a DKEK share with random password split up using a (3, 5) threshold scheme:</para>
<para><command>sc-hsm-tool --create-dkek-share dkek-share-1.pbe --pwd-shares-threshold 3 --pwd-shares-total 5</command></para> <para><command>sc-hsm-tool --create-dkek-share dkek-share-1.pbe --pwd-shares-threshold 3 --pwd-shares-total 5</command></para>
<para>Initialize SmartCard-HSM to use a single DKEK share:</para> <para>Initialize SmartCard-HSM to use a single DKEK share:</para>
<para><command>sc-hsm-tool --initialize --so-pin 3537363231383830 --pin 648219 --dkek-shares 1</command></para> <para><command>sc-hsm-tool --initialize --so-pin 3537363231383830 --pin 648219 --dkek-shares 1 --label mytoken</command></para>
<para>Import DKEK share:</para> <para>Import DKEK share:</para>
<para><command>sc-hsm-tool --import-dkek-share dkek-share-1.pbe</command></para> <para><command>sc-hsm-tool --import-dkek-share dkek-share-1.pbe</command></para>
<para>Import DKEK share using a password split up using a (3, 5) threshold scheme for encryption:</para> <para>Import DKEK share using a password split up using a (3, 5) threshold scheme for encryption:</para>

View File

@ -227,9 +227,9 @@ static int sc_hsm_read_binary(sc_card_t *card,
static int sc_hsm_update_binary(sc_card_t *card, static int sc_hsm_write_ef(sc_card_t *card,
unsigned int idx, const u8 *buf, size_t count, int fid,
unsigned long flags) unsigned int idx, const u8 *buf, size_t count)
{ {
sc_context_t *ctx = card->ctx; sc_context_t *ctx = card->ctx;
sc_apdu_t apdu; sc_apdu_t apdu;
@ -267,10 +267,11 @@ static int sc_hsm_update_binary(sc_card_t *card,
len = 8; len = 8;
} }
memcpy(p, buf, count); if (buf != NULL)
memcpy(p, buf, count);
len += count; len += count;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, 0x00, 0x00); sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xD7, fid >> 8, fid & 0xFF);
apdu.data = cmdbuff; apdu.data = cmdbuff;
apdu.datalen = len; apdu.datalen = len;
apdu.lc = len; apdu.lc = len;
@ -287,6 +288,15 @@ static int sc_hsm_update_binary(sc_card_t *card,
static int sc_hsm_update_binary(sc_card_t *card,
unsigned int idx, const u8 *buf, size_t count,
unsigned long flags)
{
return sc_hsm_write_ef(card, 0, idx, buf, count);
}
static int sc_hsm_list_files(sc_card_t *card, u8 * buf, size_t buflen) static int sc_hsm_list_files(sc_card_t *card, u8 * buf, size_t buflen)
{ {
sc_apdu_t apdu; sc_apdu_t apdu;
@ -322,23 +332,12 @@ static int sc_hsm_list_files(sc_card_t *card, u8 * buf, size_t buflen)
static int sc_hsm_create_file(sc_card_t *card, sc_file_t *file) static int sc_hsm_create_file(sc_card_t *card, sc_file_t *file)
{ {
sc_context_t *ctx = card->ctx;
sc_apdu_t apdu;
u8 cmdbuff[] = { 0x54, 0x02, 0x00, 0x00, 0x53, 0x00 };
int r; int r;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD7, file->id >> 8, file->id & 0xFF); r = sc_hsm_write_ef(card, file->id, 0, NULL, 0);
apdu.data = cmdbuff; LOG_TEST_RET(card->ctx, r, "Create file failed");
apdu.datalen = sizeof(cmdbuff);
apdu.lc = sizeof(cmdbuff);
r = sc_transmit_apdu(card, &apdu); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(ctx, r, "Check SW error");
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
} }
@ -432,7 +431,8 @@ static int sc_hsm_decode_ecdsa_signature(sc_card_t *card,
const u8 * data, size_t datalen, const u8 * data, size_t datalen,
u8 * out, size_t outlen) { u8 * out, size_t outlen) {
int fieldsizebytes, i, r; int i, r;
size_t fieldsizebytes;
const u8 *body, *tag; const u8 *body, *tag;
size_t bodylen, taglen; size_t bodylen, taglen;
@ -620,7 +620,10 @@ static int sc_hsm_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
static int sc_hsm_initialize(sc_card_t *card, sc_cardctl_sc_hsm_init_param_t *params) static int sc_hsm_initialize(sc_card_t *card, sc_cardctl_sc_hsm_init_param_t *params)
{ {
sc_context_t *ctx = card->ctx; sc_context_t *ctx = card->ctx;
sc_pkcs15_tokeninfo_t ti;
struct sc_pin_cmd_data pincmd;
int r; int r;
size_t tilen;
sc_apdu_t apdu; sc_apdu_t apdu;
u8 ibuff[50], *p; u8 ibuff[50], *p;
@ -669,6 +672,29 @@ static int sc_hsm_initialize(sc_card_t *card, sc_cardctl_sc_hsm_init_param_t *pa
LOG_TEST_RET(ctx, r, "Check SW error"); LOG_TEST_RET(ctx, r, "Check SW error");
if (params->label) {
memset(&ti, 0, sizeof(ti));
ti.label = params->label;
ti.flags = SC_PKCS15_TOKEN_PRN_GENERATION;
r = sc_pkcs15_encode_tokeninfo(ctx, &ti, &p, &tilen);
LOG_TEST_RET(ctx, r, "Error encoding tokeninfo");
memset(&pincmd, 0, sizeof(pincmd));
pincmd.cmd = SC_PIN_CMD_VERIFY;
pincmd.pin_type = SC_AC_CHV;
pincmd.pin_reference = 0x81;
pincmd.pin1.data = params->user_pin;
pincmd.pin1.len = params->user_pin_len;
r = (*iso_ops->pin_cmd)(card, &pincmd, NULL);
LOG_TEST_RET(ctx, r, "Could not verify PIN");
r = sc_hsm_write_ef(card, 0x2F03, 0, p, tilen);
LOG_TEST_RET(ctx, r, "Could not write EF.TokenInfo");
}
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
} }
@ -784,32 +810,27 @@ static int sc_hsm_unwrap_key(sc_card_t *card, sc_cardctl_sc_hsm_wrapped_key_t *p
static int sc_hsm_init_token(sc_card_t *card, sc_cardctl_pkcs11_init_token_t *params) static int sc_hsm_init_token(sc_card_t *card, sc_cardctl_pkcs11_init_token_t *params)
{ {
sc_context_t *ctx = card->ctx; sc_context_t *ctx = card->ctx;
sc_cardctl_sc_hsm_init_param_t ip;
int r, i; int r, i;
sc_apdu_t apdu; u8 *p;
u8 ibuff[50], *p; char label[33],*cpo;
LOG_FUNC_CALLED(card->ctx); LOG_FUNC_CALLED(ctx);
if (params->so_pin_len != 16) { if (params->so_pin_len != 16) {
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "SO PIN wrong length (!=16)"); LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "SO PIN wrong length (!=16)");
} }
p = ibuff; memset(&ip, 0, sizeof(ip));
*p++ = 0x80; // Options ip.dkek_shares = -1;
*p++ = 0x02; ip.options[0] = 0x00;
*p++ = 0x00; ip.options[0] = 0x01;
*p++ = 0x01;
*p++ = 0x81; // User PIN ip.user_pin = (unsigned char *)params->so_pin; // Use the first 6 digits of the SO-PIN as initial User-PIN value
*p++ = 0x06; // Default value, later changed with C_InitPIN ip.user_pin_len = 6;
// We use only 6 of the 16 bytes init password for the initial user PIN ip.user_pin_retry_counter = 3;
memcpy(p, params->so_pin, 6);
p += 6;
*p++ = 0x82; // Initialization code p = ip.init_code;
*p++ = 0x08;
memset(p, 0, 8);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
*p <<= 4; *p <<= 4;
*p |= params->so_pin[i] & 0xf; *p |= params->so_pin[i] & 0xf;
@ -817,28 +838,22 @@ static int sc_hsm_init_token(sc_card_t *card, sc_cardctl_pkcs11_init_token_t *pa
p++; p++;
} }
*p++ = 0x91; // User PIN retry counter if (params->label) {
*p++ = 0x01; // Strip trailing spaces
*p++ = 0x03; memcpy(label, params->label, 32);
label[32] = 0;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x50, 0x00, 0x00); cpo = label + 31;
apdu.cla = 0x80; while ((cpo >= label) && (*cpo == ' ')) {
apdu.data = ibuff; *cpo = 0;
apdu.datalen = p - ibuff; cpo--;
apdu.lc = apdu.datalen; }
ip.label = label;
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r == SC_ERROR_NOT_ALLOWED) {
r = SC_ERROR_PIN_CODE_INCORRECT;
} }
r = sc_hsm_initialize(card, &ip);
LOG_TEST_RET(ctx, r, "Check SW error"); LOG_TEST_RET(ctx, r, "Check SW error");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); LOG_FUNC_RETURN(ctx, SC_SUCCESS);
} }

View File

@ -938,8 +938,9 @@ typedef struct sc_cardctl_sc_hsm_init_param {
u8 *user_pin; /* Initial user PIN */ u8 *user_pin; /* Initial user PIN */
size_t user_pin_len; /* Length of user PIN */ size_t user_pin_len; /* Length of user PIN */
u8 user_pin_retry_counter; /* Retry counter default value */ u8 user_pin_retry_counter; /* Retry counter default value */
u8 options[2]; /* Initilization options */ u8 options[2]; /* Initialization options */
char dkek_shares; /* Number of DKEK shares, 0 for card generated, -1 for none */ char dkek_shares; /* Number of DKEK shares, 0 for card generated, -1 for none */
char *label; /* Token label to be set in EF.TokenInfo (2F03) */
} sc_cardctl_sc_hsm_init_param_t; } sc_cardctl_sc_hsm_init_param_t;
typedef struct sc_cardctl_sc_hsm_dkek { typedef struct sc_cardctl_sc_hsm_dkek {

View File

@ -514,6 +514,33 @@ static int sc_pkcs15emu_sc_hsm_add_cd(sc_pkcs15_card_t * p15card, u8 id) {
static int sc_pkcs15emu_sc_hsm_read_tokeninfo (sc_pkcs15_card_t * p15card)
{
sc_card_t *card = p15card->card;
sc_file_t *file = NULL;
sc_path_t path;
int r;
u8 efbin[512];
LOG_FUNC_CALLED(card->ctx);
/* Read token info */
sc_path_set(&path, SC_PATH_TYPE_FILE_ID, (u8 *) "\x2F\x03", 2, 0, 0);
r = sc_select_file(card, &path, &file);
LOG_TEST_RET(card->ctx, r, "Could not select EF.TokenInfo");
sc_file_free(file);
r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0);
LOG_TEST_RET(card->ctx, r, "Could not read EF.TokenInfo");
r = sc_pkcs15_parse_tokeninfo(card->ctx, p15card->tokeninfo, efbin, r);
LOG_TEST_RET(card->ctx, r, "Could not decode EF.TokenInfo");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
/* /*
* Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects * Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects
* *
@ -536,16 +563,12 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
LOG_FUNC_CALLED(card->ctx); LOG_FUNC_CALLED(card->ctx);
p15card->tokeninfo->label = strdup("SmartCard-HSM");
p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de");
appinfo = calloc(1, sizeof(struct sc_app_info)); appinfo = calloc(1, sizeof(struct sc_app_info));
if (appinfo == NULL) { if (appinfo == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
} }
appinfo->label = strdup(p15card->tokeninfo->label);
appinfo->aid = sc_hsm_aid; appinfo->aid = sc_hsm_aid;
appinfo->ddo.aid = sc_hsm_aid; appinfo->ddo.aid = sc_hsm_aid;
@ -578,14 +601,36 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert);
LOG_TEST_RET(card->ctx, r, "Could not decode EF.C_DevAut"); LOG_TEST_RET(card->ctx, r, "Could not decode EF.C_DevAut");
sc_pkcs15emu_sc_hsm_read_tokeninfo(p15card);
if (p15card->tokeninfo->label == NULL) {
p15card->tokeninfo->label = strdup("SmartCard-HSM");
if (p15card->tokeninfo->label == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) {
free(p15card->tokeninfo->manufacturer_id);
p15card->tokeninfo->manufacturer_id = NULL;
}
if (p15card->tokeninfo->manufacturer_id == NULL) {
p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de");
if (p15card->tokeninfo->manufacturer_id == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
appinfo->label = strdup(p15card->tokeninfo->label);
if (appinfo->label == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
len = strlen(devcert.chr); /* Strip last 5 digit sequence number from CHR */ len = strlen(devcert.chr); /* Strip last 5 digit sequence number from CHR */
assert(len >= 8); assert(len >= 8);
len -= 5; len -= 5;
p15card->tokeninfo->serial_number = calloc(len + 1, 1); p15card->tokeninfo->serial_number = calloc(len + 1, 1);
if (p15card->tokeninfo->serial_number == NULL) { if (p15card->tokeninfo->serial_number == NULL)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(p15card->tokeninfo->serial_number, devcert.chr, len); memcpy(p15card->tokeninfo->serial_number, devcert.chr, len);
*(p15card->tokeninfo->serial_number + len) = 0; *(p15card->tokeninfo->serial_number + len) = 0;
@ -594,7 +639,6 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
sc_pkcs15emu_sc_hsm_free_cvc(&devcert); sc_pkcs15emu_sc_hsm_free_cvc(&devcert);
memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_info, 0, sizeof(pin_info));
memset(&pin_obj, 0, sizeof(pin_obj)); memset(&pin_obj, 0, sizeof(pin_obj));

View File

@ -52,7 +52,8 @@ static const char magic[] = "Salted__";
static struct sc_aid sc_hsm_aid = { { 0xE8,0x2B,0x06,0x01,0x04,0x01,0x81,0xC3,0x1F,0x02,0x01 }, 11 }; static struct sc_aid sc_hsm_aid = { { 0xE8,0x2B,0x06,0x01,0x04,0x01,0x81,0xC3,0x1F,0x02,0x01 }, 11 };
static int opt_wait = 0; static int opt_wait = 0;
static char *opt_reader; static char *opt_reader = NULL;
static char *opt_label = NULL;
static int verbose = 0; static int verbose = 0;
// Some reasonable maximums // Some reasonable maximums
@ -84,6 +85,7 @@ static const struct option options[] = {
{ "pwd-shares-threshold", 1, NULL, OPT_PASSWORD_SHARES_THRESHOLD }, { "pwd-shares-threshold", 1, NULL, OPT_PASSWORD_SHARES_THRESHOLD },
{ "pwd-shares-total", 1, NULL, OPT_PASSWORD_SHARES_TOTAL }, { "pwd-shares-total", 1, NULL, OPT_PASSWORD_SHARES_TOTAL },
{ "key-reference", 1, NULL, 'i' }, { "key-reference", 1, NULL, 'i' },
{ "label", 1, NULL, 'l' },
{ "force", 0, NULL, 'f' }, { "force", 0, NULL, 'f' },
{ "reader", 1, NULL, 'r' }, { "reader", 1, NULL, 'r' },
{ "wait", 0, NULL, 'w' }, { "wait", 0, NULL, 'w' },
@ -105,6 +107,7 @@ static const char *option_help[] = {
"Define threshold for number of password shares required for reconstruction", "Define threshold for number of password shares required for reconstruction",
"Define number of password shares", "Define number of password shares",
"Key reference for key wrap/unwrap", "Key reference for key wrap/unwrap",
"Token label for --initialize",
"Force replacement of key and certificate", "Force replacement of key and certificate",
"Uses reader number <arg> [0]", "Uses reader number <arg> [0]",
"Wait for a card to be inserted", "Wait for a card to be inserted",
@ -138,7 +141,7 @@ static sc_card_t *card = NULL;
* @param rngSeed Seed value for CPRNG * @param rngSeed Seed value for CPRNG
* *
*/ */
static void generatePrime(BIGNUM *prime, const BIGNUM *s, const unsigned int n, char *rngSeed) static void generatePrime(BIGNUM *prime, const BIGNUM *s, const unsigned int n, unsigned char *rngSeed)
{ {
int bits = 0; int bits = 0;
@ -490,7 +493,7 @@ static void print_info(sc_card_t *card, sc_file_t *file)
static void initialize(sc_card_t *card, const char *so_pin, const char *user_pin, int retry_counter, int dkek_shares) static void initialize(sc_card_t *card, const char *so_pin, const char *user_pin, int retry_counter, int dkek_shares, const char *label)
{ {
sc_cardctl_sc_hsm_init_param_t param; sc_cardctl_sc_hsm_init_param_t param;
size_t len; size_t len;
@ -560,6 +563,7 @@ static void initialize(sc_card_t *card, const char *so_pin, const char *user_pin
param.options[1] = 0x01; param.options[1] = 0x01;
param.dkek_shares = (char)dkek_shares; param.dkek_shares = (char)dkek_shares;
param.label = (char *)label;
r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_INITIALIZE, (void *)&param); r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_INITIALIZE, (void *)&param);
if (r < 0) { if (r < 0) {
@ -816,7 +820,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas
*pwd = calloc(1, 8); *pwd = calloc(1, 8);
*pwdlen = 8; *pwdlen = 8;
r = sc_get_challenge(card, *pwd, 8); r = sc_get_challenge(card, (unsigned char *)*pwd, 8);
if (r < 0) { if (r < 0) {
printf("Error generating random key failed with %s", sc_strerror(r)); printf("Error generating random key failed with %s", sc_strerror(r));
OPENSSL_cleanse(*pwd, *pwdlen); OPENSSL_cleanse(*pwd, *pwdlen);
@ -834,7 +838,7 @@ static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int pas
/* /*
* Encode the secret value * Encode the secret value
*/ */
BN_bin2bn(*pwd, *pwdlen, &secret); BN_bin2bn((unsigned char *)*pwd, *pwdlen, &secret);
/* /*
* Generate seed and calculate a prime depending on the size of the secret * Generate seed and calculate a prime depending on the size of the secret
@ -1007,7 +1011,7 @@ static int wrap_with_tag(u8 tag, u8 *indata, size_t inlen, u8 **outdata, size_t
if (inlen > 127) { if (inlen > 127) {
do { do {
nlc++; nlc++;
} while (inlen >= (1 << (nlc << 3))); } while (inlen >= (unsigned)(1 << (nlc << 3)));
} }
*outlen = 2 + nlc + inlen; *outlen = 2 + nlc + inlen;
@ -1056,14 +1060,14 @@ static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pi
util_getpass(&lpin, NULL, stdin); util_getpass(&lpin, NULL, stdin);
printf("\n"); printf("\n");
} else { } else {
lpin = pin; lpin = (char *)pin;
} }
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
data.cmd = SC_PIN_CMD_VERIFY; data.cmd = SC_PIN_CMD_VERIFY;
data.pin_type = SC_AC_CHV; data.pin_type = SC_AC_CHV;
data.pin_reference = ID_USER_PIN; data.pin_reference = ID_USER_PIN;
data.pin1.data = lpin; data.pin1.data = (unsigned char *)lpin;
data.pin1.len = strlen(lpin); data.pin1.len = strlen(lpin);
r = sc_pin_cmd(card, &data, NULL); r = sc_pin_cmd(card, &data, NULL);
@ -1313,14 +1317,14 @@ static void unwrap_key(sc_card_t *card, u8 keyid, const char *inf, const char *p
util_getpass(&lpin, NULL, stdin); util_getpass(&lpin, NULL, stdin);
printf("\n"); printf("\n");
} else { } else {
lpin = (u8 *)pin; lpin = (char *)pin;
} }
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
data.cmd = SC_PIN_CMD_VERIFY; data.cmd = SC_PIN_CMD_VERIFY;
data.pin_type = SC_AC_CHV; data.pin_type = SC_AC_CHV;
data.pin_reference = ID_USER_PIN; data.pin_reference = ID_USER_PIN;
data.pin1.data = lpin; data.pin1.data = (u8 *)lpin;
data.pin1.len = strlen(lpin); data.pin1.len = strlen(lpin);
r = sc_pin_cmd(card, &data, NULL); r = sc_pin_cmd(card, &data, NULL);
@ -1466,6 +1470,9 @@ int main(int argc, char * const argv[])
case 'r': case 'r':
opt_reader = optarg; opt_reader = optarg;
break; break;
case 'l':
opt_label = optarg;
break;
case 'v': case 'v':
verbose++; verbose++;
break; break;
@ -1509,7 +1516,7 @@ int main(int argc, char * const argv[])
} }
if (do_initialize) { if (do_initialize) {
initialize(card, opt_so_pin, opt_pin, opt_retry_counter, opt_dkek_shares); initialize(card, opt_so_pin, opt_pin, opt_retry_counter, opt_dkek_shares, opt_label);
} }
if (do_create_dkek_share) { if (do_create_dkek_share) {