From 2871cd82692294113422f1872f01efcc96e3743f Mon Sep 17 00:00:00 2001 From: sth Date: Sat, 7 Jun 2003 07:17:26 +0000 Subject: [PATCH] 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 --- src/pkcs15init/Makefile.am | 2 +- src/pkcs15init/flex_so.profile | 105 +++++++++++++++++++++++++++ src/pkcs15init/pkcs15-cflex.c | 127 +++++++++++++++++++++++++++++---- 3 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 src/pkcs15init/flex_so.profile diff --git a/src/pkcs15init/Makefile.am b/src/pkcs15init/Makefile.am index 32f9aec0..73e7ebd4 100644 --- a/src/pkcs15init/Makefile.am +++ b/src/pkcs15init/Makefile.am @@ -20,7 +20,7 @@ libpkcs15init_la_SOURCES = \ include_HEADERS = pkcs15-init.h noinst_HEADERS = profile.h pkgdata_DATA = etoken.profile \ - flex.profile \ + flex.profile flex_so.profile \ gpk.profile \ miocos.profile \ pkcs15.profile diff --git a/src/pkcs15init/flex_so.profile b/src/pkcs15init/flex_so.profile new file mode 100644 index 00000000..172bc895 --- /dev/null +++ b/src/pkcs15init/flex_so.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; +} diff --git a/src/pkcs15init/pkcs15-cflex.c b/src/pkcs15init/pkcs15-cflex.c index 6d16a263..17281ed4 100644 --- a/src/pkcs15init/pkcs15-cflex.c +++ b/src/pkcs15init/pkcs15-cflex.c @@ -29,13 +29,69 @@ #include "profile.h" 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) { - 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, const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len) { - if (pin && pin_len) { - profile->cbs->error("Cryptoflex card driver doesn't " - "support SO PIN\n"); - return SC_ERROR_NOT_SUPPORTED; - } + sc_file_t *pinfile, *keyfile; + struct sc_pkcs15_pin_info sopin,tmpinfo; + int pin_tries, puk_tries; + 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 (sc_pkcs15init_create_file(profile, card, profile->df_info->file)) - return 1; - - return 0; + if (pin && pin_len) { + pin_tries = sopin.tries_left; + sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &tmpinfo); + puk_tries = tmpinfo.tries_left; + 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; } /*