Engine PKCS#11 initial commit
authorSajesh Kumar Saran <sajesh@ti.com>
Fri, 4 Jan 2013 23:58:36 +0000 (18:58 -0500)
committerSajesh Kumar Saran <sajesh@ti.com>
Fri, 4 Jan 2013 23:58:36 +0000 (18:58 -0500)
19 files changed:
Makefile.am [new file with mode: 0644]
NEWS [new file with mode: 0644]
README.txt [deleted file]
bootstrap [new file with mode: 0755]
configure.ac [new file with mode: 0644]
doc/Makefile.am [new file with mode: 0644]
doc/README [new file with mode: 0644]
doc/nonpersistent/Makefile.am [new file with mode: 0644]
doc/nonpersistent/export-wiki.sh [new file with mode: 0755]
doc/nonpersistent/export-wiki.xsl [new file with mode: 0644]
doc/nonpersistent/svn2cl.xsl [new file with mode: 0755]
packaged [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/Makefile.mak [new file with mode: 0644]
src/engine_pkcs11.c [new file with mode: 0644]
src/engine_pkcs11.exports [new file with mode: 0644]
src/engine_pkcs11.h [new file with mode: 0644]
src/hw_pkcs11.c [new file with mode: 0644]
src/versioninfo.rc.in [new file with mode: 0644]

diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..6c3f91c
--- /dev/null
@@ -0,0 +1,26 @@
+
+AUTOMAKE_OPTIONS = foreign 1.10
+ACLOCAL_AMFLAGS = -I m4
+
+MAINTAINERCLEANFILES = \
+       config.log config.status \
+       $(srcdir)/Makefile.in \
+       $(srcdir)/config.h.in $(srcdir)/config.h.in~ $(srcdir)/configure \
+       $(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \
+       $(srcdir)/depcomp $(srcdir)/aclocal.m4 \
+       $(srcdir)/config.guess $(srcdir)/config.sub \
+       $(srcdir)/m4/ltsugar.m4 $(srcdir)/m4/libtool.m4 \
+       $(srcdir)/m4/ltversion.m4 $(srcdir)/m4/lt~obsolete.m4 \
+       $(srcdir)/m4/ltoptions.m4 \
+       $(srcdir)/packaged
+EXTRA_DIST = svnignore
+
+SUBDIRS = src doc
+
+dist_noinst_SCRIPTS = bootstrap
+dist_doc_DATA = NEWS
+
+# Allow detection of packaged tarball
+dist-hook:
+       $(MKDIR_P) "$(distdir)/m4"
+       echo > "$(distdir)/packaged"
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..d31f6f1
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,35 @@
+NEWS for Engine PKCS#11 -- History of user visible changes
+
+New in 0.1.8; 2010-01-07; Andreas Jellinghaus
+* Fix problem causing slot_n parsing returning not certs or keys 
+  by Camille Moncelier
+* Fix missing declaration of set_init_args symbol
+  by Arfrever Frehtes Taifersar Arahesis
+
+New in 0.1.7; 2009-10-20; Andreas Jellinghaus
+* Buffer overrun fixed by David Smith
+
+New in 0.1.6; 2009-06-15; Andreas Jellinghaus
+* Fixed set_pin (strdup causes segfault in OPENSSL_CLEANSE later)
+* Require new libp11 0.2.5 with new function to get the slot id.
+* Revert changes to slot parsing code - seems partial bogus and
+  orginal author doesn't respond to questions.
+* print slot id in verbose mode (Douglas E. Engert).
+
+New in 0.1.5; 2008-07-31; Andreas Jellinghaus
+* Build system rewritten (NOTICE: configure options was modified). 
+  The build system can produce outputs for *NIX, cygwin and native
+  windows (using mingw).
+* cleanup pin code, always use MAX_PIN_LENGTH, proper cleanup.
+* new use PKCS11_CTX_init_args (David Smith)
+* fix segfault in init_args code.
+* needs new version of libp11 (0.2.4 or later).
+
+New in 0.1.4; 2007-07-11; Andreas Jellinghaus
+* update wiki export script.
+* new urls.
+* disabled some dead code.
+* new max length for pin: 32 bytes.
+* make internal variables and code static.
+* parse slot as hex too.
+* support selecting slot by label.
diff --git a/README.txt b/README.txt
deleted file mode 100644 (file)
index b35787d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Initial temporary file
diff --git a/bootstrap b/bootstrap
new file mode 100755 (executable)
index 0000000..1ed89d2
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -e
+set -x
+if test -f Makefile; then
+  make distclean
+fi
+rm -rf *~ *.cache *.m4 config.guess config.log \
+       config.status config.sub depcomp ltmain.sh
+autoreconf --verbose --install --force
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..bcdc19c
--- /dev/null
@@ -0,0 +1,340 @@
+
+AC_PREREQ(2.60)
+
+define([PACKAGE_VERSION_MAJOR], [0])
+define([PACKAGE_VERSION_MINOR], [1])
+define([PACKAGE_VERSION_FIX], [9])
+define([PACKAGE_SUFFIX], [-svn-r129])
+
+AC_INIT([engine_pkcs11],[PACKAGE_VERSION_MAJOR.PACKAGE_VERSION_MINOR.PACKAGE_VERSION_FIX[]PACKAGE_SUFFIX])
+AC_CONFIG_AUX_DIR([.])
+AM_CONFIG_HEADER([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AM_INIT_AUTOMAKE([${PACKAGE_NAME}], [${PACKAGE_VERSION}])
+
+ENGINE_PKCS11_VERSION_MAJOR="PACKAGE_VERSION_MAJOR"
+ENGINE_PKCS11_VERSION_MINOR="PACKAGE_VERSION_MINOR"
+ENGINE_PKCS11_VERSION_FIX="PACKAGE_VERSION_FIX"
+
+AC_CONFIG_SRCDIR([src/engine_pkcs11.c])
+
+AC_CANONICAL_HOST
+AC_PROG_CC
+PKG_PROG_PKG_CONFIG
+AC_C_BIGENDIAN
+
+AC_MSG_CHECKING([svn checkout])
+if test -e "${srcdir}/packaged"; then
+       svn_checkout="no"
+else
+       svn_checkout="yes"
+fi
+AC_MSG_RESULT([${svn_checkout}])
+
+AC_ARG_WITH(
+       [cygwin-native],
+       [AS_HELP_STRING([--with-cygwin-native],[compile native win32])],
+       ,
+       [with_cygwin_native="no"]
+)
+
+dnl Check for some target-specific stuff
+test -z "${WIN32}" && WIN32="no"
+test -z "${CYGWIN}" && CYGWIN="no"
+case "${host}" in
+       *-mingw*|*-winnt*)
+               WIN32="yes"
+               CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN"
+               WIN_LIBPREFIX="lib"
+       ;;
+       *-cygwin*)
+               AC_MSG_CHECKING([cygwin mode to use])
+               CYGWIN="yes"
+               if test "${with_cygwin_native}" = "yes"; then
+                       AC_MSG_RESULT([Using native win32])
+                       CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN"
+                       CFLAGS="${CFLAGS} -mno-cygwin"
+                       WIN32="yes"
+               else
+                       AC_MSG_RESULT([Using cygwin])
+                       CPPFLAGS="${CPPFLAGS} -DCRYPTOKI_FORCE_WIN32"
+                       WIN_LIBPREFIX="cyg"
+                       AC_DEFINE([USE_CYGWIN], [1], [Define if you are on Cygwin])
+               fi
+       ;;
+esac
+
+AC_ARG_ENABLE(
+       [strict],
+       [AS_HELP_STRING([--enable-strict],[enable strict compile mode @<:@disabled@:>@])],
+       ,
+       [enable_strict="no"]
+)
+
+AC_ARG_ENABLE(
+       [pedantic],
+       [AS_HELP_STRING([--enable-pedantic],[enable pedantic compile mode @<:@disabled@:>@])],
+       ,
+       [enable_pedantic="no"]
+)
+
+AC_ARG_ENABLE(
+       [doc],
+       [AS_HELP_STRING([--enable-doc],[enable installation of documents @<:@disabled@:>@])],
+       ,
+       [enable_doc="no"]
+)
+
+AC_ARG_WITH(
+       [enginesdir],
+       [AS_HELP_STRING([--with-enginesdir],[OpenSSL engines directory @<:@LIBDIR/engines@:>@])],
+       [enginesdir="${withval}"],
+       [enginesdir="\$(libdir)/engines"]
+)
+
+dnl Checks for programs.
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MKDIR_P
+AC_PROG_SED
+AC_PROG_MAKE_SET
+
+dnl Add libtool support.
+ifdef(
+       [LT_INIT],
+       [
+               LT_INIT([win32-dll])
+               LT_LANG([Windows Resource])
+       ],
+       [
+               AC_LIBTOOL_WIN32_DLL
+               AC_LIBTOOL_RC
+               AC_PROG_LIBTOOL
+       ]
+)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([ \
+       errno.h fcntl.h malloc.h stdlib.h inttypes.h \
+       string.h strings.h sys/time.h unistd.h \
+       locale.h getopt.h dlfcn.h utmp.h \
+])
+
+PKG_CHECK_MODULES([LIBP11], [libp11 >= 0.2.5],, [AC_MSG_ERROR([libp11 >= 0.2.5 is required])])
+
+dnl These required for svn checkout
+AC_ARG_VAR([XSLTPROC], [xsltproc utility])
+AC_ARG_VAR([SVN], [subversion utility])
+AC_ARG_VAR([WGET], [wget utility])
+AC_ARG_VAR([WGET_OPTS], [wget options])
+AC_ARG_VAR([TR], [tr utility])
+AC_CHECK_PROGS([XSLTPROC],[xsltproc])
+AC_CHECK_PROGS([SVN],[svn])
+AC_CHECK_PROGS([WGET],[wget])
+AC_CHECK_PROGS([TR],[tr])
+test -z "${WGET_OPTS}" && WGET_OPTS="-nv"
+
+dnl svn checkout dependencies
+if test "${svn_checkout}" = "yes"; then
+       AC_MSG_CHECKING([XSLTPROC requirement])
+       if test -n "${XSLTPROC}"; then
+               AC_MSG_RESULT([ok])
+       else
+               if test "${enable_doc}" = "yes"; then
+                       AC_MSG_ERROR([Missing XSLTPROC svn build with doc])
+               else
+                       AC_MSG_WARN(["make dist" will not work])
+               fi
+       fi
+
+       AC_MSG_CHECKING([svn doc build dependencies])
+       if test -n "${SVN}" -a -n "${TR}" -a -n "${WGET}"; then
+               AC_MSG_RESULT([ok])
+       else
+               if test "${enable_doc}" = "yes"; then
+                       AC_MSG_ERROR([Missing SVN, TR or WGET for svn doc build])
+               else
+                       AC_MSG_WARN(["make dist" will not work])
+               fi
+       fi
+fi
+
+PKG_CHECK_MODULES(
+       [OPENSSL],
+       [libcrypto >= 0.9.7],
+       ,
+       [PKG_CHECK_MODULES(
+               [OPENSSL],
+               [openssl >= 0.9.7],
+               ,
+               [AC_CHECK_LIB(
+                       [crypto],
+                       [RSA_version],
+                       [OPENSSL_LIBS="-lcrypto"],
+                       [AC_MSG_ERROR([Cannot find OpenSSL])]
+               )]
+       )]
+)
+
+# ok, now we might (or not) have ssl and an engine.
+# still room for "improvements", i.e. hacks to work
+# with old engines.
+
+AC_MSG_CHECKING([for openssl version])
+saved_CPPFLAGS="${CPPFLAGS}"
+CPPFLAGS="${CPPFLAGS} ${OPENSSL_CFLAGS}"
+AC_EGREP_CPP(
+       [new],
+       [
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER >= 0x0090704fL
+new
+#else
+old
+#endif
+       ],
+       [
+               AC_MSG_RESULT([good, 0.9.7d or later])
+               old_openssl="no"
+       ],
+       [
+               AC_MSG_RESULT([not so good, 0.9.7d or later would be better])
+               old_openssl="yes"
+       ]
+)
+CPPFLAGS="${saved_CPPFLAGS}"
+
+if test "x$old_openssl" = "xyes"; then
+       # openssl found, but version less than 0.9.7d
+       # linking libcrypto.a statically possible?
+
+       saved_CFLAGS="${CFLAGS}"
+       saved_LIBS="${LIBS}"
+       CFLAGS="${CFLAGS} ${OPENSSL_CFLAGS}"
+       if echo "${OPENSSL_LIBS}" | grep -- "-L" > /dev/null; then
+               OPENSSL_DIR="$(echo "${OPENSSL_LIBS}" | ${SED} 's/.*-L\([^ ]*\).*/\1/')"
+       else
+               OPENSSL_DIR="${usrlibdir}"
+       fi
+       LIBS="${LIBS} ${OPENSSL_DIR}/libcrypto.a"
+       AC_CHECK_LIB(
+               [dl],
+               [dlopen]
+       )
+       AC_MSG_CHECKING([should link static openssl])
+       AC_LINK_IFELSE(
+               [AC_LANG_PROGRAM([[
+#include <string.h>
+#include <openssl/opensslv.h>
+#include <openssl/engine.h>
+#include <openssl/rand.h>
+int test(void)
+{
+       char a[2048];
+       ENGINE *e;
+
+       e = ENGINE_new();
+       ENGINE_load_dynamic();
+       if (!e) return 1;
+       memset(a, 0, sizeof(a));
+       RAND_add(a, sizeof(a), sizeof(a));
+       return(RAND_status() <= 0);
+}
+               ]])],
+               [
+                       AC_MSG_RESULT([yes])
+                       ENGINE_LINK="${OPENSSL_DIR}/libcrypto.a"
+               ],
+               [AC_MSG_ERROR([OpenSSL is old and cannot link with its static library])]
+       )
+       CFLAGS="${saved_CFLAGS}"
+       LIBS="${saved_LIBS}"
+fi
+
+#@alonbl: This was never actually used.
+#
+# now - last part to do: check if we gain anything from
+# funny parameters to link openssl with.
+#saved_LDFLAGS="${LDFLAGS}"
+#for test_flags in "-Wl,-Bsymbolic" "-G -Wl,-Bsymbolic" "-Wl,-all_load"; do
+#      AC_MSG_CHECKING([whether we can use ${test_flags}])
+#      LDFLAGS="${saved_LDFLAGS} ${test_flags}"
+#      AC_LINK_IFELSE(
+#              [AC_LANG_PROGRAM([[
+#int test()
+#{
+#      return 1;
+#}
+#              ]])],
+#              [result="yes"],
+#              [result="no"]
+#      )
+#      AC_MSG_RESULT([${result}])
+#      if test "${result}" = "yes"; then
+#              OPENSSL_EXTRA_LDFLAGS="${test_flags}"
+#              break;
+#      fi
+#done
+#LDFLAGS="${saved_LDFLAGS}"
+
+
+AC_SUBST([enginesdir])
+AC_SUBST([ENGINE_LINK])
+AC_SUBST([ENGINE_PKCS11_VERSION_MAJOR])
+AC_SUBST([ENGINE_PKCS11_VERSION_MINOR])
+AC_SUBST([ENGINE_PKCS11_VERSION_FIX])
+AC_SUBST([WIN_LIBPREFIX])
+AC_SUBST([OPENSSL_EXTRA_LDFLAGS])
+
+AM_CONDITIONAL([SVN_CHECKOUT], [test "${svn_checkout}" = "yes"])
+AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"])
+AM_CONDITIONAL([CYGWIN], [test "${CYGWIN}" = "yes"])
+AM_CONDITIONAL([ENABLE_DOC], [test "${enable_doc}" = "yes"])
+
+if test "${enable_pedantic}" = "yes"; then
+       enable_strict="yes";
+       CFLAGS="${CFLAGS} -pedantic"
+fi
+if test "${enable_strict}" = "yes"; then
+       CFLAGS="${CFLAGS} -Wall -Wextra"
+fi
+
+AC_CONFIG_FILES([
+       Makefile
+       doc/Makefile
+       doc/nonpersistent/Makefile
+       src/Makefile
+       src/versioninfo.rc
+])
+AC_OUTPUT
+
+cat <<EOF
+
+engine_pkcs11 has been configured with the following options:
+
+
+Version:                 ${PACKAGE_VERSION}
+Libraries:               $(eval eval eval echo "${libdir}")
+
+doc support:             ${enable_doc}
+
+Host:                    ${host}
+Compiler:                ${CC}
+Preprocessor flags:      ${CPPFLAGS}
+Compiler flags:          ${CFLAGS}
+Linker flags:            ${LDFLAGS}
+Libraries:               ${LIBS}
+
+enginesdir               ${enginesdir}
+
+LIBP11_CFLAGS:           ${LIBP11_CFLAGS}
+LIBP11_LIBS:             ${LIBP11_LIBS}
+OPENSSL_CFLAGS:          ${OPENSSL_CFLAGS}
+OPENSSL_LIBS:            ${OPENSSL_LIBS}
+OPENSSL_EXTRA_LDFLAGS:   ${OPENSSL_EXTRA_LDFLAGS}
+ENGINE_LINK:             ${ENGINE_LINK}
+
+EOF
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644 (file)
index 0000000..a97911d
--- /dev/null
@@ -0,0 +1,8 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+if ENABLE_DOC
+SUBDIRS = nonpersistent
+endif
+DIST_SUBDIRS = nonpersistent
+
+dist_doc_DATA = README
diff --git a/doc/README b/doc/README
new file mode 100644 (file)
index 0000000..dbb39ad
--- /dev/null
@@ -0,0 +1,10 @@
+This directory contains a snapshot of the engine_pkcs11 Wiki
+============================================================
+
+The original wiki page is at http://www.opensc-project.org/engine_pkcs11/
+and includes a bug tracker and source browser.
+
+The wiki was transformed to html using the export-wiki shell
+script and xsl style sheet. The original version is at 
+       http://www.twdata.org/trac-howto/
+
diff --git a/doc/nonpersistent/Makefile.am b/doc/nonpersistent/Makefile.am
new file mode 100644 (file)
index 0000000..e67c6af
--- /dev/null
@@ -0,0 +1,59 @@
+MAINTAINERCLEANFILES = \
+       $(srcdir)/Makefile.in
+
+wikidir=$(htmldir)/wiki
+
+dist_noinst_SCRIPTS = export-wiki.sh export-wiki.xsl \
+       svn2cl.xsl 
+dist_wiki_DATA = wiki.out/*
+dist_noinst_DATA = ChangeLog
+
+if SVN_CHECKOUT
+
+wiki.out/*:    wiki.out
+wiki.out:
+       -rm -fr wiki.out
+       test -n "$(WGET)" -a -n "$(SED)" -a -n "$(TR)" -a -n "$(XSLTPROC)"
+       WGET="$(WGET)" WGET_OPTS="$(WGET_OPTS)" SED="$(SED)" TR="$(TR)" XSLTPROC="$(XSLTPROC)" \
+               PROJECT="@PACKAGE_NAME@" \
+               $(SHELL) "$(srcdir)/export-wiki.sh" "$(srcdir)" "wiki.tmp"
+       mv wiki.tmp wiki.out
+
+ChangeLog:
+       test -n "$(SVN)" -a -n "$(XSLTPROC)"
+       if test -d "$(top_srcdir)/.svn"; then \
+               $(SVN) --verbose --xml log "$(top_srcdir)" | \
+                       $(XSLTPROC) --nonet --stringparam linelen 75 \
+                       --stringparam groupbyday no \
+                       --stringparam include-rev no \
+                       "$(srcdir)/svn2cl.xsl" - > ChangeLog.tmp; \
+       else \
+               echo "Warning: Unable to generate ChangeLog from none svn checkout" >&2; \
+               echo > ChangeLog.tmp; \
+       fi
+       mv ChangeLog.tmp ChangeLog
+
+else
+
+wiki.out/*:    $(abs_builddir)/wiki.out
+$(abs_builddir)/wiki.out:
+       $(LN_S) "$(srcdir)/wiki.out" wiki.out
+
+ChangeLog:
+       $(LN_S) "$(srcdir)/ChangeLog" ChangeLog
+
+endif
+
+distclean-local:
+       -rm -rf wiki.tmp
+       if test -L wiki.out; then \
+               rm -fr wiki.out; \
+       fi
+       -rm -fr ChangeLog.tmp
+       if test -L ChangeLog; then \
+               rm -fr ChangeLog; \
+       fi
+
+maintainer-clean-local:
+       -rm -rf "$(srcdir)/wiki.out"
+       -rm -rf "$(srcdir)/ChangeLog"
diff --git a/doc/nonpersistent/export-wiki.sh b/doc/nonpersistent/export-wiki.sh
new file mode 100755 (executable)
index 0000000..956fb21
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+set -e
+
+test -z "$XSLTPROC" && XSLTPROC="xsltproc"
+test -z "$WGET" && WGET="wget"
+test -z "$WGET_OPTS" && WGET_OPTS="$WGET_OPTS"
+test -z "$SED" && SED="sed"
+test -z "$TR" && TR="tr"
+
+test -z "$SERVER" && SERVER="http://www.opensc-project.org"
+test -z "$PROJECT" && PROJECT="opensc"
+
+SRCDIR=.
+OUTDIR=.
+test -n "$1" && SRCDIR="$1"
+test -n "$2" &&        OUTDIR="$2"
+
+WIKI="$PROJECT/wiki"
+XSL="$SRCDIR/export-wiki.xsl"
+
+test -f "$SRCDIR"/`basename $0`
+
+test -e "$OUTDIR" && rm -fr "$OUTDIR"
+
+mkdir "$OUTDIR" || exit 1
+
+$WGET $WGET_OPTS $SERVER/$WIKI/TitleIndex -O "$OUTDIR"/TitleIndex.tmp
+
+$SED -e "s#</li>#</li>\n#g" < "$OUTDIR"/TitleIndex.tmp \
+       | grep "\"/$WIKI/[^\"]*\"" \
+        |$SED -e "s#.*\"/$WIKI/\([^\"]*\)\".*#\1#g" \
+       > "$OUTDIR"/WikiWords.tmp
+$SED -e /^Trac/d -e /^Wiki/d -e /^TitleIndex/d -e /^RecentChanges/d \
+        -e /^CamelCase/d -e /^SandBox/d -e /^InterMapTxt/d -e /^InterWiki/d \
+        -e /^InterTrac/d -i "$OUTDIR"/WikiWords.tmp
+
+for A in WikiStart `cat "$OUTDIR"/WikiWords.tmp`
+do
+       F=`echo $A|$SED -e 's/\//_/g'`
+       $WGET $WGET_OPTS $SERVER/$WIKI/$A  -O "$OUTDIR"/$F.tmp
+       $XSLTPROC --nonet --output "$OUTDIR"/$F.html "$XSL" "$OUTDIR"/$F.tmp
+       $SED -e "s#<a href=\"/$WIKI/\([^\"]*\)\"#<a href=\"\1.html\"#g" \
+               -i "$OUTDIR"/$F.html
+done
+
+mv "$OUTDIR"/WikiStart.html "$OUTDIR"/index.html
+
+$WGET $WGET_OPTS http://www.opensc-project.org/trac/css/trac.css \
+       -O "$OUTDIR"/trac.css
+
+cat "$OUTDIR"/*.html |grep "<img src=\"/$PROJECT/attachment/wiki" \
+       |$SED -e 's/.*<img src="\/'$PROJECT'\/attachment\/wiki\/\([^"]*\)?format=raw".*/\1/g' \
+       |sort -u |while read A
+do
+       B="`echo $A |$TR / _`"
+       $WGET $WGET_OPTS "$SERVER/$PROJECT/attachment/wiki/$A?format=raw" -O "$OUTDIR"/$B
+       for C in "${OUTDIR}"/*.html
+       do
+               $SED -e 's#\/'$PROJECT'\/attachment\/wiki\/'$A'?format=raw#'$B'#g' -i "$C"
+       done
+done
+
+for A in "${OUTDIR}"/*.html
+do
+       $SED -e 's#href="/'$PROJECT'/wiki/\([^"]*\)"#href="\1.html"#g' \
+               -i $A
+done
+
+rm "$OUTDIR"/*.tmp
+exit 0
diff --git a/doc/nonpersistent/export-wiki.xsl b/doc/nonpersistent/export-wiki.xsl
new file mode 100644 (file)
index 0000000..30a600e
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+xmlns="http://www.w3.org/1999/xhtml"
+xmlns:html="http://www.w3.org/1999/xhtml">
+       <xsl:output method="html" indent="yes"/>
+  
+  <xsl:template match="/">
+    <xsl:apply-templates />
+  </xsl:template>
+  
+  <xsl:template match="/html:html">
+      <html>
+        <head>
+          <title><xsl:value-of select="/html:html/html:head/html:title" /></title>
+          <style type="text/css">
+           @import url(trac.css);
+          </style>
+        </head>
+        <body>
+          <xsl:apply-templates select="//html:div[@class='wiki']" />
+          <div class="footer">
+            <hr />
+            <p><a href="index.html">Back to Index</a></p>
+          </div>
+        </body>
+      </html>
+  </xsl:template>
+  
+  <xsl:template match="/pages">
+      <html>
+        <head>
+          <title>Wiki Index</title>
+          <style type="text/css">
+           @import url(trac.css);
+          </style>
+        </head>
+        <body>
+          <h1>Index of Wiki Pages</h1>
+          <ul>
+          <xsl:apply-templates select="page" />
+          </ul>
+        </body>
+      </html>
+  </xsl:template>
+  
+  <xsl:template match="page">
+    <li><a href="{.}.html"><xsl:value-of select="." /></a></li>
+  </xsl:template>
+  
+  <xsl:template match="node()|@*" priority="-1">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+</xsl:stylesheet>
+
diff --git a/doc/nonpersistent/svn2cl.xsl b/doc/nonpersistent/svn2cl.xsl
new file mode 100755 (executable)
index 0000000..3672035
--- /dev/null
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+
+   svn2cl.xsl - xslt stylesheet for converting svn log to a normal
+                changelog
+
+   Usage (replace ++ with two minus signs):
+     svn ++verbose ++xml log | \
+       xsltproc ++stringparam strip-prefix `basename $(pwd)` \
+                ++stringparam linelen 75 \
+                ++stringparam groupbyday yes \
+                ++stringparam include-rev yes \
+                svn2cl.xsl - > ChangeLog
+
+   This file is based on several implementations of this conversion
+   that I was not completely happy with and some other common
+   xslt constructs found on the web.
+
+   Copyright (C) 2004, 2005 Arthur de Jong.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+   3. The name of the author may not be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!DOCTYPE page [
+ <!ENTITY tab "&#9;">
+ <!ENTITY newl "&#13;">
+ <!ENTITY space "&#32;">
+]>
+
+<!--
+   TODO
+   - make external lookups of author names possible
+   - find a place for revision numbers
+   - mark deleted files as such
+   - combine paths
+   - make path formatting nicer
+-->
+
+<xsl:stylesheet
+  version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns="http://www.w3.org/1999/xhtml">
+
+ <xsl:output
+   method="text"
+   encoding="iso-8859-15"
+   media-type="text/plain"
+   omit-xml-declaration="yes"
+   standalone="yes"
+   indent="no" />
+
+ <xsl:strip-space elements="*" />
+
+ <!-- the prefix of pathnames to strip -->
+ <xsl:param name="strip-prefix" select="'/'" />
+
+ <!-- the length of a line to wrap messages at -->
+ <xsl:param name="linelen" select="75" />
+ <!-- whether entries should be grouped by day -->
+ <xsl:param name="groupbyday" select="'no'" />
+
+ <!-- whether entries should be grouped by day -->
+ <xsl:param name="include-rev" select="'no'" />
+
+ <!-- add newlines at the end of the changelog -->
+ <xsl:template match="log">
+  <xsl:apply-templates/>
+  <xsl:text>&newl;</xsl:text>
+ </xsl:template>
+
+ <!-- format one entry from the log -->
+ <xsl:template match="logentry">
+  <!-- save log entry number -->
+  <xsl:variable name="pos" select="position()"/>
+  <!-- fetch previous entry's date -->
+  <xsl:variable name="prevdate">
+   <xsl:apply-templates select="../logentry[position()=(($pos)-1)]/date"/>
+  </xsl:variable>
+  <!-- fetch previous entry's author -->
+  <xsl:variable name="prevauthor">
+   <xsl:apply-templates select="../logentry[position()=(($pos)-1)]/author"/>
+  </xsl:variable>
+  <!-- fetch this entry's date -->
+  <xsl:variable name="date">
+   <xsl:apply-templates select="date" />
+  </xsl:variable>
+  <!-- fetch this entry's author -->
+  <xsl:variable name="author">
+   <xsl:apply-templates select="author" />
+  </xsl:variable>
+  <!-- check if header is changed -->
+  <xsl:if test="($prevdate!=$date) or ($prevauthor!=$author)">
+   <!-- add newline -->
+   <xsl:if test="not(position()=1)">
+     <xsl:text>&newl;</xsl:text>
+   </xsl:if>
+   <!-- date -->
+   <xsl:apply-templates select="date" />
+   <!-- two spaces -->
+   <xsl:text>&space;&space;</xsl:text>
+   <!-- author's name -->
+   <xsl:apply-templates select="author" />
+   <!-- two newlines -->
+   <xsl:text>&newl;&newl;</xsl:text>
+  </xsl:if>
+  <!-- get paths string -->
+  <xsl:variable name="paths">
+   <xsl:apply-templates select="paths" />
+  </xsl:variable>
+  <!-- get revision number -->
+  <xsl:variable name="rev">
+   <xsl:if test="$include-rev='yes'">
+    <xsl:text>[r</xsl:text>
+    <xsl:value-of select="@revision"/>
+    <xsl:text>]&space;</xsl:text>
+   </xsl:if>
+  </xsl:variable>
+  <!-- first line is indented (other indents are done in wrap template) -->
+  <xsl:text>&tab;*&space;</xsl:text>
+  <!-- print the paths and message nicely wrapped -->
+  <xsl:call-template name="wrap">
+   <xsl:with-param name="txt" select="concat($rev,$paths,normalize-space(msg))" />
+  </xsl:call-template>
+ </xsl:template>
+
+ <!-- format date -->
+ <xsl:template match="date">
+  <xsl:variable name="date" select="normalize-space(.)" />
+  <!-- output date part -->
+  <xsl:value-of select="substring($date,1,10)" />
+  <!-- output time part -->
+  <xsl:if test="$groupbyday!='yes'">
+   <xsl:text>&space;</xsl:text>
+   <xsl:value-of select="substring($date,12,5)" />
+  </xsl:if>
+ </xsl:template>
+
+ <!-- format author -->
+ <xsl:template match="author">
+  <xsl:value-of select="normalize-space(.)" />
+ </xsl:template>
+
+ <!-- present a list of paths names -->
+ <xsl:template match="paths">
+  <xsl:for-each select="path">
+   <xsl:sort select="normalize-space(.)" data-type="text" />
+   <!-- unless we are the first entry, add a comma -->
+   <xsl:if test="not(position()=1)">
+    <xsl:text>,&space;</xsl:text>
+   </xsl:if>
+   <!-- print the path name -->
+   <xsl:apply-templates select="."/>
+  </xsl:for-each>
+  <!-- end the list with a colon -->
+  <xsl:text>:&space;</xsl:text>
+ </xsl:template>
+
+ <!-- transform path to something printable -->
+ <xsl:template match="path">
+  <!-- fetch the pathname -->
+  <xsl:variable name="p1" select="normalize-space(.)" />
+  <!-- strip leading slash -->
+  <xsl:variable name="p2">
+   <xsl:choose>
+    <xsl:when test="starts-with($p1,'/')">
+     <xsl:value-of select="substring($p1,2)" />
+    </xsl:when>
+    <xsl:otherwise>
+     <xsl:value-of select="$p1" />
+    </xsl:otherwise>
+   </xsl:choose>
+  </xsl:variable>
+  <!-- strip trailing slash from strip-prefix -->
+  <xsl:variable name="sp">
+   <xsl:choose>
+    <xsl:when test="substring($strip-prefix,string-length($strip-prefix),1)='/'">
+     <xsl:value-of select="substring($strip-prefix,1,string-length($strip-prefix)-1)" />
+    </xsl:when>
+    <xsl:otherwise>
+     <xsl:value-of select="$strip-prefix" />
+    </xsl:otherwise>
+   </xsl:choose>
+  </xsl:variable>
+  <!-- strip strip-prefix -->
+  <xsl:variable name="p3">
+   <xsl:choose>
+    <xsl:when test="starts-with($p2,$sp)">
+     <xsl:value-of select="substring($p2,1+string-length($sp))" />
+    </xsl:when>
+    <xsl:otherwise>
+     <!-- TODO: do not print strings that do not begin with strip-prefix -->
+     <xsl:value-of select="$p2" />
+    </xsl:otherwise>
+   </xsl:choose>
+  </xsl:variable>
+  <!-- strip another slash -->
+  <xsl:variable name="p4">
+   <xsl:choose>
+    <xsl:when test="starts-with($p3,'/')">
+     <xsl:value-of select="substring($p3,2)" />
+    </xsl:when>
+    <xsl:otherwise>
+     <xsl:value-of select="$p3" />
+    </xsl:otherwise>
+   </xsl:choose>
+  </xsl:variable>
+  <!-- translate empty string to dot -->
+  <xsl:choose>
+   <xsl:when test="$p4 = ''">
+    <xsl:text>.</xsl:text>
+   </xsl:when>
+   <xsl:otherwise>
+    <xsl:value-of select="$p4" />
+   </xsl:otherwise>
+  </xsl:choose>
+ </xsl:template>
+
+ <!-- string-wrapping template -->
+ <xsl:template name="wrap">
+  <xsl:param name="txt" />
+  <xsl:choose>
+   <xsl:when test="(string-length($txt) &lt; (($linelen)-9)) or not(contains($txt,' '))">
+    <!-- this is easy, nothing to do -->
+    <xsl:value-of select="$txt" />
+    <!-- add newline -->
+    <xsl:text>&newl;</xsl:text>
+   </xsl:when>
+   <xsl:otherwise>
+    <!-- find the first line -->
+    <xsl:variable name="tmp" select="substring($txt,1,(($linelen)-10))" />
+    <xsl:variable name="line">
+     <xsl:choose>
+      <xsl:when test="contains($tmp,' ')">
+       <xsl:call-template name="find-line">
+        <xsl:with-param name="txt" select="$tmp" />
+       </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+       <xsl:value-of select="substring-before($txt,' ')" />
+      </xsl:otherwise>
+     </xsl:choose>
+    </xsl:variable>
+    <!-- print newline and tab -->
+    <xsl:value-of select="$line" />
+    <xsl:text>&newl;&tab;&space;&space;</xsl:text>
+    <!-- wrap the rest of the text -->
+    <xsl:call-template name="wrap">
+     <xsl:with-param name="txt" select="normalize-space(substring($txt,string-length($line)+1))" />
+    </xsl:call-template>
+   </xsl:otherwise>
+  </xsl:choose>
+ </xsl:template>
+
+ <!-- template to trim line to contain space as last char -->
+ <xsl:template name="find-line">
+  <xsl:param name="txt" />
+  <xsl:choose>
+   <xsl:when test="substring($txt,string-length($txt),1) = ' '">
+    <xsl:value-of select="normalize-space($txt)" />
+   </xsl:when>
+   <xsl:otherwise>
+    <xsl:call-template name="find-line">
+     <xsl:with-param name="txt" select="substring($txt,1,string-length($txt)-1)" />
+    </xsl:call-template>
+   </xsl:otherwise>
+  </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/packaged b/packaged
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
+++ b/packaged
@@ -0,0 +1 @@
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..3febe07
--- /dev/null
@@ -0,0 +1,42 @@
+MAINTAINERCLEANFILES = \
+       $(srcdir)/Makefile.in $(srcdir)/versioninfo.rc
+EXTRA_DIST = Makefile.mak
+
+engines_LTLIBRARIES = engine_pkcs11.la
+
+OPENSSL_EXTRA_CFLAGS = \
+       -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H \
+       -DOPENSSL_NO_KRB5 -DL_ENDIAN -DTERMIO -DENGINE_DYNAMIC_SUPPORT \
+       -DSHA1_ASM -DMD5_ASM -DRMD160_ASM
+
+engine_pkcs11_la_SOURCES = \
+       hw_pkcs11.c engine_pkcs11.c engine_pkcs11.h  \
+       engine_pkcs11.exports
+if WIN32
+engine_pkcs11_la_SOURCES += versioninfo.rc
+else
+dist_noinst_DATA = versioninfo.rc
+endif
+engine_pkcs11_la_CFLAGS = $(AM_CFLAGS) $(OPENSSL_EXTRA_CFLAGS) $(OPENSSL_CFLAGS) \
+       $(LIBP11_CFLAGS)
+engine_pkcs11_la_LIBADD = $(ENGINE_LINK) $(OPENSSL_LIBS) $(LIBP11_LIBS)
+engine_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) $(OPENSSL_EXTRA_LDFLAGS) \
+       -module -avoid-version \
+       -export-symbols "$(srcdir)/engine_pkcs11.exports" \
+       -no-undefined
+
+install-data-hook:
+       rm -f "$(DESTDIR)$(enginesdir)/engine_pkcs11.la"
+       rm -f "$(DESTDIR)$(enginesdir)/engine_pkcs11.a"
+       rm -f "$(DESTDIR)$(enginesdir)/engine_pkcs11.dll.a"
+
+RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS)
+LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
+
+.rc.lo:
+       $(LTRCCOMPILE) -i "$<" -o "$@"
+
+.rc.o:
+       $(RCCOMPILE) -i "$<" -o "$@"
+
diff --git a/src/Makefile.mak b/src/Makefile.mak
new file mode 100644 (file)
index 0000000..cb9151e
--- /dev/null
@@ -0,0 +1,28 @@
+# - set the OPENSSL_INCL_DIR below to your openssl include directory, preceded by "/I"
+# - set the OPENSSL_LIB below to your openssl lib file
+# Note: these instructions obsolete the instructions in opensc.html
+
+OPENSSL_INC = /IC:\openssl\include
+OPENSSL_LIB = C:\openssl\lib\libeay32.lib
+LIBP11_INC = /IC:\libp11\include
+LIBP11_LIB = C:\libp11\lib\libp11.lib
+
+COPTS = /Zi /MD /nologo /I..\ /DHAVE_CONFIG_H $(OPENSSL_INC) $(LIBP11_INC) /D_WIN32_WINNT=0x0400 /DWIN32_LEAN_AND_MEAN /DHAVE_OPENSSL
+LINKFLAGS = /DEBUG /NOLOGO /INCREMENTAL:NO /MACHINE:IX86
+
+
+TARGET                  = engine_pkcs11.dll
+
+OBJECTS                        = engine_pkcs11.obj hw_pkcs11.obj
+
+all: $(TARGET)
+
+.c.obj::
+       cl $(COPTS) /c $<
+
+$(TARGET): $(OBJECTS) .
+       echo LIBRARY $* > $*.def
+       echo EXPORTS >> $*.def
+       type $*.exports >> $*.def
+       link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET) $(OBJECTS) $(OPENSSL_LIB) $(LIBP11_LIB) gdi32.lib
+       if EXIST $*.dll.manifest mt -manifest $*.dll.manifest -outputresource:$*.dll;2
diff --git a/src/engine_pkcs11.c b/src/engine_pkcs11.c
new file mode 100644 (file)
index 0000000..c1b8fbb
--- /dev/null
@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 2002 Juha Yrjölä.  All rights reserved.
+ * Copyright (c) 2001 Markus Friedl.
+ * Copyright (c) 2002 Olaf Kirch
+ * Copyright (c) 2003 Kevin Stefanik
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/objects.h>
+#include <openssl/engine.h>
+#include <libp11.h>
+#include "engine_pkcs11.h"
+
+#ifdef _WIN32
+#define strncasecmp strnicmp
+#endif
+
+#define fail(msg) { fprintf(stderr,msg); return NULL;}
+
+/** The maximum length of an internally-allocated PIN */
+#define MAX_PIN_LENGTH   32
+
+static PKCS11_CTX *ctx;
+
+/** 
+ * The PIN used for login. Cache for the get_pin function.
+ * The memory for this PIN is always owned internally,
+ * and may be freed as necessary. Before freeing, the PIN 
+ * must be whitened, to prevent security holes.
+ */
+static char *pin = NULL;
+static int pin_length = 0;
+
+static int verbose = 0;
+
+static char *module = NULL;
+
+static char *init_args = NULL;
+
+int set_module(const char *modulename)
+{
+       module = modulename ? strdup(modulename) : NULL;
+       return 1;
+}
+
+/**
+ * Set the PIN used for login. A copy of the PIN shall be made.
+ *
+ * If the PIN cannot be assigned, the value 0 shall be returned
+ * and errno shall be set as follows:
+ *
+ *   EINVAL - a NULL PIN was supplied
+ *   ENOMEM - insufficient memory to copy the PIN
+ *
+ * @param _pin the pin to use for login. Must not be NULL.
+ *
+ * @return 1 on success, 0 on failure.
+ */
+int set_pin(const char *_pin)
+{
+       /* Pre-condition check */
+       if (_pin == NULL) {
+               errno = EINVAL;
+               return 0;
+       }
+
+       /* Copy the PIN. If the string cannot be copied, NULL
+          shall be returned and errno shall be set. */
+       pin = strdup(_pin);
+       if (pin != NULL)
+               pin_length = strlen(pin);
+
+       return (pin != NULL);
+}
+
+int inc_verbose(void)
+{
+       verbose++;
+       return 1;
+}
+
+/* either get the pin code from the supplied callback data, or get the pin
+ * via asking our self. In both cases keep a copy of the pin code in the
+ * pin variable (strdup'ed copy). */
+static int get_pin(UI_METHOD * ui_method, void *callback_data)
+{
+       UI *ui;
+       struct {
+               const void *password;
+               const char *prompt_info;
+       } *mycb = callback_data;
+
+       /* pin in the call back data, copy and use */
+       if (mycb != NULL && mycb->password) {
+               pin = (char *)calloc(MAX_PIN_LENGTH, sizeof(char));
+               if (!pin)
+                       return 0;
+               strncpy(pin,mycb->password,MAX_PIN_LENGTH);
+               pin_length = MAX_PIN_LENGTH;
+               return 1;
+       }
+
+       /* call ui to ask for a pin */
+       ui = UI_new();
+       if (ui_method != NULL)
+               UI_set_method(ui, ui_method);
+       if (callback_data != NULL)
+               UI_set_app_data(ui, callback_data);
+
+       if (!UI_add_input_string
+           (ui, "PKCS#11 token PIN: ", 0, pin, 1, MAX_PIN_LENGTH)) {
+               fprintf(stderr, "UI_add_input_string failed\n");
+               UI_free(ui);
+               return 0;
+       }
+       if (UI_process(ui)) {
+               fprintf(stderr, "UI_process failed\n");
+               UI_free(ui);
+               return 0;
+       }
+       UI_free(ui);
+       return 1;
+}
+
+int set_init_args(const char *init_args_orig)
+{
+       init_args = init_args_orig ? strdup(init_args_orig) : NULL;
+       return 1;
+}
+
+int pkcs11_finish(ENGINE * engine)
+{
+       if (ctx) {
+               PKCS11_CTX_unload(ctx);
+               PKCS11_CTX_free(ctx);
+               ctx = NULL;
+       }
+       if (pin != NULL) {
+               OPENSSL_cleanse(pin, pin_length);
+               free(pin);
+               pin = NULL;
+               pin_length = 0;
+       }
+       return 1;
+}
+
+int pkcs11_init(ENGINE * engine)
+{
+       if (verbose) {
+               fprintf(stderr, "initializing engine\n");
+       }
+       ctx = PKCS11_CTX_new();
+        PKCS11_CTX_init_args(ctx, init_args);
+       if (PKCS11_CTX_load(ctx, module) < 0) {
+               fprintf(stderr, "unable to load module %s\n", module);
+               return 0;
+       }
+       return 1;
+}
+
+int pkcs11_rsa_finish(RSA * rsa)
+{
+       if (pin) {
+               OPENSSL_cleanse(pin, pin_length);
+               free(pin);
+               pin = NULL;
+               pin_length = 0;
+       }
+       if (module) {
+               free(module);
+               module = NULL;
+       }
+       /* need to free RSA_ex_data? */
+       return 1;
+}
+
+static int hex_to_bin(const char *in, unsigned char *out, size_t * outlen)
+{
+       size_t left, count = 0;
+
+       if (in == NULL || *in == '\0') {
+               *outlen = 0;
+               return 1;
+       }
+
+       left = *outlen;
+
+       while (*in != '\0') {
+               int byte = 0, nybbles = 2;
+
+               while (nybbles-- && *in && *in != ':') {
+                       char c;
+                       byte <<= 4;
+                       c = *in++;
+                       if ('0' <= c && c <= '9')
+                               c -= '0';
+                       else if ('a' <= c && c <= 'f')
+                               c = c - 'a' + 10;
+                       else if ('A' <= c && c <= 'F')
+                               c = c - 'A' + 10;
+                       else {
+                               fprintf(stderr,
+                                       "hex_to_bin(): invalid char '%c' in hex string\n",
+                                       c);
+                               *outlen = 0;
+                               return 0;
+                       }
+                       byte |= c;
+               }
+               if (*in == ':')
+                       in++;
+               if (left <= 0) {
+                       fprintf(stderr, "hex_to_bin(): hex string too long\n");
+                       *outlen = 0;
+                       return 0;
+               }
+               out[count++] = (unsigned char)byte;
+               left--;
+       }
+
+       *outlen = count;
+       return 1;
+}
+
+/* parse string containing slot and id information */
+
+static int parse_slot_id_string(const char *slot_id, int *slot,
+                               unsigned char *id, size_t * id_len,
+                               char **label)
+{
+       int n, i;
+
+       if (!slot_id)
+               return 0;
+
+       /* support for several formats */
+#define HEXDIGITS "01234567890ABCDEFabcdef"
+#define DIGITS "0123456789"
+
+       /* first: pure hex number (id, slot is 0) */
+       if (strspn(slot_id, HEXDIGITS) == strlen(slot_id)) {
+               /* ah, easiest case: only hex. */
+               if ((strlen(slot_id) + 1) / 2 > *id_len) {
+                       fprintf(stderr, "id string too long!\n");
+                       return 0;
+               }
+               *slot = 0;
+               return hex_to_bin(slot_id, id, id_len);
+       }
+
+       /* second: slot:id. slot is an digital int. */
+       if (sscanf(slot_id, "%d", &n) == 1) {
+               i = strspn(slot_id, DIGITS);
+
+               if (slot_id[i] != ':') {
+                       fprintf(stderr, "could not parse string!\n");
+                       return 0;
+               }
+               i++;
+               if (slot_id[i] == 0) {
+                       *slot = n;
+                       *id_len = 0;
+                       return 1;
+               }
+               if (strspn(slot_id + i, HEXDIGITS) + i != strlen(slot_id)) {
+                       fprintf(stderr, "could not parse string!\n");
+                       return 0;
+               }
+               /* ah, rest is hex */
+               if ((strlen(slot_id) - i + 1) / 2 > *id_len) {
+                       fprintf(stderr, "id string too long!\n");
+                       return 0;
+               }
+               *slot = n;
+               return hex_to_bin(slot_id + i, id, id_len);
+       }
+
+       /* third: id_<id>  */
+       if (strncmp(slot_id, "id_", 3) == 0) {
+               if (strspn(slot_id + 3, HEXDIGITS) + 3 != strlen(slot_id)) {
+                       fprintf(stderr, "could not parse string!\n");
+                       return 0;
+               }
+               /* ah, rest is hex */
+               if ((strlen(slot_id) - 3 + 1) / 2 > *id_len) {
+                       fprintf(stderr, "id string too long!\n");
+                       return 0;
+               }
+               *slot = 0;
+               return hex_to_bin(slot_id + 3, id, id_len);
+       }
+
+       /* label_<label>  */
+       if (strncmp(slot_id, "label_", 6) == 0) {
+               *label = strdup(slot_id + 6);
+               return *label != NULL;
+       }
+
+       /* last try: it has to be slot_<slot> and then "-id_<cert>" */
+
+       if (strncmp(slot_id, "slot_", 5) != 0) {
+               fprintf(stderr, "format not recognized!\n");
+               return 0;
+       }
+
+       /* slot is an digital int. */
+       if (sscanf(slot_id + 5, "%d", &n) != 1) {
+               fprintf(stderr, "slot number not deciphered!\n");
+               return 0;
+       }
+
+       i = strspn(slot_id + 5, DIGITS);
+
+       if (slot_id[i + 5] == 0) {
+               *slot = n;
+               *id_len = 0;
+               return 1; 
+       }
+
+       if (slot_id[i + 5] != '-') {
+               fprintf(stderr, "could not parse string!\n");
+               return 0;
+       }
+
+       i = 5 + i + 1;
+
+       /* now followed by "id_" */
+       if (strncmp(slot_id + i, "id_", 3) == 0) {
+               if (strspn(slot_id + i + 3, HEXDIGITS) + 3 + i !=
+                   strlen(slot_id)) {
+                       fprintf(stderr, "could not parse string!\n");
+                       return 0;
+               }
+               /* ah, rest is hex */
+               if ((strlen(slot_id) - i - 3 + 1) / 2 > *id_len) {
+                       fprintf(stderr, "id string too long!\n");
+                       return 0;
+               }
+               *slot = n;
+               return hex_to_bin(slot_id + i + 3, id, id_len);
+       }
+
+       /* ... or "label_" */
+       if (strncmp(slot_id + i, "label_", 6) == 0) {
+               *slot = n;
+               return (*label = strdup(slot_id + i + 6)) != NULL;
+       }
+
+       fprintf(stderr, "could not parse string!\n");
+       return 0;
+}
+
+#define MAX_VALUE_LEN  200
+
+/* prototype for OpenSSL ENGINE_load_cert */
+/* used by load_cert_ctrl via ENGINE_ctrl for now */
+
+static X509 *pkcs11_load_cert(ENGINE * e, const char *s_slot_cert_id)
+{
+       PKCS11_SLOT *slot_list, *slot;
+       PKCS11_SLOT *found_slot = NULL;
+       PKCS11_TOKEN *tok;
+       PKCS11_CERT *certs, *selected_cert = NULL;
+       X509 *x509;
+       unsigned int slot_count, cert_count, n, m;
+       unsigned char cert_id[MAX_VALUE_LEN / 2];
+       size_t cert_id_len = sizeof(cert_id);
+       char *cert_label = NULL;
+       int slot_nr = -1;
+       char flags[64];
+
+       if (s_slot_cert_id && *s_slot_cert_id) {
+               n = parse_slot_id_string(s_slot_cert_id, &slot_nr,
+                                        cert_id, &cert_id_len, &cert_label);
+               if (!n) {
+                       fprintf(stderr,
+                               "supported formats: <id>, <slot>:<id>, id_<id>, slot_<slot>-id_<id>, label_<label>, slot_<slot>-label_<label>\n");
+                       fprintf(stderr,
+                               "where <slot> is the slot number as normal integer,\n");
+                       fprintf(stderr,
+                               "and <id> is the id number as hex string.\n");
+                       fprintf(stderr,
+                               "and <label> is the textual key label string.\n");
+                       return NULL;
+               }
+               if (verbose) {
+                       fprintf(stderr, "Looking in slot %d for certificate: ",
+                               slot_nr);
+                       if (cert_label == NULL) {
+                               for (n = 0; n < cert_id_len; n++)
+                                       fprintf(stderr, "%02x", cert_id[n]);
+                               fprintf(stderr, "\n");
+                       } else
+                               fprintf(stderr, "label: %s\n", cert_label);
+
+               }
+       }
+
+       if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0)
+               fail("failed to enumerate slots\n");
+
+       if (verbose) {
+               fprintf(stderr, "Found %u slot%s\n", slot_count,
+                       (slot_count <= 1) ? "" : "s");
+       }
+       for (n = 0; n < slot_count; n++) {
+               slot = slot_list + n;
+               flags[0] = '\0';
+               if (slot->token) {
+                       if (!slot->token->initialized)
+                               strcat(flags, "uninitialized, ");
+                       else if (!slot->token->userPinSet)
+                               strcat(flags, "no pin, ");
+                       if (slot->token->loginRequired)
+                               strcat(flags, "login, ");
+                       if (slot->token->readOnly)
+                               strcat(flags, "ro, ");
+               } else {
+                       strcpy(flags, "no token");
+               }
+               if ((m = strlen(flags)) != 0) {
+                       flags[m - 2] = '\0';
+               }
+
+               if (slot_nr != -1 &&
+                       slot_nr == PKCS11_get_slotid_from_slot(slot)) {
+                       found_slot = slot;
+               }
+
+               if (verbose) {
+                       fprintf(stderr, "[%lu] %-25.25s  %-16s",
+                               PKCS11_get_slotid_from_slot(slot),
+                               slot->description, flags);
+                       if (slot->token) {
+                               fprintf(stderr, "  (%s)",
+                                       slot->token->label[0] ?
+                                       slot->token->label : "no label");
+                       }
+                       fprintf(stderr, "\n");
+               }
+       }
+
+       if (slot_nr == -1) {
+               if (!(slot = PKCS11_find_token(ctx, slot_list, slot_count)))
+                       fail("didn't find any tokens\n");
+       } else if (found_slot) {
+               slot = found_slot; 
+       } else {
+               fprintf(stderr, "Invalid slot number: %d\n", slot_nr);
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+       tok = slot->token;
+
+       if (tok == NULL) {
+               fprintf(stderr, "Found empty token; \n");
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+
+       if (verbose) {
+               fprintf(stderr, "Found slot:  %s\n", slot->description);
+               fprintf(stderr, "Found token: %s\n", slot->token->label);
+       }
+
+       if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
+               fprintf(stderr, "unable to enumerate certificates\n");
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+
+       if (verbose) {
+               fprintf(stderr, "Found %u cert%s:\n", cert_count,
+                       (cert_count <= 1) ? "" : "s");
+       }
+       if ((s_slot_cert_id && *s_slot_cert_id) && (cert_id_len != 0)) {
+               for (n = 0; n < cert_count; n++) {
+                       PKCS11_CERT *k = certs + n;
+
+                       if (cert_id_len != 0 && k->id_len == cert_id_len &&
+                           memcmp(k->id, cert_id, cert_id_len) == 0) {
+                               selected_cert = k;
+                       }
+               }
+       } else {
+               selected_cert = certs;  /* use first */
+       }
+
+       if (selected_cert == NULL) {
+               fprintf(stderr, "certificate not found.\n");
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+
+       x509 = X509_dup(selected_cert->x509);
+       if (cert_label != NULL)
+               free(cert_label);
+       return x509;
+}
+
+int load_cert_ctrl(ENGINE * e, void *p)
+{
+       struct {
+               const char *s_slot_cert_id;
+               X509 *cert;
+       } *parms = p;
+
+       if (parms->cert != NULL)
+               return 0;
+
+       parms->cert = pkcs11_load_cert(e, parms->s_slot_cert_id);
+       if (parms->cert == NULL)
+               return 0;
+
+       return 1;
+}
+
+static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
+                                UI_METHOD * ui_method, void *callback_data,
+                                int isPrivate)
+{
+       PKCS11_SLOT *slot_list, *slot;
+       PKCS11_SLOT *found_slot = NULL;
+       PKCS11_TOKEN *tok;
+       PKCS11_KEY *keys, *selected_key = NULL;
+       PKCS11_CERT *certs;
+       EVP_PKEY *pk;
+       unsigned int slot_count, cert_count, key_count, n, m;
+       unsigned char key_id[MAX_VALUE_LEN / 2];
+       size_t key_id_len = sizeof(key_id);
+       char *key_label = NULL;
+       int slot_nr = -1;
+       char flags[64];
+
+       if (s_slot_key_id && *s_slot_key_id) {
+               n = parse_slot_id_string(s_slot_key_id, &slot_nr,
+                                        key_id, &key_id_len, &key_label);
+
+               if (!n) {
+                       fprintf(stderr,
+                               "supported formats: <id>, <slot>:<id>, id_<id>, slot_<slot>-id_<id>, label_<label>, slot_<slot>-label_<label>\n");
+                       fprintf(stderr,
+                               "where <slot> is the slot number as normal integer,\n");
+                       fprintf(stderr,
+                               "and <id> is the id number as hex string.\n");
+                       fprintf(stderr,
+                               "and <label> is the textual key label string.\n");
+                       return NULL;
+               }
+               if (verbose) {
+                       fprintf(stderr, "Looking in slot %d for key: ",
+                               slot_nr);
+                       if (key_label == NULL) {
+                               for (n = 0; n < key_id_len; n++)
+                                       fprintf(stderr, "%02x", key_id[n]);
+                               fprintf(stderr, "\n");
+                       } else
+                               fprintf(stderr, "label: %s\n", key_label);
+               }
+       }
+
+       if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0)
+               fail("failed to enumerate slots\n");
+
+       if (verbose) {
+               fprintf(stderr, "Found %u slot%s\n", slot_count,
+                       (slot_count <= 1) ? "" : "s");
+       }
+       for (n = 0; n < slot_count; n++) {
+               slot = slot_list + n;
+               flags[0] = '\0';
+               if (slot->token) {
+                       if (!slot->token->initialized)
+                               strcat(flags, "uninitialized, ");
+                       else if (!slot->token->userPinSet)
+                               strcat(flags, "no pin, ");
+                       if (slot->token->loginRequired)
+                               strcat(flags, "login, ");
+                       if (slot->token->readOnly)
+                               strcat(flags, "ro, ");
+               } else {
+                       strcpy(flags, "no token");
+               }
+               if ((m = strlen(flags)) != 0) {
+                       flags[m - 2] = '\0';
+               }
+
+               if (slot_nr != -1 &&
+                       slot_nr == PKCS11_get_slotid_from_slot(slot)) {
+                       found_slot = slot;
+               }
+
+               if (verbose) {
+                       fprintf(stderr, "[%lu] %-25.25s  %-16s",
+                               PKCS11_get_slotid_from_slot(slot),
+                               slot->description, flags);
+                       if (slot->token) {
+                               fprintf(stderr, "  (%s)",
+                                       slot->token->label[0] ?
+                                       slot->token->label : "no label");
+                       }
+                       fprintf(stderr, "\n");
+               }
+       }
+
+       if (slot_nr == -1) {
+               if (!(slot = PKCS11_find_token(ctx, slot_list, slot_count)))
+                       fail("didn't find any tokens\n");
+       } else if (found_slot) {
+               slot = found_slot;
+       } else {
+               fprintf(stderr, "Invalid slot number: %d\n", slot_nr);
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+       tok = slot->token;
+
+       if (tok == NULL) {
+               fprintf(stderr, "Found empty token; \n");
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+/* Removed for interop with some other pkcs11 libs. */
+#if 0
+       if (!tok->initialized) {
+               fprintf(stderr, "Found uninitialized token; \n");
+               return NULL;
+       }
+#endif
+       if (isPrivate && !tok->userPinSet && !tok->readOnly) {
+               fprintf(stderr, "Found slot without user PIN\n");
+               PKCS11_release_all_slots(ctx, slot_list, slot_count);
+               return NULL;
+       }
+
+       if (verbose) {
+               fprintf(stderr, "Found slot:  %s\n", slot->description);
+               fprintf(stderr, "Found token: %s\n", slot->token->label);
+       }
+
+       if (PKCS11_enumerate_certs(tok, &certs, &cert_count))
+               fail("unable to enumerate certificates\n");
+
+       if (verbose) {
+               fprintf(stderr, "Found %u certificate%s:\n", cert_count,
+                       (cert_count <= 1) ? "" : "s");
+               for (n = 0; n < cert_count; n++) {
+                       PKCS11_CERT *c = certs + n;
+                       char *dn = NULL;
+
+                       fprintf(stderr, "  %2u    %s", n + 1, c->label);
+                       if (c->x509)
+                               dn = X509_NAME_oneline(X509_get_subject_name
+                                                      (c->x509), NULL, 0);
+                       if (dn) {
+                               fprintf(stderr, " (%s)", dn);
+                               OPENSSL_free(dn);
+                       }
+                       fprintf(stderr, "\n");
+               }
+       }
+
+       /* Perform login to the token if required */
+       if (tok->loginRequired) {
+               /* If the token has a secure login (i.e., an external keypad),
+                  then use a NULL pin. Otherwise, check if a PIN exists. If
+                  not, allocate and obtain a new PIN. */
+               if (tok->secureLogin) {
+                       /* Free the PIN if it has already been 
+                          assigned (i.e, cached by get_pin) */
+                       if (pin != NULL) {
+                               OPENSSL_cleanse(pin, pin_length);
+                               free(pin);
+                               pin = NULL;
+                               pin_length = 0;
+                       }
+               } else if (pin == NULL) {
+                       pin = (char *)calloc(MAX_PIN_LENGTH, sizeof(char));
+                       pin_length = MAX_PIN_LENGTH;
+                       if (pin == NULL) {
+                               fail("Could not allocate memory for PIN");
+                       }
+                       if (!get_pin(ui_method, callback_data) ) {
+                               OPENSSL_cleanse(pin, pin_length);
+                               free(pin);
+                               pin = NULL;
+                               pin_length = 0;
+                               fail("No pin code was entered");
+                       }
+               }
+
+               /* Now login in with the (possibly NULL) pin */
+               if (PKCS11_login(slot, 0, pin)) {
+                       /* Login failed, so free the PIN if present */
+                       if (pin != NULL) {
+                               OPENSSL_cleanse(pin, pin_length);
+                               free(pin);
+                               pin = NULL;
+                               pin_length = 0;
+                       }
+                       fail("Login failed\n");
+               }
+               /* Login successful, PIN retained in case further logins are 
+                  required. This will occur on subsequent calls to the
+                  pkcs11_load_key function. Subsequent login calls should be
+                  relatively fast (the token should maintain its own login
+                  state), although there may still be a slight performance 
+                  penalty. We could maintain state noting that successful
+                  login has been performed, but this state may not be updated
+                  if the token is removed and reinserted between calls. It
+                  seems safer to retain the PIN and peform a login on each
+                  call to pkcs11_load_key, even if this may not be strictly
+                  necessary. */
+               /* TODO when does PIN get freed after successful login? */
+               /* TODO confirm that multiple login attempts do not introduce
+                  significant performance penalties */
+
+       }
+
+       /* Make sure there is at least one private key on the token */
+       if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
+               fail("unable to enumerate keys\n");
+       }
+       if (key_count == 0) {
+               fail("No keys found.\n");
+       }
+
+       if (verbose) {
+               fprintf(stderr, "Found %u key%s:\n", key_count,
+                       (key_count <= 1) ? "" : "s");
+       }
+       if (s_slot_key_id && *s_slot_key_id && (key_id_len != 0 || key_label != NULL)) {
+               for (n = 0; n < key_count; n++) {
+                       PKCS11_KEY *k = keys + n;
+
+                       if (verbose) {
+                               fprintf(stderr, "  %2u %c%c %s\n", n + 1,
+                                       k->isPrivate ? 'P' : ' ',
+                                       k->needLogin ? 'L' : ' ', k->label);
+                       }
+                       if (key_label == NULL) {
+                               if (key_id_len != 0 && k->id_len == key_id_len
+                                   && memcmp(k->id, key_id, key_id_len) == 0) {
+                                       selected_key = k;
+                               }
+                       } else {
+                               if (strcmp(k->label, key_label) == 0) {
+                                       selected_key = k;
+                               }
+                       }
+               }
+       } else {
+               selected_key = keys;    /* use first */
+       }
+
+       if (selected_key == NULL) {
+               fprintf(stderr, "key not found.\n");
+               return NULL;
+       }
+
+       if (isPrivate) {
+               pk = PKCS11_get_private_key(selected_key);
+       } else {
+               /*pk = PKCS11_get_public_key(&keys[0]);
+                  need a get_public_key? */
+               pk = PKCS11_get_private_key(selected_key);
+       }
+       if (key_label != NULL)
+               free(key_label);
+       return pk;
+}
+
+EVP_PKEY *pkcs11_load_public_key(ENGINE * e, const char *s_key_id,
+                                UI_METHOD * ui_method, void *callback_data)
+{
+       EVP_PKEY *pk;
+
+       pk = pkcs11_load_key(e, s_key_id, ui_method, callback_data, 0);
+       if (pk == NULL)
+               fail("PKCS11_load_public_key returned NULL\n");
+       return pk;
+}
+
+EVP_PKEY *pkcs11_load_private_key(ENGINE * e, const char *s_key_id,
+                                 UI_METHOD * ui_method, void *callback_data)
+{
+       EVP_PKEY *pk;
+
+       pk = pkcs11_load_key(e, s_key_id, ui_method, callback_data, 1);
+       if (pk == NULL)
+               fail("PKCS11_get_private_key returned NULL\n");
+       return pk;
+}
diff --git a/src/engine_pkcs11.exports b/src/engine_pkcs11.exports
new file mode 100644 (file)
index 0000000..6b8b3a9
--- /dev/null
@@ -0,0 +1,2 @@
+v_check
+bind_engine
diff --git a/src/engine_pkcs11.h b/src/engine_pkcs11.h
new file mode 100644 (file)
index 0000000..2159330
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2002 Juha Yrjölä.  All rights reserved.
+ * Copyright (c) 2001 Markus Friedl.
+ * Copyright (c) 2003 Kevin Stefanik
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ENGINE_PKCS11_H
+#define _ENGINE_PKCS11_H
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/objects.h>
+#include <openssl/engine.h>
+
+int set_module(const char *modulename);
+
+int set_pin(const char *pin);
+
+int set_init_args(const char *init_args_orig);
+
+int load_cert_ctrl(ENGINE * e, void *p);
+
+int inc_verbose(void);
+
+int pkcs11_finish(ENGINE * engine);
+
+int pkcs11_init(ENGINE * engine);
+
+int pkcs11_rsa_finish(RSA * rsa);
+
+EVP_PKEY *pkcs11_load_public_key(ENGINE * e, const char *s_key_id,
+                                UI_METHOD * ui_method, void *callback_data);
+
+EVP_PKEY *pkcs11_load_private_key(ENGINE * e, const char *s_key_id,
+                                 UI_METHOD * ui_method, void *callback_data);
+
+#endif
diff --git a/src/hw_pkcs11.c b/src/hw_pkcs11.c
new file mode 100644 (file)
index 0000000..24806ff
--- /dev/null
@@ -0,0 +1,217 @@
+/* crypto/engine/hw_pkcs11.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ * Copied/modified by Kevin Stefanik (kstef@mtppi.org) for the OpenSC
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
+ * Portions Copyright (c) 2003 Kevin Stefanik (kstef@mtppi.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/objects.h>
+#include <openssl/engine.h>
+#include <openssl/dso.h>
+#ifndef ENGINE_CMD_BASE
+#error did not get engine.h
+#endif
+#include <libp11.h>
+#include "engine_pkcs11.h"
+
+#define PKCS11_ENGINE_ID "pkcs11"
+#define PKCS11_ENGINE_NAME "pkcs11 engine"
+
+#define CMD_SO_PATH            ENGINE_CMD_BASE
+#define CMD_MODULE_PATH        (ENGINE_CMD_BASE+1)
+#define CMD_PIN                (ENGINE_CMD_BASE+2)
+#define CMD_VERBOSE            (ENGINE_CMD_BASE+3)
+#define CMD_QUIET              (ENGINE_CMD_BASE+4)
+#define CMD_LOAD_CERT_CTRL     (ENGINE_CMD_BASE+5)
+#define CMD_INIT_ARGS  (ENGINE_CMD_BASE+6)
+
+static int pkcs11_engine_destroy(ENGINE * e);
+static int pkcs11_engine_ctrl(ENGINE * e, int cmd, long i, void *p,
+                             void (*f) ());
+
+/* The definitions for control commands specific to this engine */
+
+/* need to add function to pass in reader id? or user reader:key as key id string? */
+
+static const ENGINE_CMD_DEFN pkcs11_cmd_defns[] = {
+       {CMD_SO_PATH,
+        "SO_PATH",
+        "Specifies the path to the 'pkcs11-engine' shared library",
+        ENGINE_CMD_FLAG_STRING},
+       {CMD_MODULE_PATH,
+        "MODULE_PATH",
+        "Specifies the path to the pkcs11 module shared library",
+        ENGINE_CMD_FLAG_STRING},
+       {CMD_PIN,
+        "PIN",
+        "Specifies the pin code",
+        ENGINE_CMD_FLAG_STRING},
+       {CMD_VERBOSE,
+        "VERBOSE",
+        "Print additional details",
+        ENGINE_CMD_FLAG_NO_INPUT},
+       {CMD_QUIET,
+        "QUIET",
+        "Remove additional details",
+        ENGINE_CMD_FLAG_NO_INPUT},
+       {CMD_LOAD_CERT_CTRL,
+        "LOAD_CERT_CTRL",
+        "Get the certificate from card",
+        ENGINE_CMD_FLAG_INTERNAL},
+       {CMD_INIT_ARGS,
+        "INIT_ARGS",
+        "Specifies additional initialization arguments to the pkcs11 module",
+        ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+};
+
+/* Destructor */
+static int pkcs11_engine_destroy(ENGINE * e)
+{
+       return 1;
+}
+
+static int pkcs11_engine_ctrl(ENGINE * e, int cmd, long i, void *p,
+                             void (*f) ())
+{
+       /*int initialised = ((pkcs11_dso == NULL) ? 0 : 1); */
+       switch (cmd) {
+       case CMD_MODULE_PATH:
+               return set_module((const char *)p);
+       case CMD_PIN:
+               return set_pin((const char *)p);
+       case CMD_VERBOSE:
+               return inc_verbose();
+       case CMD_LOAD_CERT_CTRL:
+               return load_cert_ctrl(e, p);
+       case CMD_INIT_ARGS:
+               return set_init_args((const char *)p);
+       default:
+               break;
+       }
+       return 0;
+}
+
+#if 0
+/* set up default rsa_meth_st with overloaded rsa functions */
+/* the actual implementation needs to be in another object */
+
+static int (*orig_finish) (RSA * rsa);
+
+static int pkcs11_engine_rsa_finish(RSA * rsa)
+{
+
+       pkcs11_rsa_finish(rsa);
+
+       if (orig_finish)
+               orig_finish(rsa);
+       return 1;
+
+}
+#endif
+
+/* This internal function is used by ENGINE_pkcs11() and possibly by the
+ * "dynamic" ENGINE support too */
+static int bind_helper(ENGINE * e)
+{
+       if (!ENGINE_set_id(e, PKCS11_ENGINE_ID) ||
+           !ENGINE_set_destroy_function(e, pkcs11_engine_destroy) ||
+           !ENGINE_set_init_function(e, pkcs11_init) ||
+           !ENGINE_set_finish_function(e, pkcs11_finish) ||
+           !ENGINE_set_ctrl_function(e, pkcs11_engine_ctrl) ||
+           !ENGINE_set_cmd_defns(e, pkcs11_cmd_defns) ||
+           !ENGINE_set_name(e, PKCS11_ENGINE_NAME) ||
+#ifndef OPENSSL_NO_RSA
+           !ENGINE_set_RSA(e, PKCS11_get_rsa_method()) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+           !ENGINE_set_DSA(e, DSA_get_default_method()) ||
+#endif
+#ifndef OPENSSL_NO_DH
+           !ENGINE_set_DH(e, DH_get_default_method()) ||
+#endif
+           !ENGINE_set_RAND(e, RAND_SSLeay()) ||
+#if 0
+           !ENGINE_set_BN_mod_exp(e, BN_mod_exp) ||
+#endif
+           !ENGINE_set_load_pubkey_function(e, pkcs11_load_public_key) ||
+           !ENGINE_set_load_privkey_function(e, pkcs11_load_private_key)) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+static int bind_fn(ENGINE * e, const char *id)
+{
+       if (id && (strcmp(id, PKCS11_ENGINE_ID) != 0)) {
+               fprintf(stderr, "bad engine id\n");
+               return 0;
+       }
+       if (!bind_helper(e)) {
+               fprintf(stderr, "bind failed\n");
+               return 0;
+       }
+       return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN();
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in
new file mode 100644 (file)
index 0000000..dc2a866
--- /dev/null
@@ -0,0 +1,35 @@
+#include <winresrc.h>
+
+VS_VERSION_INFO VERSIONINFO
+       FILEVERSION @ENGINE_PKCS11_VERSION_MAJOR@,@ENGINE_PKCS11_VERSION_MINOR@,@ENGINE_PKCS11_VERSION_FIX@,0
+       PRODUCTVERSION @ENGINE_PKCS11_VERSION_MAJOR@,@ENGINE_PKCS11_VERSION_MINOR@,@ENGINE_PKCS11_VERSION_FIX@,0
+       FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+       FILEFLAGS 0x21L
+#else
+       FILEFLAGS 0x20L
+#endif
+       FILEOS 0x40004L
+       FILETYPE 0x1L
+       FILESUBTYPE 0x0L
+BEGIN
+       BLOCK "StringFileInfo"
+       BEGIN
+               BLOCK "040904b0"
+               BEGIN
+                       VALUE "Comments", "Provided under the terms of the GNU General Public License (LGPLv2.1+).\0"
+                       VALUE "CompanyName", "OpenSC Project\0"
+                       VALUE "FileDescription", "OpenSSL PKCS#11 engine\0"
+                       VALUE "FileVersion", "@ENGINE_PKCS11_VERSION_MAJOR@,@ENGINE_PKCS11_VERSION_MINOR@,@ENGINE_PKCS11_VERSION_FIX@,0\0"
+                       VALUE "InternalName", "@PACKAGE_NAME@\0"
+                       VALUE "LegalCopyright", "OpenSC Project\0"
+                       VALUE "LegalTrademarks", "\0"
+                       VALUE "OriginalFilename", "@PACKAGE_NAME@.dll\0"
+                       VALUE "PrivateBuild", "\0"
+                       VALUE "ProductName", "@PACKAGE_NAME@\0"
+                       VALUE "ProductVersion", "@ENGINE_PKCS11_VERSION_MAJOR@,@ENGINE_PKCS11_VERSION_MINOR@,@ENGINE_PKCS11_VERSION_FIX@,0\0"
+                       VALUE "SpecialBuild", "\0"
+               END
+       END
+END
+