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

Diff for /src/usr.bin/ssh/Attic/key.c between version 1.82 and 1.83

version 1.82, 2010/01/13 01:10:56 version 1.83, 2010/02/26 20:29:54
Line 48 
Line 48 
 #include "uuencode.h"  #include "uuencode.h"
 #include "buffer.h"  #include "buffer.h"
 #include "log.h"  #include "log.h"
   #include "ssh2.h"
   
   static struct KeyCert *
   cert_new(void)
   {
           struct KeyCert *cert;
   
           cert = xcalloc(1, sizeof(*cert));
           buffer_init(&cert->certblob);
           buffer_init(&cert->constraints);
           cert->key_id = NULL;
           cert->principals = NULL;
           cert->signature_key = NULL;
           return cert;
   }
   
 Key *  Key *
 key_new(int type)  key_new(int type)
 {  {
Line 59 
Line 74 
         k->type = type;          k->type = type;
         k->dsa = NULL;          k->dsa = NULL;
         k->rsa = NULL;          k->rsa = NULL;
           k->cert = NULL;
         switch (k->type) {          switch (k->type) {
         case KEY_RSA1:          case KEY_RSA1:
         case KEY_RSA:          case KEY_RSA:
           case KEY_RSA_CERT:
                 if ((rsa = RSA_new()) == NULL)                  if ((rsa = RSA_new()) == NULL)
                         fatal("key_new: RSA_new failed");                          fatal("key_new: RSA_new failed");
                 if ((rsa->n = BN_new()) == NULL)                  if ((rsa->n = BN_new()) == NULL)
Line 71 
Line 88 
                 k->rsa = rsa;                  k->rsa = rsa;
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
                 if ((dsa = DSA_new()) == NULL)                  if ((dsa = DSA_new()) == NULL)
                         fatal("key_new: DSA_new failed");                          fatal("key_new: DSA_new failed");
                 if ((dsa->p = BN_new()) == NULL)                  if ((dsa->p = BN_new()) == NULL)
Line 89 
Line 107 
                 fatal("key_new: bad key type %d", k->type);                  fatal("key_new: bad key type %d", k->type);
                 break;                  break;
         }          }
   
           if (key_is_cert(k))
                   k->cert = cert_new();
   
         return k;          return k;
 }  }
   
 Key *  void
 key_new_private(int type)  key_add_private(Key *k)
 {  {
         Key *k = key_new(type);  
         switch (k->type) {          switch (k->type) {
         case KEY_RSA1:          case KEY_RSA1:
         case KEY_RSA:          case KEY_RSA:
           case KEY_RSA_CERT:
                 if ((k->rsa->d = BN_new()) == NULL)                  if ((k->rsa->d = BN_new()) == NULL)
                         fatal("key_new_private: BN_new failed");                          fatal("key_new_private: BN_new failed");
                 if ((k->rsa->iqmp = BN_new()) == NULL)                  if ((k->rsa->iqmp = BN_new()) == NULL)
Line 113 
Line 135 
                         fatal("key_new_private: BN_new failed");                          fatal("key_new_private: BN_new failed");
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
                 if ((k->dsa->priv_key = BN_new()) == NULL)                  if ((k->dsa->priv_key = BN_new()) == NULL)
                         fatal("key_new_private: BN_new failed");                          fatal("key_new_private: BN_new failed");
                 break;                  break;
Line 121 
Line 144 
         default:          default:
                 break;                  break;
         }          }
   }
   
   Key *
   key_new_private(int type)
   {
           Key *k = key_new(type);
   
           key_add_private(k);
         return k;          return k;
 }  }
   
   static void
   cert_free(struct KeyCert *cert)
   {
           u_int i;
   
           buffer_free(&cert->certblob);
           buffer_free(&cert->constraints);
           if (cert->key_id != NULL)
                   xfree(cert->key_id);
           for (i = 0; i < cert->nprincipals; i++)
                   xfree(cert->principals[i]);
           if (cert->principals != NULL)
                   xfree(cert->principals);
           if (cert->signature_key != NULL)
                   key_free(cert->signature_key);
   }
   
 void  void
 key_free(Key *k)  key_free(Key *k)
 {  {
Line 132 
Line 180 
         switch (k->type) {          switch (k->type) {
         case KEY_RSA1:          case KEY_RSA1:
         case KEY_RSA:          case KEY_RSA:
           case KEY_RSA_CERT:
                 if (k->rsa != NULL)                  if (k->rsa != NULL)
                         RSA_free(k->rsa);                          RSA_free(k->rsa);
                 k->rsa = NULL;                  k->rsa = NULL;
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
                 if (k->dsa != NULL)                  if (k->dsa != NULL)
                         DSA_free(k->dsa);                          DSA_free(k->dsa);
                 k->dsa = NULL;                  k->dsa = NULL;
Line 147 
Line 197 
                 fatal("key_free: bad key type %d", k->type);                  fatal("key_free: bad key type %d", k->type);
                 break;                  break;
         }          }
           if (key_is_cert(k)) {
                   if (k->cert != NULL)
                           cert_free(k->cert);
                   k->cert = NULL;
           }
   
         xfree(k);          xfree(k);
 }  }
   
   static int
   cert_compare(struct KeyCert *a, struct KeyCert *b)
   {
           if (a == NULL && b == NULL)
                   return 1;
           if (a == NULL || b == NULL)
                   return 0;
           if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
                   return 0;
           if (memcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
               buffer_len(&a->certblob)) != 0)
                   return 0;
           return 1;
   }
   
   /*
    * Compare public portions of key only, allowing comparisons between
    * certificates and plain keys too.
    */
 int  int
 key_equal(const Key *a, const Key *b)  key_equal_public(const Key *a, const Key *b)
 {  {
         if (a == NULL || b == NULL || a->type != b->type)          if (a == NULL || b == NULL ||
               key_type_plain(a->type) != key_type_plain(b->type))
                 return 0;                  return 0;
   
         switch (a->type) {          switch (a->type) {
         case KEY_RSA1:          case KEY_RSA1:
           case KEY_RSA_CERT:
         case KEY_RSA:          case KEY_RSA:
                 return a->rsa != NULL && b->rsa != NULL &&                  return a->rsa != NULL && b->rsa != NULL &&
                     BN_cmp(a->rsa->e, b->rsa->e) == 0 &&                      BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
                     BN_cmp(a->rsa->n, b->rsa->n) == 0;                      BN_cmp(a->rsa->n, b->rsa->n) == 0;
           case KEY_DSA_CERT:
         case KEY_DSA:          case KEY_DSA:
                 return a->dsa != NULL && b->dsa != NULL &&                  return a->dsa != NULL && b->dsa != NULL &&
                     BN_cmp(a->dsa->p, b->dsa->p) == 0 &&                      BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
Line 173 
Line 252 
         /* NOTREACHED */          /* NOTREACHED */
 }  }
   
   int
   key_equal(const Key *a, const Key *b)
   {
           if (a == NULL || b == NULL || a->type != b->type)
                   return 0;
           if (key_is_cert(a)) {
                   if (!cert_compare(a->cert, b->cert))
                           return 0;
           }
           return key_equal_public(a, b);
   }
   
 u_char*  u_char*
 key_fingerprint_raw(const Key *k, enum fp_type dgst_type,  key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
     u_int *dgst_raw_length)  
 {  {
         const EVP_MD *md = NULL;          const EVP_MD *md = NULL;
         EVP_MD_CTX ctx;          EVP_MD_CTX ctx;
         u_char *blob = NULL;          u_char *blob = NULL;
         u_char *retval = NULL;          u_char *retval = NULL;
         u_int len = 0;          u_int len = 0;
         int nlen, elen;          int nlen, elen, otype;
   
         *dgst_raw_length = 0;          *dgst_raw_length = 0;
   
Line 210 
Line 300 
         case KEY_RSA:          case KEY_RSA:
                 key_to_blob(k, &blob, &len);                  key_to_blob(k, &blob, &len);
                 break;                  break;
           case KEY_DSA_CERT:
           case KEY_RSA_CERT:
                   /* We want a fingerprint of the _key_ not of the cert */
                   otype = k->type;
                   k->type = key_type_plain(k->type);
                   key_to_blob(k, &blob, &len);
                   k->type = otype;
                   break;
         case KEY_UNSPEC:          case KEY_UNSPEC:
                 return retval;                  return retval;
         default:          default:
Line 404 
Line 502 
 }  }
   
 char *  char *
 key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)  key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
 {  {
         char *retval = NULL;          char *retval = NULL;
         u_char *dgst_raw;          u_char *dgst_raw;
Line 529 
Line 627 
         case KEY_UNSPEC:          case KEY_UNSPEC:
         case KEY_RSA:          case KEY_RSA:
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
           case KEY_RSA_CERT:
                 space = strchr(cp, ' ');                  space = strchr(cp, ' ');
                 if (space == NULL) {                  if (space == NULL) {
                         debug3("key_read: missing whitespace");                          debug3("key_read: missing whitespace");
Line 573 
Line 673 
                         return -1;                          return -1;
                 }                  }
 /*XXXX*/  /*XXXX*/
                 if (ret->type == KEY_RSA) {                  if (key_is_cert(ret)) {
                           if (!key_is_cert(k)) {
                                   error("key_read: loaded key is not a cert");
                                   key_free(k);
                                   return -1;
                           }
                           if (ret->cert != NULL)
                                   cert_free(ret->cert);
                           ret->cert = k->cert;
                           k->cert = NULL;
                   }
                   if (key_type_plain(ret->type) == KEY_RSA) {
                         if (ret->rsa != NULL)                          if (ret->rsa != NULL)
                                 RSA_free(ret->rsa);                                  RSA_free(ret->rsa);
                         ret->rsa = k->rsa;                          ret->rsa = k->rsa;
                         k->rsa = NULL;                          k->rsa = NULL;
                         success = 1;  
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                         RSA_print_fp(stderr, ret->rsa, 8);                          RSA_print_fp(stderr, ret->rsa, 8);
 #endif  #endif
                 } else {                  }
                   if (key_type_plain(ret->type) == KEY_DSA) {
                         if (ret->dsa != NULL)                          if (ret->dsa != NULL)
                                 DSA_free(ret->dsa);                                  DSA_free(ret->dsa);
                         ret->dsa = k->dsa;                          ret->dsa = k->dsa;
                         k->dsa = NULL;                          k->dsa = NULL;
                         success = 1;  
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                         DSA_print_fp(stderr, ret->dsa, 8);                          DSA_print_fp(stderr, ret->dsa, 8);
 #endif  #endif
                 }                  }
                   success = 1;
 /*XXXX*/  /*XXXX*/
                 key_free(k);                  key_free(k);
                 if (success != 1)                  if (success != 1)
Line 618 
Line 729 
         u_char *blob;          u_char *blob;
         char *uu;          char *uu;
   
         if (key->type == KEY_RSA1 && key->rsa != NULL) {          if (key_is_cert(key)) {
                   if (key->cert == NULL) {
                           error("%s: no cert data", __func__);
                           return 0;
                   }
                   if (buffer_len(&key->cert->certblob) == 0) {
                           error("%s: no signed certificate blob", __func__);
                           return 0;
                   }
           }
   
           switch (key->type) {
           case KEY_RSA1:
                   if (key->rsa == NULL)
                           return 0;
                 /* size of modulus 'n' */                  /* size of modulus 'n' */
                 bits = BN_num_bits(key->rsa->n);                  bits = BN_num_bits(key->rsa->n);
                 fprintf(f, "%u", bits);                  fprintf(f, "%u", bits);
                 if (write_bignum(f, key->rsa->e) &&                  if (write_bignum(f, key->rsa->e) &&
                     write_bignum(f, key->rsa->n)) {                      write_bignum(f, key->rsa->n))
                         success = 1;                          return 1;
                 } else {                  error("key_write: failed for RSA key");
                         error("key_write: failed for RSA key");                  return 0;
                 }          case KEY_DSA:
         } else if ((key->type == KEY_DSA && key->dsa != NULL) ||          case KEY_DSA_CERT:
             (key->type == KEY_RSA && key->rsa != NULL)) {                  if (key->dsa == NULL)
                 key_to_blob(key, &blob, &len);                          return 0;
                 uu = xmalloc(2*len);                  break;
                 n = uuencode(blob, len, uu, 2*len);          case KEY_RSA:
                 if (n > 0) {          case KEY_RSA_CERT:
                         fprintf(f, "%s %s", key_ssh_name(key), uu);                  if (key->rsa == NULL)
                         success = 1;                          return 0;
                 }                  break;
                 xfree(blob);          default:
                 xfree(uu);                  return 0;
         }          }
   
           key_to_blob(key, &blob, &len);
           uu = xmalloc(2*len);
           n = uuencode(blob, len, uu, 2*len);
           if (n > 0) {
                   fprintf(f, "%s %s", key_ssh_name(key), uu);
                   success = 1;
           }
           xfree(blob);
           xfree(uu);
   
         return success;          return success;
 }  }
   
Line 653 
Line 789 
                 return "RSA";                  return "RSA";
         case KEY_DSA:          case KEY_DSA:
                 return "DSA";                  return "DSA";
           case KEY_RSA_CERT:
                   return "RSA-CERT";
           case KEY_DSA_CERT:
                   return "DSA-CERT";
         }          }
         return "unknown";          return "unknown";
 }  }
Line 665 
Line 805 
                 return "ssh-rsa";                  return "ssh-rsa";
         case KEY_DSA:          case KEY_DSA:
                 return "ssh-dss";                  return "ssh-dss";
           case KEY_RSA_CERT:
                   return "ssh-rsa-cert-v00@openssh.com";
           case KEY_DSA_CERT:
                   return "ssh-dss-cert-v00@openssh.com";
         }          }
         return "ssh-unknown";          return "ssh-unknown";
 }  }
Line 675 
Line 819 
         switch (k->type) {          switch (k->type) {
         case KEY_RSA1:          case KEY_RSA1:
         case KEY_RSA:          case KEY_RSA:
           case KEY_RSA_CERT:
                 return BN_num_bits(k->rsa->n);                  return BN_num_bits(k->rsa->n);
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
                 return BN_num_bits(k->dsa->p);                  return BN_num_bits(k->dsa->p);
         }          }
         return 0;          return 0;
Line 719 
Line 865 
         case KEY_RSA1:          case KEY_RSA1:
                 k->rsa = rsa_generate_private_key(bits);                  k->rsa = rsa_generate_private_key(bits);
                 break;                  break;
           case KEY_RSA_CERT:
           case KEY_DSA_CERT:
                   fatal("key_generate: cert keys cannot be generated directly");
         default:          default:
                 fatal("key_generate: unknown type %d", type);                  fatal("key_generate: unknown type %d", type);
         }          }
Line 726 
Line 875 
         return k;          return k;
 }  }
   
   void
   key_cert_copy(const Key *from_key, struct Key *to_key)
   {
           u_int i;
           const struct KeyCert *from;
           struct KeyCert *to;
   
           if (to_key->cert != NULL) {
                   cert_free(to_key->cert);
                   to_key->cert = NULL;
           }
   
           if ((from = from_key->cert) == NULL)
                   return;
   
           to = to_key->cert = cert_new();
   
           buffer_append(&to->certblob, buffer_ptr(&from->certblob),
               buffer_len(&from->certblob));
   
           buffer_append(&to->constraints, buffer_ptr(&from->constraints),
               buffer_len(&from->constraints));
   
           to->type = from->type;
           to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
           to->valid_after = from->valid_after;
           to->valid_before = from->valid_before;
           to->signature_key = from->signature_key == NULL ?
               NULL : key_from_private(from->signature_key);
   
           to->nprincipals = from->nprincipals;
           if (to->nprincipals > CERT_MAX_PRINCIPALS)
                   fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
                       __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
           if (to->nprincipals > 0) {
                   to->principals = xcalloc(from->nprincipals,
                       sizeof(*to->principals));
                   for (i = 0; i < to->nprincipals; i++)
                           to->principals[i] = xstrdup(from->principals[i]);
           }
   }
   
 Key *  Key *
 key_from_private(const Key *k)  key_from_private(const Key *k)
 {  {
         Key *n = NULL;          Key *n = NULL;
         switch (k->type) {          switch (k->type) {
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
                 n = key_new(k->type);                  n = key_new(k->type);
                 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||                  if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
                     (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||                      (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
Line 741 
Line 933 
                 break;                  break;
         case KEY_RSA:          case KEY_RSA:
         case KEY_RSA1:          case KEY_RSA1:
           case KEY_RSA_CERT:
                 n = key_new(k->type);                  n = key_new(k->type);
                 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||                  if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
                     (BN_copy(n->rsa->e, k->rsa->e) == NULL))                      (BN_copy(n->rsa->e, k->rsa->e) == NULL))
Line 750 
Line 943 
                 fatal("key_from_private: unknown type %d", k->type);                  fatal("key_from_private: unknown type %d", k->type);
                 break;                  break;
         }          }
           if (key_is_cert(k))
                   key_cert_copy(k, n);
         return n;          return n;
 }  }
   
Line 766 
Line 961 
                 return KEY_RSA;                  return KEY_RSA;
         } else if (strcmp(name, "ssh-dss") == 0) {          } else if (strcmp(name, "ssh-dss") == 0) {
                 return KEY_DSA;                  return KEY_DSA;
           } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
                   return KEY_RSA_CERT;
           } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
                   return KEY_DSA_CERT;
         }          }
         debug2("key_type_from_name: unknown key type '%s'", name);          debug2("key_type_from_name: unknown key type '%s'", name);
         return KEY_UNSPEC;          return KEY_UNSPEC;
Line 793 
Line 992 
         return 1;          return 1;
 }  }
   
   static int
   cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
   {
           u_char *principals, *constraints, *sig_key, *sig;
           u_int signed_len, plen, clen, sklen, slen;
           Buffer tmp;
           char *principal;
           int ret = -1;
   
           buffer_init(&tmp);
   
           /* Copy the entire key blob for verification and later serialisation */
           buffer_append(&key->cert->certblob, blob, blen);
   
           principals = constraints = sig_key = sig = NULL;
           if (buffer_get_int_ret(&key->cert->type, b) != 0 ||
               (key->cert->key_id = buffer_get_string_ret(b, NULL)) == NULL ||
               (principals = buffer_get_string_ret(b, &plen)) == NULL ||
               buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
               buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
               (constraints = buffer_get_string_ret(b, &clen)) == NULL ||
               /* skip nonce */ buffer_get_string_ptr_ret(b, NULL) == NULL ||
               /* skip reserved */ buffer_get_string_ptr_ret(b, NULL) == NULL ||
               (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
                   error("%s: parse error", __func__);
                   goto out;
           }
   
           /* Signature is left in the buffer so we can calculate this length */
           signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
   
           if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
                   error("%s: parse error", __func__);
                   goto out;
           }
   
           if (key->cert->type != SSH2_CERT_TYPE_USER &&
               key->cert->type != SSH2_CERT_TYPE_HOST) {
                   error("Unknown certificate type %u", key->cert->type);
                   goto out;
           }
   
           buffer_append(&tmp, principals, plen);
           while (buffer_len(&tmp) > 0) {
                   if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
                           error("Too many principals");
                           goto out;
                   }
                   if ((principal = buffer_get_string_ret(&tmp, NULL)) == NULL) {
                           error("Principals data invalid");
                           goto out;
                   }
                   key->cert->principals = xrealloc(key->cert->principals,
                       key->cert->nprincipals + 1, sizeof(*key->cert->principals));
                   key->cert->principals[key->cert->nprincipals++] = principal;
           }
   
           buffer_clear(&tmp);
   
           buffer_append(&key->cert->constraints, constraints, clen);
           buffer_append(&tmp, constraints, clen);
           /* validate structure */
           while (buffer_len(&tmp) != 0) {
                   if (buffer_get_string_ptr(&tmp, NULL) == NULL ||
                       buffer_get_string_ptr(&tmp, NULL) == NULL) {
                           error("Constraints data invalid");
                           goto out;
                   }
           }
           buffer_clear(&tmp);
   
           if ((key->cert->signature_key = key_from_blob(sig_key,
               sklen)) == NULL) {
                   error("Signature key invalid");
                   goto out;
           }
           if (key->cert->signature_key->type != KEY_RSA &&
               key->cert->signature_key->type != KEY_DSA) {
                   error("Invalid signature key type %s (%d)",
                       key_type(key->cert->signature_key),
                       key->cert->signature_key->type);
                   goto out;
           }
   
           switch (key_verify(key->cert->signature_key, sig, slen,
               buffer_ptr(&key->cert->certblob), signed_len)) {
           case 1:
                   break; /* Good signature */
           case 0:
                   error("Invalid signature on certificate");
                   goto out;
           case -1:
                   error("Certificate signature verification failed");
                   goto out;
           }
   
           ret = 0;
   
    out:
           buffer_free(&tmp);
           if (principals != NULL)
                   xfree(principals);
           if (constraints != NULL)
                   xfree(constraints);
           if (sig_key != NULL)
                   xfree(sig_key);
           if (sig != NULL)
                   xfree(sig);
           return ret;
   }
   
 Key *  Key *
 key_from_blob(const u_char *blob, u_int blen)  key_from_blob(const u_char *blob, u_int blen)
 {  {
Line 815 
Line 1125 
   
         switch (type) {          switch (type) {
         case KEY_RSA:          case KEY_RSA:
           case KEY_RSA_CERT:
                 key = key_new(type);                  key = key_new(type);
                 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||                  if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
                     buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {                      buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
                         error("key_from_blob: can't read rsa key");                          error("key_from_blob: can't read rsa key");
    badkey:
                         key_free(key);                          key_free(key);
                         key = NULL;                          key = NULL;
                         goto out;                          goto out;
Line 828 
Line 1140 
 #endif  #endif
                 break;                  break;
         case KEY_DSA:          case KEY_DSA:
           case KEY_DSA_CERT:
                 key = key_new(type);                  key = key_new(type);
                 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||                  if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
                     buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||                      buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
                     buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||                      buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
                     buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {                      buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
                         error("key_from_blob: can't read dsa key");                          error("key_from_blob: can't read dsa key");
                         key_free(key);                          goto badkey;
                         key = NULL;  
                         goto out;  
                 }                  }
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                 DSA_print_fp(stderr, key->dsa, 8);                  DSA_print_fp(stderr, key->dsa, 8);
Line 849 
Line 1160 
                 error("key_from_blob: cannot handle type %s", ktype);                  error("key_from_blob: cannot handle type %s", ktype);
                 goto out;                  goto out;
         }          }
           if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
                   error("key_from_blob: can't parse cert data");
                   goto badkey;
           }
         rlen = buffer_len(&b);          rlen = buffer_len(&b);
         if (key != NULL && rlen != 0)          if (key != NULL && rlen != 0)
                 error("key_from_blob: remaining bytes in key blob %d", rlen);                  error("key_from_blob: remaining bytes in key blob %d", rlen);
Line 871 
Line 1186 
         }          }
         buffer_init(&b);          buffer_init(&b);
         switch (key->type) {          switch (key->type) {
           case KEY_DSA_CERT:
           case KEY_RSA_CERT:
                   /* Use the existing blob */
                   buffer_append(&b, buffer_ptr(&key->cert->certblob),
                       buffer_len(&key->cert->certblob));
                   break;
         case KEY_DSA:          case KEY_DSA:
                 buffer_put_cstring(&b, key_ssh_name(key));                  buffer_put_cstring(&b, key_ssh_name(key));
                 buffer_put_bignum2(&b, key->dsa->p);                  buffer_put_bignum2(&b, key->dsa->p);
Line 907 
Line 1228 
     const u_char *data, u_int datalen)      const u_char *data, u_int datalen)
 {  {
         switch (key->type) {          switch (key->type) {
           case KEY_DSA_CERT:
         case KEY_DSA:          case KEY_DSA:
                 return ssh_dss_sign(key, sigp, lenp, data, datalen);                  return ssh_dss_sign(key, sigp, lenp, data, datalen);
           case KEY_RSA_CERT:
         case KEY_RSA:          case KEY_RSA:
                 return ssh_rsa_sign(key, sigp, lenp, data, datalen);                  return ssh_rsa_sign(key, sigp, lenp, data, datalen);
         default:          default:
Line 931 
Line 1254 
                 return -1;                  return -1;
   
         switch (key->type) {          switch (key->type) {
           case KEY_DSA_CERT:
         case KEY_DSA:          case KEY_DSA:
                 return ssh_dss_verify(key, signature, signaturelen, data, datalen);                  return ssh_dss_verify(key, signature, signaturelen, data, datalen);
           case KEY_RSA_CERT:
         case KEY_RSA:          case KEY_RSA:
                 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);                  return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
         default:          default:
Line 954 
Line 1279 
         pk->rsa = NULL;          pk->rsa = NULL;
   
         switch (k->type) {          switch (k->type) {
           case KEY_RSA_CERT:
                   key_cert_copy(k, pk);
                   /* FALLTHROUGH */
         case KEY_RSA1:          case KEY_RSA1:
         case KEY_RSA:          case KEY_RSA:
                 if ((pk->rsa = RSA_new()) == NULL)                  if ((pk->rsa = RSA_new()) == NULL)
Line 963 
Line 1291 
                 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)                  if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
                         fatal("key_demote: BN_dup failed");                          fatal("key_demote: BN_dup failed");
                 break;                  break;
           case KEY_DSA_CERT:
                   key_cert_copy(k, pk);
                   /* FALLTHROUGH */
         case KEY_DSA:          case KEY_DSA:
                 if ((pk->dsa = DSA_new()) == NULL)                  if ((pk->dsa = DSA_new()) == NULL)
                         fatal("key_demote: DSA_new failed");                          fatal("key_demote: DSA_new failed");
Line 981 
Line 1312 
         }          }
   
         return (pk);          return (pk);
   }
   
   int
   key_is_cert(const Key *k)
   {
           return k != NULL &&
               (k->type == KEY_RSA_CERT || k->type == KEY_DSA_CERT);
   }
   
   /* Return the cert-less equivalent to a certified key type */
   int
   key_type_plain(int type)
   {
           switch (type) {
           case KEY_RSA_CERT:
                   return KEY_RSA;
           case KEY_DSA_CERT:
                   return KEY_DSA;
           default:
                   return type;
           }
   }
   
   /* Convert a KEY_RSA or KEY_DSA to their _CERT equivalent */
   int
   key_to_certified(Key *k)
   {
           switch (k->type) {
           case KEY_RSA:
                   k->cert = cert_new();
                   k->type = KEY_RSA_CERT;
                   return 0;
           case KEY_DSA:
                   k->cert = cert_new();
                   k->type = KEY_DSA_CERT;
                   return 0;
           default:
                   error("%s: key has incorrect type %s", __func__, key_type(k));
                   return -1;
           }
   }
   
   /* Convert a KEY_RSA_CERT or KEY_DSA_CERT to their raw key equivalent */
   int
   key_drop_cert(Key *k)
   {
           switch (k->type) {
           case KEY_RSA_CERT:
                   cert_free(k->cert);
                   k->type = KEY_RSA;
                   return 0;
           case KEY_DSA_CERT:
                   cert_free(k->cert);
                   k->type = KEY_DSA;
                   return 0;
           default:
                   error("%s: key has incorrect type %s", __func__, key_type(k));
                   return -1;
           }
   }
   
   /* Sign a KEY_RSA_CERT or KEY_DSA_CERT, (re-)generating the signed certblob */
   int
   key_certify(Key *k, Key *ca)
   {
           Buffer principals;
           u_char *ca_blob, *sig_blob, nonce[32];
           u_int i, ca_len, sig_len;
   
           if (k->cert == NULL) {
                   error("%s: key lacks cert info", __func__);
                   return -1;
           }
   
           if (!key_is_cert(k)) {
                   error("%s: certificate has unknown type %d", __func__,
                       k->cert->type);
                   return -1;
           }
   
           if (ca->type != KEY_RSA && ca->type != KEY_DSA) {
                   error("%s: CA key has unsupported type %s", __func__,
                       key_type(ca));
                   return -1;
           }
   
           key_to_blob(ca, &ca_blob, &ca_len);
   
           buffer_clear(&k->cert->certblob);
           buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
   
           switch (k->type) {
           case KEY_DSA_CERT:
                   buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
                   buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
                   buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
                   buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
                   break;
           case KEY_RSA_CERT:
                   buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
                   buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
                   break;
           default:
                   error("%s: key has incorrect type %s", __func__, key_type(k));
                   buffer_clear(&k->cert->certblob);
                   xfree(ca_blob);
                   return -1;
           }
   
           buffer_put_int(&k->cert->certblob, k->cert->type);
           buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
   
           buffer_init(&principals);
           for (i = 0; i < k->cert->nprincipals; i++)
                   buffer_put_cstring(&principals, k->cert->principals[i]);
           buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
               buffer_len(&principals));
           buffer_free(&principals);
   
           buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
           buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
           buffer_put_string(&k->cert->certblob,
               buffer_ptr(&k->cert->constraints),
               buffer_len(&k->cert->constraints));
   
           arc4random_buf(&nonce, sizeof(nonce));
           buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
           buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
           buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
           xfree(ca_blob);
   
           /* Sign the whole mess */
           if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob),
               buffer_len(&k->cert->certblob)) != 0) {
                   error("%s: signature operation failed", __func__);
                   buffer_clear(&k->cert->certblob);
                   return -1;
           }
           /* Append signature and we are done */
           buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
           xfree(sig_blob);
   
           return 0;
   }
   
   int
   key_cert_check_authority(const Key *k, int want_host, int require_principal,
       const char *name, const char **reason)
   {
           u_int i, principal_matches;
           time_t now = time(NULL);
   
           if (want_host) {
                   if (k->cert->type != SSH2_CERT_TYPE_HOST) {
                           *reason = "Certificate invalid: not a host certificate";
                           return -1;
                   }
           } else {
                   if (k->cert->type != SSH2_CERT_TYPE_USER) {
                           *reason = "Certificate invalid: not a user certificate";
                           return -1;
                   }
           }
           if (now < 0) {
                   error("%s: system clock lies before epoch", __func__);
                   *reason = "Certificate invalid: not yet valid";
                   return -1;
           }
           if ((u_int64_t)now < k->cert->valid_after) {
                   *reason = "Certificate invalid: not yet valid";
                   return -1;
           }
           if ((u_int64_t)now >= k->cert->valid_before) {
                   *reason = "Certificate invalid: expired";
                   return -1;
           }
           if (k->cert->nprincipals == 0) {
                   if (require_principal) {
                           *reason = "Certificate lacks principal list";
                           return -1;
                   }
           } else {
                   principal_matches = 0;
                   for (i = 0; i < k->cert->nprincipals; i++) {
                           if (strcmp(name, k->cert->principals[i]) == 0) {
                                   principal_matches = 1;
                                   break;
                           }
                   }
                   if (!principal_matches) {
                           *reason = "Certificate invalid: name is not a listed "
                               "principal";
                           return -1;
                   }
           }
           return 0;
 }  }

Legend:
Removed from v.1.82  
changed lines
  Added in v.1.83