- pkcs15 rewrite

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1508 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2003-10-13 16:13:12 +00:00
parent 3d283fd925
commit 23c1e81512
17 changed files with 3361 additions and 1453 deletions

View File

@ -22,11 +22,11 @@ EXTRA_DIST = $(PROFILES) Makefile.mak
lib_LTLIBRARIES = libpkcs15init.la
libpkcs15init_la_SOURCES = \
pkcs15-lib.c profile.c \
pkcs15-lib.c profile.c keycache.c \
pkcs15-gpk.c pkcs15-miocos.c pkcs15-cflex.c \
pkcs15-etoken.c
libpkcs15init_la_LDFLAGS = -version-info @OPENSC_LT_CURRENT@:@OPENSC_LT_REVISION@:@OPENSC_LT_AGE@
include_HEADERS = pkcs15-init.h
noinst_HEADERS = profile.h
noinst_HEADERS = profile.h keycache.h
pkgdata_DATA = $(PROFILES)

View File

@ -5,7 +5,7 @@ TARGET = pkcs15init.lib
HEADERS = pkcs15-init.h
HEADERSDIR = $(TOPDIR)\src\include\opensc
OBJECTS = profile.obj pkcs15-lib.obj \
OBJECTS = profile.obj pkcs15-lib.obj keycache.obj \
pkcs15-miocos.obj pkcs15-gpk.obj pkcs15-cflex.obj \
pkcs15-etoken.obj

View File

@ -8,8 +8,14 @@ cardinfo {
}
# Define reasonable limits for PINs and PUK
# Note that we do not set a file path or reference
# here; that is done dynamically.
# We set the reference for SO pin+puk here, because
# those are hard-coded (if a PUK us assigned).
PIN so-pin {
reference = 0;
}
PIN so-puk {
reference = 1;
}
PIN user-pin {
attempts = 3;
}
@ -31,24 +37,66 @@ filesystem {
size = 256;
}
EF template-private-key {
type = internal-ef;
file-id = 4B01; # This is the base FileID
size = 266; # 266 is enough for 1024-bit keys
ACL = *=NEVER, UPDATE=$PIN, ERASE=$PIN;
}
EF template-public-key {
file-id = 5501;
ACL = *=NEVER, READ=NONE, UPDATE=$PIN, ERASE=$PIN;
# 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 = FFFF;
}
EF public-key {
file-id = 3003;
structure = transparent;
ACL = *=NEVER,
READ=NONE,
UPDATE=$PIN,
ERASE=$PIN;
}
# Certificate template
EF certificate {
file-id = 3004;
structure = transparent;
ACL = *=NEVER,
READ=NONE,
UPDATE=$PIN,
ERASE=$PIN;
}
# Extractable private keys are stored in transparent EFs.
# Encryption of the content is performed by libopensc.
EF extractable-key {
file-id = 3001;
structure = transparent;
ACL = *=NEVER,
READ=$PIN,
UPDATE=$PIN,
ERASE=$PIN;
}
# data objects are stored in transparent EFs.
EF data {
file-id = 3002;
structure = transparent;
ACL = *=NEVER,
READ=NONE,
UPDATE=$PIN,
WRITE=$PIN;
}
}
EF template-certificate {
file-id = 4301;
ACL = *=NEVER, READ=NONE, UPDATE=$PIN, ERASE=$PIN;
}
EF template-extractable-key {
file-id = 7000;
ACL = *=NEVER, READ=$PIN, UPDATE=$PIN, ERASE=$PIN;
}
# EF template-private-key {
# type = internal-ef;
# file-id = 4B01; # This is the base FileID
# size = 266; # 266 is enough for 1024-bit keys
# ACL = *=NEVER, UPDATE=$PIN, ERASE=$PIN;
# }
# This is needed when generating a key on-card.
EF tempfile {
file-id = 7EAD;
structure = linear-variable-tlv;
@ -58,10 +106,3 @@ filesystem {
}
}
}
# Define an SO pin
# This PIN is not used yet.
#PIN sopin {
# file = sopinfile;
# reference = 0;
#}

View File

@ -1,18 +1,24 @@
#
# PKCS15 r/w profile for Cryptoflex cards
# General purpose PKCS15 profile for Cryptoflex cards
#
cardinfo {
max-pin-length = 8;
pin-encoding = ascii-numeric;
pin-pad-char = 0x00;
pin-domains = yes;
# This profile does not PIN-protect certificates
# stored on the card. If you enable this, you MUST
# adjust the sizes of the pin-domain and key-dir DFs
# accordingly.
protect-certificates = no;
}
# Define reasonable limits for PINs and PUK
# Note that we do not set a file path or reference
# here; that is done dynamically.
# The user pin must always be CHV1, otherwise things
# won't work (crypto operations are protected by CHV1)
PIN user-pin {
attempts = 3;
flags = 0x32; # local, initialized, needs-padding
}
PIN user-puk {
attempts = 10;
@ -22,70 +28,80 @@ PIN user-puk {
# This is added to the file system info specified in the
# main profile.
filesystem {
# Define default ACLs and file ids for CHV1/CHV2
EF CHV1 {
file-id = 0000;
ACL = *=NEVER, UPDATE=CHV1;
}
EF CHV2 {
file-id = 0100;
ACL = *=NEVER, UPDATE=CHV2;
}
DF MF {
ACL = *=AUT1;
# The DELETE=NONE ACLs will go away once the code
# works. It's here to make sure I can erase the card
# even if I mess up big time.
DF PKCS15-AppDF {
ACL = *=AUT1, FILES=NONE;
DF keydir-1 {
ACL = *=AUT1, FILES=NONE;
file-id = 4B01;
size = 1370; # Sufficient for a 2048-bit key
EF pinfile-1 {
file-id = 0000;
size = 23;
ACL = *=NEVER, UPDATE=AUT1;
}
EF template-private-key-1 {
file-id = 0012;
ACL = *=NEVER, CRYPTO=$PIN, UPDATE=AUT1;
ACL = *=$SOPIN, FILES=NONE, DELETE=NONE;
size = 7500;
# This "pin-domain" DF is a template that is
# instantiated for each PIN created on the card.
#
# 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. That is, PIN 01 will reside
# in 4b01, PIN 02 will reside in 4b02, etc.
template pin-domain {
DF pin-dir {
ACL = *=$SOPIN, FILES=NONE, DELETE=NONE;
file-id = 4B00;
# The minimum size for a 2048 bit key is 1396
size = 1396;
}
EF template-extractable-key-1 {
file-id = 7000;
ACL = *=NEVER, READ=CHV1, UPDATE=AUT1;
}
}
DF keydir-2 {
ACL = *=AUT1, FILES=NONE;
file-id = 4B02;
size = 1370; # Sufficient for a 2048-bit key
EF pinfile-2 {
file-id = 0000;
size = 23;
ACL = *=NEVER, UPDATE=AUT1;
}
EF template-private-key-2 {
file-id = 0012;
ACL = *=NEVER, CRYPTO=CHV1, UPDATE=AUT1;
}
# For PIN-protected files, instantiate this template
# below the pin directory.
# For unprotected objects, install within the application DF.
#
# 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 {
# In order to support more than one key per PIN,
# each key must be within its own subdirectory.
DF key-directory {
ACL = *=$PIN, FILES=NONE;
file-id = 3000;
size = 1332;
EF private-key {
file-id = 0012;
ACL = *=NEVER, CRYPTO=$PIN, UPDATE=$PIN;
}
EF internal-pubkey-file {
file-id = 1012;
ACL = *=$PIN, READ=NONE;
}
}
EF template-extractable-key-2 {
file-id = 7000;
ACL = *=NEVER, READ=$PIN, UPDATE=AUT1;
}
}
EF template-public-key-1 {
file-id = 5201;
ACL = *=AUT1, READ=NONE;
}
EF template-public-key-2 {
file-id = 5202;
ACL = *=AUT1, READ=NONE;
}
EF template-certificate-1 {
file-id = 5501;
ACL = *=AUT1, READ=NONE;
}
EF template-certificate-2 {
file-id = 5502;
ACL = *=AUT1, READ=NONE;
}
EF extractable-key {
file-id = 4300;
ACL = *=NEVER, READ=$PIN, UPDATE=$PIN;
}
EF public-key {
file-id = 4400;
ACL = *=$PIN, READ=NONE;
}
EF certificate {
file-id = 4500;
ACL = *=$PIN, READ=NONE;
}
}
}
}
}
# Define an SO pin
# This PIN is not used yet.
#PIN sopin {
# file = sopinfile;
# reference = 0;
#}

View File

@ -7,12 +7,6 @@ cardinfo {
pin-pad-char = 0x00;
}
# Define reference for SO PIN
PIN so-pin {
file = pinfile;
reference = 0x08;
}
# Additional filesystem info.
# This is added to the file system info specified in the
# main profile.
@ -37,53 +31,60 @@ filesystem {
ACL = *=NEVER;
}
# Private key files.
# GPK private key files will never let you read the private key
# part, so it's okay to set READ=NONE. What's more, we may need
# read access so we're able to check the key size/type.
EF template-private-key {
file-id = 0006; # This is the base FileID
structure = 0x2C; # GPK specific
ACL = *=NEVER,
READ=NONE,
CRYPTO=$PIN,
UPDATE=$PIN,
WRITE=$PIN;
}
# 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 {
# Private key files.
# GPK private key files will never let you read the private key
# part, so it's okay to set READ=NONE. What's more, we may need
# read access so we're able to check the key size/type.
EF private-key {
file-id = 3000; # This is the base FileID
structure = 0x2C; # GPK specific
ACL = *=NEVER,
READ=NONE,
CRYPTO=$PIN,
UPDATE=$PIN,
WRITE=$PIN;
}
# Extractable private keys are stored in transparent EFs.
# Encryption of the content is performed by libopensc.
EF template-extractable-key {
file-id = 7000;
structure = transparent;
ACL = *=NEVER,
# Extractable private keys are stored in transparent EFs.
# Encryption of the content is performed by libopensc.
EF extractable-key {
file-id = 3001;
structure = transparent;
ACL = *=NEVER,
READ=$PIN,
UPDATE=$PIN,
WRITE=$PIN;
}
}
# data objects are stored in transparent EFs.
EF template-data {
file-id = 5000;
structure = transparent;
ACL = *=NEVER,
# data objects are stored in transparent EFs.
EF data {
file-id = 3002;
structure = transparent;
ACL = *=NEVER,
READ=NONE,
UPDATE=$PIN,
WRITE=$PIN;
}
}
EF template-public-key {
file-id = 8000;
structure = transparent;
ACL = *=NONE;
}
EF public-key {
file-id = 3003;
structure = transparent;
ACL = *=NONE;
}
# Certificate template
EF template-certificate {
file-id = 9000;
structure = transparent;
ACL = *=NONE;
}
# Certificate template
EF certificate {
file-id = 3004;
structure = transparent;
ACL = *=NONE;
}
}
}
}
}

387
src/pkcs15init/keycache.c Normal file
View File

@ -0,0 +1,387 @@
/*
* Cache authentication info
*
* Copyright (C) 2003, Olaf Kirch <okir@lst.de>
*
* 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
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <assert.h>
#include <opensc/pkcs15.h>
#include "profile.h"
#include "pkcs15-init.h"
#include <opensc/cardctl.h>
#ifdef _WIN32
#include <windows.h>
#endif
#undef KEYCACHE_DEBUG
#define MAX_SECRET 32 /* sufficient for 128bit symmetric keys */
struct secret {
struct secret * next;
sc_path_t path;
int type, ref, named_pin;
size_t len;
unsigned char value[MAX_SECRET];
};
static struct secret * secret_cache = NULL;
static struct secret * named_pin[SC_PKCS15INIT_NPINS];
#ifdef KEYCACHE_DEBUG
static void sc_keycache_dump(void);
#endif
/*
* Check if a keycache entry matches the given type, reference
* and path.
*/
static int
__match_entry(struct secret *s, int type, int ref, const sc_path_t *path,
int match_prefix)
{
if ((type != -1 && s->type != type)
|| (ref != -1 && s->ref != ref))
return 0;
/* Compare the two paths */
if (match_prefix) {
/* Prefix match - the path argument given by
* the caller should be a prefix of the keycache
* entry.
*/
/* If the path is a wildcard, it's a match */
if (path == NULL)
return 1;
if (s->path.len > path->len)
return 0;
} else {
/* Exact match - path names must patch exactly.
* A NULL path argument is an empty path */
if (path == 0)
return (s->path.len == 0);
if (s->path.len != path->len)
return 0;
}
if (memcmp(s->path.value, path->value, s->path.len))
return 0;
return 1;
}
/*
* Find the secret, given a path name, type and reference.
* If none found, search for it in parent directories.
*/
static struct secret *
find_entry(const sc_path_t *path, int type, int ref, int match_prefix)
{
struct secret *s;
if (type == SC_AC_SYMBOLIC) {
if (0 <= ref && ref < SC_PKCS15INIT_NPINS
&& (s = named_pin[ref]) != NULL
&& __match_entry(s, SC_AC_CHV, -1, path, match_prefix))
return s;
return NULL;
}
for (s = secret_cache; s; s = s->next) {
if (__match_entry(s, type, ref, path, match_prefix))
break;
}
return s;
}
/*
* Find a key with matching type/reference. If a path is
* given, find the entry with the longest matching prefix.
*/
static struct secret *
search_key(const sc_path_t *path, int type, int ref)
{
struct secret *best = NULL, *s;
if (type == SC_AC_SYMBOLIC) {
if (0 <= ref && ref < SC_PKCS15INIT_NPINS
&& (s = named_pin[ref]) != NULL
&& __match_entry(s, type, -1, path, 1))
return s;
return NULL;
}
for (s = secret_cache; s; s = s->next) {
if (s->len != 0
&& __match_entry(s, type, ref, path, 1)) {
/* Ignore if path shorter than the longest
* matched prefix.
*/
if (path == NULL || best == NULL
|| best->path.len < path->len)
best = s;
}
}
return best;
}
/*
* Store a secret in the cache
*/
struct secret *
new_entry(const sc_path_t *path, int type, int ref)
{
struct secret *s;
s = (struct secret *) calloc(1, sizeof(*s));
s->next = secret_cache;
secret_cache = s;
if (path)
s->path = *path;
if (type == SC_AC_SYMBOLIC) {
s->type = SC_AC_CHV;
s->ref = -1;
s->named_pin = ref;
} else {
s->type = type;
s->ref = ref;
s->named_pin = -1;
}
return s;
}
/*
* Cache the given key
*/
int
sc_keycache_put_key(const sc_path_t *path, int type, int ref,
const unsigned char *secret, size_t len)
{
struct secret *s;
if (len > MAX_SECRET)
return SC_ERROR_BUFFER_TOO_SMALL;
if (!(s = find_entry(path, type, ref, 0)))
s = new_entry(path, type, ref);
memset(s->value, 0, sizeof(s->value));
memcpy(s->value, secret, len);
s->len = len;
#ifdef KEYCACHE_DEBUG
sc_keycache_dump();
#endif
return 0;
}
int
sc_keycache_put_pin(const sc_path_t *path, int ref, const char *pin)
{
return sc_keycache_put_key(path, SC_AC_CHV, ref, pin,
pin? strlen(pin) : 0);
}
/*
* Get a key/pin from the cache
*/
int
sc_keycache_get_key(const sc_path_t *path, int type, int ref,
unsigned char *key, size_t size)
{
struct secret *s;
if (!(s = search_key(path, type, ref)))
return SC_ERROR_OBJECT_NOT_FOUND;
if (s->len > size)
return SC_ERROR_BUFFER_TOO_SMALL;
memcpy(key, s->value, s->len);
return s->len;
}
const char *
sc_keycache_get_pin(const sc_path_t *path, int ref)
{
struct secret *s;
if (!(s = search_key(path, SC_AC_CHV, ref)))
return NULL;
return s->len? s->value : NULL;
}
/*
* Define a symbolic name for a PIN. This is used to define
* what $PIN and $SOPIN mean in a given context.
*/
int
sc_keycache_set_pin_name(const sc_path_t *path, int ref, int name)
{
struct secret *s, *old;
if (name < 0 || name >= SC_PKCS15INIT_NPINS)
return SC_ERROR_INVALID_ARGUMENTS;
/* If we had previously marked a PIN with this name,
* unlink it */
if ((old = named_pin[name]) != NULL) {
named_pin[name] = NULL;
old->named_pin = -1;
}
if (ref >= 0) {
/* Create the named PIN if it doesn't exist */
if (!(s = find_entry(path, SC_AC_CHV, ref, 0)))
s = new_entry(path, SC_AC_CHV, ref);
/* Set the pin name */
s->named_pin = name;
/* If the old SOPIN was just the name entry,
* copy over the name to the new entry */
if (old && old->ref == -1 && s->len == 0) {
memcpy(s->value, old->value, old->len);
s->len = old->len;
}
named_pin[name] = s;
}
#ifdef KEYCACHE_DEBUG
sc_keycache_dump();
#endif
return 0;
}
/*
* Get the symbolic name of a PIN, if any
*/
int
sc_keycache_get_pin_name(const sc_path_t *path, int ref)
{
struct secret *s;
#ifdef KEYCACHE_DEBUG
printf("sc_keycache_get_pin_name(%s, %d)\n",
path? sc_print_path(path) : "any", ref);
#endif
if (!(s = find_entry(path, SC_AC_CHV, ref, 1)))
return -1;
return s->named_pin;
}
/*
* Get path and reference of symbolic PIN
*/
int
sc_keycache_find_named_pin(const sc_path_t *path, int name)
{
struct secret *s;
if (name < 0 || name >= SC_PKCS15INIT_NPINS
|| (s = named_pin[name]) == NULL
|| !__match_entry(s, SC_AC_CHV, -1, path, 1))
return -1;
return s->ref;
}
/*
* Zap one or more keys from the cache
*/
void
sc_keycache_forget_key(const sc_path_t *path, int type, int ref)
{
struct secret *s, **prev;
prev = &secret_cache;
while ((s = *prev) != NULL) {
if (__match_entry(s, type, ref, path, 1)) {
*prev = s->next;
memset(s, 0, sizeof(*s));
free(s);
} else {
prev = &s->next;
}
}
#ifdef KEYCACHE_DEBUG
sc_keycache_dump();
#endif
}
/*
* Dump the keycache
*/
#ifdef KEYCACHE_DEBUG
void
sc_keycache_dump(void)
{
struct secret *s;
int j;
printf("== Keycache ==\n");
for (s = secret_cache; s; s = s->next) {
char buf[32];
switch (s->type) {
case SC_AC_CHV: printf("CHV"); break;
case SC_AC_AUT: printf("AUT"); break;
case SC_AC_PRO: printf("PRO"); break;
default: printf("%d/", s->type);
}
printf("%d %-16s\t", s->ref, sc_print_path(&s->path));
sc_bin_to_hex(s->value, s->len, buf, sizeof(buf), ':');
printf("key=%s", buf);
switch (s->named_pin) {
case SC_PKCS15INIT_SO_PIN:
printf(", SO PIN"); break;
case SC_PKCS15INIT_SO_PUK:
printf(", SO PUK"); break;
case SC_PKCS15INIT_USER_PIN:
printf(", USER PIN"); break;
case SC_PKCS15INIT_USER_PUK:
printf(", USER PUK"); break;
}
if (s->named_pin >= 0
&& named_pin[s->named_pin] != s)
printf(" [PTR MISMATCH!]");
printf("\n");
}
for (j = 0; j < SC_PKCS15INIT_NPINS; j++) {
if ((s = named_pin[j]) == NULL)
continue;
if (s->named_pin != j)
printf(" named_pin[%d] MISMATCH: name=%d\n",
j, s->named_pin);
}
}
#endif

34
src/pkcs15init/keycache.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Cache authentication info
*
* Copyright (C) 2003, Olaf Kirch <okir@lst.de>
*
* 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
*/
#ifndef _PKCS15INIT_KEYCACHE_H
#define _PKCS15INIT_KEYCACHE_H
extern int sc_keycache_put_key(const sc_path_t *, int, int,
const unsigned char *, size_t);
extern int sc_keycache_put_pin(const sc_path_t *, int, const char *);
extern int sc_keycache_set_pin_name(const sc_path_t *, int, int);
extern int sc_keycache_get_pin_name(const sc_path_t *, int);
extern int sc_keycache_find_named_pin(const sc_path_t *, int);
extern int sc_keycache_get_key(const sc_path_t *, int, int, unsigned char *, size_t);
extern const char *sc_keycache_get_pin(const sc_path_t *, int);
extern void sc_keycache_forget_key(const sc_path_t *, int, int);
#endif /* _PKCS15INIT_KEYCACHE_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* eToken PRO specific operation for PKCS15 initialization
* CardOS specific operation for PKCS15 initialization
*
* Copyright (C) 2002 Olaf Kirch <okir@lst.de>
*
@ -54,9 +54,19 @@ struct rsakey {
/*
* Local functions
*/
static int etoken_store_pin(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_pin_info_t *pin_info, int puk_id,
const u8 *pin, size_t pin_len);
static int etoken_create_sec_env(sc_profile_t *, sc_card_t *,
unsigned int, unsigned int);
static int etoken_new_file(struct sc_profile *, struct sc_card *,
unsigned int, unsigned int,
struct sc_file **);
static int etoken_put_key(struct sc_profile *, struct sc_card *,
int, unsigned int, struct sc_pkcs15_prkey_rsa *);
static int etoken_key_algorithm(unsigned int, int *);
static int etoken_extract_pubkey(sc_card_t *, int,
u8, sc_pkcs15_bignum_t *);
static void error(struct sc_profile *, const char *, ...);
/* Object IDs for PIN objects.
@ -123,20 +133,273 @@ etoken_erase(struct sc_profile *profile, struct sc_card *card)
}
/*
* Initialize pin file
* Create the Application DF
*/
static int
etoken_store_pin(struct sc_profile *profile, struct sc_card *card,
int pin_type, unsigned int pin_id, unsigned int puk_id,
etoken_create_dir(sc_profile_t *profile, sc_card_t *card, sc_file_t *df)
{
int r;
/* Create the application DF */
if ((r = sc_pkcs15init_create_file(profile, card, df)) < 0)
return r;
if ((r = sc_select_file(card, &df->path, NULL)) < 0)
return r;
/* Create a default security environment for this DF.
* This SE autometically becomes the current SE when the
* DF is selected. */
if ((r = etoken_create_sec_env(profile, card, 0x01, 0x00)) < 0)
return r;
return 0;
}
/*
* Caller passes in a suggested PIN reference.
* See if it's good, and if it isn't, propose something better
*/
static int
etoken_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_pin_info_t *pin_info)
{
int preferred, current;
if ((current = pin_info->reference) < 0)
current = 1;
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
preferred = 1;
} else {
preferred = current;
/* PINs are even numbered, PUKs are odd */
if (!(preferred & 1))
preferred++;
if (preferred >= 126)
return SC_ERROR_TOO_MANY_OBJECTS;
}
if (current > preferred)
return SC_ERROR_TOO_MANY_OBJECTS;
pin_info->reference = preferred;
return 0;
}
/*
* Store a PIN
*/
static int
etoken_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
sc_pkcs15_pin_info_t *pin_info,
const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len)
{
unsigned int puk_id = ETOKEN_AC_NEVER;
int r;
if (!pin || !pin_len)
return SC_ERROR_INVALID_ARGUMENTS;
r = sc_select_file(card, &df->path, NULL);
if (r < 0)
return r;
if (puk && puk_len) {
struct sc_pkcs15_pin_info puk_info;
sc_profile_get_pin_info(profile,
SC_PKCS15INIT_USER_PUK, &puk_info);
puk_info.reference = puk_id = pin_info->reference + 1;
r = etoken_store_pin(profile, card,
&puk_info, ETOKEN_AC_NEVER,
puk, puk_len);
}
if (r >= 0) {
r = etoken_store_pin(profile, card,
pin_info, puk_id,
pin, pin_len);
}
return r;
}
/*
* Select a key reference
*/
static int
etoken_select_key_reference(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_prkey_info_t *key_info)
{
struct sc_file *df = profile->df_info->file;
if (key_info->key_reference > 255)
return SC_ERROR_TOO_MANY_OBJECTS;
key_info->path = df->path;
return 0;
}
/*
* Create a private key object.
* This is a no-op.
*/
static int
etoken_create_key(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_object_t *obj)
{
return 0;
}
/*
* Store a private key object.
*/
static int
etoken_store_key(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_object_t *obj,
sc_pkcs15_prkey_t *key)
{
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
int algorithm, r;
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
error(profile, "CardOS supports RSA keys only.\n");
return SC_ERROR_NOT_SUPPORTED;
}
if (etoken_key_algorithm(key_info->usage, &algorithm) < 0) {
error(profile, "CardOS does not support keys "
"that can both sign _and_ decrypt.");
return SC_ERROR_NOT_SUPPORTED;
}
r = etoken_put_key(profile, card, algorithm,
key_info->key_reference,
&key->u.rsa);
return r;
}
/*
* Key generation
*/
static int
etoken_generate_key(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_object_t *obj,
sc_pkcs15_pubkey_t *pubkey)
{
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
struct sc_pkcs15_prkey_rsa key_obj;
struct sc_cardctl_etoken_genkey_info args;
struct sc_file *temp;
u8 abignum[RSAKEY_MAX_SIZE];
u8 randbuf[64];
unsigned int keybits;
int algorithm, r, delete_it = 0;
if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) {
error(profile, "CardOS supports only RSA keys.");
return SC_ERROR_NOT_SUPPORTED;
}
if (etoken_key_algorithm(key_info->usage, &algorithm) < 0) {
error(profile, "CardOS does not support keys "
"that can both sign _and_ decrypt.");
return SC_ERROR_NOT_SUPPORTED;
}
keybits = key_info->modulus_length & ~7UL;
if (keybits > RSAKEY_MAX_BITS) {
error(profile, "Unable to generate key, max size is %d\n",
RSAKEY_MAX_BITS);
return SC_ERROR_INVALID_ARGUMENTS;
}
if (sc_profile_get_file(profile, "tempfile", &temp) < 0) {
error(profile, "Profile doesn't define temporary file "
"for key generation.\n");
return SC_ERROR_NOT_SUPPORTED;
}
memset(pubkey, 0, sizeof(*pubkey));
if ((r = sc_pkcs15init_create_file(profile, card, temp)) < 0)
goto out;
delete_it = 1;
/* Create a key object, initializing components to 0xff */
memset(&key_obj, 0, sizeof(key_obj));
memset(abignum, 0xFF, sizeof(abignum));
key_obj.modulus.data = abignum;
key_obj.modulus.len = keybits >> 3;
key_obj.d.data = abignum;
key_obj.d.len = keybits >> 3;
r = etoken_put_key(profile, card, algorithm,
key_info->key_reference, &key_obj);
if (r < 0)
goto out;
memset(&args, 0, sizeof(args));
#ifdef notyet
if ((r = scrandom_get_data(randbuf, sizeof(randbuf))) < 0)
goto out;
/* For now, we have to rely on the card's internal number
* generator because libscrandom is static, which causes
* all sorts of headaches when linking against it
* (some platforms don't allow non-PIC code in a shared lib,
* such as ia64).
*/
args.random_data = randbuf;
args.random_len = sizeof(randbuf);
#endif
args.key_id = key_info->key_reference;
args.key_bits = keybits;
args.fid = temp->id;
r = sc_card_ctl(card, SC_CARDCTL_ETOKEN_GENERATE_KEY, &args);
memset(randbuf, 0, sizeof(randbuf));
if (r < 0)
goto out;
/* extract public key from file and delete it */
if ((r = sc_select_file(card, &temp->path, NULL)) < 0)
goto out;
r = etoken_extract_pubkey(card, 1, 0x10, &pubkey->u.rsa.modulus);
if (r < 0)
goto out;
r = etoken_extract_pubkey(card, 2, 0x11, &pubkey->u.rsa.exponent);
if (r < 0)
goto out;
pubkey->algorithm = SC_ALGORITHM_RSA;
out: if (delete_it) {
sc_pkcs15init_rmdir(card, profile, temp);
}
sc_file_free(temp);
if (r < 0) {
if (pubkey->u.rsa.modulus.data)
free (pubkey->u.rsa.modulus.data);
if (pubkey->u.rsa.exponent.data)
free (pubkey->u.rsa.exponent.data);
}
return r;
}
/*
* Store a PIN or PUK
*/
static int
etoken_store_pin(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_pin_info_t *pin_info, int puk_id,
const u8 *pin, size_t pin_len)
{
struct sc_pkcs15_pin_info params;
struct sc_cardctl_etoken_obj_info args;
unsigned char buffer[256];
unsigned char pinpadded[16];
struct tlv tlv;
unsigned int attempts, minlen, maxlen;
printf("etoken_store_pin(ref=%d, puk=%d\n", pin_info->reference, puk_id);
/* We need to do padding because pkcs15-lib.c does it.
* Would be nice to have a flag in the profile that says
* "no padding required". */
@ -148,21 +411,15 @@ etoken_store_pin(struct sc_profile *profile, struct sc_card *card,
pinpadded[pin_len++] = profile->pin_pad_char;
pin = pinpadded;
sc_profile_get_pin_info(profile, pin_type, &params);
attempts = params.tries_left;
minlen = params.min_length;
/* Set the profile's PIN reference */
params.reference = pin_id;
params.path = profile->df_info->file->path;
sc_profile_set_pin_info(profile, pin_type, &params);
attempts = pin_info->tries_left;
minlen = pin_info->min_length;
tlv_init(&tlv, buffer, sizeof(buffer));
/* object address: class, id */
tlv_next(&tlv, 0x83);
tlv_add(&tlv, 0x00); /* class byte: usage TEST, k=0 */
tlv_add(&tlv, pin_id);
tlv_add(&tlv, pin_info->reference);
/* parameters */
tlv_next(&tlv, 0x85);
@ -181,16 +438,16 @@ etoken_store_pin(struct sc_profile *profile, struct sc_card *card,
/* DEK: not documented, no idea what it means */
tlv_add(&tlv, 0x00);
/* ARA counter: not documented, no idea what it means */
/* ARA counter: Nils says this is the userConsent field */
tlv_add(&tlv, 0x00);
tlv_add(&tlv, minlen); /* minlen */
tlv_add(&tlv, minlen); /* minlen */
/* AC conditions */
tlv_next(&tlv, 0x86);
tlv_add(&tlv, 0x00); /* use: always */
tlv_add(&tlv, pin_id); /* change: PIN */
tlv_add(&tlv, puk_id); /* unblock: PUK */
tlv_add(&tlv, 0x00); /* use: always */
tlv_add(&tlv, pin_info->reference); /* change: PIN */
tlv_add(&tlv, puk_id); /* unblock: PUK */
/* data: PIN */
tlv_next(&tlv, 0x8f);
@ -235,11 +492,13 @@ etoken_create_sec_env(struct sc_profile *profile, struct sc_card *card,
return sc_card_ctl(card, SC_CARDCTL_ETOKEN_PUT_DATA_SECI, &args);
}
#if 0
/*
* Initialize the Application DF and pin file
*/
static int
etoken_init_app(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *pin_info,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len)
{
@ -259,16 +518,20 @@ etoken_init_app(struct sc_profile *profile, struct sc_card *card,
u8 puk_id = ETOKEN_AC_NEVER;
if (r >= 0 && puk && puk_len) {
puk_id = ETOKEN_PUK_ID(0);
struct sc_pkcs15_pin_info puk_info;
sc_profile_get_pin_info(profile,
SC_PKCS15INIT_SO_PUK, &puk_info);
puk_id = puk_info.reference;
r = etoken_store_pin(profile, card,
SC_PKCS15INIT_SO_PUK,
puk_id, ETOKEN_AC_NEVER,
&puk_info, ETOKEN_AC_NEVER,
puk, puk_len);
}
if (r >= 0) {
pin_info->path = df->path;
r = etoken_store_pin(profile, card,
SC_PKCS15INIT_SO_PIN,
ETOKEN_PIN_ID(0), puk_id,
pin_info, puk_id,
pin, pin_len);
}
}
@ -281,50 +544,7 @@ etoken_init_app(struct sc_profile *profile, struct sc_card *card,
return r;
}
/*
* Store a PIN
*/
static int
etoken_new_pin(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *info, unsigned int index,
const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len)
{
struct sc_file *df = profile->df_info->file;
unsigned int puk_id = ETOKEN_AC_NEVER, pin_id;
int r;
if (!pin || !pin_len)
return SC_ERROR_INVALID_ARGUMENTS;
r = sc_select_file(card, &df->path, NULL);
if (r < 0)
return r;
if (index >= ETOKEN_MAX_PINS)
return SC_ERROR_TOO_MANY_OBJECTS;
if (puk && puk_len) {
puk_id = ETOKEN_PUK_ID(index);
r = etoken_store_pin(profile, card,
SC_PKCS15INIT_USER_PUK,
puk_id, ETOKEN_AC_NEVER,
puk, puk_len);
}
if (r >= 0) {
pin_id = ETOKEN_PIN_ID(index);
r = etoken_store_pin(profile, card,
SC_PKCS15INIT_USER_PIN,
pin_id, puk_id,
pin, pin_len);
info->reference = pin_id;
info->path = df->path;
}
return r;
}
#endif
/*
* Determine the key algorithm based on the intended usage
@ -419,7 +639,7 @@ etoken_store_key_component(struct sc_card *card,
}
static int
etoken_store_key(struct sc_profile *profile, struct sc_card *card,
etoken_put_key(struct sc_profile *profile, struct sc_card *card,
int algorithm, unsigned int key_id,
struct sc_pkcs15_prkey_rsa *key)
{
@ -440,38 +660,6 @@ etoken_store_key(struct sc_profile *profile, struct sc_card *card,
return r;
}
/*
* Store a private key
*/
static int
etoken_new_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *info)
{
struct sc_pkcs15_prkey_rsa *rsa;
int algorithm, key_id, r;
if (key->algorithm != SC_ALGORITHM_RSA) {
error(profile, "eToken supports RSA keys only.\n");
return SC_ERROR_NOT_SUPPORTED;
}
if (etoken_key_algorithm(info->usage, &algorithm) < 0) {
error(profile, "eToken does not support keys "
"that can both sign _and_ decrypt.");
return SC_ERROR_NOT_SUPPORTED;
}
rsa = &key->u.rsa;
key_id = ETOKEN_KEY_ID(index);
r = etoken_store_key(profile, card, algorithm, key_id, rsa);
if (r >= 0) {
info->path = profile->df_info->file->path;
info->key_reference = key_id;
}
return r;
}
/*
* Allocate a file
*/
@ -574,107 +762,6 @@ etoken_extract_pubkey(struct sc_card *card, int nr, u8 tag,
return 0;
}
/*
* Key generation
*/
static int
etoken_generate_key(struct sc_profile *profile, struct sc_card *card,
unsigned int index, unsigned int keybits,
sc_pkcs15_pubkey_t *pubkey,
struct sc_pkcs15_prkey_info *info)
{
struct sc_pkcs15_prkey_rsa key_obj;
struct sc_cardctl_etoken_genkey_info args;
struct sc_file *temp;
u8 abignum[RSAKEY_MAX_SIZE];
u8 randbuf[64], key_id;
int algorithm, r, delete_it = 0;
keybits &= ~7UL;
if (keybits > RSAKEY_MAX_BITS) {
error(profile, "Unable to generate key, max size is %d\n",
RSAKEY_MAX_BITS);
return SC_ERROR_INVALID_ARGUMENTS;
}
if (etoken_key_algorithm(info->usage, &algorithm) < 0) {
error(profile, "eToken does not support keys "
"that can both sign _and_ decrypt.");
return SC_ERROR_NOT_SUPPORTED;
}
if (sc_profile_get_file(profile, "tempfile", &temp) < 0) {
error(profile, "Profile doesn't define temporary file "
"for key generation.\n");
return SC_ERROR_NOT_SUPPORTED;
}
memset(pubkey, 0, sizeof(*pubkey));
if ((r = sc_pkcs15init_create_file(profile, card, temp)) < 0)
goto out;
delete_it = 1;
key_id = ETOKEN_KEY_ID(index);
/* Create a key object, initializing components to 0xff */
memset(&key_obj, 0, sizeof(key_obj));
memset(abignum, 0xFF, sizeof(abignum));
key_obj.modulus.data = abignum;
key_obj.modulus.len = keybits >> 3;
key_obj.d.data = abignum;
key_obj.d.len = keybits >> 3;
r = etoken_store_key(profile, card, algorithm, key_id, &key_obj);
if (r < 0)
goto out;
memset(&args, 0, sizeof(args));
#ifdef notyet
if ((r = scrandom_get_data(randbuf, sizeof(randbuf))) < 0)
goto out;
/* For now, we have to rely on the card's internal number
* generator because libscrandom is static, which causes
* all sorts of headaches when linking against it
* (some platforms don't allow non-PIC code in a shared lib,
* such as ia64).
*/
args.random_data = randbuf;
args.random_len = sizeof(randbuf);
#endif
args.key_id = key_id;
args.key_bits = keybits;
args.fid = temp->id;
r = sc_card_ctl(card, SC_CARDCTL_ETOKEN_GENERATE_KEY, &args);
memset(randbuf, 0, sizeof(randbuf));
if (r < 0)
goto out;
/* extract public key from file and delete it */
if ((r = sc_select_file(card, &temp->path, NULL)) < 0)
goto out;
r = etoken_extract_pubkey(card, 1, 0x10, &pubkey->u.rsa.modulus);
if (r < 0)
goto out;
r = etoken_extract_pubkey(card, 2, 0x11, &pubkey->u.rsa.exponent);
if (r < 0)
goto out;
pubkey->algorithm = SC_ALGORITHM_RSA;
info->key_reference = key_id;
info->path = profile->df_info->file->path;
out: if (delete_it) {
sc_pkcs15init_rmdir(card, profile, temp);
}
sc_file_free(temp);
if (r < 0) {
if (pubkey->u.rsa.modulus.data)
free (pubkey->u.rsa.modulus.data);
if (pubkey->u.rsa.exponent.data)
free (pubkey->u.rsa.exponent.data);
}
return r;
}
static void
error(struct sc_profile *profile, const char *fmt, ...)
{
@ -689,10 +776,15 @@ error(struct sc_profile *profile, const char *fmt, ...)
}
struct sc_pkcs15init_operations sc_pkcs15init_etoken_operations = {
etoken_erase,
etoken_init_app,
etoken_new_pin,
etoken_new_key,
etoken_new_file,
etoken_generate_key
.erase_card = etoken_erase,
.create_dir = etoken_create_dir,
.select_pin_reference = etoken_select_pin_reference,
.create_pin = etoken_create_pin,
.select_key_reference = etoken_select_key_reference,
.create_key = etoken_create_key,
.store_key = etoken_store_key,
//.new_pin = etoken_new_pin,
//.new_key = etoken_new_key,
.generate_key = etoken_generate_key
//.new_file = etoken_new_file,
};

View File

@ -32,6 +32,7 @@
#include "profile.h"
#define GPK_MAX_PINS 8
#define GPK_PIN_SCOPE 8
#define GPK_FTYPE_SECRET_CODE 0x21
#define GPK_FTYPE_PUBLIC_KEY 0x2C
@ -60,13 +61,7 @@ struct pkdata {
/*
* Local functions
*/
static int gpk_new_pin(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *info, unsigned int index,
const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len);
static int gpk_new_file(struct sc_profile *, struct sc_card *,
unsigned int, unsigned int,
struct sc_file **);
static int gpk_pkfile_create(sc_profile_t *, sc_card_t *, sc_file_t *);
static int gpk_encode_rsa_key(struct sc_profile *,
struct sc_pkcs15_prkey_rsa *, struct pkdata *,
struct sc_pkcs15_prkey_info *);
@ -75,6 +70,7 @@ static int gpk_encode_dsa_key(struct sc_profile *,
struct sc_pkcs15_prkey_info *);
static int gpk_store_pk(struct sc_profile *, struct sc_card *,
struct sc_file *, struct pkdata *);
static int gpk_init_pinfile(sc_profile_t *, sc_card_t *, sc_file_t *);
static void error(struct sc_profile *, const char *, ...);
static void debug(struct sc_profile *, const char *, ...);
@ -97,6 +93,152 @@ gpk_erase_card(struct sc_profile *pro, struct sc_card *card)
return sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);
}
/*
* Create a new DF
* This will usually be the application DF
*/
static int
gpk_create_dir(sc_profile_t *profile, sc_card_t *card, sc_file_t *df)
{
struct sc_file *pinfile;
int r, locked, i;
if (sc_card_ctl(card, SC_CARDCTL_GPK_IS_LOCKED, &locked) == 0
&& locked) {
error(profile,
"This card is already personalized, unable to "
"create PKCS#15 structure.");
return SC_ERROR_NOT_SUPPORTED;
}
/* Create the DF. */
r = sc_pkcs15init_create_file(profile, card, df);
if (r < 0)
return r;
/* See if there's a file called "pinfile" that resides within
* this DF. If so, create it */
if (sc_profile_get_file(profile, "pinfile", &pinfile) >= 0) {
/* Build the pin file's path from the DF path + its
* file ID */
pinfile->path = df->path;
sc_append_file_id(&pinfile->path, pinfile->id);
r = gpk_init_pinfile(profile, card, pinfile);
sc_file_free(pinfile);
if (r < 0)
return r;
for (i = 0; i < GPK_MAX_PINS; i++)
sc_keycache_put_pin(&df->path, GPK_PIN_SCOPE|i, " ");
}
return r;
}
/*
* Select a PIN reference
*/
static int
gpk_select_pin_reference(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_pin_info_t *pin_info)
{
int preferred, current;
if ((current = pin_info->reference) < 0)
current = 0;
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
preferred = GPK_PIN_SCOPE | 0;
} else {
preferred = current | GPK_PIN_SCOPE;
if (preferred & 1)
preferred++;
if (preferred < (GPK_PIN_SCOPE | 2))
preferred = GPK_PIN_SCOPE | 2;
if (preferred > 15)
return SC_ERROR_TOO_MANY_OBJECTS;
}
if (current > preferred)
return SC_ERROR_TOO_MANY_OBJECTS;
pin_info->reference = preferred;
return 0;
}
/*
* Store a PIN
*/
static int
gpk_create_pin(sc_profile_t *profile, sc_card_t *card, sc_file_t *df,
sc_pkcs15_pin_info_t *pin_info,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len)
{
unsigned char nulpin[8];
int r, type;
if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
type = SC_PKCS15INIT_SO_PIN;
/* SO PIN reference must be 0 */
if (pin_info->reference != (GPK_PIN_SCOPE | 0))
return SC_ERROR_INVALID_ARGUMENTS;
} else {
type = SC_PKCS15INIT_USER_PIN;
/* PIN references must be even numbers
* (the odd numbered PIN entries contain the
* PUKs).
* Returning SC_ERROR_INVALID_PIN_REFERENCE will
* tell the caller to pick a different value.
*/
if ((pin_info->reference & 1) || !(pin_info->reference & GPK_PIN_SCOPE))
return SC_ERROR_INVALID_PIN_REFERENCE;
if (pin_info->reference >= (GPK_PIN_SCOPE + GPK_MAX_PINS))
return SC_ERROR_TOO_MANY_OBJECTS;
}
/* No PUK given, but the PIN file specifies an unblock
* PIN for every PIN.
* Use the same value for the PUK for now.
* Alternatively, we could leave the unblock PIN at the default
* value, but deliberately block it. */
if (puk == NULL || puk_len == 0) {
puk = pin;
puk_len = pin_len;
}
r = sc_select_file(card, &df->path, NULL);
if (r < 0)
return r;
/* Current PIN is 00:00:00:00:00:00:00:00 */
memset(nulpin, 0, sizeof(nulpin));
r = sc_change_reference_data(card, SC_AC_CHV,
pin_info->reference,
nulpin, sizeof(nulpin),
pin, pin_len, NULL);
if (r < 0)
return r;
/* Current PUK is 00:00:00:00:00:00:00:00 */
r = sc_change_reference_data(card, SC_AC_CHV,
pin_info->reference + 1,
nulpin, sizeof(nulpin),
puk, puk_len, NULL);
if (r < 0)
return r;
sc_keycache_set_pin_name(&df->path,
pin_info->reference,
type);
return r;
}
/*
* Lock a file operation
*/
@ -146,7 +288,6 @@ static int
gpk_init_pinfile(struct sc_profile *profile, struct sc_card *card,
struct sc_file *file)
{
struct sc_pkcs15_pin_info sopin_info, pin_info;
const struct sc_acl_entry *acl;
unsigned char buffer[GPK_MAX_PINS * 8], *blk;
struct sc_file *pinfile;
@ -155,14 +296,10 @@ gpk_init_pinfile(struct sc_profile *profile, struct sc_card *card,
int r;
/* Set defaults */
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin_info);
so_attempts[0] = sopin_info.tries_left;
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &pin_info);
so_attempts[1] = pin_info.tries_left;
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PIN, &pin_info);
user_attempts[0] = pin_info.tries_left;
sc_profile_get_pin_info(profile, SC_PKCS15INIT_USER_PUK, &pin_info);
user_attempts[1] = pin_info.tries_left;
so_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PIN);
so_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_SO_PUK);
user_attempts[0] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PIN);
user_attempts[1] = sc_profile_get_pin_retries(profile, SC_PKCS15INIT_USER_PUK);
sc_file_dup(&pinfile, file);
@ -199,7 +336,7 @@ gpk_init_pinfile(struct sc_profile *profile, struct sc_card *card,
* the next will be a PUK so take note of the
* unlock code */
if (i + 1 < npins)
blk[2] = 0x8 | (i + 1);
blk[2] = GPK_PIN_SCOPE | (i + 1);
}
/* Compute the CKS */
@ -217,100 +354,54 @@ out: sc_file_free(pinfile);
}
/*
* Initialize the Application DF and pin file
* Create a key file
*/
static int
gpk_init_app(struct sc_profile *profile, struct sc_card *card,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len)
gpk_create_key(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_object_t *obj)
{
struct sc_pkcs15_pin_info sopin_info;
struct sc_file *pinfile;
int r, locked;
if (sc_card_ctl(card, SC_CARDCTL_GPK_IS_LOCKED, &locked) == 0
&& locked) {
error(profile,
"This card is already personalized, unable to "
"create PKCS#15 structure.");
return SC_ERROR_NOT_SUPPORTED;
}
/* Profile must define a "pinfile" */
if (sc_profile_get_file(profile, "pinfile", &pinfile) < 0) {
error(profile, "Profile doesn't define a \"pinfile\"");
return SC_ERROR_NOT_SUPPORTED;
}
/* Create the application DF */
r = sc_pkcs15init_create_file(profile, card, profile->df_info->file);
/* Create the PIN file */
if (r >= 0)
r = gpk_init_pinfile(profile, card, pinfile);
sc_profile_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &sopin_info);
if (r >= 0 && pin_len) {
r = gpk_new_pin(profile, card, &sopin_info, 0,
pin, pin_len,
puk, puk_len);
if (r >= 0)
sc_profile_set_pin_info(profile, SC_PKCS15INIT_SO_PIN,
&sopin_info);
}
sc_file_free(pinfile);
return r;
}
/*
* Store a PIN
*/
static int
gpk_new_pin(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *info, unsigned int index,
const u8 *pin, size_t pin_len,
const u8 *puk, size_t puk_len)
{
unsigned char nulpin[8];
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
struct sc_file *keyfile = NULL;
size_t bytes, mod_len, exp_len, prv_len, pub_len;
int r;
/* Profile must define a "pinfile" */
if (sc_profile_get_path(profile, "pinfile", &info->path) < 0) {
error(profile, "Profile doesn't define a \"pinfile\"");
/* The caller is supposed to have chosen a key file path for us */
if (key_info->path.len == 0 || key_info->modulus_length == 0)
return SC_ERROR_INVALID_ARGUMENTS;
}
if (info->path.len > 2)
info->path.len -= 2;
r = sc_select_file(card, &info->path, NULL);
/* Get the file we're supposed to create */
r = sc_profile_get_file_by_path(profile, &key_info->path, &keyfile);
if (r < 0)
return r;
index <<= 2;
if (index >= GPK_MAX_PINS)
return SC_ERROR_TOO_MANY_OBJECTS;
if (puk == NULL || puk_len == 0) {
puk = pin;
puk_len = pin_len;
/* Compute the file size.
* We assume private keys are stored as CRT elements.
* - 512, 768 bit keys: all CRT elements fit into one record
* - >= 1024: each CRT element into a record of its own
*
* We also assume the public exponent is 32bit max
*
* Rules
* - private key records must have a length divisible by 8
*/
mod_len = key_info->modulus_length / 8;
exp_len = 4;
bytes = mod_len / 2;
pub_len = 8 + ((3 + mod_len + 3 + exp_len + 3) & ~3UL);
if (5 * bytes < 256) {
prv_len = 8 + ((3 + 5 * bytes + 7) & ~7UL);
} else {
prv_len = 8 + 5 * ((3 + bytes + 7) & ~7UL);
}
keyfile->size = pub_len + prv_len;
/* Current PIN is 00:00:00:00:00:00:00:00 */
memset(nulpin, 0, sizeof(nulpin));
r = sc_change_reference_data(card, SC_AC_CHV,
0x8 | index,
nulpin, sizeof(nulpin),
pin, pin_len, NULL);
if (r < 0)
return r;
/* Fix up PIN references in file ACL */
r = sc_pkcs15init_fixup_file(profile, keyfile);
/* Current PUK is 00:00:00:00:00:00:00:00 */
r = sc_change_reference_data(card, SC_AC_CHV,
0x8 | (index + 1),
nulpin, sizeof(nulpin),
puk, puk_len, NULL);
if (r >= 0)
r = gpk_pkfile_create(profile, card, keyfile);
info->reference = 0x8 | index;
if (keyfile)
sc_file_free(keyfile);
return r;
}
@ -318,6 +409,50 @@ gpk_new_pin(struct sc_profile *profile, struct sc_card *card,
* Store a private key
*/
static int
gpk_store_key(sc_profile_t *profile, sc_card_t *card,
sc_pkcs15_object_t *obj, struct sc_pkcs15_prkey *key)
{
sc_pkcs15_prkey_info_t *key_info = (sc_pkcs15_prkey_info_t *) obj->data;
struct sc_file *keyfile = NULL;
struct pkdata data;
int r;
/* The caller is supposed to have chosen a key file path for us */
if (key_info->path.len == 0 || key_info->modulus_length == 0)
return SC_ERROR_INVALID_ARGUMENTS;
/* Get the file we're supposed to create */
r = sc_select_file(card, &key_info->path, &keyfile);
if (r < 0)
return r;
switch (key->algorithm) {
case SC_ALGORITHM_RSA:
r = gpk_encode_rsa_key(profile, &key->u.rsa,
&data, key_info);
break;
case SC_ALGORITHM_DSA:
r = gpk_encode_dsa_key(profile, &key->u.dsa,
&data, key_info);
break;
default:
return SC_ERROR_NOT_SUPPORTED;
}
if (r >= 0)
r = gpk_store_pk(profile, card, keyfile, &data);
if (keyfile)
sc_file_free(keyfile);
return r;
}
/*
* Store a private key
*/
#if 0
static int
gpk_new_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_prkey *key, unsigned int index,
struct sc_pkcs15_prkey_info *info)
@ -439,6 +574,7 @@ gpk_new_file(struct sc_profile *profile, struct sc_card *card,
*out = file;
return 0;
}
#endif
/*
* GPK public/private key file handling is hideous.
@ -449,8 +585,7 @@ gpk_new_file(struct sc_profile *profile, struct sc_card *card,
* XXX: Handle the UPDATE ACL = NEVER case just like for EFsc files
*/
static int
gpk_pkfile_create(struct sc_profile *profile, struct sc_card *card,
struct sc_file *file)
gpk_pkfile_create(sc_profile_t *profile, sc_card_t *card, sc_file_t *file)
{
struct sc_file *found = NULL;
int r;
@ -500,12 +635,12 @@ gpk_pkfile_keyalgo(unsigned int algo, unsigned char *p)
* Set up the public key record for a signature only public key
*/
static int
gpk_pkfile_init_public(struct sc_profile *profile,
struct sc_card *card, struct sc_file *file,
gpk_pkfile_init_public(sc_profile_t *profile, sc_card_t *card, sc_file_t *file,
unsigned int algo, unsigned int bits,
unsigned int usage)
{
const struct sc_acl_entry *acl;
sc_file_t *tmp = NULL;
u8 sysrec[7], buffer[256];
unsigned int n, npins;
int r, gpkclass;
@ -531,8 +666,17 @@ gpk_pkfile_init_public(struct sc_profile *profile,
|| (r = gpk_pkfile_keyalgo(algo, &sysrec[5])) < 0)
return r;
/* Set PIN protection if requested. */
acl = sc_file_get_acl_entry(file, SC_AC_OP_CRYPTO);
/* Set PIN protection if requested.
* As the crypto ACLs are stored inside the file,
* we have to get them from the profile here. */
r = sc_profile_get_file_by_path(profile, &file->path, &tmp);
if (r < 0)
return r;
/* Fix up PIN references in file ACL */
if ((r = sc_pkcs15init_fixup_file(profile, tmp)) < 0)
goto out;
acl = sc_file_get_acl_entry(tmp, SC_AC_OP_CRYPTO);
for (npins = 0; acl; acl = acl->next) {
if (acl->method == SC_AC_NONE
|| acl->method == SC_AC_NEVER)
@ -540,11 +684,13 @@ gpk_pkfile_init_public(struct sc_profile *profile,
if (acl->method != SC_AC_CHV) {
error(profile, "Authentication method not "
"supported for private key files.\n");
return SC_ERROR_NOT_SUPPORTED;
r = SC_ERROR_NOT_SUPPORTED;
goto out;
}
if (++npins >= 2) {
error(profile, "Too many pins for PrKEY file!\n");
return SC_ERROR_NOT_SUPPORTED;
r = SC_ERROR_NOT_SUPPORTED;
goto out;
}
sysrec[2] += 0x40;
sysrec[3] >>= 4;
@ -578,6 +724,9 @@ gpk_pkfile_init_public(struct sc_profile *profile,
} else {
r = sc_append_record(card, sysrec, sizeof(sysrec), 0);
}
out: if (tmp)
sc_file_free(tmp);
return r;
}
@ -673,24 +822,12 @@ gpk_pkfile_update_private(struct sc_profile *profile,
{
unsigned int m, size, nb, cks;
struct pkcomp *pe;
u8 keybuf[32], data[256];
size_t keysize;
u8 data[256];
int r = 0;
if (card->ctx->debug > 1)
debug(profile, "Updating private key elements\n");
/* We must set a secure messaging key before each Load Private Key
* command. Any key will do...
* The GPK _is_ weird. */
keysize = sizeof(keybuf);
r = sc_pkcs15init_get_secret(profile, card,
SC_AC_PRO, 1, keybuf, &keysize);
if (r < 0) {
error(profile, "No secure messaging key defined by profile");
return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
}
for (m = 0; m < part->count; m++) {
pe = part->components + m;
@ -699,7 +836,10 @@ gpk_pkfile_update_private(struct sc_profile *profile,
memcpy(data, pe->data, pe->size);
size = pe->size;
r = sc_verify(card, SC_AC_PRO, 1, keybuf, keysize, NULL);
/* We must set a secure messaging key before each
* Load Private Key command. Any key will do...
* The GPK _is_ weird. */
r = sc_pkcs15init_verify_key(profile, card, NULL, SC_AC_PRO, 1);
if (r < 0)
break;
@ -912,6 +1052,7 @@ static int
gpk_store_pk(struct sc_profile *profile, struct sc_card *card,
struct sc_file *file, struct pkdata *p)
{
size_t fsize;
int r;
/* Compute length of private/public key parts */
@ -923,10 +1064,9 @@ gpk_store_pk(struct sc_profile *profile, struct sc_card *card,
"Storing pk: %u bits, pub %u bytes, priv %u bytes\n",
p->bits, p->_public.size, p->_private.size);
file->size = p->_public.size + p->_private.size;
r = gpk_pkfile_create(profile, card, file);
if (r < 0)
return r;
fsize = p->_public.size + p->_private.size;
if (fsize > file->size)
return SC_ERROR_FILE_TOO_SMALL;
/* Put the system record */
r = gpk_pkfile_init_public(profile, card, file, p->algo,
@ -973,14 +1113,17 @@ debug(struct sc_profile *profile, const char *fmt, ...)
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
if (profile->cbs && profile->cbs->debug)
profile->cbs->debug("%s", buffer);
profile->cbs->debug(2, "%s", buffer);
printf("%s", buffer); /* XXX */
}
struct sc_pkcs15init_operations sc_pkcs15init_gpk_operations = {
gpk_erase_card,
gpk_init_app,
gpk_new_pin,
gpk_new_key,
gpk_new_file,
.erase_card = gpk_erase_card,
.create_dir = gpk_create_dir,
.select_pin_reference = gpk_select_pin_reference,
.create_pin = gpk_create_pin,
.create_key = gpk_create_key,
.store_key = gpk_store_key,
// .new_key = gpk_new_key,
// .new_file = gpk_new_file,
};

View File

@ -13,19 +13,85 @@ extern "C" {
#include <opensc/pkcs15.h>
struct sc_profile; /* opaque type */
typedef struct sc_profile sc_profile_t; /* opaque type */
struct sc_pkcs15init_operations {
/*
* Erase everything that's on the card
* So far, only the GPK supports this
*/
* So far, only the GPK supports this */
int (*erase_card)(struct sc_profile *, struct sc_card *);
/*
* New style API
*/
/*
* Create a DF
*/
int (*create_dir)(sc_profile_t *, sc_card_t *, sc_file_t *);
/*
* Create a "pin domain". This is for cards such as
* the cryptoflex that need to put their pins into
* separate directories
*/
int (*create_domain)(sc_profile_t *, sc_card_t *,
const sc_pkcs15_id_t *, sc_file_t **);
/*
* Select a PIN reference
*/
int (*select_pin_reference)(sc_profile_t *, sc_card_t *,
sc_pkcs15_pin_info_t *);
/*
* Create a PIN object within the given DF.
*
* The pin_info object is completely filled in by the caller.
* The card driver can reject the pin reference; in this case
* the caller needs to adjust it.
*/
int (*create_pin)(sc_profile_t *, sc_card_t *, sc_file_t *,
struct sc_pkcs15_pin_info *,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len);
/*
* Select a reference for a private key object
*/
int (*select_key_reference)(sc_profile_t *, sc_card_t *,
sc_pkcs15_prkey_info_t *);
/*
* Create an empty key object.
* @index is the number key objects already on the card.
* @pin_info contains information on the PIN protecting
* the key. NULL if the key should be
* unprotected.
* @key_info should be filled in by the function
*/
int (*create_key)(sc_profile_t *, sc_card_t *,
sc_pkcs15_object_t *o);
/*
* Store a key on the card
*/
int (*store_key)(sc_profile_t *, sc_card_t *,
sc_pkcs15_object_t *,
sc_pkcs15_prkey_t *);
/*
* Generate key
*/
int (*generate_key)(sc_profile_t *, sc_card_t *,
sc_pkcs15_object_t *,
sc_pkcs15_pubkey_t *);
/*
* Initialize application, and optionally set a SO pin
*/
int (*init_app)(struct sc_profile *, struct sc_card *,
struct sc_pkcs15_pin_info *,
const unsigned char *pin, size_t pin_len,
const unsigned char *puk, size_t puk_len);
@ -58,7 +124,7 @@ struct sc_pkcs15init_operations {
/*
* Generate a new key pair
*/
int (*generate_key)(struct sc_profile *, struct sc_card *,
int (*old_generate_key)(struct sc_profile *, struct sc_card *,
unsigned int index, unsigned int keybits,
sc_pkcs15_pubkey_t *pubkey_res,
struct sc_pkcs15_prkey_info *);
@ -75,7 +141,7 @@ struct sc_pkcs15init_operations {
struct sc_pkcs15init_callbacks {
/* Error and debug output */
void (*error)(const char *, ...);
void (*debug)(const char *, ...);
void (*debug)(int level, const char *, ...);
/*
* Get a PIN from the front-end. The first argument is
@ -100,6 +166,7 @@ struct sc_pkcs15init_initargs {
size_t so_pin_len;
const u8 * so_puk;
size_t so_puk_len;
const char * so_pin_label;
const char * label;
const char * serial;
};
@ -220,8 +287,6 @@ extern int sc_pkcs15init_update_file(struct sc_profile *,
struct sc_card *, struct sc_file *, void *, unsigned int);
extern int sc_pkcs15init_authenticate(struct sc_profile *,
struct sc_card *, struct sc_file *, int);
extern int sc_pkcs15init_present_pin(struct sc_profile *,
struct sc_card *, unsigned int);
extern int sc_pkcs15init_fixup_file(struct sc_profile *, struct sc_file *);
extern int sc_pkcs15init_fixup_acls(struct sc_profile *,
struct sc_file *,
@ -229,18 +294,17 @@ extern int sc_pkcs15init_fixup_acls(struct sc_profile *,
struct sc_acl_entry *);
extern int sc_pkcs15init_get_pin_info(struct sc_profile *, unsigned int,
struct sc_pkcs15_pin_info *);
extern int sc_profile_get_pin_retries(sc_profile_t *, unsigned int);
extern int sc_pkcs15init_get_manufacturer(struct sc_profile *,
const char **);
extern int sc_pkcs15init_get_serial(struct sc_profile *, const char **);
extern int sc_pkcs15init_set_serial(struct sc_profile *, const char *);
extern int sc_pkcs15init_get_label(struct sc_profile *, const char **);
extern void sc_pkcs15init_set_pin_data(struct sc_profile *, int,
const void *, size_t);
extern void sc_pkcs15init_set_secret(struct sc_profile *,
int, int, u8 *, size_t);
extern int sc_pkcs15init_get_secret(struct sc_profile *,
struct sc_card *, int, int, u8 *, size_t *);
extern int sc_pkcs15init_verify_key(struct sc_profile *, struct sc_card *,
sc_file_t *, unsigned int, unsigned int);
/* Erasing the card structure via rm -rf */
extern int sc_pkcs15init_erase_card_recursively(struct sc_card *,
@ -254,6 +318,9 @@ extern int sc_pkcs15init_requires_restrictive_usage(
struct sc_pkcs15init_prkeyargs *,
unsigned int);
extern int sc_pkcs15_create_pin_domain(sc_profile_t *, sc_card_t *,
const sc_pkcs15_id_t *, sc_file_t **);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
* Initialize the Application DF
*/
static int miocos_init_app(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15_pin_info *pin_info,
const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len)
{
/* Create the application DF */
@ -200,8 +201,8 @@ miocos_new_key(struct sc_profile *profile, struct sc_card *card,
struct sc_pkcs15init_operations sc_pkcs15init_miocos_operations = {
NULL,
miocos_init_app,
miocos_new_pin,
miocos_new_key,
miocos_new_file,
.init_app = miocos_init_app,
.new_pin = miocos_new_pin,
.new_key = miocos_new_key,
.new_file = miocos_new_file,
};

View File

@ -11,11 +11,40 @@ cardinfo {
max-pin-length = 8;
}
# Default settings.
# This option block will always be processed.
option default {
macros {
protected = *=$SOPIN, READ=NONE;
unprotected = *=NONE;
so-pin-flags = local, initialized, needs-padding, soPin;
default-df-size = 256;
}
}
# This option sets up the card so that a single
# user PIN protects all files
option onepin {
macros {
protected = *=$PIN, READ=NONE;
unprotected = *=NONE;
so-pin-flags = local, initialized, needs-padding;
}
}
# This option is for cards with very little memory
option small {
macros {
default-df-size = 128;
}
}
# 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, needs-padding;
}
PIN user-puk {
attempts = 7;
@ -24,7 +53,7 @@ PIN so-pin {
auth-id = FF;
attempts = 2;
min-length = 6;
flags = 0x32;
flags = $so-pin-flags;
}
PIN so-puk {
attempts = 4;
@ -54,43 +83,43 @@ filesystem {
EF PKCS15-ODF {
file-id = 5031;
size = 256;
ACL = *=NONE;
size = $default-df-size;
ACL = $unprotected;
}
EF PKCS15-TokenInfo {
file-id = 5032;
ACL = *=NONE;
ACL = $unprotected;
}
EF PKCS15-AODF {
file-id = 4401;
size = 256;
ACL = *=$SOPIN, READ=NONE;
size = $default-df-size;
ACL = $protected;
}
EF PKCS15-PrKDF {
file-id = 4402;
size = 256;
acl = *=$SOPIN, READ=NONE;
size = $default-df-size;
acl = $protected;
}
EF PKCS15-PuKDF {
file-id = 4403;
size = 256;
acl = *=$SOPIN, READ=NONE;
size = $default-df-size;
acl = $protected;
}
EF PKCS15-CDF {
file-id = 4404;
size = 512;
acl = *=$SOPIN, READ=NONE;
size = "2 * $default-df-size";
acl = $protected;
}
EF PKCS15-DODF {
file-id = 4405;
size = 256;
ACL = *=NONE;
size = $default-df-size;
ACL = $protected;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ extern "C" {
#endif
#include <opensc/pkcs15.h>
#include "keycache.h"
#ifndef SC_PKCS15_PROFILE_DIRECTORY
#define SC_PKCS15_PROFILE_DIRECTORY "/usr/lib/opensc/profiles"
@ -20,6 +21,7 @@ extern "C" {
#define SC_PKCS15_PROFILE_SUFFIX "profile"
#endif
/* Obsolete */
struct auth_info {
struct auth_info * next;
unsigned int type; /* CHV, AUT, PRO */
@ -34,6 +36,12 @@ struct file_info {
struct sc_file * file;
unsigned int dont_free;
struct file_info * parent;
/* Template support */
struct file_info * instance;
struct sc_profile * base_template;
unsigned int inst_index;
sc_path_t inst_path;
};
/* For now, we assume the PUK always resides
@ -42,13 +50,33 @@ struct file_info {
struct pin_info {
unsigned int id;
struct pin_info * next;
char * file_name;
unsigned int file_offset;
struct file_info * file;
char * file_name; /* obsolete */
unsigned int file_offset; /* obsolete */
struct file_info * file; /* obsolete */
struct sc_pkcs15_pin_info pin;
sc_pkcs15_pin_info_t pin;
};
typedef struct sc_macro {
char * name;
struct sc_macro * next;
scconf_list * value;
} sc_macro_t;
/* Template support.
*
* Templates are EFs or entire hierarchies of DFs/EFs.
* When instantiating a template, the file IDs of the
* EFs and DFs are combined from the value given in the
* profile, and the last octet of the pkcs15 ID.
*/
typedef struct sc_template {
char * name;
struct sc_template * next;
struct sc_profile * data;
struct file_info * file;
} sc_template_t;
struct sc_profile {
char * driver;
struct sc_pkcs15init_operations *ops;
@ -61,7 +89,10 @@ struct sc_profile {
struct pin_info * pin_list;
struct auth_info * auth_list;
sc_template_t * template_list;
sc_macro_t * macro_list;
unsigned int pin_domains;
unsigned int pin_maxlen;
unsigned int pin_minlen;
unsigned int pin_pad_char;
@ -70,36 +101,36 @@ struct sc_profile {
unsigned int puk_attempts;
unsigned int rsa_access_flags;
unsigned int dsa_access_flags;
unsigned int protect_certificates;
/* PKCS15 information */
struct sc_pkcs15_card * p15_card;
};
struct sc_profile *sc_profile_new();
int sc_profile_load(struct sc_profile *, const char *);
int sc_profile_load(struct sc_profile *, const char *,
const char *);
int sc_profile_finish(struct sc_profile *);
void sc_profile_free(struct sc_profile *);
int sc_profile_build_pkcs15(struct sc_profile *);
void sc_profile_set_so_pin(struct sc_profile *, const char *);
void sc_profile_set_user_pin(struct sc_profile *, const char *);
void sc_profile_set_secret(struct sc_profile *,
unsigned int, unsigned int, const u8 *, size_t);
int sc_profile_get_secret(struct sc_profile *,
unsigned int, unsigned int, u8 *, size_t *);
void sc_profile_forget_secrets(struct sc_profile *,
unsigned int, int);
void sc_profile_get_pin_info(struct sc_profile *,
unsigned int, struct sc_pkcs15_pin_info *);
int sc_profile_get_pin_id(struct sc_profile *,
unsigned int, unsigned int *);
void sc_profile_set_pin_info(struct sc_profile *,
unsigned int, const struct sc_pkcs15_pin_info *);
int sc_profile_get_file(struct sc_profile *, const char *,
struct sc_file **);
int sc_profile_get_file_by_path(struct sc_profile *,
const struct sc_path *, struct sc_file **);
int sc_profile_get_path(struct sc_profile *,
const char *, struct sc_path *);
int sc_profile_get_file_in(struct sc_profile *,
const sc_path_t *, const char *, sc_file_t **);
int sc_profile_instantiate_template(struct sc_profile *,
const char *, const sc_path_t *,
const char *, const sc_pkcs15_id_t *,
sc_file_t **);
int sc_profile_add_file(struct sc_profile *,
const char *, sc_file_t *);
#ifdef __cplusplus
}

View File

@ -47,6 +47,7 @@
#include <opensc/cardctl.h>
#include <opensc/pkcs15.h>
#include <opensc/pkcs15-init.h>
#include <opensc/log.h>
#include "util.h"
@ -95,6 +96,7 @@ static int do_read_certificate(const char *, const char *, X509 **);
static void parse_commandline(int argc, char **argv);
static void read_options_file(const char *);
static void ossl_print_errors(void);
static void p15init_debug(int, const char *, ...);
enum {
@ -199,7 +201,7 @@ const char * option_help[] = {
"Do not prompt the user, except for PINs",
"Specify the general profile to use",
"Specify the card profile option to use",
"Specify the card profile to use",
"Read additional command line options from file",
"Wait for card insertion",
"Enable debugging output",
@ -286,7 +288,7 @@ static unsigned int opt_secret_count;
static struct sc_pkcs15init_callbacks callbacks = {
error, /* error() */
NULL, /* debug() */
p15init_debug, /* debug() */
get_pin_callback, /* get_pin() */
get_key_callback, /* get_key() */
};
@ -517,7 +519,7 @@ do_init_app(struct sc_profile *profile)
args.so_puk_len = strlen((char *) args.so_puk);
args.serial = (const char *) opt_serial;
args.label = opt_label;
return sc_pkcs15init_add_app(card, profile, &args);
failed:
@ -699,6 +701,7 @@ static int
do_store_public_key(struct sc_profile *profile, EVP_PKEY *pkey)
{
struct sc_pkcs15init_pubkeyargs args;
sc_pkcs15_object_t *dummy;
int r = 0;
memset(&args, 0, sizeof(args));
@ -712,7 +715,7 @@ do_store_public_key(struct sc_profile *profile, EVP_PKEY *pkey)
r = do_convert_public_key(&args.key, pkey);
if (r >= 0)
r = sc_pkcs15init_store_public_key(p15card, profile,
&args, NULL);
&args, &dummy);
return r;
}
@ -1935,3 +1938,22 @@ ossl_print_errors()
while ((err = ERR_get_error()) != 0)
fprintf(stderr, "%s\n", ERR_error_string(err, NULL));
}
/*
* Debug helper function
*/
void
p15init_debug(int level, const char *fmt, ...)
{
char buffer[128];
va_list ap;
if (ctx->debug < level)
return;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
sc_debug(ctx, "%s", buffer);
}