[pkg-opensc-commit] [engine-pkcs11] 02/152: initial checkin of a standalone engine_pkcs11.
Eric Dorland
eric at moszumanska.debian.org
Mon Oct 19 03:11:07 UTC 2015
This is an automated email from the git hooks/post-receive script.
eric pushed a commit to branch master
in repository engine-pkcs11.
commit b2455b097f8bd9b0a075df3820ce21c6bf33357a
Author: Andreas Jellinghaus <andreas at ionisiert.de>
Date: Sun Aug 28 19:52:19 2005 +0000
initial checkin of a standalone engine_pkcs11.
---
Makefile.am | 15 ++
bootstrap | 11 +
configure.ac | 282 +++++++++++++++++++++
doc/Makefile.am | 7 +
doc/README | 10 +
doc/export-wiki.sh | 34 +++
doc/export-wiki.xsl | 58 +++++
libtool-bundle | 104 ++++++++
src/Makefile.am | 32 +++
src/Makefile.mak | 12 +
src/engine_pkcs11.c | 671 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/engine_pkcs11.def | 4 +
src/engine_pkcs11.h | 59 +++++
src/hw_opensc.c | 215 ++++++++++++++++
src/hw_pkcs11.c | 204 +++++++++++++++
15 files changed, 1718 insertions(+)
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..f86a689
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,15 @@
+# Process this file with automake to create Makefile.in
+
+SUBDIRS = . doc src
+
+EXTRA_DIST = bootstrap depcomp
+
+MAINTAINERCLEANFILES = \
+ Makefile.in config.h.in configure \
+ install-sh ltmain.sh missing mkinstalldirs \
+ compile depcomp config.log config.status \
+ config.guess config.sub acinclude.m4 aclocal.m4
+
+DEPCLEANFILES = config.log configure
+
+AUTOMAKE_OPTIONS = foreign 1.5
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..4e964bd
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,11 @@
+#!/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
+(cat aclocal/*.m4 > acinclude.m4 2> /dev/null)
+autoreconf --verbose --install
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..52d46f8
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,282 @@
+dnl -*- mode: m4; -*-
+dnl Process this file with autoconf to produce a configure script.
+
+# Require autoconf 2.52
+AC_PREREQ(2.52)
+
+AC_INIT(engine_pkcs11, WIP)
+AM_INIT_AUTOMAKE
+AM_CONFIG_HEADER(config.h)
+
+AC_CONFIG_SRCDIR(src/engine_pkcs11.c)
+
+
+AC_CANONICAL_HOST
+AC_PROG_CC
+AC_C_BIGENDIAN
+
+dnl Options
+AM_MAINTAINER_MODE
+
+dnl Checks for programs.
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+dnl Add libtool support.
+AM_PROG_LIBTOOL
+dnl Automatically update the libtool script if it becomes out-of-date.
+#AC_SUBST(LIBTOOL_DEPS)
+
+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])
+
+dnl The big mess with OpenSSL
+saved_LIBS="$LIBS"
+saved_LDFLAGS="$LDFLAGS"
+saved_CPPFLAGS="$CPPFLAGS"
+
+SSL_MSG="no"
+ssldir=""
+
+AC_ARG_WITH(openssl,
+ AC_HELP_STRING([--with-openssl=PATH], [use OpenSSL in PATH]),
+ [
+ # Disable OpenSSL support
+ if test "x$withval" = "xno" ; then
+ SSL_MSG="no (disabled)"
+ break;
+ fi
+
+ # ok we got a directory, so only check in that dir.
+ LIBCRYPTO="-lcrypto"
+ CPPFLAGS="$saved_CPPFLAGS"
+ LDFLAGS="$saved_LDFLAGS"
+ LIBS="$LIBCRYPTO $saved_LIBS"
+ LDFLAGS="-L$withval/lib $saved_LDFLAGS"
+ if test ! -z "$need_dash_r" ; then
+ LDFLAGS="-R$withval/lib $LDFLAGS"
+ fi
+ CPPFLAGS="-I$withval/include $saved_CPPFLAGS"
+
+ AC_TRY_RUN(
+ [
+#include <string.h>
+#include <openssl/rand.h>
+int main(void)
+{
+ char a[2048];
+ memset(a, 0, sizeof(a));
+ RAND_add(a, sizeof(a), sizeof(a));
+ return(RAND_status() <= 0);
+}
+ ],
+ [
+ SSL_MSG="yes"
+ ssldir="$withval"
+ break
+ ])
+ ],[
+
+ # we didn't get a directory, so we start searching for openssl
+ for tryssldir in $commondir /usr /usr/local/openssl /usr/lib/openssl /usr/local/ssl /usr/lib/ssl /usr/local /usr/pkg /opt /opt/openssl; do
+ # Skip directories if they don't exist
+ if test ! -d "$tryssldir/" ; then
+ continue;
+ fi
+
+ LIBCRYPTO="-lcrypto"
+ CPPFLAGS="$saved_CPPFLAGS"
+ LDFLAGS="$saved_LDFLAGS"
+ LIBS="$saved_LIBS $LIBCRYPTO"
+
+ if test "x$tryssldir" != "x/usr"; then
+ LDFLAGS="-L$tryssldir/lib $saved_LDFLAGS"
+ if test ! -z "$need_dash_r" ; then
+ LDFLAGS="-R$tryssldir/lib $LDFLAGS"
+ fi
+ CPPFLAGS="-I$tryssldir/include $saved_CPPFLAGS"
+ fi
+
+ # Basic test to check for compatible version and correct linking
+ # *does not* test for RSA - that comes later.
+ AC_TRY_RUN(
+ [
+#include <string.h>
+#include <openssl/rand.h>
+int main(void)
+{
+ char a[2048];
+ memset(a, 0, sizeof(a));
+ RAND_add(a, sizeof(a), sizeof(a));
+ return(RAND_status() <= 0);
+}
+ ],
+ [
+ SSL_MSG="yes"
+ ssldir=$tryssldir
+ break;
+ ],
+ [
+ SSL_MSG="no"
+ LIBS="$saved_LIBS"
+ LDFLAGS="$saved_LDFLAGS"
+ CPPFLAGS="$saved_CPPFLAGS"
+ ])
+ done
+ ])
+LIBS="$saved_LIBS"
+AC_SUBST(LIBCRYPTO)
+AM_CONDITIONAL(HAVE_SSL, test "x$SSL_MSG" = "xyes")
+
+if test "x$SSL_MSG" = "xyes" ; then
+ AC_DEFINE(HAVE_OPENSSL, 1, [Have OpenSSL libraries])
+else
+ LIBCRYPTO=""
+fi
+
+# ok, we checked for basic ssl support.
+# if it is not available, we can skip the rest of
+# the test. also we have $ssldir set to the location
+# of the openssl libs.
+
+ENGINE_MSG="no"
+if test "x$SSL_MSG" = "xyes"; then
+ # engine has to be there and working
+ LIBS="$saved_LIBS $LIBCRYPTO $LIBDL"
+ AC_TRY_RUN(
+ [
+#include <string.h>
+#include <openssl/opensslv.h>
+#include <openssl/engine.h>
+#include <openssl/rand.h>
+int main(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);
+}
+ ],
+ [
+ ENGINE_MSG=yes
+ ENGINE_LINK="$LIBCRYPTO"
+ ],
+ [
+ ENGINE_MSG=no
+ ]);
+fi
+LIBS="$saved_LIBS"
+AC_SUBST(ENGINE_LINK)
+AM_CONDITIONAL(HAVE_ENGINE, test "x$ENGINE_MSG" = "xyes")
+
+# ok, now we might (or not) have ssl and an engine.
+# still room for "improvements", i.e. hacks to work
+# with old engines.
+
+SSLHACK_MSG=no
+if test "x$SSL_MSG" = "xyes" -a "x$ENGINE_MSG" = "xyes"; then
+ # latest openssl version with engine
+ # properly integrated?
+ AC_MSG_CHECKING([for openssl version])
+ AC_TRY_RUN(
+ [
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/opensslv.h>
+
+int main(void)
+{
+ if(OPENSSL_VERSION_NUMBER >= 0x0090704fL) {
+ exit(0);
+ } else {
+ exit(1);
+ }
+}
+ ],
+ [
+ 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
+ ])
+
+ if test "x$OLD_OPENSSL" = "xyes"; then
+ # openssl found, but version less than 0.9.7d
+ # linking libcrypto.a statically possible?
+
+ LIBS="$saved_LIBS $ssldir/lib/libcrypto.a $LIBDL"
+ AC_TRY_RUN(
+ [
+#include <string.h>
+#include <openssl/opensslv.h>
+#include <openssl/engine.h>
+#include <openssl/rand.h>
+int main(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);
+}
+ ],
+ [
+ SSLHACK_MSG=yes
+ ENGINE_LINK="$ssldir/lib/libcrypto.a"
+ ])
+ LIBS="$saved_LIBS"
+ fi
+fi
+
+# now - last part to do: check if we gain anything from
+# funny parameters to link openssl with.
+
+saved_LDFLAGS="$LDFLAGS"
+if test "x$ENGINE_MSG" = "xyes" ; then
+ for openssl_ldflag in "-Wl,-Bsymbolic" "-G -Wl,-Bsymbolic" "-shared -G -Wl,-Bsymbolic" "-Wl,-all_load"; do
+ AC_MSG_CHECKING([whether we can use $openssl_ldflag])
+ LDFLAGS="$saved_LDFLAGS $openssl_ldflag"
+ AC_TRY_LINK(,[return 1],ac_cv_use_openssl_flag="yes",ac_cv_use_openssl_flag="no")
+ AC_MSG_RESULT($ac_cv_use_openssl_flag)
+ if test "$ac_cv_use_openssl_flag" = "yes"; then
+ OPENSSL_LDFLAGS="$openssl_ldflag"
+ break;
+ fi
+ done
+fi
+LDFLAGS="$saved_LDFLAGS"
+AC_SUBST(OPENSSL_LDFLAGS)
+
+AM_CONDITIONAL(HAVE_BUNDLES, test "x$with_bundles" = "xyes")
+
+AC_OUTPUT([
+Makefile
+doc/Makefile
+src/Makefile
+])
+
+echo ""
+echo "Engine_pkcs11 has been configured with the following options"
+
+echo ""
+echo "OpenSSL support: ${SSL_MSG}"
+echo " with engine: ${ENGINE_MSG}"
+echo " with sslhack: ${SSLHACK_MSG}"
+echo ""
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..2a63710
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,7 @@
+# Process this file with automake to create Makefile.in
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = README export-wiki.sh export-wiki.xsl $(HTML)
+
+HTML=
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..2c3ff75
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,10 @@
+This directory contains a snapshot of the engine_pkcs11 Wiki
+============================================================
+
+The original wiki page is at http://www.opensc.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/export-wiki.sh b/doc/export-wiki.sh
new file mode 100644
index 0000000..ea7f5ec
--- /dev/null
+++ b/doc/export-wiki.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+set -e
+
+export SERVER=http://www.opensc.org
+export WIKI=engine_pkcs11/wiki
+export XSL=export-wiki.xsl
+
+test -f `basename $0`
+
+rm -rf *.html *.css
+
+wget $SERVER/$WIKI/TitleIndex -O TitleIndex.tmp
+
+grep "\"/$WIKI/[^\"]*\"" TitleIndex.tmp \
+ |sed -e "s#.*\"/$WIKI/\([^\"]*\)\".*#\1#g" \
+ > WikiWords.tmp
+sed -e /^Trac/d -e /^Wiki/d -e /^TitleIndex/d -e /^RecentChanges/d \
+ -e /^CamelCase/d -e /^SandBox/d -i WikiWords.tmp
+
+for A in WikiStart `cat WikiWords.tmp`
+do
+ F=`echo $A|sed -e 's/\//_/g'`
+ wget $SERVER/$WIKI/$A -O $F.tmp
+ xsltproc --output $F.html $XSL $F.tmp
+ sed -e "s#<a href=\"/$WIKI/\([^\"]*\)\"#<a href=\"\1.html\"#g" \
+ -i $F.html
+done
+
+mv WikiStart.html index.html
+
+wget http://www.opensc.org/trac/css/trac.css
+
+rm *.tmp
diff --git a/doc/export-wiki.xsl b/doc/export-wiki.xsl
new file mode 100644
index 0000000..145befb
--- /dev/null
+++ b/doc/export-wiki.xsl
@@ -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='wikipage']" />
+ <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/libtool-bundle b/libtool-bundle
new file mode 100755
index 0000000..96f094d
--- /dev/null
+++ b/libtool-bundle
@@ -0,0 +1,104 @@
+#!/bin/sh
+# A shell script to create MacOS X bundles
+# from files created by GNU libtool.
+# Incomplete, but works.
+#
+# $Id: libtool-bundle 1533 2003-10-16 20:41:34Z aet $
+# <aet at cc.hut.fi>
+#
+
+set -e
+verbose=0
+
+verbose_msg ()
+{
+ if [ $verbose -ne 0 ]; then
+ echo "libtool-bundle: $@"
+ fi
+}
+
+error_msg ()
+{
+ echo 1>&2 "libtool-bundle: $@"
+}
+
+usage ()
+{
+ error_msg "Usage: $0 [-e extra XML data] [Mach-O bundle file] [destination directory] <bundle name>"
+ exit 1
+}
+
+case $1 in
+ -e) shift; if [ "$1" ]; then extradata=$1; shift; else usage; fi; ;;
+esac
+
+[ $# -le 1 -o $# -ge 4 ] && usage
+
+sofile=$1
+[ ! -f $sofile ] && error_msg "Not a file or file not found: $sofile" && exit 1
+case "$sofile" in
+*.so*)
+ # Assume it's ok
+ ;;
+*)
+ error_msg "Invalid bundle: $sofile"
+ exit 1
+ ;;
+esac
+
+destdir=$2
+[ ! -d $destdir -o ! -w $destdir ] && error_msg "Not a directory or no write access: $destdir" && exit 1
+
+name="$sofile"
+[ $# -eq 3 ] && name=$3
+name=`echo $name | sed -e "s at .*/@@" -e "s@\.so.*@@"`
+root="$destdir/${name}.bundle"
+
+verbose_msg "sofile: $sofile"
+verbose_msg "destdir: $destdir"
+verbose_msg "name: $name"
+verbose_msg "root: $root"
+
+arch=`uname`
+[ x$arch = xDarwin ] && arch=MacOS
+type="BNDL"
+creator="????"
+
+# Overwrite existing bundle
+[ -d "$root" ] && rm -rf "$root"
+
+mkdir -p "$root"/Contents/$arch
+cp "$sofile" "$root"/Contents/$arch/"$name"
+echo "$type$creator" > "$root"/Contents/PkgInfo
+
+create_info_plist ()
+{
+ echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ echo "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
+ echo "<plist version=\"1.0\">"
+ echo "<dict>"
+ echo " <key>CFBundleDevelopmentRegion</key>"
+ echo " <string>English</string>"
+ echo " <key>CFBundleExecutable</key>"
+ echo " <string>$name</string>"
+ echo " <key>CFBundleInfoDictionaryVersion</key>"
+ echo " <string>6.0</string>"
+ echo " <key>CFBundleName</key>"
+ echo " <string>$name</string>"
+ echo " <key>CFBundlePackageType</key>"
+ echo " <string>$type</string>"
+ echo " <key>CFBundleSignature</key>"
+ echo " <string>$creator</string>"
+ echo " <key>CFBundleVersion</key>"
+ echo " <string>0.0.1d1</string>"
+ if [ "$extradata" ]; then
+ echo ""
+ [ -f "$extradata" ]; cat $extradata
+ fi
+ echo "</dict>"
+ echo "</plist>"
+}
+
+create_info_plist > "$root"/Contents/Info.plist
+
+echo "Installed $sofile as $root"
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..608103e
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,32 @@
+# Process this file with automake to create Makefile.in
+
+bundledir = @BUNDLEDIR@/opensc
+enginedir = @libdir@/openssl
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = Makefile.mak engine_pkcs11.def
+
+engine_LTLIBRARIES = engine_pkcs11.la
+
+OPENSSL_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_la_CFLAGS = $(OPENSSL_CFLAGS) -I$(srcdir)/../libp11 @LIBP11_CFLAGS@
+engine_pkcs11_la_LIBADD = @ENGINE_LINK@ @LIBP11_LIBS@
+engine_pkcs11_la_LDFLAGS = @OPENSSL_LDFLAGS@ -module -avoid-version
+
+install-exec-local: install-engineLTLIBRARIES
+if HAVE_BUNDLES
+ -${top_srcdir}/libtool-bundle $(DESTDIR)$(enginedir)/engine_pkcs11.so \
+ $(DESTDIR)$(bundledir)/
+endif
+
+uninstall-local: uninstall-engineLTLIBRARIES
+if HAVE_BUNDLES
+ rm -rf $(DESTDIR)$(bundledir)/engine_pkcs11.bundle/
+endif
diff --git a/src/Makefile.mak b/src/Makefile.mak
new file mode 100644
index 0000000..c67124e
--- /dev/null
+++ b/src/Makefile.mak
@@ -0,0 +1,12 @@
+TOPDIR = ..\..
+
+TARGET = engine_pkcs11.dll
+
+OBJECTS = engine_pkcs11.obj hw_pkcs11.obj
+
+all: $(TARGET)
+
+!INCLUDE $(TOPDIR)\win32\Make.rules.mak
+
+$(TARGET): $(OBJECTS) ..\libp11\libp11.lib ..\scconf\scconf.lib
+ link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET) $(OBJECTS) ..\libp11\libp11.lib ..\scconf\scconf.lib winscard.lib $(OPENSSL_LIB) gdi32.lib
diff --git a/src/engine_pkcs11.c b/src/engine_pkcs11.c
new file mode 100644
index 0000000..5becc83
--- /dev/null
+++ b/src/engine_pkcs11.c
@@ -0,0 +1,671 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/objects.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 12
+
+PKCS11_CTX *ctx;
+
+/**
+ * The PIN used for login. May be assigend by set_pin function, or by the
+ * get_pin function (using an external UI). 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;
+
+int verbose = 0;
+
+#if defined(_WIN32)
+#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11"
+#elif defined(HAVE_DLFCN_H) && defined(__APPLE__)
+#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11.so"
+#elif defined(__APPLE__)
+#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11.bundle"
+#else
+#define PKCS11_DEFAULT_MODULE_NAME "opensc-pkcs11.so"
+#endif
+
+char *module = PKCS11_DEFAULT_MODULE_NAME;
+int default_module = 1;
+
+int set_module(const char *modulename)
+{
+ module = strdup (modulename);
+ default_module = 0;
+ 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);
+
+ return (pin != NULL);
+}
+
+int inc_verbose()
+{
+ verbose++;
+ return 1;
+}
+
+static char *get_pin(UI_METHOD * ui_method, void *callback_data, char *sc_pin, int maxlen)
+{
+ UI *ui;
+
+ 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, sc_pin, 1, maxlen)) {
+ fprintf(stderr, "UI_add_input_string failed\n");
+ UI_free(ui);
+ return NULL;
+ }
+ if (UI_process(ui)) {
+ fprintf(stderr, "UI_process failed\n");
+ UI_free(ui);
+ return NULL;
+ }
+ UI_free(ui);
+ return sc_pin;
+}
+
+int pkcs11_finish(ENGINE * engine)
+{
+ if (ctx) {
+ PKCS11_CTX_free(ctx);
+ }
+ if (pin != NULL) {
+ OPENSSL_cleanse(pin, strlen(pin));
+ free(pin);
+ pin = NULL;
+ }
+ return 1;
+}
+
+int pkcs11_init(ENGINE * engine)
+{
+ if (verbose) {
+ fprintf(stderr, "initializing engine\n");
+ }
+ ctx = PKCS11_CTX_new();
+ 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) {
+ free(pin);
+ pin = NULL;
+ }
+ if (!default_module && module) {
+ free(module);
+ }
+ /* 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;
+ char c;
+
+ while (nybbles-- && *in && *in != ':') {
+ 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--;
+ c++;
+ }
+
+ *outlen = count;
+ return 1;
+}
+
+#define MAX_VALUE_LEN 200
+
+/* prototype for OpenSSL ENGINE_load_cert */
+/* used by load_cert_ctrl via ENGINE_ctrl for now */
+
+X509 *pkcs11_load_cert(ENGINE * e, const char *s_slot_cert_id)
+{
+ PKCS11_SLOT *slot_list, *slot;
+ PKCS11_TOKEN *tok;
+ PKCS11_CERT *certs, *selected_cert = NULL;
+ X509 *x509;
+ unsigned int count, n, m;
+ unsigned char cert_id[MAX_VALUE_LEN / 2];
+ char *s_cert_id = NULL, buf[MAX_VALUE_LEN];
+ size_t cert_id_len = sizeof(cert_id);
+ int slot_nr = -1;
+ char flags[64];
+
+ /* Parse s_slot_cert_id: [slot_<slotNr>][-][id_<certID>] or NULL,
+ with slotNr in decimal (0 = first slot, ...), and certID in hex.
+ E.g."slot_1" or "id_46" or "slot_1-id_46 */
+ while (s_slot_cert_id != NULL && *s_slot_cert_id != '\0') {
+ char *p_sep1, *p_sep2;
+ char val[MAX_VALUE_LEN];
+ int val_len;;
+
+ p_sep1 = strchr(s_slot_cert_id, '_');
+ if (p_sep1 == NULL) {
+ fprintf(stderr,"No \'_\' found in \"-cert\" option \"%s\"\n", s_slot_cert_id);
+ fprintf(stderr,"Format: [slot_<slotNr>][-][id_<certID>]\n");
+ fprintf(stderr," with slotNr = 0, 1, ... and certID = a hex string\n");
+ return NULL;
+ }
+
+ p_sep2 = strchr(p_sep1, '-');
+ if (p_sep2 == NULL)
+ p_sep2 = p_sep1 + strlen(p_sep1);
+
+ /* val = the string between the _ and the - (or '\0') */
+ val_len = p_sep2 - p_sep1 - 1;
+ if (val_len >= MAX_VALUE_LEN || val_len == 0)
+ fail("Too long or empty value after the \'-\' sign\n");
+ memcpy(val, p_sep1 + 1, val_len);
+ val[val_len] = '\0';
+ if (strncasecmp(s_slot_cert_id, "slot", p_sep1 - s_slot_cert_id) == 0) {
+ if (val_len >= 3) {
+ fprintf(stderr,"Slot number \"%s\" should be a small integer\n", val);
+ return NULL;
+ }
+ slot_nr = atoi(val);
+ if (slot_nr == 0 && val[0] != '0') {
+ fprintf(stderr,"Slot number \"%s\" should be an integer\n", val);
+ return NULL;
+ }
+ } else if (strncasecmp(s_slot_cert_id, "id", p_sep1 - s_slot_cert_id)
+ == 0) {
+ if (!hex_to_bin(val, cert_id, &cert_id_len)) {
+ fprintf(stderr,"cert id \"%s\" should be a hex string\n", val);
+ return NULL;
+ }
+ strcpy(buf, val);
+ s_cert_id = buf;
+ } else {
+ memcpy(val, s_slot_cert_id, p_sep1 - s_slot_cert_id);
+ val[p_sep1 - s_slot_cert_id] = '\0';
+ fprintf(stderr,"Now allowed in -cert: \"%s\"\n", val);
+ return NULL;
+ }
+ s_slot_cert_id = (*p_sep2 == '\0' ? p_sep2 : p_sep2 + 1);
+ }
+
+ if (PKCS11_enumerate_slots(ctx, &slot_list, &count) < 0)
+ fail("failed to enumerate slots\n");
+
+ if(verbose) {
+ fprintf(stderr,"Found %u slot%s\n", count, (count <= 1) ? "" : "s");
+ }
+ for (n = 0; n < 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(verbose) {
+ fprintf(stderr,"[%u] %-25.25s %-16s", n, 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)))
+ fail("didn't find any tokens\n");
+ } else if (slot_nr >= 0 && slot_nr < count)
+ slot = slot_list + slot_nr;
+ else {
+ fprintf(stderr,"Invalid slot number: %d\n", slot_nr);
+ return NULL;
+ }
+ tok = slot->token;
+
+ if (tok == NULL) {
+ fprintf(stderr,"Found empty token; \n");
+ 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, &count)) {
+ fail("unable to enumerate certificates\n");
+
+ return NULL;
+ }
+
+ if(verbose) {
+ fprintf(stderr,"Found %u cert%s:\n", count, (count <= 1) ? "" : "s");
+ }
+ for (n = 0; n < 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) {
+ if(verbose) {
+ fprintf(stderr," ID = %s\n", s_cert_id);
+ }
+ selected_cert = k;
+ }
+ }
+
+ if (selected_cert == NULL) {
+ if (s_cert_id != NULL) {
+ fprintf(stderr,"No cert with ID \"%s\" found.\n", s_cert_id);
+ return NULL;
+ } else /* Take the first cert that was found */
+ selected_cert = &certs[0];
+ }
+
+ x509 = X509_dup(selected_cert->x509);
+
+ 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;
+}
+
+
+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_TOKEN *tok;
+ PKCS11_KEY *keys, *selected_key = NULL;
+ PKCS11_CERT *certs;
+ EVP_PKEY *pk;
+ unsigned int count, n, m;
+ unsigned char key_id[MAX_VALUE_LEN / 2];
+ char *s_key_id = NULL, buf[MAX_VALUE_LEN];
+ size_t key_id_len = sizeof(key_id);
+ int slot_nr = -1;
+ char flags[64];
+
+ /* Parse s_slot_key_id: [slot_<slotNr>][-][id_<keyID>] or NULL,
+ with slotNr in decimal (0 = first slot, ...), and keyID in hex.
+ E.g. "slot_1" or "id_46" or "slot_1-id_46 */
+ while (s_slot_key_id != NULL && *s_slot_key_id != '\0') {
+ char *p_sep1, *p_sep2;
+ char val[MAX_VALUE_LEN];
+ int val_len;;
+
+ p_sep1 = strchr(s_slot_key_id, '_');
+ if (p_sep1 == NULL) {
+ fprintf(stderr,"No \'_\' found in \"-key\" option \"%s\"\n", s_slot_key_id);
+ fprintf(stderr,"Format: [slot_<slotNr>][-][id_<keyID>]\n");
+ fprintf(stderr," with slotNr = 0, 1, ... and keyID = a hex string\n");
+ return NULL;
+ }
+
+ p_sep2 = strchr(p_sep1, '-');
+ if (p_sep2 == NULL)
+ p_sep2 = p_sep1 + strlen(p_sep1);
+
+ /* val = the string between the _ and the - (or '\0') */
+ val_len = p_sep2 - p_sep1 - 1;
+ if (val_len >= MAX_VALUE_LEN || val_len == 0)
+ fail("Too long or empty value after the \'-\' sign\n");
+ memcpy(val, p_sep1 + 1, val_len);
+ val[val_len] = '\0';
+
+ if (strncasecmp(s_slot_key_id, "slot", p_sep1 - s_slot_key_id) == 0) {
+ if (val_len >= 3) {
+ fprintf(stderr,"Slot number \"%s\" should be a small integer\n", val);
+ return NULL;
+ }
+ slot_nr = atoi(val);
+ if (slot_nr == 0 && val[0] != '0') {
+ fprintf(stderr,"Slot number \"%s\" should be an integer\n", val);
+ return NULL;
+ }
+ } else if (strncasecmp(s_slot_key_id, "id", p_sep1 - s_slot_key_id)
+ == 0) {
+ if (!hex_to_bin(val, key_id, &key_id_len)) {
+ fprintf(stderr,"Key id \"%s\" should be a hex string\n", val);
+ return NULL;
+ }
+ strcpy(buf, val);
+ s_key_id = buf;
+ } else {
+ memcpy(val, s_slot_key_id, p_sep1 - s_slot_key_id);
+ val[p_sep1 - s_slot_key_id] = '\0';
+ fprintf(stderr,"Now allowed in -key: \"%s\"\n", val);
+ return NULL;
+ }
+ s_slot_key_id = (*p_sep2 == '\0' ? p_sep2 : p_sep2 + 1);
+ }
+
+ if (PKCS11_enumerate_slots(ctx, &slot_list, &count) < 0)
+ fail("failed to enumerate slots\n");
+
+ if(verbose) {
+ fprintf(stderr,"Found %u slot%s\n", count, (count <= 1) ? "" : "s");
+ }
+ for (n = 0; n < 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(verbose) {
+ fprintf(stderr,"[%u] %-25.25s %-16s", n, 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)))
+ fail("didn't find any tokens\n");
+ } else if (slot_nr >= 0 && slot_nr < count)
+ slot = slot_list + slot_nr;
+ else {
+ fprintf(stderr,"Invalid slot number: %d\n", slot_nr);
+ return NULL;
+ }
+ tok = slot->token;
+
+ if (tok == NULL) {
+ fprintf(stderr,"Found empty token; \n");
+ 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");
+ 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, &count))
+ fail("unable to enumerate certificates\n");
+
+ if(verbose) {
+ fprintf(stderr,"Found %u certificate%s:\n", count, (count <= 1) ? "" : "s");
+ for (n = 0; n < 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, via set_pin */
+ if (pin != NULL) {
+ OPENSSL_cleanse(pin, strlen(pin));
+ free (pin);
+ pin = NULL;
+ }
+ }
+ else if (pin == NULL) {
+ pin = (char *) calloc(MAX_PIN_LENGTH, sizeof(char));
+ if (pin == NULL) {
+ fail("Could not allocate memory for PIN");
+ }
+ get_pin(ui_method, callback_data, pin, MAX_PIN_LENGTH);
+ }
+
+ /* 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, strlen(pin));
+ free(pin);
+ pin = NULL;
+ }
+ 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, &count)) {
+ fail("unable to enumerate keys\n");
+ }
+ if (count == 0) {
+ fail("No keys found.\n");
+ }
+
+ if(verbose) {
+ fprintf(stderr,"Found %u key%s:\n", count, (count <= 1) ? "" : "s");
+ }
+ for (n = 0; n < 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_id_len != 0 && k->id_len == key_id_len &&
+ memcmp(k->id, key_id, key_id_len) == 0) {
+ if(verbose) {
+ fprintf(stderr," ID = %s\n", s_key_id);
+ }
+ selected_key = k;
+ }
+ }
+
+ if (selected_key == NULL) {
+ if (s_key_id != NULL) {
+ fprintf(stderr,"No key with ID \"%s\" found.\n", s_key_id);
+ return NULL;
+ } else /* Take the first key that was found */
+ selected_key = &keys[0];
+ }
+
+ 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);
+ }
+
+ 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.def b/src/engine_pkcs11.def
new file mode 100644
index 0000000..2a38483
--- /dev/null
+++ b/src/engine_pkcs11.def
@@ -0,0 +1,4 @@
+LIBRARY engine_pkcs11
+EXPORTS
+ v_check
+ bind_engine
diff --git a/src/engine_pkcs11.h b/src/engine_pkcs11.h
new file mode 100644
index 0000000..4b03998
--- /dev/null
+++ b/src/engine_pkcs11.h
@@ -0,0 +1,59 @@
+/*
+ * 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 load_cert_ctrl(ENGINE *e, void *p);
+
+int inc_verbose();
+
+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);
+
+/* defined in p11_rsa.c */
+RSA_METHOD *pkcs11_get_rsa_method(void);
+
+#endif
diff --git a/src/hw_opensc.c b/src/hw_opensc.c
new file mode 100644
index 0000000..a05d239
--- /dev/null
+++ b/src/hw_opensc.c
@@ -0,0 +1,215 @@
+/* crypto/engine/hw_opensc.c */
+/* Written by Geoff Thorpe (geoff at geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ * Copied/modified by Kevin Stefanik (kstef at mtppi.org) for the OpenSC
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ * Portions Copyright (c) 2003 Kevin Stefanik (kstef at 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 at 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 at cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <openssl/engine.h>
+#ifndef ENGINE_CMD_BASE
+#error did not get engine.h
+#endif
+#include <openssl/crypto.h>
+#include <openssl/dso.h>
+#include <opensc/opensc.h>
+#include <opensc/pkcs15.h>
+#include "engine_opensc.h"
+
+#define OPENSC_ENGINE_ID "opensc"
+#define OPENSC_ENGINE_NAME "opensc engine"
+
+#define CMD_SO_PATH ENGINE_CMD_BASE
+#define CMD_PIN (ENGINE_CMD_BASE+1)
+
+static int opensc_engine_destroy(ENGINE * e);
+static int opensc_engine_init(ENGINE * e);
+static int opensc_engine_finish(ENGINE * e);
+static int opensc_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 opensc_cmd_defns[] = {
+ {CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the 'opensc-engine' shared library",
+ ENGINE_CMD_FLAG_STRING},
+ {CMD_PIN,
+ "PIN",
+ "Specifies the pin code",
+ ENGINE_CMD_FLAG_STRING},
+ {0, NULL, NULL, 0}
+};
+
+static int opensc_engine_finish(ENGINE * e)
+{
+ return opensc_finish();
+}
+
+static int opensc_engine_init(ENGINE * e)
+{
+ return opensc_init();
+}
+
+/* Destructor */
+static int opensc_engine_destroy(ENGINE * e)
+{
+ return 1;
+}
+
+static int opensc_engine_ctrl(ENGINE * e, int cmd, long i, void *p, void (*f) ())
+{
+ switch (cmd) {
+ case CMD_PIN:
+ return set_pin((const char *) p);
+ default:
+ break;
+ }
+ return 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 opensc_engine_rsa_finish(RSA * rsa)
+{
+ opensc_rsa_finish(rsa);
+
+ if (orig_finish)
+ orig_finish(rsa);
+ return 1;
+}
+
+static RSA_METHOD *sc_get_rsa_method(void)
+{
+ static RSA_METHOD smart_rsa;
+ const RSA_METHOD *def = RSA_get_default_method();
+
+ /* use the OpenSSL version */
+ memcpy(&smart_rsa, def, sizeof(smart_rsa));
+
+ smart_rsa.name = "opensc";
+
+ /* overload */
+ smart_rsa.rsa_priv_enc = sc_private_encrypt;
+ smart_rsa.rsa_priv_dec = sc_private_decrypt;
+ smart_rsa.rsa_sign = sc_sign;
+
+ /* save original */
+ orig_finish = def->finish;
+ smart_rsa.finish = opensc_engine_rsa_finish;
+
+ /* set flags for sign version */
+ smart_rsa.flags |= RSA_FLAG_SIGN_VER;
+ return &smart_rsa;
+}
+
+/* This internal function is used by ENGINE_opensc() and possibly by the
+ * "dynamic" ENGINE support too */
+static int bind_helper(ENGINE * e)
+{
+ if (!ENGINE_set_id(e, OPENSC_ENGINE_ID) ||
+ !ENGINE_set_destroy_function(e, opensc_engine_destroy) ||
+ !ENGINE_set_init_function(e, opensc_engine_init) ||
+ !ENGINE_set_finish_function(e, opensc_engine_finish) ||
+ !ENGINE_set_ctrl_function(e, opensc_engine_ctrl) ||
+ !ENGINE_set_cmd_defns(e, opensc_cmd_defns) ||
+ !ENGINE_set_name(e, OPENSC_ENGINE_NAME) ||
+#ifndef OPENSSL_NO_RSA
+ !ENGINE_set_RSA(e, sc_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, opensc_load_public_key) ||
+ !ENGINE_set_load_privkey_function(e, opensc_load_private_key)) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+static int bind_fn(ENGINE * e, const char *id)
+{
+ if (id && (strcmp(id, OPENSC_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/hw_pkcs11.c b/src/hw_pkcs11.c
new file mode 100644
index 0000000..9da606c
--- /dev/null
+++ b/src/hw_pkcs11.c
@@ -0,0 +1,204 @@
+/* crypto/engine/hw_pkcs11.c */
+/* Written by Geoff Thorpe (geoff at geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ * Copied/modified by Kevin Stefanik (kstef at mtppi.org) for the OpenSC
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ * Portions Copyright (c) 2003 Kevin Stefanik (kstef at 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 at 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 at cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include <libp11.h>
+#include <stdio.h>
+#include <string.h>
+#include <openssl/engine.h>
+#ifndef ENGINE_CMD_BASE
+#error did not get engine.h
+#endif
+#include <openssl/crypto.h>
+#include <openssl/dso.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)
+
+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},
+ {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);
+ default:
+ break;
+ }
+ return 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;
+
+}
+
+/* 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);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-opensc/engine-pkcs11.git
More information about the pkg-opensc-commit
mailing list