- (bal) Patch for OpenSC SmartCard library; ok markus@; patch by

Juha Yrjölä <jyrjola@cc.hut.fi>
 - (bal) Minor documentation update to reflect smartcard library
   support changes.
This commit is contained in:
Ben Lindstrom 2002-04-05 16:11:45 +00:00
Родитель 8a725a843d
Коммит a42694fa25
8 изменённых файлов: 530 добавлений и 17 удалений

Просмотреть файл

@ -1,3 +1,9 @@
20020405
- (bal) Patch for OpenSC SmartCard library; ok markus@; patch by
Juha Yrjölä <jyrjola@cc.hut.fi>
- (bal) Minor documentation update to reflect smartcard library
support changes.
20020404
- (stevesk) [auth-pam.c auth-pam.h auth-passwd.c auth-sia.c auth-sia.h
auth1.c auth2.c] PAM, OSF_SIA password auth cleanup; from djm.
@ -8155,4 +8161,4 @@
- Wrote replacements for strlcpy and mkdtemp
- Released 1.0pre1
$Id: ChangeLog,v 1.2022 2002/04/04 22:10:38 mouring Exp $
$Id: ChangeLog,v 1.2023 2002/04/05 16:11:45 mouring Exp $

Просмотреть файл

@ -178,6 +178,10 @@ are installed.
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
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
can specify these as environment variables before running ./configure.
For example:
@ -218,4 +222,4 @@ Please refer to the "reporting bugs" section of the webpage at
http://www.openssh.com/
$Id: INSTALL,v 1.49 2002/03/07 17:49:40 mouring Exp $
$Id: INSTALL,v 1.50 2002/04/05 16:11:46 mouring Exp $

Просмотреть файл

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.200 2002/03/22 02:30:43 mouring Exp $
# $Id: Makefile.in,v 1.201 2002/04/05 16:11:46 mouring Exp $
prefix=@prefix@
exec_prefix=@exec_prefix@
@ -50,7 +50,7 @@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS)
LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o
LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o scard-opensc.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o monitor_wrap.o monitor_fdpass.o
SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o

Просмотреть файл

@ -8,18 +8,22 @@ are still subject to change.
To enable this you need to:
(1) install sectok
(1) install sectok or openSC
Sources are instructions are available from
http://www.citi.umich.edu/projects/smartcard/sectok.html
or
http://www.opensc.org/
(2) enable SMARTCARD support in OpenSSH:
$ ./configure --with-smartcard [options]
$ ./configure --with-sectok[=/path/to/libsectok] [options]
You can also specify a path to libsectok:
or
$ ./configure --with-smartcard=/path/to/libsectok [options]
$ ./configure --with-opensc[=/path/to/opensc] [options]
(3) load the Java Cardlet to the Cyberflex card:

Просмотреть файл

@ -1,4 +1,4 @@
/* $Id: acconfig.h,v 1.124 2002/03/22 18:19:54 stevesk Exp $ */
/* $Id: acconfig.h,v 1.125 2002/04/05 16:11:46 mouring Exp $ */
#ifndef _CONFIG_H
#define _CONFIG_H
@ -329,6 +329,12 @@
/* Define if you want smartcard support */
#undef SMARTCARD
/* Define if you want smartcard support using sectok */
#undef USE_SECTOK
/* Define if you want smartcard support using OpenSC */
#undef USE_OPENSC
/* Define if you want to use OpenSSL's internally seeded PRNG only */
#undef OPENSSL_PRNG_ONLY

Просмотреть файл

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.30 2002/03/31 19:23:07 tim Exp $
# $Id: configure.ac,v 1.31 2002/04/05 16:11:46 mouring Exp $
AC_INIT
AC_CONFIG_SRCDIR([ssh.c])
@ -1667,11 +1667,11 @@ if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
AC_DEFINE(HAVE_SYS_NERR)
fi
# Check whether user wants Kerberos support
SCARD_MSG="no"
AC_ARG_WITH(smartcard,
[ --with-smartcard Enable smartcard support],
# 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
@ -1693,7 +1693,38 @@ AC_ARG_WITH(smartcard,
AC_MSG_ERROR(Can't find libsectok)
fi
AC_DEFINE(SMARTCARD)
SCARD_MSG="yes"
AC_DEFINE(USE_SECTOK)
SCARD_MSG="yes, using sectok"
fi
]
)
# Check whether user wants OpenSC support
AC_ARG_WITH(opensc,
[ --with-opensc Enable smartcard support using OpenSC],
[
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(opensc-pkcs15.h)
if test "$ac_cv_header_opensc_pkcs15_h" != yes; then
AC_MSG_ERROR(Can't find opensc-pkcs15.h)
fi
AC_CHECK_LIB(opensc, sc_pkcs15_bind)
if test "$ac_cv_lib_opensc_sc_pkcs15_bind" != yes; then
AC_MSG_ERROR(Can't find libopensc)
fi
AC_DEFINE(SMARTCARD)
AC_DEFINE(USE_OPENSC)
SCARD_MSG="yes, using OpenSC"
fi
]
)

462
scard-opensc.c Normal file
Просмотреть файл

@ -0,0 +1,462 @@
/*
* 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 <openssl/evp.h>
#include <openssl/x509.h>
#include <opensc.h>
#include <opensc-pkcs15.h>
#include "key.h"
#include "log.h"
#include "xmalloc.h"
#include "readpass.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
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;
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)
{
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(p15card, &priv->cert_id, &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) {
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;
}
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);
if (r)
return -1;
r = sc_pkcs15_decipher(p15card, key_obj, 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;
}
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;
r = sc_prkey_op_init(rsa, &key_obj);
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) {
log("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)) {
log("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) {
log("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) {
log("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;
}
/* FIXME: only keep entries with a corresponding private key */
keys = xmalloc(sizeof(Key *) * (key_count*2+1));
for (i = 0; i < key_count; i++) {
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;
}
#endif /* SMARTCARD */

Просмотреть файл

@ -23,7 +23,7 @@
*/
#include "includes.h"
#ifdef SMARTCARD
#if defined(SMARTCARD) && defined(USE_SECTOK)
RCSID("$OpenBSD: scard.c,v 1.25 2002/03/26 18:46:59 rees Exp $");
#include <openssl/evp.h>
@ -554,4 +554,4 @@ done:
sectok_close(fd);
return (status);
}
#endif /* SMARTCARD */
#endif /* SMARTCARD && USE_SECTOK */