pkcs15init: no more need for static keycache

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4079 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
viktor.tarasov 2010-03-02 17:03:44 +00:00
parent 02c35be138
commit 0bb56af014
6 changed files with 2 additions and 452 deletions

View File

@ -13,7 +13,6 @@ all-local:
@$(LN_S) $(top_srcdir)/src/libopensc/types.h types.h
@$(LN_S) $(top_srcdir)/src/pkcs11/pkcs11.h pkcs11.h
@$(LN_S) $(top_srcdir)/src/pkcs11/pkcs11-opensc.h pkcs11-opensc.h
@$(LN_S) $(top_srcdir)/src/pkcs15init/keycache.h keycache.h
@$(LN_S) $(top_srcdir)/src/pkcs15init/pkcs15-init.h pkcs15-init.h
@$(LN_S) $(top_srcdir)/src/scconf/scconf.h scconf.h
@$(LN_S) $(top_srcdir)/src/common/simclist.h simclist.h

View File

@ -235,14 +235,6 @@ sc_wait_for_event
sc_write_binary
sc_write_record
sc_get_iso7816_driver
sc_keycache_find_named_pin
sc_keycache_forget_key
sc_keycache_get_key
sc_keycache_get_pin
sc_keycache_get_pin_name
sc_keycache_put_key
sc_keycache_put_pin
sc_keycache_set_pin_name
sc_pkcs15init_add_app
sc_pkcs15init_authenticate
sc_pkcs15init_bind

View File

@ -5,7 +5,7 @@ EXTRA_DIST = Makefile.mak
noinst_LTLIBRARIES = libpkcs15init.la
openscinclude_HEADERS = pkcs15-init.h
noinst_HEADERS = profile.h keycache.h
noinst_HEADERS = profile.h
dist_pkgdata_DATA = \
cyberflex.profile \
flex.profile \
@ -31,7 +31,7 @@ AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(LTLIB_CFLAGS)
INCLUDES = -I$(top_srcdir)/src/common -I$(top_builddir)/src/include
libpkcs15init_la_SOURCES = \
pkcs15-lib.c profile.c keycache.c \
pkcs15-lib.c profile.c \
pkcs15-westcos.c \
pkcs15-gpk.c pkcs15-miocos.c pkcs15-cflex.c \
pkcs15-cardos.c pkcs15-jcop.c pkcs15-starcos.c \

View File

@ -1,396 +0,0 @@
/*
* 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 <opensc/cardctl.h>
#include "profile.h"
#include "pkcs15-init.h"
#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
*/
static struct secret *
new_entry(const sc_path_t *path, int type, int ref)
{
struct secret *s;
s = (struct secret *) calloc(1, sizeof(*s));
if (s == NULL)
return NULL;
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);
if (s == NULL)
return SC_ERROR_OUT_OF_MEMORY;
if (type == SC_AC_SYMBOLIC)
named_pin[ref] = s;
}
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 u8 *pin)
{
return sc_keycache_put_key(path, SC_AC_CHV, ref, pin,
pin? strlen((const char *) 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 u8 *
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);
if (s == NULL)
return SC_ERROR_OUT_OF_MEMORY;
}
/* 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;
if (s->named_pin >= 0 && s->named_pin < SC_PKCS15INIT_NPINS)
named_pin[s->named_pin] = NULL;
sc_mem_clear(s, 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

View File

@ -1,44 +0,0 @@
/*
* 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
#ifdef __cplusplus
extern "C" {
#endif
#include <opensc/opensc.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 u8 *);
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 u8 *sc_keycache_get_pin(const sc_path_t *, int);
extern void sc_keycache_forget_key(const sc_path_t *, int, int);
#ifdef __cplusplus
}
#endif
#endif /* _PKCS15INIT_KEYCACHE_H */

View File

@ -12,7 +12,6 @@ extern "C" {
#endif
#include <opensc/pkcs15.h>
#include "keycache.h"
#ifndef SC_PKCS15_PROFILE_SUFFIX
#define SC_PKCS15_PROFILE_SUFFIX "profile"