Merge pull request #204 from CardContact/master

SmartCard-HSM improved token, PIN and EC key support
This commit is contained in:
viktorTarasov 2014-01-12 12:32:57 -08:00
commit 3dba84714f
7 changed files with 429 additions and 294 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

@ -24,6 +24,7 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "internal.h"
#include "asn1.h"
@ -165,18 +166,56 @@ static int sc_hsm_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data,
/*
* Encode 16 hexadecimals of SO-PIN into binary form
* Caller must check length of sopin and provide an 8 byte buffer
*/
static int sc_hsm_encode_sopin(const u8 *sopin, u8 *sopinbin)
{
int i;
char digit;
memset(sopinbin, 0, 8);
for (i = 0; i < 16; i++) {
*sopinbin <<= 4;
digit = *sopin++;
if (!isxdigit(digit))
return SC_ERROR_PIN_CODE_INCORRECT;
digit = toupper(digit);
if (digit >= 'A')
digit = digit - 'A' + 10;
else
digit = digit & 0xF;
*sopinbin |= digit & 0xf;
if (i & 1)
sopinbin++;
}
return SC_SUCCESS;
}
static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
int *tries_left)
{
sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data;
int r;
if (data->cmd == SC_PIN_CMD_GET_INFO) {
return sc_hsm_pin_info(card, data, tries_left);
}
if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) {
// Save SO PIN for later use in init pin
memcpy(priv->initpw, data->pin1.data, sizeof(priv->initpw));
return SC_SUCCESS;
if (data->pin1.len != 16)
return SC_ERROR_INVALID_PIN_LENGTH;
// Save SO PIN for later use in sc_hsm_init_pin()
r = sc_hsm_encode_sopin(data->pin1.data, priv->sopin);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}
return (*iso_ops->pin_cmd)(card, data, tries_left);
}
@ -227,9 +266,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 +306,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 +327,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 +371,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 +470,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 +659,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 +711,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,61 +849,44 @@ 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;
int r, i;
sc_apdu_t apdu;
u8 ibuff[50], *p;
sc_cardctl_sc_hsm_init_param_t ip;
int r;
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;
r = sc_hsm_encode_sopin(params->so_pin, ip.init_code);
LOG_TEST_RET(ctx, r, "SO PIN wrong format");
*p++ = 0x82; // Initialization code
*p++ = 0x08;
ip.user_pin = ip.init_code; // Use the first 6 bytes of the SO-PIN as initial User-PIN value
ip.user_pin_len = 6;
ip.user_pin_retry_counter = 3;
memset(p, 0, 8);
for (i = 0; i < 16; i++) {
*p <<= 4;
*p |= params->so_pin[i] & 0xf;
if (i & 1)
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);
}
@ -859,14 +907,13 @@ static int sc_hsm_init_pin(sc_card_t *card, sc_cardctl_pkcs11_init_pin_t *params
p = ibuff;
// We use only 6 of the 8 bytes init password for the initial user PIN
memcpy(p, priv->initpw, 6);
p += 6;
memcpy(p, priv->sopin, sizeof(priv->sopin));
p += sizeof(priv->sopin);
memcpy(p, params->pin, params->pin_len);
p += params->pin_len;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x00, 0x81);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2C, 0x00, 0x81);
apdu.data = ibuff;
apdu.datalen = p - ibuff;
apdu.lc = apdu.datalen;
@ -875,9 +922,31 @@ static int sc_hsm_init_pin(sc_card_t *card, sc_cardctl_pkcs11_init_pin_t *params
LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
// Cards before version 1.0 do not implement RESET_RETRY_COUNTER
// For those cards the CHANGE REFERENCE DATA command is used instead
if (r == SC_ERROR_INS_NOT_SUPPORTED) {
p = ibuff;
memcpy(p, priv->sopin, 6);
p += 6;
memcpy(p, params->pin, params->pin_len);
p += params->pin_len;
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x00, 0x81);
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);
}
LOG_TEST_RET(ctx, r, "Check SW error");
memset(priv->initpw, 0, sizeof(priv->initpw));
memset(priv->sopin, 0, sizeof(priv->sopin));
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
}

View File

@ -56,7 +56,7 @@ typedef struct sc_hsm_private_data {
u8 algorithm;
int noExtLength;
char *serialno;
char initpw[6]; // Initial user PIN set at initialization (first 6 digits of token pin)
u8 sopin[8];
} sc_hsm_private_data_t;
@ -96,6 +96,18 @@ typedef struct sc_cvc sc_cvc_t;
struct ec_curve {
const struct sc_lv_data oid;
const struct sc_lv_data prime;
const struct sc_lv_data coefficientA;
const struct sc_lv_data coefficientB;
const struct sc_lv_data basePointG;
const struct sc_lv_data order;
const struct sc_lv_data coFactor;
};
int sc_pkcs15emu_sc_hsm_decode_cvc(sc_pkcs15_card_t * p15card,
const u8 ** buf, size_t *buflen,
sc_cvc_t *cvc);
@ -103,5 +115,7 @@ int sc_pkcs15emu_sc_hsm_encode_cvc(sc_pkcs15_card_t * p15card,
sc_cvc_t *cvc,
u8 ** buf, size_t *buflen);
void sc_pkcs15emu_sc_hsm_free_cvc(sc_cvc_t *cvc);
int sc_pkcs15emu_sc_hsm_get_curve(struct ec_curve **curve, u8 *oid, size_t oidlen);
int sc_pkcs15emu_sc_hsm_get_public_key(sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey);
#endif /* SC_HSM_H_ */

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

@ -39,6 +39,74 @@ void sc_hsm_set_serialnr(sc_card_t *card, char *serial);
static struct ec_curve curves[] = {
{
{ (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x01", 8}, // secp192r1 aka prime192r1
{ (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 24},
{ (unsigned char *) "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1", 24},
{ (unsigned char *) "\x04\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00\xF4\xFF\x0A\xFD\x82\xFF\x10\x12\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5\x73\xF9\x77\xA1\x1E\x79\x48\x11", 49},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36\x14\x6B\xC9\xB1\xB4\xD2\x28\x31", 24},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8}, // secp256r1 aka prime256r1
{ (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 32},
{ (unsigned char *) "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B", 32},
{ (unsigned char *) "\x04\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 65},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 9}, // brainpoolP192r1
{ (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24},
{ (unsigned char *) "\x6A\x91\x17\x40\x76\xB1\xE0\xE1\x9C\x39\xC0\x31\xFE\x86\x85\xC1\xCA\xE0\x40\xE5\xC6\x9A\x28\xEF", 24},
{ (unsigned char *) "\x46\x9A\x28\xEF\x7C\x28\xCC\xA3\xDC\x72\x1D\x04\x4F\x44\x96\xBC\xCA\x7E\xF4\x14\x6F\xBF\x25\xC9", 24},
{ (unsigned char *) "\x04\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 49},
{ (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x05", 9}, // brainpoolP224r1
{ (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFF", 28},
{ (unsigned char *) "\x68\xA5\xE6\x2C\xA9\xCE\x6C\x1C\x29\x98\x03\xA6\xC1\x53\x0B\x51\x4E\x18\x2A\xD8\xB0\x04\x2A\x59\xCA\xD2\x9F\x43", 28},
{ (unsigned char *) "\x25\x80\xF6\x3C\xCF\xE4\x41\x38\x87\x07\x13\xB1\xA9\x23\x69\xE3\x3E\x21\x35\xD2\x66\xDB\xB3\x72\x38\x6C\x40\x0B", 28},
{ (unsigned char *) "\x04\x0D\x90\x29\xAD\x2C\x7E\x5C\xF4\x34\x08\x23\xB2\xA8\x7D\xC6\x8C\x9E\x4C\xE3\x17\x4C\x1E\x6E\xFD\xEE\x12\xC0\x7D\x58\xAA\x56\xF7\x72\xC0\x72\x6F\x24\xC6\xB8\x9E\x4E\xCD\xAC\x24\x35\x4B\x9E\x99\xCA\xA3\xF6\xD3\x76\x14\x02\xCD", 57},
{ (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD0\xFB\x98\xD1\x16\xBC\x4B\x6D\xDE\xBC\xA3\xA5\xA7\x93\x9F", 28},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x07", 9}, // brainpoolP256r1
{ (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32},
{ (unsigned char *) "\x7D\x5A\x09\x75\xFC\x2C\x30\x57\xEE\xF6\x75\x30\x41\x7A\xFF\xE7\xFB\x80\x55\xC1\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9", 32},
{ (unsigned char *) "\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9\xBB\xD7\x7C\xBF\x95\x84\x16\x29\x5C\xF7\xE1\xCE\x6B\xCC\xDC\x18\xFF\x8C\x07\xB6", 32},
{ (unsigned char *) "\x04\x8B\xD2\xAE\xB9\xCB\x7E\x57\xCB\x2C\x4B\x48\x2F\xFC\x81\xB7\xAF\xB9\xDE\x27\xE1\xE3\xBD\x23\xC2\x3A\x44\x53\xBD\x9A\xCE\x32\x62\x54\x7E\xF8\x35\xC3\xDA\xC4\xFD\x97\xF8\x46\x1A\x14\x61\x1D\xC9\xC2\x77\x45\x13\x2D\xED\x8E\x54\x5C\x1D\x54\xC7\x2F\x04\x69\x97", 65},
{ (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x71\x8C\x39\x7A\xA3\xB5\x61\xA6\xF7\x90\x1E\x0E\x82\x97\x48\x56\xA7", 32},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x09", 9}, // brainpoolP320r1
{ (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x27", 40},
{ (unsigned char *) "\x3E\xE3\x0B\x56\x8F\xBA\xB0\xF8\x83\xCC\xEB\xD4\x6D\x3F\x3B\xB8\xA2\xA7\x35\x13\xF5\xEB\x79\xDA\x66\x19\x0E\xB0\x85\xFF\xA9\xF4\x92\xF3\x75\xA9\x7D\x86\x0E\xB4", 40},
{ (unsigned char *) "\x52\x08\x83\x94\x9D\xFD\xBC\x42\xD3\xAD\x19\x86\x40\x68\x8A\x6F\xE1\x3F\x41\x34\x95\x54\xB4\x9A\xCC\x31\xDC\xCD\x88\x45\x39\x81\x6F\x5E\xB4\xAC\x8F\xB1\xF1\xA6", 40},
{ (unsigned char *) "\x04\x43\xBD\x7E\x9A\xFB\x53\xD8\xB8\x52\x89\xBC\xC4\x8E\xE5\xBF\xE6\xF2\x01\x37\xD1\x0A\x08\x7E\xB6\xE7\x87\x1E\x2A\x10\xA5\x99\xC7\x10\xAF\x8D\x0D\x39\xE2\x06\x11\x14\xFD\xD0\x55\x45\xEC\x1C\xC8\xAB\x40\x93\x24\x7F\x77\x27\x5E\x07\x43\xFF\xED\x11\x71\x82\xEA\xA9\xC7\x78\x77\xAA\xAC\x6A\xC7\xD3\x52\x45\xD1\x69\x2E\x8E\xE1", 81},
{ (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA5\xB6\x8F\x12\xA3\x2D\x48\x2E\xC7\xEE\x86\x58\xE9\x86\x91\x55\x5B\x44\xC5\x93\x11", 40},
{ (unsigned char *) "\x01", 1}
},
{
{ NULL, 0},
{ NULL, 0},
{ NULL, 0},
{ NULL, 0},
{ NULL, 0},
{ NULL, 0},
{ NULL, 0}
}
};
#define C_ASN1_CVC_PUBKEY_SIZE 10
static const struct sc_asn1_entry c_asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE] = {
{ "publicKeyOID", SC_ASN1_OBJECT, SC_ASN1_UNI | SC_ASN1_OBJECT, 0, NULL, NULL },
@ -231,6 +299,117 @@ int sc_pkcs15emu_sc_hsm_encode_cvc(sc_pkcs15_card_t * p15card,
int sc_pkcs15emu_sc_hsm_get_curve(struct ec_curve **curve, u8 *oid, size_t oidlen)
{
int i;
for (i = 0; curves[i].oid.value; i++) {
if ((curves[i].oid.len == oidlen) && !memcmp(curves[i].oid.value, oid, oidlen)) {
*curve = &curves[i];
return SC_SUCCESS;
}
}
return SC_ERROR_INVALID_DATA;
}
int sc_pkcs15emu_sc_hsm_get_curve_oid(sc_cvc_t *cvc, const struct sc_lv_data **oid)
{
int i;
for (i = 0; curves[i].oid.value; i++) {
if ((curves[i].prime.len == cvc->primeOrModuluslen) && !memcmp(curves[i].prime.value, cvc->primeOrModulus, cvc->primeOrModuluslen)) {
*oid = &curves[i].oid;
return SC_SUCCESS;
}
}
return SC_ERROR_INVALID_DATA;
}
static int sc_pkcs15emu_sc_hsm_get_rsa_public_key(sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey)
{
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id));
if (!pubkey->alg_id)
return SC_ERROR_OUT_OF_MEMORY;
pubkey->alg_id->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = cvc->primeOrModuluslen;
pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = cvc->coefficientAorExponentlen;
pubkey->u.rsa.exponent.data = malloc(pubkey->u.rsa.exponent.len);
if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(pubkey->u.rsa.exponent.data, cvc->coefficientAorExponent, pubkey->u.rsa.exponent.len);
memcpy(pubkey->u.rsa.modulus.data, cvc->primeOrModulus, pubkey->u.rsa.modulus.len);
return SC_SUCCESS;
}
static int sc_pkcs15emu_sc_hsm_get_ec_public_key(sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey)
{
struct sc_ec_params *ecp;
const struct sc_lv_data *oid;
int r;
pubkey->algorithm = SC_ALGORITHM_EC;
r = sc_pkcs15emu_sc_hsm_get_curve_oid(cvc, &oid);
if (r != SC_SUCCESS)
return r;
ecp = calloc(1, sizeof(struct sc_ec_params));
if (!ecp)
return SC_ERROR_OUT_OF_MEMORY;
ecp->der_len = oid->len + 2;
ecp->der = calloc(ecp->der_len, 1);
if (!ecp->der)
return SC_ERROR_OUT_OF_MEMORY;
ecp->der[0] = 0x06;
ecp->der[1] = (u8)oid->len;
memcpy(ecp->der + 2, oid->value, oid->len);
ecp->type = 1; // Named curve
pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id));
if (!pubkey->alg_id)
return SC_ERROR_OUT_OF_MEMORY;
pubkey->alg_id->algorithm = SC_ALGORITHM_EC;
pubkey->alg_id->params = ecp;
pubkey->u.ec.ecpointQ.value = malloc(cvc->publicPointlen);
if (!pubkey->u.ec.ecpointQ.value)
return SC_ERROR_OUT_OF_MEMORY;
memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen);
pubkey->u.ec.ecpointQ.len = cvc->publicPointlen;
return SC_SUCCESS;
}
int sc_pkcs15emu_sc_hsm_get_public_key(sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey)
{
if (cvc->publicPoint || cvc->publicPointlen) {
return sc_pkcs15emu_sc_hsm_get_ec_public_key(cvc, pubkey);
} else {
return sc_pkcs15emu_sc_hsm_get_rsa_public_key(cvc, pubkey);
}
}
void sc_pkcs15emu_sc_hsm_free_cvc(sc_cvc_t *cvc)
{
if (cvc->signature) {
@ -283,29 +462,29 @@ static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_p
r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc);
LOG_TEST_RET(card->ctx, r, "Could decode certificate signing request");
if (cvc.publicPoint || cvc.publicPointlen) {
/* ToDo implement support for EC Public Keys */
return SC_SUCCESS;
} else {
pubkey.algorithm = SC_ALGORITHM_RSA;
pubkey.u.rsa.modulus.data = cvc.primeOrModulus;
pubkey.u.rsa.modulus.len = cvc.primeOrModuluslen;
pubkey.u.rsa.exponent.data = cvc.coefficientAorExponent;
pubkey.u.rsa.exponent.len = cvc.coefficientAorExponentlen;
}
memset(&pubkey, 0, sizeof(pubkey));
r = sc_pkcs15emu_sc_hsm_get_public_key(&cvc, &pubkey);
LOG_TEST_RET(card->ctx, r, "Could not extract public key");
memset(&pubkey_info, 0, sizeof(pubkey_info));
memset(&pubkey_obj, 0, sizeof(pubkey_obj));
sc_pkcs15_encode_pubkey(p15card->card->ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len);
sc_pkcs15_encode_pubkey_as_spki(p15card->card->ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len);
pubkey_info.id = key_info->id;
strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label));
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
if (pubkey.algorithm == SC_ALGORITHM_RSA) {
pubkey_info.modulus_length = pubkey.u.rsa.modulus.len << 3;
r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
} else {
pubkey_info.field_length = cvc.primeOrModuluslen << 3;
r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info);
}
LOG_TEST_RET(card->ctx, r, "Could not add public key");
sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
sc_pkcs15_erase_pubkey(&pubkey);
return SC_SUCCESS;
}
@ -514,6 +693,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 +742,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 +780,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 +818,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

@ -47,88 +47,6 @@ static u8 pubexp[] = { 0x01, 0x00, 0x01 };
#define C_ASN1_EC_POINTQ_SIZE 2
static struct sc_asn1_entry c_asn1_ec_pointQ[C_ASN1_EC_POINTQ_SIZE] = {
{ "ecpointQ", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
struct ec_curve {
const struct sc_lv_data oid;
const struct sc_lv_data prime;
const struct sc_lv_data coefficientA;
const struct sc_lv_data coefficientB;
const struct sc_lv_data basePointG;
const struct sc_lv_data order;
const struct sc_lv_data coFactor;
};
static struct ec_curve curves[] = {
{
{ (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x01", 8}, // secp192r1 aka prime192r1
{ (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 24},
{ (unsigned char *) "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1", 24},
{ (unsigned char *) "\x04\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00\xF4\xFF\x0A\xFD\x82\xFF\x10\x12\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5\x73\xF9\x77\xA1\x1E\x79\x48\x11", 49},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36\x14\x6B\xC9\xB1\xB4\xD2\x28\x31", 24},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8}, // secp256r1 aka prime256r1
{ (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 32},
{ (unsigned char *) "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B", 32},
{ (unsigned char *) "\x04\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 65},
{ (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 9}, // brainpoolP192r1
{ (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24},
{ (unsigned char *) "\x6A\x91\x17\x40\x76\xB1\xE0\xE1\x9C\x39\xC0\x31\xFE\x86\x85\xC1\xCA\xE0\x40\xE5\xC6\x9A\x28\xEF", 24},
{ (unsigned char *) "\x46\x9A\x28\xEF\x7C\x28\xCC\xA3\xDC\x72\x1D\x04\x4F\x44\x96\xBC\xCA\x7E\xF4\x14\x6F\xBF\x25\xC9", 24},
{ (unsigned char *) "\x04\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 49},
{ (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x05", 9}, // brainpoolP224r1
{ (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFF", 28},
{ (unsigned char *) "\x68\xA5\xE6\x2C\xA9\xCE\x6C\x1C\x29\x98\x03\xA6\xC1\x53\x0B\x51\x4E\x18\x2A\xD8\xB0\x04\x2A\x59\xCA\xD2\x9F\x43", 28},
{ (unsigned char *) "\x25\x80\xF6\x3C\xCF\xE4\x41\x38\x87\x07\x13\xB1\xA9\x23\x69\xE3\x3E\x21\x35\xD2\x66\xDB\xB3\x72\x38\x6C\x40\x0B", 28},
{ (unsigned char *) "\x04\x0D\x90\x29\xAD\x2C\x7E\x5C\xF4\x34\x08\x23\xB2\xA8\x7D\xC6\x8C\x9E\x4C\xE3\x17\x4C\x1E\x6E\xFD\xEE\x12\xC0\x7D\x58\xAA\x56\xF7\x72\xC0\x72\x6F\x24\xC6\xB8\x9E\x4E\xCD\xAC\x24\x35\x4B\x9E\x99\xCA\xA3\xF6\xD3\x76\x14\x02\xCD", 57},
{ (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD0\xFB\x98\xD1\x16\xBC\x4B\x6D\xDE\xBC\xA3\xA5\xA7\x93\x9F", 28},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x07", 9}, // brainpoolP256r1
{ (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32},
{ (unsigned char *) "\x7D\x5A\x09\x75\xFC\x2C\x30\x57\xEE\xF6\x75\x30\x41\x7A\xFF\xE7\xFB\x80\x55\xC1\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9", 32},
{ (unsigned char *) "\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9\xBB\xD7\x7C\xBF\x95\x84\x16\x29\x5C\xF7\xE1\xCE\x6B\xCC\xDC\x18\xFF\x8C\x07\xB6", 32},
{ (unsigned char *) "\x04\x8B\xD2\xAE\xB9\xCB\x7E\x57\xCB\x2C\x4B\x48\x2F\xFC\x81\xB7\xAF\xB9\xDE\x27\xE1\xE3\xBD\x23\xC2\x3A\x44\x53\xBD\x9A\xCE\x32\x62\x54\x7E\xF8\x35\xC3\xDA\xC4\xFD\x97\xF8\x46\x1A\x14\x61\x1D\xC9\xC2\x77\x45\x13\x2D\xED\x8E\x54\x5C\x1D\x54\xC7\x2F\x04\x69\x97", 65},
{ (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x71\x8C\x39\x7A\xA3\xB5\x61\xA6\xF7\x90\x1E\x0E\x82\x97\x48\x56\xA7", 32},
{ (unsigned char *) "\x01", 1}
},
{
{ (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x09", 9}, // brainpoolP320r1
{ (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x27", 40},
{ (unsigned char *) "\x3E\xE3\x0B\x56\x8F\xBA\xB0\xF8\x83\xCC\xEB\xD4\x6D\x3F\x3B\xB8\xA2\xA7\x35\x13\xF5\xEB\x79\xDA\x66\x19\x0E\xB0\x85\xFF\xA9\xF4\x92\xF3\x75\xA9\x7D\x86\x0E\xB4", 40},
{ (unsigned char *) "\x52\x08\x83\x94\x9D\xFD\xBC\x42\xD3\xAD\x19\x86\x40\x68\x8A\x6F\xE1\x3F\x41\x34\x95\x54\xB4\x9A\xCC\x31\xDC\xCD\x88\x45\x39\x81\x6F\x5E\xB4\xAC\x8F\xB1\xF1\xA6", 40},
{ (unsigned char *) "\x04\x43\xBD\x7E\x9A\xFB\x53\xD8\xB8\x52\x89\xBC\xC4\x8E\xE5\xBF\xE6\xF2\x01\x37\xD1\x0A\x08\x7E\xB6\xE7\x87\x1E\x2A\x10\xA5\x99\xC7\x10\xAF\x8D\x0D\x39\xE2\x06\x11\x14\xFD\xD0\x55\x45\xEC\x1C\xC8\xAB\x40\x93\x24\x7F\x77\x27\x5E\x07\x43\xFF\xED\x11\x71\x82\xEA\xA9\xC7\x78\x77\xAA\xAC\x6A\xC7\xD3\x52\x45\xD1\x69\x2E\x8E\xE1", 81},
{ (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA5\xB6\x8F\x12\xA3\x2D\x48\x2E\xC7\xEE\x86\x58\xE9\x86\x91\x55\x5B\x44\xC5\x93\x11", 40},
{ (unsigned char *) "\x01", 1}
},
{
{ NULL, 0}
}
};
static int sc_hsm_delete_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id)
{
sc_card_t *card = p15card->card;
@ -244,22 +162,6 @@ static int sc_hsm_encode_gakp_rsa(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc,
static int sc_hsm_get_curve(struct sc_pkcs15_card *p15card, struct ec_curve **curve, u8 *oid, size_t oidlen) {
int i;
LOG_FUNC_CALLED(p15card->card->ctx);
for (i = 0; curves[i].oid.value; i++) {
if ((curves[i].oid.len == oidlen) && !memcmp(curves[i].oid.value, oid, oidlen)) {
*curve = &curves[i];
return SC_SUCCESS;
}
}
sc_log(p15card->card->ctx, "Unknown curve");
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_INVALID_DATA);
}
static int sc_hsm_encode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc, struct sc_pkcs15_prkey_info *key_info) {
struct sc_object_id ecdsaWithSHA256 = { { 0,4,0,127,0,7,2,2,2,2,3,-1 } };
struct sc_pkcs15_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)key_info->params.data;
@ -277,7 +179,7 @@ static int sc_hsm_encode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc,
curveoidlen = *curveoid++;
sc_hsm_get_curve(p15card, &curve, curveoid, curveoidlen);
sc_pkcs15emu_sc_hsm_get_curve(&curve, curveoid, curveoidlen);
cvc->primeOrModuluslen = curve->prime.len;
cvc->primeOrModulus = malloc(cvc->primeOrModuluslen);
@ -328,89 +230,6 @@ static int sc_hsm_encode_gakp_ec(struct sc_pkcs15_card *p15card, sc_cvc_t *cvc,
static int sc_hsm_decode_gakp_rsa(struct sc_pkcs15_card *p15card,
sc_cvc_t *cvc,
struct sc_pkcs15_prkey_info *key_info,
struct sc_pkcs15_pubkey *pubkey)
{
LOG_FUNC_CALLED(p15card->card->ctx);
if (((key_info->modulus_length + 7) / 8) != cvc->primeOrModuluslen) {
sc_log(p15card->card->ctx, "Modulus size in request does not match generated public key");
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id));
if (!pubkey->alg_id) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
pubkey->alg_id->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = cvc->primeOrModuluslen;
pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = sizeof(pubexp);
pubkey->u.rsa.exponent.data = malloc(pubkey->u.rsa.exponent.len);
if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(pubkey->u.rsa.exponent.data, pubexp, pubkey->u.rsa.exponent.len);
memcpy(pubkey->u.rsa.modulus.data, cvc->primeOrModulus, pubkey->u.rsa.modulus.len);
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
static int sc_hsm_decode_gakp_ec(struct sc_pkcs15_card *p15card,
sc_cvc_t *cvc,
struct sc_pkcs15_prkey_info *key_info,
struct sc_pkcs15_pubkey *pubkey)
{
struct sc_pkcs15_ec_parameters *ecparams = (struct sc_pkcs15_ec_parameters *)(key_info->params.data);
struct sc_ec_params *ecp;
LOG_FUNC_CALLED(p15card->card->ctx);
pubkey->algorithm = SC_ALGORITHM_EC;
pubkey->u.ec.params.named_curve = strdup(ecparams->named_curve);
sc_pkcs15_fix_ec_parameters(p15card->card->ctx, &pubkey->u.ec.params);
ecp = calloc(1, sizeof(struct sc_ec_params));
if (!ecp) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
ecp->der = malloc(ecparams->der.len);
if (!ecp->der) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
ecp->der_len = ecparams->der.len;
memcpy(ecp->der, ecparams->der.value, ecp->der_len);
ecp->type = 1; // Named curve
pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id));
if (!pubkey->alg_id) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
pubkey->alg_id->algorithm = SC_ALGORITHM_EC;
pubkey->alg_id->params = ecp;
pubkey->u.ec.ecpointQ.value = malloc(cvc->publicPointlen);
if (!pubkey->u.ec.ecpointQ.value) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen);
pubkey->u.ec.ecpointQ.len = cvc->publicPointlen;
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
static int sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *object,
struct sc_pkcs15_pubkey *pubkey)
@ -484,14 +303,7 @@ static int sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card
}
if (pubkey != NULL) {
switch(object->type) {
case SC_PKCS15_TYPE_PRKEY_RSA:
r = sc_hsm_decode_gakp_rsa(p15card, &cvc, key_info, pubkey);
break;
case SC_PKCS15_TYPE_PRKEY_EC:
r = sc_hsm_decode_gakp_ec(p15card, &cvc, key_info, pubkey);
break;
}
r = sc_pkcs15emu_sc_hsm_get_public_key(&cvc, pubkey);
}
out:

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