- (djm) [INSTALL Makefile.in README.smartcard configure.ac scard-opensc.c]
[scard.c scard.h pkcs11.h scard/Makefile.in scard/Ssh.bin.uu scard/Ssh.java] Remove obsolete smartcard support
This commit is contained in:
parent
d400da5ba8
commit
d8f6002272
|
@ -37,6 +37,9 @@
|
||||||
- jmc@cvs.openbsd.org 2010/02/11 13:23:29
|
- jmc@cvs.openbsd.org 2010/02/11 13:23:29
|
||||||
[ssh.1]
|
[ssh.1]
|
||||||
libarary -> library;
|
libarary -> library;
|
||||||
|
- (djm) [INSTALL Makefile.in README.smartcard configure.ac scard-opensc.c]
|
||||||
|
[scard.c scard.h pkcs11.h scard/Makefile.in scard/Ssh.bin.uu scard/Ssh.java]
|
||||||
|
Remove obsolete smartcard support
|
||||||
|
|
||||||
20100210
|
20100210
|
||||||
- (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for
|
- (djm) add -lselinux to LIBS before calling AC_CHECK_FUNCS for
|
||||||
|
|
6
INSTALL
6
INSTALL
|
@ -208,10 +208,6 @@ are installed.
|
||||||
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
|
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
|
||||||
real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
|
real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
|
||||||
|
|
||||||
--with-opensc=DIR
|
|
||||||
--with-sectok=DIR allows for OpenSC or sectok smartcard libraries to
|
|
||||||
be used with OpenSSH. See 'README.smartcard' for more details.
|
|
||||||
|
|
||||||
If you need to pass special options to the compiler or linker, you
|
If you need to pass special options to the compiler or linker, you
|
||||||
can specify these as environment variables before running ./configure.
|
can specify these as environment variables before running ./configure.
|
||||||
For example:
|
For example:
|
||||||
|
@ -266,4 +262,4 @@ Please refer to the "reporting bugs" section of the webpage at
|
||||||
http://www.openssh.com/
|
http://www.openssh.com/
|
||||||
|
|
||||||
|
|
||||||
$Id: INSTALL,v 1.84 2007/08/17 12:52:05 dtucker Exp $
|
$Id: INSTALL,v 1.85 2010/02/11 22:34:22 djm Exp $
|
||||||
|
|
13
Makefile.in
13
Makefile.in
|
@ -1,4 +1,4 @@
|
||||||
# $Id: Makefile.in,v 1.304 2010/02/11 22:21:02 djm Exp $
|
# $Id: Makefile.in,v 1.305 2010/02/11 22:34:22 djm Exp $
|
||||||
|
|
||||||
# uncomment if you run a non bourne compatable shell. Ie. csh
|
# uncomment if you run a non bourne compatable shell. Ie. csh
|
||||||
#SHELL = @SH@
|
#SHELL = @SH@
|
||||||
|
@ -72,8 +72,8 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
|
||||||
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
|
readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
|
||||||
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
|
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
|
||||||
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
|
monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
|
||||||
kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
|
kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \
|
||||||
entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o \
|
entropy.o gss-genr.o umac.o jpake.o schnorr.o \
|
||||||
ssh-pkcs11.o
|
ssh-pkcs11.o
|
||||||
|
|
||||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||||
|
@ -215,7 +215,6 @@ distclean: regressclean
|
||||||
rm -f survey.sh openbsd-compat/regress/Makefile *~
|
rm -f survey.sh openbsd-compat/regress/Makefile *~
|
||||||
rm -rf autom4te.cache
|
rm -rf autom4te.cache
|
||||||
(cd openbsd-compat && $(MAKE) distclean)
|
(cd openbsd-compat && $(MAKE) distclean)
|
||||||
(cd scard && $(MAKE) distclean)
|
|
||||||
if test -d pkg ; then \
|
if test -d pkg ; then \
|
||||||
rm -fr pkg ; \
|
rm -fr pkg ; \
|
||||||
fi
|
fi
|
||||||
|
@ -238,7 +237,6 @@ catman-do:
|
||||||
distprep: catman-do
|
distprep: catman-do
|
||||||
$(AUTORECONF)
|
$(AUTORECONF)
|
||||||
-rm -rf autom4te.cache
|
-rm -rf autom4te.cache
|
||||||
(cd scard && $(MAKE) -f Makefile.in distprep)
|
|
||||||
|
|
||||||
install: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
|
install: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
|
||||||
install-nokeys: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf
|
install-nokeys: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf
|
||||||
|
@ -247,10 +245,7 @@ install-nosysconf: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) insta
|
||||||
check-config:
|
check-config:
|
||||||
-$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
|
-$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
|
||||||
|
|
||||||
scard-install:
|
install-files:
|
||||||
(cd scard && env DESTDIR=$(DESTDIR) $(MAKE) DESTDIR=$(DESTDIR) install)
|
|
||||||
|
|
||||||
install-files: scard-install
|
|
||||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
|
$(srcdir)/mkinstalldirs $(DESTDIR)$(bindir)
|
||||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
|
$(srcdir)/mkinstalldirs $(DESTDIR)$(sbindir)
|
||||||
$(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
|
$(srcdir)/mkinstalldirs $(DESTDIR)$(mandir)
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
How to use smartcards with OpenSSH?
|
|
||||||
|
|
||||||
OpenSSH contains experimental support for authentication using
|
|
||||||
Cyberflex smartcards and TODOS card readers, in addition to the cards
|
|
||||||
with PKCS#15 structure supported by OpenSC. To enable this you
|
|
||||||
need to:
|
|
||||||
|
|
||||||
Using libsectok:
|
|
||||||
|
|
||||||
(1) enable sectok support in OpenSSH:
|
|
||||||
|
|
||||||
$ ./configure --with-sectok
|
|
||||||
|
|
||||||
(2) If you have used a previous version of ssh with your card, you
|
|
||||||
must remove the old applet and keys.
|
|
||||||
|
|
||||||
$ sectok
|
|
||||||
sectok> login -d
|
|
||||||
sectok> junload Ssh.bin
|
|
||||||
sectok> delete 0012
|
|
||||||
sectok> delete sh
|
|
||||||
sectok> quit
|
|
||||||
|
|
||||||
(3) load the Java Cardlet to the Cyberflex card and set card passphrase:
|
|
||||||
|
|
||||||
$ sectok
|
|
||||||
sectok> login -d
|
|
||||||
sectok> jload /usr/libdata/ssh/Ssh.bin
|
|
||||||
sectok> setpass
|
|
||||||
Enter new AUT0 passphrase:
|
|
||||||
Re-enter passphrase:
|
|
||||||
sectok> quit
|
|
||||||
|
|
||||||
Do not forget the passphrase. There is no way to
|
|
||||||
recover if you do.
|
|
||||||
|
|
||||||
IMPORTANT WARNING: If you attempt to login with the
|
|
||||||
wrong passphrase three times in a row, you will
|
|
||||||
destroy your card.
|
|
||||||
|
|
||||||
(4) load a RSA key to the card:
|
|
||||||
|
|
||||||
$ ssh-keygen -f /path/to/rsakey -U 1
|
|
||||||
(where 1 is the reader number, you can also try 0)
|
|
||||||
|
|
||||||
In spite of the name, this does not generate a key.
|
|
||||||
It just loads an already existing key on to the card.
|
|
||||||
|
|
||||||
(5) Optional: If you don't want to use a card passphrase, change the
|
|
||||||
acl on the private key file:
|
|
||||||
|
|
||||||
$ sectok
|
|
||||||
sectok> login -d
|
|
||||||
sectok> acl 0012 world: w
|
|
||||||
world: w
|
|
||||||
AUT0: w inval
|
|
||||||
sectok> quit
|
|
||||||
|
|
||||||
If you do this, anyone who has access to your card
|
|
||||||
can assume your identity. This is not recommended.
|
|
||||||
|
|
||||||
|
|
||||||
Using OpenSC:
|
|
||||||
|
|
||||||
(1) install OpenSC:
|
|
||||||
|
|
||||||
Sources and instructions are available from
|
|
||||||
http://www.opensc.org/
|
|
||||||
|
|
||||||
(2) enable OpenSC support in OpenSSH:
|
|
||||||
|
|
||||||
$ ./configure --with-opensc[=/path/to/opensc] [options]
|
|
||||||
|
|
||||||
(3) load a RSA key to the card:
|
|
||||||
|
|
||||||
Not supported yet.
|
|
||||||
|
|
||||||
|
|
||||||
Common operations:
|
|
||||||
|
|
||||||
(1) tell the ssh client to use the card reader:
|
|
||||||
|
|
||||||
$ ssh -I 1 otherhost
|
|
||||||
|
|
||||||
(2) or tell the agent (don't forget to restart) to use the smartcard:
|
|
||||||
|
|
||||||
$ ssh-add -s 1
|
|
||||||
|
|
||||||
|
|
||||||
-markus,
|
|
||||||
Tue Jul 17 23:54:51 CEST 2001
|
|
||||||
|
|
||||||
$OpenBSD: README.smartcard,v 1.9 2003/11/21 11:57:02 djm Exp $
|
|
73
configure.ac
73
configure.ac
|
@ -1,4 +1,4 @@
|
||||||
# $Id: configure.ac,v 1.441 2010/02/11 22:21:02 djm Exp $
|
# $Id: configure.ac,v 1.442 2010/02/11 22:34:22 djm Exp $
|
||||||
#
|
#
|
||||||
# Copyright (c) 1999-2004 Damien Miller
|
# Copyright (c) 1999-2004 Damien Miller
|
||||||
#
|
#
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
|
AC_INIT(OpenSSH, Portable, openssh-unix-dev@mindrot.org)
|
||||||
AC_REVISION($Revision: 1.441 $)
|
AC_REVISION($Revision: 1.442 $)
|
||||||
AC_CONFIG_SRCDIR([ssh.c])
|
AC_CONFIG_SRCDIR([ssh.c])
|
||||||
|
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADER(config.h)
|
||||||
|
@ -3263,73 +3263,6 @@ if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
|
||||||
AC_DEFINE(HAVE_SYS_NERR, 1, [Define if your system defines sys_nerr])
|
AC_DEFINE(HAVE_SYS_NERR, 1, [Define if your system defines sys_nerr])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SCARD_MSG="no"
|
|
||||||
# Check whether user wants sectok support
|
|
||||||
AC_ARG_WITH(sectok,
|
|
||||||
[ --with-sectok Enable smartcard support using libsectok],
|
|
||||||
[
|
|
||||||
if test "x$withval" != "xno" ; then
|
|
||||||
if test "x$withval" != "xyes" ; then
|
|
||||||
CPPFLAGS="$CPPFLAGS -I${withval}"
|
|
||||||
LDFLAGS="$LDFLAGS -L${withval}"
|
|
||||||
if test ! -z "$need_dash_r" ; then
|
|
||||||
LDFLAGS="$LDFLAGS -R${withval}"
|
|
||||||
fi
|
|
||||||
if test ! -z "$blibpath" ; then
|
|
||||||
blibpath="$blibpath:${withval}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_CHECK_HEADERS(sectok.h)
|
|
||||||
if test "$ac_cv_header_sectok_h" != yes; then
|
|
||||||
AC_MSG_ERROR(Can't find sectok.h)
|
|
||||||
fi
|
|
||||||
AC_CHECK_LIB(sectok, sectok_open)
|
|
||||||
if test "$ac_cv_lib_sectok_sectok_open" != yes; then
|
|
||||||
AC_MSG_ERROR(Can't find libsectok)
|
|
||||||
fi
|
|
||||||
AC_DEFINE(SMARTCARD, 1,
|
|
||||||
[Define if you want smartcard support])
|
|
||||||
AC_DEFINE(USE_SECTOK, 1,
|
|
||||||
[Define if you want smartcard support
|
|
||||||
using sectok])
|
|
||||||
SCARD_MSG="yes, using sectok"
|
|
||||||
fi
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check whether user wants OpenSC support
|
|
||||||
OPENSC_CONFIG="no"
|
|
||||||
AC_ARG_WITH(opensc,
|
|
||||||
[ --with-opensc[[=PFX]] Enable smartcard support using OpenSC (optionally in PATH)],
|
|
||||||
[
|
|
||||||
if test "x$withval" != "xno" ; then
|
|
||||||
AC_PATH_PROG(PKGCONFIG, pkg-config, no)
|
|
||||||
AC_MSG_CHECKING(how to get opensc config)
|
|
||||||
if test "x$withval" != "xyes" -a "x$PKGCONFIG" = "xno"; then
|
|
||||||
OPENSC_CONFIG="$withval/bin/opensc-config"
|
|
||||||
elif test -f "$withval/src/libopensc/libopensc.pc"; then
|
|
||||||
OPENSC_CONFIG="$PKGCONFIG $withval/src/libopensc/libopensc.pc"
|
|
||||||
elif test "x$PKGCONFIG" != "xno"; then
|
|
||||||
OPENSC_CONFIG="$PKGCONFIG libopensc"
|
|
||||||
else
|
|
||||||
AC_PATH_PROG(OPENSC_CONFIG, opensc-config, no)
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT($OPENSC_CONFIG)
|
|
||||||
if test "$OPENSC_CONFIG" != "no"; then
|
|
||||||
LIBOPENSC_CFLAGS=`$OPENSC_CONFIG --cflags`
|
|
||||||
LIBOPENSC_LIBS=`$OPENSC_CONFIG --libs`
|
|
||||||
CPPFLAGS="$CPPFLAGS $LIBOPENSC_CFLAGS"
|
|
||||||
LIBS="$LIBS $LIBOPENSC_LIBS"
|
|
||||||
AC_DEFINE(SMARTCARD)
|
|
||||||
AC_DEFINE(USE_OPENSC, 1,
|
|
||||||
[Define if you want smartcard support
|
|
||||||
using OpenSC])
|
|
||||||
SCARD_MSG="yes, using OpenSC"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Check libraries needed by DNS fingerprint support
|
# Check libraries needed by DNS fingerprint support
|
||||||
AC_SEARCH_LIBS(getrrsetbyname, resolv,
|
AC_SEARCH_LIBS(getrrsetbyname, resolv,
|
||||||
[AC_DEFINE(HAVE_GETRRSETBYNAME, 1,
|
[AC_DEFINE(HAVE_GETRRSETBYNAME, 1,
|
||||||
|
@ -4204,7 +4137,7 @@ fi
|
||||||
AC_EXEEXT
|
AC_EXEEXT
|
||||||
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
|
||||||
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
|
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
|
||||||
scard/Makefile ssh_prng_cmds survey.sh])
|
ssh_prng_cmds survey.sh])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
# Print summary of options
|
# Print summary of options
|
||||||
|
|
532
scard-opensc.c
532
scard-opensc.c
|
@ -1,532 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
|
|
||||||
* Copyright (c) 2001 Markus Friedl.
|
|
||||||
*
|
|
||||||
* 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 "includes.h"
|
|
||||||
#if defined(SMARTCARD) && defined(USE_OPENSC)
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/x509.h>
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <opensc/opensc.h>
|
|
||||||
#include <opensc/pkcs15.h>
|
|
||||||
|
|
||||||
#include "key.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "scard.h"
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
|
|
||||||
#define USE_ENGINE
|
|
||||||
#define RSA_get_default_method RSA_get_default_openssl_method
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_ENGINE
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#define sc_get_rsa sc_get_engine
|
|
||||||
#else
|
|
||||||
#define sc_get_rsa sc_get_rsa_method
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int sc_reader_id;
|
|
||||||
static sc_context_t *ctx = NULL;
|
|
||||||
static sc_card_t *card = NULL;
|
|
||||||
static sc_pkcs15_card_t *p15card = NULL;
|
|
||||||
|
|
||||||
static char *sc_pin = NULL;
|
|
||||||
|
|
||||||
struct sc_priv_data
|
|
||||||
{
|
|
||||||
struct sc_pkcs15_id cert_id;
|
|
||||||
int ref_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
sc_close(void)
|
|
||||||
{
|
|
||||||
if (p15card) {
|
|
||||||
sc_pkcs15_unbind(p15card);
|
|
||||||
p15card = NULL;
|
|
||||||
}
|
|
||||||
if (card) {
|
|
||||||
sc_disconnect_card(card, 0);
|
|
||||||
card = NULL;
|
|
||||||
}
|
|
||||||
if (ctx) {
|
|
||||||
sc_release_context(ctx);
|
|
||||||
ctx = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_init(void)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
r = sc_establish_context(&ctx, "openssh");
|
|
||||||
if (r)
|
|
||||||
goto err;
|
|
||||||
if (sc_reader_id >= ctx->reader_count) {
|
|
||||||
r = SC_ERROR_NO_READERS_FOUND;
|
|
||||||
error("Illegal reader number %d (max %d)", sc_reader_id,
|
|
||||||
ctx->reader_count -1);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card);
|
|
||||||
if (r)
|
|
||||||
goto err;
|
|
||||||
r = sc_pkcs15_bind(card, &p15card);
|
|
||||||
if (r)
|
|
||||||
goto err;
|
|
||||||
return 0;
|
|
||||||
err:
|
|
||||||
sc_close();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* private key operations */
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out,
|
|
||||||
unsigned int usage)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
struct sc_priv_data *priv;
|
|
||||||
struct sc_pkcs15_object *key_obj;
|
|
||||||
struct sc_pkcs15_prkey_info *key;
|
|
||||||
struct sc_pkcs15_object *pin_obj;
|
|
||||||
struct sc_pkcs15_pin_info *pin;
|
|
||||||
|
|
||||||
priv = (struct sc_priv_data *) RSA_get_app_data(rsa);
|
|
||||||
if (priv == NULL)
|
|
||||||
return -1;
|
|
||||||
if (p15card == NULL) {
|
|
||||||
sc_close();
|
|
||||||
r = sc_init();
|
|
||||||
if (r) {
|
|
||||||
error("SmartCard init failed: %s", sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->cert_id,
|
|
||||||
usage, &key_obj);
|
|
||||||
if (r) {
|
|
||||||
error("Unable to find private key from SmartCard: %s",
|
|
||||||
sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
key = key_obj->data;
|
|
||||||
r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id,
|
|
||||||
&pin_obj);
|
|
||||||
if (r == SC_ERROR_OBJECT_NOT_FOUND) {
|
|
||||||
/* no pin required */
|
|
||||||
r = sc_lock(card);
|
|
||||||
if (r) {
|
|
||||||
error("Unable to lock smartcard: %s", sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
*key_obj_out = key_obj;
|
|
||||||
return 0;
|
|
||||||
} else if (r) {
|
|
||||||
error("Unable to find PIN object from SmartCard: %s",
|
|
||||||
sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
pin = pin_obj->data;
|
|
||||||
r = sc_lock(card);
|
|
||||||
if (r) {
|
|
||||||
error("Unable to lock smartcard: %s", sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (sc_pin != NULL) {
|
|
||||||
r = sc_pkcs15_verify_pin(p15card, pin, sc_pin,
|
|
||||||
strlen(sc_pin));
|
|
||||||
if (r) {
|
|
||||||
sc_unlock(card);
|
|
||||||
error("PIN code verification failed: %s",
|
|
||||||
sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*key_obj_out = key_obj;
|
|
||||||
return 0;
|
|
||||||
err:
|
|
||||||
sc_close();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SC_USAGE_DECRYPT SC_PKCS15_PRKEY_USAGE_DECRYPT | \
|
|
||||||
SC_PKCS15_PRKEY_USAGE_UNWRAP
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
|
||||||
int padding)
|
|
||||||
{
|
|
||||||
struct sc_pkcs15_object *key_obj;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (padding != RSA_PKCS1_PADDING)
|
|
||||||
return -1;
|
|
||||||
r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_DECRYPT);
|
|
||||||
if (r)
|
|
||||||
return -1;
|
|
||||||
r = sc_pkcs15_decipher(p15card, key_obj, SC_ALGORITHM_RSA_PAD_PKCS1,
|
|
||||||
from, flen, to, flen);
|
|
||||||
sc_unlock(card);
|
|
||||||
if (r < 0) {
|
|
||||||
error("sc_pkcs15_decipher() failed: %s", sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
err:
|
|
||||||
sc_close();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SC_USAGE_SIGN SC_PKCS15_PRKEY_USAGE_SIGN | \
|
|
||||||
SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_sign(int type, u_char *m, unsigned int m_len,
|
|
||||||
unsigned char *sigret, unsigned int *siglen, RSA *rsa)
|
|
||||||
{
|
|
||||||
struct sc_pkcs15_object *key_obj;
|
|
||||||
int r;
|
|
||||||
unsigned long flags = 0;
|
|
||||||
|
|
||||||
/* XXX: sc_prkey_op_init will search for a pkcs15 private
|
|
||||||
* key object with the sign or signrecover usage flag set.
|
|
||||||
* If the signing key has only the non-repudiation flag set
|
|
||||||
* the key will be rejected as using a non-repudiation key
|
|
||||||
* for authentication is not recommended. Note: This does not
|
|
||||||
* prevent the use of a non-repudiation key for authentication
|
|
||||||
* if the sign or signrecover flag is set as well.
|
|
||||||
*/
|
|
||||||
r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_SIGN);
|
|
||||||
if (r)
|
|
||||||
return -1;
|
|
||||||
/* FIXME: length of sigret correct? */
|
|
||||||
/* FIXME: check 'type' and modify flags accordingly */
|
|
||||||
flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1;
|
|
||||||
r = sc_pkcs15_compute_signature(p15card, key_obj, flags,
|
|
||||||
m, m_len, sigret, RSA_size(rsa));
|
|
||||||
sc_unlock(card);
|
|
||||||
if (r < 0) {
|
|
||||||
error("sc_pkcs15_compute_signature() failed: %s",
|
|
||||||
sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
*siglen = r;
|
|
||||||
return 1;
|
|
||||||
err:
|
|
||||||
sc_close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
|
||||||
int padding)
|
|
||||||
{
|
|
||||||
error("Private key encryption not supported");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called on free */
|
|
||||||
|
|
||||||
static int (*orig_finish)(RSA *rsa) = NULL;
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_finish(RSA *rsa)
|
|
||||||
{
|
|
||||||
struct sc_priv_data *priv;
|
|
||||||
|
|
||||||
priv = RSA_get_app_data(rsa);
|
|
||||||
priv->ref_count--;
|
|
||||||
if (priv->ref_count == 0) {
|
|
||||||
free(priv);
|
|
||||||
sc_close();
|
|
||||||
}
|
|
||||||
if (orig_finish)
|
|
||||||
orig_finish(rsa);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* engine for overloading private key operations */
|
|
||||||
|
|
||||||
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 = sc_finish;
|
|
||||||
|
|
||||||
return &smart_rsa;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_ENGINE
|
|
||||||
static ENGINE *
|
|
||||||
sc_get_engine(void)
|
|
||||||
{
|
|
||||||
static ENGINE *smart_engine = NULL;
|
|
||||||
|
|
||||||
if ((smart_engine = ENGINE_new()) == NULL)
|
|
||||||
fatal("ENGINE_new failed");
|
|
||||||
|
|
||||||
ENGINE_set_id(smart_engine, "opensc");
|
|
||||||
ENGINE_set_name(smart_engine, "OpenSC");
|
|
||||||
|
|
||||||
ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
|
|
||||||
ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
|
|
||||||
ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
|
|
||||||
ENGINE_set_RAND(smart_engine, RAND_SSLeay());
|
|
||||||
ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
|
|
||||||
|
|
||||||
return smart_engine;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
convert_rsa_to_rsa1(Key * in, Key * out)
|
|
||||||
{
|
|
||||||
struct sc_priv_data *priv;
|
|
||||||
|
|
||||||
out->rsa->flags = in->rsa->flags;
|
|
||||||
out->flags = in->flags;
|
|
||||||
RSA_set_method(out->rsa, RSA_get_method(in->rsa));
|
|
||||||
BN_copy(out->rsa->n, in->rsa->n);
|
|
||||||
BN_copy(out->rsa->e, in->rsa->e);
|
|
||||||
priv = RSA_get_app_data(in->rsa);
|
|
||||||
priv->ref_count++;
|
|
||||||
RSA_set_app_data(out->rsa, priv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
sc_pkcs15_cert_t *cert = NULL;
|
|
||||||
struct sc_priv_data *priv = NULL;
|
|
||||||
sc_pkcs15_cert_info_t *cinfo = cert_obj->data;
|
|
||||||
|
|
||||||
X509 *x509 = NULL;
|
|
||||||
EVP_PKEY *pubkey = NULL;
|
|
||||||
u8 *p;
|
|
||||||
char *tmp;
|
|
||||||
|
|
||||||
debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]);
|
|
||||||
r = sc_pkcs15_read_certificate(p15card, cinfo, &cert);
|
|
||||||
if (r) {
|
|
||||||
logit("Certificate read failed: %s", sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
x509 = X509_new();
|
|
||||||
if (x509 == NULL) {
|
|
||||||
r = -1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
p = cert->data;
|
|
||||||
if (!d2i_X509(&x509, &p, cert->data_len)) {
|
|
||||||
logit("Unable to parse X.509 certificate");
|
|
||||||
r = -1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
sc_pkcs15_free_certificate(cert);
|
|
||||||
cert = NULL;
|
|
||||||
pubkey = X509_get_pubkey(x509);
|
|
||||||
X509_free(x509);
|
|
||||||
x509 = NULL;
|
|
||||||
if (pubkey->type != EVP_PKEY_RSA) {
|
|
||||||
logit("Public key is of unknown type");
|
|
||||||
r = -1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
k->rsa = EVP_PKEY_get1_RSA(pubkey);
|
|
||||||
EVP_PKEY_free(pubkey);
|
|
||||||
|
|
||||||
k->rsa->flags |= RSA_FLAG_SIGN_VER;
|
|
||||||
RSA_set_method(k->rsa, sc_get_rsa_method());
|
|
||||||
priv = xmalloc(sizeof(struct sc_priv_data));
|
|
||||||
priv->cert_id = cinfo->id;
|
|
||||||
priv->ref_count = 1;
|
|
||||||
RSA_set_app_data(k->rsa, priv);
|
|
||||||
|
|
||||||
k->flags = KEY_FLAG_EXT;
|
|
||||||
tmp = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
|
|
||||||
debug("fingerprint %d %s", key_size(k), tmp);
|
|
||||||
xfree(tmp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
err:
|
|
||||||
if (cert)
|
|
||||||
sc_pkcs15_free_certificate(cert);
|
|
||||||
if (pubkey)
|
|
||||||
EVP_PKEY_free(pubkey);
|
|
||||||
if (x509)
|
|
||||||
X509_free(x509);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
Key **
|
|
||||||
sc_get_keys(const char *id, const char *pin)
|
|
||||||
{
|
|
||||||
Key *k, **keys;
|
|
||||||
int i, r, real_count = 0, key_count;
|
|
||||||
sc_pkcs15_id_t cert_id;
|
|
||||||
sc_pkcs15_object_t *certs[32];
|
|
||||||
char *buf = xstrdup(id), *p;
|
|
||||||
|
|
||||||
debug("sc_get_keys called: id = %s", id);
|
|
||||||
|
|
||||||
if (sc_pin != NULL)
|
|
||||||
xfree(sc_pin);
|
|
||||||
sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
|
|
||||||
|
|
||||||
cert_id.len = 0;
|
|
||||||
if ((p = strchr(buf, ':')) != NULL) {
|
|
||||||
*p = 0;
|
|
||||||
p++;
|
|
||||||
sc_pkcs15_hex_string_to_id(p, &cert_id);
|
|
||||||
}
|
|
||||||
r = sscanf(buf, "%d", &sc_reader_id);
|
|
||||||
xfree(buf);
|
|
||||||
if (r != 1)
|
|
||||||
goto err;
|
|
||||||
if (p15card == NULL) {
|
|
||||||
sc_close();
|
|
||||||
r = sc_init();
|
|
||||||
if (r) {
|
|
||||||
error("Smartcard init failed: %s", sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cert_id.len) {
|
|
||||||
r = sc_pkcs15_find_cert_by_id(p15card, &cert_id, &certs[0]);
|
|
||||||
if (r < 0)
|
|
||||||
goto err;
|
|
||||||
key_count = 1;
|
|
||||||
} else {
|
|
||||||
r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509,
|
|
||||||
certs, 32);
|
|
||||||
if (r == 0) {
|
|
||||||
logit("No certificates found on smartcard");
|
|
||||||
r = -1;
|
|
||||||
goto err;
|
|
||||||
} else if (r < 0) {
|
|
||||||
error("Certificate enumeration failed: %s",
|
|
||||||
sc_strerror(r));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
key_count = r;
|
|
||||||
}
|
|
||||||
if (key_count > 1024)
|
|
||||||
fatal("Too many keys (%u), expected <= 1024", key_count);
|
|
||||||
keys = xcalloc(key_count * 2 + 1, sizeof(Key *));
|
|
||||||
for (i = 0; i < key_count; i++) {
|
|
||||||
sc_pkcs15_object_t *tmp_obj = NULL;
|
|
||||||
cert_id = ((sc_pkcs15_cert_info_t *)(certs[i]->data))->id;
|
|
||||||
if (sc_pkcs15_find_prkey_by_id(p15card, &cert_id, &tmp_obj))
|
|
||||||
/* skip the public key (certificate) if no
|
|
||||||
* corresponding private key is present */
|
|
||||||
continue;
|
|
||||||
k = key_new(KEY_RSA);
|
|
||||||
if (k == NULL)
|
|
||||||
break;
|
|
||||||
r = sc_read_pubkey(k, certs[i]);
|
|
||||||
if (r) {
|
|
||||||
error("sc_read_pubkey failed: %s", sc_strerror(r));
|
|
||||||
key_free(k);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
keys[real_count] = k;
|
|
||||||
real_count++;
|
|
||||||
k = key_new(KEY_RSA1);
|
|
||||||
if (k == NULL)
|
|
||||||
break;
|
|
||||||
convert_rsa_to_rsa1(keys[real_count-1], k);
|
|
||||||
keys[real_count] = k;
|
|
||||||
real_count++;
|
|
||||||
}
|
|
||||||
keys[real_count] = NULL;
|
|
||||||
|
|
||||||
return keys;
|
|
||||||
err:
|
|
||||||
sc_close();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
sc_put_key(Key *prv, const char *id)
|
|
||||||
{
|
|
||||||
error("key uploading not yet supported");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
sc_get_key_label(Key *key)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
const struct sc_priv_data *priv;
|
|
||||||
struct sc_pkcs15_object *key_obj;
|
|
||||||
|
|
||||||
priv = (const struct sc_priv_data *) RSA_get_app_data(key->rsa);
|
|
||||||
if (priv == NULL || p15card == NULL) {
|
|
||||||
logit("SmartCard key not loaded");
|
|
||||||
/* internal error => return default label */
|
|
||||||
return xstrdup("smartcard key");
|
|
||||||
}
|
|
||||||
r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj);
|
|
||||||
if (r) {
|
|
||||||
logit("Unable to find private key from SmartCard: %s",
|
|
||||||
sc_strerror(r));
|
|
||||||
return xstrdup("smartcard key");
|
|
||||||
}
|
|
||||||
if (key_obj == NULL || key_obj->label == NULL)
|
|
||||||
/* the optional PKCS#15 label does not exists
|
|
||||||
* => return the default label */
|
|
||||||
return xstrdup("smartcard key");
|
|
||||||
return xstrdup(key_obj->label);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* SMARTCARD */
|
|
571
scard.c
571
scard.c
|
@ -1,571 +0,0 @@
|
||||||
/* $OpenBSD: scard.c,v 1.36 2006/11/06 21:25:28 markus Exp $ */
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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 "includes.h"
|
|
||||||
#if defined(SMARTCARD) && defined(USE_SECTOK)
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <sectok.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "key.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "scard.h"
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x00907000L
|
|
||||||
#define USE_ENGINE
|
|
||||||
#define RSA_get_default_method RSA_get_default_openssl_method
|
|
||||||
#else
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_ENGINE
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#define sc_get_rsa sc_get_engine
|
|
||||||
#else
|
|
||||||
#define sc_get_rsa sc_get_rsa_method
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CLA_SSH 0x05
|
|
||||||
#define INS_DECRYPT 0x10
|
|
||||||
#define INS_GET_KEYLENGTH 0x20
|
|
||||||
#define INS_GET_PUBKEY 0x30
|
|
||||||
#define INS_GET_RESPONSE 0xc0
|
|
||||||
|
|
||||||
#define MAX_BUF_SIZE 256
|
|
||||||
|
|
||||||
u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
|
|
||||||
|
|
||||||
static int sc_fd = -1;
|
|
||||||
static char *sc_reader_id = NULL;
|
|
||||||
static char *sc_pin = NULL;
|
|
||||||
static int cla = 0x00; /* class */
|
|
||||||
|
|
||||||
static void sc_mk_digest(const char *pin, u_char *digest);
|
|
||||||
static int get_AUT0(u_char *aut0);
|
|
||||||
static int try_AUT0(void);
|
|
||||||
|
|
||||||
/* interface to libsectok */
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_open(void)
|
|
||||||
{
|
|
||||||
int sw;
|
|
||||||
|
|
||||||
if (sc_fd >= 0)
|
|
||||||
return sc_fd;
|
|
||||||
|
|
||||||
sc_fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw);
|
|
||||||
if (sc_fd < 0) {
|
|
||||||
error("sectok_open failed: %s", sectok_get_sw(sw));
|
|
||||||
return SCARD_ERROR_FAIL;
|
|
||||||
}
|
|
||||||
if (! sectok_cardpresent(sc_fd)) {
|
|
||||||
debug("smartcard in reader %s not present, skipping",
|
|
||||||
sc_reader_id);
|
|
||||||
sc_close();
|
|
||||||
return SCARD_ERROR_NOCARD;
|
|
||||||
}
|
|
||||||
if (sectok_reset(sc_fd, 0, NULL, &sw) <= 0) {
|
|
||||||
error("sectok_reset failed: %s", sectok_get_sw(sw));
|
|
||||||
sc_fd = -1;
|
|
||||||
return SCARD_ERROR_FAIL;
|
|
||||||
}
|
|
||||||
if ((cla = cyberflex_inq_class(sc_fd)) < 0)
|
|
||||||
cla = 0;
|
|
||||||
|
|
||||||
debug("sc_open ok %d", sc_fd);
|
|
||||||
return sc_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_enable_applet(void)
|
|
||||||
{
|
|
||||||
static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e};
|
|
||||||
int sw = 0;
|
|
||||||
|
|
||||||
/* select applet id */
|
|
||||||
sectok_apdu(sc_fd, cla, 0xa4, 0x04, 0, sizeof aid, aid, 0, NULL, &sw);
|
|
||||||
if (!sectok_swOK(sw)) {
|
|
||||||
error("sectok_apdu failed: %s", sectok_get_sw(sw));
|
|
||||||
sc_close();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_init(void)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
status = sc_open();
|
|
||||||
if (status == SCARD_ERROR_NOCARD) {
|
|
||||||
return SCARD_ERROR_NOCARD;
|
|
||||||
}
|
|
||||||
if (status < 0) {
|
|
||||||
error("sc_open failed");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
if (sc_enable_applet() < 0) {
|
|
||||||
error("sc_enable_applet failed");
|
|
||||||
return SCARD_ERROR_APPLET;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_read_pubkey(Key * k)
|
|
||||||
{
|
|
||||||
u_char buf[2], *n;
|
|
||||||
char *p;
|
|
||||||
int len, sw, status = -1;
|
|
||||||
|
|
||||||
len = sw = 0;
|
|
||||||
n = NULL;
|
|
||||||
|
|
||||||
if (sc_fd < 0) {
|
|
||||||
if (sc_init() < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get key size */
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL,
|
|
||||||
sizeof(buf), buf, &sw);
|
|
||||||
if (!sectok_swOK(sw)) {
|
|
||||||
error("could not obtain key length: %s", sectok_get_sw(sw));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
len = (buf[0] << 8) | buf[1];
|
|
||||||
len /= 8;
|
|
||||||
debug("INS_GET_KEYLENGTH: len %d sw %s", len, sectok_get_sw(sw));
|
|
||||||
|
|
||||||
n = xmalloc(len);
|
|
||||||
/* get n */
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
|
|
||||||
|
|
||||||
if (sw == 0x6982) {
|
|
||||||
if (try_AUT0() < 0)
|
|
||||||
goto err;
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
|
|
||||||
}
|
|
||||||
if (!sectok_swOK(sw)) {
|
|
||||||
error("could not obtain public key: %s", sectok_get_sw(sw));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("INS_GET_KEYLENGTH: sw %s", sectok_get_sw(sw));
|
|
||||||
|
|
||||||
if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
|
|
||||||
error("c_read_pubkey: BN_bin2bn failed");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* currently the java applet just stores 'n' */
|
|
||||||
if (!BN_set_word(k->rsa->e, 35)) {
|
|
||||||
error("c_read_pubkey: BN_set_word(e, 35) failed");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = 0;
|
|
||||||
p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
|
|
||||||
debug("fingerprint %u %s", key_size(k), p);
|
|
||||||
xfree(p);
|
|
||||||
|
|
||||||
err:
|
|
||||||
if (n != NULL)
|
|
||||||
xfree(n);
|
|
||||||
sc_close();
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* private key operations */
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
|
||||||
int padding)
|
|
||||||
{
|
|
||||||
u_char *padded = NULL;
|
|
||||||
int sw, len, olen, status = -1;
|
|
||||||
|
|
||||||
debug("sc_private_decrypt called");
|
|
||||||
|
|
||||||
olen = len = sw = 0;
|
|
||||||
if (sc_fd < 0) {
|
|
||||||
status = sc_init();
|
|
||||||
if (status < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (padding != RSA_PKCS1_PADDING)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
len = BN_num_bytes(rsa->n);
|
|
||||||
padded = xmalloc(len);
|
|
||||||
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
|
|
||||||
|
|
||||||
if (sw == 0x6982) {
|
|
||||||
if (try_AUT0() < 0)
|
|
||||||
goto err;
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw);
|
|
||||||
}
|
|
||||||
if (!sectok_swOK(sw)) {
|
|
||||||
error("sc_private_decrypt: INS_DECRYPT failed: %s",
|
|
||||||
sectok_get_sw(sw));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1,
|
|
||||||
len);
|
|
||||||
err:
|
|
||||||
if (padded)
|
|
||||||
xfree(padded);
|
|
||||||
sc_close();
|
|
||||||
return (olen >= 0 ? olen : status);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
|
|
||||||
int padding)
|
|
||||||
{
|
|
||||||
u_char *padded = NULL;
|
|
||||||
int sw, len, status = -1;
|
|
||||||
|
|
||||||
len = sw = 0;
|
|
||||||
if (sc_fd < 0) {
|
|
||||||
status = sc_init();
|
|
||||||
if (status < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (padding != RSA_PKCS1_PADDING)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
debug("sc_private_encrypt called");
|
|
||||||
len = BN_num_bytes(rsa->n);
|
|
||||||
padded = xmalloc(len);
|
|
||||||
|
|
||||||
if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) {
|
|
||||||
error("RSA_padding_add_PKCS1_type_1 failed");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
|
|
||||||
if (sw == 0x6982) {
|
|
||||||
if (try_AUT0() < 0)
|
|
||||||
goto err;
|
|
||||||
sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
|
|
||||||
}
|
|
||||||
if (!sectok_swOK(sw)) {
|
|
||||||
error("sc_private_encrypt: INS_DECRYPT failed: %s",
|
|
||||||
sectok_get_sw(sw));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
err:
|
|
||||||
if (padded)
|
|
||||||
xfree(padded);
|
|
||||||
sc_close();
|
|
||||||
return (len >= 0 ? len : status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* called on free */
|
|
||||||
|
|
||||||
static int (*orig_finish)(RSA *rsa) = NULL;
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_finish(RSA *rsa)
|
|
||||||
{
|
|
||||||
if (orig_finish)
|
|
||||||
orig_finish(rsa);
|
|
||||||
sc_close();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* engine for overloading private key operations */
|
|
||||||
|
|
||||||
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 = "sectok";
|
|
||||||
|
|
||||||
/* overload */
|
|
||||||
smart_rsa.rsa_priv_enc = sc_private_encrypt;
|
|
||||||
smart_rsa.rsa_priv_dec = sc_private_decrypt;
|
|
||||||
|
|
||||||
/* save original */
|
|
||||||
orig_finish = def->finish;
|
|
||||||
smart_rsa.finish = sc_finish;
|
|
||||||
|
|
||||||
return &smart_rsa;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_ENGINE
|
|
||||||
static ENGINE *
|
|
||||||
sc_get_engine(void)
|
|
||||||
{
|
|
||||||
static ENGINE *smart_engine = NULL;
|
|
||||||
|
|
||||||
if ((smart_engine = ENGINE_new()) == NULL)
|
|
||||||
fatal("ENGINE_new failed");
|
|
||||||
|
|
||||||
ENGINE_set_id(smart_engine, "sectok");
|
|
||||||
ENGINE_set_name(smart_engine, "libsectok");
|
|
||||||
|
|
||||||
ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
|
|
||||||
ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
|
|
||||||
ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
|
|
||||||
ENGINE_set_RAND(smart_engine, RAND_SSLeay());
|
|
||||||
ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
|
|
||||||
|
|
||||||
return smart_engine;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
sc_close(void)
|
|
||||||
{
|
|
||||||
if (sc_fd >= 0) {
|
|
||||||
sectok_close(sc_fd);
|
|
||||||
sc_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Key **
|
|
||||||
sc_get_keys(const char *id, const char *pin)
|
|
||||||
{
|
|
||||||
Key *k, *n, **keys;
|
|
||||||
int status, nkeys = 2;
|
|
||||||
|
|
||||||
if (sc_reader_id != NULL)
|
|
||||||
xfree(sc_reader_id);
|
|
||||||
sc_reader_id = xstrdup(id);
|
|
||||||
|
|
||||||
if (sc_pin != NULL)
|
|
||||||
xfree(sc_pin);
|
|
||||||
sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
|
|
||||||
|
|
||||||
k = key_new(KEY_RSA);
|
|
||||||
if (k == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
status = sc_read_pubkey(k);
|
|
||||||
if (status == SCARD_ERROR_NOCARD) {
|
|
||||||
key_free(k);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (status < 0) {
|
|
||||||
error("sc_read_pubkey failed");
|
|
||||||
key_free(k);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
keys = xcalloc((nkeys+1), sizeof(Key *));
|
|
||||||
|
|
||||||
n = key_new(KEY_RSA1);
|
|
||||||
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
|
|
||||||
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
|
|
||||||
fatal("sc_get_keys: BN_copy failed");
|
|
||||||
RSA_set_method(n->rsa, sc_get_rsa());
|
|
||||||
n->flags |= KEY_FLAG_EXT;
|
|
||||||
keys[0] = n;
|
|
||||||
|
|
||||||
n = key_new(KEY_RSA);
|
|
||||||
if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
|
|
||||||
(BN_copy(n->rsa->e, k->rsa->e) == NULL))
|
|
||||||
fatal("sc_get_keys: BN_copy failed");
|
|
||||||
RSA_set_method(n->rsa, sc_get_rsa());
|
|
||||||
n->flags |= KEY_FLAG_EXT;
|
|
||||||
keys[1] = n;
|
|
||||||
|
|
||||||
keys[2] = NULL;
|
|
||||||
|
|
||||||
key_free(k);
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NUM_RSA_KEY_ELEMENTS 5+1
|
|
||||||
#define COPY_RSA_KEY(x, i) \
|
|
||||||
do { \
|
|
||||||
len = BN_num_bytes(prv->rsa->x); \
|
|
||||||
elements[i] = xmalloc(len); \
|
|
||||||
debug("#bytes %d", len); \
|
|
||||||
if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
|
|
||||||
goto done; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static void
|
|
||||||
sc_mk_digest(const char *pin, u_char *digest)
|
|
||||||
{
|
|
||||||
const EVP_MD *evp_md = EVP_sha1();
|
|
||||||
EVP_MD_CTX md;
|
|
||||||
|
|
||||||
EVP_DigestInit(&md, evp_md);
|
|
||||||
EVP_DigestUpdate(&md, pin, strlen(pin));
|
|
||||||
EVP_DigestFinal(&md, digest, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
get_AUT0(u_char *aut0)
|
|
||||||
{
|
|
||||||
char *pass;
|
|
||||||
|
|
||||||
pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
|
|
||||||
if (pass == NULL)
|
|
||||||
return -1;
|
|
||||||
if (!strcmp(pass, "-")) {
|
|
||||||
memcpy(aut0, DEFAUT0, sizeof DEFAUT0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sc_mk_digest(pass, aut0);
|
|
||||||
memset(pass, 0, strlen(pass));
|
|
||||||
xfree(pass);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
try_AUT0(void)
|
|
||||||
{
|
|
||||||
u_char aut0[EVP_MAX_MD_SIZE];
|
|
||||||
|
|
||||||
/* permission denied; try PIN if provided */
|
|
||||||
if (sc_pin && strlen(sc_pin) > 0) {
|
|
||||||
sc_mk_digest(sc_pin, aut0);
|
|
||||||
if (cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
|
|
||||||
error("smartcard passphrase incorrect");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* try default AUT0 key */
|
|
||||||
if (cyberflex_verify_AUT0(sc_fd, cla, DEFAUT0, 8) < 0) {
|
|
||||||
/* default AUT0 key failed; prompt for passphrase */
|
|
||||||
if (get_AUT0(aut0) < 0 ||
|
|
||||||
cyberflex_verify_AUT0(sc_fd, cla, aut0, 8) < 0) {
|
|
||||||
error("smartcard passphrase incorrect");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
sc_put_key(Key *prv, const char *id)
|
|
||||||
{
|
|
||||||
u_char *elements[NUM_RSA_KEY_ELEMENTS];
|
|
||||||
u_char key_fid[2];
|
|
||||||
u_char AUT0[EVP_MAX_MD_SIZE];
|
|
||||||
int len, status = -1, i, fd = -1, ret;
|
|
||||||
int sw = 0, cla = 0x00;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
|
|
||||||
elements[i] = NULL;
|
|
||||||
|
|
||||||
COPY_RSA_KEY(q, 0);
|
|
||||||
COPY_RSA_KEY(p, 1);
|
|
||||||
COPY_RSA_KEY(iqmp, 2);
|
|
||||||
COPY_RSA_KEY(dmq1, 3);
|
|
||||||
COPY_RSA_KEY(dmp1, 4);
|
|
||||||
COPY_RSA_KEY(n, 5);
|
|
||||||
len = BN_num_bytes(prv->rsa->n);
|
|
||||||
fd = sectok_friendly_open(id, STONOWAIT, &sw);
|
|
||||||
if (fd < 0) {
|
|
||||||
error("sectok_open failed: %s", sectok_get_sw(sw));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (! sectok_cardpresent(fd)) {
|
|
||||||
error("smartcard in reader %s not present", id);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ret = sectok_reset(fd, 0, NULL, &sw);
|
|
||||||
if (ret <= 0) {
|
|
||||||
error("sectok_reset failed: %s", sectok_get_sw(sw));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if ((cla = cyberflex_inq_class(fd)) < 0) {
|
|
||||||
error("cyberflex_inq_class failed");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
|
|
||||||
if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
|
|
||||||
if (get_AUT0(AUT0) < 0 ||
|
|
||||||
cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
|
|
||||||
memset(AUT0, 0, sizeof(DEFAUT0));
|
|
||||||
error("smartcard passphrase incorrect");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(AUT0, 0, sizeof(DEFAUT0));
|
|
||||||
key_fid[0] = 0x00;
|
|
||||||
key_fid[1] = 0x12;
|
|
||||||
if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
|
|
||||||
&sw) < 0) {
|
|
||||||
error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!sectok_swOK(sw))
|
|
||||||
goto done;
|
|
||||||
logit("cyberflex_load_rsa_priv done");
|
|
||||||
key_fid[0] = 0x73;
|
|
||||||
key_fid[1] = 0x68;
|
|
||||||
if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
|
|
||||||
&sw) < 0) {
|
|
||||||
error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (!sectok_swOK(sw))
|
|
||||||
goto done;
|
|
||||||
logit("cyberflex_load_rsa_pub done");
|
|
||||||
status = 0;
|
|
||||||
|
|
||||||
done:
|
|
||||||
memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
|
|
||||||
memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
|
|
||||||
memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
|
|
||||||
memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
|
|
||||||
memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
|
|
||||||
memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
|
|
||||||
if (elements[i])
|
|
||||||
xfree(elements[i]);
|
|
||||||
if (fd != -1)
|
|
||||||
sectok_close(fd);
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
sc_get_key_label(Key *key)
|
|
||||||
{
|
|
||||||
return xstrdup("smartcard key");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* SMARTCARD && USE_SECTOK */
|
|
39
scard.h
39
scard.h
|
@ -1,39 +0,0 @@
|
||||||
/* $OpenBSD: scard.h,v 1.14 2006/08/03 03:34:42 deraadt Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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 SCARD_H
|
|
||||||
#define SCARD_H
|
|
||||||
|
|
||||||
#define SCARD_ERROR_FAIL -1
|
|
||||||
#define SCARD_ERROR_NOCARD -2
|
|
||||||
#define SCARD_ERROR_APPLET -3
|
|
||||||
|
|
||||||
Key **sc_get_keys(const char *, const char *);
|
|
||||||
void sc_close(void);
|
|
||||||
int sc_put_key(Key *, const char *);
|
|
||||||
char *sc_get_key_label(Key *);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,29 +0,0 @@
|
||||||
# $Id: Makefile.in,v 1.5 2006/10/23 21:44:47 tim Exp $
|
|
||||||
|
|
||||||
prefix=@prefix@
|
|
||||||
datadir=@datadir@
|
|
||||||
datarootdir=@datarootdir@
|
|
||||||
srcdir=@srcdir@
|
|
||||||
top_srcdir=@top_srcdir@
|
|
||||||
|
|
||||||
INSTALL=@INSTALL@
|
|
||||||
|
|
||||||
VPATH=@srcdir@
|
|
||||||
|
|
||||||
all:
|
|
||||||
|
|
||||||
#Ssh.bin: Ssh.bin.uu
|
|
||||||
# uudecode Ssh.bin.uu
|
|
||||||
|
|
||||||
clean:
|
|
||||||
# rm -rf Ssh.bin
|
|
||||||
|
|
||||||
distprep:
|
|
||||||
uudecode Ssh.bin.uu
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
rm -f Makefile *~
|
|
||||||
|
|
||||||
install: $(srcdir)/Ssh.bin
|
|
||||||
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir)
|
|
||||||
$(INSTALL) -m 0644 $(srcdir)/Ssh.bin $(DESTDIR)$(datadir)/Ssh.bin
|
|
|
@ -1,17 +0,0 @@
|
||||||
begin 644 Ssh.bin
|
|
||||||
M`P)!&P`801X`>``!`E@"`/Y@\`4`_J'P!0!!&T$=`?Z@\`4`01M!'`'^>/,!
|
|
||||||
M`4$;01X!_G#S%P'^0],1`?Y@\!0`_G/S'0#^<]4``D$;L`4`_F'3``#^8=,%
|
|
||||||
M`/ZAT`$!_J#0)P'^H],*`?ZCTPD`_G/5"P7^8=,'`OZAT`H`_J#0$@3^:-,@
|
|
||||||
M`T$;`P`%`/Y@`<P``$$<\@\``$$=\B$``$$>\A```/`0__(%`@8!`0H``&``
|
|
||||||
M0205!!D)I$L`"0J0`&``*!4$&58``````.P````%____P````.D````0````
|
|
||||||
M,P```"````#'````,````(T````R````V!4#&0A*``D*;@!@`"@5!QD*`/\]
|
|
||||||
M(6``1A)*``D*9P!@`"@*/P!@`$LK"1)@`$LK!6``4!P$#00#2@`.#01@`%5@
|
|
||||||
M`%I@`"@37``>%0@2%0A>`%\($F``9%(`:`H_`&``2RL*<VA@`$LK8`!I"1`U
|
|
||||||
M(14#`Q)@`&X<!`T$`TL`"P,28`!D4@`.#01@`%5@`%I@`"A2`"X5`PH$`&``
|
|
||||||
M<RL#!6``9%(`'14#"@$"8`!S*P,%8`!D4@`,4@`)"FT`8``H60``\`+_\@$!
|
|
||||||
M`0D`"```"I``8``H60#P$__R`0$""0`,``!B01LM7P`\*UD```#P$O_V`0$#
|
|
||||||
M`0`8```37``>7@`R10`/$UP`'@H`R`D07@`W!%>P!?_R`0$$`@`\```37P``
|
|
||||||
M$V+^H2U?``5=``H38OZ@+5\`#UT`%!-B_G@M"@0`7P`970`>"@0`8``C10`)
|
|
||||||
/"F<`8``H$UX`+5D`````
|
|
||||||
`
|
|
||||||
end
|
|
164
scard/Ssh.java
164
scard/Ssh.java
|
@ -1,164 +0,0 @@
|
||||||
// $Id: Ssh.java,v 1.3 2002/05/22 04:24:02 djm Exp $
|
|
||||||
//
|
|
||||||
// Ssh.java
|
|
||||||
// SSH / smartcard integration project, smartcard side
|
|
||||||
//
|
|
||||||
// Tomoko Fukuzawa, created, Feb., 2000
|
|
||||||
//
|
|
||||||
// Naomaru Itoi, modified, Apr., 2000
|
|
||||||
//
|
|
||||||
|
|
||||||
// copyright 2000
|
|
||||||
// the regents of the university of michigan
|
|
||||||
// all rights reserved
|
|
||||||
//
|
|
||||||
// permission is granted to use, copy, create derivative works
|
|
||||||
// and redistribute this software and such derivative works
|
|
||||||
// for any purpose, so long as the name of the university of
|
|
||||||
// michigan is not used in any advertising or publicity
|
|
||||||
// pertaining to the use or distribution of this software
|
|
||||||
// without specific, written prior authorization. if the
|
|
||||||
// above copyright notice or any other identification of the
|
|
||||||
// university of michigan is included in any copy of any
|
|
||||||
// portion of this software, then the disclaimer below must
|
|
||||||
// also be included.
|
|
||||||
//
|
|
||||||
// this software is provided as is, without representation
|
|
||||||
// from the university of michigan as to its fitness for any
|
|
||||||
// purpose, and without warranty by the university of
|
|
||||||
// michigan of any kind, either express or implied, including
|
|
||||||
// without limitation the implied warranties of
|
|
||||||
// merchantability and fitness for a particular purpose. the
|
|
||||||
// regents of the university of michigan shall not be liable
|
|
||||||
// for any damages, including special, indirect, incidental, or
|
|
||||||
// consequential damages, with respect to any claim arising
|
|
||||||
// out of or in connection with the use of the software, even
|
|
||||||
// if it has been or is hereafter advised of the possibility of
|
|
||||||
// such damages.
|
|
||||||
|
|
||||||
import javacard.framework.*;
|
|
||||||
import javacardx.framework.*;
|
|
||||||
import javacardx.crypto.*;
|
|
||||||
|
|
||||||
public class Ssh extends javacard.framework.Applet
|
|
||||||
{
|
|
||||||
// Change this when the applet changes; hi byte is major, low byte is minor
|
|
||||||
static final short applet_version = (short)0x0102;
|
|
||||||
|
|
||||||
/* constants declaration */
|
|
||||||
// code of CLA byte in the command APDU header
|
|
||||||
static final byte Ssh_CLA =(byte)0x05;
|
|
||||||
|
|
||||||
// codes of INS byte in the command APDU header
|
|
||||||
static final byte DECRYPT = (byte) 0x10;
|
|
||||||
static final byte GET_KEYLENGTH = (byte) 0x20;
|
|
||||||
static final byte GET_PUBKEY = (byte) 0x30;
|
|
||||||
static final byte GET_VERSION = (byte) 0x32;
|
|
||||||
static final byte GET_RESPONSE = (byte) 0xc0;
|
|
||||||
|
|
||||||
static final short keysize = 1024;
|
|
||||||
static final short root_fid = (short)0x3f00;
|
|
||||||
static final short privkey_fid = (short)0x0012;
|
|
||||||
static final short pubkey_fid = (short)(('s'<<8)|'h');
|
|
||||||
|
|
||||||
/* instance variables declaration */
|
|
||||||
AsymKey rsakey;
|
|
||||||
CyberflexFile file;
|
|
||||||
CyberflexOS os;
|
|
||||||
|
|
||||||
private Ssh()
|
|
||||||
{
|
|
||||||
file = new CyberflexFile();
|
|
||||||
os = new CyberflexOS();
|
|
||||||
|
|
||||||
rsakey = new RSA_CRT_PrivateKey (keysize);
|
|
||||||
|
|
||||||
if ( ! rsakey.isSupportedLength (keysize) )
|
|
||||||
ISOException.throwIt (ISO.SW_WRONG_LENGTH);
|
|
||||||
|
|
||||||
register();
|
|
||||||
} // end of the constructor
|
|
||||||
|
|
||||||
public boolean select() {
|
|
||||||
if (!rsakey.isInitialized())
|
|
||||||
rsakey.setKeyInstance ((short)0xc8, (short)0x10);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void install(APDU apdu)
|
|
||||||
{
|
|
||||||
new Ssh(); // create a Ssh applet instance (card)
|
|
||||||
} // end of install method
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
|
||||||
ISOException.throwIt((short) 0x9000);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void process(APDU apdu)
|
|
||||||
{
|
|
||||||
// APDU object carries a byte array (buffer) to
|
|
||||||
// transfer incoming and outgoing APDU header
|
|
||||||
// and data bytes between card and CAD
|
|
||||||
byte buffer[] = apdu.getBuffer();
|
|
||||||
short size, st;
|
|
||||||
|
|
||||||
// verify that if the applet can accept this
|
|
||||||
// APDU message
|
|
||||||
// NI: change suggested by Wayne Dyksen, Purdue
|
|
||||||
if (buffer[ISO.OFFSET_INS] == ISO.INS_SELECT)
|
|
||||||
ISOException.throwIt(ISO.SW_NO_ERROR);
|
|
||||||
|
|
||||||
switch (buffer[ISO.OFFSET_INS]) {
|
|
||||||
case DECRYPT:
|
|
||||||
if (buffer[ISO.OFFSET_CLA] != Ssh_CLA)
|
|
||||||
ISOException.throwIt(ISO.SW_CLA_NOT_SUPPORTED);
|
|
||||||
//decrypt (apdu);
|
|
||||||
size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF);
|
|
||||||
|
|
||||||
if (apdu.setIncomingAndReceive() != size)
|
|
||||||
ISOException.throwIt (ISO.SW_WRONG_LENGTH);
|
|
||||||
|
|
||||||
// check access; depends on bit 2 (x/a)
|
|
||||||
file.selectFile(root_fid);
|
|
||||||
file.selectFile(privkey_fid);
|
|
||||||
st = os.checkAccess(ACL.EXECUTE);
|
|
||||||
if (st != ST.ACCESS_CLEARED) {
|
|
||||||
CyberflexAPDU.prepareSW1SW2(st);
|
|
||||||
ISOException.throwIt(CyberflexAPDU.getSW1SW2());
|
|
||||||
}
|
|
||||||
|
|
||||||
rsakey.cryptoUpdate (buffer, (short) ISO.OFFSET_CDATA, size,
|
|
||||||
buffer, (short) ISO.OFFSET_CDATA);
|
|
||||||
|
|
||||||
apdu.setOutgoingAndSend ((short) ISO.OFFSET_CDATA, size);
|
|
||||||
break;
|
|
||||||
case GET_PUBKEY:
|
|
||||||
file.selectFile(root_fid); // select root
|
|
||||||
file.selectFile(pubkey_fid); // select public key file
|
|
||||||
size = (short)(file.getFileSize() - 16);
|
|
||||||
st = os.readBinaryFile(buffer, (short)0, (short)0, size);
|
|
||||||
if (st == ST.SUCCESS)
|
|
||||||
apdu.setOutgoingAndSend((short)0, size);
|
|
||||||
else {
|
|
||||||
CyberflexAPDU.prepareSW1SW2(st);
|
|
||||||
ISOException.throwIt(CyberflexAPDU.getSW1SW2());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GET_KEYLENGTH:
|
|
||||||
Util.setShort(buffer, (short)0, keysize);
|
|
||||||
apdu.setOutgoingAndSend ((short)0, (short)2);
|
|
||||||
break;
|
|
||||||
case GET_VERSION:
|
|
||||||
Util.setShort(buffer, (short)0, applet_version);
|
|
||||||
apdu.setOutgoingAndSend ((short)0, (short)2);
|
|
||||||
break;
|
|
||||||
case GET_RESPONSE:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ISOException.throwIt (ISO.SW_INS_NOT_SUPPORTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end of process method
|
|
||||||
|
|
||||||
} // end of class Ssh
|
|
Loading…
Reference in New Issue