diff --git a/doc/tools/sc-hsm-tool.1.xml b/doc/tools/sc-hsm-tool.1.xml
index 3e76aacb..f65fe7e1 100644
--- a/doc/tools/sc-hsm-tool.1.xml
+++ b/doc/tools/sc-hsm-tool.1.xml
@@ -45,6 +45,7 @@
Use to define the initial user pin value.
Use to define the maximum number of wrong user PIN presentations.
Use with to enable key wrap / unwrap.
+ Use with to define a token label
@@ -180,6 +181,14 @@
+
+
+ label,
+ label
+
+ Define the token label to be used in --initialize.
+
+
num,
@@ -217,7 +226,7 @@
Create a DKEK share with random password split up using a (3, 5) threshold scheme:
sc-hsm-tool --create-dkek-share dkek-share-1.pbe --pwd-shares-threshold 3 --pwd-shares-total 5
Initialize SmartCard-HSM to use a single DKEK share:
- sc-hsm-tool --initialize --so-pin 3537363231383830 --pin 648219 --dkek-shares 1
+ sc-hsm-tool --initialize --so-pin 3537363231383830 --pin 648219 --dkek-shares 1 --label mytoken
Import DKEK share:
sc-hsm-tool --import-dkek-share dkek-share-1.pbe
Import DKEK share using a password split up using a (3, 5) threshold scheme for encryption:
diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c
index ea9bf324..d0b9108b 100644
--- a/src/libopensc/card-sc-hsm.c
+++ b/src/libopensc/card-sc-hsm.c
@@ -227,9 +227,9 @@ static int sc_hsm_read_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)
+static int sc_hsm_write_ef(sc_card_t *card,
+ int fid,
+ unsigned int idx, const u8 *buf, size_t count)
{
sc_context_t *ctx = card->ctx;
sc_apdu_t apdu;
@@ -267,10 +267,11 @@ static int sc_hsm_update_binary(sc_card_t *card,
len = 8;
}
- memcpy(p, buf, count);
+ if (buf != NULL)
+ memcpy(p, buf, 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.datalen = 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)
{
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)
{
- sc_context_t *ctx = card->ctx;
- sc_apdu_t apdu;
- u8 cmdbuff[] = { 0x54, 0x02, 0x00, 0x00, 0x53, 0x00 };
int r;
- sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD7, file->id >> 8, file->id & 0xFF);
- apdu.data = cmdbuff;
- apdu.datalen = sizeof(cmdbuff);
- apdu.lc = sizeof(cmdbuff);
+ r = sc_hsm_write_ef(card, file->id, 0, NULL, 0);
+ LOG_TEST_RET(card->ctx, r, "Create file failed");
- r = sc_transmit_apdu(card, &apdu);
- 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);
+ LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
@@ -432,7 +431,8 @@ static int sc_hsm_decode_ecdsa_signature(sc_card_t *card,
const u8 * data, size_t datalen,
u8 * out, size_t outlen) {
- int fieldsizebytes, i, r;
+ int i, r;
+ size_t fieldsizebytes;
const u8 *body, *tag;
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)
{
sc_context_t *ctx = card->ctx;
+ sc_pkcs15_tokeninfo_t ti;
+ struct sc_pin_cmd_data pincmd;
int r;
+ size_t tilen;
sc_apdu_t apdu;
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");
+ 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);
}
@@ -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)
{
sc_context_t *ctx = card->ctx;
+ sc_cardctl_sc_hsm_init_param_t ip;
int r, i;
- sc_apdu_t apdu;
- u8 ibuff[50], *p;
+ u8 *p;
+ char label[33],*cpo;
- LOG_FUNC_CALLED(card->ctx);
+ LOG_FUNC_CALLED(ctx);
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;
- *p++ = 0x80; // Options
- *p++ = 0x02;
- *p++ = 0x00;
- *p++ = 0x01;
+ memset(&ip, 0, sizeof(ip));
+ ip.dkek_shares = -1;
+ ip.options[0] = 0x00;
+ ip.options[0] = 0x01;
- *p++ = 0x81; // User PIN
- *p++ = 0x06; // Default value, later changed with C_InitPIN
- // We use only 6 of the 16 bytes init password for the initial user PIN
- memcpy(p, params->so_pin, 6);
- p += 6;
+ ip.user_pin = (unsigned char *)params->so_pin; // Use the first 6 digits of the SO-PIN as initial User-PIN value
+ ip.user_pin_len = 6;
+ ip.user_pin_retry_counter = 3;
- *p++ = 0x82; // Initialization code
- *p++ = 0x08;
-
- memset(p, 0, 8);
+ p = ip.init_code;
for (i = 0; i < 16; i++) {
*p <<= 4;
*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++ = 0x91; // User PIN retry counter
- *p++ = 0x01;
- *p++ = 0x03;
-
- sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x50, 0x00, 0x00);
- apdu.cla = 0x80;
- apdu.data = ibuff;
- apdu.datalen = p - ibuff;
- apdu.lc = apdu.datalen;
-
- 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;
+ if (params->label) {
+ // Strip trailing spaces
+ memcpy(label, params->label, 32);
+ label[32] = 0;
+ cpo = label + 31;
+ while ((cpo >= label) && (*cpo == ' ')) {
+ *cpo = 0;
+ cpo--;
+ }
+ ip.label = label;
}
+ r = sc_hsm_initialize(card, &ip);
LOG_TEST_RET(ctx, r, "Check SW error");
- LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
+ LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
diff --git a/src/libopensc/cardctl.h b/src/libopensc/cardctl.h
index 3c426ed6..b46185ab 100644
--- a/src/libopensc/cardctl.h
+++ b/src/libopensc/cardctl.h
@@ -938,8 +938,9 @@ typedef struct sc_cardctl_sc_hsm_init_param {
u8 *user_pin; /* Initial user PIN */
size_t user_pin_len; /* Length of user PIN */
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 *label; /* Token label to be set in EF.TokenInfo (2F03) */
} sc_cardctl_sc_hsm_init_param_t;
typedef struct sc_cardctl_sc_hsm_dkek {
diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c
index df7cda4c..fa9157cd 100644
--- a/src/libopensc/pkcs15-sc-hsm.c
+++ b/src/libopensc/pkcs15-sc-hsm.c
@@ -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
*
@@ -536,16 +563,12 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
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));
if (appinfo == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
- appinfo->label = strdup(p15card->tokeninfo->label);
appinfo->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);
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 */
assert(len >= 8);
len -= 5;
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);
- }
memcpy(p15card->tokeninfo->serial_number, devcert.chr, len);
*(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);
-
memset(&pin_info, 0, sizeof(pin_info));
memset(&pin_obj, 0, sizeof(pin_obj));
diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c
index d6eb5ed3..2f0d106e 100644
--- a/src/tools/sc-hsm-tool.c
+++ b/src/tools/sc-hsm-tool.c
@@ -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 int opt_wait = 0;
-static char *opt_reader;
+static char *opt_reader = NULL;
+static char *opt_label = NULL;
static int verbose = 0;
// Some reasonable maximums
@@ -84,6 +85,7 @@ static const struct option options[] = {
{ "pwd-shares-threshold", 1, NULL, OPT_PASSWORD_SHARES_THRESHOLD },
{ "pwd-shares-total", 1, NULL, OPT_PASSWORD_SHARES_TOTAL },
{ "key-reference", 1, NULL, 'i' },
+ { "label", 1, NULL, 'l' },
{ "force", 0, NULL, 'f' },
{ "reader", 1, NULL, 'r' },
{ "wait", 0, NULL, 'w' },
@@ -105,6 +107,7 @@ static const char *option_help[] = {
"Define threshold for number of password shares required for reconstruction",
"Define number of password shares",
"Key reference for key wrap/unwrap",
+ "Token label for --initialize",
"Force replacement of key and certificate",
"Uses reader number [0]",
"Wait for a card to be inserted",
@@ -138,7 +141,7 @@ static sc_card_t *card = NULL;
* @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;
@@ -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;
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.dkek_shares = (char)dkek_shares;
+ param.label = (char *)label;
r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_INITIALIZE, (void *)¶m);
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);
*pwdlen = 8;
- r = sc_get_challenge(card, *pwd, 8);
+ r = sc_get_challenge(card, (unsigned char *)*pwd, 8);
if (r < 0) {
printf("Error generating random key failed with %s", sc_strerror(r));
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
*/
- 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
@@ -1007,7 +1011,7 @@ static int wrap_with_tag(u8 tag, u8 *indata, size_t inlen, u8 **outdata, size_t
if (inlen > 127) {
do {
nlc++;
- } while (inlen >= (1 << (nlc << 3)));
+ } while (inlen >= (unsigned)(1 << (nlc << 3)));
}
*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);
printf("\n");
} else {
- lpin = pin;
+ lpin = (char *)pin;
}
memset(&data, 0, sizeof(data));
data.cmd = SC_PIN_CMD_VERIFY;
data.pin_type = SC_AC_CHV;
data.pin_reference = ID_USER_PIN;
- data.pin1.data = lpin;
+ data.pin1.data = (unsigned char *)lpin;
data.pin1.len = strlen(lpin);
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);
printf("\n");
} else {
- lpin = (u8 *)pin;
+ lpin = (char *)pin;
}
memset(&data, 0, sizeof(data));
data.cmd = SC_PIN_CMD_VERIFY;
data.pin_type = SC_AC_CHV;
data.pin_reference = ID_USER_PIN;
- data.pin1.data = lpin;
+ data.pin1.data = (u8 *)lpin;
data.pin1.len = strlen(lpin);
r = sc_pin_cmd(card, &data, NULL);
@@ -1466,6 +1470,9 @@ int main(int argc, char * const argv[])
case 'r':
opt_reader = optarg;
break;
+ case 'l':
+ opt_label = optarg;
+ break;
case 'v':
verbose++;
break;
@@ -1509,7 +1516,7 @@ int main(int argc, char * const argv[])
}
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) {