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</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

@ -24,6 +24,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include "internal.h" #include "internal.h"
#include "asn1.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, static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
int *tries_left) int *tries_left)
{ {
sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data;
int r;
if (data->cmd == SC_PIN_CMD_GET_INFO) { if (data->cmd == SC_PIN_CMD_GET_INFO) {
return sc_hsm_pin_info(card, data, tries_left); return sc_hsm_pin_info(card, data, tries_left);
} }
if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) { if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) {
// Save SO PIN for later use in init pin if (data->pin1.len != 16)
memcpy(priv->initpw, data->pin1.data, sizeof(priv->initpw)); return SC_ERROR_INVALID_PIN_LENGTH;
return SC_SUCCESS;
// 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); 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, 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 +306,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 +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) 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 +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) 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 +470,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 +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) 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 +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"); 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,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) 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;
int r, i; sc_cardctl_sc_hsm_init_param_t ip;
sc_apdu_t apdu; int r;
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 r = sc_hsm_encode_sopin(params->so_pin, ip.init_code);
*p++ = 0x06; // Default value, later changed with C_InitPIN LOG_TEST_RET(ctx, r, "SO PIN wrong format");
// We use only 6 of the 16 bytes init password for the initial user PIN
memcpy(p, params->so_pin, 6);
p += 6;
*p++ = 0x82; // Initialization code ip.user_pin = ip.init_code; // Use the first 6 bytes of the SO-PIN as initial User-PIN value
*p++ = 0x08; ip.user_pin_len = 6;
ip.user_pin_retry_counter = 3;
memset(p, 0, 8); if (params->label) {
for (i = 0; i < 16; i++) { // Strip trailing spaces
*p <<= 4; memcpy(label, params->label, 32);
*p |= params->so_pin[i] & 0xf; label[32] = 0;
if (i & 1) cpo = label + 31;
p++; while ((cpo >= label) && (*cpo == ' ')) {
} *cpo = 0;
cpo--;
*p++ = 0x91; // User PIN retry counter }
*p++ = 0x01; ip.label = label;
*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;
} }
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);
} }
@ -859,14 +907,13 @@ static int sc_hsm_init_pin(sc_card_t *card, sc_cardctl_pkcs11_init_pin_t *params
p = ibuff; p = ibuff;
// We use only 6 of the 8 bytes init password for the initial user PIN memcpy(p, priv->sopin, sizeof(priv->sopin));
memcpy(p, priv->initpw, 6); p += sizeof(priv->sopin);
p += 6;
memcpy(p, params->pin, params->pin_len); memcpy(p, params->pin, params->pin_len);
p += 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.data = ibuff;
apdu.datalen = p - ibuff; apdu.datalen = p - ibuff;
apdu.lc = apdu.datalen; 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"); LOG_TEST_RET(ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2); 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"); 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); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
} }

View File

@ -56,7 +56,7 @@ typedef struct sc_hsm_private_data {
u8 algorithm; u8 algorithm;
int noExtLength; int noExtLength;
char *serialno; 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; } 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, int sc_pkcs15emu_sc_hsm_decode_cvc(sc_pkcs15_card_t * p15card,
const u8 ** buf, size_t *buflen, const u8 ** buf, size_t *buflen,
sc_cvc_t *cvc); sc_cvc_t *cvc);
@ -103,5 +115,7 @@ int sc_pkcs15emu_sc_hsm_encode_cvc(sc_pkcs15_card_t * p15card,
sc_cvc_t *cvc, sc_cvc_t *cvc,
u8 ** buf, size_t *buflen); u8 ** buf, size_t *buflen);
void sc_pkcs15emu_sc_hsm_free_cvc(sc_cvc_t *cvc); 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_ */ #endif /* SC_HSM_H_ */

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

@ -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 #define C_ASN1_CVC_PUBKEY_SIZE 10
static const struct sc_asn1_entry c_asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE] = { 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 }, { "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) void sc_pkcs15emu_sc_hsm_free_cvc(sc_cvc_t *cvc)
{ {
if (cvc->signature) { 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); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc);
LOG_TEST_RET(card->ctx, r, "Could decode certificate signing request"); LOG_TEST_RET(card->ctx, r, "Could decode certificate signing request");
if (cvc.publicPoint || cvc.publicPointlen) { memset(&pubkey, 0, sizeof(pubkey));
/* ToDo implement support for EC Public Keys */ r = sc_pkcs15emu_sc_hsm_get_public_key(&cvc, &pubkey);
return SC_SUCCESS; LOG_TEST_RET(card->ctx, r, "Could not extract public key");
} 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_info, 0, sizeof(pubkey_info)); memset(&pubkey_info, 0, sizeof(pubkey_info));
memset(&pubkey_obj, 0, sizeof(pubkey_obj)); 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; pubkey_info.id = key_info->id;
strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label)); 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"); LOG_TEST_RET(card->ctx, r, "Could not add public key");
sc_pkcs15emu_sc_hsm_free_cvc(&cvc); sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
sc_pkcs15_erase_pubkey(&pubkey);
return SC_SUCCESS; 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 * 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); 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 +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); 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 +818,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

@ -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) static int sc_hsm_delete_ef(sc_pkcs15_card_t *p15card, u8 prefix, u8 id)
{ {
sc_card_t *card = p15card->card; 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) { 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_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; 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++; 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->primeOrModuluslen = curve->prime.len;
cvc->primeOrModulus = malloc(cvc->primeOrModuluslen); 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, static int sc_hsm_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
struct sc_pkcs15_object *object, struct sc_pkcs15_object *object,
struct sc_pkcs15_pubkey *pubkey) 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) { if (pubkey != NULL) {
switch(object->type) { r = sc_pkcs15emu_sc_hsm_get_public_key(&cvc, pubkey);
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;
}
} }
out: 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 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) {