[Fedora-directory-commits] coolkey/src/libckyapplet Makefile.am, NONE, 1.1 Makefile.in, NONE, 1.1 cky_applet.c, NONE, 1.1 cky_applet.h, NONE, 1.1 cky_base.c, NONE, 1.1 cky_base.h, NONE, 1.1 cky_basei.h, NONE, 1.1 cky_card.c, NONE, 1.1 cky_card.h, NONE, 1.1 cky_factory.c, NONE, 1.1 cky_factory.h, NONE, 1.1 cky_list.h, NONE, 1.1 cky_list.i, NONE, 1.1 config.mk, NONE, 1.1 dynlink.c, NONE, 1.1 dynlink.h, NONE, 1.1 dynlink_mac.c, NONE, 1.1 dynlink_unix.c, NONE, 1.1 dynlink_win.c, NONE, 1.1 manifest.mn, NONE, 1.1
Robert Relyea (rrelyea)
fedora-directory-commits at redhat.com
Fri Jun 9 18:44:19 UTC 2006
- Previous message (by thread): [Fedora-directory-commits] coolkey/src/libckyapplet - New directory
- Next message (by thread): [Fedora-directory-commits] coolkey Makefile.am, 1.1.1.1, 1.2 Makefile.in, 1.1.1.1, 1.2 config.status, 1.1.1.1, 1.2 configure, 1.1.1.1, 1.2 configure.in, 1.1.1.1, 1.2 coolkey.spec, 1.1.1.1, 1.2 libtool, 1.1.1.1, 1.2
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Author: rrelyea
Update of /cvs/dirsec/coolkey/src/libckyapplet
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv1977/libckyapplet
Added Files:
Makefile.am Makefile.in cky_applet.c cky_applet.h cky_base.c
cky_base.h cky_basei.h cky_card.c cky_card.h cky_factory.c
cky_factory.h cky_list.h cky_list.i config.mk dynlink.c
dynlink.h dynlink_mac.c dynlink_unix.c dynlink_win.c
manifest.mn
Log Message:
libckyapplet was also misnamed.
--- NEW FILE Makefile.am ---
# ***** BEGIN COPYRIGHT BLOCK *****
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
#
# 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 version
# 2.1 of the License.
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# ***** END COPYRIGHT BLOCK *****
# Process this file with automake to create Makefile.in
SUBDIRS =
AM_CFLAGS =
# bleh what do I add just to get static but pic libraries?
noinst_LTLIBRARIES = libckyapplet.la
libckyapplet_la_SOURCES = \
cky_applet.c \
cky_base.c \
cky_card.c \
cky_factory.c \
dynlink.c
quote=\"
libckyapplet_la_LDFLAGS = -avoid-version
libckyapplet_la_CFLAGS = $(CFLAGS) -DSCARD_LIB_NAME=$(quote)$(SCARD_LIB_NAME)$(quote) $(PCSC_CFLAGS)
nobase_include_HEADERS = \
cky_base.h \
cky_card.h \
cky_factory.h \
cky_list.h \
cky_applet.h
noinst_HEADERS = \
cky_basei.h \
dynlink.h
#pcdir = $(libdir)/pkgconfig
#pc_DATA = libckyapplet.pc
--- NEW FILE Makefile.in ---
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# ***** BEGIN COPYRIGHT BLOCK *****
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
#
# 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 version
# 2.1 of the License.
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# ***** END COPYRIGHT BLOCK *****
# Process this file with automake to create Makefile.in
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = clib
DIST_COMMON = $(nobase_include_HEADERS) $(noinst_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libckyapplet_la_LIBADD =
am_libckyapplet_la_OBJECTS = libckyapplet_la-cky_applet.lo \
libckyapplet_la-cky_base.lo libckyapplet_la-cky_card.lo \
libckyapplet_la-cky_factory.lo libckyapplet_la-dynlink.lo
libckyapplet_la_OBJECTS = $(am_libckyapplet_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libckyapplet_la_SOURCES)
DIST_SOURCES = $(libckyapplet_la_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-exec-recursive install-info-recursive \
install-recursive installcheck-recursive installdirs-recursive \
pdf-recursive ps-recursive uninstall-info-recursive \
uninstall-recursive
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(includedir)"
nobase_includeHEADERS_INSTALL = $(install_sh_DATA)
HEADERS = $(nobase_include_HEADERS) $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
HAVE_PCSC_FALSE = @HAVE_PCSC_FALSE@
HAVE_PCSC_TRUE = @HAVE_PCSC_TRUE@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBCKYAPPLET = @LIBCKYAPPLET@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PCSC_CFLAGS = @PCSC_CFLAGS@
PCSC_LIBS = @PCSC_LIBS@
PKG_CONFIG = @PKG_CONFIG@
RANLIB = @RANLIB@
SCARD_LIB_NAME = @SCARD_LIB_NAME@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
SUBDIRS =
AM_CFLAGS =
# bleh what do I add just to get static but pic libraries?
noinst_LTLIBRARIES = libckyapplet.la
libckyapplet_la_SOURCES = \
cky_applet.c \
cky_base.c \
cky_card.c \
cky_factory.c \
dynlink.c
quote = \"
libckyapplet_la_LDFLAGS = -avoid-version
libckyapplet_la_CFLAGS = $(CFLAGS) -DSCARD_LIB_NAME=$(quote)$(SCARD_LIB_NAME)$(quote) $(PCSC_CFLAGS)
nobase_include_HEADERS = \
cky_base.h \
cky_card.h \
cky_factory.h \
cky_list.h \
cky_applet.h
noinst_HEADERS = \
cky_basei.h \
dynlink.h
all: all-recursive
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu clib/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu clib/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libckyapplet.la: $(libckyapplet_la_OBJECTS) $(libckyapplet_la_DEPENDENCIES)
$(LINK) $(libckyapplet_la_LDFLAGS) $(libckyapplet_la_OBJECTS) $(libckyapplet_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libckyapplet_la-cky_applet.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libckyapplet_la-cky_base.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libckyapplet_la-cky_card.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libckyapplet_la-cky_factory.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libckyapplet_la-dynlink.Plo at am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
libckyapplet_la-cky_applet.lo: cky_applet.c
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -MT libckyapplet_la-cky_applet.lo -MD -MP -MF "$(DEPDIR)/libckyapplet_la-cky_applet.Tpo" -c -o libckyapplet_la-cky_applet.lo `test -f 'cky_applet.c' || echo '$(srcdir)/'`cky_applet.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libckyapplet_la-cky_applet.Tpo" "$(DEPDIR)/libckyapplet_la-cky_applet.Plo"; else rm -f "$(DEPDIR)/libckyapplet_la-cky_applet.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cky_applet.c' object='libckyapplet_la-cky_applet.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -c -o libckyapplet_la-cky_applet.lo `test -f 'cky_applet.c' || echo '$(srcdir)/'`cky_applet.c
libckyapplet_la-cky_base.lo: cky_base.c
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -MT libckyapplet_la-cky_base.lo -MD -MP -MF "$(DEPDIR)/libckyapplet_la-cky_base.Tpo" -c -o libckyapplet_la-cky_base.lo `test -f 'cky_base.c' || echo '$(srcdir)/'`cky_base.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libckyapplet_la-cky_base.Tpo" "$(DEPDIR)/libckyapplet_la-cky_base.Plo"; else rm -f "$(DEPDIR)/libckyapplet_la-cky_base.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cky_base.c' object='libckyapplet_la-cky_base.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -c -o libckyapplet_la-cky_base.lo `test -f 'cky_base.c' || echo '$(srcdir)/'`cky_base.c
libckyapplet_la-cky_card.lo: cky_card.c
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -MT libckyapplet_la-cky_card.lo -MD -MP -MF "$(DEPDIR)/libckyapplet_la-cky_card.Tpo" -c -o libckyapplet_la-cky_card.lo `test -f 'cky_card.c' || echo '$(srcdir)/'`cky_card.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libckyapplet_la-cky_card.Tpo" "$(DEPDIR)/libckyapplet_la-cky_card.Plo"; else rm -f "$(DEPDIR)/libckyapplet_la-cky_card.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cky_card.c' object='libckyapplet_la-cky_card.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -c -o libckyapplet_la-cky_card.lo `test -f 'cky_card.c' || echo '$(srcdir)/'`cky_card.c
libckyapplet_la-cky_factory.lo: cky_factory.c
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -MT libckyapplet_la-cky_factory.lo -MD -MP -MF "$(DEPDIR)/libckyapplet_la-cky_factory.Tpo" -c -o libckyapplet_la-cky_factory.lo `test -f 'cky_factory.c' || echo '$(srcdir)/'`cky_factory.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libckyapplet_la-cky_factory.Tpo" "$(DEPDIR)/libckyapplet_la-cky_factory.Plo"; else rm -f "$(DEPDIR)/libckyapplet_la-cky_factory.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cky_factory.c' object='libckyapplet_la-cky_factory.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -c -o libckyapplet_la-cky_factory.lo `test -f 'cky_factory.c' || echo '$(srcdir)/'`cky_factory.c
libckyapplet_la-dynlink.lo: dynlink.c
@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -MT libckyapplet_la-dynlink.lo -MD -MP -MF "$(DEPDIR)/libckyapplet_la-dynlink.Tpo" -c -o libckyapplet_la-dynlink.lo `test -f 'dynlink.c' || echo '$(srcdir)/'`dynlink.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libckyapplet_la-dynlink.Tpo" "$(DEPDIR)/libckyapplet_la-dynlink.Plo"; else rm -f "$(DEPDIR)/libckyapplet_la-dynlink.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dynlink.c' object='libckyapplet_la-dynlink.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libckyapplet_la_CFLAGS) $(CFLAGS) -c -o libckyapplet_la-dynlink.lo `test -f 'dynlink.c' || echo '$(srcdir)/'`dynlink.c
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
install-nobase_includeHEADERS: $(nobase_include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(mkdir_p) "$(DESTDIR)$(includedir)"
@$(am__vpath_adj_setup) \
list='$(nobase_include_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
$(am__vpath_adj) \
echo " $(nobase_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
$(nobase_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
done
uninstall-nobase_includeHEADERS:
@$(NORMAL_UNINSTALL)
@$(am__vpath_adj_setup) \
list='$(nobase_include_HEADERS)'; for p in $$list; do \
$(am__vpath_adj) \
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
rm -f "$(DESTDIR)$(includedir)/$$f"; \
done
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(mkdir_p) "$(distdir)/$$subdir" \
|| exit 1; \
distdir=`$(am__cd) $(distdir) && pwd`; \
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
(cd $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$top_distdir" \
distdir="$$distdir/$$subdir" \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
info: info-recursive
info-am:
install-data-am: install-nobase_includeHEADERS
install-exec-am:
install-info: install-info-recursive
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-info-am uninstall-nobase_includeHEADERS
uninstall-info: uninstall-info-recursive
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
clean clean-generic clean-libtool clean-noinstLTLIBRARIES \
clean-recursive ctags ctags-recursive distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-recursive distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-nobase_includeHEADERS \
install-strip installcheck installcheck-am installdirs \
installdirs-am maintainer-clean maintainer-clean-generic \
maintainer-clean-recursive mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
uninstall-info-am uninstall-nobase_includeHEADERS
#pcdir = $(libdir)/pkgconfig
#pc_DATA = libckyapplet.pc
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
--- NEW FILE cky_applet.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include <stdio.h>
#include "cky_applet.h"
#define MIN(x, y) ((x) < (y) ? (x) : (y))
/*****************************************************************
*
* Generic factorys are used by the generic APDU processing
* to customize the formatting of APDU. Typically APDUs are formatted
* using parameterized calls of the form CKYAPDUFactory_ADPUNAME.
* The generic processing code, however needs calls with a common
* Signature. To accomplish the conversion, we build generic versions
* which take a void * parameter. Trivial APDU's can pass NULL or a pointer
* to the single parameter that they need. More complicated APDU's use
* CKYAppletArg* data structures defined above to pass more arguments.
*
* Generic factorys then call the standard CKYAPDUFactor_ADPUNAME() functions
* to build the APDUs. These functions are intended only as arguments
* to the generic ADPU calls, and not to be called directly.
*
*****************************************************************/
CKYStatus
CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_SelectFile(apdu,(const CKYBuffer *)param);
}
CKYStatus
CKYAppletFactory_SelectCardManager(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_SelectCardManager(apdu);
}
CKYStatus
CKYAppletFactory_GetCPLCData(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetCPLCData(apdu);
}
CKYStatus
CKYAppletFactory_ListKeys(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_ListKeys(apdu, *( CKYByte *)param);
}
CKYStatus
CKYAppletFactory_ComputeCryptInit(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
return CKYAPDUFactory_ComputeCryptInit(apdu, ccs->keyNumber, ccs->mode,
ccs->direction, ccs->location);
}
CKYStatus
CKYAppletFactory_ComputeCryptProcess(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
return CKYAPDUFactory_ComputeCryptProcess(apdu, ccs->keyNumber,
ccs->location, ccs->data);
}
CKYStatus
CKYAppletFactory_ComputeCryptFinal(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
return CKYAPDUFactory_ComputeCryptFinal(apdu, ccs->keyNumber,
ccs->location, ccs->data, ccs->sig);
}
CKYStatus
CKYAppletFactory_ComputeCryptOneStep(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgComputeCrypt *ccs=(const CKYAppletArgComputeCrypt *)param;
return CKYAPDUFactory_ComputeCryptOneStep(apdu, ccs->keyNumber,ccs->mode,
ccs->direction, ccs->location, ccs->data, ccs->sig);
}
CKYStatus
CKYAppletFactory_CreatePIN(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgCreatePIN *cps = (const CKYAppletArgCreatePIN *)param;
return CKYAPDUFactory_CreatePIN(apdu, cps->pinNumber, cps->maxAttempts,
cps->pinValue);
}
CKYStatus
CKYAppletFactory_VerifyPIN(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgVerifyPIN *vps = (const CKYAppletArgVerifyPIN *)param;
return CKYAPDUFactory_VerifyPIN(apdu, vps->pinNumber, vps->pinValue);
}
CKYStatus
CKYAppletFactory_ChangePIN(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgChangePIN *cps = (const CKYAppletArgChangePIN *)param;
return CKYAPDUFactory_ChangePIN(apdu, cps->pinNumber, cps->oldPin,
cps->newPin);
}
CKYStatus
CKYAppletFactory_ListPINs(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_ListPINs(apdu);
}
CKYStatus
CKYAppletFactory_Logout(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_Logout(apdu, *(const CKYByte *)param);
}
/* Future add WriteObject */
CKYStatus
CKYAppletFactory_CreateObject(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgCreateObject *cos=(const CKYAppletArgCreateObject *)param;
return CKYAPDUFactory_CreateObject(apdu, cos->objectID, cos->size,
cos->readACL, cos->writeACL, cos->deleteACL);
}
CKYStatus
CKYAppletFactory_DeleteObject(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgDeleteObject *dos=(const CKYAppletArgDeleteObject *)param;
return CKYAPDUFactory_DeleteObject(apdu, dos->objectID, dos->zero);
}
CKYStatus
CKYAppletFactory_ReadObject(CKYAPDU *apdu, const void *param)
{
const CKYAppletArgReadObject *ros = (const CKYAppletArgReadObject *)param;
return CKYAPDUFactory_ReadObject(apdu, ros->objectID,
ros->offset, ros->size);
}
CKYStatus
CKYAppletFactory_ListObjects(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_ListObjects(apdu, *(const CKYByte *)param);
}
CKYStatus
CKYAppletFactory_GetStatus(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetStatus(apdu);
}
CKYStatus
CKYAppletFactory_Noop(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_Noop(apdu);
}
CKYStatus
CKYAppletFactory_GetBuildID(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetBuildID(apdu);
}
CKYStatus
CKYAppletFactory_GetLifeCycle(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetLifeCycle(apdu);
}
CKYStatus
CKYAppletFactory_GetLifeCycleV2(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetLifeCycleV2(apdu);
}
CKYStatus
CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetRandom(apdu, *(CKYByte *)param);
}
CKYStatus
CKYAppletFactory_SeedRandom(CKYAPDU *apdu, const void *param)
{
const CKYBuffer *buf=(CKYBuffer *)param;
return CKYAPDUFactory_SeedRandom(apdu, buf);
}
CKYStatus
CKYAppletFactory_GetIssuerInfo(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetIssuerInfo(apdu);
}
CKYStatus
CKYAppletFactory_GetBuiltinACL(CKYAPDU *apdu, const void *param)
{
return CKYAPDUFactory_GetBuiltinACL(apdu);
}
CKYStatus
CACAppletFactory_SignDecrypt(CKYAPDU *apdu, const void *param)
{
const CKYBuffer *buf=(CKYBuffer *)param;
return CACAPDUFactory_SignDecrypt(apdu, buf);
}
CKYStatus
CACAppletFactory_VerifyPIN(CKYAPDU *apdu, const void *param)
{
const char *pin=(const char *)param;
return CACAPDUFactory_VerifyPIN(apdu, pin);
}
CKYStatus
CACAppletFactory_GetCertificate(CKYAPDU *apdu, const void *param)
{
CKYSize *size=(CKYSize*)param;
return CACAPDUFactory_GetCertificate(apdu, *size);
}
CKYStatus
CACAppletFactory_GetProperties(CKYAPDU *apdu, const void *param)
{
return CACAPDUFactory_GetProperties(apdu);
}
/*
* deprecates 0.x functions
*/
CKYStatus
CKYAppletFactory_LogoutAllV0(CKYAPDU *apdu, const void *param)
{
CKYByte data[2] = { 0, 0};
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_LOGOUT_ALL);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetSendData(apdu, data, sizeof(data));
}
/*****************************************************************
*
* Generic Fill routines used by several calls in common
* and globally accessible
*
*****************************************************************/
/* a null fill function for those APDU's which do not return data */
CKYStatus
CKYAppletFill_Null(const CKYBuffer *response, CKYSize size, void *param)
{
return CKYSUCCESS;
}
/* a Buffer Replace fill function for those APDU's which return unformated
* chunks of data */
CKYStatus
CKYAppletFill_ReplaceBuffer(const CKYBuffer *response, CKYSize size, void *param)
{
CKYBuffer *buf = (CKYBuffer *)param;
if (buf == NULL) {
return CKYSUCCESS;
}
return CKYBuffer_Replace(buf, 0, CKYBuffer_Data(response),
CKYBuffer_Size(response) -2);
}
/* a Buffer Append fill function. Can be used with any APDU that uses Buffer
* Replace. Repeated calls continuously fill the buffer. Most useful for read.
*/
CKYStatus
CKYAppletFill_AppendBuffer(const CKYBuffer *response, CKYSize size, void *param)
{
CKYBuffer *buf = (CKYBuffer *)param;
return CKYBuffer_AppendData(buf, CKYBuffer_Data(response),
CKYBuffer_Size(response) -2);
}
CKYStatus
CKYAppletFill_Byte(const CKYBuffer *response, CKYSize size, void *param)
{
CKYByte *v = (CKYByte *)param;
*v = CKYBuffer_GetChar(response, 0);
return CKYSUCCESS;
}
CKYStatus
CKYAppletFill_Short(const CKYBuffer *response, CKYSize size, void *param)
{
unsigned short *v = (unsigned short *)param;
*v = CKYBuffer_GetShort(response, 0);
return CKYSUCCESS;
}
CKYStatus
CKYAppletFill_Long(const CKYBuffer *response, CKYSize size, void *param)
{
unsigned long *v = (unsigned long *)param;
*v = CKYBuffer_GetLong(response, 0);
return CKYSUCCESS;
}
/*****************************************************************
*
* Utilities shared by all the fetch Cards.
*
*****************************************************************/
/*
* verify the we got a successful response. Responses should include
* the expected data returned plus a 2 byte return code. This return
* code should be 0x9000 on success.
*/
CKYBool
CKYApplet_VerifyResponse(const CKYBuffer *buf, CKYSize dataSize,
CKYISOStatus *apduRC) {
CKYSize size = CKYBuffer_Size(buf);
CKYISOStatus rc = CKYISO_INVRESPONSE;
CKYBool valid = 0;
/* is there enough size for the return code ? */
if (size < 2) {
goto done;
}
/* fetch the data */
rc = CKYBuffer_GetShort(buf, size-2);
/* is there enough size for the expected data ? */
if ((dataSize != CKY_SIZE_UNKNOWN) && (size != dataSize+2)) {
goto done;
}
/* did we return successfully? */
valid = (rc == CKYISO_SUCCESS) || ((rc & CKYISO_MORE_MASK) == CKYISO_MORE);
done:
if (apduRC) {
*apduRC = rc;
}
return valid;
}
/*
* most commands have identical operations. Isolate the differences in
* call back functions, and create a generic APDU handler which Creates
* APDU's, Does the exchange, and fills in the results.
*/
CKYStatus
CKYApplet_HandleAPDU(CKYCardConnection *conn,
CKYAppletFactory afFunc, const void *afArg,
const CKYBuffer *nonce, CKYSize size,
CKYFillFunction fillFunc, void *fillArg, CKYISOStatus *apduRC)
{
CKYAPDU apdu;
CKYBuffer response;
CKYStatus ret;
if (apduRC) {
*apduRC = CKYISO_NORESPONSE;
}
/* initialize the response and APDU buffers */
CKYBuffer_InitEmpty(&response);
ret = CKYAPDU_Init(&apdu);
if (ret != CKYSUCCESS) {
goto done;
}
/* fill in the APDU buffer with the correct values */
ret = (*afFunc)(&apdu, afArg);
if (ret != CKYSUCCESS) {
goto done;
}
/* if NONCE supplied, add it to the end of the apdu */
if (nonce) {
/*
* Local Secured commands need the nonce returned from Login to
* verify that they are valid. Nonce's are just added to the end
* of the APDU much like
*/
ret = CKYAPDU_AppendSendDataBuffer(&apdu, nonce);
if (ret != CKYSUCCESS) {
goto done;
}
}
/* send it to the card */
ret = CKYCardConnection_ExchangeAPDU(conn, &apdu, &response);
if (ret != CKYSUCCESS) {
goto done;
}
/* verify we got the expected response */
if (!CKYApplet_VerifyResponse(&response, size, apduRC)) {
ret = CKYAPDUFAIL;
goto done;
}
/* Fill in our output data structure */
ret = (*fillFunc)(&response, size, fillArg);
done:
CKYBuffer_FreeData(&response);
CKYAPDU_FreeData(&apdu);
return ret;
}
/*****************************************************************
*
* The following convience functions convert APDU calls
* into function calls, with input and output parameters.
* The application is still responsible for 1) creating a connection
* to the card, 2) Getting a tranaction long, then 3) selecting
* the appropriate applet (or Card manager). Except for those
* calls that have been noted, the appropriate applet is the CoolKey
* applet.
*
*****************************************************************/
/*
* Select an applet. Must happen after we start a transaction and before
* we issue any applet specific command.
*/
CKYStatus
CKYApplet_SelectFile(CKYCardConnection *conn, const CKYBuffer *AID,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, AID, NULL,
0, CKYAppletFill_Null, NULL, apduRC);
}
static CKYByte coolkeyid[] = {0x62, 0x76, 0x01, 0xff, 0x00, 0x00, 0x00 };
/*
* Select the CoolKey applet. Must happen after we start a transaction and
* before we issue any applet specific command.
*/
CKYStatus
CKYApplet_SelectCoolKeyManager(CKYCardConnection *conn, CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYBuffer COOLKEYAID;
CKYBuffer_InitFromData(&COOLKEYAID, coolkeyid, sizeof(coolkeyid));
ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &COOLKEYAID,
NULL, 0, CKYAppletFill_Null, NULL, apduRC);
CKYBuffer_FreeData(&COOLKEYAID);
return ret;
}
static CKYByte CACPKIid[] = {0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
/*
* Select the CoolKey applet. Must happen after we start a transaction and
* before we issue any applet specific command.
*/
CKYStatus
CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance,
CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYBuffer CACPKIAID;
CKYBuffer_InitFromData(&CACPKIAID, CACPKIid, sizeof(CACPKIid));
CKYBuffer_SetChar(&CACPKIAID, 6, instance);
ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CACPKIAID,
NULL, CKY_SIZE_UNKNOWN, CKYAppletFill_Null, NULL, apduRC);
CKYBuffer_FreeData(&CACPKIAID);
return ret;
}
/*
* Select the card manager. Must happen after we start a transaction and before
* we issue any card manager commands.
*/
CKYStatus
CKYApplet_SelectCardManager(CKYCardConnection *conn, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectCardManager, NULL,
NULL, 0, CKYAppletFill_Null, NULL, apduRC);
}
static CKYByte cacmgrid[] = {0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
CKYStatus
CACApplet_SelectCardManager(CKYCardConnection *conn, CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYBuffer CAC_CM_AID;
CKYBuffer_InitFromData(&CAC_CM_AID, cacmgrid, sizeof(cacmgrid));
ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_SelectFile, &CAC_CM_AID,
NULL, 0, CKYAppletFill_Null, NULL, apduRC);
CKYBuffer_FreeData(&CAC_CM_AID);
return ret;
}
/*
* GetCPLC cluster -- must be called with CM selected
*/
static CKYStatus
ckyAppletFill_GetCPLCData(const CKYBuffer *response, CKYSize size, void *param)
{
CKYAppletRespGetCPLCData *gcdp = (CKYAppletRespGetCPLCData *)param;
gcdp->CPLCtag = CKYBuffer_GetShort(response, 0);
gcdp->length = CKYBuffer_GetChar(response, 2);
gcdp->fabricator = CKYBuffer_GetShort(response, 3);
gcdp->romType = CKYBuffer_GetShort(response, 5);
gcdp->romOSID = CKYBuffer_GetShort(response, 7);
gcdp->romOSDate = CKYBuffer_GetShort(response, 9);
gcdp->romOSLevel = CKYBuffer_GetShort(response, 11);
gcdp->eepromFabricationDate = CKYBuffer_GetShort(response, 13);
gcdp->eepromSerialNumber = CKYBuffer_GetLong(response, 15);
gcdp->eepromBatchID = CKYBuffer_GetShort(response, 19);
gcdp->eepromModuleFabricator = CKYBuffer_GetShort(response, 21);
gcdp->eepromModuleDate = CKYBuffer_GetShort(response, 23);
gcdp->eepromICManufacturer = CKYBuffer_GetShort(response, 25);
gcdp->eepromEmbeddingDate = CKYBuffer_GetShort(response, 27);
gcdp->eepromPrePersonalizer = CKYBuffer_GetShort(response, 29);
gcdp->eepromPrePersonalizeDate = CKYBuffer_GetShort(response, 31);
gcdp->eepromPrePersonalizeID = CKYBuffer_GetLong(response, 33);
gcdp->eepromPersonalizer = CKYBuffer_GetShort(response, 37);
gcdp->eepromPersonalizeDate = CKYBuffer_GetShort(response, 39);
gcdp->eepromPersonalizeID = CKYBuffer_GetLong(response, 41);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetCPLCData(CKYCardConnection *conn, CKYAppletRespGetCPLCData *cplc,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetCPLCData, NULL, NULL,
CKY_SIZE_GET_CPLCDATA, ckyAppletFill_GetCPLCData, cplc, apduRC);
}
/*
* Get CUID. The CUID exists in the CPLC data. We use the same basic
* APDU, but use a differ fill function to collect it.
*/
static CKYStatus
ckyAppletFill_GetCUID(const CKYBuffer *response, CKYSize size, void *param)
{
CKYBuffer *cuid = (CKYBuffer *)param;
CKYStatus ret;
ret = CKYBuffer_Resize(cuid,10);
if (ret != CKYSUCCESS) {
return ret;
}
/* fabricator 2 bytes */
CKYBuffer_SetChar(cuid, 0, CKYBuffer_GetChar(response, 3));
CKYBuffer_SetChar(cuid, 1, CKYBuffer_GetChar(response, 4));
/* IC Type 2 bytes */
CKYBuffer_SetChar(cuid, 2, CKYBuffer_GetChar(response, 5));
CKYBuffer_SetChar(cuid, 3, CKYBuffer_GetChar(response, 6));
/* Batch ID 2 bytes */
CKYBuffer_SetChar(cuid, 4, CKYBuffer_GetChar(response, 19));
CKYBuffer_SetChar(cuid, 5, CKYBuffer_GetChar(response, 20));
/* IC Serial Number 4 bytes */
CKYBuffer_SetChar(cuid, 6, CKYBuffer_GetChar(response, 15));
CKYBuffer_SetChar(cuid, 7, CKYBuffer_GetChar(response, 16));
CKYBuffer_SetChar(cuid, 8, CKYBuffer_GetChar(response, 17));
CKYBuffer_SetChar(cuid, 9, CKYBuffer_GetChar(response, 18));
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetCUID(CKYCardConnection *conn, CKYBuffer *cuid, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetCPLCData, NULL, NULL,
CKY_SIZE_GET_CPLCDATA, ckyAppletFill_GetCUID, cuid, apduRC);
}
/*
* Get MSN. The MSN exists in the CPLC data. We use the same basic
* APDU, but use a differ fill function to collect it.
*/
static CKYStatus
ckyAppletFill_GetMSN(const CKYBuffer *response, CKYSize size, void *param)
{
unsigned long *msn = (unsigned long *)param;
*msn = CKYBuffer_GetLong(response, 41);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetMSN(CKYCardConnection *conn, unsigned long *msn,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetCPLCData, NULL, NULL,
CKY_SIZE_GET_CPLCDATA, ckyAppletFill_GetMSN, msn, apduRC);
}
/*
* ListKeys cluster
*/
static CKYStatus
ckyAppletFill_ListKeys(const CKYBuffer *response, CKYSize size, void *param)
{
CKYAppletRespListKeys *lkp = (CKYAppletRespListKeys *)param;
lkp->keyNum = CKYBuffer_GetChar(response, 0);
lkp->keyType = CKYBuffer_GetChar(response, 1);
lkp->keyPartner = CKYBuffer_GetChar(response, 2);
lkp->keySize = CKYBuffer_GetShort(response, 3);
lkp->readACL = CKYBuffer_GetShort(response, 5);
lkp->writeACL = CKYBuffer_GetShort(response, 7);
lkp->useACL = CKYBuffer_GetShort(response, 9);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_ListKeys(CKYCardConnection *conn, CKYByte seq,
CKYAppletRespListKeys *lkp, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ListKeys, &seq, NULL,
CKY_SIZE_LIST_KEYS, ckyAppletFill_ListKeys, lkp, apduRC);
}
/*
* Compute Crypt Cluster.
*
* Compute Crypt takes 3 types: Init, Process, Final.
*
*/
CKYStatus
CKYApplet_ComputeCryptInit(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte mode, CKYByte direction, CKYByte location,
const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgComputeCrypt ccd;
ccd.keyNumber = keyNumber;
ccd.mode = mode;
ccd.direction = direction;
ccd.location = location;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptInit, &ccd,
nonce, 0, CKYAppletFill_Null, NULL, apduRC);
}
CKYStatus
CKYApplet_ComputeCryptProcess(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data,
const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgComputeCrypt ccd;
ccd.keyNumber = keyNumber;
ccd.location = location;
ccd.data = data;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptProcess, &ccd,
nonce, 0, CKYAppletFill_Null, NULL, apduRC);
}
/* computeCrypt returns data in the form :
* len: short
* data: byte[len]
* This fill routine returns A buffer with a copy of data and a length of len */
static CKYStatus
ckyAppletFill_ComputeCryptFinal(const CKYBuffer *response,
CKYSize size, void *param)
{
CKYBuffer *cbuf = (CKYBuffer *)param;
CKYSize respSize = CKYBuffer_Size(response);
CKYSize dataLen;
if (cbuf == 0) {
return CKYSUCCESS; /* app didn't want the result */
}
/* data response code + length code */
if (respSize < 4) {
return CKYAPDUFAIL;
}
dataLen = CKYBuffer_GetShort(response, 0);
if (dataLen > (respSize-4)) {
return CKYAPDUFAIL;
}
return CKYBuffer_Replace(cbuf, 0, CKYBuffer_Data(response)+2, dataLen);
}
CKYStatus
CKYApplet_ComputeCryptFinal(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data, CKYBuffer *sig, CKYBuffer *result,
const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgComputeCrypt ccd;
ccd.keyNumber = keyNumber;
ccd.location = location;
ccd.data = data;
ccd.data = sig;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ComputeCryptFinal, &ccd,
nonce, CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal, result, apduRC);
}
/*
* do a complete ComputeCrypt operation
* ...look to data size to see if we should read/write the data to
* the on card buffer. (future)
*/
CKYStatus
CKYApplet_ComputeCrypt(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte mode, CKYByte direction, const CKYBuffer *data, CKYBuffer *sig,
CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYAppletArgComputeCrypt ccd;
CKYBuffer empty;
CKYISOStatus status;
int use2APDUs = 0;
CKYBuffer_InitEmpty(&empty);
ccd.keyNumber = keyNumber;
ccd.mode = mode;
ccd.direction = direction;
ccd.location = CKY_DL_APDU;
if (!apduRC)
apduRC = &status;
if (mode == CKY_RSA_NO_PAD) {
ccd.data = data;
ccd.sig = sig;
ret = CKYApplet_HandleAPDU(conn,
CKYAppletFactory_ComputeCryptOneStep, &ccd, nonce,
CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal,
result, apduRC);
if (ret == CKYAPDUFAIL && *apduRC == CKYISO_INCORRECT_P2) {
use2APDUs = 1; /* maybe it's an old applet */
}
} else {
use2APDUs = 1;
}
if (use2APDUs) {
/* future, if data is to big write it to the internal object
* and set location to DL_OBJECT */
ccd.data = ∅
ccd.sig = sig;
ret = CKYApplet_HandleAPDU(conn,
CKYAppletFactory_ComputeCryptInit, &ccd, nonce,
0, CKYAppletFill_Null, NULL, apduRC);
if (ret == CKYSUCCESS) {
ccd.data = data;
ret = CKYApplet_HandleAPDU(conn,
CKYAppletFactory_ComputeCryptFinal, &ccd, nonce,
CKY_SIZE_UNKNOWN, ckyAppletFill_ComputeCryptFinal,
result, apduRC);
}
}
return ret;
}
/*
* do a CAC Sign/Decrypt
*/
CKYStatus
CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data,
CKYBuffer *result, CKYISOStatus *apduRC)
{
CKYStatus ret;
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_SignDecrypt, data, NULL,
CKYBuffer_Size(data), CKYAppletFill_ReplaceBuffer,
result, apduRC);
return ret;
}
/*
* do a CAC VerifyPIN
*/
CKYStatus
CACApplet_VerifyPIN(CKYCardConnection *conn, const char *pin,
CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYISOStatus status;
if (apduRC == NULL) {
apduRC = &status;
}
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_VerifyPIN, pin, NULL,
0, CKYAppletFill_Null,
NULL, apduRC);
/* it's unfortunate that the same code that means 'more data to follow' for
* GetCertificate also means, auth failure, you only have N more attempts
* left in the verify PIN call */
if ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
ret = CKYAPDUFAIL;
}
return ret;
}
/*
* Get a CAC Certificate
*/
CKYStatus
CACApplet_GetCertificate(CKYCardConnection *conn, CKYBuffer *cert,
CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYISOStatus status;
CKYSize size = 100;
CKYBuffer_Resize(cert,0);
if (apduRC == NULL) {
apduRC = &status;
}
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_GetCertificate, &size, NULL,
CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
apduRC);
while ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
size = *apduRC & ~CKYISO_MORE_MASK;
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_GetCertificate, &size, NULL,
CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
apduRC);
}
return ret;
}
CKYStatus
CACApplet_GetCertificateFirst(CKYCardConnection *conn, CKYBuffer *cert,
CKYSize *nextSize, CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYISOStatus status;
CKYSize size = 100;
CKYBuffer_Resize(cert,0);
if (apduRC == NULL) {
apduRC = &status;
}
*nextSize = 0;
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_GetCertificate, &size, NULL,
CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
apduRC);
if ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
*nextSize = *apduRC & ~CKYISO_MORE_MASK;
}
return ret;
}
CKYStatus
CACApplet_GetCertificateAppend(CKYCardConnection *conn, CKYBuffer *cert,
CKYSize nextSize, CKYISOStatus *apduRC)
{
CKYStatus ret;
CKYISOStatus status;
CKYSize size = nextSize;
if (apduRC == NULL) {
apduRC = &status;
}
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_GetCertificate, &size, NULL,
CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
apduRC);
while ((*apduRC & CKYISO_MORE_MASK) == CKYISO_MORE) {
size = *apduRC & ~CKYISO_MORE_MASK;
ret = CKYApplet_HandleAPDU(conn,
CACAppletFactory_GetCertificate, &size, NULL,
CKY_SIZE_UNKNOWN, CKYAppletFill_AppendBuffer, cert,
apduRC);
}
return ret;
}
/*
* PIN cluster
*/
CKYStatus
CKYApplet_CreatePIN(CKYCardConnection *conn, CKYByte pinNumber,
CKYByte maxAttempts, const char *pinValue,
const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgCreatePIN cpd;
cpd.pinValue = pinValue;
cpd.maxAttempts = maxAttempts;
cpd.pinValue = pinValue;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_CreatePIN, &cpd, nonce,
0, CKYAppletFill_Null, NULL, apduRC);
}
CKYStatus
CKYApplet_VerifyPIN(CKYCardConnection *conn, CKYByte pinNumber,
const char *pinValue, CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgVerifyPIN vpd;
vpd.pinValue = pinValue;
vpd.pinNumber = pinNumber;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_VerifyPIN, &vpd, NULL,
8, CKYAppletFill_ReplaceBuffer, nonce, apduRC);
}
CKYStatus
CKYApplet_ChangePIN(CKYCardConnection *conn, const char *oldPin,
const char *newPin, const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgChangePIN cpd;
cpd.oldPin = oldPin;
cpd.newPin = newPin;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ChangePIN, &cpd, nonce,
0, CKYAppletFill_Null, NULL, apduRC);
}
CKYStatus
CKYApplet_ListPINs(CKYCardConnection *conn, unsigned short *pins,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ListPINs, NULL, NULL,
CKY_SIZE_LIST_PINS, CKYAppletFill_Short, pins, apduRC);
}
CKYStatus
CKYApplet_Logout(CKYCardConnection *conn, CKYByte pinNumber,
const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_Logout, &pinNumber, nonce,
0, CKYAppletFill_Null, NULL, apduRC);
}
CKYStatus
CKYApplet_CreateObject(CKYCardConnection *conn, unsigned long objectID,
CKYSize size, unsigned short readACL, unsigned short writeACL,
unsigned short deleteACL, const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgCreateObject cod;
cod.objectID = objectID;
cod.size = size;
cod.readACL = readACL;
cod.writeACL = writeACL;
cod.deleteACL = deleteACL;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_CreateObject, &cod,
nonce, 0, CKYAppletFill_Null, NULL, apduRC);
}
CKYStatus
CKYApplet_DeleteObject(CKYCardConnection *conn, unsigned long objectID,
CKYByte zero, const CKYBuffer *nonce, CKYISOStatus *apduRC)
{
CKYAppletArgDeleteObject dod;
dod.objectID = objectID;
dod.zero = zero;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_DeleteObject, &dod,
nonce, 0, CKYAppletFill_Null, NULL, apduRC);
}
/*
* Read Object cluster...
* This is the raw version that goes issues a single APDU.
*/
CKYStatus
CKYApplet_ReadObject(CKYCardConnection *conn, unsigned long objectID,
CKYOffset offset, CKYByte size, const CKYBuffer *nonce,
CKYBuffer *data, CKYISOStatus *apduRC)
{
CKYAppletArgReadObject rod;
rod.objectID = objectID;
rod.offset = offset;
rod.size = size;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ReadObject, &rod, nonce,
size, CKYAppletFill_ReplaceBuffer, data, apduRC);
}
/*
* Read Object Append cluster...
* This is also issues a single APDU, but appends the resulting data
* to an existing buffer.
*/
CKYStatus
CKYApplet_ReadObjectAppend(CKYCardConnection *conn, unsigned long objectID,
CKYOffset offset, CKYByte size, const CKYBuffer *nonce,
CKYBuffer *data, CKYISOStatus *apduRC)
{
CKYAppletArgReadObject rod;
rod.objectID = objectID;
rod.offset = offset;
rod.size = size;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ReadObject, &rod, nonce,
size, CKYAppletFill_AppendBuffer, data, apduRC);
}
/*
* Read Object
* This is makes multiple APDU calls to read the entire object.
*/
CKYStatus
CKYApplet_ReadObjectFull(CKYCardConnection *conn, unsigned long objectID,
CKYOffset offset, CKYSize size, const CKYBuffer *nonce,
CKYBuffer *data, CKYISOStatus *apduRC)
{
CKYAppletArgReadObject rod;
CKYStatus ret = CKYSUCCESS;
rod.objectID = objectID;
rod.offset = offset;
do {
rod.size = (CKYByte) MIN(size, CKY_MAX_READ_CHUNK_SIZE);
ret = CKYApplet_HandleAPDU(conn, CKYAppletFactory_ReadObject, &rod,
nonce, rod.size, CKYAppletFill_AppendBuffer, data, apduRC);
size -= rod.size;
rod.offset += rod.size;
} while ((size > 0) && (ret == CKYSUCCESS));
return ret;
}
/*
* List Object cluster
*/
static CKYStatus
ckyAppletFill_ListObjects(const CKYBuffer *response, CKYSize size, void *param)
{
CKYAppletRespListObjects *lop = (CKYAppletRespListObjects *)param;
lop->objectID = CKYBuffer_GetLong(response, 0);
lop->objectSize = CKYBuffer_GetLong(response, 4);
lop->readACL = CKYBuffer_GetShort(response, 8);
lop->writeACL = CKYBuffer_GetShort(response, 10);
lop->deleteACL = CKYBuffer_GetShort(response, 12);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_ListObjects(CKYCardConnection *conn, CKYByte seq,
CKYAppletRespListObjects *lop, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_ListObjects, &seq, NULL,
CKY_SIZE_LIST_OBJECTS, ckyAppletFill_ListObjects, lop, apduRC);
}
/*
* GetStatus cluster
*/
static CKYStatus
ckyAppletFill_GetStatus(const CKYBuffer *response, CKYSize size, void *param)
{
CKYAppletRespGetStatus *gsp = (CKYAppletRespGetStatus *)param;
gsp->protocolMajorVersion = CKYBuffer_GetChar(response, 0);
gsp->protocolMinorVersion = CKYBuffer_GetChar(response, 1);
gsp->appletMajorVersion = CKYBuffer_GetChar(response, 2);
gsp->appletMinorVersion = CKYBuffer_GetChar(response, 3);
gsp->totalObjectMemory = CKYBuffer_GetLong(response, 4);
gsp->freeObjectMemory = CKYBuffer_GetLong(response, 8);
gsp->numberPins = CKYBuffer_GetChar(response, 12);
gsp->numberKeys = CKYBuffer_GetChar(response, 13);
gsp->loggedInMask = CKYBuffer_GetShort(response, 14);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetStatus(CKYCardConnection *conn, CKYAppletRespGetStatus *status,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetStatus, NULL, NULL,
CKY_SIZE_GET_STATUS, ckyAppletFill_GetStatus, status, apduRC);
}
CKYStatus
CKYApplet_Noop(CKYCardConnection *conn, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_Noop, NULL, NULL,
0, CKYAppletFill_Null, NULL, apduRC);
}
CKYStatus
CKYApplet_GetBuildID(CKYCardConnection *conn, unsigned long *buildID,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetBuildID, NULL, NULL,
CKY_SIZE_GET_BUILDID, CKYAppletFill_Long, buildID, apduRC);
}
/*
* GetLifeCycle cluster
*/
static CKYStatus
ckyAppletFill_GetLifeCycle(const CKYBuffer *response, CKYSize size, void *param)
{
*(CKYByte *)param= CKYBuffer_GetChar(response,0);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetLifeCycle(CKYCardConnection *conn, CKYByte *personalized,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetLifeCycle, NULL, NULL,
CKY_SIZE_GET_LIFE_CYCLE, ckyAppletFill_GetLifeCycle, personalized, apduRC);
}
static CKYStatus
ckyAppletFill_GetLifeCycleV2(const CKYBuffer *response, CKYSize size, void *param)
{
CKYAppletRespGetLifeCycleV2 *ext = (CKYAppletRespGetLifeCycleV2 *) param;
ext->lifeCycle = CKYBuffer_GetChar(response,0);
ext->pinCount = CKYBuffer_GetChar(response,1);
ext->protocolMajorVersion = CKYBuffer_GetChar(response,2);
ext->protocolMinorVersion = CKYBuffer_GetChar(response,3);
return CKYSUCCESS;
}
/*
* GetStatus cluster
*/
static CKYStatus
ckyAppletFill_LifeCycleStatus(const CKYBuffer *response, CKYSize size, void *param)
{
CKYAppletRespGetLifeCycleV2 *ext = (CKYAppletRespGetLifeCycleV2 *) param;
ext->pinCount = CKYBuffer_GetChar(response,12);
ext->protocolMajorVersion = CKYBuffer_GetChar(response,0);
ext->protocolMinorVersion = CKYBuffer_GetChar(response,1);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetLifeCycleV2(CKYCardConnection *conn,
CKYAppletRespGetLifeCycleV2 *ext, CKYISOStatus *apduRC)
{
CKYStatus status;
status = CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetLifeCycleV2,
NULL,NULL, CKY_SIZE_GET_LIFE_CYCLE_V2, ckyAppletFill_GetLifeCycleV2,
ext, apduRC);
/* Get Life Cycle Version 2 is a new APDU with combines data from
* two other APDUs. Older tokens don't have this APDU, so use
* the old method to get the data */
if (status == CKYAPDUFAIL) {
status = CKYApplet_GetLifeCycle(conn,&ext->lifeCycle, apduRC);
if (status != CKYSUCCESS) {
return status;
}
status = CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetStatus, NULL,
NULL, CKY_SIZE_GET_STATUS, ckyAppletFill_LifeCycleStatus, ext, apduRC);
}
return status;
}
/*
* GetBuiltin cluster
*/
static CKYStatus
ckyAppletFill_GetBuiltinACL(const CKYBuffer *response,CKYSize size,void *param)
{
CKYAppletRespGetBuiltinACL *gba = (CKYAppletRespGetBuiltinACL *) param;
gba->create_object_ACL = CKYBuffer_GetShort(response,0);
gba->create_object_ACL = CKYBuffer_GetShort(response,2);
gba->create_object_ACL = CKYBuffer_GetShort(response,4);
gba->enable_ACL_change = CKYBuffer_GetChar(response,6);
return CKYSUCCESS;
}
CKYStatus
CKYApplet_GetBuiltinACL(CKYCardConnection *conn,
CKYAppletRespGetBuiltinACL *gba, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetBuiltinACL, NULL,
NULL, CKY_SIZE_GET_BUILTIN_ACL, ckyAppletFill_GetBuiltinACL, gba,
apduRC);
}
CKYStatus
CKYApplet_GetIssuerInfo(CKYCardConnection *conn, CKYBuffer *info,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetIssuerInfo, NULL,
NULL, CKY_SIZE_GET_ISSUER_INFO, CKYAppletFill_ReplaceBuffer,
info, apduRC);
}
CKYStatus
CKYApplet_GetRandom(CKYCardConnection *conn, CKYBuffer *data, CKYByte len,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetRandom, &len,
NULL, len, CKYAppletFill_ReplaceBuffer, data, apduRC);
}
CKYStatus
CKYApplet_GetRandomAppend(CKYCardConnection *conn, CKYBuffer *data, CKYByte len,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_GetRandom, &len,
NULL, len, CKYAppletFill_AppendBuffer, data, apduRC);
}
CKYStatus
CKYApplet_SeedRandom(CKYCardConnection *conn, const CKYBuffer *data,
CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_SeedRandom, data,
NULL, 0, CKYAppletFill_Null, NULL, apduRC);
}
/*
* deprecates 0.x functions
*/
/* old applet verify pin call (no nonce returned) */
CKYStatus
CKYApplet_VerifyPinV0(CKYCardConnection *conn, CKYByte pinNumber,
const char *pinValue, CKYISOStatus *apduRC)
{
CKYAppletArgVerifyPIN vpd;
vpd.pinValue = pinValue;
vpd.pinNumber = pinNumber;
vpd.pinValue = pinValue;
vpd.pinNumber = pinNumber;
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_VerifyPIN, &vpd, NULL,
0, CKYAppletFill_Null, NULL, apduRC);
}
/* logout all */
CKYStatus
CKYApplet_LogoutAllV0(CKYCardConnection *conn, CKYISOStatus *apduRC)
{
return CKYApplet_HandleAPDU(conn, CKYAppletFactory_LogoutAllV0, NULL, NULL,
0, CKYAppletFill_Null, NULL, apduRC);
}
--- NEW FILE cky_applet.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_APPLET_H
#define CKY_APPLET_H 1
#include "cky_base.h"
#include "cky_card.h"
#include "cky_factory.h"
/*
* base typdefs
*/
/*
* ISO and applet response codes.
*/
typedef unsigned short CKYISOStatus; /* applet return status */
/* Psuedo return codes created by the library software */
#define CKYISO_INVRESPONSE 0xffff /* code returned by library to
* indicate no valid response
* received */
#define CKYISO_NORESPONSE 0x0000 /* code returned by the library if
* operation failed before
* attempting to read a response */
/* ISO defined Return codes */
#define CKYISO_SUCCESS 0x9000 /* SUCCESS! */
#define CKYISO_MORE_MASK 0xff00 /* More data mask */
#define CKYISO_MORE 0x6300 /* More data available */
#define CKYISO_DATA_INVALID 0x6984
/* Applet Defined Return codes */
#define CKYISO_NO_MEMORY_LEFT 0x9c01 /* There have been memory
* problems on the card */
#define CKYISO_AUTH_FAILED 0x9c02 /* Entered PIN is not correct */
#define CKYISO_OPERATION_NOT_ALLOWED 0x9c03 /* Required operation is not
* allowed in actual
* circumstances */
#define CKYISO_UNSUPPORTED_FEATURE 0x9c05 /* Required feature is not (yet)
* supported */
#define CKYISO_UNAUTHORIZED 0x9c06 /* Required operation was not
* authorized because of a lack of
* privileges */
#define CKYISO_OBJECT_NOT_FOUND 0x9c07 /* Required object is missing */
#define CKYISO_OBJECT_EXISTS 0x9c08 /* New object ID already in use */
#define CKYISO_INCORRECT_ALG 0x9c09 /* Algorithm specified is not
* correct */
#define CKYISO_SIGNATURE_INVALID 0x9c0b /* Verify operation detected an
* invalid signature */
#define CKYISO_IDENTITY_BLOCKED 0x9c0c /* Operation has been blocked for
* security reason */
#define CKYISO_INVALID_PARAMETER 0x9c0f /* Invalid input parameter to
* command */
#define CKYISO_INCORRECT_P1 0x9c10 /* Incorrect P1 parameter */
#define CKYISO_INCORRECT_P2 0x9c11 /* Incorrect P2 parameter */
#define CKYISO_SEQUENCE_END 0x9c12 /* No more data available */
#define CKYISO_INTERNAL_ERROR 0x9cff /* Reserved for debugging,
* shouldn't happen */
/*
* Pin Constants as used by our applet
*/
#define CKY_OLD_USER_PIN_NUM 1 /* version 0 and earlier */
#define CKY_USER_PIN_NUM 0
/*
* special size that tells the Verify Function not to verify the size because
* the ADPU can return variable size.
*/
#define CKY_SIZE_UNKNOWN 0xffffffff
/*
* structures for returning Applet responses
*/
typedef struct _CKYAppletRespGetStatus {
CKYByte protocolMajorVersion;
CKYByte protocolMinorVersion;
CKYByte appletMajorVersion;
CKYByte appletMinorVersion;
unsigned long totalObjectMemory;
unsigned long freeObjectMemory;
CKYByte numberPins;
CKYByte numberKeys;
unsigned short loggedInMask;
} CKYAppletRespGetStatus;
typedef struct _CKYAppletRespGetLifeCycleV2 {
CKYByte lifeCycle;
CKYByte pinCount;
CKYByte protocolMajorVersion;
CKYByte protocolMinorVersion;
} CKYAppletRespGetLifeCycleV2;
typedef struct _CKYAppletRespGetBuiltinACL {
unsigned short create_object_ACL;
unsigned short create_key_ACL;
unsigned short create_pin_ACL;
CKYByte enable_ACL_change;
} CKYAppletRespGetBuiltinACL;
typedef struct _CKYAppletRespGetCPLCData {
unsigned short CPLCtag;
CKYByte length;
unsigned short fabricator;
unsigned short romType;
unsigned short romOSID;
unsigned short romOSDate;
unsigned short romOSLevel;
unsigned short eepromFabricationDate;
unsigned long eepromSerialNumber;
unsigned short eepromBatchID;
unsigned short eepromModuleFabricator;
unsigned short eepromModuleDate;
unsigned short eepromICManufacturer;
unsigned short eepromEmbeddingDate;
unsigned short eepromPrePersonalizer;
unsigned short eepromPrePersonalizeDate;
unsigned long eepromPrePersonalizeID;
unsigned short eepromPersonalizer;
unsigned short eepromPersonalizeDate;
unsigned long eepromPersonalizeID;
} CKYAppletRespGetCPLCData;
typedef struct _CKYAppletRespListObjects {
unsigned long objectID;
CKYSize objectSize;
unsigned short readACL;
unsigned short writeACL;
unsigned short deleteACL;
} CKYAppletRespListObjects;
typedef struct _CKYAppletRespListKeys {
CKYByte keyNum;
CKYByte keyType;
CKYByte keyPartner;
unsigned short keySize;
unsigned short readACL;
unsigned short writeACL;
unsigned short useACL;
} CKYAppletRespListKeys;
/*
* structures for the generic factories
*/
typedef struct _CKYAppletArgCreatePIN {
const char *pinValue;
CKYByte pinNumber;
CKYByte maxAttempts;
} CKYAppletArgCreatePIN;
typedef struct _CKYAppletArgVerifyPIN {
const char *pinValue;
CKYByte pinNumber;
} CKYAppletArgVerifyPIN;
typedef struct _CKYAppletArgChangePIN {
const char *oldPin;
const char *newPin;
CKYByte pinNumber;
} CKYAppletArgChangePIN;
typedef struct _CKYAppletArgCreateObject {
unsigned long objectID;
CKYSize size;
unsigned short readACL;
unsigned short writeACL;
unsigned short deleteACL;
} CKYAppletArgCreateObject;
typedef struct _CKYAppletArgDeleteObject {
unsigned long objectID;
CKYByte zero;
} CKYAppletArgDeleteObject;
typedef struct _CKYAppletArgReadObject {
unsigned long objectID;
CKYOffset offset;
CKYByte size;
} CKYAppletArgReadObject;
typedef struct _CKYAppletArgComputeCrypt {
CKYByte keyNumber;
CKYByte mode;
CKYByte direction;
CKYByte location;
const CKYBuffer *data;
const CKYBuffer *sig;
} CKYAppletArgComputeCrypt;
/* fills in an APDU from a structure -- form of all the generic factories*/
typedef CKYStatus (*CKYAppletFactory)(CKYAPDU *apdu, const void *param);
/* fills in an a structure from a response -- form of all the fill structures*/
typedef CKYStatus (*CKYFillFunction)(const CKYBuffer *response,
CKYSize size, void *param);
CKY_BEGIN_PROTOS
/*****************************************************************
*
* Generic factorys are used by the generic APDU processing
* to customize the formatting of APDU. The all have the same signature
* as CKYAppletFactory. Typically APDUs are formatted
* using parameterized calls of the form CKYAPDUFactory_ADPUNAME.
* The generic processing code, however needs calls with a common
* Signature. To accomplish the conversion, we build generic versions
* which take a void * parameter. Trivial APDU's can pass NULL or a pointer
* to the single parameter that they need. More complicated APDU's use
* CKYAppletArg* data structures defined above to pass more arguments.
*
* Generic factorys then call the standard CKYAPDUFactor_ADPUNAME() functions
* to build the APDUs. These functions are intended only as arguments
* to the generic ADPU calls, and not to be called directly.
*
*****************************************************************/
/* param == CKYBuffer * (AID) */
CKYStatus CKYAppletFactory_SelectFile(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_SelectCardManager(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetCPLCData(CKYAPDU *apdu, const void *param);
/* param == CKYByte * (pointer to seq) */
CKYStatus CKYAppletFactory_ListKeys(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgComputeCrypt */
CKYStatus CKYAppletFactory_ComputeCryptInit(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgComputeCrypt */
CKYStatus CKYAppletFactory_ComputeCryptProcess(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgComputeCrypt */
CKYStatus CKYAppletFactory_ComputeCryptFinal(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgCreatePIN */
CKYStatus CKYAppletFactory_CreatePIN(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgVeriryPIN */
CKYStatus CKYAppletFactory_VerifyPIN(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgChangePIN */
CKYStatus CKYAppletFactory_ChangePIN(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_ListPINs(CKYAPDU *apdu, const void *param);
/* param == CKYByte * (pointer to pinNumber) */
CKYStatus CKYAppletFactory_Logout(CKYAPDU *apdu, const void *param);
/* Future add WriteObject */
/* param == CKYAppletArgCreateObject */
CKYStatus CKYAppletFactory_CreateObject(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgDeleteObject */
CKYStatus CKYAppletFactory_DeleteObject(CKYAPDU *apdu, const void *param);
/* param == CKYAppletArgReadObject */
CKYStatus CKYAppletFactory_ReadObject(CKYAPDU *apdu, const void *param);
/* param == CKYByte * (pointer to seq) */
CKYStatus CKYAppletFactory_ListObjects(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetStatus(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_Noop(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetBuildID(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetLifeCycle(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetLifeCycleV2(CKYAPDU *apdu, const void *param);
/* param == CKYByte * */
CKYStatus CKYAppletFactory_GetRandom(CKYAPDU *apdu, const void *param);
/* param == CKY_Buffer */
CKYStatus CKYAppletFactory_SeedRandom(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetIssuerInfo(CKYAPDU *apdu, const void *param);
/* param == NULL */
CKYStatus CKYAppletFactory_GetBuiltinACL(CKYAPDU *apdu, const void *param);
/* deprecates 0.x functions */
/* param == NULL */
CKYStatus CKYAppletFactory_LogoutAllV0(CKYAPDU *apdu, const void *param);
/*****************************************************************
*
* Generic Fill routines used by the generic APDU processing
* to customize how the response data is returned to the application.
* generally the param points to some structure which is filled in
* by the Fill function from the response data. Each APDU command
* can potentially have it's own fill function. Different appearent
* functions can be accomplished by calling the same APDU with a different
* fill function. The fill functions below are considered globally interesting
* to applications that wish to make custom APDU calls using the
* applet generic processing. Fill functions are never called directly,
* but through callback, and all have the same signature (CKYFillFunction)
*
*****************************************************************/
/* a null fill function for those APDU's which do not return data */
CKYStatus CKYAppletFill_Null(const CKYBuffer *response, CKYSize size, void *param);
/* Buffer Fills: */
/* Replace fill function for those APDU's which return raw data */
/* param == CKYBuffer * */
CKYStatus CKYAppletFill_ReplaceBuffer(const CKYBuffer *response, CKYSize size,
void *param);
/* Append fill function can be used with any APDU that uses Buffer
* Replace. Repeated calls continuously adds more data to the buffer.
* Useful for repeated operations like read. */
/* param == CKYBuffer * */
CKYStatus CKYAppletFill_AppendBuffer(const CKYBuffer *response,
CKYSize size, void *param);
/* Single value fills: Byte, Short, & Long */
/* param == CKYByte * */
CKYStatus CKYAppletFill_Byte(const CKYBuffer *response, CKYSize size, void *param);
/* param == CKYByte * */
CKYStatus CKYAppletFill_Short(const CKYBuffer *response, CKYSize size, void *param);
CKYStatus CKYAppletFill_Long(const CKYBuffer *response, CKYSize size, void *param);
/*****************************************************************
*
* Utilities shared by all the fetch Cards.
*
*****************************************************************/
/*
* verify the we got a successful response. Responses should include
* the expected data returned plus a 2 byte return code. This return
* code should be 0x9000 on success. The function copies the return code
* to apduRC if apduRC is not NULL.
*/
CKYBool CKYApplet_VerifyResponse(const CKYBuffer *response, CKYSize dataSize,
CKYISOStatus *apduRC);
/*
* most commands have identical operations. This function
* handles these operations, isolating the differences in
* call back functions.
* It creates the ADPU using afFunc with afArg.
* Adds nonce if it exists.
* Sends the ADPU to the card through the connection conn.
* Checks that the response was valid (returning the responce code in apduRC.
* Formats the response data into fillArg with fillFunc
* nonce and apduRC can be NULL (no nonce is added, not status returned
* legal values for afArg are depened on afFunc.
* legal values for fillArg are depened on fillFunc.
*/
CKYStatus CKYApplet_HandleAPDU(CKYCardConnection *conn,
CKYAppletFactory afFunc, const void *afArg,
const CKYBuffer *nonce, CKYSize size,
CKYFillFunction fillFunc, void *fillArg, CKYISOStatus *apduRC);
/*****************************************************************
*
* The following convience functions convert APDU calls
* into function calls, with input and output parameters.
* The application is still responsible for
* 1) creating a connection to the card,
* 2) Getting a tranaction long, then
* 3) selecting the appropriate applet (or Card manager).
* Except for those calls that have been noted, the appropriate applet
* is the CoolKey applet.
*
*****************************************************************/
/* Select an applet. Can happen with either applet selected */
CKYStatus CKYApplet_SelectFile(CKYCardConnection *conn, const CKYBuffer *AID,
CKYISOStatus *apduRC);
/* Select the CoolKey applet. Special case of the above command */
/* Can happen with either applet selected */
CKYStatus CKYApplet_SelectCoolKeyManager(CKYCardConnection *conn,
CKYISOStatus *apduRC);
/* Select the card manager. Can happen with either applet selected */
CKYStatus CKYApplet_SelectCardManager(CKYCardConnection *conn,
CKYISOStatus *apduRC);
/* GetCPLC data -- must be called with CM selected */
/* fills in cplc */
CKYStatus CKYApplet_GetCPLCData(CKYCardConnection *conn,
CKYAppletRespGetCPLCData *cplc, CKYISOStatus *apduRC);
/* Get CUID. -- must be called with CM selected */
/* special case of GetCPLCData */
/* fills in cuid */
CKYStatus CKYApplet_GetCUID(CKYCardConnection *conn,
CKYBuffer *cuid, CKYISOStatus *apduRC);
/* Get MSN. -- must be called with CM selected */
/* special case of GetCPLCData */
/* returns msn */
CKYStatus CKYApplet_GetMSN(CKYCardConnection *conn, unsigned long *msn,
CKYISOStatus *apduRC);
/* List Keys -- see applet documentation */
CKYStatus CKYApplet_ListKeys(CKYCardConnection *conn, CKYByte seq,
CKYAppletRespListKeys *lkp, CKYISOStatus *apduRC);
/*
* Compute Crypt Cluster.
*
* Compute Crypt takes 3 phases: Init, Process, Final.
* Applications can call each phase separately using:
* CKYApplet_ComputeCryptInit
* CKYApplet_ComputeCryptProcess
* CKYApplet_ComputeCryptFinal
* or call all three in one set with:
* CKYApplet_ComputeCrypt
* Buffer values passed to Compute crypt should be raw data.
* The helper functions format the 2 byte length data required by the
* applet automatically.
*/
CKYStatus CKYApplet_ComputeCryptInit(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte mode, CKYByte direction, CKYByte location,
const CKYBuffer *nonce, CKYISOStatus *apduRC);
CKYStatus CKYApplet_ComputeCryptProcess(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data, const CKYBuffer *nonce,
CKYISOStatus *apduRC);
CKYStatus CKYApplet_ComputeCryptFinal(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data, CKYBuffer *sig, CKYBuffer *result,
const CKYBuffer *nonce, CKYISOStatus *apduRC);
/** ...look to data size to see if we should read/write the data to
* the on card buffer. (future) */
CKYStatus CKYApplet_ComputeCrypt(CKYCardConnection *conn, CKYByte keyNumber,
CKYByte mode, CKYByte direction, const CKYBuffer *data, CKYBuffer *sig,
CKYBuffer *result, const CKYBuffer *nonce, CKYISOStatus *apduRC);
/* Pin Command -- see applet documentation for use */
CKYStatus CKYApplet_CreatePIN(CKYCardConnection *conn, CKYByte pinNumber,
CKYByte maxAttempts, const char *pinValue,
const CKYBuffer *nonce, CKYISOStatus *apduRC);
CKYStatus CKYApplet_VerifyPIN(CKYCardConnection *conn, CKYByte pinNumber,
const char *pinValue, CKYBuffer *nonce, CKYISOStatus *apduRC);
CKYStatus CKYApplet_ChangePIN(CKYCardConnection *conn, const char *oldPin,
const char *newPin, const CKYBuffer *nonce,
CKYISOStatus *apduRC);
CKYStatus CKYApplet_ListPINs(CKYCardConnection *conn, unsigned short *pins,
CKYISOStatus *apduRC);
CKYStatus CKYApplet_Logout(CKYCardConnection *conn, CKYByte pinNumber,
const CKYBuffer *nonce, CKYISOStatus *apduRC);
/* Object Commands -- see applet documentation for use */
CKYStatus CKYApplet_CreateObject(CKYCardConnection *conn, unsigned long objectID,
CKYSize size, unsigned short readACL, unsigned short writeACL,
unsigned short deleteACL, const CKYBuffer *nonce, CKYISOStatus *apduRC);
CKYStatus CKYApplet_DeleteObject(CKYCardConnection *conn, unsigned long objectID,
CKYByte zero, const CKYBuffer *nonce, CKYISOStatus *apduRC);
/* CAC commands */
/* Select one of the CAC PKI applets. Special case of CKYApplet_SelectFile */
/* Select the CAC card manager. Can happen with either applet selected */
CKYStatus CACApplet_SelectCardManager(CKYCardConnection *conn,
CKYISOStatus *apduRC);
/* Can happen with either applet selected */
CKYStatus CACApplet_SelectPKI(CKYCardConnection *conn, CKYByte instance,
CKYISOStatus *apduRC);
/* must happen with PKI applet selected */
CKYStatus CACApplet_SignDecrypt(CKYCardConnection *conn, const CKYBuffer *data,
CKYBuffer *result, CKYISOStatus *apduRC);
CKYStatus CACApplet_GetCertificate(CKYCardConnection *conn, CKYBuffer *cert,
CKYISOStatus *apduRC);
CKYStatus CACApplet_GetCertificateFirst(CKYCardConnection *conn,
CKYBuffer *cert, CKYSize *nextSize,
CKYISOStatus *apduRC);
CKYStatus CACApplet_GetCertificateAppend(CKYCardConnection *conn,
CKYBuffer *cert, CKYSize nextSize,
CKYISOStatus *apduRC);
/*CKYStatus CACApplet_GetProperties(); */
CKYStatus CACApplet_VerifyPIN(CKYCardConnection *conn, const char *pin,
CKYISOStatus *apduRC);
/*
* There are 3 read commands:
*
* CKYApplet_ReadObject issues a single Read APDU call. Supplied data buffer
* is overwritten. This function is limited to reading 240 bytes.
* CKYApplet_ReadObjectAppend also issues a single Read APDU call. However,
* the result is appended to the data buffer. Again, this function is limited
* to reading 240 bytes.
* CKYApplet_ReadObjectFull can read an entire data object. It makes multiple
* apdu calls in order to read the full amount into the buffer. The buffer
* is overwriten.
*/
CKYStatus CKYApplet_ReadObject(CKYCardConnection *conn, unsigned long objectID,
CKYOffset offset, CKYByte size, const CKYBuffer *nonce,
CKYBuffer *data, CKYISOStatus *apduRC);
CKYStatus CKYApplet_ReadObjectAppend(CKYCardConnection *conn,
unsigned long objectID, CKYOffset offset, CKYByte size,
const CKYBuffer *nonce, CKYBuffer *data, CKYISOStatus *apduRC);
CKYStatus CKYApplet_ReadObjectFull(CKYCardConnection *conn,
unsigned long objectID, CKYOffset offset, CKYSize size,
const CKYBuffer *nonce, CKYBuffer *data, CKYISOStatus *apduRC);
CKYStatus CKYApplet_ListObjects(CKYCardConnection *conn, CKYByte seq,
CKYAppletRespListObjects *lop, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetStatus(CKYCardConnection *conn,
CKYAppletRespGetStatus *status, CKYISOStatus *apduRC);
CKYStatus CKYApplet_Noop(CKYCardConnection *conn, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetBuildID(CKYCardConnection *conn, unsigned long *buildID,
CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetLifeCycle(CKYCardConnection *conn, CKYByte *personalized,
CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetLifeCycleV2(CKYCardConnection *conn,
CKYAppletRespGetLifeCycleV2 *ext, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetRandom(CKYCardConnection *conn,
CKYBuffer *buf, CKYByte len, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetRandomAppend(CKYCardConnection *conn,
CKYBuffer *buf, CKYByte len, CKYISOStatus *apduRC);
CKYStatus CKYApplet_SeedRandom(CKYCardConnection *conn,
const CKYBuffer *buf, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetIssuerInfo(CKYCardConnection *conn,
CKYBuffer *buf, CKYISOStatus *apduRC);
CKYStatus CKYApplet_GetBuiltinACL(CKYCardConnection *conn,
CKYAppletRespGetBuiltinACL *gba, CKYISOStatus *apduRC);
/*
* deprecates 0.x functions
*/
/* old applet verify pin call (no nonce returned) */
CKYStatus CKYApplet_VerifyPinV0(CKYCardConnection *conn, CKYByte pinNumber,
const char *pinValue, CKYISOStatus *apduRC);
/* logout all */
CKYStatus CKYApplet_LogoutAllV0(CKYCardConnection *conn, CKYISOStatus *apduRC);
CKY_END_PROTOS
#endif /* CKY_APPLET_H */
--- NEW FILE cky_base.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "cky_basei.h"
#include "cky_base.h"
#include "dynlink.h"
/*
* generic buffer management functions
*
* These functions allow simple buffer management used in the CoolKey
* library and it's clients.
*/
/* initialize a new buffer to a known state */
static void
ckyBuffer_initBuffer(CKYBuffer *buf)
{
#ifdef DEBUG
assert(sizeof(CKYBuffer) == sizeof(CKYBufferPublic));
#endif
buf->data = NULL;
buf->size = 0;
buf->len = 0;
}
/*
* Init functions clobbers the current contents and allocates the required
* space. Active buffers should call CKYBuffer_FreerData before
* calling an init function. All init functions copies the supplied data
* into newly allocated space.
*/
/* init an empty buffer that will later be filled in. */
CKYStatus
CKYBuffer_InitEmpty(CKYBuffer *buf)
{
ckyBuffer_initBuffer(buf);
return CKYSUCCESS;
}
/* Create a buffer of length len all initialized to '0' */
CKYStatus
CKYBuffer_InitFromLen(CKYBuffer *buf, CKYSize len)
{
CKYStatus ret;
ckyBuffer_initBuffer(buf);
ret = CKYBuffer_Reserve(buf, len);
if (ret != CKYSUCCESS) {
return ret;
}
buf->len = len;
memset(buf->data, 0, buf->len);
return CKYSUCCESS;
}
static CKYByte
fromHex(const char *cp)
{
if (*cp >= '0' && *cp <= '9') {
return (CKYByte) *cp - '0';
}
if (*cp >= 'a' && *cp <= 'f') {
return (CKYByte) *cp - 'a' + 0xa;
}
if (*cp >= 'A' && *cp <= 'F') {
return (CKYByte) *cp - 'A' + 0xA;
}
return 0;
}
/* Create a buffer by decoding a hex string. hexString is NULL terminated. */
CKYStatus
CKYBuffer_InitFromHex(CKYBuffer *buf, const char *hexString)
{
int len = strlen(hexString);
int dataHalf = 0;
CKYByte lastDigit = 0;
CKYByte digit;
const char *cp;
CKYByte *bp;
CKYStatus ret;
if (len & 1) {
len++;
dataHalf++;
}
ckyBuffer_initBuffer(buf);
ret = CKYBuffer_Reserve(buf, len/2);
if (ret != CKYSUCCESS) {
return ret;
}
buf->len = len/2;
bp = buf->data;
for (cp = hexString; *cp; cp++) {
digit = fromHex(cp);
/* check for error? */
if (dataHalf) {
*bp++= lastDigit << 4 | digit;
}
dataHalf ^= 1;
lastDigit = digit;
}
return CKYSUCCESS;
}
/* Create a buffer from data */
CKYStatus
CKYBuffer_InitFromData(CKYBuffer *buf, const CKYByte *data, CKYSize len)
{
CKYStatus ret;
ckyBuffer_initBuffer(buf);
ret = CKYBuffer_Reserve(buf, len);
if (ret != CKYSUCCESS) {
return ret;
}
buf->len = len;
memcpy(buf->data, data, buf->len);
return CKYSUCCESS;
}
/* Create a buffer from part of another buffer. Start indicates the
* offset in the old buffer to start in, and len specifies how many bytes
* to copy */
CKYStatus
CKYBuffer_InitFromBuffer(CKYBuffer *buf,
const CKYBuffer *src, CKYOffset start, CKYSize len)
{
CKYStatus ret;
ckyBuffer_initBuffer(buf);
if (src->len < start) {
len = 0;
} else if (src->len < start+len) {
len = src->len -start;
}
ret = CKYBuffer_Reserve(buf, len);
if (ret != CKYSUCCESS) {
return ret;
}
buf->len = len;
if (len == 0) {
return CKYSUCCESS;
}
memcpy(buf->data, src->data+start, buf->len);
return CKYSUCCESS;
}
/* Create a buffer from and exact copy of another buffer. */
CKYStatus
CKYBuffer_InitFromCopy(CKYBuffer *buf, const CKYBuffer *src)
{
CKYStatus ret;
ckyBuffer_initBuffer(buf);
/* src buffer has no length, make sure the dest is empty */
if (src->len == 0) {
return CKYSUCCESS;
}
ret = CKYBuffer_Reserve(buf, src->len);
if (ret != CKYSUCCESS) {
return ret;
}
buf->len = src->len;
memcpy(buf->data, src->data, buf->len);
return CKYSUCCESS;
}
/*
* append functions increase the buffer size if necessary
*/
CKYStatus
CKYBuffer_AppendChar(CKYBuffer *buf, CKYByte val)
{
CKYStatus ret;
ret = CKYBuffer_Reserve(buf, buf->len + 1);
if (ret != CKYSUCCESS) {
return ret;
}
buf->data[buf->len] = val;
buf->len += 1;
return CKYSUCCESS;
}
/* append a short in network order */
CKYStatus
CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val)
{
CKYStatus ret;
ret = CKYBuffer_Reserve(buf, buf->len + 2);
if (ret != CKYSUCCESS) {
return ret;
}
buf->data[buf->len+0] = (CKYByte) ((val >> 8) & 0xff);
buf->data[buf->len+1] = (CKYByte) ((val >> 0) & 0xff);
buf->len += 2;
return CKYSUCCESS;
}
/* append a long in applet order */
CKYStatus
CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val)
{
CKYStatus ret;
ret = CKYBuffer_Reserve(buf, buf->len + 4);
if (ret != CKYSUCCESS) {
return ret;
}
buf->data[buf->len+0] = (CKYByte) ((val >> 24) & 0xff);
buf->data[buf->len+1] = (CKYByte) ((val >> 16) & 0xff);
buf->data[buf->len+2] = (CKYByte) ((val >> 8) & 0xff);
buf->data[buf->len+3] = (CKYByte) ((val >> 0) & 0xff);
buf->len += 4;
return CKYSUCCESS;
}
CKYStatus
CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data, CKYSize len)
{
CKYStatus ret;
ret = CKYBuffer_Reserve(buf, offset+len);
if (ret != CKYSUCCESS) {
return ret;
}
if (buf->len < offset + len) {
buf->len = offset + len;
}
memcpy(buf->data+offset, data, len);
return CKYSUCCESS;
}
/* append data with length of len bytes */
CKYStatus
CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len)
{
CKYStatus ret;
ret = CKYBuffer_Reserve(buf, buf->len + len);
if (ret != CKYSUCCESS) {
return ret;
}
memcpy(buf->data+buf->len, data, len);
buf->len += len;
return CKYSUCCESS;
}
/* append data with length of len bytes */
CKYStatus
CKYBuffer_AppendBuffer(CKYBuffer *buf, const CKYBuffer *src,
CKYOffset offset, CKYSize len)
{
unsigned long maxlen = src->len - offset;
if ((maxlen < len) || (src->len < offset)) {
return CKYDATATOOLONG;
}
return CKYBuffer_AppendData(buf, src->data+offset, len);
}
/* append data with length of len bytes */
CKYStatus
CKYBuffer_AppendCopy(CKYBuffer *buf, const CKYBuffer *src)
{
return CKYBuffer_AppendData(buf, src->data, src->len);
}
CKYStatus
CKYBuffer_Reserve(CKYBuffer *buf, CKYSize newSize)
{
if (buf->size >= newSize) {
return CKYSUCCESS;
}
buf->data = (CKYByte *)realloc(buf->data, newSize);
if (buf->data == NULL) {
buf->size = 0;
buf->len = 0;
return CKYNOMEM;
}
buf->size = newSize;
return CKYSUCCESS;
}
CKYStatus
CKYBuffer_SetChar(CKYBuffer *buf, CKYOffset offset, CKYByte val)
{
CKYStatus ret;
if (buf->len < offset+1) {
ret = CKYBuffer_Resize(buf,offset+1);
if (ret != CKYSUCCESS) {
return ret;
}
}
buf->data[offset] = val;
return CKYSUCCESS;
}
CKYStatus
CKYBuffer_SetChars(CKYBuffer *buf, CKYOffset offset, CKYByte val, CKYSize len)
{
CKYStatus ret;
if (buf->len < offset+len) {
ret = CKYBuffer_Resize(buf,offset+len);
if (ret != CKYSUCCESS) {
return ret;
}
}
memset(buf->data+offset,val, len);
return CKYSUCCESS;
}
CKYStatus
CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val)
{
CKYStatus ret;
if (buf->len < offset+2) {
ret = CKYBuffer_Resize(buf,offset+2);
if (ret != CKYSUCCESS) {
return ret;
}
}
buf->data[offset+0] = (CKYByte) ((val >> 8) & 0xff);
buf->data[offset+1] = (CKYByte) ((val >> 0) & 0xff);
return CKYSUCCESS;
}
CKYStatus
CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val)
{
CKYStatus ret;
if (buf->len < offset+4) {
ret = CKYBuffer_Resize(buf,offset+4);
if (ret != CKYSUCCESS) {
return ret;
}
}
buf->data[offset+0] = (CKYByte) ((val >> 24) & 0xff);
buf->data[offset+1] = (CKYByte) ((val >> 16) & 0xff);
buf->data[offset+2] = (CKYByte) ((val >> 8) & 0xff);
buf->data[offset+3] = (CKYByte) ((val >> 0) & 0xff);
return CKYSUCCESS;
}
CKYByte
CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset)
{
if (buf->len < offset+1) {
return 0;
}
return buf->data[offset];
}
unsigned short
CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset)
{
unsigned short val;
if (buf->len < offset+2) {
return 0;
}
val = ((unsigned short)buf->data[offset+0]) << 8;
val |= ((unsigned short)buf->data[offset+1]) << 0;
return val;
}
unsigned long
CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset)
{
unsigned long val;
if (buf->len < offset+4) {
return 0;
}
val = ((unsigned long)buf->data[offset+0]) << 24;
val |= ((unsigned long)buf->data[offset+1]) << 16;
val |= ((unsigned long)buf->data[offset+2]) << 8;
val |= ((unsigned long)buf->data[offset+3]) << 0;
return val;
}
CKYStatus
CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen)
{
CKYStatus ret;
if (buf->len < newLen) {
ret = CKYBuffer_Reserve(buf, newLen);
if (ret != CKYSUCCESS) {
return ret;
}
memset(buf->data+buf->len, 0, newLen - buf->len);
}
buf->len = newLen;
return CKYSUCCESS;
}
/* clear out a memory buffer... including unallocated space, then
* set the buffer length to '0' */
void
CKYBuffer_Zero(CKYBuffer *buf)
{
if (buf->size != 0) {
memset(buf->data, 0, buf->size);
}
buf->len = 0;;
}
CKYSize
CKYBuffer_Size(const CKYBuffer *buf)
{
return buf->len;
}
const CKYByte *
CKYBuffer_Data(const CKYBuffer *buf)
{
return buf->data;
}
CKYBool
CKYBuffer_DataIsEqual(const CKYBuffer *buf1, const CKYByte *buf2, CKYSize buf2Len)
{
if (buf1->len != buf2Len) {
return 0;
}
/* all zero length buffers are equal, whether or not they have pointers
* allocated */
if (buf1->len == 0) {
return 1;
}
return memcmp(buf1->data, buf2, buf1->len) == 0;
}
CKYBool
CKYBuffer_IsEqual(const CKYBuffer *buf1, const CKYBuffer *buf2)
{
return CKYBuffer_DataIsEqual(buf1, buf2->data, buf2->len);
}
CKYStatus
CKYBuffer_FreeData(CKYBuffer *buf)
{
free(buf->data);
ckyBuffer_initBuffer(buf);
return CKYSUCCESS;
}
CKYStatus
CKYAPDU_Init(CKYAPDU *apdu)
{
#ifdef DEBUG
assert(sizeof(CKYAPDU) == sizeof(CKYAPDUPublic));
#endif
ckyBuffer_initBuffer(&apdu->apduBuf);
return CKYBuffer_Resize(&apdu->apduBuf, CKYAPDU_MIN_LEN);
}
CKYStatus
CKYAPDU_InitFromData(CKYAPDU *apdu, const CKYByte *data, CKYSize len)
{
#ifdef DEBUG
assert(sizeof(CKYAPDU) == sizeof(CKYAPDUPublic));
#endif
ckyBuffer_initBuffer(&apdu->apduBuf);
if (len > CKYAPDU_MAX_DATA_LEN) {
return CKYDATATOOLONG;
}
return CKYBuffer_InitFromData(&apdu->apduBuf, data, len);
}
CKYStatus
CKYAPDU_FreeData(CKYAPDU *apdu)
{
return CKYBuffer_FreeData(&apdu->apduBuf);
}
CKYByte
CKYAPDU_GetCLA(const CKYAPDU *apdu)
{
return CKYBuffer_GetChar(&apdu->apduBuf, CKY_CLA_OFFSET);
}
CKYStatus
CKYAPDU_SetCLA(CKYAPDU *apdu, CKYByte b)
{
return CKYBuffer_SetChar(&apdu->apduBuf, CKY_CLA_OFFSET, b);
}
CKYByte
CKYAPDU_GetINS(const CKYAPDU *apdu)
{
return CKYBuffer_GetChar(&apdu->apduBuf, CKY_INS_OFFSET);
}
CKYStatus
CKYAPDU_SetINS(CKYAPDU *apdu, CKYByte b)
{
return CKYBuffer_SetChar(&apdu->apduBuf, CKY_INS_OFFSET, b);
}
CKYByte
CKYAPDU_GetP1(const CKYAPDU *apdu)
{
return CKYBuffer_GetChar(&apdu->apduBuf, CKY_P1_OFFSET);
}
CKYStatus
CKYAPDU_SetP1(CKYAPDU *apdu, CKYByte b)
{
return CKYBuffer_SetChar(&apdu->apduBuf, CKY_P1_OFFSET, b);
}
CKYByte
CKYAPDU_GetP2(const CKYAPDU *apdu)
{
return CKYBuffer_GetChar(&apdu->apduBuf, CKY_P2_OFFSET);
}
CKYStatus
CKYAPDU_SetP2(CKYAPDU *apdu, CKYByte b)
{
return CKYBuffer_SetChar(&apdu->apduBuf, CKY_P2_OFFSET, b);
}
CKYStatus
CKYAPDU_SetSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len)
{
CKYStatus ret;
if (len > CKYAPDU_MAX_DATA_LEN) {
return CKYDATATOOLONG;
}
ret = CKYBuffer_Resize(&apdu->apduBuf, len + CKYAPDU_HEADER_LEN);
if (ret != CKYSUCCESS) {
return ret;
}
ret = CKYBuffer_SetChar(&apdu->apduBuf, CKY_LC_OFFSET,
len == CKYAPDU_MAX_DATA_LEN ? 0: (CKYByte) len);
if (ret != CKYSUCCESS) {
return ret;
}
return CKYBuffer_Replace(&apdu->apduBuf, CKYAPDU_HEADER_LEN, data, len);
}
CKYStatus
CKYAPDU_SetSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf)
{
return CKYAPDU_SetSendData(apdu, buf->data, buf->len);
}
CKYStatus
CKYAPDU_AppendSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len)
{
CKYStatus ret;
CKYSize dataLen;
if (CKYBuffer_Size(&apdu->apduBuf) <= CKYAPDU_MIN_LEN) {
return CKYAPDU_SetSendData(apdu,data, len);
}
dataLen = CKYBuffer_Size(&apdu->apduBuf) + len - CKYAPDU_HEADER_LEN;
if (dataLen > CKYAPDU_MAX_DATA_LEN) {
return CKYDATATOOLONG;
}
ret = CKYBuffer_AppendData(&apdu->apduBuf, data, len);
if (ret != CKYSUCCESS) {
return ret;
}
return CKYBuffer_SetChar(&apdu->apduBuf, CKY_LC_OFFSET,
dataLen == CKYAPDU_MAX_DATA_LEN ? 0 : (CKYByte) dataLen);
}
CKYStatus
CKYAPDU_AppendSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf)
{
return CKYAPDU_AppendSendData(apdu, buf->data, buf->len);
}
CKYStatus
CKYAPDU_SetReceiveLen(CKYAPDU *apdu, CKYByte recvlen)
{
CKYStatus ret;
ret = CKYBuffer_Resize(&apdu->apduBuf, CKYAPDU_HEADER_LEN);
if (ret != CKYSUCCESS) {
return ret;
}
return CKYBuffer_SetChar(&apdu->apduBuf, CKY_LE_OFFSET, recvlen);
}
void
CKY_SetName(char *p)
{
}
--- NEW FILE cky_base.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_BASE_H
#define CKY_BASE_H 1
/*
* Common types and structs
*/
/* buffer sizes */
typedef unsigned long CKYSize;
/* offsets into buffers are data */
typedef unsigned long CKYOffset;
/* bytes, buffers */
typedef unsigned char CKYByte;
/* Bool type */
typedef unsigned char CKYBool;
#define CKYBUFFER_PUBLIC \
unsigned long reserved1;\
unsigned long reserved2;\
void *reserved3;\
void *reserved4;
#define CKYAPDU_PUBLIC \
unsigned long reserved1;\
unsigned long reserved2;\
void *reserved3;\
void *reserved4; \
void *reserved5;
typedef struct _CKYBuffer {
#ifdef CKYBUFFER_PRIVATE
CKYBUFFER_PRIVATE
#else
CKYBUFFER_PUBLIC
#endif
} CKYBuffer;
typedef struct _CKYAPDU {
#ifdef CKYAPDU_PRIVATE
CKYAPDU_PRIVATE
#else
CKYAPDU_PUBLIC
#endif
} CKYAPDU;
/*
* the following is just to make sure the sizes match
*/
#ifdef DEBUG
#ifdef CKYBUFFER_PRIVATE
typedef struct _CKYBufferPublic {
CKYBUFFER_PUBLIC
} CKYBufferPublic;
typedef struct _CKYAPDUPublic {
CKYAPDU_PUBLIC
} CKYAPDUPublic;
#endif
#endif
typedef enum {
CKYSUCCESS, /* operation completed successfully */
CKYNOMEM, /* failed to allocate memory */
CKYDATATOOLONG, /* index or length exceeded a buffer or device size */
CKYNOSCARD, /* Scard library does not exist */
CKYSCARDERR, /* I/O Error in the SCard interface level. */
/* more specific error values can be queried from
* the context or connection with the
* GetLastError() call */
CKYLIBFAIL, /* error is shared library. no additional
* error is available. Only returned from internal
* SHlib calls (not surfaced in public APIs */
CKYAPDUFAIL, /* processing worked, but applet rejected the APDU
* (command) sent. ADPUIOStatus has more info on
* why the APDU failed */
CKYINVALIDARGS, /* Caller passed in bad args */
} CKYStatus;
/*
* defines related to APDU's
*/
#define CKY_CLA_OFFSET 0
#define CKY_INS_OFFSET 1
#define CKY_P1_OFFSET 2
#define CKY_P2_OFFSET 3
#define CKY_P3_OFFSET 4 /* P3 is P3, LC, and LE depending on usage */
#define CKY_LC_OFFSET 4
#define CKY_LE_OFFSET 4
#define CKYAPDU_MAX_DATA_LEN 256
#define CKYAPDU_MIN_LEN 4
#define CKYAPDU_HEADER_LEN 5
#define CKYAPDU_MAX_LEN (CKYAPDU_HEADER_LEN+CKYAPDU_MAX_DATA_LEN)
#define CKY_MAX_ATR_LEN 32
#define CKY_OUTRAGEOUS_MALLOC_SIZE (1024*1024)
/*
* allow direct inclusion in C++ files
*/
#ifdef __cplusplus
#define CKY_BEGIN_PROTOS extern "C" {
#define CKY_END_PROTOS }
#else
#define CKY_BEGIN_PROTOS
#define CKY_END_PROTOS
#endif
CKY_BEGIN_PROTOS
/*
* generic buffer management functions
*
* These functions allow simple buffer management used in the CoolKey
* library and it's clients.
*/
/*
* Init functions clobbers the current contents and allocates the required
* space.
* - Active buffers should call CKYBuffer_FreeData before calling an init
* function.
* - New buffers should call some CKYBuffer_Init function before any use.
* - All init functions copies the supplied data into newly allocated space.
*/
/* Create an empty buffer with no memory allocated to it. This is sufficient
* to begin using a buffer. Note that new calls will probably allocate memory.
* It is safe to free an empty buffer. */
CKYStatus CKYBuffer_InitEmpty(CKYBuffer *buf);
/* Create a buffer of length len all initialized to '0' */
CKYStatus CKYBuffer_InitFromLen(CKYBuffer *buf, CKYSize len);
/* Create a buffer by decoding a hex string. hexString is NULL terminated. */
CKYStatus CKYBuffer_InitFromHex(CKYBuffer *buf, const char *hexString);
/* Create a buffer from data */
CKYStatus CKYBuffer_InitFromData(CKYBuffer *buf, const CKYByte *data, CKYSize len);
/* Create a buffer from part of another buffer. Start indicates the
* offset in the old buffer to start in, and len specifies how many bytes
* to copy */
CKYStatus CKYBuffer_InitFromBuffer(CKYBuffer *buf, const CKYBuffer *src,
CKYOffset start, CKYSize len);
/* Create a buffer from an exact copy of another buffer */
CKYStatus CKYBuffer_InitFromCopy(CKYBuffer *buf, const CKYBuffer *src);
/*
* append functions increase the buffer size if necessary
*/
/* append a short in applet order */
CKYStatus CKYBuffer_AppendChar(CKYBuffer *buf, CKYByte b);
/* append a short in applet order */
CKYStatus CKYBuffer_AppendShort(CKYBuffer *buf, unsigned short val);
/* append a long in applet order */
CKYStatus CKYBuffer_AppendLong(CKYBuffer *buf, unsigned long val);
/* append data. the data starts at data and extends len bytes */
CKYStatus CKYBuffer_AppendData(CKYBuffer *buf, const CKYByte *data, CKYSize len);
/* append buffer fragment. the data starts at buffer[offset]
* and extends len bytes */
CKYStatus CKYBuffer_AppendBuffer(CKYBuffer *buf, const CKYBuffer *src,
CKYOffset offset, CKYSize len);
/* append a full buffer */
CKYStatus CKYBuffer_AppendCopy(CKYBuffer *buf, const CKYBuffer *src );
/* reserve increases the space allocated for the buffer, but does not
* increase the actual buffer size. If the buffer already newSize or more
* space allocated, Reserve is a no op.
*/
CKYStatus CKYBuffer_Reserve(CKYBuffer *buf, CKYSize newSize) ;
/* resize affects the buffer's size. If the buffer len increases,
* the new date will be zero'ed out. If the buffer shrinks, the buffer
* is truncated, but the space is not removed.
*/
CKYStatus CKYBuffer_Resize(CKYBuffer *buf, CKYSize newLen);
/* replace bytes starting at 'offset'. If the buffer needs to be extended,
* it will be automatically */
CKYStatus CKYBuffer_Replace(CKYBuffer *buf, CKYOffset offset, const CKYByte *data,
CKYSize len);
/* set byte at ofset. The buffer is extended to offset if necessary */
CKYStatus CKYBuffer_SetChar(CKYBuffer *buf, CKYOffset offset, CKYByte c);
/* set several copies of 'c' at from offset to offset+ len */
CKYStatus CKYBuffer_SetChars(CKYBuffer *buf, CKYOffset offset,
CKYByte c, CKYSize len);
/* These functions work in applet order */
CKYStatus CKYBuffer_SetShort(CKYBuffer *buf, CKYOffset offset, unsigned short val);
CKYStatus CKYBuffer_SetLong(CKYBuffer *buf, CKYOffset offset, unsigned long val);
/* read a character from offset. If offset is beyond the end of the buffer,
* then the function returns '0' */
CKYByte CKYBuffer_GetChar(const CKYBuffer *buf, CKYOffset offset);
/* These functions work in applet order */
unsigned short CKYBuffer_GetShort(const CKYBuffer *buf, CKYOffset offset);
unsigned long CKYBuffer_GetLong(const CKYBuffer *buf, CKYOffset offset);
/* clear out all the data in a buffer */
void CKYBuffer_Zero(CKYBuffer *buf);
/* return the size (length) of a buffer. This is only the portion of the
* buffer that has valid data set. */
CKYSize CKYBuffer_Size(const CKYBuffer *buf);
/* return a pointer to the data buffer */
const CKYByte *CKYBuffer_Data(const CKYBuffer *buf);
/* compare two buffers return :
* 1 if the two buffers are equal,
* 0 if they are not */
CKYBool CKYBuffer_IsEqual(const CKYBuffer *buf1, const CKYBuffer *buf2);
/* compares raw data with a buffer or equality */
CKYBool CKYBuffer_DataIsEqual(const CKYBuffer *buf1,
const CKYByte *buf2, CKYSize buf2Len);
/* free all the data associated with a buffer and initialize the buffer */
CKYStatus CKYBuffer_FreeData(CKYBuffer *buf);
/*
* APDU's are buffers that know about the APDU structure
*/
CKYStatus CKYAPDU_Init(CKYAPDU *apdu);
CKYStatus CKYAPDU_InitFromData(CKYAPDU *apdu, const CKYByte *data, CKYSize size);
CKYStatus CKYAPDU_FreeData(CKYAPDU *apdu);
/* Access APDU header bytes */
CKYByte CKYAPDU_GetCLA(const CKYAPDU *apdu);
CKYStatus CKYAPDU_SetCLA(CKYAPDU *apdu, CKYByte b);
CKYByte CKYAPDU_GetINS(const CKYAPDU *apdu);
CKYStatus CKYAPDU_SetINS(CKYAPDU *apdu, CKYByte b);
CKYByte CKYAPDU_GetP1(const CKYAPDU *apdu);
CKYStatus CKYAPDU_SetP1(CKYAPDU *apdu, CKYByte b);
CKYByte CKYAPDU_GetP2(const CKYAPDU *apdu);
CKYStatus CKYAPDU_SetP2(CKYAPDU *apdu, CKYByte b);
/* add sending date to the APDU */
/* Set resets the buffer, append, adds the data to the end. Lc in
* the APDU header is automaticallu updated */
CKYStatus CKYAPDU_SetSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len);
CKYStatus CKYAPDU_SetSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf);
CKYStatus CKYAPDU_AppendSendData(CKYAPDU *apdu, const CKYByte *data, CKYSize len);
CKYStatus CKYAPDU_AppendSendDataBuffer(CKYAPDU *apdu, const CKYBuffer *buf);
/* set Le in the APDU header to the amount of bytes expected to be
* returned. */
CKYStatus CKYAPDU_SetReceiveLen(CKYAPDU *apdu, CKYByte recvlen);
/* set the parent loadmodule name */
void CKY_SetName(char *name);
CKY_END_PROTOS
#endif /* CKY_BASE_H */
--- NEW FILE cky_basei.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_BASE_H
#ifndef CKY_BASEI_H
#define CKY_BASEI_H 1
#define CKYBUFFER_PRIVATE \
CKYSize len; \
CKYSize size; \
CKYByte *data; \
void *reserved;
#define CKYAPDU_PRIVATE \
CKYBuffer apduBuf; \
void *reserved;
#endif /* CKY_BASE_H */
#endif /* CKY_BASEI_H */
--- NEW FILE cky_card.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include <winscard.h>
#include <stdlib.h>
#include <string.h>
#include "cky_basei.h" /* friend class */
#include "cky_base.h"
#include "cky_card.h"
#include "dynlink.h"
#ifndef WINAPI
#define WINAPI
typedef SCARD_READERSTATE *LPSCARD_READERSTATE;
#endif
#ifndef SCARD_E_NO_READERS_AVAILABLE
#define SCARD_E_NO_READERS_AVAILABLE ((unsigned long)0x8010002EL)
#endif
#define NEW(type,count) (type *)malloc((count)*sizeof(type))
/*
* protect against scard API not being installed.
*/
typedef long (WINAPI * SCardEstablishContextFn) (
unsigned long dwScope,
const void * pvReserved1,
const void * pvReserved2,
LPSCARDCONTEXT phContext);
typedef long (WINAPI * SCardReleaseContextFn) (
SCARDCONTEXT hContext);
typedef long (WINAPI * SCardBeginTransactionFn) (
long hCard);
typedef long (WINAPI * SCardEndTransactionFn) (
long hCard,
unsigned long dwDisposition);
typedef long (WINAPI * SCardConnectFn) (
SCARDCONTEXT hContext,
const char *szReader,
unsigned long dwShareMode,
unsigned long dwPreferredProtocols,
long *phCard,
unsigned long *pdwActiveProtocol);
typedef long (WINAPI * SCardDisconnectFn) (
long hCard,
unsigned long dwDisposition);
typedef long (WINAPI * SCardTransmitFn) (
long hCard,
LPCSCARD_IO_REQUEST pioSendPci,
const unsigned char *pbSendBuffer,
unsigned long cbSendLength,
LPSCARD_IO_REQUEST pioRecvPci,
unsigned char *pbRecvBuffer,
unsigned long *pcbRecvLength);
typedef long (WINAPI * SCardReconnectFn) (
long hCard,
unsigned long dwShareMode,
unsigned long dwPreferredProtocols,
unsigned long dwInitialization,
unsigned long *pdwActiveProtocol);
typedef long (WINAPI * SCardListReadersFn) (
SCARDCONTEXT hContext,
const char *mszGroups,
char *mszReaders,
unsigned long *pcchReaders);
typedef long (WINAPI * SCardStatusFn) (
long hCard,
char *mszReaderNames,
unsigned long *pcchReaderLen,
unsigned long *pdwState,
unsigned long *pdwProtocol,
unsigned char *pbAtr,
unsigned long *pcbAtrLen);
typedef long (WINAPI * SCardGetAttribFn) (
long hCard,
unsigned long dwAttId,
char *pbAttr,
unsigned long *pchAttrLen);
typedef long (WINAPI * SCardGetStatusChangeFn) (
SCARDCONTEXT hContext,
unsigned long dwTimeout,
LPSCARD_READERSTATE rgReaderStates,
unsigned long cReaders);
typedef long (WINAPI * SCardCancelFn) (
SCARDCONTEXT hContext);
typedef struct _SCard {
SCardEstablishContextFn SCardEstablishContext;
SCardReleaseContextFn SCardReleaseContext;
SCardBeginTransactionFn SCardBeginTransaction;
SCardEndTransactionFn SCardEndTransaction;
SCardConnectFn SCardConnect;
SCardDisconnectFn SCardDisconnect;
SCardTransmitFn SCardTransmit;
SCardReconnectFn SCardReconnect;
SCardListReadersFn SCardListReaders;
SCardStatusFn SCardStatus;
SCardGetAttribFn SCardGetAttrib;
SCardGetStatusChangeFn SCardGetStatusChange;
SCardCancelFn SCardCancel;
SCARD_IO_REQUEST *SCARD_PCI_T0_;
} SCard;
#define GET_ADDRESS(library, scard, name) \
status= ckyShLibrary_getAddress(library, \
(void**) &scard->name, MAKE_DLL_SYMBOL(name)); \
if (status != CKYSUCCESS) { \
goto fail; \
}
#ifdef WIN32
#define SCARD_LIB_NAME "winscard.dll"
#else
#ifdef MAC
#define SCARD_LIB_NAME "PCSC.Framework/PCSC"
#else
#ifdef LINUX
#define SCARD_LIB_NAME "libpcsclite.so"
#else
#ifndef SCARD_LIB_NAME
#error "define wincard library for this platform"
#endif
#endif
#endif
#endif
static SCard *
ckySCard_Init(void)
{
ckyShLibrary library;
CKYStatus status;
SCard *scard = NEW(SCard, 1);
if (!scard) {
return NULL;
}
library = ckyShLibrary_open(SCARD_LIB_NAME);
if (!library) {
goto fail;
}
GET_ADDRESS(library, scard, SCardEstablishContext);
GET_ADDRESS(library, scard, SCardReleaseContext);
GET_ADDRESS(library, scard, SCardBeginTransaction);
GET_ADDRESS(library, scard, SCardEndTransaction);
/* expands to SCardConnectA on Windows */
GET_ADDRESS(library, scard, SCardConnect);
GET_ADDRESS(library, scard, SCardDisconnect);
GET_ADDRESS(library, scard, SCardTransmit);
GET_ADDRESS(library, scard, SCardReconnect);
/* expands to SCardListReadersA on Windows */
GET_ADDRESS(library, scard, SCardListReaders);
/* expands to SCardStatusA on Windows */
GET_ADDRESS(library, scard, SCardStatus);
#ifdef WIN32
GET_ADDRESS(library, scard, SCardGetAttrib);
#endif
/* SCardGetStatusChangeA */
GET_ADDRESS(library, scard, SCardGetStatusChange);
GET_ADDRESS(library, scard, SCardCancel);
status = ckyShLibrary_getAddress( library,
(void**) &scard->SCARD_PCI_T0_, MAKE_DLL_SYMBOL(g_rgSCardT0Pci));
if( status != CKYSUCCESS ) {
goto fail;
}
return scard;
fail:
if (library) {
ckyShLibrary_close(library);
}
free(scard);
return NULL;
}
/*
* Implement CKYReaderNameLists and CKYCardConnectionLists
*/
/* make the list code happy */
static void
CKYReaderName_Destroy(char *data) {
free(data);
}
#include "cky_list.i" /* implemnentation of the lists define by cky_list.h */
CKYLIST_IMPLEMENT(CKYReaderName, char *)
CKYLIST_IMPLEMENT(CKYCardConnection, CKYCardConnection *)
/*
* CKReader objects represent Readers attached to the system.
* The objects themselves are really SCard SCARD_READERSTATE objects.
* These objects are used in 2 ways:
* 1) the application creates static SCARD_READERSTATE's and use
* CKYReader_Init() to initialize the structure. In this case
* the application can call any of the reader 'methods' (functions
* starting with CKReader) on these objects. When finished the
* application is responsible for calling CKYReader_FreeData() to free
* any data held by the reader object.
* 2) Acquire an array of readers with CKYReader_CreateArray(). In this
* case the application can call any method on any particular array member
* In the end the Application is responsible for calling
* CKYReader_DestroyArray() to free the entire array.
*/
void
CKYReader_Init(SCARD_READERSTATE *reader)
{
reader->szReader = NULL;
reader->pvUserData = 0;
reader->cbAtr = 0;
reader->dwCurrentState = SCARD_STATE_UNAWARE;
}
void
CKYReader_FreeData(SCARD_READERSTATE *reader)
{
if (reader->szReader) {
free((void *)reader->szReader);
}
CKYReader_Init(reader);
}
CKYStatus
CKYReader_SetReaderName(SCARD_READERSTATE *reader, const char *name)
{
free((void *)reader->szReader);
reader->szReader = strdup(name);
return (reader->szReader)? CKYSUCCESS: CKYNOMEM;
}
const char *
CKYReader_GetReaderName(const SCARD_READERSTATE *reader)
{
return reader->szReader;
}
/* see openSC or PCSC for the semantics of Known State and Event States */
CKYStatus
CKYReader_SetKnownState(SCARD_READERSTATE *reader, unsigned long state)
{
reader->dwCurrentState = state;
return CKYSUCCESS;
}
unsigned long
CKYReader_GetKnownState(const SCARD_READERSTATE *reader)
{
return reader->dwCurrentState;
}
unsigned long
CKYReader_GetEventState(const SCARD_READERSTATE *reader)
{
return reader->dwEventState;
}
/* Caller must have init'ed the buffer before calling
* any data in the existing buffer is overwritten */
CKYStatus
CKYReader_GetATR(const SCARD_READERSTATE *reader, CKYBuffer *buf)
{
CKYStatus ret;
ret = CKYBuffer_Resize(buf, reader->cbAtr);
if (ret != CKYSUCCESS) {
return ret;
}
return CKYBuffer_Replace(buf, 0, reader->rgbAtr, reader->cbAtr);
}
SCARD_READERSTATE *
CKYReader_CreateArray(const CKYReaderNameList readerNames,
unsigned long *returnReaderCount)
{
unsigned long i,j;
unsigned long readerCount;
SCARD_READERSTATE *readers;
CKYStatus ret;
readerCount=CKYReaderNameList_GetCount(readerNames);
if (readerCount == 0) {
return NULL;
}
readers = NEW(SCARD_READERSTATE, readerCount);
if (readers == NULL) {
return NULL;
}
for (i=0; i < readerCount; i++) {
CKYReader_Init(&readers[i]);
ret = CKYReader_SetReaderName(&readers[i],
CKYReaderNameList_GetValue(readerNames,i));
if (ret != CKYSUCCESS) {
break;
}
}
if (ret != CKYSUCCESS) {
for (j=0; j < i; j++) {
CKYReader_FreeData(&readers[j]);
}
free(readers);
return NULL;
}
if (returnReaderCount) {
*returnReaderCount=readerCount;
}
return readers;
}
/*
* add more reader states to an existing reader state array.
* The existing reader will have a new pointer, which will be updated only
* after the new one is complete, and before the old one is freed. The 'add'
* array is not modified or freed.
*/
CKYStatus
CKYReader_AppendArray(SCARD_READERSTATE **array, unsigned long arraySize,
const char **readerNames, unsigned long numReaderNames)
{
unsigned long i,j;
SCARD_READERSTATE *readers;
SCARD_READERSTATE *old;
CKYStatus ret = CKYSUCCESS;
readers = NEW(SCARD_READERSTATE, arraySize+numReaderNames);
if (readers == NULL) {
return CKYNOMEM;
}
/* copy the original readers, inheriting all the pointer memory */
memcpy(readers, *array, arraySize*sizeof(SCARD_READERSTATE));
/* initialize and add the new reader states. */
for (i=0; i < numReaderNames; i++) {
CKYReader_Init(&readers[i+arraySize]);
ret = CKYReader_SetReaderName(&readers[i+arraySize],readerNames[i]);
if (ret != CKYSUCCESS) {
break;
}
}
/* we failed, only free the new reader states, ownership of the new
* ones will revert back to the original */
if (ret != CKYSUCCESS) {
for (j=0; j < i; j++) {
CKYReader_FreeData(&readers[j+arraySize]);
}
free(readers);
return ret;
}
/* Now we swap the readers states */
old = *array;
*array = readers;
/* it's now safe to free the old one */
free(old);
return CKYSUCCESS;
}
void
CKYReader_DestroyArray(SCARD_READERSTATE *reader, unsigned long readerCount)
{
unsigned long i;
for (i=0; i < readerCount; i++) {
CKYReader_FreeData(&reader[i]);
}
free(reader);
}
/*
* CKYCardContexts are wrapped access to the SCard Context, which is
* part of the openSC/ Microsoft PCSC interface. Applications will
* typically open one context to get access to the SCard Subsystem.
*
* To protect ourselves from systems without the SCard library installed,
* the SCard calls are looked up from the library and called through
* a function pointer.
*/
struct _CKYCardContext {
SCARDCONTEXT context;
SCard *scard;
unsigned long scope;
unsigned long lastError;
};
static CKYStatus
ckyCardContext_init(CKYCardContext *ctx)
{
static SCard *scard;
ctx->lastError = 0;
ctx->context = 0;
if (!scard) {
scard = ckySCard_Init();
if (!scard) {
return CKYNOSCARD;
}
}
ctx->scard = scard;
return CKYSUCCESS;
}
static CKYStatus
ckyCardContext_release(CKYCardContext *ctx)
{
unsigned long rv = ctx->scard->SCardReleaseContext(ctx->context);
ctx->context = 0;
if (rv != SCARD_S_SUCCESS) {
ctx->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
static CKYStatus
ckyCardContext_establish(CKYCardContext *ctx, unsigned long scope)
{
unsigned long rv;
if (ctx->context) {
ckyCardContext_release(ctx);
}
rv = ctx->scard->SCardEstablishContext(scope, NULL, NULL, &ctx->context);
if (rv != SCARD_S_SUCCESS) {
ctx->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYCardContext *
CKYCardContext_Create(unsigned long scope)
{
CKYCardContext *ctx;
CKYStatus ret;
ctx = NEW(CKYCardContext, 1);
if (ctx == NULL) {
return NULL;
}
ret = ckyCardContext_init(ctx);
if (ret != CKYSUCCESS) {
CKYCardContext_Destroy(ctx);
return NULL;
}
ctx->scope = scope;
ret = ckyCardContext_establish(ctx, scope);
#ifdef MAC
/* Apple won't establish a connnection if pcscd is not running. Because of
* the way securityd controls pcscd, this may not necessarily be an error
* condition. Detect this case and continue. We'll establish the connection
* later..
*/
if (ctx->lastError == SCARD_F_INTERNAL_ERROR) {
ctx->context = 0; /* make sure it's not established */
return ctx;
}
#endif
if (ret != CKYSUCCESS) {
CKYCardContext_Destroy(ctx);
return NULL;
}
return ctx;
}
CKYStatus
CKYCardContext_Destroy(CKYCardContext *ctx)
{
CKYStatus ret = CKYSUCCESS;
if (ctx == NULL) {
return CKYSUCCESS;
}
if (ctx->context) {
ret = ckyCardContext_release(ctx);
}
free(ctx);
return ret;
}
SCARDCONTEXT
CKYCardContext_GetContext(const CKYCardContext *ctx)
{
return ctx->context;
}
CKYStatus
CKYCardContext_ListReaders(CKYCardContext *ctx, CKYReaderNameList *readerNames)
{
unsigned long readerLen;
unsigned long rv;
char * readerStr = NULL;
char *cur;
char ** readerList;
int count,i;
/* return NULL in the case nothing is found, or there is an error */
*readerNames = NULL;
/* if we aren't established yet, do so now */
if (!ctx->context) {
CKYStatus ret = ckyCardContext_establish(ctx, ctx->scope);
if (ret != CKYSUCCESS) {
#ifdef MAC
if (ctx->lastError == SCARD_F_INTERNAL_ERROR) {
/* Still can't establish, just treat it as 'zero' readers */
return CKYSUCCESS;
}
#endif
return ret;
}
}
/* get the initial length */
readerLen = 0;
rv = ctx->scard->SCardListReaders(ctx->context, NULL /*groups*/,
NULL, &readerLen);
/* handle the other errors from SCardListReaders */
if (rv == SCARD_E_NO_READERS_AVAILABLE) {
/* not really an error: there are no readers */
return CKYSUCCESS;
}
if( rv != SCARD_S_SUCCESS ) {
ctx->lastError = rv;
return CKYSCARDERR;
}
/* if no readers, return OK and a NULL list */
if (readerLen == 0) {
return CKYSUCCESS;
}
/*
* Keep trying to read in the buffer, allowing that the required buffer
* length may change between calls to SCardListReaders.
*/
do {
if (readerLen < 1 || readerLen > CKY_OUTRAGEOUS_MALLOC_SIZE) {
return CKYNOMEM;
}
readerStr = NEW(char,readerLen);
if (readerStr == NULL) {
return CKYNOMEM;
}
rv = ctx->scard->SCardListReaders(ctx->context, NULL /*groups*/,
readerStr, &readerLen);
/* we've found it, pop out with readerStr allocated */
if (rv == SCARD_S_SUCCESS) {
break;
}
/* Nope, free the reader we allocated */
free(readerStr);
readerStr = NULL;
} while( rv == SCARD_E_INSUFFICIENT_BUFFER );
/* handle the other errors from SCardListReaders */
if (rv == SCARD_E_NO_READERS_AVAILABLE) {
/* not really an error: there are no readers */
ctx->lastError = SCARD_E_NO_READERS_AVAILABLE;
return CKYSUCCESS;
}
if (rv != SCARD_S_SUCCESS) {
/* stash the error and fail */
ctx->lastError = rv;
return CKYSCARDERR;
}
/*
* Windows returns the list of readers as a series of null terminated
* strings, terminated with an additional NULL. For example, if there
* are three readers name "Reader 1", "Reader 2", "Reader 3", the returned
* readerStr would look like: "Reader 1\0Reader 2\0Reader N\0\0".
*
* We need to return a list of ReaderNames. This is currently a pointer
* to an array of string pointers, terminated by a NULL.
*
* +--------------+
* | Reader 1 ptr | -> "Reader 1"
* +--------------+
* | Reader 2 ptr | -> "Reader 2"
* +--------------+
* | Reader N ptr | -> "Reader N"
* +--------------+
* | NULL |
* +--------------+
*
* NOTE: This code explicitly knows the underlying format for
* CKYReaderNameLists defined in cky_list.i. If cky_list.i is changes,
* this code will need to be changed as well.
*/
/* find the count of readers */
for (cur = readerStr, count = 0; *cur; cur += strlen(cur)+1, count++ )
/* Empty */ ;
readerList = NEW(char *,count+1);
if (readerList == NULL) {
goto fail;
}
/* now copy the readers into the array */
for (i=0, cur=readerStr; i < count ; cur+=strlen(cur) +1, i++) {
readerList[i] = strdup(cur);
if (readerList[i] == NULL) {
goto fail;
}
}
readerList[count] = NULL;
free(readerStr);;
*readerNames = (CKYReaderNameList) readerList;
return CKYSUCCESS;
fail:
if (readerStr) {
free(readerStr);
}
if (readerList) {
CKYReaderNameList_Destroy((CKYReaderNameList) readerList);
}
return CKYNOMEM;
}
/*
* The original C++ API had to very similiar functions that returned
* either reader names or connections based on ATR. This is a single
* function that can return both. The exported interface calls this
* one with one of the lists set to NULL.
*
* NOTE: this function "knows" the underlying format for lists and
* hand builds the related lists.
*/
CKYStatus
ckyCardContext_findReadersByATR(CKYCardContext *ctx,
CKYReaderNameList *returnReaders,
CKYCardConnectionList *returnConn,
const CKYBuffer *targetATR)
{
CKYReaderNameList readerNames;
CKYBuffer ATR;
CKYCardConnection **connList = NULL;
CKYCardConnection **connPtr = NULL;
char **readerList = NULL;
char **readerPtr = NULL;
int readerCount, i;
CKYStatus ret;
CKYBuffer_InitEmpty(&ATR);
/* if we aren't established yet, do so now */
if (!ctx->context) {
ret = ckyCardContext_establish(ctx, ctx->scope);
if (ret != CKYSUCCESS) {
return ret;
}
}
/* initialize our returned values to empty */
if (returnReaders) {
*returnReaders = NULL;
}
if (returnConn) {
*returnConn = NULL;
}
ret = CKYCardContext_ListReaders(ctx, &readerNames);
if (ret != CKYSUCCESS) {
return ret;
}
readerCount = CKYReaderNameList_GetCount(readerNames);
/* none found, return success */
if (readerCount == 0) {
CKYReaderNameList_Destroy(readerNames);
return CKYSUCCESS;
}
/* now initialize our name and connection lists */
if (returnConn) {
connList = NEW(CKYCardConnection *, readerCount);
connPtr = connList;
if (connList == NULL) {
goto fail;
}
}
if (returnReaders) {
readerList = NEW(char *, readerCount);
readerPtr = readerList;
if (readerList == NULL) {
goto fail;
}
}
ret = CKYBuffer_Resize(&ATR, CKY_MAX_ATR_LEN);
if (ret != CKYSUCCESS) {
goto fail;
}
/* now walk the reader list trying to get connections */
for (i=0; i < readerCount ; i++) {
CKYCardConnection * conn = CKYCardConnection_Create(ctx);
unsigned long state;
const char *thisReader = CKYReaderNameList_GetValue(readerNames, i);
if (!conn) {
goto loop;
}
ret = CKYCardConnection_Connect(conn, thisReader);
if (ret != CKYSUCCESS) {
goto loop;
}
ret = CKYCardConnection_GetStatus(conn, &state, &ATR);
if (ret != CKYSUCCESS) {
goto loop;
}
if (CKYBuffer_IsEqual(targetATR, &ATR)) {
if (connPtr) {
*connPtr++ = conn; /* adopt */
conn = NULL;
}
if (readerPtr) {
*readerPtr++ = strdup(thisReader);
}
}
loop:
/* must happen each time through the loop */
if (conn) {
CKYCardConnection_Destroy(conn);
}
}
/* done with the reader names now */
CKYReaderNameList_Destroy(readerNames);
/* and the ATR buffer */
CKYBuffer_FreeData(&ATR);
/* terminate out lists and return them */
if (readerPtr) {
*readerPtr = NULL;
*returnReaders = (CKYReaderNameList) readerList;
}
if (connPtr) {
*connPtr = NULL;
*returnConn = (CKYCardConnectionList) connList;
}
return CKYSUCCESS;
fail:
if (readerNames) {
CKYReaderNameList_Destroy(readerNames);
}
if (connList) {
free(connList);
}
if (readerList) {
free(readerList);
}
CKYBuffer_FreeData(&ATR);
return CKYNOMEM;
}
CKYStatus
CKYCardContext_FindCardsByATR(CKYCardContext *ctx,
CKYCardConnectionList *cardList, const CKYBuffer *targetATR)
{
return ckyCardContext_findReadersByATR(ctx, NULL, cardList, targetATR);
}
CKYStatus
CKYCardContext_FindReadersByATR(CKYCardContext *ctx,
CKYReaderNameList *readerNames, const CKYBuffer *targetATR)
{
return ckyCardContext_findReadersByATR(ctx, readerNames, NULL, targetATR);
}
CKYCardConnection *
CKYCardContext_CreateConnection(CKYCardContext *ctx)
{
return CKYCardConnection_Create(ctx);
}
CKYStatus
CKYCardContext_WaitForStatusChange(CKYCardContext *ctx,
SCARD_READERSTATE *readers, unsigned long readerCount,
unsigned long timeout)
{
unsigned long rv;
/* if we aren't established yet, do so now */
if (!ctx->context) {
CKYStatus ret = ckyCardContext_establish(ctx, ctx->scope);
if (ret != CKYSUCCESS) {
return ret;
}
}
rv = ctx->scard->SCardGetStatusChange(ctx->context, timeout,
readers, readerCount);
if (rv != SCARD_S_SUCCESS) {
ctx->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYStatus
CKYCardContext_Cancel(CKYCardContext *ctx)
{
unsigned long rv;
/* if we aren't established yet, we can't be in change status then */
if (!ctx->context) {
return CKYSUCCESS;
}
rv = ctx->scard->SCardCancel(ctx->context);
if (rv != SCARD_S_SUCCESS) {
ctx->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
unsigned long
CKYCardContext_GetLastError(const CKYCardContext *ctx)
{
return ctx->lastError;
}
/*
* Connections represent the connection to the actual smart cards.
* Applications usually has one of these for each card inserted in
* the system. Connections are where we can get information about
* each card, as well as transmit commands (APDU's) to the card.
*/
/* In the originaly C++ library, lastError was set to the last return
* code from any SCARD call. In this C version of the library, lastError
* is the last non-successful SCARD call. lastError will be set
* if the function returns CKYSCARDERR.
*/
struct _CKYCardConnection {
const CKYCardContext *ctx;
SCard *scard; /* cache a copy from the context */
SCARDHANDLE cardHandle;
unsigned long lastError;
CKYBool inTransaction;
};
static void
ckyCardConnection_init(CKYCardConnection *conn, const CKYCardContext *ctx)
{
conn->ctx = ctx;
conn->scard = ctx->scard;
conn->cardHandle = 0;
conn->lastError = 0;
conn->inTransaction = 0;
}
CKYCardConnection *
CKYCardConnection_Create(const CKYCardContext *ctx)
{
CKYCardConnection *conn;
/* don't even try if we don't have a Card Context */
if (ctx == NULL) {
return NULL;
}
conn = NEW(CKYCardConnection, 1);
if (conn == NULL) {
return NULL;
}
ckyCardConnection_init(conn, ctx);
return conn;
}
CKYStatus
CKYCardConnection_Destroy(CKYCardConnection *conn)
{
if (conn == NULL) {
return CKYSUCCESS;
}
if (conn->inTransaction) {
CKYCardConnection_EndTransaction(conn);
}
CKYCardConnection_Disconnect(conn);
free(conn);
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_Connect(CKYCardConnection *conn, const char *readerName)
{
CKYStatus ret;
unsigned long rv;
unsigned long protocol;
ret = CKYCardConnection_Disconnect(conn);
if (ret != CKYSUCCESS) {
return ret;
}
rv = conn->scard->SCardConnect( conn->ctx->context, readerName,
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &conn->cardHandle, &protocol);
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_Disconnect(CKYCardConnection *conn)
{
unsigned long rv;
if (conn->cardHandle == 0) {
return CKYSUCCESS;
}
rv = conn->scard->SCardDisconnect( conn->cardHandle, SCARD_LEAVE_CARD);
conn->cardHandle = 0;
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYBool
CKYCardConnection_IsConnected(const CKYCardConnection *conn)
{
return (conn->cardHandle != 0);
}
CKYStatus
ckyCardConnection_reconnectRaw(CKYCardConnection *conn, unsigned long init)
{
unsigned long rv;
unsigned long protocol;
rv = conn->scard->SCardReconnect(conn->cardHandle,
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, init, &protocol);
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_Reconnect(CKYCardConnection *conn)
{
return ckyCardConnection_reconnectRaw(conn, SCARD_LEAVE_CARD);
}
CKYStatus CKYCardConnection_Reset(CKYCardConnection *conn)
{
return ckyCardConnection_reconnectRaw(conn, SCARD_RESET_CARD);
}
CKYStatus
CKYCardConnection_BeginTransaction(CKYCardConnection *conn)
{
unsigned long rv;
rv = conn->scard->SCardBeginTransaction(conn->cardHandle);
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
}
conn->inTransaction = 1;
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_EndTransaction(CKYCardConnection *conn)
{
unsigned long rv;
if (!conn->inTransaction) {
return CKYSUCCESS; /* C++ library returns success in this case, but
* it may be better to return an error ? */
}
rv = conn->scard->SCardEndTransaction(conn->cardHandle, SCARD_LEAVE_CARD);
conn->inTransaction = 0;
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_TransmitAPDU(CKYCardConnection *conn, CKYAPDU *apdu,
CKYBuffer *response)
{
CKYStatus ret;
unsigned long rv;
ret = CKYBuffer_Resize(response, CKYAPDU_MAX_LEN);
if (ret != CKYSUCCESS) {
return ret;
}
rv = conn->scard->SCardTransmit(conn->cardHandle,
conn->scard->SCARD_PCI_T0_,
CKYBuffer_Data(&apdu->apduBuf), CKYBuffer_Size(&apdu->apduBuf),
NULL, response->data, &response->len);
if (rv != SCARD_S_SUCCESS) {
conn->lastError =rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_ExchangeAPDU(CKYCardConnection *conn, CKYAPDU *apdu,
CKYBuffer *response)
{
CKYStatus ret;
ret = CKYCardConnection_TransmitAPDU(conn, apdu, response);
if (ret != CKYSUCCESS) {
return ret;
}
if (CKYBuffer_Size(response) == 2 && CKYBuffer_GetChar(response,0) == 0x61) {
/* get the response */
CKYAPDU getResponseAPDU;
CKYAPDU_Init(&getResponseAPDU);
CKYAPDU_SetCLA(&getResponseAPDU, 0x00);
CKYAPDU_SetINS(&getResponseAPDU, 0xc0);
CKYAPDU_SetP1(&getResponseAPDU, 0x00);
CKYAPDU_SetP2(&getResponseAPDU, 0x00);
CKYAPDU_SetReceiveLen(&getResponseAPDU, CKYBuffer_GetChar(response,1));
ret = CKYCardConnection_TransmitAPDU(conn, &getResponseAPDU, response);
CKYAPDU_FreeData(&getResponseAPDU);
}
return ret;
}
CKYStatus
CKYCardConnection_GetStatus(CKYCardConnection *conn,
unsigned long *state, CKYBuffer *ATR)
{
unsigned long readerLen = 0;
unsigned long protocol;
unsigned long rv;
CKYSize atrLen;
char *readerStr;
CKYStatus ret;
/*
* Get initial length. We have to do all this because the Muscle
* implementation of PCSC requires us to supply a non-NULL argument
* for readerName before it will tell us the ATR, which is all we really
* care about.
*/
rv = conn->scard->SCardStatus(conn->cardHandle,
NULL /*readerName*/, &readerLen, state, &protocol, NULL, &atrLen);
if ( rv != SCARD_S_SUCCESS ) {
conn->lastError = rv;
return CKYSCARDERR;
}
do {
if (readerLen < 1 || readerLen > CKY_OUTRAGEOUS_MALLOC_SIZE) {
return CKYNOMEM;
}
/* Mac & Linux return '0' or ATR length, just use the max value */
if (atrLen == 0) {
atrLen = CKY_MAX_ATR_LEN;
}
if (atrLen < 1 || atrLen > CKY_OUTRAGEOUS_MALLOC_SIZE) {
return CKYNOMEM;
}
ret = CKYBuffer_Resize(ATR, atrLen);
if (ret != CKYSUCCESS) {
return ret;
}
readerStr = NEW(char, readerLen);
if (readerStr == NULL) {
return CKYNOMEM;
}
rv = conn->scard->SCardStatus(conn->cardHandle, readerStr, &readerLen,
state, &protocol, ATR->data, &atrLen);
ATR->len = atrLen;
free(readerStr);
} while (rv == SCARD_E_INSUFFICIENT_BUFFER);
if (rv != SCARD_S_SUCCESS) {
conn->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
}
CKYStatus
CKYCardConnection_GetAttribute(CKYCardConnection *conn,
unsigned long attrID, CKYBuffer *attrBuf)
{
#ifdef WIN32
unsigned long len = 0;
unsigned long rv;
/*
* Get initial length. We have to do all this because the Muscle
* implementation of PCSC requires us to supply a non-NULL argument
* for readerName before it will tell us the ATR, which is all we really
* care about.
*/
rv = conn->scard->SCardGetAttrib(conn->cardHandle, attrID, NULL, &len);
if ( rv != SCARD_S_SUCCESS ) {
conn->lastError = rv;
return CKYSCARDERR;
}
CKYBuffer_Resize(attrBuf, len);
rv = conn->scard->SCardGetAttrib(conn->cardHandle, attrID,
attrBuf->data, &attrBuf->len);
if( rv != SCARD_S_SUCCESS ) {
conn->lastError = rv;
return CKYSCARDERR;
}
return CKYSUCCESS;
#else
conn->lastError = -1;
return CKYSCARDERR;
#endif
}
const CKYCardContext *
CKYCardConnection_GetContext(const CKYCardConnection *conn)
{
return conn->ctx;
}
unsigned long
CKYCardConnection_GetLastError(const CKYCardConnection *conn)
{
return conn->lastError;
}
--- NEW FILE cky_card.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_CARD_H
#define CKY_CARD_H 1
#include <winscard.h>
#include "cky_base.h"
#include "cky_list.h"
/*
* hide the structure of CardConnections and CardContexts
*/
typedef struct _CKYCardContext CKYCardContext;
typedef struct _CKYCardConnection CKYCardConnection;
/*
* define CKYReaderNameList, CKYReaderNameIterator, CKYCardConnectionList, and
* CKYCardConnectionIterator, and their associated functions.
* See cky_list.h for these functions .
*/
CKYLIST_DECLARE(CKYReaderName, char *)
CKYLIST_DECLARE(CKYCardConnection, CKYCardConnection *)
CKY_BEGIN_PROTOS
void CKYReader_Init(SCARD_READERSTATE_A *reader);
void CKYReader_FreeData(SCARD_READERSTATE_A *reader);
/*
* "Accessors": for SCARD_READERSTATE_A structure as a class.
* These functions take an SCARD_READERSTATE_A which can also be referenced
* directly.
*/
CKYStatus CKYReader_SetReaderName(SCARD_READERSTATE_A *reader, const char *name);
const char *CKYReader_GetReaderName(const SCARD_READERSTATE_A *reader);
CKYStatus CKYReader_SetKnownState(SCARD_READERSTATE_A *reader,
unsigned long state);
unsigned long CKYReader_GetKnownState(const SCARD_READERSTATE_A *reader);
unsigned long CKYReader_GetEventState(const SCARD_READERSTATE_A *reader);
CKYStatus CKYReader_GetATR(const SCARD_READERSTATE_A *reader, CKYBuffer *buf);
/* create an array of READERSTATEs from a LIST of Readers */
SCARD_READERSTATE_A *CKYReader_CreateArray(const CKYReaderNameList readerNames,
unsigned long *readerCount);
/* frees the reader, then the full array */
void CKYReader_DestroyArray(SCARD_READERSTATE *reader, unsigned long count);
/* add more elements to a ReaderState array*/
CKYStatus
CKYReader_AppendArray(SCARD_READERSTATE **array, unsigned long arraySize,
const char **readerNames, unsigned long numReaderNames);
/*
* card contexts wrap Microsoft's SCARDCONTEXT.
*/
/* create a new one. SCOPE must be SCOPE_USER */
CKYCardContext *CKYCardContext_Create(unsigned long scope);
/* destroy an existing one */
CKYStatus CKYCardContext_Destroy(CKYCardContext *context);
/* get the Windows handle associated with this context */
SCARDCONTEXT CKYCardContext_GetContext(const CKYCardContext *context);
/* Get a list of the installed readers */
CKYStatus CKYCardContext_ListReaders(CKYCardContext *context,
CKYReaderNameList *readerNames);
/* get a list of card connections for cards matching our target ATR */
CKYStatus CKYCardContext_FindCardsByATR(CKYCardContext *context,
CKYCardConnectionList *cardList,
const CKYBuffer *targetATR);
/* get a list of readers with attached cards that match our target ATR */
CKYStatus CKYCardContext_FindReadersByATR(CKYCardContext *context,
CKYReaderNameList *readerNames,
const CKYBuffer *targetATR);
/* return if any of the readers in our array has changed in status */
CKYStatus CKYCardContext_WaitForStatusChange(CKYCardContext *context,
SCARD_READERSTATE_A *readers,
unsigned long readerCount,
unsigned long timeout);
/* cancel any current operation (such as wait for status change) on this
* context */
CKYStatus CKYCardContext_Cancel(CKYCardContext *context);
/* get the last underlying Windows SCARD error */
unsigned long CKYCardContext_GetLastError(const CKYCardContext *context);
/*
* manage the actual connection to a card.
*/
/* create a connection. A connection is not associated with a reader
* until CKYCardConnection_Connect() is called.
*/
CKYCardConnection *CKYCardConnection_Create(const CKYCardContext *context);
CKYStatus CKYCardConnection_Destroy(CKYCardConnection *connection);
CKYStatus CKYCardConnection_BeginTransaction(CKYCardConnection *connection);
CKYStatus CKYCardConnection_EndTransaction(CKYCardConnection *connection);
CKYStatus CKYCardConnection_TransmitAPDU(CKYCardConnection *connection,
CKYAPDU *apdu,
CKYBuffer *response);
CKYStatus CKYCardConnection_ExchangeAPDU(CKYCardConnection *connection,
CKYAPDU *apdu,
CKYBuffer *response);
CKYStatus CKYCardConnection_Connect(CKYCardConnection *connection,
const char *readerName);
CKYStatus CKYCardConnection_Disconnect(CKYCardConnection *connection);
CKYBool CKYCardConnection_IsConnected(const CKYCardConnection *connection);
CKYStatus CKYCardConnection_Reconnect(CKYCardConnection *connection);
CKYStatus CKYCardConnection_GetStatus(CKYCardConnection *connection,
unsigned long *state, CKYBuffer *ATR);
CKYStatus CKYCardConnection_GetAttribute(CKYCardConnection *connection,
unsigned long attrID, CKYBuffer *attrBuf);
CKYStatus CKYCardConnection_Reset(CKYCardConnection *connection);
const CKYCardContext *CKYCardConnection_GetContext(const CKYCardConnection *cxt);
unsigned long CKYCardConnection_GetLastError(const CKYCardConnection *context);
CKY_END_PROTOS
#endif /* CKY_CARD_H */
--- NEW FILE cky_factory.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include "string.h"
#include "cky_base.h"
#include "cky_factory.h"
/*
* special commands can be issued at any time
*/
CKYStatus
CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CKY_INS_SELECT_FILE);
CKYAPDU_SetP1(apdu, 0x04);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetSendDataBuffer(apdu, AID);
}
CKYStatus
CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu)
{
CKYByte c = 0;
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CKY_INS_SELECT_FILE);
CKYAPDU_SetP1(apdu, 0x04);
CKYAPDU_SetP2(apdu, 0x00);
/* I can't find the documentation for this, but if you pass an empty
* AID to SelectFile on the Cyberflex Access 32k, it selects the
* CardManager applet. Good thing, because I couldn't find any other
* way to accomplish this without knowing the AID of the CardManager. */
return CKYAPDU_SetSendData(apdu,&c,0);
}
/*
* card manager commands must be issued with the card manager selected.
*/
CKYStatus
CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_GLOBAL_PLATFORM);
CKYAPDU_SetINS(apdu, CKY_INS_GET_DATA);
CKYAPDU_SetP1(apdu, 0x9f);
CKYAPDU_SetP2(apdu, 0x7f);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_CPLCDATA);
}
/*
* applet commands must be issued with the appplet selected.
*/
CKYStatus
CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_LIST_KEYS);
CKYAPDU_SetP1(apdu, sequence);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_LIST_KEYS);
}
CKYStatus
CKYAPDUFactory_ComputeCryptInit(CKYAPDU *apdu, CKYByte keyNumber, CKYByte mode,
CKYByte direction, CKYByte location)
{
CKYByte data[5];
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
CKYAPDU_SetP1(apdu, keyNumber);
CKYAPDU_SetP2(apdu, CKY_CIPHER_INIT);
data[0] = mode;
data[1] = direction;
data[2] = location;
data[3] = 0; /* future provide for init data */
data[4] = 0;
return CKYAPDU_SetSendData(apdu, data, sizeof(data));
}
CKYStatus
CKYAPDUFactory_ComputeCryptProcess(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data)
{
CKYStatus ret;
CKYBuffer buf;
CKYBuffer_InitEmpty(&buf);
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
CKYAPDU_SetP1(apdu, keyNumber);
CKYAPDU_SetP2(apdu, CKY_CIPHER_PROCESS);
if (data) {
ret = CKYBuffer_Reserve(&buf, 3);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendChar(&buf, location);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf, (unsigned short)CKYBuffer_Size(data));
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
} else {
ret = CKYAPDU_SetSendData(apdu, &location, 1);
}
fail:
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data, const CKYBuffer *sig)
{
CKYStatus ret;
CKYBuffer buf;
CKYBuffer_InitEmpty(&buf);
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
CKYAPDU_SetP1(apdu, keyNumber);
CKYAPDU_SetP2(apdu, CKY_CIPHER_FINAL);
if (data) {
ret = CKYBuffer_Reserve(&buf, 3);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendChar(&buf, location);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf, (unsigned short)CKYBuffer_Size(data));
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_AppendSendDataBuffer(apdu, data);
if (ret != CKYSUCCESS) {
goto fail;
}
if (sig) {
CKYBuffer_Resize(&buf,2);
CKYBuffer_SetShort(&buf, 0, (unsigned short)CKYBuffer_Size(sig));
ret = CKYAPDU_AppendSendDataBuffer(apdu, &buf);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_AppendSendDataBuffer(apdu, sig);
}
} else {
ret = CKYAPDU_SetSendData(apdu, &location, 1);
}
fail:
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_ComputeCryptOneStep(CKYAPDU *apdu, CKYByte keyNumber, CKYByte mode,
CKYByte direction, CKYByte location,
const CKYBuffer *idata, const CKYBuffer *sig)
{
CKYStatus ret = CKYINVALIDARGS;
CKYSize len;
CKYBuffer buf;
if (!idata || !(len = CKYBuffer_Size(idata)) || location != CKY_DL_APDU)
return ret;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_COMPUTE_CRYPT);
CKYAPDU_SetP1(apdu, keyNumber);
CKYAPDU_SetP2(apdu, CKY_CIPHER_ONE_STEP);
CKYBuffer_InitEmpty(&buf);
ret = CKYBuffer_Reserve(&buf, 5);
if (ret == CKYSUCCESS)
ret = CKYBuffer_AppendChar(&buf, mode);
if (ret == CKYSUCCESS)
ret = CKYBuffer_AppendChar(&buf, direction);
if (ret == CKYSUCCESS)
ret = CKYBuffer_AppendChar(&buf, location);
if (ret == CKYSUCCESS)
ret = CKYBuffer_AppendShort(&buf, (unsigned short)len);
if (ret == CKYSUCCESS)
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
if (ret == CKYSUCCESS)
ret = CKYAPDU_AppendSendDataBuffer(apdu, idata);
if (ret == CKYSUCCESS && sig && 0 < (len = CKYBuffer_Size(sig))) {
CKYBuffer_Resize(&buf,2);
CKYBuffer_SetShort(&buf, 0, (unsigned short)len);
ret = CKYAPDU_AppendSendDataBuffer(apdu, &buf);
if (ret == CKYSUCCESS)
ret = CKYAPDU_AppendSendDataBuffer(apdu, sig);
}
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_CreatePIN(CKYAPDU *apdu, CKYByte pinNumber, CKYByte maxAttempts,
const char *pinValue)
{
CKYSize len;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_CREATE_PIN);
CKYAPDU_SetP1(apdu, pinNumber);
CKYAPDU_SetP2(apdu, maxAttempts);
len = strlen(pinValue);
return CKYAPDU_SetSendData(apdu, (unsigned char *)pinValue, len);
}
CKYStatus
CKYAPDUFactory_VerifyPIN(CKYAPDU *apdu, CKYByte pinNumber, const char *pinValue)
{
CKYSize len;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_VERIFY_PIN);
CKYAPDU_SetP1(apdu, pinNumber);
CKYAPDU_SetP2(apdu, 0x00);
len = strlen(pinValue);
return CKYAPDU_SetSendData(apdu, (unsigned char *)pinValue, len);
}
CKYStatus
CKYAPDUFactory_ChangePIN(CKYAPDU *apdu, CKYByte pinNumber, const char *oldPin,
const char *newPin)
{
CKYSize oldLen, newLen;
CKYBuffer buf;
CKYStatus ret;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_CHANGE_PIN);
CKYAPDU_SetP1(apdu, pinNumber);
CKYAPDU_SetP2(apdu, 0x00);
CKYBuffer_InitEmpty(&buf);
oldLen = strlen(oldPin);
newLen = strlen(newPin);
/* optimization, do a single malloc for the whole block */
ret = CKYBuffer_Reserve(&buf, oldLen+newLen+4);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf, (unsigned short)oldLen);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendData(&buf, (unsigned char *)oldPin, oldLen);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf, (unsigned short)newLen);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendData(&buf, (unsigned char *)newPin, newLen);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
fail:
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_ListPINs(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_LIST_PINS);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_LIST_PINS);
}
CKYStatus
CKYAPDUFactory_Logout(CKYAPDU *apdu, CKYByte pinNumber)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_LOGOUT);
CKYAPDU_SetP1(apdu, pinNumber);
CKYAPDU_SetP2(apdu, 0x00);
return CKYSUCCESS;
}
/* Future add WriteObject */
CKYStatus
CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID, CKYSize size,
unsigned short readACL, unsigned short writeACL, unsigned short deleteACL)
{
CKYBuffer buf;
CKYStatus ret;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_CREATE_OBJ);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
CKYBuffer_InitEmpty(&buf);
/* optimization, do a single malloc for the whole block */
ret = CKYBuffer_Reserve(&buf,0x0e);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendLong(&buf,objectID);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendLong(&buf,size);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf,readACL);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf,writeACL);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendShort(&buf,deleteACL);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
fail:
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_DeleteObject(CKYAPDU *apdu, unsigned long objectID, CKYByte zero)
{
CKYBuffer buf;
CKYStatus ret;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_DELETE_OBJ);
CKYAPDU_SetP1(apdu, zero);
CKYAPDU_SetP2(apdu, 0x00);
CKYBuffer_InitEmpty(&buf);
ret = CKYBuffer_AppendLong(&buf,objectID);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
fail:
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_ReadObject(CKYAPDU *apdu, unsigned long objectID,
CKYOffset offset, CKYByte size)
{
CKYBuffer buf;
CKYStatus ret;
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_READ_OBJ);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
CKYBuffer_InitEmpty(&buf);
/* optimization, do a single malloc for the whole block */
ret = CKYBuffer_Reserve(&buf,0x09);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendLong(&buf,objectID);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendLong(&buf,offset);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYBuffer_AppendChar(&buf, size);
if (ret != CKYSUCCESS) {
goto fail;
}
ret = CKYAPDU_SetSendDataBuffer(apdu, &buf);
fail:
CKYBuffer_FreeData(&buf);
return ret;
}
CKYStatus
CKYAPDUFactory_ListObjects(CKYAPDU *apdu, CKYByte sequence)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_LIST_OBJECTS);
CKYAPDU_SetP1(apdu, sequence);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_LIST_OBJECTS);
}
CKYStatus
CKYAPDUFactory_GetStatus(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_STATUS);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_STATUS);
}
CKYStatus
CKYAPDUFactory_Noop(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_NOP);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYSUCCESS;
}
CKYStatus
CKYAPDUFactory_GetBuildID(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_BUILDID);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_BUILDID);
}
CKYStatus
CKYAPDUFactory_GetLifeCycle(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_LIFECYCLE);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_LIFE_CYCLE);
}
CKYStatus
CKYAPDUFactory_GetLifeCycleV2(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_LIFECYCLE);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_LIFE_CYCLE_V2);
}
CKYStatus
CKYAPDUFactory_GetRandom(CKYAPDU *apdu, CKYByte len)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_RANDOM);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, len);
}
CKYStatus
CKYAPDUFactory_SeedRandom(CKYAPDU *apdu, const CKYBuffer *data)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_SEED_RANDOM);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetSendDataBuffer(apdu, data);
}
CKYStatus
CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_ISSUER_INFO);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_ISSUER_INFO);
}
CKYStatus
CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_COOLKEY);
CKYAPDU_SetINS(apdu, CKY_INS_GET_BUILTIN_ACL);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CKY_SIZE_GET_BUILTIN_ACL);
}
CKYStatus
CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CAC_INS_SIGN_DECRYPT);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetSendDataBuffer(apdu, data);
}
CKYStatus
CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CAC_INS_GET_CERTIFICATE);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, size);
}
CKYStatus
CACAPDUFactory_GetProperties(CKYAPDU *apdu)
{
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CAC_INS_GET_PROPERTIES);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
return CKYAPDU_SetReceiveLen(apdu, CAC_SIZE_GET_PROPERTIES);
}
CKYStatus
CACAPDUFactory_VerifyPIN(CKYAPDU *apdu, const char *pin)
{
CKYStatus ret;
CKYSize size;
CKYAPDU_SetCLA(apdu, CKY_CLASS_ISO7816);
CKYAPDU_SetINS(apdu, CAC_INS_VERIFY_PIN);
CKYAPDU_SetP1(apdu, 0x00);
CKYAPDU_SetP2(apdu, 0x00);
/* no pin, send an empty buffer */
if (!pin) {
return CKYAPDU_SetReceiveLen(apdu, 0);
}
/* all CAC pins are 8 bytes exactly. If to long, truncate it */
size = strlen(pin);
if (size > 8) {
size = 8;
}
ret = CKYAPDU_SetSendData(apdu, (unsigned char *) pin, size);
/* if too short, pad it */
if ((ret == CKYSUCCESS) && (size < 8)) {
static const unsigned char pad[]= { 0xff , 0xff, 0xff ,0xff,
0xff, 0xff, 0xff, 0xff };
return CKYAPDU_AppendSendData(apdu, pad, 8-size);
}
return ret;
}
--- NEW FILE cky_factory.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_FACTORY_H
#define CKY_FACTORY_H 1
#include "cky_base.h"
/*
* Various Class bytes
*/
#define CKY_CLASS_ISO7816 0x00
#define CKY_CLASS_GLOBAL_PLATFORM 0x80
#define CKY_CLASS_SECURE 0x84
#define CKY_CLASS_COOLKEY 0xb0
/*
* Applet Instruction Bytes
*/
/* Card Manager */
#define CKY_INS_SELECT_FILE 0xa4
#define CKY_INS_GET_DATA 0xca
/* deprecated */
#define CKY_INS_SETUP 0x2A
#define CKY_INS_GEN_KEYPAIR 0x30
#define CKY_INS_EXPORT_KEY 0x34
#define CKY_INS_UNBLOCK_PIN 0x46
#define CKY_INS_GET_CHALLENGE 0x62
#define CKY_INS_CAC_EXT_AUTH 0x38
#define CKY_INS_LOGOUT_ALL 0x60
/* public */
#define CKY_INS_VERIFY_PIN 0x42
#define CKY_INS_LIST_OBJECTS 0x58
#define CKY_INS_LIST_KEYS 0x3A
#define CKY_INS_LIST_PINS 0x48
#define CKY_INS_GET_STATUS 0x3C
#define CKY_INS_GET_LIFECYCLE 0xF2
#define CKY_INS_GET_ISSUER_INFO 0xF6
#define CKY_INS_GET_BUILTIN_ACL 0xFA
#define CKY_INS_GET_BUILDID 0x70
#define CKY_INS_GET_RANDOM 0x72
#define CKY_INS_SEED_RANDOM 0x73
#define CKY_INS_NOP 0x71
/* nonce validated only */
#define CKY_INS_LOGOUT 0x61
/* nonce validated & Secure Channel */
#define CKY_INS_IMPORT_KEY 0x32
#define CKY_INS_COMPUTE_CRYPT 0x36
#define CKY_INS_CREATE_PIN 0x40
#define CKY_INS_CHANGE_PIN 0x44
#define CKY_INS_CREATE_OBJ 0x5A
#define CKY_INS_DELETE_OBJ 0x52
#define CKY_INS_READ_OBJ 0x56
#define CKY_INS_WRITE_OBJ 0x54
/* Secure channel only */
#define CKY_INS_INIT_UPDATE 0x50
#define CKY_INS_SEC_EXT_AUTH 0x82
#define CKY_INS_SEC_SET_LIFECYCLE 0xF0
#define CKY_INS_SEC_SET_PIN 0x04
#define CKY_INS_SEC_READ_IOBUF 0x08
#define CKY_INS_SEC_START_ENROLLMENT 0x0C
/* CAC */
#define CAC_INS_GET_CERTIFICATE 0x36
#define CAC_INS_SIGN_DECRYPT 0x42
#define CAC_INS_VERIFY_PIN 0x20
#define CAC_INS_GET_PROPERTIES 0x56
#define CAC_SIZE_GET_PROPERTIES 48
/*
* Fixed return sized from various commands
*/
#define CKY_SIZE_GET_CPLCDATA 45
#define CKY_SIZE_LIST_KEYS 11
#define CKY_SIZE_LIST_PINS 2
#define CKY_SIZE_LIST_OBJECTS 14
#define CKY_SIZE_GET_STATUS 16
#define CKY_SIZE_GET_LIFE_CYCLE 1
#define CKY_SIZE_GET_LIFE_CYCLE_V2 4
#define CKY_SIZE_GET_BUILDID 4
#define CKY_SIZE_GET_ISSUER_INFO 0xe0
#define CKY_SIZE_GET_BUILTIN_ACL 7
/*
* Crypt functions
*/
/* functions */
#define CKY_CIPHER_INIT 1
#define CKY_CIPHER_PROCESS 2
#define CKY_CIPHER_FINAL 3
#define CKY_CIPHER_ONE_STEP 4 /* init and final in one APDU */
/* modes */
#define CKY_RSA_NO_PAD 0x00
#define CKY_RSA_PAD_PKCS1 0x01
#define CKY_DSA_SHA 0x10
#define CKY_DES_CBC_NOPAD 0x20
#define CKY_DES_ECB_NOPAD 0x21
/* operations (Cipher Direction) */
#define CKY_DIR_SIGN 0x01
#define CKY_DIR_VERIFY 0x02
#define CKY_DIR_ENCRYPT 0x03
#define CKY_DIR_DECRYPT 0x04
/* Data Location */
#define CKY_DL_APDU 0x01
#define CKY_DL_OBJECT 0x02
/* Key Types */
#define CKY_KEY_RSA_PUBLIC 0x01
#define CKY_KEY_RSA_PRIVATE 0x02
#define CKY_KEY_RSA_PRIVATE_CRT 0x03
#define CKY_KEY_DSA_PUBLIC 0x04
#define CKY_KEY_DSA_PRIVATE 0x05
#define CKY_KEY_DES 0x06
#define CKY_KEY_3DES 0x07
#define CKY_KEY_3DES3 0x08
/* List Operators */
#define CKY_LIST_RESET 0x00
#define CKY_LIST_NEXT 0x01
/* Max Size for a read block */
#define CKY_MAX_READ_CHUNK_SIZE 255
#define CKY_MAX_WRITE_CHUNK_SIZE 240
/* Life Cycle State */
#define CKY_APPLICATION_LOGICALLY_DELETED 0x00
#define CKY_APPLICATION_INSTALLED 0x03
#define CKY_APPLICATION_SELECTABLE 0x07
#define CKY_APPLICATION_PERSONALIZED 0x0f
#define CKY_APPLICATION_BLOCKED 0x7f
#define CKY_APPLICATION_LOCKED 0xff
#define CKY_CARDM_MANAGER_OP_READER 0x01
#define CKY_CARDM_MANAGER_INITIALIZED 0x03
#define CKY_CARDM_MANAGER_SECURED 0x0f
#define CKY_CARDM_MANAGER_LOCKED 0x7f
#define CKY_CARDM_MANAGER_TERMINATED 0xff
/*
* The following factories 'Fill in' APDUs for each of the
* functions described below. Nonces are not automatically added.
* APDU's are for COOLKEY version 1.0 protocol. Callers should pass
* in Already inited apdu's . Callers are responsible for freeing.
* the APDU data, even in event of failure.
*/
CKY_BEGIN_PROTOS
/* function based factorys */
CKYStatus CKYAPDUFactory_SelectFile(CKYAPDU *apdu, const CKYBuffer *AID);
CKYStatus CKYAPDUFactory_SelectCardManager(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetCPLCData(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_ListKeys(CKYAPDU *apdu, CKYByte sequence);
CKYStatus CKYAPDUFactory_ComputeCryptInit(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte mode, CKYByte direction, CKYByte location);
CKYStatus CKYAPDUFactory_ComputeCryptProcess(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data);
CKYStatus CKYAPDUFactory_ComputeCryptFinal(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte location, const CKYBuffer *data, const CKYBuffer *sig);
CKYStatus CKYAPDUFactory_ComputeCryptOneStep(CKYAPDU *apdu, CKYByte keyNumber,
CKYByte mode, CKYByte direction, CKYByte location,
const CKYBuffer *data, const CKYBuffer *sig);
CKYStatus CKYAPDUFactory_CreatePIN(CKYAPDU *apdu, CKYByte pinNumber,
CKYByte maxAttempts, const char *pinValue);
CKYStatus CKYAPDUFactory_VerifyPIN(CKYAPDU *apdu, CKYByte pinNumber,
const char *pinValue);
CKYStatus CKYAPDUFactory_ChangePIN(CKYAPDU *apdu, CKYByte pinNUmber,
const char *oldPin, const char *newPin);
CKYStatus CKYAPDUFactory_ListPINs(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_Logout(CKYAPDU *apdu, CKYByte pinNumber);
/* Future add WriteObject */
CKYStatus CKYAPDUFactory_CreateObject(CKYAPDU *apdu, unsigned long objectID,
CKYSize size, unsigned short readACL, unsigned short writeACL,
unsigned short deleteACL);
CKYStatus CKYAPDUFactory_DeleteObject(CKYAPDU *apdu, unsigned long objectID,
CKYByte zero);
CKYStatus CKYAPDUFactory_ReadObject(CKYAPDU *apdu, unsigned long objectID,
CKYOffset offset, CKYByte size);
CKYStatus CKYAPDUFactory_ListObjects(CKYAPDU *apdu, CKYByte sequence);
CKYStatus CKYAPDUFactory_GetStatus(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_Noop(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetBuildID(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetLifeCycle(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetLifeCycleV2(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetRandom(CKYAPDU *apdu, CKYByte len);
CKYStatus CKYAPDUFactory_SeedRandom(CKYAPDU *apdu, const CKYBuffer *data);
CKYStatus CKYAPDUFactory_GetIssuerInfo(CKYAPDU *apdu);
CKYStatus CKYAPDUFactory_GetBuiltinACL(CKYAPDU *apdu);
CKYStatus CACAPDUFactory_SignDecrypt(CKYAPDU *apdu, const CKYBuffer *data);
CKYStatus CACAPDUFactory_VerifyPIN(CKYAPDU *apdu, const char *pin);
CKYStatus CACAPDUFactory_GetCertificate(CKYAPDU *apdu, CKYSize size);
CKYStatus CACAPDUFactory_GetProperties(CKYAPDU *apdu);
CKY_END_PROTOS
#endif /* CKY_FACTORY_H */
--- NEW FILE cky_list.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_LIST_H
#define CKY_LIST_H 1
/*
* Macro to declare methods and types for CoolKey Lists.
*/
#define CKYLIST_DECLARE(name, type) \
typedef void *name##List; \
typedef void *name##Iterator; \
\
CKY_BEGIN_PROTOS \
/* get the number of elements in the name##List */ \
unsigned long name##List_GetCount(name##List list); \
\
/* returns the 'index'th element of the list. \
* This provides one way of walking the list... \
* \
* // acquire name##List list \
* int count; \
* int i; \
* \
* count = name##List_GetCount(list); \
* for (i=0; i < count; i++) { \
* const type value = name##List_GetValue(list, i); \
* \
* // Process value \
* } \
*/ \
const type name##List_GetValue(name##List list, unsigned long index); \
\
/* * Destroy a list */ \
void name##List_Destroy(name##List list); \
\
/* \
* The following iterators allows someone to easily walk the list using \
* the following sample code. These functions hide the underlying \
* implementation. \
* \
* // acquire name##List list \
* name##Iterator iter; \
* \
* for (iter = name##List_GetIterator(list); !name##Iterator_End(inter); \
* iter = name##Interator_Next(iter) ) { \
* const type value = name##Interator_GetValue(iter); \
* \
* // Process value \
* } \
* \
*/ \
name##Iterator name##List_GetIterator(name##List list); \
CKYBool name##Iterator_End(name##Iterator iter); \
name##Iterator name##Iterator_Next(name##Iterator iter); \
const type name##Iterator_GetValue(name##Iterator iter); \
CKY_END_PROTOS \
/* end of Declarations */
#endif /* CKY_LIST_H */
--- NEW FILE cky_list.i ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#ifndef CKY_LIST_I
#define CKY_LIST_I 1
#define CKYLIST_IMPLEMENT(name,type) \
\
/* \
* name##List is implemented as a pointer to a NULL terminated array of \
* type##s. A NULL name##List is valid and means a list with '0' elements \
* The actual type is a void * and the follow functions are designed to \
* hide the underlying structure of name##List. \
*/ \
\
/* get the number of elements in the reader List */ \
unsigned long \
name##List_GetCount(name##List list) \
{ \
type *current; \
int count; \
\
if (list == NULL) { \
return 0; \
} \
\
for (count=0, current = (type *)list; *current; current++, count++) { \
/* EMPTY */ ; \
} \
\
return count; \
} \
\
\
/* returns the 'index'th element of the list. \
* index is not checked for overruns in this implementation. \
* \
* This provides one way of walking the list... \
* \
* // acquire name##List list \
* int count; \
* int i; \
* \
* count = name##List_GetCount(list); \
* for (i=0; i < count; i++) { \
* const type value = name##List_GetValue(list, i); \
* \
* // Process value \
* } \
*/ \
const type \
name##List_GetValue(name##List list, unsigned long index) \
{ \
type *array = (type *)list; \
\
/* should probably be an assert */ \
if (list == NULL) { \
return NULL; \
} \
return array[index]; \
} \
\
/* Destroy a list */ \
void \
name##List_Destroy(name##List list) \
{ \
type *cur; \
if (list == NULL) { \
return ; \
} \
\
for (cur =(type *)list; *cur; cur++) { \
name##_Destroy(*cur); \
} \
free(list); \
} \
\
/* \
* The following iterators allows someone to easily walk the list using \
* the following sample code. These functions hide the underlying \
* implementation. \
* \
* // acquire name##List list \
* name##Iterator iter; \
* \
* for (iter = name##List_GetIterator(list); !name##Iterator_End(inter); \
* iter = name##Iterator_Next(iter) ) { \
* const type value = name##Iterator_GetValue(iter); \
* // process value \
* } \
* \
*/ \
name##Iterator \
name##List_GetIterator(name##List list) \
{ \
return (name##Iterator) list; \
} \
\
CKYBool \
name##Iterator_End(name##Iterator iter) \
{ \
if (iter == NULL) { \
return 1; \
} \
return *(type *)iter == NULL; \
} \
\
name##Iterator \
name##Iterator_Next(name##Iterator iter) \
{ \
if (iter == NULL) { \
return NULL; \
} \
return (name##Iterator) (((type *)iter)+1); \
} \
\
const type \
name##Iterator_GetValue(name##Iterator iter) \
{ \
/* assert(iter != NULL); */ \
return *(type *)iter; \
} \
\
/* \
* add functions to create lists, & add elements to lists \
*/ \
#endif /* CKY_LIST_I */
--- NEW FILE config.mk ---
# ***** BEGIN COPYRIGHT BLOCK *****
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
#
# 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 version
# 2.1 of the License.
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# ***** END COPYRIGHT BLOCK *****
#
# Override TARGETS variable so that only static libraries
# are specifed as dependencies within rules.mk.
#
TARGETS = $(LIBRARY)
SHARED_LIBRARY =
IMPORT_LIBRARY =
PROGRAM =
ifneq ($(OS_ARCH),WINNT)
EXPORTS += msc_winscard.h pcsclite.h wintypes.h
endif
--- NEW FILE dynlink.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include "../config.h"
#ifdef WIN32
#include "dynlink_win.c"
#else
#ifdef MAC
#include "dynlink_mac.c"
#else
#ifdef HAVE_DLFCN_H
#include "dynlink_unix.c"
#else
#error "Platform not supported... add dynlink_PLAT.c and update dynlink.c"
#endif
#endif
#endif
--- NEW FILE dynlink.h ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
/*
* the following header file is private to the CoolKey library.
* This is because CoolKey library is supposed to operate in the PKCS #11
* module which needs to be independent of runtimes like NSPR. Longer term
* there should be a generic version of this which uses the application
* runtime, and pkcs #11 supplies it's only copy of these functions.
*/
#ifndef CKY_SHLIB_H
#define CKY_SHLIB_H 1
#undef QUOTE
#undef QUOTE_MACRO
#define QUOTE(arg) #arg
#define QUOTE_MACRO(arg) QUOTE(arg)
/* Hmmm maybe this should be hidden in getAddress? */
#ifdef MAC
#define DLL_SYM_PREFIX "_"
#else
#define DLL_SYM_PREFIX
#endif
#define MAKE_DLL_SYMBOL(name) DLL_SYM_PREFIX QUOTE(name)
typedef void *ckyShLibrary;
ckyShLibrary ckyShLibrary_open(const char *libname);
CKYStatus ckyShLibrary_close(ckyShLibrary libHandle);
CKYStatus ckyShLibrary_getAddress(ckyShLibrary libHandle,
void **func, const char *funcName);
#ifdef MAC
void ckyShLibrary_setParent(char *name);
#endif
#endif
--- NEW FILE dynlink_mac.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
***** END COPYRIGHT BLOCK *****/
#include <mach-o/dyld.h>
#include <stdio.h>
#include "cky_base.h"
#include "dynlink.h"
#include "string.h"
#include "stdlib.h"
#define EXEPATH "@executable_path/"
#define SYSPATH "/System/Library/Frameworks/"
static char *ckyShLibrary_parent = NULL;
/* allow the parent library to set our name */
void
ckyShLibrary_setParent(char *p)
{
ckyShLibrary_parent = p;
}
#ifdef nodef
/* get the parent librarie's path */
char *
ckyShLibrary_getParentPath()
{
char *result;
char *image_name;
int i, count = _dyld_image_count();
if (ckyShLibrary_parent == NULL) {
return NULL;
}
for (i = 0; i < count; i++) {
image_name = _dyld_get_image_name(i);
if (strstr(image_name, ckyShLibrary_parent) != NULL) {
result = malloc(strlen(image_name)+1);
if (result != NULL) {
char *truncate;
strcpy(result, image_name);
truncate = strrchr(result,'/');
if (truncate) {
*(truncate+1) = 0;
}
}
return result;
}
}
return NULL;
}
#endif
ckyShLibrary
ckyShLibrary_open(const char *libname)
{
const struct mach_header *library;
/*char *parentPath = ckyShLibrary_getParentPath(); */
char *libPath = NULL;
int len = sizeof(SYSPATH);
#ifdef notdef
if (parentPath) {
int pLen = strlen(parentPath)+1;
if (pLen > len) {
len = pLen;
}
}
#endif
libPath = malloc(len+strlen(libname)+1);
/* if we couldn't get the space, just use the LD_LIBPATH */
if (libPath) {
#ifdef notdef
/* first try the parent DLL path if known */
if (parentPath) {
/* then try the path of the shared library */
strcpy(libPath,parentPath);
strcat(libPath,libname);
free(parentPath);
library = NSAddImage(libPath,
NSADDIMAGE_OPTION_RETURN_ON_ERROR |
NSADDIMAGE_OPTION_WITH_SEARCHING);
if (library) {
free(libPath);
return (ckyShLibrary)library;
}
}
#endif
/* the try the executable's lib path */
strcpy(libPath,SYSPATH);
strcat(libPath,libname);
library = NSAddImage(libPath,
NSADDIMAGE_OPTION_RETURN_ON_ERROR |
NSADDIMAGE_OPTION_WITH_SEARCHING);
free(libPath);
if (library) {
return (ckyShLibrary)library;
}
}
/* finally grab it from the system libpath */
library = NSAddImage(libname,
NSADDIMAGE_OPTION_RETURN_ON_ERROR |
NSADDIMAGE_OPTION_WITH_SEARCHING);
return (ckyShLibrary)library;
}
CKYStatus
ckyShLibrary_close(ckyShLibrary _lib)
{
// Can't unload an image on Mac OS X.
return CKYSUCCESS;
}
CKYStatus
ckyShLibrary_getAddress(const ckyShLibrary _lib, void ** func,
const char *funcName)
{
const struct mach_header *library = (const struct mach_header *)_lib;
NSSymbol symbol;
symbol = NSLookupSymbolInImage(library, funcName,
NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
if( symbol == NULL ) {
return CKYLIBFAIL;
}
*func = NSAddressOfSymbol(symbol);
return CKYSUCCESS;
}
--- NEW FILE dynlink_unix.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include <dlfcn.h>
#include <unistd.h>
#if !defined(MAC) && !defined(HPUX)
#include <link.h>
#endif
#include <assert.h>
#include "cky_base.h"
#include "dynlink.h"
ckyShLibrary
ckyShLibrary_open(const char *libname)
{
void *library;
library = dlopen(libname, RTLD_LAZY);
return library;
}
CKYStatus
ckyShLibrary_close(ckyShLibrary library)
{
int rv;
if (library == NULL) {
return CKYSUCCESS;
}
rv = dlclose(library);
if( rv != 0 ) {
return CKYLIBFAIL;
}
return CKYSUCCESS;
}
CKYStatus
ckyShLibrary_getAddress(const ckyShLibrary library, void **func,
const char *funcName)
{
assert(library);
void* f = dlsym(library, funcName);
if( f == NULL ) {
return CKYLIBFAIL;
}
*func = f;
return CKYSUCCESS;
}
--- NEW FILE dynlink_win.c ---
/* ***** BEGIN COPYRIGHT BLOCK *****
* Copyright (C) 2005 Red Hat, Inc.
* All rights reserved.
*
* 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 version
* 2.1 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***** END COPYRIGHT BLOCK ***** */
#include <Windows.h>
#include "cky_base.h"
#include "dynlink.h"
ckyShLibrary
ckyShLibrary_open(const char *libname)
{
HMODULE library;
library = LoadLibrary(libname);
return (ckyShLibrary) library;
}
CKYStatus
ckyShLibrary_close(ckyShLibrary _lib)
{
HMODULE library = (HMODULE) _lib;
BOOL ret;
if( library == NULL ) {
return CKYSUCCESS;
}
ret = FreeLibrary(library);
library = NULL;
if (!ret) {
return CKYLIBFAIL;
}
return CKYSUCCESS;
}
CKYStatus
ckyShLibrary_getAddress(const ckyShLibrary _lib, void **func,
const char *funcName)
{
const HMODULE library = (const HMODULE) _lib;
*func = (void *)GetProcAddress(library, funcName);
if (*func == NULL) {
return CKYLIBFAIL;
}
return CKYSUCCESS;
}
--- NEW FILE manifest.mn ---
# ***** BEGIN COPYRIGHT BLOCK *****
# Copyright (C) 2005 Red Hat, Inc.
# All rights reserved.
#
# 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 version
# 2.1 of the License.
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# ***** END COPYRIGHT BLOCK *****
CORE_DEPTH = ..
#USE_NSS=1
#USE_STATIC_RTL=1
MODULE = ckyapplet
LIBRARY_NAME = $(MODULE)
DEFINES += -DNSPR20 -D_STATIC_CPPLIB
EXPORTS = cky_base.h \
cky_card.h \
cky_factory.h \
cky_list.h \
cky_applet.h \
$(NULL)
CSRCS = \
cky_base.c \
cky_card.c \
cky_factory.c \
cky_applet.c \
dynlink.c \
$(NULL)
- Previous message (by thread): [Fedora-directory-commits] coolkey/src/libckyapplet - New directory
- Next message (by thread): [Fedora-directory-commits] coolkey Makefile.am, 1.1.1.1, 1.2 Makefile.in, 1.1.1.1, 1.2 config.status, 1.1.1.1, 1.2 configure, 1.1.1.1, 1.2 configure.in, 1.1.1.1, 1.2 coolkey.spec, 1.1.1.1, 1.2 libtool, 1.1.1.1, 1.2
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Fedora-directory-commits
mailing list