Add support for a new cryptoflex profile in which the SO (CHV1) is in charge of the pkcs15 DF
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1185 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
c85913c5c7
commit
2871cd8269
|
@ -20,7 +20,7 @@ libpkcs15init_la_SOURCES = \
|
||||||
include_HEADERS = pkcs15-init.h
|
include_HEADERS = pkcs15-init.h
|
||||||
noinst_HEADERS = profile.h
|
noinst_HEADERS = profile.h
|
||||||
pkgdata_DATA = etoken.profile \
|
pkgdata_DATA = etoken.profile \
|
||||||
flex.profile \
|
flex.profile flex_so.profile \
|
||||||
gpk.profile \
|
gpk.profile \
|
||||||
miocos.profile \
|
miocos.profile \
|
||||||
pkcs15.profile
|
pkcs15.profile
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
#
|
||||||
|
# PKCS15 r/w profile for Cryptoflex cards
|
||||||
|
#
|
||||||
|
cardinfo {
|
||||||
|
max-pin-length = 8;
|
||||||
|
pin-encoding = ascii-numeric;
|
||||||
|
pin-pad-char = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define reasonable limits for PINs and PUK
|
||||||
|
# Note that we do not set a file path or reference
|
||||||
|
# here; that is done dynamically.
|
||||||
|
PIN user-pin {
|
||||||
|
attempts = 3;
|
||||||
|
flags = 0x32; # local, initialized, needs-padding
|
||||||
|
}
|
||||||
|
PIN user-puk {
|
||||||
|
attempts = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Additional filesystem info.
|
||||||
|
# This is added to the file system info specified in the
|
||||||
|
# main profile.
|
||||||
|
filesystem {
|
||||||
|
DF MF {
|
||||||
|
ACL = *=AUT1;
|
||||||
|
|
||||||
|
DF PKCS15-AppDF {
|
||||||
|
ACL = DELETE=$SOPIN, CREATE=NONE, FILES=NONE;
|
||||||
|
size = 7500; # enough for 2 2048 bit keys, and 1 cert each
|
||||||
|
EF sopinfile {
|
||||||
|
file-id = 0100;
|
||||||
|
size = 23;
|
||||||
|
ACL = *=NEVER, UPDATE=AUT1;
|
||||||
|
}
|
||||||
|
EF extkey {
|
||||||
|
file-id = 0011;
|
||||||
|
size = 15;
|
||||||
|
ACL = *=NEVER, UPDATE=AUT1;
|
||||||
|
}
|
||||||
|
DF keydir-1 {
|
||||||
|
ACL = *=$SOPIN, FILES=NONE;
|
||||||
|
file-id = 4B01;
|
||||||
|
size = 1370; # Sufficient for a 2048-bit key
|
||||||
|
EF pinfile-2 {
|
||||||
|
file-id = 0000;
|
||||||
|
size = 23;
|
||||||
|
ACL = *=NEVER, UPDATE=$SOPIN;
|
||||||
|
}
|
||||||
|
EF template-private-key-1 {
|
||||||
|
file-id = 0012;
|
||||||
|
ACL = *=NEVER, CRYPTO=CHV1, UPDATE=$SOPIN;
|
||||||
|
}
|
||||||
|
EF template-extractable-key-1 {
|
||||||
|
file-id = 7000;
|
||||||
|
ACL = *=NEVER, READ=$PIN, UPDATE=$SOPIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DF keydir-2 {
|
||||||
|
ACL = *=$SOPIN, FILES=NONE;
|
||||||
|
file-id = 4B02;
|
||||||
|
size = 1370; # Sufficient for a 2048-bit key
|
||||||
|
EF pinfile-3 {
|
||||||
|
file-id = 0000;
|
||||||
|
size = 23;
|
||||||
|
ACL = *=NEVER, UPDATE=$SOPIN;
|
||||||
|
}
|
||||||
|
EF template-private-key-2 {
|
||||||
|
file-id = 0012;
|
||||||
|
ACL = *=NEVER, CRYPTO=CHV1, UPDATE=$SOPIN;
|
||||||
|
}
|
||||||
|
EF template-extractable-key-2 {
|
||||||
|
file-id = 7000;
|
||||||
|
ACL = *=NEVER, READ=$PIN, UPDATE=$SOPIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EF template-public-key-1 {
|
||||||
|
file-id = 5201;
|
||||||
|
ACL = *=$SOPIN, READ=NONE;
|
||||||
|
}
|
||||||
|
EF template-public-key-2 {
|
||||||
|
file-id = 5202;
|
||||||
|
ACL = *=$SOPIN, READ=NONE;
|
||||||
|
}
|
||||||
|
EF template-certificate-1 {
|
||||||
|
file-id = 5501;
|
||||||
|
ACL = *=$SOPIN, READ=NONE;
|
||||||
|
}
|
||||||
|
EF template-certificate-2 {
|
||||||
|
file-id = 5502;
|
||||||
|
ACL = *=$SOPIN, READ=NONE;
|
||||||
|
}
|
||||||
|
EF PKCS15-AODF {
|
||||||
|
size = 160; # 1 SOPIN + 2 user pins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define an SO pin
|
||||||
|
# This PIN is not used yet.
|
||||||
|
PIN so-pin {
|
||||||
|
file = sopinfile;
|
||||||
|
reference = 0;
|
||||||
|
}
|
|
@ -29,13 +29,69 @@
|
||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
|
|
||||||
static void invert_buf(u8 *dest, const u8 *src, size_t c);
|
static void invert_buf(u8 *dest, const u8 *src, size_t c);
|
||||||
|
static int cflex_update_pin(struct sc_profile *profile, struct sc_card *card,
|
||||||
|
sc_file_t *file,
|
||||||
|
const u8 *pin, size_t pin_len, int pin_tries,
|
||||||
|
const u8 *puk, size_t puk_len, int puk_tries);
|
||||||
|
|
||||||
|
static int cflex_delete_file(struct sc_card *card, struct sc_profile *profile,
|
||||||
|
struct sc_file *df)
|
||||||
|
{
|
||||||
|
struct sc_path path;
|
||||||
|
struct sc_file *parent;
|
||||||
|
int r = 0;
|
||||||
|
/* Select the parent DF */
|
||||||
|
path = df->path;
|
||||||
|
path.len -= 2;
|
||||||
|
r = sc_select_file(card, &path, &parent);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_DELETE);
|
||||||
|
sc_file_free(parent);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* cryptoflex has no ERASE AC */
|
||||||
|
memset(&path, 0, sizeof(path));
|
||||||
|
path.type = SC_PATH_TYPE_FILE_ID;
|
||||||
|
path.value[0] = df->id >> 8;
|
||||||
|
path.value[1] = df->id & 0xFF;
|
||||||
|
path.len = 2;
|
||||||
|
|
||||||
|
card->ctx->log_errors = 0;
|
||||||
|
r = sc_delete_file(card, &path);
|
||||||
|
card->ctx->log_errors = 1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Erase the card via rm -rf
|
* Erase the card via rm
|
||||||
*/
|
*/
|
||||||
static int cflex_erase_card(struct sc_profile *profile, struct sc_card *card)
|
static int cflex_erase_card(struct sc_profile *profile, struct sc_card *card)
|
||||||
{
|
{
|
||||||
return sc_pkcs15init_erase_card_recursively(card, profile, -1);
|
struct sc_file *df = profile->df_info->file, *dir;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Delete EF(DIR). This may not be very nice
|
||||||
|
* against other applications that use this file, but
|
||||||
|
* extremely useful for testing :)
|
||||||
|
* Note we need to delete if before the DF because we create
|
||||||
|
* it *after* the DF.
|
||||||
|
* */
|
||||||
|
if (sc_profile_get_file(profile, "DIR", &dir) >= 0) {
|
||||||
|
r = cflex_delete_file(card, profile, dir);
|
||||||
|
sc_file_free(dir);
|
||||||
|
if (r < 0 && r != SC_ERROR_FILE_NOT_FOUND)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
r=cflex_delete_file(card, profile, df);
|
||||||
|
/* Unfrob the SO pin reference, and return */
|
||||||
|
out: sc_profile_forget_secrets(profile, SC_AC_CHV, -1);
|
||||||
|
sc_free_apps(card);
|
||||||
|
if (r == SC_ERROR_FILE_NOT_FOUND)
|
||||||
|
r=0;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -44,17 +100,64 @@ static int cflex_erase_card(struct sc_profile *profile, struct sc_card *card)
|
||||||
static int cflex_init_app(struct sc_profile *profile, struct sc_card *card,
|
static int cflex_init_app(struct sc_profile *profile, struct sc_card *card,
|
||||||
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len)
|
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len)
|
||||||
{
|
{
|
||||||
if (pin && pin_len) {
|
sc_file_t *pinfile, *keyfile;
|
||||||
profile->cbs->error("Cryptoflex card driver doesn't "
|
struct sc_pkcs15_pin_info sopin,tmpinfo;
|
||||||
"support SO PIN\n");
|
int pin_tries, puk_tries;
|
||||||
return SC_ERROR_NOT_SUPPORTED;
|
int r;
|
||||||
}
|
char extkey_contents[15];
|
||||||
|
|
||||||
|
if (pin && pin_len) {
|
||||||
|
|
||||||
|
if (sc_profile_get_file(profile, "sopinfile", &pinfile) < 0) {
|
||||||
|
profile->cbs->error("Profile doesn't define \"sopinfile\"");
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
if (sc_profile_get_file(profile, "extkey", &keyfile) < 0) {
|
||||||
|
profile->cbs->error("Profile doesn't define \"extkey\"");
|
||||||
|
return SC_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
if (pin_len > 8)
|
||||||
|
pin_len = 8;
|
||||||
|
if (puk_len > 8)
|
||||||
|
puk_len = 8;
|
||||||
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin);
|
||||||
|
sopin.reference=0x2; /* XXX where did this come from? */
|
||||||
|
memcpy(&sopin.path, &profile->df_info->file->path, sizeof(sc_path_t));
|
||||||
|
sc_profile_set_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin);
|
||||||
|
}
|
||||||
|
/* Create the application DF */
|
||||||
|
if (sc_pkcs15init_create_file(profile, card, profile->df_info->file))
|
||||||
|
return 1;
|
||||||
|
|
||||||
/* Create the application DF */
|
if (pin && pin_len) {
|
||||||
if (sc_pkcs15init_create_file(profile, card, profile->df_info->file))
|
pin_tries = sopin.tries_left;
|
||||||
return 1;
|
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &tmpinfo);
|
||||||
|
puk_tries = tmpinfo.tries_left;
|
||||||
return 0;
|
r = cflex_update_pin(profile, card, pinfile, pin, pin_len, pin_tries,
|
||||||
|
puk, puk_len, puk_tries);
|
||||||
|
if (r) {
|
||||||
|
profile->cbs->error("update_pin failed for SOPIN\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
memset(&extkey_contents, 0, sizeof(extkey_contents));
|
||||||
|
extkey_contents[0]=0; /* RFU */
|
||||||
|
extkey_contents[1]=1; /* skip AUT0 */
|
||||||
|
extkey_contents[2]=8; /* AUT1 length; single DES */
|
||||||
|
extkey_contents[3]=0; /* single DES */
|
||||||
|
extkey_contents[12]=1; /* # allowed verification attempts */
|
||||||
|
extkey_contents[13]=255; /* block key */
|
||||||
|
extkey_contents[14]=0; /* no more keys */
|
||||||
|
r=sc_pkcs15init_update_file(profile, card, keyfile,
|
||||||
|
extkey_contents, 15);
|
||||||
|
if (r != 15) {
|
||||||
|
profile->cbs->error("update_file failed for extkey file\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue