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

Diff for /src/usr.bin/ssh/ssh-pkcs11.c between version 1.46 and 1.47

version 1.46, 2019/10/01 10:22:53 version 1.47, 2020/01/25 00:03:36
Line 880 
Line 880 
         return (key);          return (key);
 }  }
   
 static struct sshkey *  static int
 pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,  pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
     CK_OBJECT_HANDLE *obj)      CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
 {  {
         CK_ATTRIBUTE             cert_attr[3];          CK_ATTRIBUTE             cert_attr[3];
         CK_SESSION_HANDLE        session;          CK_SESSION_HANDLE        session;
         CK_FUNCTION_LIST        *f = NULL;          CK_FUNCTION_LIST        *f = NULL;
         CK_RV                    rv;          CK_RV                    rv;
         X509                    *x509 = NULL;          X509                    *x509 = NULL;
           X509_NAME               *x509_name = NULL;
         EVP_PKEY                *evp;          EVP_PKEY                *evp;
         RSA                     *rsa = NULL;          RSA                     *rsa = NULL;
         EC_KEY                  *ec = NULL;          EC_KEY                  *ec = NULL;
         struct sshkey           *key = NULL;          struct sshkey           *key = NULL;
         int                      i;          int                      i;
         int                      nid;          int                      nid;
         const u_char             *cp;          const u_char            *cp;
           char                    *subject = NULL;
   
           *keyp = NULL;
           *labelp = NULL;
   
         memset(&cert_attr, 0, sizeof(cert_attr));          memset(&cert_attr, 0, sizeof(cert_attr));
         cert_attr[0].type = CKA_ID;          cert_attr[0].type = CKA_ID;
         cert_attr[1].type = CKA_SUBJECT;          cert_attr[1].type = CKA_SUBJECT;
Line 909 
Line 914 
         rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);          rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
         if (rv != CKR_OK) {          if (rv != CKR_OK) {
                 error("C_GetAttributeValue failed: %lu", rv);                  error("C_GetAttributeValue failed: %lu", rv);
                 return (NULL);                  return -1;
         }          }
   
         /*          /*
Line 920 
Line 925 
         if (cert_attr[1].ulValueLen == 0 ||          if (cert_attr[1].ulValueLen == 0 ||
             cert_attr[2].ulValueLen == 0) {              cert_attr[2].ulValueLen == 0) {
                 error("invalid attribute length");                  error("invalid attribute length");
                 return (NULL);                  return -1;
         }          }
   
         /* allocate buffers for attributes */          /* allocate buffers for attributes */
Line 932 
Line 937 
         rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);          rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
         if (rv != CKR_OK) {          if (rv != CKR_OK) {
                 error("C_GetAttributeValue failed: %lu", rv);                  error("C_GetAttributeValue failed: %lu", rv);
                 goto fail;                  goto out;
         }          }
   
         x509 = X509_new();          /* Decode DER-encoded cert subject */
         if (x509 == NULL) {          cp = cert_attr[2].pValue;
                 error("x509_new failed");          if ((x509_name = d2i_X509_NAME(NULL, &cp,
                 goto fail;              cert_attr[1].ulValueLen)) == NULL ||
         }              (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
                   subject = xstrdup("invalid subject");
           X509_NAME_free(x509_name);
   
         cp = cert_attr[2].pValue;          cp = cert_attr[2].pValue;
         if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) {          if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
                 error("d2i_x509 failed");                  error("d2i_x509 failed");
                 goto fail;                  goto out;
         }          }
   
         evp = X509_get_pubkey(x509);          if ((evp = X509_get_pubkey(x509)) == NULL) {
         if (evp == NULL) {  
                 error("X509_get_pubkey failed");                  error("X509_get_pubkey failed");
                 goto fail;                  goto out;
         }          }
   
         if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {          if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
                 if (EVP_PKEY_get0_RSA(evp) == NULL) {                  if (EVP_PKEY_get0_RSA(evp) == NULL) {
                         error("invalid x509; no rsa key");                          error("invalid x509; no rsa key");
                         goto fail;                          goto out;
                 }                  }
                 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {                  if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
                         error("RSAPublicKey_dup failed");                          error("RSAPublicKey_dup failed");
                         goto fail;                          goto out;
                 }                  }
   
                 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))                  if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
                         goto fail;                          goto out;
   
                 key = sshkey_new(KEY_UNSPEC);                  key = sshkey_new(KEY_UNSPEC);
                 if (key == NULL) {                  if (key == NULL) {
                         error("sshkey_new failed");                          error("sshkey_new failed");
                         goto fail;                          goto out;
                 }                  }
   
                 key->rsa = rsa;                  key->rsa = rsa;
Line 979 
Line 985 
         } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {          } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
                 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {                  if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
                         error("invalid x509; no ec key");                          error("invalid x509; no ec key");
                         goto fail;                          goto out;
                 }                  }
                 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {                  if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
                         error("EC_KEY_dup failed");                          error("EC_KEY_dup failed");
                         goto fail;                          goto out;
                 }                  }
   
                 nid = sshkey_ecdsa_key_to_nid(ec);                  nid = sshkey_ecdsa_key_to_nid(ec);
                 if (nid < 0) {                  if (nid < 0) {
                         error("couldn't get curve nid");                          error("couldn't get curve nid");
                         goto fail;                          goto out;
                 }                  }
   
                 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))                  if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
                         goto fail;                          goto out;
   
                 key = sshkey_new(KEY_UNSPEC);                  key = sshkey_new(KEY_UNSPEC);
                 if (key == NULL) {                  if (key == NULL) {
                         error("sshkey_new failed");                          error("sshkey_new failed");
                         goto fail;                          goto out;
                 }                  }
   
                 key->ecdsa = ec;                  key->ecdsa = ec;
Line 1006 
Line 1012 
                 key->type = KEY_ECDSA;                  key->type = KEY_ECDSA;
                 key->flags |= SSHKEY_FLAG_EXT;                  key->flags |= SSHKEY_FLAG_EXT;
                 ec = NULL;      /* now owned by key */                  ec = NULL;      /* now owned by key */
         } else          } else {
                 error("unknown certificate key type");                  error("unknown certificate key type");
                   goto out;
 fail:          }
    out:
         for (i = 0; i < 3; i++)          for (i = 0; i < 3; i++)
                 free(cert_attr[i].pValue);                  free(cert_attr[i].pValue);
         X509_free(x509);          X509_free(x509);
         RSA_free(rsa);          RSA_free(rsa);
         EC_KEY_free(ec);          EC_KEY_free(ec);
           if (key == NULL) {
         return (key);                  free(subject);
                   return -1;
           }
           /* success */
           *keyp = key;
           *labelp = subject;
           return 0;
 }  }
   
 #if 0  #if 0
Line 1037 
Line 1050 
  */   */
 static int  static int
 pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,  pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
     struct sshkey ***keysp, int *nkeys)      struct sshkey ***keysp, char ***labelsp, int *nkeys)
 {  {
         struct sshkey           *key = NULL;          struct sshkey           *key = NULL;
         CK_OBJECT_CLASS          key_class;          CK_OBJECT_CLASS          key_class;
Line 1048 
Line 1061 
         CK_OBJECT_HANDLE         obj;          CK_OBJECT_HANDLE         obj;
         CK_ULONG                 n = 0;          CK_ULONG                 n = 0;
         int                      ret = -1;          int                      ret = -1;
           char                    *label;
   
         memset(&key_attr, 0, sizeof(key_attr));          memset(&key_attr, 0, sizeof(key_attr));
         memset(&obj, 0, sizeof(obj));          memset(&obj, 0, sizeof(obj));
Line 1089 
Line 1103 
                         goto fail;                          goto fail;
                 }                  }
   
                   key = NULL;
                   label = NULL;
                 switch (ck_cert_type) {                  switch (ck_cert_type) {
                 case CKC_X_509:                  case CKC_X_509:
                         key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj);                          if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
                               &key, &label) != 0) {
                                   error("failed to fetch key");
                                   continue;
                           }
                         break;                          break;
                 default:                  default:
                         /* XXX print key type? */                          error("skipping unsupported certificate type %lu",
                         key = NULL;                              ck_cert_type);
                         error("skipping unsupported certificate type");  
                 }  
   
                 if (key == NULL) {  
                         error("failed to fetch key");  
                         continue;                          continue;
                 }                  }
   
Line 1111 
Line 1126 
                         *keysp = xrecallocarray(*keysp, *nkeys,                          *keysp = xrecallocarray(*keysp, *nkeys,
                             *nkeys + 1, sizeof(struct sshkey *));                              *nkeys + 1, sizeof(struct sshkey *));
                         (*keysp)[*nkeys] = key;                          (*keysp)[*nkeys] = key;
                           if (labelsp != NULL) {
                                   *labelsp = xrecallocarray(*labelsp, *nkeys,
                                       *nkeys + 1, sizeof(char *));
                                   (*labelsp)[*nkeys] = xstrdup((char *)label);
                           }
                         *nkeys = *nkeys + 1;                          *nkeys = *nkeys + 1;
                         debug("have %d keys", *nkeys);                          debug("have %d keys", *nkeys);
                 }                  }
Line 1134 
Line 1154 
  */   */
 static int  static int
 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,  pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
     struct sshkey ***keysp, int *nkeys)      struct sshkey ***keysp, char ***labelsp, int *nkeys)
 {  {
         struct sshkey           *key = NULL;          struct sshkey           *key = NULL;
         CK_OBJECT_CLASS          key_class;          CK_OBJECT_CLASS          key_class;
         CK_ATTRIBUTE             key_attr[1];          CK_ATTRIBUTE             key_attr[2];
         CK_SESSION_HANDLE        session;          CK_SESSION_HANDLE        session;
         CK_FUNCTION_LIST        *f = NULL;          CK_FUNCTION_LIST        *f = NULL;
         CK_RV                    rv;          CK_RV                    rv;
Line 1165 
Line 1185 
   
         while (1) {          while (1) {
                 CK_KEY_TYPE     ck_key_type;                  CK_KEY_TYPE     ck_key_type;
                   CK_UTF8CHAR     label[256];
   
                 rv = f->C_FindObjects(session, &obj, 1, &n);                  rv = f->C_FindObjects(session, &obj, 1, &n);
                 if (rv != CKR_OK) {                  if (rv != CKR_OK) {
Line 1179 
Line 1200 
                 key_attr[0].type = CKA_KEY_TYPE;                  key_attr[0].type = CKA_KEY_TYPE;
                 key_attr[0].pValue = &ck_key_type;                  key_attr[0].pValue = &ck_key_type;
                 key_attr[0].ulValueLen = sizeof(ck_key_type);                  key_attr[0].ulValueLen = sizeof(ck_key_type);
                   key_attr[1].type = CKA_LABEL;
                   key_attr[1].pValue = &label;
                   key_attr[1].ulValueLen = sizeof(label) - 1;
   
                 rv = f->C_GetAttributeValue(session, obj, key_attr, 1);                  rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
                 if (rv != CKR_OK) {                  if (rv != CKR_OK) {
                         error("C_GetAttributeValue failed: %lu", rv);                          error("C_GetAttributeValue failed: %lu", rv);
                         goto fail;                          goto fail;
                 }                  }
   
                   label[key_attr[1].ulValueLen] = '\0';
   
                 switch (ck_key_type) {                  switch (ck_key_type) {
                 case CKK_RSA:                  case CKK_RSA:
                         key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);                          key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
Line 1211 
Line 1237 
                         *keysp = xrecallocarray(*keysp, *nkeys,                          *keysp = xrecallocarray(*keysp, *nkeys,
                             *nkeys + 1, sizeof(struct sshkey *));                              *nkeys + 1, sizeof(struct sshkey *));
                         (*keysp)[*nkeys] = key;                          (*keysp)[*nkeys] = key;
                           if (labelsp != NULL) {
                                   *labelsp = xrecallocarray(*labelsp, *nkeys,
                                       *nkeys + 1, sizeof(char *));
                                   (*labelsp)[*nkeys] = xstrdup((char *)label);
                           }
                         *nkeys = *nkeys + 1;                          *nkeys = *nkeys + 1;
                         debug("have %d keys", *nkeys);                          debug("have %d keys", *nkeys);
                 }                  }
Line 1415 
Line 1446 
  * keyp is provided, fetch keys.   * keyp is provided, fetch keys.
  */   */
 static int  static int
 pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,  pkcs11_register_provider(char *provider_id, char *pin,
       struct sshkey ***keyp, char ***labelsp,
     struct pkcs11_provider **providerp, CK_ULONG user)      struct pkcs11_provider **providerp, CK_ULONG user)
 {  {
         int nkeys, need_finalize = 0;          int nkeys, need_finalize = 0;
Line 1434 
Line 1466 
   
         if (keyp != NULL)          if (keyp != NULL)
                 *keyp = NULL;                  *keyp = NULL;
           if (labelsp != NULL)
                   *labelsp = NULL;
   
         if (pkcs11_provider_lookup(provider_id) != NULL) {          if (pkcs11_provider_lookup(provider_id) != NULL) {
                 debug("%s: provider already registered: %s",                  debug("%s: provider already registered: %s",
Line 1531 
Line 1565 
                 if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||                  if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
                     keyp == NULL)                      keyp == NULL)
                         continue;                          continue;
                 pkcs11_fetch_keys(p, i, keyp, &nkeys);                  pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
                 pkcs11_fetch_certs(p, i, keyp, &nkeys);                  pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
                 if (nkeys == 0 && !p->slotinfo[i].logged_in &&                  if (nkeys == 0 && !p->slotinfo[i].logged_in &&
                     pkcs11_interactive) {                      pkcs11_interactive) {
                         /*                          /*
Line 1544 
Line 1578 
                                 error("login failed");                                  error("login failed");
                                 continue;                                  continue;
                         }                          }
                         pkcs11_fetch_keys(p, i, keyp, &nkeys);                          pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
                         pkcs11_fetch_certs(p, i, keyp, &nkeys);                          pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
                 }                  }
         }          }
   
Line 1576 
Line 1610 
  * fails if provider already exists   * fails if provider already exists
  */   */
 int  int
 pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)  pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
       char ***labelsp)
 {  {
         struct pkcs11_provider *p = NULL;          struct pkcs11_provider *p = NULL;
         int nkeys;          int nkeys;
   
         nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER);          nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
               &p, CKU_USER);
   
         /* no keys found or some other error, de-register provider */          /* no keys found or some other error, de-register provider */
         if (nkeys <= 0 && p != NULL) {          if (nkeys <= 0 && p != NULL) {
Line 1613 
Line 1649 
   
         if ((p = pkcs11_provider_lookup(provider_id)) != NULL)          if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
                 debug("%s: provider \"%s\" available", __func__, provider_id);                  debug("%s: provider \"%s\" available", __func__, provider_id);
         else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p,          else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
             CKU_SO)) < 0) {              &p, CKU_SO)) < 0) {
                 debug("%s: could not register provider %s", __func__,                  debug("%s: could not register provider %s", __func__,
                     provider_id);                      provider_id);
                 goto out;                  goto out;
Line 1685 
Line 1721 
   
         if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {          if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
                 debug("%s: using provider \"%s\"", __func__, provider_id);                  debug("%s: using provider \"%s\"", __func__, provider_id);
         } else if (pkcs11_register_provider(provider_id, pin, NULL, &p,          } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
             CKU_SO) < 0) {              CKU_SO) < 0) {
                 debug("%s: could not register provider %s", __func__,                  debug("%s: could not register provider %s", __func__,
                     provider_id);                      provider_id);

Legend:
Removed from v.1.46  
changed lines
  Added in v.1.47