From 3133dbbdba20943f283f818f42265d956722e884 Mon Sep 17 00:00:00 2001 From: Ben Lindstrom Date: Wed, 4 Jul 2001 05:35:00 +0000 Subject: - (bal) forget a few new files in sync up. --- ChangeLog | 5 +- scard.c | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ scard.h | 35 +++++++ scard/Ssh.bin.uu | 17 +++ scard/Ssh.java | 156 ++++++++++++++++++++++++++++ 5 files changed, 520 insertions(+), 2 deletions(-) create mode 100644 scard.c create mode 100644 scard.h create mode 100644 scard/Ssh.bin.uu create mode 100644 scard/Ssh.java diff --git a/ChangeLog b/ChangeLog index aa734bcd0..f7e597364 100644 --- a/ChangeLog +++ b/ChangeLog @@ -130,7 +130,8 @@ stop listening to channels, detach channel users (e.g. sessions). wait for children (i.e. dying sessions), send exit messages, cleanup all channels. - + - (bal) forget a few new files in sync up. + 20010629 - (bal) Removed net_aton() since we don't use it any more - (bal) Fixed _DISABLE_VPOSIX in readpassphrase.c. @@ -5957,4 +5958,4 @@ - Wrote replacements for strlcpy and mkdtemp - Released 1.0pre1 -$Id: ChangeLog,v 1.1376 2001/07/04 05:26:06 mouring Exp $ +$Id: ChangeLog,v 1.1377 2001/07/04 05:35:00 mouring Exp $ diff --git a/scard.c b/scard.c new file mode 100644 index 000000000..4f038ddac --- /dev/null +++ b/scard.c @@ -0,0 +1,309 @@ +/* + * 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. + */ + +#ifdef SMARTCARD +#include "includes.h" +RCSID("$OpenBSD: scard.c,v 1.4 2001/07/02 22:40:17 markus Exp $"); + +#include +#include + +#include "key.h" +#include "log.h" +#include "xmalloc.h" +#include "scard.h" + +#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 + +static int sc_fd = -1; +static int sc_reader_num = 0; +static int cla = 0x00; /* class */ + +/* interface to libsectok */ + +static int +sc_open(int num) +{ + u_char atr[256]; + int sw; + + if (sc_fd >= 0) + return sc_fd; + sc_reader_num = num; + + sc_fd = sectok_open(sc_reader_num, 0, NULL); + if (sc_fd < 0) { + error("sectok_open failed %d", sc_fd); + return sc_fd; + } + if (sectok_reset(sc_fd, 0, atr, &sw) <= 0) { + error("sectok_reset failed: %s", sectok_get_sw(sw)); + sc_fd = -1; + return sc_fd; + } + debug("sc_open ok %d", sc_fd); + return sc_fd; +} + +static int +sc_enable_applet(void) +{ + u_char contID[2], aid[MAX_BUF_SIZE]; + int i, len, sw, aid_len; + + len = sw = 0; + contID[0] = 0x77; + contID[1] = 0x78; + + if (sectok_selectfile(sc_fd, cla, root_fid, &sw) < 0) { + error("sectok_selectfile root_fid failed: %s", + sectok_get_sw(sw)); + return -1; + } + if (sectok_selectfile(sc_fd, cla, contID, &sw) < 0) { + error("sectok_selectfile failed: %s", sectok_get_sw(sw)); + return -1; + } + /* send appled id */ + for (i = 0; i < sizeof(aid); i++) + aid[i] = 0x77; + aid_len = 5; + sectok_apdu(sc_fd, cla, 0xa4, 0x04, 0, aid_len, aid, 0, NULL, &sw); + if (!sectok_swOK(sw)) { + error("sectok_apdu failed: %s", sectok_get_sw(sw)); + return -1; + } + return 0; +} + +static int +sc_read_pubkey(Key * k) +{ + u_char buf[2], *n; + char *p; + int len, sw; + + len = sw = 0; + + /* 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)); + return -1; + } + 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 (!sectok_swOK(sw)) { + error("could not obtain public key: %s", sectok_get_sw(sw)); + xfree(n); + return -1; + } + 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"); + xfree(n); + return -1; + } + xfree(n); + + /* 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"); + return -1; + } + + p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX); + debug("fingerprint %d %s", key_size(k), p); + xfree(p); + + return 0; +} + +/* 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; + + debug("sc_private_decrypt called"); + + olen = len = sw = 0; + 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, 0, NULL, &sw); + if (!sectok_swOK(sw)) { + error("sc_private_decrypt: INS_DECRYPT failed: %s", + sectok_get_sw(sw)); + goto err; + } + sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL, + len, padded, &sw); + if (!sectok_swOK(sw)) { + error("sc_private_decrypt: INS_GET_RESPONSE 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); + return olen; +} + +static int +sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding) +{ + u_char *padded = NULL; + int sw, len; + + len = sw = 0; + 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, 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, 0, NULL, &sw); + if (!sectok_swOK(sw)) { + error("sc_private_decrypt: INS_DECRYPT failed: %s", + sectok_get_sw(sw)); + goto err; + } + sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL, + len, to, &sw); + if (!sectok_swOK(sw)) { + error("sc_private_decrypt: INS_GET_RESPONSE failed: %s", + sectok_get_sw(sw)); + goto err; + } +err: + if (padded) + xfree(padded); + return len; +} + +/* engine for overloading private key operations */ + +static ENGINE *smart_engine = NULL; +static RSA_METHOD smart_rsa = +{ + "sectok", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + NULL, +}; + +ENGINE * +sc_get_engine(void) +{ + RSA_METHOD *def; + + def = RSA_get_default_openssl_method(); + + /* overload */ + smart_rsa.rsa_priv_enc = sc_private_encrypt; + smart_rsa.rsa_priv_dec = sc_private_decrypt; + + /* just use the OpenSSL version */ + smart_rsa.rsa_pub_enc = def->rsa_pub_enc; + smart_rsa.rsa_pub_dec = def->rsa_pub_dec; + smart_rsa.rsa_mod_exp = def->rsa_mod_exp; + smart_rsa.bn_mod_exp = def->bn_mod_exp; + smart_rsa.init = def->init; + smart_rsa.finish = def->finish; + smart_rsa.flags = def->flags; + smart_rsa.app_data = def->app_data; + smart_rsa.rsa_sign = def->rsa_sign; + smart_rsa.rsa_verify = def->rsa_verify; + + smart_engine = ENGINE_new(); + + ENGINE_set_id(smart_engine, "sectok"); + ENGINE_set_name(smart_engine, "libsectok"); + ENGINE_set_RSA(smart_engine, &smart_rsa); + 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; +} + +Key * +sc_get_key(int sc_reader_num) +{ + Key *k; + + if (sc_open(sc_reader_num) < 0) { + error("sc_open failed"); + return NULL; + } + if (sc_enable_applet() < 0) { + error("sc_enable_applet failed"); + return NULL; + } + k = key_new(KEY_RSA); + if (k == NULL) { + return NULL; + } + if (sc_read_pubkey(k) < 0) { + error("sc_read_pubkey failed"); + key_free(k); + return NULL; + } + return k; +} +#endif diff --git a/scard.h b/scard.h new file mode 100644 index 000000000..480be0764 --- /dev/null +++ b/scard.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +/* $OpenBSD: scard.h,v 1.3 2001/06/26 17:27:24 markus Exp $ */ + +#include + +#ifndef SCARD_H +#define SCARD_H + +Key *sc_get_key(int); +ENGINE *sc_get_engine(void); + +#endif diff --git a/scard/Ssh.bin.uu b/scard/Ssh.bin.uu new file mode 100644 index 000000000..9af0adf04 --- /dev/null +++ b/scard/Ssh.bin.uu @@ -0,0 +1,17 @@ +begin 644 Ssh.bin +M`P)!#``:01\`A``!`F@"`$$,014!_F#P!0!!#$$?`4$,01X!00Q!'0%!#$$< +M`4$,01L!00Q!&@'^H?`%`$$,01@!_J#P!0!!#$$7`?YX\P$!00Q!&0'^<]4` +M`OYP\Q__8"`$$?__8" +M`/`0__(#`@8!`,H``!-@`%]=`&037`!D!!D)I$L`"0J0`&``4!-<`&0$&58` +M````H@````3____`````H0```!`````J````(````(T````P````:A-<`&0# +M&0A*``D*;@!@`%`37`!D!QD*`/\](&``:1%*``D*9P!@`%`37`!!$UP`9`@1 +M$UP`9`A>`&X($6``"T* +M!`!?`#Q=`$$37`!!"@#("1!>`$8*!`!@`$M%``D*9P!@`%`37@!56?`&__(` +?``0(`!0```9C""T#"<(H+00$*"T%""A;``!9``````!@ +` +end diff --git a/scard/Ssh.java b/scard/Ssh.java new file mode 100644 index 000000000..05e2b4872 --- /dev/null +++ b/scard/Ssh.java @@ -0,0 +1,156 @@ +/* + * copyright 1997, 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. + * + * SSH / smartcard integration project, smartcard side + * + * Tomoko Fukuzawa, created, Feb., 2000 + * Naomaru Itoi, modified, Apr., 2000 + */ + +import javacard.framework.*; +import javacardx.framework.*; +import javacardx.crypto.*; + +public class Ssh extends javacard.framework.Applet +{ + /* constants declaration */ + // code of CLA byte in the command APDU header + private final byte Ssh_CLA =(byte)0x05; + + // codes of INS byte in the command APDU header + private final byte DECRYPT = (byte) 0x10; + private final byte GET_KEYLENGTH = (byte) 0x20; + private final byte GET_PUBKEY = (byte) 0x30; + private final byte GET_RESPONSE = (byte) 0xc0; + + /* instance variables declaration */ + private final short keysize = 1024; + + //RSA_CRT_PrivateKey rsakey; + AsymKey rsakey; + CyberflexFile file; + CyberflexOS os; + + byte buffer[]; + //byte pubkey[]; + + static byte[] keyHdr = {(byte)0xC2, (byte)0x01, (byte)0x05}; + + private Ssh() + { + file = new CyberflexFile(); + os = new CyberflexOS(); + + rsakey = new RSA_CRT_PrivateKey (keysize); + rsakey.setKeyInstance ((short)0xc8, (short)0x10); + + if ( ! rsakey.isSupportedLength (keysize) ) + ISOException.throwIt (ISO.SW_WRONG_LENGTH); + + /* + pubkey = new byte[keysize/8]; + file.selectFile((short)(0x3f<<8)); // select root + file.selectFile((short)(('s'<<8)|'h')); // select public key file + os.readBinaryFile (pubkey, (short)0, (short)0, (short)(keysize/8)); + */ + register(); + } // end of the constructor + + public static void install(APDU apdu) + { + new Ssh(); // create a Ssh applet instance (card) + } // end of install method + + 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 + buffer = apdu.getBuffer(); + + // 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); + short size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF); + + if (apdu.setIncomingAndReceive() != size) + ISOException.throwIt (ISO.SW_WRONG_LENGTH); + + rsakey.cryptoUpdate (buffer, (short) ISO.OFFSET_CDATA, size, + buffer, (short) ISO.OFFSET_CDATA); + apdu.setOutgoingAndSend ((short) ISO.OFFSET_CDATA, size); + return; + case GET_PUBKEY: + file.selectFile((short)(0x3f<<8)); // select root + file.selectFile((short)(('s'<<8)|'h')); // select public key file + os.readBinaryFile (buffer, (short)0, (short)0, (short)(keysize/8)); + apdu.setOutgoingAndSend((short)0, (short)(keysize/8)); + /* + apdu.setOutgoing(); + apdu.setOutgoingLength((short)(keysize/8)); + apdu.sendBytesLong(pubkey, (short)0, (short)(keysize/8)); + */ + return; + case GET_KEYLENGTH: + buffer[0] = (byte)((keysize >> 8) & 0xff); + buffer[1] = (byte)(keysize & 0xff); + apdu.setOutgoingAndSend ((short)0, (short)2); + return; + case GET_RESPONSE: + return; + default: + ISOException.throwIt (ISO.SW_INS_NOT_SUPPORTED); + } + + } // end of process method + + /* + private void decrypt (APDU apdu) + { + short size = (short) (buffer[ISO.OFFSET_LC] & 0x00FF); + + if (apdu.setIncomingAndReceive() != size) + ISOException.throwIt (ISO.SW_WRONG_LENGTH); + + //short offset = (short) ISO.OFFSET_CDATA; + + rsakey.cryptoUpdate (buffer, (short) ISO.OFFSET_CDATA, size, buffer, + (short) ISO.OFFSET_CDATA); + apdu.setOutgoingAndSend ((short) ISO.OFFSET_CDATA, size); + } + */ +} // end of class Ssh -- cgit v1.2.3