Merge remote-tracking branch 'upstream/staging' into staging

This commit is contained in:
Ludovic Rousseau 2012-08-06 09:01:52 +02:00
commit 12b545f9a9
44 changed files with 1952 additions and 455 deletions

26
NEWS
View File

@ -3,6 +3,32 @@ NEWS for OpenSC -- History of user visible changes
Complete change history is available online:
http://www.opensc-project.org/opensc/timeline
New in 0.13.0; 2012-08-05
* New card driver ePass2003.
* OpenPGP card:
greatly improved card driver and PKCS#15 emulation;
implemented write (pkcs15init) mode;
greatly enhanced documentation and tools.
* ECDSA keys supported in 'read' and 'write' modes by
internal PKCS#15 library, PKCS#11 and tools.
* Minidriver in 'write' mode.
* SM: secure messaging in GlobalPlatform-SP01 and CW14890 specifications;
supported by ePass2003, IAS/ECC and AuthentIC cards;
"ACL" and "APDU" modes to trigger secure messaging session;
'local' version of the external secure messaging module.
* PKCS#15: support of 'secret-key' PKCS#15 objects
support of 'authentication-object' PKCS#15 objects
support of 'algReference' common key PKCS#15 attribute
support of 'algReference' common key PKCS#15 attribute
support of 'subjectName' common public key PKCS#15 attribute
* PKCS#11: removed 'onepin' version of pkcs#11 module
configuration options to expose slots for PINs and present on-card applications.
support GOSTR3410 generate key mechanism
* Support of PACE reader.
* Remove libltdl reference.
* New usefull commands in 'opensc-explorer' tool: 'find', 'put-data', ...
* fixes for the number of documentation ussues
New in 0.12.2; 2011-07-15
* Builds are now silent by default when OpenSC is built from source on Unix.
* Using --wait with command line tools works with 64bit Linux again.

View File

@ -60,7 +60,7 @@
<varlistentry>
<term>
<option>--raw</option>,
<option>--raw</option>
</term>
<listitem><para>
Print values in raw format, as they are stored on the card.
@ -69,7 +69,7 @@
<varlistentry>
<term>
<option>--pretty</option>,
<option>--pretty</option>
</term>
<listitem><para>
Print values in pretty format.
@ -96,6 +96,52 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<option>--verify</option> <replaceable>pintype</replaceable>
</term>
<listitem>
<para>
Verify PIN (CHV1, CHV2 or CHV3).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--pin</option> <replaceable>string</replaceable>
</term>
<listitem>
<para>
The PIN text to verify.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--gen-key</option> <replaceable>ID</replaceable>,
<option>-G</option> <replaceable>ID</replaceable>
</term>
<listitem>
<para>
Generate key. Specify key ID (1, 2 or 3) to generate.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--key-length</option> <replaceable>bitlength</replaceable>,
<option>-L</option> <replaceable>bitlength</replaceable>
</term>
<listitem>
<para>
Length (default 2048 bit) of the key to be generated.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--version</option>,

View File

@ -119,10 +119,7 @@
<varlistentry>
<term>
<command>cat</command> [<replaceable>file-id</replaceable>]
</term>
<term>
<command>cat sfi:</command><replaceable>short-id</replaceable>
<command>cat</command> [<replaceable>file-id</replaceable> | sfi:<replaceable>short-id</replaceable>]
</term>
<listitem><para>Print the contents of the currently selected EF or the contents
of a file specified by <replaceable>file-id</replaceable> or the short file id
@ -132,27 +129,52 @@
<varlistentry>
<term>
<command>cd</command> <replaceable>file-id</replaceable>
<command>cd</command> {.. | <replaceable>file-id</replaceable> | aid:<replaceable>DF-name</replaceable>}
</term>
<listitem><para>Change to another DF specified by <replaceable>file-id</replaceable></para></listitem>
<listitem><para>
Change to another DF specified by the argument passed.
If the argument given is <literal>..</literal>, then move up one level in the
file system hierarchy.
If it is <replaceable>file-id</replaceable>, which must be a DF directly
beneath the current DF, then change to that DF.
If it is an application identifier given as
<literal>aid:</literal><replaceable>DF-name</replaceable>,
then jump to the MF of the application denoted by
<replaceable>DF-name</replaceable>.
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>change CHV</command><replaceable>id</replaceable> [[<replaceable>old-pin</replaceable>] <replaceable>new-pin</replaceable>]
<command>change</command> CHV<replaceable>pin-ref</replaceable> [[<replaceable>old-pin</replaceable>] <replaceable>new-pin</replaceable>]
</term>
<listitem><para>Change a PIN, where <replaceable>id</replaceable> is the PIN reference</para>
<listitem>
<para>Change a PIN, where <replaceable>pin-ref</replaceable> is the PIN reference.</para>
<para>
Examples:
</para>
<para>
Change PIN: change CHV2 00:00:00:00:00:00 "foobar"
</para>
<para>
Set PIN: change CHV2 "foobar"
</para>
<para>
Change PIN with pinpad: change CHV2
Examples:
<variablelist>
<varlistentry>
<term><code>change CHV2 00:00:00:00:00:00 "foobar"</code></term>
<listitem><para>
Change PIN <literal>CHV2</literal>
to the new value <literal>foobar</literal>,
giving the old value <literal>00:00:00:00:00:00</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>change CHV2 "foobar"</code></term>
<listitem><para>
Set PIN <literal>CHV2</literal>
to the new value <literal>foobar</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>change CHV2</code></term>
<listitem><para>
Change PIN <literal>CHV2</literal> using the card reader's pinpad.
</para></listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>
@ -307,16 +329,86 @@
<listitem><para>Remove the EF or DF specified by <replaceable>file-id</replaceable></para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>unblock</command> CHV<replaceable>pin-ref</replaceable> [<replaceable>puk</replaceable> [<replaceable>new pin</replaceable>]]
</term>
<listitem>
<para>
Unblock the PIN denoted by <replaceable>pin-ref</replaceable>
using the PUK <replaceable>puk</replaceable>, and set potentially
change its value to <replaceable>new pin</replaceable>.
</para>
<para>
PUK and PIN values can be a sequence of hexadecimal values,
<literal>"</literal>-enclosed strings, empty (<literal>""</literal>),
or absent.
If they are absent, the values are read from the card reader's pin pad.
</para>
<para>
Examples:
<variablelist>
<varlistentry>
<term><code>unblock CHV2 00:00:00:00:00:00 "foobar"</code></term>
<listitem><para>
Unblock PIN <literal>CHV2</literal> using PUK
<literal>00:00:00:00:00:00</literal>
and set it to the new value <literal>foobar</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>unblock CHV2 00:00:00:00:00:00 ""</code></term>
<listitem><para>
Unblock PIN <literal>CHV2</literal> using PUK
<literal>00:00:00:00:00:00</literal> keeping the old value.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>unblock CHV2 "" "foobar"</code></term>
<listitem><para>
Set new value of PIN <literal>CHV2</literal>
to <literal>foobar</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>unblock CHV2 00:00:00:00:00:00</code></term>
<listitem><para>
Unblock PIN <literal>CHV2</literal> using PUK
<literal>00:00:00:00:00:00</literal>.
The new PIN value is prompted by pinpad.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>unblock CHV2 ""</code></term>
<listitem><para>
Set PIN <literal>CHV2</literal>.
The new PIN value is prompted by pinpad.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>unblock CHV2</code></term>
<listitem><para>
Unblock PIN <literal>CHV2</literal>.
The unblock code and new PIN value are prompted by pinpad.
</para></listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<command>update_binary</command> <replaceable>file-id</replaceable> <replaceable>offs</replaceable> <replaceable>data</replaceable>
</term>
<listitem>
<para>Binary update of the file specified by <replaceable>file-id</replaceable> with the literal data
<replaceable>data</replaceable> starting from offset specified by <replaceable>offs</replaceable>.</para>
<para><replaceable>data</replaceable> can be supplied as a sequence of the hex values or
as a <literal>"</literal> enclosed string. </para>
</listitem>
<para>Binary update of the file specified by
<replaceable>file-id</replaceable> with the literal data
<replaceable>data</replaceable> starting from offset specified
by <replaceable>offs</replaceable>.</para>
<para><replaceable>data</replaceable> can be supplied as a sequencer
of the hex values or as a <literal>"</literal> enclosed string. </para>
</listitem>
</varlistentry>
<varlistentry>
@ -349,7 +441,30 @@
using the card reader's pin pad.
</para>
<para>
Example: verify CHV0 31:32:33:34:00:00:00:00
Examples:
<variablelist>
<varlistentry>
<term><code>verify CHV0 31:32:33:34:00:00:00:00</code></term>
<listitem><para>
Verify <literal>CHV2</literal> using the hex value
<literal>31:32:33:34:00:00:00:00</literal>
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>verify CHV1 "secret"</code></term>
<listitem><para>
Verify <literal>CHV1</literal>
using the string value <literal>secret</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><code>verify KEY2</code></term>
<listitem><para>
Verify <literal>KEY2</literal>,
get the value from the card reader's pin pad.
</para></listitem>
</varlistentry>
</variablelist>
</para>
</listitem>
</varlistentry>

View File

@ -10,7 +10,7 @@
<refnamediv>
<refname>pkcs15-crypt</refname>
<refpurpose>perform crypto operations using pkcs15 smart card</refpurpose>
<refpurpose>perform crypto operations using PKCS#15 smart cards</refpurpose>
</refnamediv>
<refsynopsisdiv>
@ -25,8 +25,8 @@
<para>
The <command>pkcs15-crypt</command> utility can be used from the
command line to perform cryptographic operations such as computing
digital signatures or decrypting data, using keys stored on a PKCS
#15 compliant smart card.
digital signatures or decrypting data, using keys stored on a PKCS#15
compliant smart card.
</para>
</refsect1>
@ -38,7 +38,7 @@
<term>
<option>--aid</option> <replaceable>aid</replaceable>
</term>
<listitem><para>Specify the AID of the on-card PKCS#15 applicationi
<listitem><para>Specify the AID of the on-card PKCS#15 application
to bind to. The <replaceable>aid</replaceable> must be in hexadecimal
form.</para></listitem>
</varlistentry>

View File

@ -22,7 +22,7 @@ opensc.conf: opensc.conf.in force
< $< > $@
install-exec-hook: opensc.conf
$(mkdir_p) "$(DESTDIR)$(sysconfdir)"
$(MKDIR_P) "$(DESTDIR)$(sysconfdir)"
if [ -f "$(DESTDIR)$(sysconfdir)/opensc.conf" ]; then \
$(INSTALL_DATA) opensc.conf "$(DESTDIR)$(sysconfdir)/opensc.conf.new"; \
else \

View File

@ -473,11 +473,14 @@ sc_single_sm_transmit(struct sc_card *card, struct sc_apdu *apdu)
/* get SM encoded APDU */
rv = card->sm_ctx.ops.get_sm_apdu(card, apdu, &sm_apdu);
if (rv == SC_ERROR_SM_NOT_APPLIED) {
/* SM wrap of this APDU is ignored by card driver.
* Send plain APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, apdu);
LOG_FUNC_RETURN(ctx, rv);
}
LOG_TEST_RET(ctx, rv, "get SM APDU error");
if (!sm_apdu)
LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "cannot get SM APDU");
/* check if SM APDU is still valid */
rv = sc_check_apdu(card, sm_apdu);
if (rv < 0) {
@ -507,6 +510,8 @@ sc_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
if (card->reader->ops->transmit == NULL)
LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "cannot transmit APDU");
sc_log(ctx, "CLA:%X, INS:%X, P1:%X, P2:%X, data(%i) %p",
apdu->cla, apdu->ins, apdu->p1, apdu->p2, apdu->datalen, apdu->data);
#ifdef ENABLE_SM
if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)
return sc_single_sm_transmit(card, apdu);

View File

@ -34,6 +34,8 @@ static int asn1_decode(sc_context_t *ctx, struct sc_asn1_entry *asn1,
int choice, int depth);
static int asn1_encode(sc_context_t *ctx, const struct sc_asn1_entry *asn1,
u8 **ptr, size_t *size, int depth);
static int asn1_write_element(sc_context_t *ctx, unsigned int tag,
const u8 * data, size_t datalen, u8 ** out, size_t * outlen);
static const char *tag2str(unsigned int tag)
{
@ -754,6 +756,12 @@ int sc_asn1_put_tag(int tag, const u8 * data, size_t datalen, u8 * out, size_t o
return 0;
}
int sc_asn1_write_element(sc_context_t *ctx, unsigned int tag,
const u8 * data, size_t datalen, u8 ** out, size_t * outlen)
{
return asn1_write_element(ctx, tag, data, datalen, out, outlen);
}
static int asn1_write_element(sc_context_t *ctx, unsigned int tag,
const u8 * data, size_t datalen, u8 ** out, size_t * outlen)
{

View File

@ -111,6 +111,11 @@ int sc_asn1_encode_algorithm_id(struct sc_context *,
const struct sc_algorithm_id *, int);
void sc_asn1_clear_algorithm_id(struct sc_algorithm_id *);
/* ASN.1 object encoding functions */
int sc_asn1_write_element(sc_context_t *ctx, unsigned int tag,
const u8 * data, size_t datalen, u8 ** out, size_t * outlen);
#define SC_ASN1_CLASS_MASK 0x30000000
#define SC_ASN1_UNI 0x00000000 /* Universal */
#define SC_ASN1_APP 0x10000000 /* Application */

View File

@ -2000,6 +2000,7 @@ authentic_manage_sdo(struct sc_card *card, struct sc_authentic_sdo *sdo, unsigne
if (card->max_send_size > 255)
card->max_send_size = 255;
rv = sc_transmit_apdu(card, &apdu);
card->max_send_size = save_max_send;
LOG_TEST_RET(ctx, rv, "APDU transmit failed");
@ -2150,7 +2151,7 @@ authentic_sm_acl_init (struct sc_card *card, struct sm_info *sm_info, int cmd,
unsigned char *resp, size_t *resp_len)
{
struct sc_context *ctx = card->ctx;
struct sm_type_params_gp *params_gp = &sm_info->sm_params.gp;
struct sm_type_params_gp *params_gp = &sm_info->session.gp.params;
struct sc_remote_data rdata;
int rv;
@ -2248,6 +2249,9 @@ authentic_sm_open(struct sc_card *card)
memcpy(card->sm_ctx.info.config_section, card->sm_ctx.config_section, sizeof(card->sm_ctx.info.config_section));
sc_log(ctx, "SM context config '%s'; SM mode 0x%X", card->sm_ctx.info.config_section, card->sm_ctx.sm_mode);
if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT && card->max_send_size == 0)
card->max_send_size = 239;
rv = authentic_sm_acl_init (card, &card->sm_ctx.info, SM_CMD_INITIALIZE, init_data, &init_data_len);
LOG_TEST_RET(ctx, rv, "authentIC: cannot open SM");
@ -2304,18 +2308,19 @@ authentic_sm_get_wrapped_apdu(struct sc_card *card, struct sc_apdu *plain, struc
plain->cla, plain->ins, plain->p1, plain->p2, plain->datalen, plain->data);
*sm_apdu = NULL;
if (plain->cla & 0x04)
return 0;
else if (plain->cla==0x00 && plain->ins==0xA4)
return 0;
else if (plain->cla==0x00 && plain->ins==0xC0)
return 0;
else if (plain->cla==0x00 && plain->ins==0x20)
return 0;
else if (plain->cla==0x80 && plain->ins==0x2E)
return 0;
else if (plain->cla==0x80 && plain->ins==0x50)
return 0;
if ((plain->cla & 0x04)
|| (plain->cla==0x00 && plain->ins==0x22)
|| (plain->cla==0x00 && plain->ins==0x2A)
|| (plain->cla==0x00 && plain->ins==0x84)
|| (plain->cla==0x00 && plain->ins==0x88)
|| (plain->cla==0x00 && plain->ins==0xA4)
|| (plain->cla==0x00 && plain->ins==0xC0)
|| (plain->cla==0x00 && plain->ins==0xCA)
|| (plain->cla==0x80 && plain->ins==0x50)
) {
sc_log(ctx, "SM wrap is not applied for this APDU");
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_APPLIED);
}
if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT)
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_NOT_INITIALIZED);

View File

@ -641,7 +641,8 @@ static int jcop_set_security_env(sc_card_t *card,
tmp.algorithm_ref |= 0x10;
if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
tmp.algorithm_ref |= 0x20;
env=&tmp;
memcpy(env, &tmp, sizeof(struct sc_security_env));
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xC1, 0);

File diff suppressed because it is too large Load Diff

View File

@ -233,8 +233,9 @@ enum {
/*
* OpenPGP
*/
SC_CARDCTL_OPENPGP_BASE = _CTL_PREFIX('P', 'G', 'P'),
SC_CARDCTL_OPENPGP_GENERATE_KEY
SC_CARDCTL_OPENPGP_BASE = _CTL_PREFIX('P', 'G', 'P'),
SC_CARDCTL_OPENPGP_GENERATE_KEY,
SC_CARDCTL_OPENPGP_STORE_KEY
};
enum {
@ -842,14 +843,33 @@ typedef struct sc_cardctl_piv_genkey_info_st {
#define SC_OPENPGP_KEY_ENCR 2
#define SC_OPENPGP_KEY_AUTH 3
#define SC_OPENPGP_KEYFORMAT_STD 0 /* See 4.3.3.6 Algorithm Attributes */
#define SC_OPENPGP_KEYFORMAT_STDN 1 /* OpenPGP card spec v2 */
#define SC_OPENPGP_KEYFORMAT_CRT 2
#define SC_OPENPGP_KEYFORMAT_CRTN 3
typedef struct sc_cardctl_openpgp_keygen_info {
u8 keytype; /* SC_OPENPGP_KEY_ */
u8 *modulus; /* New-generated pubkey info responded from the card */
size_t modulus_len; /* Length of modulus in byte */
size_t modulus_len; /* Length of modulus in bit */
u8 *exponent;
size_t exponent_len;
} sc_cardctl_openpgp_keygen_info_t;
typedef struct sc_cardctl_openpgp_keystore_info {
u8 keytype;
u8 keyformat;
u8 *e;
size_t e_len;
u8 *p;
size_t p_len;
u8 *q;
size_t q_len;
u8 *n;
size_t n_len;
time_t creationtime;
} sc_cardctl_openpgp_keystore_info_t;
#ifdef __cplusplus
}
#endif

View File

@ -308,13 +308,11 @@ static const char *find_library(sc_context_t *ctx, const char *name)
continue;
libname = scconf_get_str(blk, "module", name);
#ifdef _WIN32
if (libname && libname[0] != '\\' ) {
if (libname && libname[0] != '\\' )
#else
if (libname && libname[0] != '/' ) {
if (libname && libname[0] != '/' )
#endif
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: relative path to driver '%s' used",
libname);
}
sc_log(ctx, "warning: relative path to driver '%s' used", libname);
break;
}
@ -338,7 +336,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name
const char *(**tmodv)(void) = &modversion;
if (name == NULL) { /* should not occurr, but... */
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No module specified",name);
sc_log(ctx, "No module specified", name);
return NULL;
}
libname = find_library(ctx, name);
@ -346,7 +344,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name
return NULL;
handle = sc_dlopen(libname);
if (handle == NULL) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror());
sc_log(ctx, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror());
return NULL;
}
@ -354,7 +352,7 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name
*(void **)tmodi = sc_dlsym(handle, "sc_module_init");
*(void **)tmodv = sc_dlsym(handle, "sc_driver_version");
if (modinit == NULL || modversion == NULL) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "dynamic library '%s' is not a OpenSC module",libname);
sc_log(ctx, "dynamic library '%s' is not a OpenSC module",libname);
sc_dlclose(handle);
return NULL;
}
@ -362,12 +360,13 @@ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name
version = modversion();
/* XXX: We really need to have ABI version for each interface */
if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"dynamic library '%s': invalid module version",libname);
sc_log(ctx, "dynamic library '%s': invalid module version", libname);
sc_dlclose(handle);
return NULL;
}
*dll = handle;
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "successfully loaded card driver '%s'", name);
if (dll)
*dll = handle;
sc_log(ctx, "successfully loaded card driver '%s'", name);
return modinit(name);
}
@ -378,9 +377,8 @@ static int load_card_driver_options(sc_context_t *ctx,
int i;
for (i = 0; ctx->conf_blocks[i]; i++) {
blocks = scconf_find_blocks(ctx->conf,
ctx->conf_blocks[i],
"card_driver", driver->short_name);
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
"card_driver", driver->short_name);
if (!blocks)
continue;
blk = blocks[0];
@ -420,7 +418,9 @@ static int load_card_drivers(sc_context_t *ctx,
*(void **)(tfunc) = load_dynamic_driver(ctx, &dll, ent->name);
/* if still null, assume driver not found */
if (func == NULL) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to load '%s'.", ent->name);
sc_log(ctx, "Unable to load '%s'.", ent->name);
if (dll)
sc_dlclose(dll);
continue;
}
@ -487,19 +487,18 @@ static int load_card_atrs(sc_context_t *ctx)
t.type = scconf_get_int(b, "type", SC_CARD_TYPE_UNKNOWN);
list = scconf_find_list(b, "flags");
while (list != NULL) {
unsigned int flags;
unsigned int flags = 0;
if (!list->data) {
list = list->next;
continue;
}
flags = 0;
if (!strcmp(list->data, "rng")) {
if (!strcmp(list->data, "rng"))
flags = SC_CARD_FLAG_RNG;
} else {
if (sscanf(list->data, "%x", &flags) != 1)
flags = 0;
}
else if (sscanf(list->data, "%x", &flags) != 1)
flags = 0;
t.flags |= flags;
list = list->next;
}
@ -549,7 +548,7 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
}
if (!conf_path) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "process_config_file doesn't find opensc config file. Please set the registry key.");
sc_log(ctx, "process_config_file doesn't find opensc config file. Please set the registry key.");
return;
}
@ -572,9 +571,9 @@ static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts)
* there, which is not an error. Nevertheless log this
* fact. */
if (r < 0)
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "scconf_parse failed: %s", ctx->conf->errmsg);
sc_log(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
else
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "scconf_parse failed: %s", ctx->conf->errmsg);
sc_log(ctx, "scconf_parse failed: %s", ctx->conf->errmsg);
scconf_free(ctx->conf);
ctx->conf = NULL;
return;
@ -695,8 +694,8 @@ int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm)
}
process_config_file(ctx, &opts);
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "==================================="); /* first thing in the log */
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "opensc version: %s", sc_get_version());
sc_log(ctx, "==================================="); /* first thing in the log */
sc_log(ctx, "opensc version: %s", sc_get_version());
#ifdef ENABLE_PCSC
ctx->reader_driver = sc_get_pcsc_driver();
@ -786,7 +785,7 @@ int sc_release_context(sc_context_t *ctx)
if (ctx->mutex != NULL) {
int r = sc_mutex_destroy(ctx, ctx->mutex);
if (r != SC_SUCCESS) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "unable to destroy mutex");
sc_log(ctx, "unable to destroy mutex");
return r;
}
}
@ -873,9 +872,9 @@ int sc_make_cache_dir(sc_context_t *ctx)
if (mkdir(dirname, 0700) >= 0)
#endif
break;
if (errno != ENOENT
|| (sp = strrchr(dirname, '/')) == NULL
|| sp == dirname)
if (errno != ENOENT || (sp = strrchr(dirname, '/')) == NULL
|| sp == dirname)
goto failed;
*sp = '\0';
}
@ -897,6 +896,7 @@ int sc_make_cache_dir(sc_context_t *ctx)
return SC_SUCCESS;
/* for lack of a better return code */
failed: sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "failed to create cache directory");
failed:
sc_log(ctx, "failed to create cache directory");
return SC_ERROR_INTERNAL;
}

View File

@ -119,6 +119,7 @@ extern "C" {
#define SC_ERROR_SM_RAND_FAILED -1607
#define SC_ERROR_SM_KEYSET_NOT_FOUND -1608
#define SC_ERROR_SM_IFD_DATA_MISSING -1609
#define SC_ERROR_SM_NOT_APPLIED -1610
/* Errors that do not fit the categories above */

View File

@ -1,9 +1,9 @@
/*
* iasecc-sdo.c: library to manipulate the Security Data Objects (SDO)
* used by IAS/ECC card support.
* used by IAS/ECC card support.
*
* Copyright (C) 2010 Viktor Tarasov <vtarasov@opentrust.com>
* OpenTrust <www.opentrust.com>
* OpenTrust <www.opentrust.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -44,7 +44,7 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags)
{
struct sc_context *ctx = card->ctx;
struct iasecc_extended_tlv *acls = &docp->acls_contact;
int ii, offs;
int ii, offs;
unsigned char mask = 0x40;
if (flags)
@ -67,15 +67,15 @@ iasecc_parse_acls(struct sc_card *card, struct iasecc_sdo_docp *docp, int flags)
int
iasecc_sdo_convert_acl(struct sc_card *card, struct iasecc_sdo *sdo,
iasecc_sdo_convert_acl(struct sc_card *card, struct iasecc_sdo *sdo,
unsigned char op, unsigned *out_method, unsigned *out_ref)
{
struct sc_context *ctx = card->ctx;
struct acl_op {
unsigned char op;
unsigned char mask;
} ops[] = {
{SC_AC_OP_PSO_COMPUTE_SIGNATURE,IASECC_ACL_PSO_SIGNATURE},
} ops[] = {
{SC_AC_OP_PSO_COMPUTE_SIGNATURE,IASECC_ACL_PSO_SIGNATURE},
{SC_AC_OP_INTERNAL_AUTHENTICATE,IASECC_ACL_INTERNAL_AUTHENTICATE},
{SC_AC_OP_PSO_DECRYPT, IASECC_ACL_PSO_DECIPHER},
{SC_AC_OP_GENERATE, IASECC_ACL_GENERATE_KEY},
@ -127,20 +127,20 @@ iasecc_sdo_convert_acl(struct sc_card *card, struct iasecc_sdo *sdo,
*out_method = SC_AC_AUT;
else if ((scb & IASECC_SCB_METHOD_MASK) == IASECC_SCB_METHOD_SM)
*out_method = SC_AC_PRO;
else
else
*out_method = SC_AC_SCB, *out_ref = scb;
break;
}
}
}
sc_log(ctx, "returns method %X; ref %X", *out_method, *out_ref);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
void
void
iasecc_sdo_free_fields(struct sc_card *card, struct iasecc_sdo *sdo)
{
if (sdo->docp.tries_remaining.value)
@ -194,7 +194,8 @@ iasecc_sdo_free_fields(struct sc_card *card, struct iasecc_sdo *sdo)
}
}
void
void
iasecc_sdo_free(struct sc_card *card, struct iasecc_sdo *sdo)
{
iasecc_sdo_free_fields(card, sdo);
@ -202,7 +203,7 @@ iasecc_sdo_free(struct sc_card *card, struct iasecc_sdo *sdo)
}
static int
static int
iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_info *se)
{
struct sc_context *ctx = card->ctx;
@ -238,11 +239,11 @@ iasecc_crt_parse(struct sc_card *card, unsigned char *data, struct iasecc_se_inf
}
}
for (ii=0; ii<IASECC_SE_CRTS_MAX; ii++)
for (ii=0; ii<SC_MAX_CRTS_IN_SE; ii++)
if (!se->crts[ii].tag)
break;
if (ii==IASECC_SE_CRTS_MAX)
if (ii==SC_MAX_CRTS_IN_SE)
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "iasecc_crt_parse() error: too much CRTs in SE");
memcpy(&se->crts[ii], &crt, sizeof(crt));
@ -260,10 +261,10 @@ iasecc_se_get_crt(struct sc_card *card, struct iasecc_se_info *se, struct sc_crt
LOG_FUNC_CALLED(ctx);
if (!se || !crt)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
sc_log(ctx, "CRT search template: %X:%X:%X, refs %X:%X:...",
sc_log(ctx, "CRT search template: %X:%X:%X, refs %X:%X:...",
crt->tag, crt->algo, crt->usage, crt->refs[0], crt->refs[1]);
for (ii=0; ii<IASECC_SE_CRTS_MAX && se->crts[ii].tag; ii++) {
for (ii=0; ii<SC_MAX_CRTS_IN_SE && se->crts[ii].tag; ii++) {
if (crt->tag != se->crts[ii].tag)
continue;
if (crt->algo && crt->algo != se->crts[ii].algo)
@ -275,7 +276,7 @@ iasecc_se_get_crt(struct sc_card *card, struct iasecc_se_info *se, struct sc_crt
memcpy(crt, &se->crts[ii], sizeof(*crt));
sc_log(ctx, "iasecc_se_get_crt() found CRT with refs %X:%X:...",
sc_log(ctx, "iasecc_se_get_crt() found CRT with refs %X:%X:...",
se->crts[ii].refs[0], se->crts[ii].refs[1]);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
@ -286,7 +287,7 @@ iasecc_se_get_crt(struct sc_card *card, struct iasecc_se_info *se, struct sc_crt
int
iasecc_se_get_crt_by_usage(struct sc_card *card, struct iasecc_se_info *se, unsigned char tag,
iasecc_se_get_crt_by_usage(struct sc_card *card, struct iasecc_se_info *se, unsigned char tag,
unsigned char usage, struct sc_crt *crt)
{
struct sc_context *ctx = card->ctx;
@ -297,7 +298,7 @@ iasecc_se_get_crt_by_usage(struct sc_card *card, struct iasecc_se_info *se, unsi
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
sc_log(ctx, "CRT search template with TAG:0x%X and UQB:0x%X", tag, usage);
for (ii=0; ii<IASECC_SE_CRTS_MAX && se->crts[ii].tag; ii++) {
for (ii=0; ii<SC_MAX_CRTS_IN_SE && se->crts[ii].tag; ii++) {
if (tag != se->crts[ii].tag)
continue;
if (usage != se->crts[ii].usage)
@ -314,7 +315,7 @@ iasecc_se_get_crt_by_usage(struct sc_card *card, struct iasecc_se_info *se, unsi
}
int
int
iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_se_info *se)
{
struct sc_context *ctx = card->ctx;
@ -358,7 +359,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
if (data_len != size + size_size + 1)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: invalide SE data size");
offs = 1 + size_size;
for (; offs < data_len;) {
rv = iasecc_crt_parse(card, data + offs, se);
@ -374,7 +375,7 @@ iasecc_se_parse(struct sc_card *card, unsigned char *data, size_t data_len, stru
}
static int
static int
iasecc_parse_size(unsigned char *data, size_t *out)
{
if (*data < 0x80) {
@ -394,7 +395,7 @@ iasecc_parse_size(unsigned char *data, size_t *out)
}
static int
static int
iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_extended_tlv *tlv)
{
struct sc_context *ctx = card->ctx;
@ -410,7 +411,7 @@ iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_ex
tlv->tag = *data;
tag_len = 1;
}
sc_log(ctx, "iasecc_parse_get_tlv() tlv->tag 0x%X", tlv->tag);
size_len = iasecc_parse_size(data + tag_len, &tlv->size);
LOG_TEST_RET(ctx, size_len, "parse error: invalid size data");
@ -427,7 +428,7 @@ iasecc_parse_get_tlv(struct sc_card *card, unsigned char *data, struct iasecc_ex
}
static int
static int
iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_chv *chv)
{
struct sc_context *ctx = card->ctx;
@ -459,7 +460,7 @@ iasecc_parse_chv(struct sc_card *card, unsigned char *data, size_t data_len, str
}
static int
static int
iasecc_parse_prvkey(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_prvkey *prvkey)
{
struct sc_context *ctx = card->ctx;
@ -487,7 +488,7 @@ iasecc_parse_prvkey(struct sc_card *card, unsigned char *data, size_t data_len,
}
static int
static int
iasecc_parse_pubkey(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_pubkey *pubkey)
{
struct sc_context *ctx = card->ctx;
@ -523,7 +524,7 @@ iasecc_parse_pubkey(struct sc_card *card, unsigned char *data, size_t data_len,
}
static int
static int
iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo_keyset *keyset)
{
struct sc_context *ctx = card->ctx;
@ -551,7 +552,7 @@ iasecc_parse_keyset(struct sc_card *card, unsigned char *data, size_t data_len,
}
static int
static int
iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo)
{
struct sc_context *ctx = card->ctx;
@ -613,7 +614,7 @@ iasecc_parse_docp(struct sc_card *card, unsigned char *data, size_t data_len, st
}
static int
static int
iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_sdo *sdo)
{
struct sc_context *ctx = card->ctx;
@ -691,7 +692,7 @@ iasecc_sdo_parse_data(struct sc_card *card, unsigned char *data, struct iasecc_s
}
int
int
iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, struct iasecc_sdo *sdo)
{
struct sc_context *ctx = card->ctx;
@ -723,7 +724,7 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str
if (data_len != size + size_size + 3)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: invalide SDO data size");
sc_log(ctx, "sz %i, sz_size %i", size, size_size);
offs = 3 + size_size;
@ -743,8 +744,8 @@ iasecc_sdo_parse(struct sc_card *card, unsigned char *data, size_t data_len, str
}
int
iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t data_len,
int
iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t data_len,
struct iasecc_sdo **out)
{
struct sc_context *ctx = card->ctx;
@ -757,7 +758,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t
if (*data != IASECC_SDO_TAG_HEADER)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
if (data_len < 3)
if (data_len < 3)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
sdo = calloc(1, sizeof(struct iasecc_sdo));
@ -778,7 +779,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t
if (data_len != size + size_size + 3)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "parse error: invalide SDO data size");
sc_log(ctx, "sz %i, sz_size %i", size, size_size);
offs = 3 + size_size;
@ -811,7 +812,7 @@ iasecc_update_blob(struct sc_context *ctx, struct iasecc_extended_tlv *tlv,
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
sz = tlv->size + 2;
if (tlv->tag > 0xFF)
sz += 1;
@ -819,11 +820,11 @@ iasecc_update_blob(struct sc_context *ctx, struct iasecc_extended_tlv *tlv,
sz += 1;
else if (tlv->size >= 0x100)
sz += 2;
pp = realloc(*blob, *blob_size + sz);
if (!pp)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
if (tlv->tag > 0xFF)
*(pp + *blob_size + offs++) = (tlv->tag >> 8) & 0xFF;
*(pp + *blob_size + offs++) = tlv->tag & 0xFF;
@ -853,7 +854,7 @@ iasecc_encode_docp(struct sc_context *ctx, struct iasecc_sdo_docp *docp, unsigne
unsigned char *st_blob, *tmp_blob, *docp_blob;
size_t blob_size;
int rv;
LOG_FUNC_CALLED(ctx);
if (!docp->acls_contact.size || (docp->size.size != 2))
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
@ -955,7 +956,7 @@ iasecc_sdo_encode_create(struct sc_context *ctx, struct iasecc_sdo *sdo, unsigne
};
struct sc_asn1_entry c_asn1_create_data[2] = {
{ "createData", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_APP | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry asn1_docp_data[2], asn1_create_data[2];
unsigned char *blob = NULL;
@ -990,7 +991,7 @@ iasecc_sdo_encode_create(struct sc_context *ctx, struct iasecc_sdo *sdo, unsigne
}
int
int
iasecc_sdo_encode_update_field(struct sc_context *ctx, unsigned char sdo_class, unsigned char sdo_ref,
struct iasecc_extended_tlv *tlv, unsigned char **out)
{
@ -1000,19 +1001,19 @@ iasecc_sdo_encode_update_field(struct sc_context *ctx, unsigned char sdo_class,
struct sc_asn1_entry c_asn1_field_value[2] = {
{ "fieldValue", SC_ASN1_OCTET_STRING, 0, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry c_asn1_sdo_field[2] = {
{ "sdoField", SC_ASN1_STRUCT, 0, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry c_asn1_class_data[2] = {
{ "classData", SC_ASN1_STRUCT, 0, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry c_asn1_update_data[2] = {
{ "updateData", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_APP | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry asn1_field_value[4], asn1_sdo_field[2], asn1_class_data[2], asn1_update_data[2];
@ -1036,14 +1037,14 @@ iasecc_sdo_encode_update_field(struct sc_context *ctx, unsigned char sdo_class,
rv = sc_asn1_encode(ctx, asn1_update_data, out, &out_len);
LOG_TEST_RET(ctx, rv, "Encode update data error");
sc_debug(ctx, SC_LOG_DEBUG_ASN1,"Data: %s", sc_dump_hex(tlv->value, tlv->size));
sc_debug(ctx, SC_LOG_DEBUG_ASN1,"Encoded: %s", sc_dump_hex(*out, out_len));
LOG_FUNC_RETURN(ctx, out_len);
}
int
int
iasecc_sdo_encode_rsa_update(struct sc_context *ctx, struct iasecc_sdo *sdo, struct sc_pkcs15_prkey_rsa *rsa,
struct iasecc_sdo_update *sdo_update)
{
@ -1055,7 +1056,7 @@ iasecc_sdo_encode_rsa_update(struct sc_context *ctx, struct iasecc_sdo *sdo, str
int indx = 0;
sc_log(ctx, "iasecc_sdo_encode_rsa_update(IASECC_SDO_CLASS_RSA_PRIVATE)");
if (!rsa->p.len || !rsa->q.len || !rsa->iqmp.len || !rsa->dmp1.len || !rsa->dmq1.len)
if (!rsa->p.len || !rsa->q.len || !rsa->iqmp.len || !rsa->dmp1.len || !rsa->dmq1.len)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "need all private RSA key components");
sdo_update->magic = SC_CARDCTL_IASECC_SDO_MAGIC_PUT_DATA;
@ -1096,7 +1097,7 @@ iasecc_sdo_encode_rsa_update(struct sc_context *ctx, struct iasecc_sdo *sdo, str
sc_log(ctx, "prv_key.compulsory.on_card %i", sdo->data.prv_key.compulsory.on_card);
if (!sdo->data.prv_key.compulsory.on_card) {
if (sdo->data.prv_key.compulsory.value) {
sc_log(ctx, "sdo_prvkey->data.prv_key.compulsory.size %i", sdo->data.prv_key.compulsory.size);
sc_log(ctx, "sdo_prvkey->data.prv_key.compulsory.size %i", sdo->data.prv_key.compulsory.size);
sdo_update->fields[indx].parent_tag = IASECC_SDO_PRVKEY_TAG;
sdo_update->fields[indx].tag = IASECC_SDO_PRVKEY_TAG_COMPULSORY;
sdo_update->fields[indx].value = sdo->data.prv_key.compulsory.value;
@ -1145,7 +1146,7 @@ iasecc_sdo_encode_rsa_update(struct sc_context *ctx, struct iasecc_sdo *sdo, str
indx++;
}
/* For ECC card 'compulsory' flag should be already here */
/* For ECC card 'compulsory' flag should be already here */
if (!sdo->data.pub_key.compulsory.on_card) {
if (sdo->data.pub_key.compulsory.value) {
sdo_update->fields[indx].parent_tag = IASECC_SDO_PUBKEY_TAG;
@ -1222,7 +1223,7 @@ iasecc_sdo_parse_card_answer(struct sc_context *ctx, unsigned char *data, size_t
static int
iasecc_tlv_copy(struct sc_context *ctx, struct iasecc_extended_tlv *in, struct iasecc_extended_tlv *out)
{
if (!in || !out)
if (!in || !out)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
memset(out, 0, sizeof(struct iasecc_extended_tlv));
@ -1233,7 +1234,7 @@ iasecc_tlv_copy(struct sc_context *ctx, struct iasecc_extended_tlv *in, struct i
out->value = calloc(1, in->size);
if (!out->value)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy(out->value, in->value, in->size);
out->size = in->size;
}
@ -1286,4 +1287,4 @@ iasecc_docp_copy(struct sc_context *ctx, struct iasecc_sdo_docp *in, struct iase
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
#endif /* ENABLE_OPENSSL */
#endif /* ENABLE_OPENSSL */

View File

@ -154,7 +154,7 @@
#define IASECC_SDO_TAGS_UPDATE_MAX 16
#define IASECC_SE_CRTS_MAX 24
//#define IASECC_SE_CRTS_MAX 24
#define _MAKE_IASECC_SDO_MAGIC(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | ((d)))
@ -163,7 +163,7 @@
#define IASECC_SDO_MAGIC_UPDATE_RSA _MAKE_IASECC_SDO_MAGIC('E', 'C', 'U', 'R')
#define IASECC_MAX_SCBS 7
#define IASECC_MAX_CRTS_IN_SE 24
//#define IASECC_MAX_CRTS_IN_SE 24
struct iasecc_extended_tlv {
unsigned tag;

View File

@ -2,7 +2,7 @@
* iasecc.h Support for IAS/ECC smart cards
*
* Copyright (C) 2010 Viktor Tarasov <vtarasov@opentrust.com>
* OpenTrust <www.opentrust.com>
* OpenTrust <www.opentrust.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -157,6 +157,7 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sc_remote_data rdata;
struct sc_apdu apdu;
unsigned char sbuf[0x100];
@ -173,9 +174,9 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
sm_info->serialnr = card->serialnr;
sm_info->card_type = card->type;
sm_info->sm_type = SM_TYPE_CWA14890;
sm_info->sm_params.cwa.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION;
sm_info->sm_params.cwa.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH;
sm_info->sm_params.cwa.crt_at.refs[0] = skey_ref;
cwa_session->params.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION;
cwa_session->params.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH;
cwa_session->params.crt_at.refs[0] = skey_ref;
offs = 0;
sbuf[offs++] = IASECC_CRT_TAG_ALGO;
@ -195,7 +196,7 @@ iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *
rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");
rv = sc_get_challenge(card, sm_info->schannel.card_challenge, sizeof(sm_info->schannel.card_challenge));
rv = sc_get_challenge(card, cwa_session->card_challenge, sizeof(cwa_session->card_challenge));
LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");
sc_remote_data_init(&rdata);
@ -227,7 +228,7 @@ iasecc_sm_se_mutual_authentication(struct sc_card *card, unsigned se_num)
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct iasecc_se_info se;
struct sc_crt *crt = &sm_info->sm_params.cwa.crt_at;
struct sc_crt *crt = &sm_info->session.cwa.params.crt_at;
struct sc_apdu apdu;
unsigned char sbuf[0x100];
int rv, offs;
@ -305,7 +306,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct sm_cwa_session *cwa_session = &sm_info->schannel.session.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sc_remote_data rdata;
int rv;
@ -320,7 +321,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
rv = iasecc_sm_se_mutual_authentication(card, se_num);
LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() MUTUAL AUTHENTICATION failed");
rv = iasecc_sm_get_challenge(card, sm_info->schannel.card_challenge, SM_SMALL_CHALLENGE_LEN);
rv = iasecc_sm_get_challenge(card, cwa_session->card_challenge, SM_SMALL_CHALLENGE_LEN);
LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() GET CHALLENGE failed");
sc_remote_data_init(&rdata);
@ -351,7 +352,7 @@ iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
rdata.free(&rdata);
sc_log(ctx, "MA data(len:%i) '%s'", cwa_session->mdata_len, sc_dump_hex(cwa_session->mdata, cwa_session->mdata_len));
if (sm_info->schannel.session.cwa.mdata_len != 0x48)
if (cwa_session->mdata_len != 0x48)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "iasecc_sm_initialize() invalid MUTUAL AUTHENTICATE result data");
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
@ -370,7 +371,7 @@ iasecc_sm_cmd(struct sc_card *card, struct sc_remote_data *rdata)
struct sc_context *ctx = card->ctx;
#ifdef ENABLE_SM
struct sm_info *sm_info = &card->sm_ctx.info;
struct sm_cwa_session *session = &sm_info->schannel.session.cwa;
struct sm_cwa_session *session = &sm_info->session.cwa;
struct sc_remote_apdu *rapdu = NULL;
int rv;

View File

@ -49,6 +49,7 @@ sc_asn1_print_tags
sc_asn1_put_tag
sc_asn1_skip_tag
sc_asn1_verify_tag
sc_asn1_write_element
sc_base64_decode
sc_base64_encode
sc_bin_to_hex

View File

@ -640,12 +640,12 @@ int msc_compute_crypt_init(sc_card_t *card,
u8 *ptr;
int r;
u8 outputBuffer[MSC_MAX_APDU];
u8 outputBuffer[MSC_MAX_APDU + 2];
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x36, keyLocation, 0x01); /* Init */
apdu.data = buffer;
apdu.datalen = dataLength + 5;
apdu.lc = dataLength + 5;
memset(outputBuffer, 0, sizeof(outputBuffer));
apdu.resp = outputBuffer;
apdu.resplen = dataLength + 2;
@ -657,13 +657,14 @@ int msc_compute_crypt_init(sc_card_t *card,
*ptr = (dataLength >> 8) & 0xFF; ptr++;
*ptr = dataLength & 0xFF; ptr++;
memcpy(ptr, initData, dataLength);
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
if(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
short receivedData = outputBuffer[0] << 8 | outputBuffer[1];
*outputDataLength = receivedData;
*outputDataLength = 0;
assert(receivedData <= MSC_MAX_APDU);
memcpy(outputData, outputBuffer + 2, receivedData);
return 0;
@ -746,7 +747,7 @@ int msc_compute_crypt_final(
{
sc_apdu_t apdu;
u8 buffer[MSC_MAX_APDU];
u8 outputBuffer[MSC_MAX_APDU];
u8 outputBuffer[MSC_MAX_APDU + 2];
u8 *ptr;
int r;

View File

@ -244,7 +244,7 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
strlcpy(prkey_obj.label, prkey_name[i], sizeof(prkey_obj.label));
prkey_obj.auth_id.len = 1;
prkey_obj.auth_id.value[0] = prkey_pin[i];
prkey_obj.user_consent = (i == 1) ? 1 : 0;
prkey_obj.user_consent = 0;
prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);

View File

@ -174,7 +174,7 @@ static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path,
/* Using (block+1) in while loop avoids using final cert object data block */
while (!found && ( (block+1) * 248 < objlen) ) {
/* Check current buffer */
for (i = 0; i < 248; i++) {
for (i = 0; i < 247; i++) {
if (ibuf[i] == 0x30 && ibuf[i+1] == 0x82) {
found = 1;
break;

View File

@ -95,7 +95,7 @@ typedef struct _pgp_key_cfg {
static const pgp_key_cfg_t key_cfg[3] = {
{ "Signature key", "B601", 1, PGP_SIG_PRKEY_USAGE, PGP_SIG_PUBKEY_USAGE },
{ "Encryption key", "B801", 2, PGP_ENC_PRKEY_USAGE, PGP_ENC_PUBKEY_USAGE },
{ "Authentication key", "A401", 2, PGP_AUTH_PRKEY_USAGE, PGP_AUTH_PUBKEY_USAGE }
{ "Authentication key", "A401", 2, PGP_AUTH_PRKEY_USAGE | PGP_ENC_PRKEY_USAGE, PGP_AUTH_PUBKEY_USAGE | PGP_ENC_PUBKEY_USAGE }
};
@ -156,11 +156,8 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
u8 c5data[70];
int r, i;
const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V2) ? pin_cfg_v2 : pin_cfg_v1;
struct sc_pkcs15_cert_info cert_info;
struct sc_pkcs15_object cert_obj;
memset(&cert_info, 0, sizeof(cert_info));
memset(&cert_obj, 0, sizeof(cert_obj));
sc_path_t path;
sc_file_t *file;
set_string(&p15card->tokeninfo->label, "OpenPGP card");
set_string(&p15card->tokeninfo->manufacturer_id, "OpenPGP project");
@ -333,16 +330,33 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
}
}
/* Certificate ID. We use the same ID as the authentication key */
cert_info.id.value[0] = 3;
cert_info.id.len = 1;
/* Authority, flag is zero */
sc_format_path("3F007F21", &cert_info.path);
strlcpy(cert_obj.label, "Cardholder certificate", sizeof(cert_obj.label));
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
/* Check if certificate DO 7F21 holds data */
sc_format_path("7F21", &path);
r = sc_select_file(card, &path, &file);
if (r < 0)
return SC_ERROR_INTERNAL;
goto failed;
/* If DO 7F21 holds data, we declare a cert object for pkcs15 */
if (file->size > 0) {
struct sc_pkcs15_cert_info cert_info;
struct sc_pkcs15_object cert_obj;
memset(&cert_info, 0, sizeof(cert_info));
memset(&cert_obj, 0, sizeof(cert_obj));
/* Certificate ID. We use the same ID as the authentication key */
cert_info.id.value[0] = 3;
cert_info.id.len = 1;
/* Authority, flag is zero */
/* The path following which PKCS15 will find the content of the object */
sc_format_path("3F007F21", &cert_info.path);
/* Object label */
strlcpy(cert_obj.label, "Cardholder certificate", sizeof(cert_obj.label));
r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
if (r < 0)
goto failed;
}
return 0;

View File

@ -498,11 +498,11 @@ sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15
}
static void
sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key)
void
sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key)
{
assert(key != NULL);
if (!key)
return;
switch (key->algorithm) {
case SC_ALGORITHM_RSA:
free(key->u.rsa.modulus.data);
@ -529,15 +529,8 @@ sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key)
/* TODO: -DEE may not need much */
break;
}
sc_mem_clear(key, sizeof(key));
}
void
sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key)
{
sc_pkcs15_erase_prkey(key);
free(key);
}
void sc_pkcs15_free_prkey_info(sc_pkcs15_prkey_info_t *key)
{

View File

@ -60,9 +60,9 @@ extern "C" {
#define SM_CMD_FILE_CREATE 0x203
#define SM_CMD_FILE_DELETE 0x204
#define SM_CMD_PIN 0x300
#define SM_CMD_PIN_VERIFY 0x301
#define SM_CMD_PIN_VERIFY 0x301
#define SM_CMD_PIN_RESET 0x302
#define SM_CMD_PIN_SET_PIN 0x303
#define SM_CMD_PIN_SET_PIN 0x303
#define SM_CMD_PSO 0x400
#define SM_CMD_PSO_DST 0x401
#define SM_CMD_APDU 0x500
@ -93,7 +93,7 @@ extern "C" {
/* Global Platform (SCP01) data types */
/*
* @struct sm_type_params_gp
* Global Platform SM channel parameters
* Global Platform SM channel parameters
*/
struct sm_type_params_gp {
unsigned level;
@ -105,9 +105,9 @@ struct sm_type_params_gp {
/*
* @struct sm_gp_keyset
* Global Platform keyset:
* - version, index;
* - keyset presented in three parts: 'ENC', 'MAC' and 'KEK';
* Global Platform keyset:
* - version, index;
* - keyset presented in three parts: 'ENC', 'MAC' and 'KEK';
* - keyset presented in continuous manner - raw or 'to be diversified'.
*/
struct sm_gp_keyset {
@ -123,9 +123,16 @@ struct sm_gp_keyset {
/*
* @struct sm_gp_session
* Global Platform SM session data
* Global Platform SM session data
*/
struct sm_gp_session {
struct sm_gp_keyset gp_keyset;
struct sm_type_params_gp params;
unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char *session_enc, *session_mac, *session_kek;
unsigned char mac_icv[8];
};
@ -142,9 +149,9 @@ struct sm_type_params_cwa {
/*
* @struct sm_cwa_keyset
* CWA keyset:
* - SDO reference;
* - 'ENC' and 'MAC' 3DES keys.
* CWA keyset:
* - SDO reference;
* - 'ENC' and 'MAC' 3DES keys.
*/
struct sm_cwa_keyset {
unsigned sdo_reference;
@ -154,9 +161,9 @@ struct sm_cwa_keyset {
/*
* @struct sm_cwa_token_data
* CWA token data:
* - serial;
* - 'small' random;
* CWA token data:
* - serial;
* - 'small' random;
* - 'big' random.
*/
struct sm_cwa_token_data {
@ -167,13 +174,17 @@ struct sm_cwa_token_data {
/*
* @struct sm_cwa_session
* CWA working SM session data:
* - ICC and IFD token data;
* - ENC and MAC session keys;
* - SSC (SM Sequence Counter);
* - 'mutual authentication' data.
* CWA working SM session data:
* - ICC and IFD token data;
* - ENC and MAC session keys;
* - SSC (SM Sequence Counter);
* - 'mutual authentication' data.
*/
struct sm_cwa_session {
struct sm_cwa_keyset cwa_keyset;
struct sm_type_params_cwa params;
struct sm_cwa_token_data icc;
struct sm_cwa_token_data ifd;
@ -182,37 +193,20 @@ struct sm_cwa_session {
unsigned char ssc[8];
unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char mdata[0x48];
size_t mdata_len;
};
/*
* @struct sc_secure channel
* data type to open and maintain the Secure Messaging session.
*/
struct sm_secure_channel {
union {
struct sm_gp_keyset gp;
struct sm_cwa_keyset cwa;
} keyset;
union {
struct sm_gp_session gp;
struct sm_cwa_session cwa;
} session;
unsigned char host_challenge[SM_SMALL_CHALLENGE_LEN];
unsigned char card_challenge[SM_SMALL_CHALLENGE_LEN];
};
/*
* @struct sc_info is the
* placehold for the secure messaging working data:
* - SM type;
* - SM session state;
* - command to execute by external SM module;
* - data related to the current card context.
* placehold for the secure messaging working data:
* - SM type;
* - SM session state;
* - command to execute by external SM module;
* - data related to the current card context.
*/
struct sm_info {
char config_section[64];
@ -223,9 +217,9 @@ struct sm_info {
unsigned sm_type;
union {
struct sm_type_params_gp gp;
struct sm_type_params_cwa cwa;
} sm_params;
struct sm_gp_session gp;
struct sm_cwa_session cwa;
} session;
struct sc_serial_number serialnr;
@ -237,13 +231,11 @@ struct sm_info {
unsigned char *rdata;
size_t rdata_len;
struct sm_secure_channel schannel;
};
/*
* @struct sm_card_response
* data type to return card response.
* data type to return card response.
*/
typedef struct sm_card_response {
int num;
@ -265,11 +257,11 @@ struct sc_card;
/*
* @struct sm_card_operations
* card driver handlers related to secure messaging (in 'APDU TRANSMIT' mode)
* - 'open' - initialize SM session;
* - 'encode apdu' - SM encoding of the raw APDU;
* - 'decrypt response' - decode card answer;
* - 'close' - close SM session.
* card driver handlers related to secure messaging (in 'APDU TRANSMIT' mode)
* - 'open' - initialize SM session;
* - 'encode apdu' - SM encoding of the raw APDU;
* - 'decrypt response' - decode card answer;
* - 'close' - close SM session.
*/
struct sm_card_operations {
int (*open)(struct sc_card *card);
@ -285,12 +277,12 @@ struct sm_card_operations {
/*
* @struct sm_module_operations
* API to use external SM modules:
* - 'initiliaze' - get APDU(s) to initialize SM session;
* - 'get apdus' - get secured APDUs to execute particular command;
* - 'finalize' - get APDU(s) to finalize SM session;
* - 'module init' - initialize external module (allocate data, read configuration, ...);
* - 'module cleanup' - free resources allocated by external module.
* API to use external SM modules:
* - 'initiliaze' - get APDU(s) to initialize SM session;
* - 'get apdus' - get secured APDUs to execute particular command;
* - 'finalize' - get APDU(s) to finalize SM session;
* - 'module init' - initialize external module (allocate data, read configuration, ...);
* - 'module cleanup' - free resources allocated by external module.
*/
struct sm_module_operations {
int (*initialize)(struct sc_context *ctx, struct sm_info *info,
@ -314,8 +306,8 @@ typedef struct sm_module {
} sm_module_t;
/* @struct sm_context
* SM context -- top level of the SM data type
* - SM mode ('ACL' or 'APDU TRANSMIT'), flags;
* SM context -- top level of the SM data type
* - SM mode ('ACL' or 'APDU TRANSMIT'), flags;
* - working SM data;
* - card operations related to SM in 'APDU TRANSMIT' mode;
* - external SM module;

View File

@ -51,7 +51,7 @@ pkcs11-jar: jar-dir
if WIN32
install-exec-hook:
$(mkdir_p) "$(DESTDIR)$(libdir)"
$(MKDIR_P) "$(DESTDIR)$(libdir)"
for l in opensc-pkcs11.dll pkcs11-spy.dll; do \
mv "$(DESTDIR)$(libdir)/$$l" "$(DESTDIR)$(bindir)/$$l"; \
done
@ -63,7 +63,7 @@ else
PKCS11_SUFFIX=.so
endif
install-exec-hook:
$(mkdir_p) "$(DESTDIR)$(pkcs11dir)"
$(MKDIR_P) "$(DESTDIR)$(pkcs11dir)"
for l in opensc-pkcs11$(PKCS11_SUFFIX) pkcs11-spy$(PKCS11_SUFFIX); do \
rm -f "$(DESTDIR)$(pkcs11dir)/$$l"; \
$(LN_S) ../$$l "$(DESTDIR)$(pkcs11dir)/$$l"; \

View File

@ -1793,16 +1793,16 @@ pkcs15_create_private_key(struct sc_pkcs11_slot *slot, struct sc_profile *profil
args.key.algorithm = SC_ALGORITHM_RSA;
rsa = &args.key.u.rsa;
break;
case CKK_EC:
args.key.algorithm = SC_ALGORITHM_EC;
ec = &args.key.u.ec;
/* TODO: -DEE Do not have PKCS15 card with EC to test this */
/* fall through */
case CKK_GOSTR3410:
set_gost_params(&args.params.gost, NULL, pTemplate, ulCount, NULL, 0);
args.key.algorithm = SC_ALGORITHM_GOSTR3410;
gost = &args.key.u.gostr3410;
break;
case CKK_EC:
args.key.algorithm = SC_ALGORITHM_EC;
ec = &args.key.u.ec;
/* TODO: -DEE Do not have PKCS15 card with EC to test this */
/* fall through */
default:
return CKR_ATTRIBUTE_VALUE_INVALID;
}
@ -2584,6 +2584,8 @@ pkcs15_gen_keypair(struct sc_pkcs11_slot *slot, CK_MECHANISM_PTR pMechanism,
keytype = CKK_RSA;
else if (rv != CKR_OK && pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
keytype = CKK_EC;
else if (rv != CKR_OK && pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN)
keytype = CKK_GOSTR3410;
else if (rv != CKR_OK)
goto kpgen_done;
@ -4324,6 +4326,17 @@ static int register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
if (rc != CKR_OK)
return rc;
}
if (flags & SC_ALGORITHM_ONBOARD_KEY_GEN) {
mech_info.flags = CKF_HW | CKF_GENERATE_KEY_PAIR;
mt = sc_pkcs11_new_fw_mechanism(CKM_GOSTR3410_KEY_PAIR_GEN,
&mech_info, CKK_GOSTR3410, NULL);
if (!mt)
return CKR_HOST_MEMORY;
rc = sc_pkcs11_register_mechanism(p11card, mt);
if (rc != CKR_OK)
return rc;
}
return CKR_OK;
}

View File

@ -28,7 +28,8 @@ dist_pkgdata_DATA = \
authentic.profile \
iasecc.profile \
ias_adele_admin1.profile ias_adele_admin2.profile ias_adele_common.profile \
iasecc_generic_pki.profile iasecc_admin_eid.profile iasecc_generic_oberthur.profile
iasecc_generic_pki.profile iasecc_admin_eid.profile iasecc_generic_oberthur.profile \
openpgp.profile
AM_CPPFLAGS = -DSC_PKCS15_PROFILE_DIRECTORY=\"$(pkgdatadir)\"
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS)
@ -44,4 +45,4 @@ libpkcs15init_la_SOURCES = \
pkcs15-entersafe.c pkcs15-epass2003.c \
pkcs15-rtecp.c pkcs15-myeid.c \
pkcs15-oberthur.c pkcs15-oberthur-awp.c \
pkcs15-authentic.c pkcs15-iasecc.c
pkcs15-authentic.c pkcs15-iasecc.c pkcs15-openpgp.c

View File

@ -9,7 +9,7 @@ OBJECTS = pkcs15-lib.obj profile.obj \
pkcs15-muscle.obj pkcs15-asepcos.obj pkcs15-rutoken.obj \
pkcs15-entersafe.obj pkcs15-rtecp.obj pkcs15-westcos.obj \
pkcs15-myeid.obj pkcs15-authentic.obj pkcs15-iasecc.obj \
pkcs15-epass2003.obj
pkcs15-epass2003.obj pkcs15-openpgp.obj
all: $(TARGET)

View File

@ -0,0 +1,98 @@
#
# PKCS15 profile, generic information.
# This profile is loaded before any card specific profile.
#
cardinfo {
min-pin-length = 6;
# max length should be overridden in the per-card profile
max-pin-length = 12; # To be defined
}
# Default settings.
# This option block will always be processed.
option default {
macros {
protected = *=$SOPIN, READ=NONE;
unprotected = *=NONE;
so-pin-flags = local, initialized, soPin;
so-min-pin-length = 8;
so-pin-attempts = 3;
so-auth-id = 3;
odf-size = 256;
aodf-size = 256;
cdf-size = 512;
prkdf-size = 256;
pukdf-size = 256;
dodf-size = 256;
}
}
# Define reasonable limits for PINs and PUK
# Note that we do not set a file path or reference
# for the user pin; that is done dynamically.
PIN user-pin {
attempts = 3;
flags = local, initialized;
}
PIN so-pin {
auth-id = $so-auth-id;
attempts = $so-pin-attempts;
min-length = $so-min-pin-length;
flags = $so-pin-flags;
}
filesystem {
DF MF {
path = 3F00;
type = DF;
# This is the DIR file
EF DIR {
type = EF;
file-id = 2F00;
acl = *=NONE;
}
# Here comes the application DF
DF PKCS15-AppDF {
type = DF;
aid = D2:76:00:01:24:01;
acl = *=NONE;
EF PKCS15-TokenInfo {
ACL = $unprotected;
}
EF PKCS15-PrKDF {
size = $prkdf-size;
acl = $protected;
}
EF PKCS15-PuKDF {
size = $pukdf-size;
acl = $protected;
}
EF PKCS15-CDF {
acl = $unprotected;
}
# This template defines files for keys, certificates etc.
#
# When instantiating the template, each file id will be
# combined with the last octet of the object's pkcs15 id
# to form a unique file ID.
template key-domain {
# This is a dummy entry - pkcs15-init insists that
# this is present
EF private-key {
file-id = 5F48;
ACL = *=NEVER, CRYPTO=$PIN, UPDATE=CHV3;
}
}
}
}
}

View File

@ -414,6 +414,7 @@ extern struct sc_pkcs15init_operations *sc_pkcs15init_get_myeid_ops(void);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_authentic_ops(void);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_iasecc_ops(void);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_piv_ops(void);
extern struct sc_pkcs15init_operations *sc_pkcs15init_get_openpgp_ops(void);
#ifdef __cplusplus
}

View File

@ -145,6 +145,7 @@ static struct profile_operations {
{ "jcop", (void *) sc_pkcs15init_get_jcop_ops },
{ "starcos", (void *) sc_pkcs15init_get_starcos_ops },
{ "oberthur", (void *) sc_pkcs15init_get_oberthur_ops },
{ "openpgp", (void *) sc_pkcs15init_get_openpgp_ops },
{ "setcos", (void *) sc_pkcs15init_get_setcos_ops },
{ "incrypto34", (void *) sc_pkcs15init_get_incrypto34_ops },
{ "muscle", (void*) sc_pkcs15init_get_muscle_ops },
@ -379,23 +380,26 @@ sc_pkcs15init_bind(struct sc_card *card, const char *name, const char *profile_o
if (app_info && app_info->aid.len) {
struct sc_path path;
if (card->ef_atr->aid.len) {
sc_log(ctx, "sc_pkcs15init_bind() select MF");
if (card->ef_atr && card->ef_atr->aid.len) {
sc_log(ctx, "sc_pkcs15init_bind() select MF using EF.ATR data");
memset(&path, 0, sizeof(struct sc_path));
path.type = SC_PATH_TYPE_DF_NAME;
path.aid = card->ef_atr->aid;
r = sc_select_file(card, &path, NULL);
sc_log(ctx, "rv %i", r);
if (r)
return r;
}
sc_log(ctx, "sc_pkcs15init_bind() select application DF");
memset(&path, 0, sizeof(struct sc_path));
path.type = SC_PATH_TYPE_DF_NAME;
path.aid = app_info->aid;
if (app_info->path.len) {
path = app_info->path;
}
else {
memset(&path, 0, sizeof(struct sc_path));
path.type = SC_PATH_TYPE_DF_NAME;
path.aid = app_info->aid;
}
sc_log(ctx, "sc_pkcs15init_bind() select application path(type:%X) '%s'", path.type, sc_print_path(&path));
r = sc_select_file(card, &path, NULL);
sc_log(ctx, "sc_pkcs15init_bind() select application DF returned %i", r);
}
*result = profile;
@ -2534,6 +2538,7 @@ sc_pkcs15init_update_tokeninfo(struct sc_pkcs15_card *p15card, struct sc_profile
size_t size;
int r;
LOG_FUNC_CALLED(p15card->card->ctx);
/* set lastUpdate field */
if (p15card->tokeninfo->last_update.gtime != NULL)
free(p15card->tokeninfo->last_update.gtime);
@ -2551,7 +2556,7 @@ sc_pkcs15init_update_tokeninfo(struct sc_pkcs15_card *p15card, struct sc_profile
r = sc_pkcs15init_update_file(profile, p15card, p15card->file_tokeninfo, buf, size);
if (buf)
free(buf);
return r;
LOG_FUNC_RETURN(p15card->card->ctx, r);
}

317
src/pkcs15init/pkcs15-openpgp.c Executable file
View File

@ -0,0 +1,317 @@
/*
* OpenPGP specific operation for PKCS15 initialization
*
* Copyright (c) 2012 Nguyen Hong Quan <ng.hong.quan@gmail.com>.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "libopensc/opensc.h"
#include "libopensc/cardctl.h"
#include "libopensc/log.h"
#include "libopensc/cards.h"
#include "libopensc/asn1.h"
#include "pkcs15-init.h"
#include "profile.h"
/**
* Erase card: erase all EFs/DFs created by OpenSC
* @param profile The sc_profile_t object with the configurable profile
* information
* @param p15card The card from which the opensc application should be
* erased.
* @return SC_SUCCESS on success and an error code otherwise
**/
static int openpgp_erase(struct sc_profile *profile, sc_pkcs15_card_t *p15card)
{
return SC_ERROR_NOT_SUPPORTED;
}
/**
* Create application DF
* @param profile sc_profile_t object with the configurable profile
* information
* @param p15card sc_card_t object to be used
* @param df sc_file_t with the application DF to create
* @return SC_SUCCESS on success and an error value otherwise
**/
static int openpgp_create_dir(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_file_t *df)
{
return SC_ERROR_NOT_SUPPORTED;
}
/**
* Select PIN reference: do nothing special, the real PIN reference if
* determined when the PIN is created. This is just helper function to
* determine the next best file id of the PIN file.
**/
static int openpgp_select_pin_reference(sc_profile_t *profile,
sc_pkcs15_card_t *p15card, sc_pkcs15_auth_info_t *auth_info)
{
return SC_ERROR_NOT_SUPPORTED;
}
/**
* Create PIN and, if specified, PUK files
* @param profile profile information for this card
* @param card sc_card_t object to use
* @param pin_obj sc_pkcs15_object_t for the PIN
* @param pin PIN value
* @param len_len PIN length
* @param puk PUK value (optional)
* @param puk_len PUK length (optional)
* @return SC_SUCCESS on success and an error code otherwise
**/
static int openpgp_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_file_t *df, sc_pkcs15_object_t *pin_obj,
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len)
{
return SC_ERROR_NOT_SUPPORTED;
}
/**
* Creates empty key file
**/
static int openpgp_create_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_object_t *obj)
{
/* For OpenPGP card, the number of keys is fixed,
* so this function does not really do anything.
* It just present here to avoid pkcs15init's default routine,
* which tries to do impossible things. */
LOG_FUNC_CALLED(p15card->card->ctx);
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
/**
* Stores an external (RSA) on the card.
* @param profile profile information for this card
* @param card sc_card_t object to use
* @param obj sc_pkcs15_object_t object with pkcs15 information
* @param key the private key
* @return SC_SUCCESS on success and an error code otherwise
**/
static int openpgp_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key)
{
sc_card_t *card = p15card->card;
sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data;
struct sc_pkcs15_prkey_rsa *rsa = &(key->u.rsa);
sc_cardctl_openpgp_keystore_info_t key_info;
int r;
LOG_FUNC_CALLED(card->ctx);
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "only RSA is currently supported");
return SC_ERROR_NOT_SUPPORTED;
}
memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keystore_info_t));
key_info.keytype = kinfo->id.value[0];
key_info.e = rsa->exponent.data;
key_info.e_len = rsa->exponent.len;
key_info.p = rsa->p.data;
key_info.p_len = rsa->p.len;
key_info.q = rsa->q.data;
key_info.q_len = rsa->q.len;
key_info.n = rsa->modulus.data;
key_info.n_len = rsa->modulus.len;
r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_STORE_KEY, &key_info);
LOG_FUNC_RETURN(card->ctx, r);
}
/**
* Generates a new (RSA) key pair using an existing key file.
* @param profile IN profile information for this card
* @param card IN sc_card_t object to use
* @param obj IN sc_pkcs15_object_t object with pkcs15 information
* @param pukkey OUT the newly created public key
* @return SC_SUCCESS on success and an error code otherwise
**/
static int openpgp_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey)
{
sc_card_t *card = p15card->card;
sc_context_t *ctx = card->ctx;
sc_cardctl_openpgp_keygen_info_t key_info;
sc_pkcs15_prkey_info_t *required = (sc_pkcs15_prkey_info_t *)obj->data;
sc_pkcs15_id_t *kid = &(required->id);
int r;
LOG_FUNC_CALLED(ctx);
memset(&key_info, 0, sizeof(key_info));
sc_log(ctx, "Key ID to be generated: %s", sc_dump_hex(kid->value, kid->len));
/* Accept KeyID = 45, which is default value set by pkcs15init */
if (kid->len == 1 && kid->value[0] == 0x45) {
/* Default key is authentication key. We choose this because the common use
* is to generate from PKCS#11 (Firefox/Thunderbird) */
sc_log(ctx, "Authentication key is to be generated.");
key_info.keytype = 3;
}
if (!key_info.keytype && (kid->len > 1 || kid->value[0] > 3)) {
sc_log(ctx, "Key ID must be 1, 2 or 3!");
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
}
if (!key_info.keytype)
key_info.keytype = kid->value[0];
/* Prepare buffer */
key_info.modulus_len = required->modulus_length;
key_info.modulus = calloc(required->modulus_length >> 3, 1);
if (key_info.modulus == NULL)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
/* The OpenPGP supports only 32-bit exponent. */
key_info.exponent_len = 32;
key_info.exponent = calloc(4, 1);
if (key_info.exponent == NULL)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info);
if (r < 0)
goto out;
sc_log(ctx, "Set output modulus info");
pubkey->u.rsa.modulus.len = key_info.modulus_len;
pubkey->u.rsa.modulus.data = calloc(key_info.modulus_len, 1);
if (pubkey->u.rsa.modulus.data == NULL)
goto out;
memcpy(pubkey->u.rsa.modulus.data, key_info.modulus, key_info.modulus_len);
sc_log(ctx, "Set output exponent info");
pubkey->u.rsa.exponent.len = key_info.exponent_len;
pubkey->u.rsa.exponent.data = calloc(key_info.exponent_len, 1);
if (pubkey->u.rsa.exponent.data == NULL)
goto out;
memcpy(pubkey->u.rsa.exponent.data, key_info.exponent, key_info.exponent_len);
out:
if (key_info.modulus)
free(key_info.modulus);
if (key_info.exponent)
free(key_info.exponent);
LOG_FUNC_RETURN(ctx, r);
}
static int openpgp_emu_update_any_df(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
unsigned operation, sc_pkcs15_object_t *obj)
{
LOG_FUNC_CALLED(p15card->card->ctx);
/* After storing object, pkcs15init will call this function to update DF.
* But OpenPGP has no other DF than OpenPGP-Application, so we do nothing. */
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
static int openpgp_emu_update_tokeninfo(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
sc_pkcs15_tokeninfo_t *tokeninfo)
{
LOG_FUNC_CALLED(p15card->card->ctx);
/* When unbinding pkcs15init, this function will be called.
* But for OpenPGP, token info does not need to change, we do nothing. */
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content,
struct sc_path *path)
{
sc_card_t *card = p15card->card;
sc_file_t *file;
sc_pkcs15_cert_info_t *cinfo;
sc_pkcs15_id_t *cid;
int r;
LOG_FUNC_CALLED(card->ctx);
switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
case SC_PKCS15_TYPE_PRKEY:
case SC_PKCS15_TYPE_PUBKEY:
/* For these two type, store_data just don't need to do anything.
* All have been done already before this function is called */
r = SC_SUCCESS;
break;
case SC_PKCS15_TYPE_CERT:
cinfo = (sc_pkcs15_cert_info_t *) obj->data;
cid = &(cinfo->id);
if (cid->len != 1) {
sc_log(card->ctx, "ID=%s is not valid.", sc_dump_hex(cid->value, cid->len));
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
/* OpenPGP card v.2 contains only 1 certificate */
if (cid->value[0] != 3) {
sc_log(card->ctx,
"This version does not support certificate ID = %d (only ID=3 is supported).",
cid->value[0]);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
/* Just update the certificate DO */
sc_format_path("7F21", path);
r = sc_select_file(card, path, &file);
LOG_TEST_RET(card->ctx, r, "Cannot select cert file");
r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
if (r >= 0 && content->len)
r = sc_update_binary(p15card->card, 0,
(const unsigned char *) content->value,
content->len, 0);
break;
default:
r = SC_ERROR_NOT_IMPLEMENTED;
}
LOG_FUNC_RETURN(card->ctx, r);
}
static struct sc_pkcs15init_operations sc_pkcs15init_openpgp_operations = {
openpgp_erase,
NULL, /* init_card */
openpgp_create_dir,
NULL, /* create_domain */
openpgp_select_pin_reference,
openpgp_create_pin,
NULL, /* select key reference */
openpgp_create_key,
openpgp_store_key,
openpgp_generate_key,
NULL, NULL, /* encode private/public key */
NULL, /* finalize_card */
NULL, /* delete_object */
NULL,
openpgp_emu_update_any_df,
openpgp_emu_update_tokeninfo,
NULL, /* emu_write_info */
openpgp_store_data, /* emu_store_data */
NULL /* sanity_check */
};
struct sc_pkcs15init_operations *sc_pkcs15init_get_openpgp_ops(void)
{
return &sc_pkcs15init_openpgp_operations;
}

View File

@ -13,7 +13,7 @@ lib_LTLIBRARIES = libsmm-local.la
libsmm_local_la_SOURCES = smm-local.c sm-module.h sm-common.c sm-global-platform.c sm-cwa14890.c \
sm-card-authentic.c sm-card-iasecc.c \
smm-local.exports
libsmm_local_la_LIBADD = ../libopensc/libopensc.la
libsmm_local_la_LIBADD = $(OPTIONAL_OPENSSL_LIBS) ../libopensc/libopensc.la
libsmm_local_la_LDFLAGS = -version-info @OPENSC_LT_CURRENT@:@OPENSC_LT_REVISION@:@OPENSC_LT_AGE@
# noinst_HEADERS = sm.h

View File

@ -48,25 +48,27 @@ static int
sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info,
unsigned char *idata, size_t idata_len)
{
struct sm_secure_channel *schannel = &sm_info->schannel;
struct sm_gp_keyset *keyset = &schannel->keyset.gp;
struct sm_gp_session *gp_session = &sm_info->session.gp;
struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset;
unsigned char master_key[16] = {
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
};
unsigned char *keys[3] = {
keyset->enc,keyset->mac,keyset->kek
gp_keyset->enc,
gp_keyset->mac,
gp_keyset->kek
};
unsigned char key_buff[16];
unsigned char *tmp;
unsigned char *tmp;
int rv = 0, ii, tmp_len;
if (keyset->kmc_len == 48) {
if (gp_keyset->kmc_len == 48) {
for (ii=0; ii<3; ii++)
memcpy(keys[ii], keyset->kmc + 16*ii, 16);
memcpy(keys[ii], gp_keyset->kmc + 16*ii, 16);
}
else if (keyset->kmc_len == 16 || keyset->kmc_len == 0) {
if (keyset->kmc_len == 16)
memcpy(master_key, keyset->kmc, 16);
else if (gp_keyset->kmc_len == 16 || gp_keyset->kmc_len == 0) {
if (gp_keyset->kmc_len == 16)
memcpy(master_key, gp_keyset->kmc, 16);
sc_log(ctx, "KMC: %s", sc_dump_hex(master_key, sizeof(master_key)));
for (ii=0; ii<3; ii++) {
key_buff[0] = key_buff[8] = 0;
@ -83,7 +85,7 @@ sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info,
rv = sm_encrypt_des_ecb3(master_key, key_buff, sizeof(key_buff), &tmp, &tmp_len);
LOG_TEST_RET(ctx, rv, "GP init session: cannot derivate key");
memcpy(keys[ii], tmp, sizeof(keyset->enc));
memcpy(keys[ii], tmp, sizeof(gp_keyset->enc));
free(tmp);
}
}
@ -95,20 +97,20 @@ sm_oberthur_diversify_keyset(struct sc_context *ctx, struct sm_info *sm_info,
char dump_buf[2048];
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL,
schannel->card_challenge, sizeof(schannel->card_challenge), dump_buf, sizeof(dump_buf));
gp_session->card_challenge, sizeof(gp_session->card_challenge), dump_buf, sizeof(dump_buf));
sc_log(ctx, "Card challenge: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL,
schannel->host_challenge, sizeof(schannel->host_challenge), dump_buf, sizeof(dump_buf));
gp_session->host_challenge, sizeof(gp_session->host_challenge), dump_buf, sizeof(dump_buf));
sc_log(ctx, "Host challenge: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, keyset->enc, sizeof(keyset->enc), dump_buf, sizeof(dump_buf));
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->enc, sizeof(gp_keyset->enc), dump_buf, sizeof(dump_buf));
sc_log(ctx, "ENC: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, keyset->mac, sizeof(keyset->mac), dump_buf, sizeof(dump_buf));
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->mac, sizeof(gp_keyset->mac), dump_buf, sizeof(dump_buf));
sc_log(ctx, "MAC: %s", dump_buf);
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, keyset->kek, sizeof(keyset->kek), dump_buf, sizeof(dump_buf));
sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, gp_keyset->kek, sizeof(gp_keyset->kek), dump_buf, sizeof(dump_buf));
sc_log(ctx, "KEK: %s", dump_buf);
}
@ -328,7 +330,7 @@ sm_authentic_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
rv = sm_authentic_get_apdu_release(ctx, sm_info, init_data, init_len, out, out_num);
LOG_TEST_RET(ctx, rv, "SM get APDUs: add 'release' failed");
sm_gp_close_session(ctx, &sm_info->schannel);
sm_gp_close_session(ctx, &sm_info->session.gp);
}
#endif
LOG_FUNC_RETURN(ctx, rv);

View File

@ -597,8 +597,8 @@ int
sm_iasecc_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
unsigned char *init_data, size_t init_len, struct sc_remote_data *rdata, int release_sm)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_keyset *keyset = &sm_info->schannel.keyset.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset;
int rv;
LOG_FUNC_CALLED(ctx);
@ -609,15 +609,15 @@ sm_iasecc_get_apdus(struct sc_context *ctx, struct sm_info *sm_info,
sc_log(ctx, "SM IAS/ECC get APDUs: rdata:%p", rdata);
sc_log(ctx, "SM IAS/ECC get APDUs: serial %s", sc_dump_hex(sm_info->serialnr.value, sm_info->serialnr.len));
rv = sm_cwa_decode_authentication_data(ctx, keyset, session_data, init_data);
rv = sm_cwa_decode_authentication_data(ctx, cwa_keyset, cwa_session, init_data);
LOG_TEST_RET(ctx, rv, "SM IAS/ECC get APDUs: decode authentication data error");
rv = sm_cwa_init_session_keys(ctx, session_data, sm_info->sm_params.cwa.crt_at.algo);
rv = sm_cwa_init_session_keys(ctx, cwa_session, cwa_session->params.crt_at.algo);
LOG_TEST_RET(ctx, rv, "SM IAS/ECC get APDUs: cannot get session keys");
sc_log(ctx, "SKENC %s", sc_dump_hex(session_data->session_enc, sizeof(session_data->session_enc)));
sc_log(ctx, "SKMAC %s", sc_dump_hex(session_data->session_mac, sizeof(session_data->session_mac)));
sc_log(ctx, "SSC %s", sc_dump_hex(session_data->ssc, sizeof(session_data->ssc)));
sc_log(ctx, "SKENC %s", sc_dump_hex(cwa_session->session_enc, sizeof(cwa_session->session_enc)));
sc_log(ctx, "SKMAC %s", sc_dump_hex(cwa_session->session_mac, sizeof(cwa_session->session_mac)));
sc_log(ctx, "SSC %s", sc_dump_hex(cwa_session->ssc, sizeof(cwa_session->ssc)));
switch (sm_info->cmd) {
case SM_CMD_FILE_READ:
@ -682,7 +682,7 @@ int
sm_iasecc_decode_card_data(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata,
unsigned char *out, size_t out_len)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_session *session_data = &sm_info->session.cwa;
struct sc_asn1_entry asn1_iasecc_sm_data_object[4];
struct sc_remote_apdu *rapdu = NULL;
int rv, offs = 0;

View File

@ -248,10 +248,10 @@ sm_cwa_incr_ssc(struct sm_cwa_session *session_data)
int
sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_keyset *keyset = &sm_info->schannel.keyset.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset;
struct sc_serial_number sn = sm_info->serialnr;
size_t icc_sn_len = sizeof(session_data->icc.sn);
size_t icc_sn_len = sizeof(cwa_session->icc.sn);
struct sc_remote_apdu *new_rapdu = NULL;
struct sc_apdu *apdu = NULL;
unsigned char buf[0x100], *encrypted;
@ -261,9 +261,9 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "SM IAS/ECC initialize: serial %s", sc_dump_hex(sm_info->serialnr.value, sm_info->serialnr.len));
sc_log(ctx, "SM IAS/ECC initialize: card challenge %s", sc_dump_hex(sm_info->schannel.card_challenge, 8));
sc_log(ctx, "SM IAS/ECC initialize: card challenge %s", sc_dump_hex(cwa_session->card_challenge, 8));
sc_log(ctx, "SM IAS/ECC initialize: current_df_path %s", sc_print_path(&sm_info->current_path_df));
sc_log(ctx, "SM IAS/ECC initialize: CRT_AT reference 0x%X", sm_info->sm_params.cwa.crt_at.refs[0]);
sc_log(ctx, "SM IAS/ECC initialize: CRT_AT reference 0x%X", cwa_session->params.crt_at.refs[0]);
if (!rdata || !rdata->alloc)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
@ -272,27 +272,27 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_TEST_RET(ctx, rv, "SM GP decode card answer: cannot allocate remote APDU");
apdu = &new_rapdu->apdu;
memcpy(&session_data->icc.rnd[0], sm_info->schannel.card_challenge, 8);
memcpy(&cwa_session->icc.rnd[0], cwa_session->card_challenge, 8);
if (sn.len > icc_sn_len)
memcpy(&session_data->icc.sn[0], &sn.value[sn.len - icc_sn_len], icc_sn_len);
memcpy(&cwa_session->icc.sn[0], &sn.value[sn.len - icc_sn_len], icc_sn_len);
else
memcpy(&session_data->icc.sn[icc_sn_len - sn.len], &sn.value[0], sn.len);
memcpy(&cwa_session->icc.sn[icc_sn_len - sn.len], &sn.value[0], sn.len);
if (sm_info->cmd == SM_CMD_EXTERNAL_AUTH) {
offs = sm_cwa_encode_external_auth_data(ctx, session_data, buf, sizeof(buf));
offs = sm_cwa_encode_external_auth_data(ctx, cwa_session, buf, sizeof(buf));
if (offs != 0x10)
LOG_FUNC_RETURN(ctx, offs);
}
else {
offs = sm_cwa_encode_mutual_auth_data(ctx, session_data, buf, sizeof(buf));
offs = sm_cwa_encode_mutual_auth_data(ctx, cwa_session, buf, sizeof(buf));
if (offs != 0x40)
LOG_FUNC_RETURN(ctx, offs);
}
sc_log(ctx, "S(%i) %s", offs, sc_dump_hex(buf, offs));
rv = sm_encrypt_des_cbc3(ctx, keyset->enc, buf, offs, &encrypted, &encrypted_len, 1);
rv = sm_encrypt_des_cbc3(ctx, cwa_keyset->enc, buf, offs, &encrypted, &encrypted_len, 1);
LOG_TEST_RET(ctx, rv, "_encrypt_des_cbc3() failed");
sc_log(ctx, "ENCed(%i) %s", encrypted_len, sc_dump_hex(encrypted, encrypted_len));
@ -300,7 +300,7 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
memcpy(buf, encrypted, encrypted_len);
offs = encrypted_len;
rv = sm_cwa_get_mac(ctx, keyset->mac, &icv, buf, offs, &cblock, 1);
rv = sm_cwa_get_mac(ctx, cwa_keyset->mac, &icv, buf, offs, &cblock, 1);
LOG_TEST_RET(ctx, rv, "sm_ecc_get_mac() failed");
sc_log(ctx, "MACed(%i) %s", sizeof(cblock), sc_dump_hex(cblock, sizeof(cblock)));
@ -323,7 +323,7 @@ sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
int
sm_cwa_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_apdu *rapdu)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_session *session_data = &sm_info->session.cwa;
struct sc_apdu *apdu = &rapdu->apdu;
unsigned char sbuf[0x400];
DES_cblock cblock, icv;

View File

@ -109,7 +109,7 @@ sm_gp_decode_card_answer(struct sc_context *ctx, struct sc_remote_data *rdata, u
sc_format_asn1_entry(asn1_authentic_card_response + 2, &card_data, &card_data_len, 0);
sc_format_asn1_entry(asn1_card_response + 0, asn1_authentic_card_response, NULL, 0);
rv = sc_asn1_decode(ctx, asn1_card_response, hex + hex_len - len_left, len_left, NULL, &len_left);
rv = sc_asn1_decode(ctx, asn1_card_response, hex + hex_len - len_left, len_left, NULL, &len_left);
if (rv) {
sc_log(ctx, "SM GP decode card answer: ASN.1 parse error: %s", sc_strerror(rv));
return rv;
@ -141,6 +141,8 @@ int
sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
struct sc_serial_number sn = sm_info->serialnr;
struct sm_gp_session *gp_session = &sm_info->session.gp;
struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset;
struct sc_remote_apdu *new_rapdu = NULL;
struct sc_apdu *apdu = NULL;
int rv;
@ -148,7 +150,7 @@ sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "SM GP initialize: serial:%s", sc_dump_hex(sn.value, sn.len));
sc_log(ctx, "SM GP initialize: current_df_path %s", sc_print_path(&sm_info->current_path_df));
sc_log(ctx, "SM GP initialize: KMC length %i", sm_info->schannel.keyset.gp.kmc_len);
sc_log(ctx, "SM GP initialize: KMC length %i", gp_keyset->kmc_len);
if (!rdata || !rdata->alloc)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
@ -157,7 +159,7 @@ sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
LOG_TEST_RET(ctx, rv, "SM GP decode card answer: cannot allocate remote APDU");
apdu = &new_rapdu->apdu;
rv = RAND_bytes(sm_info->schannel.host_challenge, SM_SMALL_CHALLENGE_LEN);
rv = RAND_bytes(gp_session->host_challenge, SM_SMALL_CHALLENGE_LEN);
if (!rv)
LOG_FUNC_RETURN(ctx, SC_ERROR_SM_RAND_FAILED);
@ -169,24 +171,24 @@ sm_gp_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_rem
apdu->lc = SM_SMALL_CHALLENGE_LEN;
apdu->le = 0x1C;
apdu->datalen = SM_SMALL_CHALLENGE_LEN;
memcpy(&new_rapdu->sbuf[0], sm_info->schannel.host_challenge, SM_SMALL_CHALLENGE_LEN);
memcpy(&new_rapdu->sbuf[0], gp_session->host_challenge, SM_SMALL_CHALLENGE_LEN);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
static unsigned char *
sc_gp_get_session_key(struct sc_context *ctx, struct sm_secure_channel *sc,
sc_gp_get_session_key(struct sc_context *ctx, struct sm_gp_session *gp_session,
unsigned char *key)
{
int out_len;
unsigned char *out;
unsigned char deriv[16];
memcpy(deriv, sc->card_challenge + 4, 4);
memcpy(deriv + 4, sc->host_challenge, 4);
memcpy(deriv + 8, sc->card_challenge, 4);
memcpy(deriv + 12, sc->host_challenge + 4, 4);
memcpy(deriv, gp_session->card_challenge + 4, 4);
memcpy(deriv + 4, gp_session->host_challenge, 4);
memcpy(deriv + 8, gp_session->card_challenge, 4);
memcpy(deriv + 12, gp_session->host_challenge + 4, 4);
if (sm_encrypt_des_ecb3(key, deriv, 16, &out, &out_len)) {
if (ctx)
@ -266,24 +268,27 @@ sm_gp_get_mac(unsigned char *key, DES_cblock *icv,
static int
sm_gp_parse_init_data(struct sc_context *ctx, struct sm_secure_channel *sc,
sm_gp_parse_init_data(struct sc_context *ctx, struct sm_gp_session *gp_session,
unsigned char *init_data, size_t init_len)
{
struct sm_gp_keyset *gp_keyset = &gp_session->gp_keyset;
if(init_len != 0x1C)
return SC_ERROR_INVALID_DATA;
sc->keyset.gp.version = *(init_data + 10);
sc->keyset.gp.index = *(init_data + 11);
memcpy(sc->card_challenge, init_data + 12, SM_SMALL_CHALLENGE_LEN);
gp_keyset->version = *(init_data + 10);
gp_keyset->index = *(init_data + 11);
memcpy(gp_session->card_challenge, init_data + 12, SM_SMALL_CHALLENGE_LEN);
return SC_SUCCESS;
}
static int
sm_gp_init_session(struct sc_context *ctx, struct sm_secure_channel *sc,
sm_gp_init_session(struct sc_context *ctx, struct sm_gp_session *gp_session,
unsigned char *adata, size_t adata_len)
{
struct sm_gp_keyset *gp_keyset = &gp_session->gp_keyset;
unsigned char cksum[8];
int rv;
@ -293,19 +298,19 @@ sm_gp_init_session(struct sc_context *ctx, struct sm_secure_channel *sc,
sc_log(ctx, "SM GP init session: auth.data %s", sc_dump_hex(adata, 8));
sc->session.gp.session_enc = sc_gp_get_session_key(ctx, sc, sc->keyset.gp.enc);
sc->session.gp.session_mac = sc_gp_get_session_key(ctx, sc, sc->keyset.gp.mac);
sc->session.gp.session_kek = sc_gp_get_session_key(ctx, sc, sc->keyset.gp.kek);
if (!sc->session.gp.session_enc || !sc->session.gp.session_mac || !sc->session.gp.session_kek)
gp_session->session_enc = sc_gp_get_session_key(ctx, gp_session, gp_keyset->enc);
gp_session->session_mac = sc_gp_get_session_key(ctx, gp_session, gp_keyset->mac);
gp_session->session_kek = sc_gp_get_session_key(ctx, gp_session, gp_keyset->kek);
if (!gp_session->session_enc || !gp_session->session_mac || !gp_session->session_kek)
LOG_TEST_RET(ctx, SC_ERROR_SM_NO_SESSION_KEYS, "SM GP init session: get session keys error");
memcpy(sc->session.gp.session_kek, sc->keyset.gp.kek, 16);
memcpy(gp_session->session_kek, gp_keyset->kek, 16);
sc_log(ctx, "SM GP init session: session ENC: %s", sc_dump_hex(sc->session.gp.session_enc, 16));
sc_log(ctx, "SM GP init session: session MAC: %s", sc_dump_hex(sc->session.gp.session_mac, 16));
sc_log(ctx, "SM GP init session: session KEK: %s", sc_dump_hex(sc->session.gp.session_kek, 16));
sc_log(ctx, "SM GP init session: session ENC: %s", sc_dump_hex(gp_session->session_enc, 16));
sc_log(ctx, "SM GP init session: session MAC: %s", sc_dump_hex(gp_session->session_mac, 16));
sc_log(ctx, "SM GP init session: session KEK: %s", sc_dump_hex(gp_session->session_kek, 16));
memset(cksum, 0, sizeof(cksum));
rv = sm_gp_get_cryptogram(sc->session.gp.session_enc, sc->host_challenge, sc->card_challenge, cksum, sizeof(cksum));
rv = sm_gp_get_cryptogram(gp_session->session_enc, gp_session->host_challenge, gp_session->card_challenge, cksum, sizeof(cksum));
LOG_TEST_RET(ctx, rv, "SM GP init session: cannot get cryptogram");
sc_log(ctx, "SM GP init session: cryptogram: %s", sc_dump_hex(cksum, 8));
@ -318,11 +323,11 @@ sm_gp_init_session(struct sc_context *ctx, struct sm_secure_channel *sc,
void
sm_gp_close_session(struct sc_context *ctx, struct sm_secure_channel *sc)
sm_gp_close_session(struct sc_context *ctx, struct sm_gp_session *gp_session)
{
free(sc->session.gp.session_enc);
free(sc->session.gp.session_mac);
free(sc->session.gp.session_kek);
free(gp_session->session_enc);
free(gp_session->session_mac);
free(gp_session->session_kek);
}
@ -336,7 +341,7 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
struct sc_remote_apdu *new_rapdu = NULL;
struct sc_apdu *apdu = NULL;
unsigned char host_cryptogram[8], raw_apdu[SC_MAX_APDU_BUFFER_SIZE];
struct sm_secure_channel *schannel = &sm_info->schannel;
struct sm_gp_session *gp_session = &sm_info->session.gp;
DES_cblock mac;
int rv, idx = 0, offs = 0;
@ -347,7 +352,7 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
if (init_len != 0x1C)
LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "SM GP authentication: invalid auth data length");
rv = sm_gp_parse_init_data(ctx, schannel, init_data, init_len);
rv = sm_gp_parse_init_data(ctx, gp_session, init_data, init_len);
LOG_TEST_RET(ctx, rv, "SM GP authentication: 'INIT DATA' parse error");
if (diversify_keyset) {
@ -355,10 +360,11 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
LOG_TEST_RET(ctx, rv, "SM GP authentication: keyset diversification error");
}
rv = sm_gp_init_session(ctx, schannel, init_data + 20, 8);
rv = sm_gp_init_session(ctx, gp_session, init_data + 20, 8);
LOG_TEST_RET(ctx, rv, "SM GP authentication: init session error");
rv = sm_gp_get_cryptogram(schannel->session.gp.session_enc, schannel->card_challenge, schannel->host_challenge,
rv = sm_gp_get_cryptogram(gp_session->session_enc,
gp_session->card_challenge, gp_session->host_challenge,
host_cryptogram, sizeof(host_cryptogram));
LOG_TEST_RET(ctx, rv, "SM GP authentication: get host cryptogram error");
@ -372,19 +378,19 @@ sm_gp_external_authentication(struct sc_context *ctx, struct sm_info *sm_info,
apdu->cse = SC_APDU_CASE_3_SHORT;
apdu->cla = raw_apdu[offs++] = 0x84;
apdu->ins = raw_apdu[offs++] = 0x82;
apdu->p1 = raw_apdu[offs++] = sm_info->sm_params.gp.level;
apdu->p1 = raw_apdu[offs++] = gp_session->params.level;
apdu->p2 = raw_apdu[offs++] = 0;
apdu->lc = raw_apdu[offs++] = 0x10;
apdu->datalen = 0x10;
memcpy(raw_apdu + offs, host_cryptogram, 8);
offs += 8;
rv = sm_gp_get_mac(schannel->session.gp.session_mac, &schannel->session.gp.mac_icv, raw_apdu, offs, &mac);
rv = sm_gp_get_mac(gp_session->session_mac, &gp_session->mac_icv, raw_apdu, offs, &mac);
LOG_TEST_RET(ctx, rv, "SM GP authentication: get MAC error");
memcpy(new_rapdu->sbuf, host_cryptogram, 8);
memcpy(new_rapdu->sbuf + 8, mac, 8);
memcpy(schannel->session.gp.mac_icv, mac, 8);
memcpy(gp_session->mac_icv, mac, 8);
LOG_FUNC_RETURN(ctx, 1);
}
@ -431,9 +437,9 @@ sm_gp_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info,
{
unsigned char buff[SC_MAX_APDU_BUFFER_SIZE + 24];
unsigned char *apdu_data = NULL;
unsigned gp_level = sm_info->sm_params.gp.level;
unsigned gp_index = sm_info->sm_params.gp.index;
struct sm_gp_session *gp_session = &sm_info->schannel.session.gp;
struct sm_gp_session *gp_session = &sm_info->session.gp;
unsigned gp_level = sm_info->session.gp.params.level;
unsigned gp_index = sm_info->session.gp.params.index;
DES_cblock mac;
unsigned char *encrypted = NULL;
size_t encrypted_len = 0;
@ -508,7 +514,7 @@ sm_gp_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info,
free(encrypted);
}
memcpy(sm_info->schannel.session.gp.mac_icv, mac, 8);
memcpy(sm_info->session.gp.mac_icv, mac, 8);
LOG_FUNC_RETURN(ctx, rv);
}

View File

@ -62,7 +62,7 @@ int sm_gp_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info,
char *init_data, struct sc_apdu *apdu);
int sm_gp_decode_card_answer(struct sc_context *ctx, struct sc_remote_data *rdata,
unsigned char *out, size_t out_len);
void sm_gp_close_session(struct sc_context *ctx, struct sm_secure_channel *sc);
void sm_gp_close_session(struct sc_context *ctx, struct sm_gp_session *gp_session);
/* CWA-14890 helper functions */

View File

@ -58,6 +58,8 @@ static int
sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
{
scconf_block *sm_conf_block = NULL, **blocks;
struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset;
const char *kmc = NULL;
unsigned char hex[48];
size_t hex_len = sizeof(hex);
@ -89,8 +91,8 @@ sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
if (hex_len != 16 && hex_len != 48 )
return SC_ERROR_INVALID_DATA;
memcpy(sm_info->schannel.keyset.gp.kmc, hex, hex_len);
sm_info->schannel.keyset.gp.kmc_len = hex_len;
memcpy(gp_keyset->kmc, hex, hex_len);
gp_keyset->kmc_len = hex_len;
return SC_SUCCESS;
}
@ -99,9 +101,10 @@ sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
static int
sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
{
struct sm_cwa_session *session_data = &sm_info->schannel.session.cwa;
struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset;
scconf_block *sm_conf_block = NULL, **blocks;
struct sc_crt *crt_at = &sm_info->sm_params.cwa.crt_at;
struct sc_crt *crt_at = &sm_info->session.cwa.params.crt_at;
const char *value = NULL;
char name[128];
unsigned char hex[48];
@ -134,7 +137,7 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
sc_log(ctx, "keyset::enc(%i) %s", strlen(value), value);
if (strlen(value) == 16) {
memcpy(sm_info->schannel.keyset.cwa.enc, value, 16);
memcpy(cwa_keyset->enc, value, 16);
}
else {
hex_len = sizeof(hex);
@ -148,9 +151,9 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
if (hex_len != 16)
return SC_ERROR_INVALID_DATA;
memcpy(sm_info->schannel.keyset.cwa.enc, hex, hex_len);
memcpy(cwa_keyset->enc, hex, hex_len);
}
sc_log(ctx, "%s %s", name, sc_dump_hex(sm_info->schannel.keyset.cwa.enc, 16));
sc_log(ctx, "%s %s", name, sc_dump_hex(cwa_keyset->enc, 16));
/* Keyset MAC */
if (sm_info->current_aid.len && (crt_at->refs[0] & IASECC_OBJECT_REF_LOCAL))
@ -166,7 +169,7 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
sc_log(ctx, "keyset::mac(%i) %s", strlen(value), value);
if (strlen(value) == 16) {
memcpy(sm_info->schannel.keyset.cwa.mac, value, 16);
memcpy(cwa_keyset->mac, value, 16);
}
else {
hex_len = sizeof(hex);
@ -180,15 +183,15 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
if (hex_len != 16)
return SC_ERROR_INVALID_DATA;
memcpy(sm_info->schannel.keyset.cwa.mac, hex, hex_len);
memcpy(cwa_keyset->mac, hex, hex_len);
}
sc_log(ctx, "%s %s", name, sc_dump_hex(sm_info->schannel.keyset.cwa.mac, 16));
sc_log(ctx, "%s %s", name, sc_dump_hex(cwa_keyset->mac, 16));
sm_info->schannel.keyset.cwa.sdo_reference = crt_at->refs[0];
cwa_keyset->sdo_reference = crt_at->refs[0];
/* IFD parameters */
memset(session_data, 0, sizeof(struct sm_cwa_session));
//memset(cwa_session, 0, sizeof(struct sm_cwa_session));
value = scconf_get_str(sm_conf_block, "ifd_serial", NULL);
if (!value)
return SC_ERROR_SM_IFD_DATA_MISSING;
@ -199,27 +202,27 @@ sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info)
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
}
if (hex_len != sizeof(session_data->ifd.sn)) {
if (hex_len != sizeof(cwa_session->ifd.sn)) {
sc_log(ctx, "SM get 'ifd_serial': invalid IFD serial length: %i", hex_len);
return SC_ERROR_UNKNOWN_DATA_RECEIVED;
}
memcpy(session_data->ifd.sn, hex, hex_len);
memcpy(cwa_session->ifd.sn, hex, hex_len);
rv = RAND_bytes(session_data->ifd.rnd, 8);
rv = RAND_bytes(cwa_session->ifd.rnd, 8);
if (!rv) {
sc_log(ctx, "Generate random error: %i", rv);
return SC_ERROR_SM_RAND_FAILED;
}
rv = RAND_bytes(session_data->ifd.k, 32);
rv = RAND_bytes(cwa_session->ifd.k, 32);
if (!rv) {
sc_log(ctx, "Generate random error: %i", rv);
return SC_ERROR_SM_RAND_FAILED;
}
sc_log(ctx, "IFD.Serial: %s", sc_dump_hex(session_data->ifd.sn, sizeof(session_data->ifd.sn)));
sc_log(ctx, "IFD.Rnd: %s", sc_dump_hex(session_data->ifd.rnd, sizeof(session_data->ifd.rnd)));
sc_log(ctx, "IFD.K: %s", sc_dump_hex(session_data->ifd.k, sizeof(session_data->ifd.k)));
sc_log(ctx, "IFD.Serial: %s", sc_dump_hex(cwa_session->ifd.sn, sizeof(cwa_session->ifd.sn)));
sc_log(ctx, "IFD.Rnd: %s", sc_dump_hex(cwa_session->ifd.rnd, sizeof(cwa_session->ifd.rnd)));
sc_log(ctx, "IFD.K: %s", sc_dump_hex(cwa_session->ifd.k, sizeof(cwa_session->ifd.k)));
return SC_SUCCESS;
}

View File

@ -147,7 +147,7 @@ static int list_sdos(char *sdo_tag)
if (!rv) {
printf("Found SE #%X\n", se.reference);
_iasecc_print_docp(&se.docp);
for(jj=0; jj<IASECC_SE_CRTS_MAX && se.crts[jj].tag; jj++)
for(jj=0; jj<SC_MAX_CRTS_IN_SE && se.crts[jj].tag; jj++)
_iasecc_print_crt(&se.crts[jj]);
}
}

View File

@ -31,10 +31,13 @@
#include "libopensc/opensc.h"
#include "libopensc/asn1.h"
#include "libopensc/cards.h"
#include "libopensc/cardctl.h"
#include "util.h"
#define OPT_RAW 256
#define OPT_PRETTY 257
#define OPT_VERIFY 258
#define OPT_PIN 259
/* define structures */
struct ef_name_map {
@ -64,6 +67,14 @@ static int verbose = 0;
static int opt_userinfo = 0;
static int opt_cardinfo = 0;
static char *exec_program = NULL;
static int opt_genkey = 0;
static int opt_keylen = 0;
static u8 key_id = 0;
static unsigned int key_len = 2048;
static int opt_verify = 0;
static char *verifytype = NULL;
static int opt_pin = 0;
static char *pin = NULL;
static const char *app_name = "openpgp-tool";
@ -75,9 +86,13 @@ static const struct option options[] = {
{ "pretty", no_argument, NULL, OPT_PRETTY },
{ "card-info", no_argument, NULL, 'C' },
{ "user-info", no_argument, NULL, 'U' },
{ "gen-key", required_argument, NULL, 'G' },
{ "key-length",required_argument, NULL, 'L' },
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ "verify", required_argument, NULL, OPT_VERIFY },
{ "pin", required_argument, NULL, OPT_PIN },
{ NULL, 0, NULL, 0 }
};
@ -89,9 +104,13 @@ static const char *option_help[] = {
"Print values in pretty format",
/* C */ NULL,
/* U */ "Show card holder information",
/* G */ "Generate key",
/* L */ "Key length (default 2048)",
/* h */ "Print this help message",
/* v */ "Verbose operation. Use several times to enable debug output.",
/* V */ "Show version number"
/* V */ "Show version number",
"Verify PIN (CHV1, CHV2, CHV3...)",
"PIN string"
};
static const struct ef_name_map openpgp_data[] = {
@ -208,7 +227,7 @@ static int decode_options(int argc, char **argv)
{
int c;
while ((c = getopt_long(argc, argv,"r:x:CUhwvV", options, (int *) 0)) != EOF) {
while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvV", options, (int *) 0)) != EOF) {
switch (c) {
case 'r':
opt_reader = optarg;
@ -224,6 +243,19 @@ static int decode_options(int argc, char **argv)
case OPT_PRETTY:
opt_raw = 0;
break;
case OPT_VERIFY:
opt_verify++;
if (verifytype)
free(verifytype);
verifytype = strdup(optarg);
actions++;
break;
case OPT_PIN:
opt_pin++;
if (pin)
free(pin);
pin = strdup(optarg);
break;
case 'C':
opt_cardinfo++;
actions++;;
@ -232,6 +264,16 @@ static int decode_options(int argc, char **argv)
opt_userinfo++;
actions++;;
break;
case 'G':
opt_genkey++;
key_id = optarg[0] - '0';
actions++;
break;
case 'L':
opt_keylen++;
key_len = atoi(optarg);
actions++;
break;
case 'h':
util_print_usage_and_die(app_name, options, option_help, NULL);
break;
@ -340,6 +382,66 @@ static void bintohex(char *buf, int len)
}
}
int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len)
{
int r;
sc_cardctl_openpgp_keygen_info_t key_info;
u8 fingerprints[60];
sc_path_t path;
sc_file_t *file;
if (key_id < 1 || key_id > 3) {
printf("Unknown key ID %d.\n", key_id);
return 1;
}
memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keygen_info_t));
key_info.keytype = key_id;
key_info.modulus_len = key_len;
key_info.modulus = malloc(key_len/8);
r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info);
free(key_info.modulus);
if (r < 0) {
printf("Failed to generate key. Error %s.\n", sc_strerror(r));
return 1;
}
sc_format_path("006E007300C5", &path);
r = sc_select_file(card, &path, &file);
r = sc_read_binary(card, 0, fingerprints, 60, 0);
if (r < 0) {
printf("Failed to retrieve fingerprints. Error %s.\n", sc_strerror(r));
return 1;
}
printf("Fingerprint:\n%s\n", (char *)sc_dump_hex(fingerprints + 20*(key_id - 1), 20));
return 0;
}
int do_verify(sc_card_t *card, u8 *type, u8* pin)
{
struct sc_pin_cmd_data data;
int tries_left;
int r;
if (!type || !pin)
return SC_ERROR_INVALID_ARGUMENTS;
if (strncasecmp("CHV", type, 3) != 0) {
printf("Invalid PIN type. Please use CHV1, CHV2 or CHV3.\n");
return SC_ERROR_INVALID_ARGUMENTS;
}
if (type[3] < '1' || type[3] > '3' || type[4] != '\0') {
printf("Invalid PIN reference. Please use CHV1, CHV2 or CHV3.\n");
return SC_ERROR_INVALID_PIN_REFERENCE;
}
memset(&data, 0, sizeof(struct sc_pin_cmd_data));
data.cmd = SC_PIN_CMD_VERIFY;
data.pin_type = SC_AC_CHV;
data.pin_reference = type[3] - '0';
data.pin1.data = pin;
data.pin1.len = strlen(pin);
r = sc_pin_cmd(card, &data, &tries_left);
return r;
}
int main(int argc, char **argv)
{
@ -396,6 +498,13 @@ int main(int argc, char **argv)
if (opt_userinfo)
exit_status |= do_userinfo(card);
if (opt_verify && opt_pin) {
exit_status |= do_verify(card, verifytype, pin);
}
if (opt_genkey)
exit_status |= do_genkey(card, key_id, key_len);
if (exec_program) {
char *const largv[] = {exec_program, NULL};
sc_unlock(card);

View File

@ -390,6 +390,15 @@ static int send_apdu(void)
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
printf("Sending: ");
for (r = 0; r < len0; r++)
printf("%02X ", buf[r]);
printf("\n");
r = sc_transmit_apdu(card, &apdu);
if (r) {
fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r));
return 1;
}
printf("Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2,
apdu.resplen ? ":" : "");
if (apdu.resplen)

View File

@ -270,6 +270,7 @@ enum {
ACTION_ASSERT_PRISTINE,
ACTION_ERASE,
ACTION_INIT,
ACTION_DELETE_OBJECTS,
ACTION_STORE_PIN,
ACTION_GENERATE_KEY,
ACTION_STORE_PRIVKEY,
@ -278,7 +279,6 @@ enum {
ACTION_UPDATE_CERT,
ACTION_STORE_DATA,
ACTION_FINALIZE_CARD,
ACTION_DELETE_OBJECTS,
ACTION_CHANGE_ATTRIBUTES,
ACTION_SANITY_CHECK,
ACTION_UPDATE_LAST_UPDATE,
@ -1184,7 +1184,7 @@ static int
do_store_data_object(struct sc_profile *profile)
{
struct sc_pkcs15init_dataargs args;
u8 *data;
unsigned char *data = NULL;
size_t datalen;
int r=0;
@ -1205,10 +1205,11 @@ do_store_data_object(struct sc_profile *profile)
/* der_encoded contains the plain data, nothing DER encoded */
args.der_encoded.value = data;
args.der_encoded.len = datalen;
r = sc_pkcs15init_store_data_object(p15card, profile,
&args, NULL);
r = sc_pkcs15init_store_data_object(p15card, profile, &args, NULL);
}
if (data)
free(data);
return r;
}
@ -2129,18 +2130,21 @@ do_read_certificate(const char *name, const char *format, X509 **out)
return 0;
}
static int determine_filesize(const char *filename)
static size_t determine_filesize(const char *filename)
{
FILE *fp;
size_t size;
long ll;
if ((fp = fopen(filename,"rb")) == NULL)
util_fatal("Unable to open %s: %m", filename);
if ((fp = fopen(filename,"rb")) == NULL) {
util_fatal("Unable to open %s: %m", filename);
}
fseek(fp,0L,SEEK_END);
size = ftell(fp);
ll = ftell(fp);
if (ll == -1l)
util_fatal("fseek/ftell error");
fclose(fp);
return size;
return (size_t)ll;
}
static int

View File

@ -811,10 +811,14 @@ static int read_ssh_key(void)
}
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
if (outf != stdout)
fclose(outf);
fprintf(stderr, "Public key with ID '%s' not found.\n", opt_pubkey);
return 2;
}
if (r < 0) {
if (outf != stdout)
fclose(outf);
fprintf(stderr, "Public key enumeration failed: %s\n", sc_strerror(r));
return 1;
}