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-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>--label</option> to define a token label</para>
</listitem>
</varlistentry>
@ -180,6 +181,14 @@
</listitem>
</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>
<term>
<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><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><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><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>

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,
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);
}

View File

@ -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 {

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
*
@ -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));

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 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 <arg> [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 *)&param);
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) {