[BACK]Return to sshkey.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / crypto / external / bsd / openssh / dist

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/crypto/external/bsd/openssh/dist/sshkey.c between version 1.14 and 1.14.2.1

version 1.14, 2018/04/06 18:59:00 version 1.14.2.1, 2019/06/10 21:41:12
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
 /* $OpenBSD: sshkey.c,v 1.64 2018/03/22 07:05:48 markus Exp $ */  /* $OpenBSD: sshkey.c,v 1.73 2019/01/21 09:54:11 djm Exp $ */
 /*  /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.   * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.   * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
Line 77  int sshkey_private_serialize_opt(const s
Line 77  int sshkey_private_serialize_opt(const s
     struct sshbuf *buf, enum sshkey_serialize_rep);      struct sshbuf *buf, enum sshkey_serialize_rep);
 static int sshkey_from_blob_internal(struct sshbuf *buf,  static int sshkey_from_blob_internal(struct sshbuf *buf,
     struct sshkey **keyp, int allow_cert);      struct sshkey **keyp, int allow_cert);
   static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
   
 /* Supported key types */  /* Supported key types */
 struct keytype {  struct keytype {
         const char *name;          const char *name;
         const char *shortname;          const char *shortname;
           const char *sigalg;
         int type;          int type;
         int nid;          int nid;
         int cert;          int cert;
         int sigonly;          int sigonly;
 };  };
 static const struct keytype keytypes[] = {  static const struct keytype keytypes[] = {
         { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },          { "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
         { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",          { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
             KEY_ED25519_CERT, 0, 1, 0 },              KEY_ED25519_CERT, 0, 1, 0 },
 #ifdef WITH_XMSS  #ifdef WITH_XMSS
         { "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 },          { "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
         { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT",          { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
             KEY_XMSS_CERT, 0, 1, 0 },              KEY_XMSS_CERT, 0, 1, 0 },
 #endif /* WITH_XMSS */  #endif /* WITH_XMSS */
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },          { "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
         { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },          { "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
         { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 },          { "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
         { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 },          { "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
         { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },          { "ecdsa-sha2-nistp256", "ECDSA", NULL,
         { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 },              KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
         { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 },          { "ecdsa-sha2-nistp384", "ECDSA", NULL,
         { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 },              KEY_ECDSA, NID_secp384r1, 0, 0 },
         { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 },          { "ecdsa-sha2-nistp521", "ECDSA", NULL,
         { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",              KEY_ECDSA, NID_secp521r1, 0, 0 },
           { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
               KEY_RSA_CERT, 0, 1, 0 },
           { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
               "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
           { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
               "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
           { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
               KEY_DSA_CERT, 0, 1, 0 },
           { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
             KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },              KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
         { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",          { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
             KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },              KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
         { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",          { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
             KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },             KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         { NULL, NULL, -1, -1, 0, 0 }          { NULL, NULL, NULL, -1, -1, 0, 0 }
 };  };
   
 const char *  const char *
Line 261  sshkey_names_valid2(const char *names, i
Line 272  sshkey_names_valid2(const char *names, i
 u_int  u_int
 sshkey_size(const struct sshkey *k)  sshkey_size(const struct sshkey *k)
 {  {
   #ifdef WITH_OPENSSL
           const BIGNUM *rsa_n, *dsa_p;
   #endif /* WITH_OPENSSL */
   
         switch (k->type) {          switch (k->type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_RSA:          case KEY_RSA:
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
 #if OPENSSL_VERSION_NUMBER >= 0x10100000UL                  if (k->rsa == NULL)
                 return RSA_bits(k->rsa);                          return 0;
 #else                  RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
                 return BN_num_bits(k->rsa->n);                  return BN_num_bits(rsa_n);
 #endif  
         case KEY_DSA:          case KEY_DSA:
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
 #if OPENSSL_VERSION_NUMBER >= 0x10100000UL                  if (k->dsa == NULL)
                 return DSA_bits(k->dsa);                          return 0;
 #else                  DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL);
                 return BN_num_bits(k->dsa->p);                  return BN_num_bits(dsa_p);
 #endif  
         case KEY_ECDSA:          case KEY_ECDSA:
         case KEY_ECDSA_CERT:          case KEY_ECDSA_CERT:
                 return sshkey_curve_nid_to_bits(k->ecdsa_nid);                  return sshkey_curve_nid_to_bits(k->ecdsa_nid);
Line 426  cert_free(struct sshkey_cert *cert)
Line 439  cert_free(struct sshkey_cert *cert)
                 free(cert->principals[i]);                  free(cert->principals[i]);
         free(cert->principals);          free(cert->principals);
         sshkey_free(cert->signature_key);          sshkey_free(cert->signature_key);
           free(cert->signature_type);
         freezero(cert, sizeof(*cert));          freezero(cert, sizeof(*cert));
 }  }
   
Line 445  cert_new(void)
Line 459  cert_new(void)
         cert->key_id = NULL;          cert->key_id = NULL;
         cert->principals = NULL;          cert->principals = NULL;
         cert->signature_key = NULL;          cert->signature_key = NULL;
           cert->signature_type = NULL;
         return cert;          return cert;
 }  }
   
Line 473  sshkey_new(int type)
Line 488  sshkey_new(int type)
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_RSA:          case KEY_RSA:
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
                 {                  if ((rsa = RSA_new()) == NULL) {
                 BIGNUM *n=NULL, *e=NULL; /* just allocate */  
                 if ((rsa = RSA_new()) == NULL ||  
                     (n = BN_new()) == NULL ||  
                     (e = BN_new()) == NULL) {  
                         BN_free(n);  
                         BN_free(e);  
                         if (rsa != NULL)  
                                 RSA_free(rsa);  
                         free(k);                          free(k);
                         return NULL;                          return NULL;
                 }                  }
                 BN_clear(n); BN_clear(e);  
                 if (RSA_set0_key(rsa, n, e, NULL) == 0)  
                         return NULL;  
                 n = e = NULL;  
                 }  
                 k->rsa = rsa;                  k->rsa = rsa;
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
                 {                  if ((dsa = DSA_new()) == NULL) {
                 BIGNUM *p=NULL, *q=NULL, *g=NULL, *pubkey=NULL; /* just allocate */  
                 if ((dsa = DSA_new()) == NULL ||  
                     (p = BN_new()) == NULL ||  
                     (q = BN_new()) == NULL ||  
                     (g = BN_new()) == NULL ||  
                     (pubkey = BN_new()) == NULL) {  
                         BN_free(p);  
                         BN_free(q);  
                         BN_free(g);  
                         BN_free(pubkey);  
                         if (dsa != NULL)  
                                 DSA_free(dsa);  
                         free(k);                          free(k);
                         return NULL;                          return NULL;
                 }                  }
                 if (DSA_set0_pqg(dsa, p, q, g) == 0) {  
                         BN_free(p); BN_free(q); BN_free(g);  
                         BN_free(pubkey);  
                         return NULL;  
                 }  
                 p = q = g = NULL;  
                 if (DSA_set0_key(dsa, pubkey, NULL) == 0) {  
                         BN_free(pubkey);  
                         return NULL;  
                 }  
                 pubkey = NULL;  
                 }  
                 k->dsa = dsa;                  k->dsa = dsa;
                 break;                  break;
         case KEY_ECDSA:          case KEY_ECDSA:
Line 552  sshkey_new(int type)
Line 530  sshkey_new(int type)
         return k;          return k;
 }  }
   
 int  
 sshkey_add_private(struct sshkey *k)  
 {  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA:  
         case KEY_RSA_CERT:  
 #if OPENSSL_VERSION_NUMBER >= 0x10100000UL  
                 /* Allocate BIGNUM. This is a mess.  
                    For OpenSSL 1.1.x API these shouldn't be mandatory,  
                    but some regression tests for non-NULL pointer of  
                    the data. */  
 #define new_or_dup(bn, nbn) \  
                 if (bn == NULL) { \  
                         if ((nbn = BN_new()) == NULL) \  
                                 return SSH_ERR_ALLOC_FAIL; \  
                 } else { \  
                         /* otherwise use-after-free will occur */ \  
                         if ((nbn = BN_dup(bn)) == NULL) \  
                                 return SSH_ERR_ALLOC_FAIL; \  
                 }  
                 {  
                 const BIGNUM *d, *iqmp, *q, *p, *dmq1, *dmp1; /* allocate if NULL */  
                 BIGNUM *nd, *niqmp, *nq, *np, *ndmq1, *ndmp1;  
   
                 RSA_get0_key(k->rsa, NULL, NULL, &d);  
                 RSA_get0_factors(k->rsa, &p, &q);  
                 RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp);  
   
                 new_or_dup(d, nd);  
                 new_or_dup(iqmp, niqmp);  
                 new_or_dup(q, nq);  
                 new_or_dup(p, np);  
                 new_or_dup(dmq1, ndmq1);  
                 new_or_dup(dmp1, ndmp1);  
   
                 if (RSA_set0_key(k->rsa, NULL, NULL, nd) == 0)  
                         goto error1;  
                 nd = NULL;  
                 if (RSA_set0_factors(k->rsa, np, nq) == 0)  
                         goto error1;  
                 np = nq = NULL;  
                 if (RSA_set0_crt_params(k->rsa, ndmp1, ndmq1, niqmp) == 0) {  
 error1:  
                         BN_free(nd);  
                         BN_free(np); BN_free(nq);  
                         BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp);  
                         return SSH_ERR_LIBCRYPTO_ERROR;  
                 }  
                 ndmp1 = ndmq1 = niqmp = NULL;  
                 }  
 #else  
 #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)  
                 if (bn_maybe_alloc_failed(k->rsa->d) ||  
                     bn_maybe_alloc_failed(k->rsa->iqmp) ||  
                     bn_maybe_alloc_failed(k->rsa->q) ||  
                     bn_maybe_alloc_failed(k->rsa->p) ||  
                     bn_maybe_alloc_failed(k->rsa->dmq1) ||  
                     bn_maybe_alloc_failed(k->rsa->dmp1))  
                         return SSH_ERR_ALLOC_FAIL;  
 #endif  
                 break;  
         case KEY_DSA:  
         case KEY_DSA_CERT:  
 #if OPENSSL_VERSION_NUMBER >= 0x10100000UL  
                 {  
                 const BIGNUM *priv_key;  
                 BIGNUM *npriv_key;  
                 DSA_get0_key(k->dsa, NULL, &priv_key);  
                 new_or_dup(priv_key, npriv_key);  
                 if (DSA_set0_key(k->dsa, NULL, npriv_key) == 0) {  
                         BN_free(npriv_key);  
                         return SSH_ERR_LIBCRYPTO_ERROR;  
                 }  
                 }  
 #else  
                 if (bn_maybe_alloc_failed(k->dsa->priv_key))  
                         return SSH_ERR_ALLOC_FAIL;  
 #endif  
                 break;  
 #undef bn_maybe_alloc_failed  
 #undef new_or_dup  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 /* Cannot do anything until we know the group */  
                 break;  
 #endif /* WITH_OPENSSL */  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
         case KEY_XMSS:  
         case KEY_XMSS_CERT:  
                 /* no need to prealloc */  
                 break;  
         case KEY_UNSPEC:  
                 break;  
         default:  
                 return SSH_ERR_INVALID_ARGUMENT;  
         }  
         return 0;  
 }  
   
 struct sshkey *  
 sshkey_new_private(int type)  
 {  
         struct sshkey *k = sshkey_new(type);  
   
         if (k == NULL)  
                 return NULL;  
         if (sshkey_add_private(k) != 0) {  
                 sshkey_free(k);  
                 return NULL;  
         }  
         return k;  
 }  
   
 void  void
 sshkey_free(struct sshkey *k)  sshkey_free(struct sshkey *k)
 {  {
Line 745  sshkey_equal_public(const struct sshkey 
Line 608  sshkey_equal_public(const struct sshkey 
 {  {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         BN_CTX *bnctx;          BN_CTX *bnctx;
           const BIGNUM *rsa_e_a, *rsa_n_a;
           const BIGNUM *rsa_e_b, *rsa_n_b;
           const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a;
           const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
   
         if (a == NULL || b == NULL ||          if (a == NULL || b == NULL ||
Line 755  sshkey_equal_public(const struct sshkey 
Line 622  sshkey_equal_public(const struct sshkey 
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
         case KEY_RSA:          case KEY_RSA:
                 {                  if (a->rsa == NULL || b->rsa == NULL)
                 const BIGNUM *a_e, *b_e, *a_n, *b_n;                          return 0;
                 const BIGNUM *a_d, *b_d;                  RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
                 if (a->rsa == NULL) return 0;                  RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
                 if (b->rsa == NULL) return 0;                  return BN_cmp(rsa_e_a, rsa_e_b) == 0 &&
                 RSA_get0_key(a->rsa, &a_n, &a_e, &a_d);                      BN_cmp(rsa_n_a, rsa_n_b) == 0;
                 RSA_get0_key(b->rsa, &b_n, &b_e, &b_d);  
                 return  
                     BN_cmp(a_e, b_e) == 0 &&  
                     BN_cmp(a_n, b_n) == 0;  
                 }  
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
         case KEY_DSA:          case KEY_DSA:
                 {                  if (a->dsa == NULL || b->dsa == NULL)
                 const BIGNUM *a_p, *a_q, *a_g, *a_pub_key;                          return 0;
                 const BIGNUM *b_p, *b_q, *b_g, *b_pub_key;                  DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a);
                 if (a->dsa == NULL) return 0;                  DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b);
                 if (b->dsa == NULL) return 0;                  DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL);
                 DSA_get0_pqg(a->dsa, &a_p, &a_q, &a_g);                  DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL);
                 DSA_get0_pqg(b->dsa, &b_p, &b_q, &b_g);                  return BN_cmp(dsa_p_a, dsa_p_b) == 0 &&
                 DSA_get0_key(a->dsa, &a_pub_key, NULL);                      BN_cmp(dsa_q_a, dsa_q_b) == 0 &&
                 DSA_get0_key(b->dsa, &b_pub_key, NULL);                      BN_cmp(dsa_g_a, dsa_g_b) == 0 &&
                 return                      BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0;
                     BN_cmp(a_p, b_p) == 0 &&  
                     BN_cmp(a_q, b_q) == 0 &&  
                     BN_cmp(a_g, b_g) == 0 &&  
                     BN_cmp(a_pub_key, b_pub_key) == 0;  
                 }  
         case KEY_ECDSA_CERT:          case KEY_ECDSA_CERT:
         case KEY_ECDSA:          case KEY_ECDSA:
                 if (a->ecdsa == NULL || b->ecdsa == NULL ||                  if (a->ecdsa == NULL || b->ecdsa == NULL ||
Line 837  to_blob_buf(const struct sshkey *key, st
Line 694  to_blob_buf(const struct sshkey *key, st
 {  {
         int type, ret = SSH_ERR_INTERNAL_ERROR;          int type, ret = SSH_ERR_INTERNAL_ERROR;
         const char *typename;          const char *typename;
   #ifdef WITH_OPENSSL
           const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
   #endif /* WITH_OPENSSL */
   
         if (key == NULL)          if (key == NULL)
                 return SSH_ERR_INVALID_ARGUMENT;                  return SSH_ERR_INVALID_ARGUMENT;
Line 869  to_blob_buf(const struct sshkey *key, st
Line 729  to_blob_buf(const struct sshkey *key, st
         case KEY_DSA:          case KEY_DSA:
                 if (key->dsa == NULL)                  if (key->dsa == NULL)
                         return SSH_ERR_INVALID_ARGUMENT;                          return SSH_ERR_INVALID_ARGUMENT;
                 {                  DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
                 const BIGNUM *p, *q, *g, *pub_key;                  DSA_get0_key(key->dsa, &dsa_pub_key, NULL);
                 DSA_get0_pqg(key->dsa, &p, &q, &g);  
                 DSA_get0_key(key->dsa, &pub_key, NULL);  
                 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||                  if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
                     (ret = sshbuf_put_bignum2(b, p)) != 0 ||                      (ret = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
                     (ret = sshbuf_put_bignum2(b, q)) != 0 ||                      (ret = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
                     (ret = sshbuf_put_bignum2(b, g)) != 0 ||                      (ret = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
                     (ret = sshbuf_put_bignum2(b, pub_key)) != 0)                      (ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
                         return ret;                          return ret;
                 }  
                 break;                  break;
         case KEY_ECDSA:          case KEY_ECDSA:
                 if (key->ecdsa == NULL)                  if (key->ecdsa == NULL)
Line 893  to_blob_buf(const struct sshkey *key, st
Line 750  to_blob_buf(const struct sshkey *key, st
         case KEY_RSA:          case KEY_RSA:
                 if (key->rsa == NULL)                  if (key->rsa == NULL)
                         return SSH_ERR_INVALID_ARGUMENT;                          return SSH_ERR_INVALID_ARGUMENT;
                 {                  RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
                 const BIGNUM *e, *n;  
                 RSA_get0_key(key->rsa, &n, &e, NULL);  
                 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||                  if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
                     (ret = sshbuf_put_bignum2(b, e)) != 0 ||                      (ret = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
                     (ret = sshbuf_put_bignum2(b, n)) != 0)                      (ret = sshbuf_put_bignum2(b, rsa_n)) != 0)
                         return ret;                          return ret;
                 }  
                 break;                  break;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
Line 1641  dsa_generate_private_key(u_int bits, DSA
Line 1495  dsa_generate_private_key(u_int bits, DSA
 int  int
 sshkey_ecdsa_key_to_nid(EC_KEY *k)  sshkey_ecdsa_key_to_nid(EC_KEY *k)
 {  {
         EC_GROUP *eg;          EC_GROUP *eg = NULL;            /* XXXGCC: unneeded init */
         int nids[] = {          int nids[] = {
                 NID_X9_62_prime256v1,                  NID_X9_62_prime256v1,
                 NID_secp384r1,                  NID_secp384r1,
Line 1770  sshkey_cert_copy(const struct sshkey *fr
Line 1624  sshkey_cert_copy(const struct sshkey *fr
         u_int i;          u_int i;
         const struct sshkey_cert *from;          const struct sshkey_cert *from;
         struct sshkey_cert *to;          struct sshkey_cert *to;
         int ret = SSH_ERR_INTERNAL_ERROR;          int r = SSH_ERR_INTERNAL_ERROR;
   
         if (to_key->cert != NULL) {  
                 cert_free(to_key->cert);  
                 to_key->cert = NULL;  
         }  
   
         if ((from = from_key->cert) == NULL)          if (to_key == NULL || (from = from_key->cert) == NULL)
                 return SSH_ERR_INVALID_ARGUMENT;                  return SSH_ERR_INVALID_ARGUMENT;
   
         if ((to = to_key->cert = cert_new()) == NULL)          if ((to = cert_new()) == NULL)
                 return SSH_ERR_ALLOC_FAIL;                  return SSH_ERR_ALLOC_FAIL;
   
         if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 ||          if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
             (ret = sshbuf_putb(to->critical, from->critical)) != 0 ||              (r = sshbuf_putb(to->critical, from->critical)) != 0 ||
             (ret = sshbuf_putb(to->extensions, from->extensions)) != 0)              (r = sshbuf_putb(to->extensions, from->extensions)) != 0)
                 return ret;                  goto out;
   
         to->serial = from->serial;          to->serial = from->serial;
         to->type = from->type;          to->type = from->type;
         if (from->key_id == NULL)          if (from->key_id == NULL)
                 to->key_id = NULL;                  to->key_id = NULL;
         else if ((to->key_id = strdup(from->key_id)) == NULL)          else if ((to->key_id = strdup(from->key_id)) == NULL) {
                 return SSH_ERR_ALLOC_FAIL;                  r = SSH_ERR_ALLOC_FAIL;
                   goto out;
           }
         to->valid_after = from->valid_after;          to->valid_after = from->valid_after;
         to->valid_before = from->valid_before;          to->valid_before = from->valid_before;
         if (from->signature_key == NULL)          if (from->signature_key == NULL)
                 to->signature_key = NULL;                  to->signature_key = NULL;
         else if ((ret = sshkey_from_private(from->signature_key,          else if ((r = sshkey_from_private(from->signature_key,
             &to->signature_key)) != 0)              &to->signature_key)) != 0)
                 return ret;                  goto out;
           if (from->signature_type != NULL &&
         if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS)              (to->signature_type = strdup(from->signature_type)) == NULL) {
                 return SSH_ERR_INVALID_ARGUMENT;                  r = SSH_ERR_ALLOC_FAIL;
                   goto out;
           }
           if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
                   r = SSH_ERR_INVALID_ARGUMENT;
                   goto out;
           }
         if (from->nprincipals > 0) {          if (from->nprincipals > 0) {
                 if ((to->principals = calloc(from->nprincipals,                  if ((to->principals = calloc(from->nprincipals,
                     sizeof(*to->principals))) == NULL)                      sizeof(*to->principals))) == NULL) {
                         return SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                           goto out;
                   }
                 for (i = 0; i < from->nprincipals; i++) {                  for (i = 0; i < from->nprincipals; i++) {
                         to->principals[i] = strdup(from->principals[i]);                          to->principals[i] = strdup(from->principals[i]);
                         if (to->principals[i] == NULL) {                          if (to->principals[i] == NULL) {
                                 to->nprincipals = i;                                  to->nprincipals = i;
                                 return SSH_ERR_ALLOC_FAIL;                                  r = SSH_ERR_ALLOC_FAIL;
                                   goto out;
                         }                          }
                 }                  }
         }          }
         to->nprincipals = from->nprincipals;          to->nprincipals = from->nprincipals;
         return 0;  
           /* success */
           cert_free(to_key->cert);
           to_key->cert = to;
           to = NULL;
           r = 0;
    out:
           cert_free(to);
           return r;
 }  }
   
 int  int
 sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)  sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
 {  {
         struct sshkey *n = NULL;          struct sshkey *n = NULL;
         int ret = SSH_ERR_INTERNAL_ERROR;          int r = SSH_ERR_INTERNAL_ERROR;
   #ifdef WITH_OPENSSL
           const BIGNUM *rsa_n, *rsa_e;
           BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
           const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
           BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL;
           BIGNUM *dsa_pub_key_dup = NULL;
   #endif /* WITH_OPENSSL */
   
         *pkp = NULL;          *pkp = NULL;
         switch (k->type) {          switch (k->type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_DSA:          case KEY_DSA:
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
                 if ((n = sshkey_new(k->type)) == NULL)                  if ((n = sshkey_new(k->type)) == NULL) {
                         return SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                 {                          goto out;
                 const BIGNUM *p, *q, *g, *pub_key, *priv_key;  
                 BIGNUM *cp=NULL, *cq=NULL, *cg=NULL, *cpub_key=NULL;  
                 DSA_get0_pqg(k->dsa, &p, &q, &g);  
                 DSA_get0_key(k->dsa, &pub_key, &priv_key);  
                 if ((cp = BN_dup(p)) == NULL ||  
                     (cq = BN_dup(q)) == NULL ||  
                     (cg = BN_dup(g)) == NULL ||  
                     (cpub_key = BN_dup(pub_key)) == NULL) {  
                         BN_free(cp); BN_free(cq); BN_free(cg);  
                         BN_free(cpub_key);  
                         sshkey_free(n);  
                         return SSH_ERR_ALLOC_FAIL;  
                 }  
                 if (DSA_set0_pqg(n->dsa, cp, cq, cg) == 0)  
                         goto error1;  
                 cp = cq = cg = NULL;  
                 if (DSA_set0_key(n->dsa, cpub_key, NULL) == 0) {  
 error1:  
                         BN_free(cp); BN_free(cq); BN_free(cg);  
                         BN_free(cpub_key);  
                         sshkey_free(n);  
                         return SSH_ERR_LIBCRYPTO_ERROR;  
                 }                  }
                 cpub_key = NULL;  
                   DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
                   DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
                   if ((dsa_p_dup = BN_dup(dsa_p)) == NULL ||
                       (dsa_q_dup = BN_dup(dsa_q)) == NULL ||
                       (dsa_g_dup = BN_dup(dsa_g)) == NULL ||
                       (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) {
                           r = SSH_ERR_ALLOC_FAIL;
                           goto out;
                 }                  }
                   if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) {
                           r = SSH_ERR_LIBCRYPTO_ERROR;
                           goto out;
                   }
                   dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */
                   if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) {
                           r = SSH_ERR_LIBCRYPTO_ERROR;
                           goto out;
                   }
                   dsa_pub_key_dup = NULL; /* transferred */
   
                 break;                  break;
         case KEY_ECDSA:          case KEY_ECDSA:
         case KEY_ECDSA_CERT:          case KEY_ECDSA_CERT:
                 if ((n = sshkey_new(k->type)) == NULL)                  if ((n = sshkey_new(k->type)) == NULL) {
                         return SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                           goto out;
                   }
                 n->ecdsa_nid = k->ecdsa_nid;                  n->ecdsa_nid = k->ecdsa_nid;
                 n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);                  n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
                 if (n->ecdsa == NULL) {                  if (n->ecdsa == NULL) {
                         sshkey_free(n);                          r = SSH_ERR_ALLOC_FAIL;
                         return SSH_ERR_ALLOC_FAIL;                          goto out;
                 }                  }
                 if (EC_KEY_set_public_key(n->ecdsa,                  if (EC_KEY_set_public_key(n->ecdsa,
                     EC_KEY_get0_public_key(k->ecdsa)) != 1) {                      EC_KEY_get0_public_key(k->ecdsa)) != 1) {
                         sshkey_free(n);                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         return SSH_ERR_LIBCRYPTO_ERROR;                          goto out;
                 }                  }
                 break;                  break;
         case KEY_RSA:          case KEY_RSA:
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
                 if ((n = sshkey_new(k->type)) == NULL)                  if ((n = sshkey_new(k->type)) == NULL) {
                         return SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                 {                          goto out;
                 const BIGNUM *nn, *e, *d;  
                 BIGNUM *cn=NULL, *ce=NULL;  
                 RSA_get0_key(k->rsa, &nn, &e, &d);  
                 if ((cn = BN_dup(nn)) == NULL ||  
                     (ce = BN_dup(e)) == NULL ) {  
                         BN_free(cn); BN_free(ce);  
                         sshkey_free(n);  
                         return SSH_ERR_ALLOC_FAIL;  
                 }  
                 if (RSA_set0_key(n->rsa, cn, ce, NULL) == 0) {  
                         BN_free(cn); BN_free(ce);  
                         sshkey_free(n);  
                         return SSH_ERR_LIBCRYPTO_ERROR;  
                 }                  }
                 cn = ce = NULL;                  RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
                   if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
                       (rsa_e_dup = BN_dup(rsa_e)) == NULL) {
                           r = SSH_ERR_ALLOC_FAIL;
                           goto out;
                   }
                   if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) {
                           r = SSH_ERR_LIBCRYPTO_ERROR;
                           goto out;
                 }                  }
                   rsa_n_dup = rsa_e_dup = NULL; /* transferred */
                 break;                  break;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
                 if ((n = sshkey_new(k->type)) == NULL)                  if ((n = sshkey_new(k->type)) == NULL) {
                         return SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                           goto out;
                   }
                 if (k->ed25519_pk != NULL) {                  if (k->ed25519_pk != NULL) {
                         if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {                          if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
                                 sshkey_free(n);                                  r = SSH_ERR_ALLOC_FAIL;
                                 return SSH_ERR_ALLOC_FAIL;                                  goto out;
                         }                          }
                         memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);                          memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
                 }                  }
Line 1914  error1:
Line 1786  error1:
 #ifdef WITH_XMSS  #ifdef WITH_XMSS
         case KEY_XMSS:          case KEY_XMSS:
         case KEY_XMSS_CERT:          case KEY_XMSS_CERT:
                 if ((n = sshkey_new(k->type)) == NULL)                  if ((n = sshkey_new(k->type)) == NULL) {
                         return SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                 if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) {                          goto out;
                         sshkey_free(n);  
                         return ret;  
                 }                  }
                   if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0)
                           goto out;
                 if (k->xmss_pk != NULL) {                  if (k->xmss_pk != NULL) {
                         size_t pklen = sshkey_xmss_pklen(k);                          size_t pklen = sshkey_xmss_pklen(k);
                         if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {                          if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
                                 sshkey_free(n);                                  r = SSH_ERR_INTERNAL_ERROR;
                                 return SSH_ERR_INTERNAL_ERROR;                                  goto out;
                         }                          }
                         if ((n->xmss_pk = malloc(pklen)) == NULL) {                          if ((n->xmss_pk = malloc(pklen)) == NULL) {
                                 sshkey_free(n);                                  r = SSH_ERR_ALLOC_FAIL;
                                 return SSH_ERR_ALLOC_FAIL;                                  goto out;
                         }                          }
                         memcpy(n->xmss_pk, k->xmss_pk, pklen);                          memcpy(n->xmss_pk, k->xmss_pk, pklen);
                 }                  }
                 break;                  break;
 #endif /* WITH_XMSS */  #endif /* WITH_XMSS */
         default:          default:
                 return SSH_ERR_KEY_TYPE_UNKNOWN;                  r = SSH_ERR_KEY_TYPE_UNKNOWN;
         }                  goto out;
         if (sshkey_is_cert(k)) {  
                 if ((ret = sshkey_cert_copy(k, n)) != 0) {  
                         sshkey_free(n);  
                         return ret;  
                 }  
         }          }
           if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
                   goto out;
           /* success */
         *pkp = n;          *pkp = n;
         return 0;          n = NULL;
           r = 0;
    out:
           sshkey_free(n);
           BN_clear_free(rsa_n_dup);
           BN_clear_free(rsa_e_dup);
           BN_clear_free(dsa_p_dup);
           BN_clear_free(dsa_q_dup);
           BN_clear_free(dsa_g_dup);
           BN_clear_free(dsa_pub_key_dup);
   
           return r;
 }  }
   
 static int  static int
Line 2058  cert_parse(struct sshbuf *b, struct sshk
Line 1939  cert_parse(struct sshbuf *b, struct sshk
         if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,          if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
             sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)              sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
                 goto out;                  goto out;
           if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0)
                   goto out;
   
         /* Success */          /* Success */
         ret = 0;          ret = 0;
Line 2071  cert_parse(struct sshbuf *b, struct sshk
Line 1954  cert_parse(struct sshbuf *b, struct sshk
 }  }
   
 static int  static int
   check_rsa_length(const RSA *rsa)
   {
           const BIGNUM *rsa_n;
   
           RSA_get0_key(rsa, &rsa_n, NULL, NULL);
           if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
                   return SSH_ERR_KEY_LENGTH;
           return 0;
   }
   
   static int
 sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,  sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
     int allow_cert)      int allow_cert)
 {  {
Line 2081  sshkey_from_blob_internal(struct sshbuf 
Line 1975  sshkey_from_blob_internal(struct sshbuf 
         u_char *pk = NULL;          u_char *pk = NULL;
         struct sshbuf *copy;          struct sshbuf *copy;
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         EC_POINT *qq = NULL;          EC_POINT *q = NULL, *qq = NULL;
           BIGNUM *rsa_n = NULL, *rsa_e = NULL;
           BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
   
 #ifdef DEBUG_PK /* XXX */  #ifdef DEBUG_PK /* XXX */
Line 2117  sshkey_from_blob_internal(struct sshbuf 
Line 2013  sshkey_from_blob_internal(struct sshbuf 
                         ret = SSH_ERR_ALLOC_FAIL;                          ret = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
                 {                  if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
                 BIGNUM *e=NULL, *n=NULL;                      sshbuf_get_bignum2(b, &rsa_n) != 0) {
                 if ((e = BN_new()) == NULL ||  
                     (n = BN_new()) == NULL ) {  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         BN_free(e); BN_free(n);  
                         goto out;  
                 }  
                 if (sshbuf_get_bignum2(b, e) != 0 ||  
                     sshbuf_get_bignum2(b, n) != 0) {  
                         ret = SSH_ERR_INVALID_FORMAT;                          ret = SSH_ERR_INVALID_FORMAT;
                         BN_free(e); BN_free(n);  
                         goto out;                          goto out;
                 }                  }
                 if (RSA_set0_key(key->rsa, n, e, NULL) == 0) {                  if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
                         BN_free(e); BN_free(n);                          ret = SSH_ERR_LIBCRYPTO_ERROR;
                         return SSH_ERR_LIBCRYPTO_ERROR;  
                 }  
                 n = e = NULL;  
                 }  
                 if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {  
                         ret = SSH_ERR_KEY_LENGTH;  
                         goto out;                          goto out;
                 }                  }
                   rsa_n = rsa_e = NULL; /* transferred */
                   if ((ret = check_rsa_length(key->rsa)) != 0)
                           goto out;
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                 RSA_print_fp(stderr, key->rsa, 8);                  RSA_print_fp(stderr, key->rsa, 8);
 #endif  #endif
Line 2157  sshkey_from_blob_internal(struct sshbuf 
Line 2041  sshkey_from_blob_internal(struct sshbuf 
                         ret = SSH_ERR_ALLOC_FAIL;                          ret = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
                 {                  if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
                 BIGNUM *p=NULL, *q=NULL, *g=NULL, *pub_key=NULL;                      sshbuf_get_bignum2(b, &dsa_q) != 0 ||
                 if ((p = BN_new()) == NULL ||                      sshbuf_get_bignum2(b, &dsa_g) != 0 ||
                     (q = BN_new()) == NULL ||                      sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
                     (g = BN_new()) == NULL ||  
                     (pub_key = BN_new()) == NULL) {  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         goto error1;  
                 }  
                 if (sshbuf_get_bignum2(b, p) != 0 ||  
                     sshbuf_get_bignum2(b, q) != 0 ||  
                     sshbuf_get_bignum2(b, g) != 0 ||  
                     sshbuf_get_bignum2(b, pub_key) != 0) {  
                         ret = SSH_ERR_INVALID_FORMAT;                          ret = SSH_ERR_INVALID_FORMAT;
                         goto error1;                          goto out;
                 }                  }
                 if (DSA_set0_pqg(key->dsa, p, q, g) == 0) {                  if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
                         ret = SSH_ERR_LIBCRYPTO_ERROR;                          ret = SSH_ERR_LIBCRYPTO_ERROR;
                         goto error1;                          goto out;
                 }                  }
                 p = q = g = NULL;                  dsa_p = dsa_q = dsa_g = NULL; /* transferred */
                 if (DSA_set0_key(key->dsa, pub_key, NULL) == 0) {                  if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
                         ret = SSH_ERR_LIBCRYPTO_ERROR;                          ret = SSH_ERR_LIBCRYPTO_ERROR;
 error1:  
                         BN_free(p); BN_free(q); BN_free(g);  
                         BN_free(pub_key);  
                         goto out;                          goto out;
                 }                  }
                 pub_key = NULL;                  dsa_pub_key = NULL; /* transferred */
                 }  
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                 DSA_print_fp(stderr, key->dsa, 8);                  DSA_print_fp(stderr, key->dsa, 8);
 #endif  #endif
Line 2319  error1:
Line 2190  error1:
         free(curve);          free(curve);
         free(pk);          free(pk);
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         if (qq != NULL)          EC_POINT_free(q);
                 EC_POINT_free(qq);          BN_clear_free(rsa_n);
           BN_clear_free(rsa_e);
           BN_clear_free(dsa_p);
           BN_clear_free(dsa_q);
           BN_clear_free(dsa_g);
           BN_clear_free(dsa_pub_key);
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         return ret;          return ret;
 }  }
Line 2357  sshkey_froms(struct sshbuf *buf, struct 
Line 2233  sshkey_froms(struct sshbuf *buf, struct 
         return r;          return r;
 }  }
   
 int  static int
 sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep)  get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
 {  {
         int r;          int r;
         struct sshbuf *b = NULL;          struct sshbuf *b = NULL;
Line 2382  sshkey_sigtype(const u_char *sig, size_t
Line 2258  sshkey_sigtype(const u_char *sig, size_t
         return r;          return r;
 }  }
   
   /*
    *
    * Checks whether a certificate's signature type is allowed.
    * Returns 0 (success) if the certificate signature type appears in the
    * "allowed" pattern-list, or the key is not a certificate to begin with.
    * Otherwise returns a ssherr.h code.
    */
   int
   sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
   {
           if (key == NULL || allowed == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
           if (!sshkey_type_is_cert(key->type))
                   return 0;
           if (key->cert == NULL || key->cert->signature_type == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
           if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
                   return SSH_ERR_SIGN_ALG_UNSUPPORTED;
           return 0;
   }
   
   /*
    * Returns the expected signature algorithm for a given public key algorithm.
    */
   const char *
   sshkey_sigalg_by_name(const char *name)
   {
           const struct keytype *kt;
   
           for (kt = keytypes; kt->type != -1; kt++) {
                   if (strcmp(kt->name, name) != 0)
                           continue;
                   if (kt->sigalg != NULL)
                           return kt->sigalg;
                   if (!kt->cert)
                           return kt->name;
                   return sshkey_ssh_name_from_type_nid(
                       sshkey_type_plain(kt->type), kt->nid);
           }
           return NULL;
   }
   
   /*
    * Verifies that the signature algorithm appearing inside the signature blob
    * matches that which was requested.
    */
   int
   sshkey_check_sigtype(const u_char *sig, size_t siglen,
       const char *requested_alg)
   {
           const char *expected_alg;
           char *sigtype = NULL;
           int r;
   
           if (requested_alg == NULL)
                   return 0;
           if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
           if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
                   return r;
           r = strcmp(expected_alg, sigtype) == 0;
           free(sigtype);
           return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
   }
   
 int  int
 sshkey_sign(const struct sshkey *key,  sshkey_sign(const struct sshkey *key,
     u_char **sigp, size_t *lenp,      u_char **sigp, size_t *lenp,
Line 2454  sshkey_verify(const struct sshkey *key,
Line 2395  sshkey_verify(const struct sshkey *key,
         }          }
 }  }
   
 /* Converts a private to a public key */  
 int  
 sshkey_demote(const struct sshkey *k, struct sshkey **dkp)  
 {  
         struct sshkey *pk;  
         int ret = SSH_ERR_INTERNAL_ERROR;  
   
         *dkp = NULL;  
         if ((pk = calloc(1, sizeof(*pk))) == NULL)  
                 return SSH_ERR_ALLOC_FAIL;  
         pk->type = k->type;  
         pk->flags = k->flags;  
         pk->ecdsa_nid = k->ecdsa_nid;  
         pk->dsa = NULL;  
         pk->ecdsa = NULL;  
         pk->rsa = NULL;  
         pk->ed25519_pk = NULL;  
         pk->ed25519_sk = NULL;  
         pk->xmss_pk = NULL;  
         pk->xmss_sk = NULL;  
   
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA_CERT:  
                 if ((ret = sshkey_cert_copy(k, pk)) != 0)  
                         goto fail;  
                 /* FALLTHROUGH */  
         case KEY_RSA:  
                 if ((pk->rsa = RSA_new()) == NULL ){  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         goto fail;  
                         }  
                 {  
                 const BIGNUM *ke, *kn;  
                 BIGNUM *pke=NULL, *pkn=NULL;  
                 RSA_get0_key(k->rsa, &kn, &ke, NULL);  
                  if ((pke = BN_dup(ke)) == NULL ||  
                      (pkn = BN_dup(kn)) == NULL) {  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         BN_free(pke); BN_free(pkn);  
                         goto fail;  
                         }  
                 if (RSA_set0_key(pk->rsa, pkn, pke, NULL) == 0) {  
                         ret = SSH_ERR_LIBCRYPTO_ERROR;  
                         BN_free(pke); BN_free(pkn);  
                         goto fail;  
                 }  
                 pkn = pke = NULL;  
                 }  
                 break;  
         case KEY_DSA_CERT:  
                 if ((ret = sshkey_cert_copy(k, pk)) != 0)  
                         goto fail;  
                 /* FALLTHROUGH */  
         case KEY_DSA:  
                 if ((pk->dsa = DSA_new()) == NULL ) {  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         goto fail;  
                 }  
                 {  
                 const BIGNUM *kp, *kq, *kg, *kpub_key;  
                 BIGNUM *pkp=NULL, *pkq=NULL, *pkg=NULL, *pkpub_key=NULL;  
                 DSA_get0_pqg(k->dsa, &kp, &kq, &kg);  
                 DSA_get0_key(k->dsa, &kpub_key, NULL);  
                 if ((pkp = BN_dup(kp)) == NULL ||  
                     (pkq = BN_dup(kq)) == NULL ||  
                     (pkg = BN_dup(kg)) == NULL ||  
                     (pkpub_key = BN_dup(kpub_key)) == NULL) {  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         goto error1;  
                 }  
                 if (DSA_set0_pqg(pk->dsa, pkp, pkq, pkg) == 0) {  
                         ret = SSH_ERR_LIBCRYPTO_ERROR;  
                         goto error1;  
                 }  
                 pkp = pkq = pkg = NULL;  
                 if (DSA_set0_key(pk->dsa, pkpub_key, NULL) == 0) {  
                         ret = SSH_ERR_LIBCRYPTO_ERROR;  
 error1:  
                         BN_free(pkp); BN_free(pkq); BN_free(pkg);  
                         BN_free(pkpub_key);  
                         goto fail;  
                 }  
                 pkpub_key = NULL;  
                 }  
                 break;  
         case KEY_ECDSA_CERT:  
                 if ((ret = sshkey_cert_copy(k, pk)) != 0)  
                         goto fail;  
                 /* FALLTHROUGH */  
         case KEY_ECDSA:  
                 pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid);  
                 if (pk->ecdsa == NULL) {  
                         ret = SSH_ERR_ALLOC_FAIL;  
                         goto fail;  
                 }  
                 if (EC_KEY_set_public_key(pk->ecdsa,  
                     EC_KEY_get0_public_key(k->ecdsa)) != 1) {  
                         ret = SSH_ERR_LIBCRYPTO_ERROR;  
                         goto fail;  
                 }  
                 break;  
 #endif /* WITH_OPENSSL */  
         case KEY_ED25519_CERT:  
                 if ((ret = sshkey_cert_copy(k, pk)) != 0)  
                         goto fail;  
                 /* FALLTHROUGH */  
         case KEY_ED25519:  
                 if (k->ed25519_pk != NULL) {  
                         if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {  
                                 ret = SSH_ERR_ALLOC_FAIL;  
                                 goto fail;  
                         }  
                         memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);  
                 }  
                 break;  
 #ifdef WITH_XMSS  
         case KEY_XMSS_CERT:  
                 if ((ret = sshkey_cert_copy(k, pk)) != 0)  
                         goto fail;  
                 /* FALLTHROUGH */  
         case KEY_XMSS:  
                 if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0)  
                         goto fail;  
                 if (k->xmss_pk != NULL) {  
                         size_t pklen = sshkey_xmss_pklen(k);  
   
                         if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) {  
                                 ret = SSH_ERR_INTERNAL_ERROR;  
                                 goto fail;  
                         }  
                         if ((pk->xmss_pk = malloc(pklen)) == NULL) {  
                                 ret = SSH_ERR_ALLOC_FAIL;  
                                 goto fail;  
                         }  
                         memcpy(pk->xmss_pk, k->xmss_pk, pklen);  
                 }  
                 break;  
 #endif /* WITH_XMSS */  
         default:  
                 ret = SSH_ERR_KEY_TYPE_UNKNOWN;  
  fail:  
                 sshkey_free(pk);  
                 return ret;  
         }  
         *dkp = pk;  
         return 0;  
 }  
   
 /* Convert a plain key to their _CERT equivalent */  /* Convert a plain key to their _CERT equivalent */
 int  int
 sshkey_to_certified(struct sshkey *k)  sshkey_to_certified(struct sshkey *k)
Line 2659  sshkey_certify_custom(struct sshkey *k, 
Line 2451  sshkey_certify_custom(struct sshkey *k, 
         u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];          u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
         size_t i, ca_len, sig_len;          size_t i, ca_len, sig_len;
         int ret = SSH_ERR_INTERNAL_ERROR;          int ret = SSH_ERR_INTERNAL_ERROR;
         struct sshbuf *cert;          struct sshbuf *cert = NULL;
           char *sigtype = NULL;
   #ifdef WITH_OPENSSL
           const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
   #endif /* WITH_OPENSSL */
   
         if (k == NULL || k->cert == NULL ||          if (k == NULL || k->cert == NULL ||
             k->cert->certblob == NULL || ca == NULL)              k->cert->certblob == NULL || ca == NULL)
Line 2669  sshkey_certify_custom(struct sshkey *k, 
Line 2465  sshkey_certify_custom(struct sshkey *k, 
         if (!sshkey_type_is_valid_ca(ca->type))          if (!sshkey_type_is_valid_ca(ca->type))
                 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;                  return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
   
           /*
            * If no alg specified as argument but a signature_type was set,
            * then prefer that. If both were specified, then they must match.
            */
           if (alg == NULL)
                   alg = k->cert->signature_type;
           else if (k->cert->signature_type != NULL &&
               strcmp(alg, k->cert->signature_type) != 0)
                   return SSH_ERR_INVALID_ARGUMENT;
   
         if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)          if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
                 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;                  return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
   
Line 2686  sshkey_certify_custom(struct sshkey *k, 
Line 2492  sshkey_certify_custom(struct sshkey *k, 
         switch (k->type) {          switch (k->type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
                 {                  DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
                 const BIGNUM *p, *q, *g, *pub_key;                  DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
                 DSA_get0_pqg(k->dsa, &p, &q, &g);                  if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 ||
                 DSA_get0_key(k->dsa, &pub_key, NULL);                      (ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 ||
                 if ((ret = sshbuf_put_bignum2(cert, p)) != 0 ||                      (ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 ||
                     (ret = sshbuf_put_bignum2(cert, q)) != 0 ||                      (ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0)
                     (ret = sshbuf_put_bignum2(cert, g)) != 0 ||  
                     (ret = sshbuf_put_bignum2(cert, pub_key)) != 0) {  
                         goto out;                          goto out;
                 }  
                 }  
                 break;                  break;
         case KEY_ECDSA_CERT:          case KEY_ECDSA_CERT:
                 if ((ret = sshbuf_put_cstring(cert,                  if ((ret = sshbuf_put_cstring(cert,
Line 2707  sshkey_certify_custom(struct sshkey *k, 
Line 2509  sshkey_certify_custom(struct sshkey *k, 
                         goto out;                          goto out;
                 break;                  break;
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
                 {                  RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
                 const BIGNUM *e, *n;                  if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 ||
                 RSA_get0_key(k->rsa, &n, &e, NULL);                      (ret = sshbuf_put_bignum2(cert, rsa_n)) != 0)
                 if (n == NULL || e == NULL ||  
                     (ret = sshbuf_put_bignum2(cert, e)) != 0 ||  
                     (ret = sshbuf_put_bignum2(cert, n)) != 0) {  
                         goto out;                          goto out;
                 }  
                 }  
                 break;                  break;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
Line 2767  sshkey_certify_custom(struct sshkey *k, 
Line 2564  sshkey_certify_custom(struct sshkey *k, 
         if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),          if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
             sshbuf_len(cert), alg, 0, signer_ctx)) != 0)              sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
                 goto out;                  goto out;
           /* Check and update signature_type against what was actually used */
           if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
                   goto out;
           if (alg != NULL && strcmp(alg, sigtype) != 0) {
                   ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
                   goto out;
           }
           if (k->cert->signature_type == NULL) {
                   k->cert->signature_type = sigtype;
                   sigtype = NULL;
           }
         /* Append signature and we are done */          /* Append signature and we are done */
         if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)          if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
                 goto out;                  goto out;
Line 2777  sshkey_certify_custom(struct sshkey *k, 
Line 2584  sshkey_certify_custom(struct sshkey *k, 
                 sshbuf_reset(cert);                  sshbuf_reset(cert);
         free(sig_blob);          free(sig_blob);
         free(ca_blob);          free(ca_blob);
           free(sigtype);
         sshbuf_free(principals);          sshbuf_free(principals);
         return ret;          return ret;
 }  }
Line 2896  sshkey_private_serialize_opt(const struc
Line 2704  sshkey_private_serialize_opt(const struc
     enum sshkey_serialize_rep opts)      enum sshkey_serialize_rep opts)
 {  {
         int r = SSH_ERR_INTERNAL_ERROR;          int r = SSH_ERR_INTERNAL_ERROR;
   #ifdef WITH_OPENSSL
           const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
           const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
   #endif /* WITH_OPENSSL */
   
         if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)          if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
                 goto out;                  goto out;
         switch (key->type) {          switch (key->type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_RSA:          case KEY_RSA:
                 {                  RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
                 const BIGNUM *n, *e, *d, *iqmp, *p, *q;                  RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
                 RSA_get0_key(key->rsa, &n, &e, &d);                  RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
                 RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);                  if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
                 RSA_get0_factors(key->rsa, &p, &q);                      (r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
                 if ((r = sshbuf_put_bignum2(b, n)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
                     (r = sshbuf_put_bignum2(b, e)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
                     (r = sshbuf_put_bignum2(b, d)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
                     (r = sshbuf_put_bignum2(b, iqmp)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
                     (r = sshbuf_put_bignum2(b, p)) != 0 ||  
                     (r = sshbuf_put_bignum2(b, q)) != 0) {  
                         goto out;                          goto out;
                 }  
                 }  
                 break;                  break;
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
                 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {                  if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
                         r = SSH_ERR_INVALID_ARGUMENT;                          r = SSH_ERR_INVALID_ARGUMENT;
                         goto out;                          goto out;
                 }                  }
                 {                  RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
                 const BIGNUM *d, *iqmp, *p, *q;                  RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
                 RSA_get0_key(key->rsa, NULL, NULL, &d);                  RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
                 RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);  
                 RSA_get0_factors(key->rsa, &p, &q);  
                 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||                  if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
                     (r = sshbuf_put_bignum2(b, d)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
                     (r = sshbuf_put_bignum2(b, iqmp)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
                     (r = sshbuf_put_bignum2(b, p)) != 0 ||                      (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
                     (r = sshbuf_put_bignum2(b, q)) != 0) {                      (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
                         goto out;                          goto out;
                 }  
                 }  
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
                 {                  DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
                 const BIGNUM *p, *q, *g, *pub_key, *priv_key;                  DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
                 DSA_get0_pqg(key->dsa, &p, &q, &g);                  if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
                 DSA_get0_key(key->dsa, &pub_key, &priv_key);                      (r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
                 if ((r = sshbuf_put_bignum2(b, p)) != 0 ||                      (r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
                     (r = sshbuf_put_bignum2(b, q)) != 0 ||                      (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 ||
                     (r = sshbuf_put_bignum2(b, g)) != 0 ||                      (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
                     (r = sshbuf_put_bignum2(b, pub_key)) != 0 ||  
                     (r = sshbuf_put_bignum2(b, priv_key)) != 0) {  
                         goto out;                          goto out;
                 }  
                 }  
                 break;                  break;
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
                 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {                  if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
                         r = SSH_ERR_INVALID_ARGUMENT;                          r = SSH_ERR_INVALID_ARGUMENT;
                         goto out;                          goto out;
                 }                  }
                 {                  DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
                 const BIGNUM *priv_key;  
                 DSA_get0_key(key->dsa, NULL, &priv_key);  
                 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||                  if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
                     (r = sshbuf_put_bignum2(b, priv_key)) != 0) {                      (r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
                         goto out;                          goto out;
                 }  
                 }  
                 break;                  break;
         case KEY_ECDSA:          case KEY_ECDSA:
                 if ((r = sshbuf_put_cstring(b,                  if ((r = sshbuf_put_cstring(b,
Line 3060  sshkey_private_deserialize(struct sshbuf
Line 2856  sshkey_private_deserialize(struct sshbuf
         u_char *xmss_pk = NULL, *xmss_sk = NULL;          u_char *xmss_pk = NULL, *xmss_sk = NULL;
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         BIGNUM *exponent = NULL;          BIGNUM *exponent = NULL;
           BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
           BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
           BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
           BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
   
         if (kp != NULL)          if (kp != NULL)
Line 3070  sshkey_private_deserialize(struct sshbuf
Line 2870  sshkey_private_deserialize(struct sshbuf
         switch (type) {          switch (type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_DSA:          case KEY_DSA:
                 if ((k = sshkey_new_private(type)) == NULL) {                  if ((k = sshkey_new(type)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
                 {                  if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
                 BIGNUM *p=NULL, *q=NULL, *g=NULL, *pub_key=NULL, *priv_key=NULL;                      (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
                 if ((p = BN_new()) == NULL ||                      (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
                     (q = BN_new()) == NULL ||                      (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0 ||
                     (g = BN_new()) == NULL ||                      (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
                     (pub_key = BN_new()) == NULL ||                          goto out;
                     (priv_key = BN_new()) == NULL) {                  if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
                         r = SSH_ERR_ALLOC_FAIL;  
                         goto error1;  
                 }  
                 if (p == NULL || q == NULL || g == NULL ||  
                     pub_key == NULL || priv_key == NULL ||  
                     (r = sshbuf_get_bignum2(buf, p)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, q)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, g)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, pub_key)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, priv_key)) != 0) {  
                         goto error1;  
                 }  
                 if (DSA_set0_pqg(k->dsa, p, q, g) == 0) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         goto error1;                          goto out;
                 }                  }
                 p = q = g = NULL;                  dsa_p = dsa_q = dsa_g = NULL; /* transferred */
                 if (DSA_set0_key(k->dsa, pub_key, priv_key) == 0) {                  if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) {
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
 error1:  
                         BN_free(p); BN_free(q); BN_free(g);  
                         BN_free(pub_key); BN_free(priv_key);  
                         goto out;                          goto out;
                 }                  }
                 pub_key = priv_key = NULL;                  dsa_pub_key = dsa_priv_key = NULL; /* transferred */
                 }  
                 break;                  break;
         case KEY_DSA_CERT:          case KEY_DSA_CERT:
                 {                  if ((r = sshkey_froms(buf, &k)) != 0 ||
                 BIGNUM *priv_key=NULL;                      (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
                 if ((priv_key = BN_new()) == NULL) {  
                         r = SSH_ERR_ALLOC_FAIL;  
                         goto out;  
                 }  
                 if (priv_key == NULL ||  
                     (r = sshkey_froms(buf, &k)) != 0 ||  
                     (r = sshkey_add_private(k)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, priv_key)) != 0) {  
                         BN_free(priv_key);  
                         goto out;                          goto out;
                 }                  if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
                 if (DSA_set0_key(k->dsa, NULL, priv_key) == 0) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         BN_free(priv_key);  
                         goto out;                          goto out;
                 }                  }
                 priv_key = NULL;                  dsa_priv_key = NULL; /* transferred */
                 }  
                 break;                  break;
         case KEY_ECDSA:          case KEY_ECDSA:
                 if ((k = sshkey_new_private(type)) == NULL) {                  if ((k = sshkey_new(type)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
Line 3146  error1:
Line 2917  error1:
                         goto out;                          goto out;
                 }                  }
                 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);                  k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
                 if (k->ecdsa  == NULL || (exponent = BN_new()) == NULL) {                  if (k->ecdsa  == NULL) {
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         goto out;                          goto out;
                 }                  }
                 if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||                  if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
                     (r = sshbuf_get_bignum2(buf, exponent)))                      (r = sshbuf_get_bignum2(buf, &exponent)))
                         goto out;                          goto out;
                 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {                  if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
Line 3163  error1:
Line 2934  error1:
                         goto out;                          goto out;
                 break;                  break;
         case KEY_ECDSA_CERT:          case KEY_ECDSA_CERT:
                 if ((exponent = BN_new()) == NULL) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;  
                         goto out;  
                 }  
                 if ((r = sshkey_froms(buf, &k)) != 0 ||                  if ((r = sshkey_froms(buf, &k)) != 0 ||
                     (r = sshkey_add_private(k)) != 0 ||                      (r = sshbuf_get_bignum2(buf, &exponent)) != 0)
                     (r = sshbuf_get_bignum2(buf, exponent)) != 0)  
                         goto out;                          goto out;
                 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {                  if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
Line 3181  error1:
Line 2947  error1:
                         goto out;                          goto out;
                 break;                  break;
         case KEY_RSA:          case KEY_RSA:
                 if ((k = sshkey_new_private(type)) == NULL) {                  if ((k = sshkey_new(type)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
                 {                  if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
                 BIGNUM *n=NULL, *e=NULL, *d=NULL, *iqmp=NULL, *p=NULL, *q=NULL;                      (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0 ||
                 BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy for RSA_set0_crt_params */                      (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
                 if ((n = BN_new()) == NULL ||                      (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
                     (e = BN_new()) == NULL ||                      (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
                     (d = BN_new()) == NULL ||                      (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
                     (iqmp = BN_new()) == NULL ||                          goto out;
                     (p = BN_new()) == NULL ||                  if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) {
                     (q = BN_new()) == NULL ||  
                     (dmp1 = BN_new()) == NULL ||  
                     (dmq1 = BN_new()) == NULL) {  
                         r = SSH_ERR_ALLOC_FAIL;  
                         goto error2;  
                 }  
                 BN_clear(dmp1); BN_clear(dmq1);  
                 if ((r = sshbuf_get_bignum2(buf, n)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, e)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, d)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, iqmp)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, p)) != 0 ||  
                     (r = sshbuf_get_bignum2(buf, q)) != 0) {  
                         goto error2;  
                 }  
                 if (RSA_set0_key(k->rsa, n, e, d) == 0) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;  
                         goto error2;  
                 }  
                 n = e = d = NULL;  
                 /* dmp1,dmpq1 should be non NULL to set iqmp value */  
                 if (RSA_set0_crt_params(k->rsa, dmp1, dmq1, iqmp) == 0) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         goto error2;                          goto out;
                 }                  }
                 dmp1 = dmq1 = iqmp = NULL;                  rsa_n = rsa_e = rsa_d = NULL; /* transferred */
                 if (RSA_set0_factors(k->rsa, p, q) == 0) {                  if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
  error2:  
                         BN_free(n); BN_free(e); BN_free(d);  
                         BN_free(iqmp);  
                         BN_free(p); BN_free(q);  
                         BN_free(dmp1); BN_free(dmq1);  
                         goto out;                          goto out;
                 }                  }
                 p = q = NULL;                  rsa_p = rsa_q = NULL; /* transferred */
                 if ((r = ssh_rsa_generate_additional_parameters(k)) != 0) {                  if ((r = check_rsa_length(k->rsa)) != 0)
                         goto out;                          goto out;
                 }                  if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
                 }  
                 if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {  
                         r = SSH_ERR_KEY_LENGTH;  
                         goto out;                          goto out;
                 }  
                 break;                  break;
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
                 {  
                 BIGNUM *d=NULL, *iqmp=NULL, *p=NULL, *q=NULL;  
                 BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy for RSA_set0_crt_params */  
                 if ((d = BN_new()) == NULL ||  
                     (iqmp = BN_new()) == NULL ||  
                     (p = BN_new()) == NULL ||  
                     (q = BN_new()) == NULL ||  
                     (dmp1 = BN_new()) == NULL ||  
                     (dmq1 = BN_new()) == NULL) {  
                         r = SSH_ERR_ALLOC_FAIL;  
                         goto error3;  
                 }  
                 BN_clear(dmp1); BN_clear(dmq1);  
                 if ((r = sshkey_froms(buf, &k)) != 0 ||                  if ((r = sshkey_froms(buf, &k)) != 0 ||
                     (r = sshkey_add_private(k)) != 0 ||                      (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
                     (r = sshbuf_get_bignum2(buf, d)) != 0 ||                      (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
                     (r = sshbuf_get_bignum2(buf, iqmp)) != 0 ||                      (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
                     (r = sshbuf_get_bignum2(buf, p)) != 0 ||                      (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
                     (r = sshbuf_get_bignum2(buf, q)) != 0) {                          goto out;
                         goto error3;                  if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
                 }  
                 if (RSA_set0_key(k->rsa, NULL, NULL, d) == 0) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;  
                         goto error3;  
                 }  
                 /* dmp1,dmpq1 should be non NULL to set value */  
                 if (RSA_set0_crt_params(k->rsa, dmp1, dmq1, iqmp) == 0) {  
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         goto error3;                          goto out;
                 }                  }
                 dmp1 = dmq1 = iqmp = NULL;                  rsa_d = NULL; /* transferred */
                 if (RSA_set0_factors(k->rsa, p, q) == 0) {                  if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
  error3:  
                         BN_free(d); BN_free(iqmp);  
                         BN_free(p); BN_free(q);  
                         BN_free(dmp1); BN_free(dmq1);  
                         goto out;                          goto out;
                 }                  }
                 p = q = NULL;                  rsa_p = rsa_q = NULL; /* transferred */
                 if ((r = ssh_rsa_generate_additional_parameters(k)) != 0)                  if ((r = check_rsa_length(k->rsa)) != 0)
                         goto out;                          goto out;
                 }                  if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
                 if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {  
                         r = SSH_ERR_KEY_LENGTH;  
                         goto out;                          goto out;
                 }  
                 break;                  break;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
                 if ((k = sshkey_new_private(type)) == NULL) {                  if ((k = sshkey_new(type)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
Line 3306  error1:
Line 3014  error1:
                 break;                  break;
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
                 if ((r = sshkey_froms(buf, &k)) != 0 ||                  if ((r = sshkey_froms(buf, &k)) != 0 ||
                     (r = sshkey_add_private(k)) != 0 ||  
                     (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||                      (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
                     (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)                      (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
                         goto out;                          goto out;
Line 3320  error1:
Line 3027  error1:
                 break;                  break;
 #ifdef WITH_XMSS  #ifdef WITH_XMSS
         case KEY_XMSS:          case KEY_XMSS:
                 if ((k = sshkey_new_private(type)) == NULL) {                  if ((k = sshkey_new(type)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
                         goto out;                          goto out;
                 }                  }
Line 3343  error1:
Line 3050  error1:
                 break;                  break;
         case KEY_XMSS_CERT:          case KEY_XMSS_CERT:
                 if ((r = sshkey_froms(buf, &k)) != 0 ||                  if ((r = sshkey_froms(buf, &k)) != 0 ||
                     (r = sshkey_add_private(k)) != 0 ||  
                     (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||                      (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
                     (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||                      (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
                     (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)                      (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
Line 3392  error1:
Line 3098  error1:
         free(curve);          free(curve);
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         BN_clear_free(exponent);          BN_clear_free(exponent);
           BN_clear_free(dsa_p);
           BN_clear_free(dsa_q);
           BN_clear_free(dsa_g);
           BN_clear_free(dsa_pub_key);
           BN_clear_free(dsa_priv_key);
           BN_clear_free(rsa_n);
           BN_clear_free(rsa_e);
           BN_clear_free(rsa_d);
           BN_clear_free(rsa_p);
           BN_clear_free(rsa_q);
           BN_clear_free(rsa_iqmp);
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         sshkey_free(k);          sshkey_free(k);
         freezero(ed25519_pk, pklen);          freezero(ed25519_pk, pklen);
Line 4044  translate_libcrypto_error(unsigned long 
Line 3761  translate_libcrypto_error(unsigned long 
                 switch (pem_reason) {                  switch (pem_reason) {
                 case EVP_R_BAD_DECRYPT:                  case EVP_R_BAD_DECRYPT:
                         return SSH_ERR_KEY_WRONG_PASSPHRASE;                          return SSH_ERR_KEY_WRONG_PASSPHRASE;
   #ifdef EVP_R_BN_DECODE_ERROR
                   case EVP_R_BN_DECODE_ERROR:
   #endif
                 case EVP_R_DECODE_ERROR:                  case EVP_R_DECODE_ERROR:
 #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR  #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
                 case EVP_R_PRIVATE_KEY_DECODE_ERROR:                  case EVP_R_PRIVATE_KEY_DECODE_ERROR:
Line 4083  convert_libcrypto_error(void)
Line 3803  convert_libcrypto_error(void)
 }  }
   
 static int  static int
   pem_passphrase_cb(char *buf, int size, int rwflag, void *u)
   {
           char *p = (char *)u;
           size_t len;
   
           if (p == NULL || (len = strlen(p)) == 0)
                   return -1;
           if (size < 0 || len > (size_t)size)
                   return -1;
           memcpy(buf, p, len);
           return (int)len;
   }
   
   static int
 sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,  sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
     const char *passphrase, struct sshkey **keyp)      const char *passphrase, struct sshkey **keyp)
 {  {
Line 4103  sshkey_parse_private_pem_fileblob(struct
Line 3837  sshkey_parse_private_pem_fileblob(struct
         }          }
   
         clear_libcrypto_errors();          clear_libcrypto_errors();
         if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,          if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb,
             __UNCONST(passphrase))) == NULL) {              __UNCONST(passphrase))) == NULL) {
                 r = convert_libcrypto_error();                 /*
                   * libcrypto may return various ASN.1 errors when attempting
                   * to parse a key with an incorrect passphrase.
                   * Treat all format errors as "incorrect passphrase" if a
                   * passphrase was supplied.
                   */
                   if (passphrase != NULL && *passphrase != '\0')
                           r = SSH_ERR_KEY_WRONG_PASSPHRASE;
                   else
                           r = convert_libcrypto_error();
                 goto out;                  goto out;
         }          }
         if (EVP_PKEY_id(pk) == EVP_PKEY_RSA &&          if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
             (type == KEY_UNSPEC || type == KEY_RSA)) {              (type == KEY_UNSPEC || type == KEY_RSA)) {
                 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {                  if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
Line 4123  sshkey_parse_private_pem_fileblob(struct
Line 3866  sshkey_parse_private_pem_fileblob(struct
                         r = SSH_ERR_LIBCRYPTO_ERROR;                          r = SSH_ERR_LIBCRYPTO_ERROR;
                         goto out;                          goto out;
                 }                  }
                 if (RSA_bits(prv->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {                  if ((r = check_rsa_length(prv->rsa)) != 0)
                         r = SSH_ERR_KEY_LENGTH;  
                         goto out;                          goto out;
                 }          } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
         } else if (EVP_PKEY_id(pk) == EVP_PKEY_DSA &&  
             (type == KEY_UNSPEC || type == KEY_DSA)) {              (type == KEY_UNSPEC || type == KEY_DSA)) {
                 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {                  if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;
Line 4138  sshkey_parse_private_pem_fileblob(struct
Line 3879  sshkey_parse_private_pem_fileblob(struct
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                 DSA_print_fp(stderr, prv->dsa, 8);                  DSA_print_fp(stderr, prv->dsa, 8);
 #endif  #endif
         } else if (EVP_PKEY_id(pk) == EVP_PKEY_EC &&          } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
             (type == KEY_UNSPEC || type == KEY_ECDSA)) {              (type == KEY_UNSPEC || type == KEY_ECDSA)) {
                 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {                  if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
                         r = SSH_ERR_ALLOC_FAIL;                          r = SSH_ERR_ALLOC_FAIL;

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.14.2.1

CVSweb <webmaster@jp.NetBSD.org>