[BACK]Return to scard.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/Attic/scard.c between version 1.15 and 1.15.2.3

version 1.15, 2001/09/28 09:49:31 version 1.15.2.3, 2002/06/26 18:22:35
Line 26 
Line 26 
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include <openssl/engine.h>  #include <openssl/evp.h>
 #include <sectok.h>  #include <sectok.h>
   
 #include "key.h"  #include "key.h"
 #include "log.h"  #include "log.h"
 #include "xmalloc.h"  #include "xmalloc.h"
   #include "readpass.h"
 #include "scard.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 CLA_SSH 0x05
 #define INS_DECRYPT 0x10  #define INS_DECRYPT 0x10
 #define INS_GET_KEYLENGTH 0x20  #define INS_GET_KEYLENGTH 0x20
Line 42 
Line 56 
   
 #define MAX_BUF_SIZE 256  #define MAX_BUF_SIZE 256
   
   u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
   
 static int sc_fd = -1;  static int sc_fd = -1;
 static char *sc_reader_id = NULL;  static char *sc_reader_id = NULL;
   static char *sc_pin = NULL;
 static int cla = 0x00;  /* class */  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 */  /* interface to libsectok */
   
 static int  static int
 sc_open(void)  sc_open(void)
 {  {
         int sw;          int sw;
Line 79 
Line 100 
         return sc_fd;          return sc_fd;
 }  }
   
 static int  static int
 sc_enable_applet(void)  sc_enable_applet(void)
 {  {
         static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e};          static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e};
Line 95 
Line 116 
         return 0;          return 0;
 }  }
   
 static int  static int
 sc_init(void)  sc_init(void)
 {  {
         int status;          int status;
Line 115 
Line 136 
         return 0;          return 0;
 }  }
   
 static int  static int
 sc_read_pubkey(Key * k)  sc_read_pubkey(Key * k)
 {  {
         u_char buf[2], *n;          u_char buf[2], *n;
Line 126 
Line 147 
         n = NULL;          n = NULL;
   
         if (sc_fd < 0) {          if (sc_fd < 0) {
                 status = sc_init();                  if (sc_init() < 0)
                 if (status < 0 )  
                         goto err;                          goto err;
         }          }
   
         /* get key size */          /* get key size */
         sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL,          sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL,
              sizeof(buf), buf, &sw);              sizeof(buf), buf, &sw);
         if (!sectok_swOK(sw)) {          if (!sectok_swOK(sw)) {
                 error("could not obtain key length: %s", sectok_get_sw(sw));                  error("could not obtain key length: %s", sectok_get_sw(sw));
                 goto err;                  goto err;
Line 145 
Line 165 
         n = xmalloc(len);          n = xmalloc(len);
         /* get n */          /* get n */
         sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);          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)) {          if (!sectok_swOK(sw)) {
                 error("could not obtain public key: %s", sectok_get_sw(sw));                  error("could not obtain public key: %s", sectok_get_sw(sw));
                 goto err;                  goto err;
Line 165 
Line 191 
   
         status = 0;          status = 0;
         p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);          p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
         debug("fingerprint %d %s", key_size(k), p);          debug("fingerprint %u %s", key_size(k), p);
         xfree(p);          xfree(p);
   
 err:  err:
Line 178 
Line 204 
 /* private key operations */  /* private key operations */
   
 static int  static int
 sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)  sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
       int padding)
 {  {
         u_char *padded = NULL;          u_char *padded = NULL;
         int sw, len, olen, status = -1;          int sw, len, olen, status = -1;
Line 197 
Line 224 
         len = BN_num_bytes(rsa->n);          len = BN_num_bytes(rsa->n);
         padded = xmalloc(len);          padded = xmalloc(len);
   
         sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, 0, NULL, &sw);          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)) {          if (!sectok_swOK(sw)) {
                 error("sc_private_decrypt: INS_DECRYPT failed: %s",                  error("sc_private_decrypt: INS_DECRYPT failed: %s",
                     sectok_get_sw(sw));                      sectok_get_sw(sw));
                 goto err;                  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,          olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1,
             len);              len);
 err:  err:
Line 220 
Line 246 
 }  }
   
 static int  static int
 sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)  sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
       int padding)
 {  {
         u_char *padded = NULL;          u_char *padded = NULL;
         int sw, len, status = -1;          int sw, len, status = -1;
Line 238 
Line 265 
         len = BN_num_bytes(rsa->n);          len = BN_num_bytes(rsa->n);
         padded = xmalloc(len);          padded = xmalloc(len);
   
         if (RSA_padding_add_PKCS1_type_1(padded, len, from, flen) <= 0) {          if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) {
                 error("RSA_padding_add_PKCS1_type_1 failed");                  error("RSA_padding_add_PKCS1_type_1 failed");
                 goto err;                  goto err;
         }          }
         sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, 0, NULL, &sw);          sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
         if (!sectok_swOK(sw)) {          if (sw == 0x6982) {
                 error("sc_private_decrypt: INS_DECRYPT failed: %s",                  if (try_AUT0() < 0)
                     sectok_get_sw(sw));                          goto err;
                 goto err;                  sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw);
         }          }
         sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,  
              len, to, &sw);  
         if (!sectok_swOK(sw)) {          if (!sectok_swOK(sw)) {
                 error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",                  error("sc_private_encrypt: INS_DECRYPT failed: %s",
                     sectok_get_sw(sw));                      sectok_get_sw(sw));
                 goto err;                  goto err;
         }          }
Line 275 
Line 300 
         return 1;          return 1;
 }  }
   
   
 /* engine for overloading private key operations */  /* engine for overloading private key operations */
   
 static ENGINE *smart_engine = NULL;  static RSA_METHOD *
 static RSA_METHOD smart_rsa =  sc_get_rsa_method(void)
 {  {
         "sectok",          static RSA_METHOD smart_rsa;
         NULL,          const RSA_METHOD *def = RSA_get_default_method();
         NULL,  
         NULL,  
         NULL,  
         NULL,  
         NULL,  
         NULL,  
         NULL,  
         0,  
         NULL,  
 };  
   
 ENGINE *          /* use the OpenSSL version */
 sc_get_engine(void)          memcpy(&smart_rsa, def, sizeof(smart_rsa));
 {  
         RSA_METHOD *def;  
   
         def = RSA_get_default_openssl_method();          smart_rsa.name          = "sectok";
   
         /* overload */          /* overload */
         smart_rsa.rsa_priv_enc  = sc_private_encrypt;          smart_rsa.rsa_priv_enc  = sc_private_encrypt;
Line 309 
Line 321 
         orig_finish             = def->finish;          orig_finish             = def->finish;
         smart_rsa.finish        = sc_finish;          smart_rsa.finish        = sc_finish;
   
         /* just use the OpenSSL version */          return &smart_rsa;
         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.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();  #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_id(smart_engine, "sectok");
         ENGINE_set_name(smart_engine, "libsectok");          ENGINE_set_name(smart_engine, "libsectok");
         ENGINE_set_RSA(smart_engine, &smart_rsa);  
           ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
         ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());          ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
         ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());          ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
         ENGINE_set_RAND(smart_engine, RAND_SSLeay());          ENGINE_set_RAND(smart_engine, RAND_SSLeay());
Line 332 
Line 344 
   
         return smart_engine;          return smart_engine;
 }  }
   #endif
   
 void  void
 sc_close(void)  sc_close(void)
Line 342 
Line 355 
         }          }
 }  }
   
 Key *  Key **
 sc_get_key(const char *id)  sc_get_keys(const char *id, const char *pin)
 {  {
         Key *k;          Key *k, *n, **keys;
         int status;          int status, nkeys = 2;
   
         if (sc_reader_id != NULL)          if (sc_reader_id != NULL)
                 xfree(sc_reader_id);                  xfree(sc_reader_id);
         sc_reader_id = xstrdup(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);          k = key_new(KEY_RSA);
         if (k == NULL) {          if (k == NULL) {
                 return NULL;                  return NULL;
Line 366 
Line 383 
                 key_free(k);                  key_free(k);
                 return NULL;                  return NULL;
         }          }
         return k;          keys = xmalloc((nkeys+1) * sizeof(Key *));
   
           n = key_new(KEY_RSA1);
           BN_copy(n->rsa->n, k->rsa->n);
           BN_copy(n->rsa->e, k->rsa->e);
           RSA_set_method(n->rsa, sc_get_rsa());
           n->flags |= KEY_FLAG_EXT;
           keys[0] = n;
   
           n = key_new(KEY_RSA);
           BN_copy(n->rsa->n, k->rsa->n);
           BN_copy(n->rsa->e, k->rsa->e);
           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;
           log("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;
           log("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);
 }  }
 #endif /* SMARTCARD */  #endif /* SMARTCARD */

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.15.2.3