For the Oberthur IdOne AuthentIC card: make possible

to initialize the card with the PIN unblocking style
of the Oberthur's native middleware.


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3805 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
viktor.tarasov 2009-11-06 10:00:31 +00:00
parent 275c7f930e
commit 51e15b8fb4
5 changed files with 99 additions and 44 deletions

View File

@ -409,6 +409,9 @@ auth_process_fci(struct sc_card *card, struct sc_file *file,
add_acl_entry(card, file, SC_AC_OP_CRYPTO, attr[1]); add_acl_entry(card, file, SC_AC_OP_CRYPTO, attr[1]);
add_acl_entry(card, file, SC_AC_OP_LIST_FILES, attr[2]); add_acl_entry(card, file, SC_AC_OP_LIST_FILES, attr[2]);
add_acl_entry(card, file, SC_AC_OP_DELETE, attr[3]); add_acl_entry(card, file, SC_AC_OP_DELETE, attr[3]);
add_acl_entry(card, file, SC_AC_OP_PIN_DEFINE, attr[4]);
add_acl_entry(card, file, SC_AC_OP_PIN_CHANGE, attr[5]);
add_acl_entry(card, file, SC_AC_OP_PIN_RESET, attr[6]);
} }
else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { /* EF */ else if (file->type == SC_FILE_TYPE_INTERNAL_EF) { /* EF */
switch (file->ef_structure) { switch (file->ef_structure) {
@ -833,9 +836,9 @@ encode_file_structure_V5(sc_card_t *card, const sc_file_t *file,
ops[1] = SC_AC_OP_CRYPTO; ops[1] = SC_AC_OP_CRYPTO;
ops[2] = SC_AC_OP_LIST_FILES; ops[2] = SC_AC_OP_LIST_FILES;
ops[3] = SC_AC_OP_DELETE; ops[3] = SC_AC_OP_DELETE;
ops[4] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_SET_REFERENCE */ ops[4] = SC_AC_OP_PIN_DEFINE;
ops[5] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_CHANGE_REFERENCE */ ops[5] = SC_AC_OP_PIN_CHANGE;
ops[6] = SC_AC_OP_LIST_FILES; /* SC_AC_OP_RESET_COUNTER */ ops[6] = SC_AC_OP_PIN_RESET;
} }
else if (file->type == SC_FILE_TYPE_WORKING_EF) { else if (file->type == SC_FILE_TYPE_WORKING_EF) {
if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {

View File

@ -111,6 +111,12 @@ extern "C" {
#define SC_AC_OP_WRITE 3 #define SC_AC_OP_WRITE 3
/* rehab and invalidate are the same as in DF case */ /* rehab and invalidate are the same as in DF case */
/* Special 'Oberthur IdOne AuthentIC's case:
* re-use the existing DF ACLs that are not relevant to this card. */
#define SC_AC_OP_PIN_DEFINE SC_AC_OP_LOCK
#define SC_AC_OP_PIN_CHANGE SC_AC_OP_REHABILITATE
#define SC_AC_OP_PIN_RESET SC_AC_OP_DELETE_SELF
/* various maximum values */ /* various maximum values */
#define SC_MAX_READER_DRIVERS 6 #define SC_MAX_READER_DRIVERS 6
#define SC_MAX_READERS 16 #define SC_MAX_READERS 16

View File

@ -53,8 +53,9 @@ filesystem {
DF OberthurAWP-AppDF { DF OberthurAWP-AppDF {
ACL = *=NONE; ACL = *=NONE;
#ACL = CREATE=CHV4, CRYPTO=NEVER, PIN_SET=CHV4, PIN_RESET=PRO0x78; #ACL = CREATE=CHV4, CRYPTO=NEVER, PIN_SET=CHV4, PIN_RESET=PRO0x78;
ACL = CREATE=CHV4, CRYPTO=NEVER; ACL = CREATE=CHV4, CRYPTO=NEVER, PIN-DEFINE=CHV4, PIN-RESET=CHV4;
#ACL = CREATE=CHV4, CRYPTO=NEVER;
file-id = 5011; file-id = 5011;
size = 40; size = 40;

View File

@ -46,8 +46,8 @@
#define COSM_TITLE "OberthurAWP" #define COSM_TITLE "OberthurAWP"
#define TLV_TYPE_V 0 #define TLV_TYPE_V 0
#define TLV_TYPE_LV 1 #define TLV_TYPE_LV 1
#define TLV_TYPE_TLV 2 #define TLV_TYPE_TLV 2
/* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */ /* Should be greater then SC_PKCS15_TYPE_CLASS_MASK */
@ -58,17 +58,49 @@
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card, static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
struct sc_pkcs15_pin_info *info, const u8 *pin, size_t pin_len, struct sc_pkcs15_pin_info *info, const unsigned char *pin, size_t pin_len,
const u8 *puk, size_t puk_len); const unsigned char *puk, size_t puk_len);
int cosm_delete_file(sc_card_t *card, struct sc_profile *profile, int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
sc_file_t *df); sc_file_t *df);
int cosm_delete_file(sc_card_t *card, struct sc_profile *profile, static int
sc_file_t *df) cosm_update_pukfile (struct sc_card *card, struct sc_profile *profile,
unsigned char *data, size_t data_len)
{ {
sc_path_t path; struct sc_pkcs15_pin_info profile_puk;
sc_file_t *parent; struct sc_file *file = NULL;
int rv, sz, flags = 0;
unsigned char buffer[16];
SC_FUNC_CALLED(card->ctx, 1);
if (!data || data_len > 16)
return SC_ERROR_INVALID_ARGUMENTS;
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &profile_puk);
if (profile_puk.max_length > 16)
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Invalid PUK settings");
if (sc_profile_get_file(profile, COSM_TITLE"-puk-file", &file))
SC_TEST_RET(card->ctx, SC_ERROR_INCONSISTENT_PROFILE, "Cannot find PUKFILE");
memset(buffer, profile_puk.pad_char, 16);
memcpy(buffer, data, data_len);
rv = sc_pkcs15init_update_file(profile, card, file, buffer, sizeof(buffer));
if (rv > 0)
rv = 0;
SC_FUNC_RETURN(card->ctx, 1, rv);
}
int
cosm_delete_file(struct sc_card *card, struct sc_profile *profile,
struct sc_file *df)
{
struct sc_path path;
struct sc_file *parent;
int rv = 0; int rv = 0;
SC_FUNC_CALLED(card->ctx, 1); SC_FUNC_CALLED(card->ctx, 1);
@ -104,7 +136,8 @@ int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
/* /*
* Erase the card * Erase the card
*/ */
static int cosm_erase_card(struct sc_profile *profile, sc_card_t *card) static int
cosm_erase_card(struct sc_profile *profile, sc_card_t *card)
{ {
sc_file_t *df = profile->df_info->file, *dir; sc_file_t *df = profile->df_info->file, *dir;
int rv; int rv;
@ -168,8 +201,8 @@ done:
static int static int
cosm_init_app(struct sc_profile *profile, sc_card_t *card, cosm_init_app(struct sc_profile *profile, sc_card_t *card,
struct sc_pkcs15_pin_info *pinfo, struct sc_pkcs15_pin_info *pinfo,
const u8 *pin, size_t pin_len, const unsigned char *pin, size_t pin_len,
const u8 *puk, size_t puk_len) const unsigned char *puk, size_t puk_len)
{ {
int rv; int rv;
size_t ii; size_t ii;
@ -214,16 +247,18 @@ cosm_init_app(struct sc_profile *profile, sc_card_t *card,
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
} }
static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *card,
static int
cosm_create_reference_data(struct sc_profile *profile, sc_card_t *card,
struct sc_pkcs15_pin_info *pinfo, struct sc_pkcs15_pin_info *pinfo,
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len ) const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len )
{ {
int rv; struct sc_pkcs15_pin_info profile_pin;
int puk_buff_len = 0; struct sc_pkcs15_pin_info profile_puk;
unsigned char *puk_buff = NULL;
sc_pkcs15_pin_info_t profile_pin;
sc_pkcs15_pin_info_t profile_puk;
struct sc_cardctl_oberthur_createpin_info args; struct sc_cardctl_oberthur_createpin_info args;
unsigned char *puk_buff = NULL;
int rv, puk_buff_len = 0;
SC_FUNC_CALLED(card->ctx, 1); SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "pin lens %i/%i\n", pin_len, puk_len); sc_debug(card->ctx, "pin lens %i/%i\n", pin_len, puk_len);
@ -279,7 +314,13 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car
args.puk_len = puk_buff_len; args.puk_len = puk_buff_len;
args.puk_tries = profile_puk.tries_left; args.puk_tries = profile_puk.tries_left;
rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args); rv = sc_card_ctl(card, SC_CARDCTL_OBERTHUR_CREATE_PIN, &args);
SC_TEST_RET(card->ctx, rv, "'CREATE_PIN' card specific command failed");
if (puk_buff_len == 16) {
rv = cosm_update_pukfile (card, profile, puk_buff, puk_buff_len);
SC_TEST_RET(card->ctx, rv, "Failed to update pukfile");
}
if (puk_buff) if (puk_buff)
free(puk_buff); free(puk_buff);
@ -290,9 +331,10 @@ static int cosm_create_reference_data(struct sc_profile *profile, sc_card_t *car
/* /*
* Update PIN * Update PIN
*/ */
static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card, static int
struct sc_pkcs15_pin_info *pinfo, const u8 *pin, size_t pin_len, cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
const u8 *puk, size_t puk_len ) struct sc_pkcs15_pin_info *pinfo, const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len )
{ {
int rv; int rv;
int tries_left = -1; int tries_left = -1;
@ -329,7 +371,7 @@ cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
SC_FUNC_CALLED(card->ctx, 1); SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "ref %i; flags %X\n", pin_info->reference, pin_info->flags); sc_debug(card->ctx, "ref %i; flags %X\n", pin_info->reference, pin_info->flags);
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) { if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
sc_error(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF"); sc_error(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF");
return SC_ERROR_INCONSISTENT_PROFILE; return SC_ERROR_INCONSISTENT_PROFILE;
} }
@ -339,12 +381,12 @@ cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
if (!pin_info->reference) { if (!pin_info->reference) {
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
pin_info->reference = 4; pin_info->reference = 4;
else else
pin_info->reference = 1; pin_info->reference = 1;
} }
if (pin_info->reference < 0 || pin_info->reference > 4) if (pin_info->reference < 0 || pin_info->reference > 4)
return SC_ERROR_INVALID_PIN_REFERENCE; return SC_ERROR_INVALID_PIN_REFERENCE;
SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
@ -355,7 +397,7 @@ cosm_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
*/ */
static int static int
cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df, cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
sc_pkcs15_object_t *pin_obj, struct sc_pkcs15_object *pin_obj,
const unsigned char *pin, size_t pin_len, const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len) const unsigned char *puk, size_t puk_len)
{ {
@ -365,11 +407,11 @@ cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
SC_FUNC_CALLED(card->ctx, 1); SC_FUNC_CALLED(card->ctx, 1);
sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags); sc_debug(card->ctx, "ref %i; flags %X\n", pinfo->reference, pinfo->flags);
if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) { if (sc_profile_get_file(profile, COSM_TITLE "-AppDF", &pinfile) < 0) {
sc_error(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF"); sc_error(card->ctx, "Profile doesn't define \"%s\"", COSM_TITLE "-AppDF");
return SC_ERROR_INCONSISTENT_PROFILE; return SC_ERROR_INCONSISTENT_PROFILE;
} }
pinfo->path = pinfile->path; pinfo->path = pinfile->path;
sc_file_free(pinfile); sc_file_free(pinfile);
@ -387,13 +429,12 @@ cosm_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
} }
if (pin && pin_len) { if (pin && pin_len) {
rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len); rv = cosm_update_pin(profile, card, pinfo, pin, pin_len, puk, puk_len);
} }
else { else {
sc_debug(card->ctx, "User PIN not updated"); sc_debug(card->ctx, "User PIN not updated");
} }
sc_debug(card->ctx, "return %i\n", rv);
sc_keycache_set_pin_name(&pinfo->path, pinfo->reference, type); sc_keycache_set_pin_name(&pinfo->path, pinfo->reference, type);
pinfo->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL; pinfo->flags &= ~SC_PKCS15_PIN_FLAG_LOCAL;
@ -465,7 +506,7 @@ cosm_new_file(struct sc_profile *profile, sc_card_t *card,
desc, _template); desc, _template);
return SC_ERROR_NOT_SUPPORTED; return SC_ERROR_NOT_SUPPORTED;
} }
file->id |= (num & 0xFF); file->id |= (num & 0xFF);
file->path.value[file->path.len-1] |= (num & 0xFF); file->path.value[file->path.len-1] |= (num & 0xFF);
if (file->type == SC_FILE_TYPE_INTERNAL_EF) { if (file->type == SC_FILE_TYPE_INTERNAL_EF) {
@ -512,8 +553,8 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
path = prkf->path; path = prkf->path;
path.len -= 2; path.len -= 2;
rv = sc_select_file(card, &path, &tmpf); rv = sc_select_file(card, &path, &tmpf);
SC_TEST_RET(card->ctx, rv, "Generate RSA: no private object DF"); SC_TEST_RET(card->ctx, rv, "Generate RSA: no private object DF");
rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO); rv = sc_pkcs15init_authenticate(profile, card, tmpf, SC_AC_OP_CRYPTO);
sc_debug(card->ctx, "rv %i\n",rv); sc_debug(card->ctx, "rv %i\n",rv);
@ -573,7 +614,7 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
/* extract public key */ /* extract public key */
pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->algorithm = SC_ALGORITHM_RSA;
pubkey->u.rsa.modulus.len = keybits / 8; pubkey->u.rsa.modulus.len = keybits / 8;
pubkey->u.rsa.modulus.data = (u8 *) malloc(keybits / 8); pubkey->u.rsa.modulus.data = (unsigned char *) malloc(keybits / 8);
if (!pubkey->u.rsa.modulus.data) { if (!pubkey->u.rsa.modulus.data) {
rv = SC_ERROR_MEMORY_FAILURE; rv = SC_ERROR_MEMORY_FAILURE;
goto failed; goto failed;
@ -581,7 +622,7 @@ cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
/* FIXME and if the exponent length is not 3? */ /* FIXME and if the exponent length is not 3? */
pubkey->u.rsa.exponent.len = 3; pubkey->u.rsa.exponent.len = 3;
pubkey->u.rsa.exponent.data = (u8 *) malloc(3); pubkey->u.rsa.exponent.data = (unsigned char *) malloc(3);
if (!pubkey->u.rsa.exponent.data) { if (!pubkey->u.rsa.exponent.data) {
rv = SC_ERROR_MEMORY_FAILURE; rv = SC_ERROR_MEMORY_FAILURE;
goto failed; goto failed;
@ -654,7 +695,8 @@ cosm_new_key(struct sc_profile *profile, sc_card_t *card,
rv = sc_pkcs15init_authenticate(profile, card, prvfile, SC_AC_OP_UPDATE); rv = sc_pkcs15init_authenticate(profile, card, prvfile, SC_AC_OP_UPDATE);
SC_TEST_RET(card->ctx, rv, "Update RSA: no authorisation"); SC_TEST_RET(card->ctx, rv, "Update RSA: no authorisation");
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
/* Mozilla style ID */
if (!info->id.len) { if (!info->id.len) {
SHA1(rsa->modulus.data, rsa->modulus.len, info->id.value); SHA1(rsa->modulus.data, rsa->modulus.len, info->id.value);
info->id.len = SHA_DIGEST_LENGTH; info->id.len = SHA_DIGEST_LENGTH;

View File

@ -104,7 +104,10 @@ static struct map fileOpNames[] = {
{ "UPDATE", SC_AC_OP_UPDATE }, { "UPDATE", SC_AC_OP_UPDATE },
{ "WRITE", SC_AC_OP_WRITE }, { "WRITE", SC_AC_OP_WRITE },
{ "ERASE", SC_AC_OP_ERASE }, { "ERASE", SC_AC_OP_ERASE },
{ "CRYPTO", SC_AC_OP_CRYPTO }, { "CRYPTO", SC_AC_OP_CRYPTO },
{ "PIN-DEFINE", SC_AC_OP_PIN_DEFINE },
{ "PIN-CHANGE", SC_AC_OP_PIN_CHANGE },
{ "PIN-RESET", SC_AC_OP_PIN_RESET },
{ NULL, 0 } { NULL, 0 }
}; };
static struct map fileTypeNames[] = { static struct map fileTypeNames[] = {