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

Diff for /src/usr.bin/ssh/sk-usbhid.c between version 1.8 and 1.9

version 1.8, 2019/12/30 09:19:52 version 1.9, 2019/12/30 09:21:16
Line 30 
Line 30 
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
   
 #include <fido.h>  #include <fido.h>
   #include <fido/credman.h>
   
 #ifndef SK_STANDALONE  #ifndef SK_STANDALONE
 #include "log.h"  #include "log.h"
Line 80 
Line 81 
         size_t sig_s_len;          size_t sig_s_len;
 };  };
   
   struct sk_resident_key {
           uint8_t alg;
           size_t slot;
           char *application;
           struct sk_enroll_response key;
   };
   
 /* If building as part of OpenSSH, then rename exported functions */  /* If building as part of OpenSSH, then rename exported functions */
 #if !defined(SK_STANDALONE)  #if !defined(SK_STANDALONE)
 #define sk_api_version  ssh_sk_api_version  #define sk_api_version          ssh_sk_api_version
 #define sk_enroll       ssh_sk_enroll  #define sk_enroll               ssh_sk_enroll
 #define sk_sign         ssh_sk_sign  #define sk_sign                 ssh_sk_sign
   #define sk_load_resident_keys   ssh_sk_load_resident_keys
 #endif  #endif
   
 /* Return the version of the middleware API */  /* Return the version of the middleware API */
Line 100 
Line 109 
     const char *application, const uint8_t *key_handle, size_t key_handle_len,      const char *application, const uint8_t *key_handle, size_t key_handle_len,
     uint8_t flags, struct sk_sign_response **sign_response);      uint8_t flags, struct sk_sign_response **sign_response);
   
   /* Load resident keys */
   int sk_load_resident_keys(const char *pin,
       struct sk_resident_key ***rks, size_t *nrks);
   
 static void skdebug(const char *func, const char *fmt, ...)  static void skdebug(const char *func, const char *fmt, ...)
     __attribute__((__format__ (printf, 2, 3)));      __attribute__((__format__ (printf, 2, 3)));
   
Line 277 
Line 290 
  * but the API expects a SEC1 octet string.   * but the API expects a SEC1 octet string.
  */   */
 static int  static int
 pack_public_key_ecdsa(fido_cred_t *cred, struct sk_enroll_response *response)  pack_public_key_ecdsa(const fido_cred_t *cred,
       struct sk_enroll_response *response)
 {  {
         const uint8_t *ptr;          const uint8_t *ptr;
         BIGNUM *x = NULL, *y = NULL;          BIGNUM *x = NULL, *y = NULL;
Line 347 
Line 361 
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
   
 static int  static int
 pack_public_key_ed25519(fido_cred_t *cred, struct sk_enroll_response *response)  pack_public_key_ed25519(const fido_cred_t *cred,
       struct sk_enroll_response *response)
 {  {
         const uint8_t *ptr;          const uint8_t *ptr;
         size_t len;          size_t len;
Line 378 
Line 393 
 }  }
   
 static int  static int
 pack_public_key(int alg, fido_cred_t *cred, struct sk_enroll_response *response)  pack_public_key(int alg, const fido_cred_t *cred,
       struct sk_enroll_response *response)
 {  {
         switch(alg) {          switch(alg) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
Line 711 
Line 727 
         }          }
         return ret;          return ret;
 }  }
   
   static int
   read_rks(const char *devpath, const char *pin,
       struct sk_resident_key ***rksp, size_t *nrksp)
   {
           int r = -1;
           fido_dev_t *dev = NULL;
           fido_credman_metadata_t *metadata = NULL;
           fido_credman_rp_t *rp = NULL;
           fido_credman_rk_t *rk = NULL;
           size_t i, j, nrp, nrk;
           const fido_cred_t *cred;
           struct sk_resident_key *srk = NULL, **tmp;
   
           if ((dev = fido_dev_new()) == NULL) {
                   skdebug(__func__, "fido_dev_new failed");
                   return -1;
           }
           if ((r = fido_dev_open(dev, devpath)) != FIDO_OK) {
                   skdebug(__func__, "fido_dev_open %s failed: %s",
                       devpath, fido_strerr(r));
                   fido_dev_free(&dev);
                   return -1;
           }
           if ((metadata = fido_credman_metadata_new()) == NULL) {
                   r = -1;
                   skdebug(__func__, "alloc failed");
                   goto out;
           }
   
           if ((r = fido_credman_get_dev_metadata(dev, metadata, pin)) != 0) {
                   if (r == FIDO_ERR_INVALID_COMMAND) {
                           skdebug(__func__, "device %s does not support "
                               "resident keys", devpath);
                           r = 0;
                           goto out;
                   }
                   skdebug(__func__, "get metadata for %s failed: %s",
                       devpath, fido_strerr(r));
                   goto out;
           }
           skdebug(__func__, "existing %llu, remaining %llu",
               (unsigned long long)fido_credman_rk_existing(metadata),
               (unsigned long long)fido_credman_rk_remaining(metadata));
           if ((rp = fido_credman_rp_new()) == NULL) {
                   r = -1;
                   skdebug(__func__, "alloc rp failed");
                   goto out;
           }
           if ((r = fido_credman_get_dev_rp(dev, rp, pin)) != 0) {
                   skdebug(__func__, "get RPs for %s failed: %s",
                       devpath, fido_strerr(r));
                   goto out;
           }
           nrp = fido_credman_rp_count(rp);
           skdebug(__func__, "Device %s has resident keys for %zu RPs",
               devpath, nrp);
   
           /* Iterate over RP IDs that have resident keys */
           for (i = 0; i < nrp; i++) {
                   skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu",
                       i, fido_credman_rp_name(rp, i), fido_credman_rp_id(rp, i),
                       fido_credman_rp_id_hash_len(rp, i));
   
                   /* Skip non-SSH RP IDs */
                   if (strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0)
                           continue;
   
                   fido_credman_rk_free(&rk);
                   if ((rk = fido_credman_rk_new()) == NULL) {
                           r = -1;
                           skdebug(__func__, "alloc rk failed");
                           goto out;
                   }
                   if ((r = fido_credman_get_dev_rk(dev, fido_credman_rp_id(rp, i),
                       rk, pin)) != 0) {
                           skdebug(__func__, "get RKs for %s slot %zu failed: %s",
                               devpath, i, fido_strerr(r));
                           goto out;
                   }
                   nrk = fido_credman_rk_count(rk);
                   skdebug(__func__, "RP \"%s\" has %zu resident keys",
                       fido_credman_rp_id(rp, i), nrk);
   
                   /* Iterate over resident keys for this RP ID */
                   for (j = 0; j < nrk; j++) {
                           if ((cred = fido_credman_rk(rk, j)) == NULL) {
                                   skdebug(__func__, "no RK in slot %zu", j);
                                   continue;
                           }
                           skdebug(__func__, "Device %s RP \"%s\" slot %zu: "
                               "type %d", devpath, fido_credman_rp_id(rp, i), j,
                               fido_cred_type(cred));
   
                           /* build response entry */
                           if ((srk = calloc(1, sizeof(*srk))) == NULL ||
                               (srk->key.key_handle = calloc(1,
                               fido_cred_id_len(cred))) == NULL ||
                               (srk->application = strdup(fido_credman_rp_id(rp,
                               i))) == NULL) {
                                   r = -1;
                                   skdebug(__func__, "alloc sk_resident_key");
                                   goto out;
                           }
   
                           srk->key.key_handle_len = fido_cred_id_len(cred);
                           memcpy(srk->key.key_handle,
                               fido_cred_id_ptr(cred),
                               srk->key.key_handle_len);
   
                           switch (fido_cred_type(cred)) {
                           case COSE_ES256:
                                   srk->alg = SK_ECDSA;
                                   break;
                           case COSE_EDDSA:
                                   srk->alg = SK_ED25519;
                                   break;
                           default:
                                   skdebug(__func__, "unsupported key type %d",
                                       fido_cred_type(cred));
                                   goto out;
                           }
   
                           if ((r = pack_public_key(srk->alg, cred,
                               &srk->key)) != 0) {
                                   skdebug(__func__, "pack public key failed");
                                   goto out;
                           }
                           /* append */
                           if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1,
                               sizeof(**rksp))) == NULL) {
                                   r = -1;
                                   skdebug(__func__, "alloc rksp");
                                   goto out;
                           }
                           *rksp = tmp;
                           (*rksp)[(*nrksp)++] = srk;
                           srk = NULL;
                   }
           }
           /* Success */
           r = 0;
    out:
           if (srk != NULL) {
                   free(srk->application);
                   freezero(srk->key.public_key, srk->key.public_key_len);
                   freezero(srk->key.key_handle, srk->key.key_handle_len);
                   freezero(srk, sizeof(*srk));
           }
           fido_credman_rp_free(&rp);
           fido_credman_rk_free(&rk);
           fido_dev_close(dev);
           fido_dev_free(&dev);
           fido_credman_metadata_free(&metadata);
           return r;
   }
   
   int
   sk_load_resident_keys(const char *pin,
       struct sk_resident_key ***rksp, size_t *nrksp)
   {
           int r = -1;
           fido_dev_info_t *devlist = NULL;
           size_t i, ndev = 0, nrks = 0;
           const fido_dev_info_t *di;
           struct sk_resident_key **rks = NULL;
           *rksp = NULL;
           *nrksp = 0;
   
           if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
                   skdebug(__func__, "fido_dev_info_new failed");
                   goto out;
           }
           if ((r = fido_dev_info_manifest(devlist,
               MAX_FIDO_DEVICES, &ndev)) != FIDO_OK) {
                   skdebug(__func__, "fido_dev_info_manifest failed: %s",
                       fido_strerr(r));
                   goto out;
           }
           for (i = 0; i < ndev; i++) {
                   if ((di = fido_dev_info_ptr(devlist, i)) == NULL) {
                           skdebug(__func__, "no dev info at %zu", i);
                           continue;
                   }
                   skdebug(__func__, "trying %s", fido_dev_info_path(di));
                   if ((r = read_rks(fido_dev_info_path(di), pin,
                       &rks, &nrks)) != 0) {
                           skdebug(__func__, "read_rks failed for %s",
                               fido_dev_info_path(di));
                           continue;
                   }
           }
           /* success */
           r = 0;
           *rksp = rks;
           *nrksp = nrks;
           rks = NULL;
           nrks = 0;
    out:
           for (i = 0; i < nrks; i++) {
                   free(rks[i]->application);
                   freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
                   freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len);
                   freezero(rks[i], sizeof(*rks[i]));
           }
           free(rks);
           fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
           return r;
   }
   

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9