[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


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)





More information about the Fedora-directory-commits mailing list