[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.117 and 1.118

version 1.117, 2014/04/29 18:01:49 version 1.118, 2014/06/24 01:13:21
Line 1 
Line 1 
 /* $OpenBSD$ */  /* $OpenBSD$ */
 /*  /*
  * read_bignum():   * placed in the public domain
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland  
  *  
  * As far as I am concerned, the code I have written for this software  
  * can be used freely for any purpose.  Any derived versions of this  
  * software must be clearly marked as such, and if the derived work is  
  * incompatible with the protocol description in the RFC file, it must be  
  * called by a name other than "ssh" or "Secure Shell".  
  *  
  *  
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.  
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.  
  *  
  * Redistribution and use in source and binary forms, with or without  
  * modification, are permitted provided that the following conditions  
  * are met:  
  * 1. Redistributions of source code must retain the above copyright  
  *    notice, this list of conditions and the following disclaimer.  
  * 2. Redistributions in binary form must reproduce the above copyright  
  *    notice, this list of conditions and the following disclaimer in the  
  *    documentation and/or other materials provided with the distribution.  
  *  
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  
  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,  
  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  
  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  
  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  */   */
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/types.h>  #include <sys/types.h>
   #include <errno.h>
 #include <openssl/evp.h>  #include <stdarg.h>
 #include "crypto_api.h"  
   
 #include <stdio.h>  #include <stdio.h>
 #include <string.h>  
   
 #include "xmalloc.h"  #define SSH_KEY_NO_DEFINE
 #include "key.h"  #include "key.h"
 #include "rsa.h"  
 #include "uuencode.h"  #include "compat.h"
 #include "buffer.h"  #include "sshkey.h"
   #include "ssherr.h"
 #include "log.h"  #include "log.h"
 #include "misc.h"  #include "authfile.h"
 #include "ssh2.h"  
 #include "digest.h"  
   
 static int to_blob(const Key *, u_char **, u_int *, int);  
 static Key *key_from_blob2(const u_char *, u_int, int);  
   
 static struct KeyCert *  
 cert_new(void)  
 {  
         struct KeyCert *cert;  
   
         cert = xcalloc(1, sizeof(*cert));  
         buffer_init(&cert->certblob);  
         buffer_init(&cert->critical);  
         buffer_init(&cert->extensions);  
         cert->key_id = NULL;  
         cert->principals = NULL;  
         cert->signature_key = NULL;  
         return cert;  
 }  
   
 Key *  
 key_new(int type)  
 {  
         Key *k;  
 #ifdef WITH_OPENSSL  
         RSA *rsa;  
         DSA *dsa;  
 #endif  
   
         k = xcalloc(1, sizeof(*k));  
         k->type = type;  
         k->ecdsa = NULL;  
         k->ecdsa_nid = -1;  
         k->dsa = NULL;  
         k->rsa = NULL;  
         k->cert = NULL;  
         k->ed25519_sk = NULL;  
         k->ed25519_pk = NULL;  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA1:  
         case KEY_RSA:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 if ((rsa = RSA_new()) == NULL)  
                         fatal("key_new: RSA_new failed");  
                 if ((rsa->n = BN_new()) == NULL)  
                         fatal("key_new: BN_new failed");  
                 if ((rsa->e = BN_new()) == NULL)  
                         fatal("key_new: BN_new failed");  
                 k->rsa = rsa;  
                 break;  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 if ((dsa = DSA_new()) == NULL)  
                         fatal("key_new: DSA_new failed");  
                 if ((dsa->p = BN_new()) == NULL)  
                         fatal("key_new: BN_new failed");  
                 if ((dsa->q = BN_new()) == NULL)  
                         fatal("key_new: BN_new failed");  
                 if ((dsa->g = BN_new()) == NULL)  
                         fatal("key_new: BN_new failed");  
                 if ((dsa->pub_key = BN_new()) == NULL)  
                         fatal("key_new: BN_new failed");  
                 k->dsa = dsa;  
                 break;  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 /* Cannot do anything until we know the group */  
                 break;  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 /* no need to prealloc */  
                 break;  
         case KEY_UNSPEC:  
                 break;  
         default:  
                 fatal("key_new: bad key type %d", k->type);  
                 break;  
         }  
   
         if (key_is_cert(k))  
                 k->cert = cert_new();  
   
         return k;  
 }  
   
 void  void
 key_add_private(Key *k)  key_add_private(Key *k)
 {  {
         switch (k->type) {          int r;
 #ifdef WITH_OPENSSL  
         case KEY_RSA1:          if ((r = sshkey_add_private(k)) != 0)
         case KEY_RSA:                  fatal("%s: %s", __func__, ssh_err(r));
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 if ((k->rsa->d = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 if ((k->rsa->iqmp = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 if ((k->rsa->q = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 if ((k->rsa->p = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 if ((k->rsa->dmq1 = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 if ((k->rsa->dmp1 = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 break;  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 if ((k->dsa->priv_key = BN_new()) == NULL)  
                         fatal("key_new_private: BN_new failed");  
                 break;  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 /* Cannot do anything until we know the group */  
                 break;  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 /* no need to prealloc */  
                 break;  
         case KEY_UNSPEC:  
                 break;  
         default:  
                 break;  
         }  
 }  }
   
 Key *  Key *
 key_new_private(int type)  key_new_private(int type)
 {  {
         Key *k = key_new(type);          Key *ret = NULL;
   
         key_add_private(k);          if ((ret = sshkey_new_private(type)) == NULL)
         return k;                  fatal("%s: failed", __func__);
           return ret;
 }  }
   
 static void  
 cert_free(struct KeyCert *cert)  
 {  
         u_int i;  
   
         buffer_free(&cert->certblob);  
         buffer_free(&cert->critical);  
         buffer_free(&cert->extensions);  
         free(cert->key_id);  
         for (i = 0; i < cert->nprincipals; i++)  
                 free(cert->principals[i]);  
         free(cert->principals);  
         if (cert->signature_key != NULL)  
                 key_free(cert->signature_key);  
         free(cert);  
 }  
   
 void  
 key_free(Key *k)  
 {  
         if (k == NULL)  
                 fatal("key_free: key is NULL");  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA1:  
         case KEY_RSA:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 if (k->rsa != NULL)  
                         RSA_free(k->rsa);  
                 k->rsa = NULL;  
                 break;  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 if (k->dsa != NULL)  
                         DSA_free(k->dsa);  
                 k->dsa = NULL;  
                 break;  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 if (k->ecdsa != NULL)  
                         EC_KEY_free(k->ecdsa);  
                 k->ecdsa = NULL;  
                 break;  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 if (k->ed25519_pk) {  
                         explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);  
                         free(k->ed25519_pk);  
                         k->ed25519_pk = NULL;  
                 }  
                 if (k->ed25519_sk) {  
                         explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);  
                         free(k->ed25519_sk);  
                         k->ed25519_sk = NULL;  
                 }  
                 break;  
         case KEY_UNSPEC:  
                 break;  
         default:  
                 fatal("key_free: bad key type %d", k->type);  
                 break;  
         }  
         if (key_is_cert(k)) {  
                 if (k->cert != NULL)  
                         cert_free(k->cert);  
                 k->cert = NULL;  
         }  
   
         free(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 (timingsafe_bcmp(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  
 key_equal_public(const Key *a, const Key *b)  
 {  
 #ifdef WITH_OPENSSL  
         BN_CTX *bnctx;  
 #endif  
   
         if (a == NULL || b == NULL ||  
             key_type_plain(a->type) != key_type_plain(b->type))  
                 return 0;  
   
         switch (a->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA1:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
         case KEY_RSA:  
                 return a->rsa != NULL && b->rsa != NULL &&  
                     BN_cmp(a->rsa->e, b->rsa->e) == 0 &&  
                     BN_cmp(a->rsa->n, b->rsa->n) == 0;  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
         case KEY_DSA:  
                 return a->dsa != NULL && b->dsa != NULL &&  
                     BN_cmp(a->dsa->p, b->dsa->p) == 0 &&  
                     BN_cmp(a->dsa->q, b->dsa->q) == 0 &&  
                     BN_cmp(a->dsa->g, b->dsa->g) == 0 &&  
                     BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;  
         case KEY_ECDSA_CERT:  
         case KEY_ECDSA:  
                 if (a->ecdsa == NULL || b->ecdsa == NULL ||  
                     EC_KEY_get0_public_key(a->ecdsa) == NULL ||  
                     EC_KEY_get0_public_key(b->ecdsa) == NULL)  
                         return 0;  
                 if ((bnctx = BN_CTX_new()) == NULL)  
                         fatal("%s: BN_CTX_new failed", __func__);  
                 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),  
                     EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||  
                     EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),  
                     EC_KEY_get0_public_key(a->ecdsa),  
                     EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {  
                         BN_CTX_free(bnctx);  
                         return 0;  
                 }  
                 BN_CTX_free(bnctx);  
                 return 1;  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&  
                     memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;  
         default:  
                 fatal("key_equal: bad key type %d", a->type);  
         }  
         /* 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(const Key *k, enum fp_type dgst_type,
     u_int *dgst_raw_length)      u_int *dgst_raw_length)
 {  {
         u_char *blob = NULL;          u_char *ret = NULL;
         u_char *retval = NULL;          size_t dlen;
         u_int len = 0;          int r;
         int hash_alg = -1;  
 #ifdef WITH_OPENSSL  
         int nlen, elen;  
 #endif  
   
         *dgst_raw_length = 0;          if (dgst_raw_length != NULL)
                   *dgst_raw_length = 0;
         /* XXX switch to DIGEST_* directly? */          if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0)
         switch (dgst_type) {                  fatal("%s: %s", __func__, ssh_err(r));
         case SSH_FP_MD5:          if (dlen > INT_MAX)
                 hash_alg = SSH_DIGEST_MD5;                  fatal("%s: giant len %zu", __func__, dlen);
                 break;          *dgst_raw_length = dlen;
         case SSH_FP_SHA1:          return ret;
                 hash_alg = SSH_DIGEST_SHA1;  
                 break;  
         case SSH_FP_SHA256:  
                 hash_alg = SSH_DIGEST_SHA256;  
                 break;  
         default:  
                 fatal("%s: bad digest type %d", __func__, dgst_type);  
         }  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA1:  
                 nlen = BN_num_bytes(k->rsa->n);  
                 elen = BN_num_bytes(k->rsa->e);  
                 len = nlen + elen;  
                 blob = xmalloc(len);  
                 BN_bn2bin(k->rsa->n, blob);  
                 BN_bn2bin(k->rsa->e, blob + nlen);  
                 break;  
         case KEY_DSA:  
         case KEY_ECDSA:  
         case KEY_RSA:  
 #endif  
         case KEY_ED25519:  
                 key_to_blob(k, &blob, &len);  
                 break;  
 #ifdef WITH_OPENSSL  
         case KEY_DSA_CERT_V00:  
         case KEY_RSA_CERT_V00:  
         case KEY_DSA_CERT:  
         case KEY_ECDSA_CERT:  
         case KEY_RSA_CERT:  
 #endif  
         case KEY_ED25519_CERT:  
                 /* We want a fingerprint of the _key_ not of the cert */  
                 to_blob(k, &blob, &len, 1);  
                 break;  
         case KEY_UNSPEC:  
                 return retval;  
         default:  
                 fatal("%s: bad key type %d", __func__, k->type);  
                 break;  
         }  
         if (blob != NULL) {  
                 retval = xmalloc(SSH_DIGEST_MAX_LENGTH);  
                 if ((ssh_digest_memory(hash_alg, blob, len,  
                     retval, SSH_DIGEST_MAX_LENGTH)) != 0)  
                         fatal("%s: digest_memory failed", __func__);  
                 explicit_bzero(blob, len);  
                 free(blob);  
                 *dgst_raw_length = ssh_digest_bytes(hash_alg);  
         } else {  
                 fatal("%s: blob is null", __func__);  
         }  
         return retval;  
 }  }
   
 static char *  
 key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)  
 {  
         char *retval;  
         u_int i;  
   
         retval = xcalloc(1, dgst_raw_len * 3 + 1);  
         for (i = 0; i < dgst_raw_len; i++) {  
                 char hex[4];  
                 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);  
                 strlcat(retval, hex, dgst_raw_len * 3 + 1);  
         }  
   
         /* Remove the trailing ':' character */  
         retval[(dgst_raw_len * 3) - 1] = '\0';  
         return retval;  
 }  
   
 static char *  
 key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)  
 {  
         char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };  
         char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',  
             'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };  
         u_int i, j = 0, rounds, seed = 1;  
         char *retval;  
   
         rounds = (dgst_raw_len / 2) + 1;  
         retval = xcalloc((rounds * 6), sizeof(char));  
         retval[j++] = 'x';  
         for (i = 0; i < rounds; i++) {  
                 u_int idx0, idx1, idx2, idx3, idx4;  
                 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {  
                         idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +  
                             seed) % 6;  
                         idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;  
                         idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +  
                             (seed / 6)) % 6;  
                         retval[j++] = vowels[idx0];  
                         retval[j++] = consonants[idx1];  
                         retval[j++] = vowels[idx2];  
                         if ((i + 1) < rounds) {  
                                 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;  
                                 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;  
                                 retval[j++] = consonants[idx3];  
                                 retval[j++] = '-';  
                                 retval[j++] = consonants[idx4];  
                                 seed = ((seed * 5) +  
                                     ((((u_int)(dgst_raw[2 * i])) * 7) +  
                                     ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;  
                         }  
                 } else {  
                         idx0 = seed % 6;  
                         idx1 = 16;  
                         idx2 = seed / 6;  
                         retval[j++] = vowels[idx0];  
                         retval[j++] = consonants[idx1];  
                         retval[j++] = vowels[idx2];  
                 }  
         }  
         retval[j++] = 'x';  
         retval[j++] = '\0';  
         return retval;  
 }  
   
 /*  
  * Draw an ASCII-Art representing the fingerprint so human brain can  
  * profit from its built-in pattern recognition ability.  
  * This technique is called "random art" and can be found in some  
  * scientific publications like this original paper:  
  *  
  * "Hash Visualization: a New Technique to improve Real-World Security",  
  * Perrig A. and Song D., 1999, International Workshop on Cryptographic  
  * Techniques and E-Commerce (CrypTEC '99)  
  * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf  
  *  
  * The subject came up in a talk by Dan Kaminsky, too.  
  *  
  * If you see the picture is different, the key is different.  
  * If the picture looks the same, you still know nothing.  
  *  
  * The algorithm used here is a worm crawling over a discrete plane,  
  * leaving a trace (augmenting the field) everywhere it goes.  
  * Movement is taken from dgst_raw 2bit-wise.  Bumping into walls  
  * makes the respective movement vector be ignored for this turn.  
  * Graphs are not unambiguous, because circles in graphs can be  
  * walked in either direction.  
  */  
   
 /*  
  * Field sizes for the random art.  Have to be odd, so the starting point  
  * can be in the exact middle of the picture, and FLDBASE should be >=8 .  
  * Else pictures would be too dense, and drawing the frame would  
  * fail, too, because the key type would not fit in anymore.  
  */  
 #define FLDBASE         8  
 #define FLDSIZE_Y       (FLDBASE + 1)  
 #define FLDSIZE_X       (FLDBASE * 2 + 1)  
 static char *  
 key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)  
 {  
         /*  
          * Chars to be used after each other every time the worm  
          * intersects with itself.  Matter of taste.  
          */  
         char    *augmentation_string = " .o+=*BOX@%&#/^SE";  
         char    *retval, *p;  
         u_char   field[FLDSIZE_X][FLDSIZE_Y];  
         u_int    i, b;  
         int      x, y;  
         size_t   len = strlen(augmentation_string) - 1;  
   
         retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));  
   
         /* initialize field */  
         memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));  
         x = FLDSIZE_X / 2;  
         y = FLDSIZE_Y / 2;  
   
         /* process raw key */  
         for (i = 0; i < dgst_raw_len; i++) {  
                 int input;  
                 /* each byte conveys four 2-bit move commands */  
                 input = dgst_raw[i];  
                 for (b = 0; b < 4; b++) {  
                         /* evaluate 2 bit, rest is shifted later */  
                         x += (input & 0x1) ? 1 : -1;  
                         y += (input & 0x2) ? 1 : -1;  
   
                         /* assure we are still in bounds */  
                         x = MAX(x, 0);  
                         y = MAX(y, 0);  
                         x = MIN(x, FLDSIZE_X - 1);  
                         y = MIN(y, FLDSIZE_Y - 1);  
   
                         /* augment the field */  
                         if (field[x][y] < len - 2)  
                                 field[x][y]++;  
                         input = input >> 2;  
                 }  
         }  
   
         /* mark starting point and end point*/  
         field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;  
         field[x][y] = len;  
   
         /* fill in retval */  
         snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));  
         p = strchr(retval, '\0');  
   
         /* output upper border */  
         for (i = p - retval - 1; i < FLDSIZE_X; i++)  
                 *p++ = '-';  
         *p++ = '+';  
         *p++ = '\n';  
   
         /* output content */  
         for (y = 0; y < FLDSIZE_Y; y++) {  
                 *p++ = '|';  
                 for (x = 0; x < FLDSIZE_X; x++)  
                         *p++ = augmentation_string[MIN(field[x][y], len)];  
                 *p++ = '|';  
                 *p++ = '\n';  
         }  
   
         /* output lower border */  
         *p++ = '+';  
         for (i = 0; i < FLDSIZE_X; i++)  
                 *p++ = '-';  
         *p++ = '+';  
   
         return retval;  
 }  
   
 char *  
 key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)  
 {  
         char *retval = NULL;  
         u_char *dgst_raw;  
         u_int dgst_raw_len;  
   
         dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);  
         if (!dgst_raw)  
                 fatal("key_fingerprint: null from key_fingerprint_raw()");  
         switch (dgst_rep) {  
         case SSH_FP_HEX:  
                 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);  
                 break;  
         case SSH_FP_BUBBLEBABBLE:  
                 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);  
                 break;  
         case SSH_FP_RANDOMART:  
                 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);  
                 break;  
         default:  
                 fatal("key_fingerprint: bad digest representation %d",  
                     dgst_rep);  
                 break;  
         }  
         explicit_bzero(dgst_raw, dgst_raw_len);  
         free(dgst_raw);  
         return retval;  
 }  
   
 #ifdef WITH_SSH1  
 /*  
  * Reads a multiple-precision integer in decimal from the buffer, and advances  
  * the pointer.  The integer must already be initialized.  This function is  
  * permitted to modify the buffer.  This leaves *cpp to point just beyond the  
  * last processed (and maybe modified) character.  Note that this may modify  
  * the buffer containing the number.  
  */  
 static int  
 read_bignum(char **cpp, BIGNUM * value)  
 {  
         char *cp = *cpp;  
         int old;  
   
         /* Skip any leading whitespace. */  
         for (; *cp == ' ' || *cp == '\t'; cp++)  
                 ;  
   
         /* Check that it begins with a decimal digit. */  
         if (*cp < '0' || *cp > '9')  
                 return 0;  
   
         /* Save starting position. */  
         *cpp = cp;  
   
         /* Move forward until all decimal digits skipped. */  
         for (; *cp >= '0' && *cp <= '9'; cp++)  
                 ;  
   
         /* Save the old terminating character, and replace it by \0. */  
         old = *cp;  
         *cp = 0;  
   
         /* Parse the number. */  
         if (BN_dec2bn(&value, *cpp) == 0)  
                 return 0;  
   
         /* Restore old terminating character. */  
         *cp = old;  
   
         /* Move beyond the number and return success. */  
         *cpp = cp;  
         return 1;  
 }  
   
 static int  
 write_bignum(FILE *f, BIGNUM *num)  
 {  
         char *buf = BN_bn2dec(num);  
         if (buf == NULL) {  
                 error("write_bignum: BN_bn2dec() failed");  
                 return 0;  
         }  
         fprintf(f, " %s", buf);  
         OPENSSL_free(buf);  
         return 1;  
 }  
 #endif  
   
 /* returns 1 ok, -1 error */  
 int  int
 key_read(Key *ret, char **cpp)  key_read(Key *ret, char **cpp)
 {  {
         Key *k;          return sshkey_read(ret, cpp) == 0 ? 1 : -1;
         int success = -1;  
         char *cp, *space;  
         int len, n, type, curve_nid = -1;  
 #ifdef WITH_SSH1  
         u_int bits;  
 #endif  
         u_char *blob;  
   
         cp = *cpp;  
   
         switch (ret->type) {  
         case KEY_RSA1:  
 #ifdef WITH_SSH1  
                 /* Get number of bits. */  
                 if (*cp < '0' || *cp > '9')  
                         return -1;      /* Bad bit count... */  
                 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)  
                         bits = 10 * bits + *cp - '0';  
                 if (bits == 0)  
                         return -1;  
                 *cpp = cp;  
                 /* Get public exponent, public modulus. */  
                 if (!read_bignum(cpp, ret->rsa->e))  
                         return -1;  
                 if (!read_bignum(cpp, ret->rsa->n))  
                         return -1;  
                 /* validate the claimed number of bits */  
                 if ((u_int)BN_num_bits(ret->rsa->n) != bits) {  
                         verbose("key_read: claimed key size %d does not match "  
                            "actual %d", bits, BN_num_bits(ret->rsa->n));  
                         return -1;  
                 }  
                 success = 1;  
 #endif  
                 break;  
         case KEY_UNSPEC:  
         case KEY_RSA:  
         case KEY_DSA:  
         case KEY_ECDSA:  
         case KEY_ED25519:  
         case KEY_DSA_CERT_V00:  
         case KEY_RSA_CERT_V00:  
         case KEY_DSA_CERT:  
         case KEY_ECDSA_CERT:  
         case KEY_RSA_CERT:  
         case KEY_ED25519_CERT:  
                 space = strchr(cp, ' ');  
                 if (space == NULL) {  
                         debug3("key_read: missing whitespace");  
                         return -1;  
                 }  
                 *space = '\0';  
                 type = key_type_from_name(cp);  
                 if (key_type_plain(type) == KEY_ECDSA &&  
                     (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {  
                         debug("key_read: invalid curve");  
                         return -1;  
                 }  
                 *space = ' ';  
                 if (type == KEY_UNSPEC) {  
                         debug3("key_read: missing keytype");  
                         return -1;  
                 }  
                 cp = space+1;  
                 if (*cp == '\0') {  
                         debug3("key_read: short string");  
                         return -1;  
                 }  
                 if (ret->type == KEY_UNSPEC) {  
                         ret->type = type;  
                 } else if (ret->type != type) {  
                         /* is a key, but different type */  
                         debug3("key_read: type mismatch");  
                         return -1;  
                 }  
                 len = 2*strlen(cp);  
                 blob = xmalloc(len);  
                 n = uudecode(cp, blob, len);  
                 if (n < 0) {  
                         error("key_read: uudecode %s failed", cp);  
                         free(blob);  
                         return -1;  
                 }  
                 k = key_from_blob(blob, (u_int)n);  
                 free(blob);  
                 if (k == NULL) {  
                         error("key_read: key_from_blob %s failed", cp);  
                         return -1;  
                 }  
                 if (k->type != type) {  
                         error("key_read: type mismatch: encoding error");  
                         key_free(k);  
                         return -1;  
                 }  
                 if (key_type_plain(type) == KEY_ECDSA &&  
                     curve_nid != k->ecdsa_nid) {  
                         error("key_read: type mismatch: EC curve mismatch");  
                         key_free(k);  
                         return -1;  
                 }  
 /*XXXX*/  
                 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;  
                 }  
 #ifdef WITH_OPENSSL  
                 if (key_type_plain(ret->type) == KEY_RSA) {  
                         if (ret->rsa != NULL)  
                                 RSA_free(ret->rsa);  
                         ret->rsa = k->rsa;  
                         k->rsa = NULL;  
 #ifdef DEBUG_PK  
                         RSA_print_fp(stderr, ret->rsa, 8);  
 #endif  
                 }  
                 if (key_type_plain(ret->type) == KEY_DSA) {  
                         if (ret->dsa != NULL)  
                                 DSA_free(ret->dsa);  
                         ret->dsa = k->dsa;  
                         k->dsa = NULL;  
 #ifdef DEBUG_PK  
                         DSA_print_fp(stderr, ret->dsa, 8);  
 #endif  
                 }  
                 if (key_type_plain(ret->type) == KEY_ECDSA) {  
                         if (ret->ecdsa != NULL)  
                                 EC_KEY_free(ret->ecdsa);  
                         ret->ecdsa = k->ecdsa;  
                         ret->ecdsa_nid = k->ecdsa_nid;  
                         k->ecdsa = NULL;  
                         k->ecdsa_nid = -1;  
 #ifdef DEBUG_PK  
                         key_dump_ec_key(ret->ecdsa);  
 #endif  
                 }  
 #endif  
                 if (key_type_plain(ret->type) == KEY_ED25519) {  
                         free(ret->ed25519_pk);  
                         ret->ed25519_pk = k->ed25519_pk;  
                         k->ed25519_pk = NULL;  
 #ifdef DEBUG_PK  
                         /* XXX */  
 #endif  
                 }  
                 success = 1;  
 /*XXXX*/  
                 key_free(k);  
                 if (success != 1)  
                         break;  
                 /* advance cp: skip whitespace and data */  
                 while (*cp == ' ' || *cp == '\t')  
                         cp++;  
                 while (*cp != '\0' && *cp != ' ' && *cp != '\t')  
                         cp++;  
                 *cpp = cp;  
                 break;  
         default:  
                 fatal("key_read: bad key type: %d", ret->type);  
                 break;  
         }  
         return success;  
 }  }
   
 int  int
 key_write(const Key *key, FILE *f)  key_write(const Key *key, FILE *f)
 {  {
         int n, success = 0;          return sshkey_write(key, f) == 0 ? 1 : 0;
 #ifdef WITH_SSH1  
         u_int bits = 0;  
 #endif  
         u_int len;  
         u_char *blob;  
         char *uu;  
   
         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) {  
 #ifdef WITH_SSH1  
         case KEY_RSA1:  
                 if (key->rsa == NULL)  
                         return 0;  
                 /* size of modulus 'n' */  
                 bits = BN_num_bits(key->rsa->n);  
                 fprintf(f, "%u", bits);  
                 if (write_bignum(f, key->rsa->e) &&  
                     write_bignum(f, key->rsa->n))  
                         return 1;  
                 error("key_write: failed for RSA key");  
                 return 0;  
 #endif  
 #ifdef WITH_OPENSSL  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 if (key->dsa == NULL)  
                         return 0;  
                 break;  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 if (key->ecdsa == NULL)  
                         return 0;  
                 break;  
         case KEY_RSA:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 if (key->rsa == NULL)  
                         return 0;  
                 break;  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 if (key->ed25519_pk == NULL)  
                         return 0;  
                 break;  
         default:  
                 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;  
         }  
         free(blob);  
         free(uu);  
   
         return success;  
 }  }
   
 const char *  Key *
 key_cert_type(const Key *k)  key_generate(int type, u_int bits)
 {  {
         switch (k->cert->type) {          int r;
         case SSH2_CERT_TYPE_USER:          Key *ret = NULL;
                 return "user";  
         case SSH2_CERT_TYPE_HOST:  
                 return "host";  
         default:  
                 return "unknown";  
         }  
 }  
   
 struct keytype {          if ((r = sshkey_generate(type, bits, &ret)) != 0)
         char *name;                  fatal("%s: %s", __func__, ssh_err(r));
         char *shortname;  
         int type;  
         int nid;  
         int cert;  
 };  
 static const struct keytype keytypes[] = {  
 #ifdef WITH_OPENSSL  
 #ifdef WITH_SSH1  
         { NULL, "RSA1", KEY_RSA1, 0, 0 },  
 #endif  
         { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },  
         { "ssh-dss", "DSA", KEY_DSA, 0, 0 },  
         { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },  
         { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },  
         { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },  
         { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },  
         { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },  
         { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",  
             KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },  
         { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",  
             KEY_ECDSA_CERT, NID_secp384r1, 1 },  
         { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",  
             KEY_ECDSA_CERT, NID_secp521r1, 1 },  
         { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",  
             KEY_RSA_CERT_V00, 0, 1 },  
         { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",  
             KEY_DSA_CERT_V00, 0, 1 },  
 #endif  
         { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },  
         { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",  
             KEY_ED25519_CERT, 0, 1 },  
         { NULL, NULL, -1, -1, 0 }  
 };  
   
 const char *  
 key_type(const Key *k)  
 {  
         const struct keytype *kt;  
   
         for (kt = keytypes; kt->type != -1; kt++) {  
                 if (kt->type == k->type)  
                         return kt->shortname;  
         }  
         return "unknown";  
 }  
   
 static const char *  
 key_ssh_name_from_type_nid(int type, int nid)  
 {  
         const struct keytype *kt;  
   
         for (kt = keytypes; kt->type != -1; kt++) {  
                 if (kt->type == type && (kt->nid == 0 || kt->nid == nid))  
                         return kt->name;  
         }  
         return "ssh-unknown";  
 }  
   
 const char *  
 key_ssh_name(const Key *k)  
 {  
         return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);  
 }  
   
 const char *  
 key_ssh_name_plain(const Key *k)  
 {  
         return key_ssh_name_from_type_nid(key_type_plain(k->type),  
             k->ecdsa_nid);  
 }  
   
 int  
 key_type_from_name(char *name)  
 {  
         const struct keytype *kt;  
   
         for (kt = keytypes; kt->type != -1; kt++) {  
                 /* Only allow shortname matches for plain key types */  
                 if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||  
                     (!kt->cert && strcasecmp(kt->shortname, name) == 0))  
                         return kt->type;  
         }  
         debug2("key_type_from_name: unknown key type '%s'", name);  
         return KEY_UNSPEC;  
 }  
   
 int  
 key_ecdsa_nid_from_name(const char *name)  
 {  
         const struct keytype *kt;  
   
         for (kt = keytypes; kt->type != -1; kt++) {  
                 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)  
                         continue;  
                 if (kt->name != NULL && strcmp(name, kt->name) == 0)  
                         return kt->nid;  
         }  
         debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);  
         return -1;  
 }  
   
 char *  
 key_alg_list(int certs_only, int plain_only)  
 {  
         char *ret = NULL;  
         size_t nlen, rlen = 0;  
         const struct keytype *kt;  
   
         for (kt = keytypes; kt->type != -1; kt++) {  
                 if (kt->name == NULL)  
                         continue;  
                 if ((certs_only && !kt->cert) || (plain_only && kt->cert))  
                         continue;  
                 if (ret != NULL)  
                         ret[rlen++] = '\n';  
                 nlen = strlen(kt->name);  
                 ret = xrealloc(ret, 1, rlen + nlen + 2);  
                 memcpy(ret + rlen, kt->name, nlen + 1);  
                 rlen += nlen;  
         }  
         return ret;          return ret;
 }  }
   
 int  
 key_type_is_cert(int type)  
 {  
         const struct keytype *kt;  
   
         for (kt = keytypes; kt->type != -1; kt++) {  
                 if (kt->type == type)  
                         return kt->cert;  
         }  
         return 0;  
 }  
   
 static int  
 key_type_is_valid_ca(int type)  
 {  
         switch (type) {  
         case KEY_RSA:  
         case KEY_DSA:  
         case KEY_ECDSA:  
         case KEY_ED25519:  
                 return 1;  
         default:  
                 return 0;  
         }  
 }  
   
 u_int  
 key_size(const Key *k)  
 {  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA1:  
         case KEY_RSA:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 return BN_num_bits(k->rsa->n);  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 return BN_num_bits(k->dsa->p);  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 return key_curve_nid_to_bits(k->ecdsa_nid);  
 #endif  
         case KEY_ED25519:  
                 return 256;     /* XXX */  
         }  
         return 0;  
 }  
   
 #ifdef WITH_OPENSSL  
 static RSA *  
 rsa_generate_private_key(u_int bits)  
 {  
         RSA *private = RSA_new();  
         BIGNUM *f4 = BN_new();  
   
         if (private == NULL)  
                 fatal("%s: RSA_new failed", __func__);  
         if (f4 == NULL)  
                 fatal("%s: BN_new failed", __func__);  
         if (!BN_set_word(f4, RSA_F4))  
                 fatal("%s: BN_new failed", __func__);  
         if (!RSA_generate_key_ex(private, bits, f4, NULL))  
                 fatal("%s: key generation failed.", __func__);  
         BN_free(f4);  
         return private;  
 }  
   
 static DSA*  
 dsa_generate_private_key(u_int bits)  
 {  
         DSA *private = DSA_new();  
   
         if (private == NULL)  
                 fatal("%s: DSA_new failed", __func__);  
         if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,  
             NULL, NULL))  
                 fatal("%s: DSA_generate_parameters failed", __func__);  
         if (!DSA_generate_key(private))  
                 fatal("%s: DSA_generate_key failed.", __func__);  
         return private;  
 }  
   
 int  
 key_ecdsa_bits_to_nid(int bits)  
 {  
         switch (bits) {  
         case 256:  
                 return NID_X9_62_prime256v1;  
         case 384:  
                 return NID_secp384r1;  
         case 521:  
                 return NID_secp521r1;  
         default:  
                 return -1;  
         }  
 }  
   
 int  
 key_ecdsa_key_to_nid(EC_KEY *k)  
 {  
         EC_GROUP *eg;  
         int nids[] = {  
                 NID_X9_62_prime256v1,  
                 NID_secp384r1,  
                 NID_secp521r1,  
                 -1  
         };  
         int nid;  
         u_int i;  
         BN_CTX *bnctx;  
         const EC_GROUP *g = EC_KEY_get0_group(k);  
   
         /*  
          * The group may be stored in a ASN.1 encoded private key in one of two  
          * ways: as a "named group", which is reconstituted by ASN.1 object ID  
          * or explicit group parameters encoded into the key blob. Only the  
          * "named group" case sets the group NID for us, but we can figure  
          * it out for the other case by comparing against all the groups that  
          * are supported.  
          */  
         if ((nid = EC_GROUP_get_curve_name(g)) > 0)  
                 return nid;  
         if ((bnctx = BN_CTX_new()) == NULL)  
                 fatal("%s: BN_CTX_new() failed", __func__);  
         for (i = 0; nids[i] != -1; i++) {  
                 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)  
                         fatal("%s: EC_GROUP_new_by_curve_name failed",  
                             __func__);  
                 if (EC_GROUP_cmp(g, eg, bnctx) == 0)  
                         break;  
                 EC_GROUP_free(eg);  
         }  
         BN_CTX_free(bnctx);  
         debug3("%s: nid = %d", __func__, nids[i]);  
         if (nids[i] != -1) {  
                 /* Use the group with the NID attached */  
                 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);  
                 if (EC_KEY_set_group(k, eg) != 1)  
                         fatal("%s: EC_KEY_set_group", __func__);  
         }  
         return nids[i];  
 }  
   
 static EC_KEY*  
 ecdsa_generate_private_key(u_int bits, int *nid)  
 {  
         EC_KEY *private;  
   
         if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)  
                 fatal("%s: invalid key length", __func__);  
         if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)  
                 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);  
         if (EC_KEY_generate_key(private) != 1)  
                 fatal("%s: EC_KEY_generate_key failed", __func__);  
         EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);  
         return private;  
 }  
 #endif  
   
 Key *  
 key_generate(int type, u_int bits)  
 {  
         Key *k = key_new(KEY_UNSPEC);  
         switch (type) {  
 #ifdef WITH_OPENSSL  
         case KEY_DSA:  
                 k->dsa = dsa_generate_private_key(bits);  
                 break;  
         case KEY_ECDSA:  
                 k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);  
                 break;  
         case KEY_RSA:  
         case KEY_RSA1:  
                 k->rsa = rsa_generate_private_key(bits);  
                 break;  
         case KEY_RSA_CERT_V00:  
         case KEY_DSA_CERT_V00:  
         case KEY_RSA_CERT:  
         case KEY_DSA_CERT:  
                 fatal("key_generate: cert keys cannot be generated directly");  
 #endif  
         case KEY_ED25519:  
                 k->ed25519_pk = xmalloc(ED25519_PK_SZ);  
                 k->ed25519_sk = xmalloc(ED25519_SK_SZ);  
                 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);  
                 break;  
         default:  
                 fatal("key_generate: unknown type %d", type);  
         }  
         k->type = type;  
         return k;  
 }  
   
 void  void
 key_cert_copy(const Key *from_key, struct Key *to_key)  key_cert_copy(const Key *from_key, Key *to_key)
 {  {
         u_int i;          int r;
         const struct KeyCert *from;  
         struct KeyCert *to;  
   
         if (to_key->cert != NULL) {          if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
                 cert_free(to_key->cert);                  fatal("%s: %s", __func__, ssh_err(r));
                 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->critical,  
             buffer_ptr(&from->critical), buffer_len(&from->critical));  
         buffer_append(&to->extensions,  
             buffer_ptr(&from->extensions), buffer_len(&from->extensions));  
   
         to->serial = from->serial;  
         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;          int r;
         switch (k->type) {          Key *ret = NULL;
 #ifdef WITH_OPENSSL  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 n = key_new(k->type);  
                 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||  
                     (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||  
                     (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||  
                     (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))  
                         fatal("key_from_private: BN_copy failed");  
                 break;  
         case KEY_ECDSA:  
         case KEY_ECDSA_CERT:  
                 n = key_new(k->type);  
                 n->ecdsa_nid = k->ecdsa_nid;  
                 if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)  
                         fatal("%s: EC_KEY_new_by_curve_name failed", __func__);  
                 if (EC_KEY_set_public_key(n->ecdsa,  
                     EC_KEY_get0_public_key(k->ecdsa)) != 1)  
                         fatal("%s: EC_KEY_set_public_key failed", __func__);  
                 break;  
         case KEY_RSA:  
         case KEY_RSA1:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 n = key_new(k->type);  
                 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||  
                     (BN_copy(n->rsa->e, k->rsa->e) == NULL))  
                         fatal("key_from_private: BN_copy failed");  
                 break;  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 n = key_new(k->type);  
                 if (k->ed25519_pk != NULL) {  
                         n->ed25519_pk = xmalloc(ED25519_PK_SZ);  
                         memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);  
                 }  
                 break;  
         default:  
                 fatal("key_from_private: unknown type %d", k->type);  
                 break;  
         }  
         if (key_is_cert(k))  
                 key_cert_copy(k, n);  
         return n;  
 }  
   
 int          if ((r = sshkey_from_private(k, &ret)) != 0)
 key_names_valid2(const char *names)                  fatal("%s: %s", __func__, ssh_err(r));
 {  
         char *s, *cp, *p;  
   
         if (names == NULL || strcmp(names, "") == 0)  
                 return 0;  
         s = cp = xstrdup(names);  
         for ((p = strsep(&cp, ",")); p && *p != '\0';  
             (p = strsep(&cp, ","))) {  
                 switch (key_type_from_name(p)) {  
                 case KEY_RSA1:  
                 case KEY_UNSPEC:  
                         free(s);  
                         return 0;  
                 }  
         }  
         debug3("key names ok: [%s]", names);  
         free(s);  
         return 1;  
 }  
   
 static int  
 cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)  
 {  
         u_char *principals, *critical, *exts, *sig_key, *sig;  
         u_int signed_len, plen, clen, sklen, slen, kidlen, elen;  
         Buffer tmp;  
         char *principal;  
         int ret = -1;  
         int v00 = key->type == KEY_DSA_CERT_V00 ||  
             key->type == KEY_RSA_CERT_V00;  
   
         buffer_init(&tmp);  
   
         /* Copy the entire key blob for verification and later serialisation */  
         buffer_append(&key->cert->certblob, blob, blen);  
   
         elen = 0; /* Not touched for v00 certs */  
         principals = exts = critical = sig_key = sig = NULL;  
         if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||  
             buffer_get_int_ret(&key->cert->type, b) != 0 ||  
             (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == 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 ||  
             (critical = buffer_get_string_ret(b, &clen)) == NULL ||  
             (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||  
             (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */  
             buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */  
             (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("%s: Too many principals", __func__);  
                         goto out;  
                 }  
                 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {  
                         error("%s: Principals data invalid", __func__);  
                         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->critical, critical, clen);  
         buffer_append(&tmp, critical, clen);  
         /* validate structure */  
         while (buffer_len(&tmp) != 0) {  
                 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||  
                     buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {  
                         error("%s: critical option data invalid", __func__);  
                         goto out;  
                 }  
         }  
         buffer_clear(&tmp);  
   
         buffer_append(&key->cert->extensions, exts, elen);  
         buffer_append(&tmp, exts, elen);  
         /* validate structure */  
         while (buffer_len(&tmp) != 0) {  
                 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||  
                     buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {  
                         error("%s: extension data invalid", __func__);  
                         goto out;  
                 }  
         }  
         buffer_clear(&tmp);  
   
         if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0))  
             == NULL) {  
                 error("%s: Signature key invalid", __func__);  
                 goto out;  
         }  
         if (!key_type_is_valid_ca(key->cert->signature_key->type)) {  
                 error("%s: Invalid signature key type %s (%d)", __func__,  
                     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:  
                 ret = 0;  
                 break; /* Good signature */  
         case 0:  
                 error("%s: Invalid signature on certificate", __func__);  
                 goto out;  
         case -1:  
                 error("%s: Certificate signature verification failed",  
                     __func__);  
                 goto out;  
         }  
   
  out:  
         buffer_free(&tmp);  
         free(principals);  
         free(critical);  
         free(exts);  
         free(sig_key);  
         free(sig);  
         return ret;          return ret;
 }  }
   
 static Key *  static void
 key_from_blob2(const u_char *blob, u_int blen, int allow_cert)  fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
 {  {
         Buffer b;          if (r == SSH_ERR_INTERNAL_ERROR ||
         int rlen, type, nid = -1;              r == SSH_ERR_ALLOC_FAIL ||
         u_int len;              (extra_fatal != 0 && r == extra_fatal))
         char *ktype = NULL, *curve = NULL;                  fatal("%s: %s", func, ssh_err(r));
         u_char *pk = NULL;  
         Key *key = NULL;  
         EC_POINT *q = NULL;  
   
 #ifdef DEBUG_PK  
         dump_base64(stderr, blob, blen);  
 #endif  
         buffer_init(&b);  
         buffer_append(&b, blob, blen);  
         if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {  
                 error("key_from_blob: can't read key type");  
                 goto out;  
         }  
   
         type = key_type_from_name(ktype);  
         if (key_type_plain(type) == KEY_ECDSA)  
                 nid = key_ecdsa_nid_from_name(ktype);  
         if (!allow_cert && key_type_is_cert(type)) {  
                 error("key_from_blob: certificate not allowed in this context");  
                 goto out;  
         }  
         switch (type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA_CERT:  
                 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */  
                 /* FALLTHROUGH */  
         case KEY_RSA:  
         case KEY_RSA_CERT_V00:  
                 key = key_new(type);  
                 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||  
                     buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {  
                         error("key_from_blob: can't read rsa key");  
                         goto badkey;  
                 }  
 #ifdef DEBUG_PK  
                 RSA_print_fp(stderr, key->rsa, 8);  
 #endif  
                 break;  
         case KEY_DSA_CERT:  
                 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */  
                 /* FALLTHROUGH */  
         case KEY_DSA:  
         case KEY_DSA_CERT_V00:  
                 key = key_new(type);  
                 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->g) == -1 ||  
                     buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {  
                         error("key_from_blob: can't read dsa key");  
                         goto badkey;  
                 }  
 #ifdef DEBUG_PK  
                 DSA_print_fp(stderr, key->dsa, 8);  
 #endif  
                 break;  
         case KEY_ECDSA_CERT:  
                 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */  
                 /* FALLTHROUGH */  
         case KEY_ECDSA:  
                 key = key_new(type);  
                 key->ecdsa_nid = nid;  
                 if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {  
                         error("key_from_blob: can't read ecdsa curve");  
                         goto badkey;  
                 }  
                 if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {  
                         error("key_from_blob: ecdsa curve doesn't match type");  
                         goto badkey;  
                 }  
                 if (key->ecdsa != NULL)  
                         EC_KEY_free(key->ecdsa);  
                 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))  
                     == NULL)  
                         fatal("key_from_blob: EC_KEY_new_by_curve_name failed");  
                 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)  
                         fatal("key_from_blob: EC_POINT_new failed");  
                 if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),  
                     q) == -1) {  
                         error("key_from_blob: can't read ecdsa key point");  
                         goto badkey;  
                 }  
                 if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),  
                     q) != 0)  
                         goto badkey;  
                 if (EC_KEY_set_public_key(key->ecdsa, q) != 1)  
                         fatal("key_from_blob: EC_KEY_set_public_key failed");  
 #ifdef DEBUG_PK  
                 key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);  
 #endif  
                 break;  
 #endif  
         case KEY_ED25519_CERT:  
                 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */  
                 /* FALLTHROUGH */  
         case KEY_ED25519:  
                 if ((pk = buffer_get_string_ret(&b, &len)) == NULL) {  
                         error("key_from_blob: can't read ed25519 key");  
                         goto badkey;  
                 }  
                 if (len != ED25519_PK_SZ) {  
                         error("key_from_blob: ed25519 len %d != %d",  
                             len, ED25519_PK_SZ);  
                         goto badkey;  
                 }  
                 key = key_new(type);  
                 key->ed25519_pk = pk;  
                 pk = NULL;  
                 break;  
         case KEY_UNSPEC:  
                 key = key_new(type);  
                 break;  
         default:  
                 error("key_from_blob: cannot handle type %s", ktype);  
                 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);  
         if (key != NULL && rlen != 0)  
                 error("key_from_blob: remaining bytes in key blob %d", rlen);  
  out:  
         free(ktype);  
         free(curve);  
         free(pk);  
         if (q != NULL)  
                 EC_POINT_free(q);  
         buffer_free(&b);  
         return key;  
   
  badkey:  
         key_free(key);  
         key = NULL;  
         goto out;  
 }  }
   
 Key *  Key *
 key_from_blob(const u_char *blob, u_int blen)  key_from_blob(const u_char *blob, u_int blen)
 {  {
         return key_from_blob2(blob, blen, 1);          int r;
           Key *ret = NULL;
   
           if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
                   fatal_on_fatal_errors(r, __func__, 0);
                   error("%s: %s", __func__, ssh_err(r));
                   return NULL;
           }
           return ret;
 }  }
   
 static int  int
 to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)  key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
 {  {
         Buffer b;          u_char *blob;
         int len, type;          size_t blen;
           int r;
   
         if (blobp != NULL)          if (blobp != NULL)
                 *blobp = NULL;                  *blobp = NULL;
         if (lenp != NULL)          if (lenp != NULL)
                 *lenp = 0;                  *lenp = 0;
         if (key == NULL) {          if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
                 error("key_to_blob: key == NULL");                  fatal_on_fatal_errors(r, __func__, 0);
                   error("%s: %s", __func__, ssh_err(r));
                 return 0;                  return 0;
         }          }
         buffer_init(&b);          if (blen > INT_MAX)
         type = force_plain ? key_type_plain(key->type) : key->type;                  fatal("%s: giant len %zu", __func__, blen);
         switch (type) {          if (blobp != NULL)
 #ifdef WITH_OPENSSL                  *blobp = blob;
         case KEY_DSA_CERT_V00:  
         case KEY_RSA_CERT_V00:  
         case KEY_DSA_CERT:  
         case KEY_ECDSA_CERT:  
         case KEY_RSA_CERT:  
 #endif  
         case KEY_ED25519_CERT:  
                 /* Use the existing blob */  
                 buffer_append(&b, buffer_ptr(&key->cert->certblob),  
                     buffer_len(&key->cert->certblob));  
                 break;  
 #ifdef WITH_OPENSSL  
         case KEY_DSA:  
                 buffer_put_cstring(&b,  
                     key_ssh_name_from_type_nid(type, key->ecdsa_nid));  
                 buffer_put_bignum2(&b, key->dsa->p);  
                 buffer_put_bignum2(&b, key->dsa->q);  
                 buffer_put_bignum2(&b, key->dsa->g);  
                 buffer_put_bignum2(&b, key->dsa->pub_key);  
                 break;  
         case KEY_ECDSA:  
                 buffer_put_cstring(&b,  
                     key_ssh_name_from_type_nid(type, key->ecdsa_nid));  
                 buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));  
                 buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),  
                     EC_KEY_get0_public_key(key->ecdsa));  
                 break;  
         case KEY_RSA:  
                 buffer_put_cstring(&b,  
                     key_ssh_name_from_type_nid(type, key->ecdsa_nid));  
                 buffer_put_bignum2(&b, key->rsa->e);  
                 buffer_put_bignum2(&b, key->rsa->n);  
                 break;  
 #endif  
         case KEY_ED25519:  
                 buffer_put_cstring(&b,  
                     key_ssh_name_from_type_nid(type, key->ecdsa_nid));  
                 buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ);  
                 break;  
         default:  
                 error("key_to_blob: unsupported key type %d", key->type);  
                 buffer_free(&b);  
                 return 0;  
         }  
         len = buffer_len(&b);  
         if (lenp != NULL)          if (lenp != NULL)
                 *lenp = len;                  *lenp = blen;
         if (blobp != NULL) {          return blen;
                 *blobp = xmalloc(len);  
                 memcpy(*blobp, buffer_ptr(&b), len);  
         }  
         explicit_bzero(buffer_ptr(&b), len);  
         buffer_free(&b);  
         return len;  
 }  }
   
 int  int
 key_to_blob(const Key *key, u_char **blobp, u_int *lenp)  key_sign(const Key *key, u_char **sigp, u_int *lenp,
 {  
         return to_blob(key, blobp, lenp, 0);  
 }  
   
 int  
 key_sign(  
     const Key *key,  
     u_char **sigp, u_int *lenp,  
     const u_char *data, u_int datalen)      const u_char *data, u_int datalen)
 {  {
         switch (key->type) {          int r;
 #ifdef WITH_OPENSSL          u_char *sig;
         case KEY_DSA_CERT_V00:          size_t siglen;
         case KEY_DSA_CERT:  
         case KEY_DSA:          if (sigp != NULL)
                 return ssh_dss_sign(key, sigp, lenp, data, datalen);                  *sigp = NULL;
         case KEY_ECDSA_CERT:          if (lenp != NULL)
         case KEY_ECDSA:                  *lenp = 0;
                 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen);          if ((r = sshkey_sign(key, &sig, &siglen,
         case KEY_RSA_CERT_V00:              data, datalen, datafellows)) != 0) {
         case KEY_RSA_CERT:                  fatal_on_fatal_errors(r, __func__, 0);
         case KEY_RSA:                  error("%s: %s", __func__, ssh_err(r));
                 return ssh_rsa_sign(key, sigp, lenp, data, datalen);  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 return ssh_ed25519_sign(key, sigp, lenp, data, datalen);  
         default:  
                 error("key_sign: invalid key type %d", key->type);  
                 return -1;                  return -1;
         }          }
           if (siglen > INT_MAX)
                   fatal("%s: giant len %zu", __func__, siglen);
           if (sigp != NULL)
                   *sigp = sig;
           if (lenp != NULL)
                   *lenp = siglen;
           return 0;
 }  }
   
 /*  
  * key_verify returns 1 for a correct signature, 0 for an incorrect signature  
  * and -1 on error.  
  */  
 int  int
 key_verify(  key_verify(const Key *key, const u_char *signature, u_int signaturelen,
     const Key *key,  
     const u_char *signature, u_int signaturelen,  
     const u_char *data, u_int datalen)      const u_char *data, u_int datalen)
 {  {
         if (signaturelen == 0)          int r;
                 return -1;  
   
         switch (key->type) {          if ((r = sshkey_verify(key, signature, signaturelen,
 #ifdef WITH_OPENSSL              data, datalen, datafellows)) != 0) {
         case KEY_DSA_CERT_V00:                  fatal_on_fatal_errors(r, __func__, 0);
         case KEY_DSA_CERT:                  error("%s: %s", __func__, ssh_err(r));
         case KEY_DSA:                  return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
                 return ssh_dss_verify(key, signature, signaturelen, data, datalen);  
         case KEY_ECDSA_CERT:  
         case KEY_ECDSA:  
                 return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
         case KEY_RSA:  
                 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);  
 #endif  
         case KEY_ED25519:  
         case KEY_ED25519_CERT:  
                 return ssh_ed25519_verify(key, signature, signaturelen, data, datalen);  
         default:  
                 error("key_verify: invalid key type %d", key->type);  
                 return -1;  
         }          }
           return 1;
 }  }
   
 /* Converts a private to a public key */  
 Key *  Key *
 key_demote(const Key *k)  key_demote(const Key *k)
 {  {
         Key *pk;          int r;
           Key *ret = NULL;
   
         pk = xcalloc(1, sizeof(*pk));          if ((r = sshkey_demote(k, &ret)) != 0)
         pk->type = k->type;                  fatal("%s: %s", __func__, ssh_err(r));
         pk->flags = k->flags;          return ret;
         pk->ecdsa_nid = k->ecdsa_nid;  
         pk->dsa = NULL;  
         pk->ecdsa = NULL;  
         pk->rsa = NULL;  
         pk->ed25519_pk = NULL;  
         pk->ed25519_sk = NULL;  
   
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 key_cert_copy(k, pk);  
                 /* FALLTHROUGH */  
         case KEY_RSA1:  
         case KEY_RSA:  
                 if ((pk->rsa = RSA_new()) == NULL)  
                         fatal("key_demote: RSA_new failed");  
                 if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)  
                         fatal("key_demote: BN_dup failed");  
                 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)  
                         fatal("key_demote: BN_dup failed");  
                 break;  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 key_cert_copy(k, pk);  
                 /* FALLTHROUGH */  
         case KEY_DSA:  
                 if ((pk->dsa = DSA_new()) == NULL)  
                         fatal("key_demote: DSA_new failed");  
                 if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)  
                         fatal("key_demote: BN_dup failed");  
                 if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)  
                         fatal("key_demote: BN_dup failed");  
                 if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)  
                         fatal("key_demote: BN_dup failed");  
                 if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)  
                         fatal("key_demote: BN_dup failed");  
                 break;  
         case KEY_ECDSA_CERT:  
                 key_cert_copy(k, pk);  
                 /* FALLTHROUGH */  
         case KEY_ECDSA:  
                 if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)  
                         fatal("key_demote: EC_KEY_new_by_curve_name failed");  
                 if (EC_KEY_set_public_key(pk->ecdsa,  
                     EC_KEY_get0_public_key(k->ecdsa)) != 1)  
                         fatal("key_demote: EC_KEY_set_public_key failed");  
                 break;  
 #endif  
         case KEY_ED25519_CERT:  
                 key_cert_copy(k, pk);  
                 /* FALLTHROUGH */  
         case KEY_ED25519:  
                 if (k->ed25519_pk != NULL) {  
                         pk->ed25519_pk = xmalloc(ED25519_PK_SZ);  
                         memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);  
                 }  
                 break;  
         default:  
                 fatal("key_demote: bad key type %d", k->type);  
                 break;  
         }  
   
         return (pk);  
 }  }
   
 int  int
 key_is_cert(const Key *k)  
 {  
         if (k == NULL)  
                 return 0;  
         return key_type_is_cert(k->type);  
 }  
   
 /* Return the cert-less equivalent to a certified key type */  
 int  
 key_type_plain(int type)  
 {  
         switch (type) {  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 return KEY_RSA;  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 return KEY_DSA;  
         case KEY_ECDSA_CERT:  
                 return KEY_ECDSA;  
         case KEY_ED25519_CERT:  
                 return KEY_ED25519;  
         default:  
                 return type;  
         }  
 }  
   
 /* Convert a plain key to their _CERT equivalent */  
 int  
 key_to_certified(Key *k, int legacy)  key_to_certified(Key *k, int legacy)
 {  {
         switch (k->type) {          int r;
         case KEY_RSA:  
                 k->cert = cert_new();          if ((r = sshkey_to_certified(k, legacy)) != 0) {
                 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;                  fatal_on_fatal_errors(r, __func__, 0);
                 return 0;                  error("%s: %s", __func__, ssh_err(r));
         case KEY_DSA:  
                 k->cert = cert_new();  
                 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;  
                 return 0;  
         case KEY_ECDSA:  
                 if (legacy)  
                         fatal("%s: legacy ECDSA certificates are not supported",  
                             __func__);  
                 k->cert = cert_new();  
                 k->type = KEY_ECDSA_CERT;  
                 return 0;  
         case KEY_ED25519:  
                 if (legacy)  
                         fatal("%s: legacy ED25519 certificates are not "  
                             "supported", __func__);  
                 k->cert = cert_new();  
                 k->type = KEY_ED25519_CERT;  
                 return 0;  
         default:  
                 error("%s: key has incorrect type %s", __func__, key_type(k));  
                 return -1;                  return -1;
         }          }
           return 0;
 }  }
   
 /* Convert a certificate to its raw key equivalent */  
 int  int
 key_drop_cert(Key *k)  key_drop_cert(Key *k)
 {  {
         if (!key_type_is_cert(k->type)) {          int r;
                 error("%s: key has incorrect type %s", __func__, key_type(k));  
           if ((r = sshkey_drop_cert(k)) != 0) {
                   fatal_on_fatal_errors(r, __func__, 0);
                   error("%s: %s", __func__, ssh_err(r));
                 return -1;                  return -1;
         }          }
         cert_free(k->cert);  
         k->cert = NULL;  
         k->type = key_type_plain(k->type);  
         return 0;          return 0;
 }  }
   
 /* Sign a certified key, (re-)generating the signed certblob. */  
 int  int
 key_certify(Key *k, Key *ca)  key_certify(Key *k, Key *ca)
 {  {
         Buffer principals;          int r;
         u_char *ca_blob, *sig_blob, nonce[32];  
         u_int i, ca_len, sig_len;  
   
         if (k->cert == NULL) {          if ((r = sshkey_certify(k, ca)) != 0) {
                 error("%s: key lacks cert info", __func__);                  fatal_on_fatal_errors(r, __func__, 0);
                   error("%s: %s", __func__, ssh_err(r));
                 return -1;                  return -1;
         }          }
   
         if (!key_is_cert(k)) {  
                 error("%s: certificate has unknown type %d", __func__,  
                     k->cert->type);  
                 return -1;  
         }  
   
         if (!key_type_is_valid_ca(ca->type)) {  
                 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));  
   
         /* -v01 certs put nonce first */  
         arc4random_buf(&nonce, sizeof(nonce));  
         if (!key_cert_is_legacy(k))  
                 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));  
   
         /* XXX this substantially duplicates to_blob(); refactor */  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_DSA_CERT_V00:  
         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_ECDSA_CERT:  
                 buffer_put_cstring(&k->cert->certblob,  
                     key_curve_nid_to_name(k->ecdsa_nid));  
                 buffer_put_ecpoint(&k->cert->certblob,  
                     EC_KEY_get0_group(k->ecdsa),  
                     EC_KEY_get0_public_key(k->ecdsa));  
                 break;  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);  
                 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);  
                 break;  
 #endif  
         case KEY_ED25519_CERT:  
                 buffer_put_string(&k->cert->certblob,  
                     k->ed25519_pk, ED25519_PK_SZ);  
                 break;  
         default:  
                 error("%s: key has incorrect type %s", __func__, key_type(k));  
                 buffer_clear(&k->cert->certblob);  
                 free(ca_blob);  
                 return -1;  
         }  
   
         /* -v01 certs have a serial number next */  
         if (!key_cert_is_legacy(k))  
                 buffer_put_int64(&k->cert->certblob, k->cert->serial);  
   
         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->critical), buffer_len(&k->cert->critical));  
   
         /* -v01 certs have non-critical options here */  
         if (!key_cert_is_legacy(k)) {  
                 buffer_put_string(&k->cert->certblob,  
                     buffer_ptr(&k->cert->extensions),  
                     buffer_len(&k->cert->extensions));  
         }  
   
         /* -v00 certs put the nonce at the end */  
         if (key_cert_is_legacy(k))  
                 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);  
         free(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);  
         free(sig_blob);  
   
         return 0;          return 0;
 }  }
   
Line 2089 
Line 242 
 key_cert_check_authority(const Key *k, int want_host, int require_principal,  key_cert_check_authority(const Key *k, int want_host, int require_principal,
     const char *name, const char **reason)      const char *name, const char **reason)
 {  {
         u_int i, principal_matches;          int r;
         time_t now = time(NULL);  
   
         if (want_host) {          if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
                 if (k->cert->type != SSH2_CERT_TYPE_HOST) {              name, reason)) != 0) {
                         *reason = "Certificate invalid: not a host certificate";                  fatal_on_fatal_errors(r, __func__, 0);
                         return -1;                  error("%s: %s", __func__, ssh_err(r));
                 }  
         } 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;                  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 if (name != NULL) {  
                 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;          return 0;
 }  }
   
   #ifdef WITH_OPENSSL
 int  int
 key_cert_is_legacy(const Key *k)  key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
 {  {
         switch (k->type) {          int r;
         case KEY_DSA_CERT_V00:  
         case KEY_RSA_CERT_V00:          if ((r = sshkey_ec_validate_public(group, public)) != 0) {
                 return 1;                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
         default:                  error("%s: %s", __func__, ssh_err(r));
                 return 0;                  return -1;
         }          }
           return 0;
 }  }
   
 #ifdef WITH_OPENSSL  
 /* XXX: these are really begging for a table-driven approach */  
 int  int
 key_curve_name_to_nid(const char *name)  key_ec_validate_private(const EC_KEY *key)
 {  {
         if (strcmp(name, "nistp256") == 0)          int r;
                 return NID_X9_62_prime256v1;  
         else if (strcmp(name, "nistp384") == 0)  
                 return NID_secp384r1;  
         else if (strcmp(name, "nistp521") == 0)  
                 return NID_secp521r1;  
   
         debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);          if ((r = sshkey_ec_validate_private(key)) != 0) {
         return -1;                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                   error("%s: %s", __func__, ssh_err(r));
                   return -1;
           }
           return 0;
 }  }
   #endif /* WITH_OPENSSL */
   
 u_int  void
 key_curve_nid_to_bits(int nid)  key_private_serialize(const Key *key, struct sshbuf *b)
 {  {
         switch (nid) {          int r;
         case NID_X9_62_prime256v1:  
                 return 256;          if ((r = sshkey_private_serialize(key, b)) != 0)
         case NID_secp384r1:                  fatal("%s: %s", __func__, ssh_err(r));
                 return 384;  
         case NID_secp521r1:  
                 return 521;  
         default:  
                 error("%s: unsupported EC curve nid %d", __func__, nid);  
                 return 0;  
         }  
 }  }
   
 const char *  Key *
 key_curve_nid_to_name(int nid)  key_private_deserialize(struct sshbuf *blob)
 {  {
         if (nid == NID_X9_62_prime256v1)          int r;
                 return "nistp256";          Key *ret = NULL;
         else if (nid == NID_secp384r1)  
                 return "nistp384";  
         else if (nid == NID_secp521r1)  
                 return "nistp521";  
   
         error("%s: unsupported EC curve nid %d", __func__, nid);          if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
         return NULL;                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                   error("%s: %s", __func__, ssh_err(r));
                   return NULL;
           }
           return ret;
 }  }
   
   /* authfile.c */
   
 int  int
 key_ec_nid_to_hash_alg(int nid)  key_save_private(Key *key, const char *filename, const char *passphrase,
       const char *comment, int force_new_format, const char *new_format_cipher,
       int new_format_rounds)
 {  {
         int kbits = key_curve_nid_to_bits(nid);          int r;
   
         if (kbits == 0)          if ((r = sshkey_save_private(key, filename, passphrase, comment,
                 fatal("%s: invalid nid %d", __func__, nid);              force_new_format, new_format_cipher, new_format_rounds)) != 0) {
         /* RFC5656 section 6.2.1 */                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
         if (kbits <= 256)                  error("%s: %s", __func__, ssh_err(r));
                 return SSH_DIGEST_SHA256;                  return 0;
         else if (kbits <= 384)          }
                 return SSH_DIGEST_SHA384;          return 1;
         else  
                 return SSH_DIGEST_SHA512;  
 }  }
   
 int  int
 key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)  key_load_file(int fd, const char *filename, struct sshbuf *blob)
 {  {
         BN_CTX *bnctx;          int r;
         EC_POINT *nq = NULL;  
         BIGNUM *order, *x, *y, *tmp;  
         int ret = -1;  
   
         if ((bnctx = BN_CTX_new()) == NULL)          if ((r = sshkey_load_file(fd, filename, blob)) != 0) {
                 fatal("%s: BN_CTX_new failed", __func__);                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
         BN_CTX_start(bnctx);                  error("%s: %s", __func__, ssh_err(r));
                   return 0;
         /*  
          * We shouldn't ever hit this case because bignum_get_ecpoint()  
          * refuses to load GF2m points.  
          */  
         if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=  
             NID_X9_62_prime_field) {  
                 error("%s: group is not a prime field", __func__);  
                 goto out;  
         }          }
           return 1;
   }
   
         /* Q != infinity */  Key *
         if (EC_POINT_is_at_infinity(group, public)) {  key_load_cert(const char *filename)
                 error("%s: received degenerate public key (infinity)",  {
                     __func__);          int r;
                 goto out;          Key *ret = NULL;
   
           if ((r = sshkey_load_cert(filename, &ret)) != 0) {
                   fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                   if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
                           debug("%s: %s", __func__, ssh_err(r));
                   else
                           error("%s: %s", __func__, ssh_err(r));
                   return NULL;
         }          }
           return ret;
   
         if ((x = BN_CTX_get(bnctx)) == NULL ||  }
             (y = BN_CTX_get(bnctx)) == NULL ||  
             (order = BN_CTX_get(bnctx)) == NULL ||  
             (tmp = BN_CTX_get(bnctx)) == NULL)  
                 fatal("%s: BN_CTX_get failed", __func__);  
   
         /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */  Key *
         if (EC_GROUP_get_order(group, order, bnctx) != 1)  key_load_public(const char *filename, char **commentp)
                 fatal("%s: EC_GROUP_get_order failed", __func__);  {
         if (EC_POINT_get_affine_coordinates_GFp(group, public,          int r;
             x, y, bnctx) != 1)          Key *ret = NULL;
                 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);  
         if (BN_num_bits(x) <= BN_num_bits(order) / 2) {  
                 error("%s: public key x coordinate too small: "  
                     "bits(x) = %d, bits(order)/2 = %d", __func__,  
                     BN_num_bits(x), BN_num_bits(order) / 2);  
                 goto out;  
         }  
         if (BN_num_bits(y) <= BN_num_bits(order) / 2) {  
                 error("%s: public key y coordinate too small: "  
                     "bits(y) = %d, bits(order)/2 = %d", __func__,  
                     BN_num_bits(x), BN_num_bits(order) / 2);  
                 goto out;  
         }  
   
         /* nQ == infinity (n == order of subgroup) */          if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
         if ((nq = EC_POINT_new(group)) == NULL)                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                 fatal("%s: BN_CTX_tmp failed", __func__);                  if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
         if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)                          debug("%s: %s", __func__, ssh_err(r));
                 fatal("%s: EC_GROUP_mul failed", __func__);                  else
         if (EC_POINT_is_at_infinity(group, nq) != 1) {                          error("%s: %s", __func__, ssh_err(r));
                 error("%s: received degenerate public key (nQ != infinity)",                  return NULL;
                     __func__);  
                 goto out;  
         }          }
           return ret;
   }
   
         /* x < order - 1, y < order - 1 */  Key *
         if (!BN_sub(tmp, order, BN_value_one()))  key_load_private(const char *path, const char *passphrase,
                 fatal("%s: BN_sub failed", __func__);      char **commentp)
         if (BN_cmp(x, tmp) >= 0) {  {
                 error("%s: public key x coordinate >= group order - 1",          int r;
                     __func__);          Key *ret = NULL;
                 goto out;  
           if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
                   fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                   if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
                           debug("%s: %s", __func__, ssh_err(r));
                   else
                           error("%s: %s", __func__, ssh_err(r));
                   return NULL;
         }          }
         if (BN_cmp(y, tmp) >= 0) {  
                 error("%s: public key y coordinate >= group order - 1",  
                     __func__);  
                 goto out;  
         }  
         ret = 0;  
  out:  
         BN_CTX_free(bnctx);  
         EC_POINT_free(nq);  
         return ret;          return ret;
 }  }
   
 int  Key *
 key_ec_validate_private(const EC_KEY *key)  key_load_private_cert(int type, const char *filename, const char *passphrase,
       int *perm_ok)
 {  {
         BN_CTX *bnctx;          int r;
         BIGNUM *order, *tmp;          Key *ret = NULL;
         int ret = -1;  
   
         if ((bnctx = BN_CTX_new()) == NULL)          if ((r = sshkey_load_private_cert(type, filename, passphrase,
                 fatal("%s: BN_CTX_new failed", __func__);              &ret, perm_ok)) != 0) {
         BN_CTX_start(bnctx);                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                   if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
         if ((order = BN_CTX_get(bnctx)) == NULL ||                          debug("%s: %s", __func__, ssh_err(r));
             (tmp = BN_CTX_get(bnctx)) == NULL)                  else
                 fatal("%s: BN_CTX_get failed", __func__);                          error("%s: %s", __func__, ssh_err(r));
                   return NULL;
         /* log2(private) > log2(order)/2 */  
         if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)  
                 fatal("%s: EC_GROUP_get_order failed", __func__);  
         if (BN_num_bits(EC_KEY_get0_private_key(key)) <=  
             BN_num_bits(order) / 2) {  
                 error("%s: private key too small: "  
                     "bits(y) = %d, bits(order)/2 = %d", __func__,  
                     BN_num_bits(EC_KEY_get0_private_key(key)),  
                     BN_num_bits(order) / 2);  
                 goto out;  
         }          }
   
         /* private < order - 1 */  
         if (!BN_sub(tmp, order, BN_value_one()))  
                 fatal("%s: BN_sub failed", __func__);  
         if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) {  
                 error("%s: private key >= group order - 1", __func__);  
                 goto out;  
         }  
         ret = 0;  
  out:  
         BN_CTX_free(bnctx);  
         return ret;          return ret;
 }  }
 #endif  
   
 #if defined(DEBUG_KEXECDH) || defined(DEBUG_PK)  Key *
 void  key_load_private_type(int type, const char *filename, const char *passphrase,
 key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)      char **commentp, int *perm_ok)
 {  {
         BIGNUM *x, *y;          int r;
         BN_CTX *bnctx;          Key *ret = NULL;
   
         if (point == NULL) {          if ((r = sshkey_load_private_type(type, filename, passphrase,
                 fputs("point=(NULL)\n", stderr);              &ret, commentp, perm_ok)) != 0) {
                 return;                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                   if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
                           debug("%s: %s", __func__, ssh_err(r));
                   else
                           error("%s: %s", __func__, ssh_err(r));
                   return NULL;
         }          }
         if ((bnctx = BN_CTX_new()) == NULL)          return ret;
                 fatal("%s: BN_CTX_new failed", __func__);  
         BN_CTX_start(bnctx);  
         if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)  
                 fatal("%s: BN_CTX_get failed", __func__);  
         if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=  
             NID_X9_62_prime_field)  
                 fatal("%s: group is not a prime field", __func__);  
         if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)  
                 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);  
         fputs("x=", stderr);  
         BN_print_fp(stderr, x);  
         fputs("\ny=", stderr);  
         BN_print_fp(stderr, y);  
         fputs("\n", stderr);  
         BN_CTX_free(bnctx);  
 }  }
   
 void  #ifdef WITH_OPENSSL
 key_dump_ec_key(const EC_KEY *key)  Key *
   key_load_private_pem(int fd, int type, const char *passphrase,
       char **commentp)
 {  {
         const BIGNUM *exponent;          int r;
           Key *ret = NULL;
   
         key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key));          if ((r = sshkey_load_private_pem(fd, type, passphrase,
         fputs("exponent=", stderr);               &ret, commentp)) != 0) {
         if ((exponent = EC_KEY_get0_private_key(key)) == NULL)                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
                 fputs("(NULL)", stderr);                  error("%s: %s", __func__, ssh_err(r));
         else                  return NULL;
                 BN_print_fp(stderr, EC_KEY_get0_private_key(key));          }
         fputs("\n", stderr);          return ret;
 }  }
 #endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */  #endif /* WITH_OPENSSL */
   
 void  int
 key_private_serialize(const Key *key, Buffer *b)  key_perm_ok(int fd, const char *filename)
 {  {
         buffer_put_cstring(b, key_ssh_name(key));          return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
         switch (key->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA:  
                 buffer_put_bignum2(b, key->rsa->n);  
                 buffer_put_bignum2(b, key->rsa->e);  
                 buffer_put_bignum2(b, key->rsa->d);  
                 buffer_put_bignum2(b, key->rsa->iqmp);  
                 buffer_put_bignum2(b, key->rsa->p);  
                 buffer_put_bignum2(b, key->rsa->q);  
                 break;  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)  
                         fatal("%s: no cert/certblob", __func__);  
                 buffer_put_string(b, buffer_ptr(&key->cert->certblob),  
                     buffer_len(&key->cert->certblob));  
                 buffer_put_bignum2(b, key->rsa->d);  
                 buffer_put_bignum2(b, key->rsa->iqmp);  
                 buffer_put_bignum2(b, key->rsa->p);  
                 buffer_put_bignum2(b, key->rsa->q);  
                 break;  
         case KEY_DSA:  
                 buffer_put_bignum2(b, key->dsa->p);  
                 buffer_put_bignum2(b, key->dsa->q);  
                 buffer_put_bignum2(b, key->dsa->g);  
                 buffer_put_bignum2(b, key->dsa->pub_key);  
                 buffer_put_bignum2(b, key->dsa->priv_key);  
                 break;  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)  
                         fatal("%s: no cert/certblob", __func__);  
                 buffer_put_string(b, buffer_ptr(&key->cert->certblob),  
                     buffer_len(&key->cert->certblob));  
                 buffer_put_bignum2(b, key->dsa->priv_key);  
                 break;  
         case KEY_ECDSA:  
                 buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid));  
                 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),  
                     EC_KEY_get0_public_key(key->ecdsa));  
                 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));  
                 break;  
         case KEY_ECDSA_CERT:  
                 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)  
                         fatal("%s: no cert/certblob", __func__);  
                 buffer_put_string(b, buffer_ptr(&key->cert->certblob),  
                     buffer_len(&key->cert->certblob));  
                 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));  
                 break;  
 #endif  
         case KEY_ED25519:  
                 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);  
                 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);  
                 break;  
         case KEY_ED25519_CERT:  
                 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)  
                         fatal("%s: no cert/certblob", __func__);  
                 buffer_put_string(b, buffer_ptr(&key->cert->certblob),  
                     buffer_len(&key->cert->certblob));  
                 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);  
                 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);  
                 break;  
         }  
 }  }
   
 Key *  int
 key_private_deserialize(Buffer *blob)  key_in_file(Key *key, const char *filename, int strict_type)
 {  {
         char *type_name;          int r;
         Key *k = NULL;  
         u_char *cert;  
         u_int len, pklen, sklen;  
         int type;  
 #ifdef WITH_OPENSSL  
         char *curve;  
         BIGNUM *exponent;  
         EC_POINT *q;  
 #endif  
   
         type_name = buffer_get_string(blob, NULL);          if ((r = sshkey_in_file(key, filename, strict_type)) != 0) {
         type = key_type_from_name(type_name);                  fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
         switch (type) {                  if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
 #ifdef WITH_OPENSSL                          return 0;
         case KEY_DSA:                  error("%s: %s", __func__, ssh_err(r));
                 k = key_new_private(type);                  return r == SSH_ERR_KEY_NOT_FOUND ? 0 : -1;
                 buffer_get_bignum2(blob, k->dsa->p);  
                 buffer_get_bignum2(blob, k->dsa->q);  
                 buffer_get_bignum2(blob, k->dsa->g);  
                 buffer_get_bignum2(blob, k->dsa->pub_key);  
                 buffer_get_bignum2(blob, k->dsa->priv_key);  
                 break;  
         case KEY_DSA_CERT_V00:  
         case KEY_DSA_CERT:  
                 cert = buffer_get_string(blob, &len);  
                 if ((k = key_from_blob(cert, len)) == NULL)  
                         fatal("Certificate parse failed");  
                 free(cert);  
                 key_add_private(k);  
                 buffer_get_bignum2(blob, k->dsa->priv_key);  
                 break;  
         case KEY_ECDSA:  
                 k = key_new_private(type);  
                 k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);  
                 curve = buffer_get_string(blob, NULL);  
                 if (k->ecdsa_nid != key_curve_name_to_nid(curve))  
                         fatal("%s: curve names mismatch", __func__);  
                 free(curve);  
                 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);  
                 if (k->ecdsa == NULL)  
                         fatal("%s: EC_KEY_new_by_curve_name failed",  
                             __func__);  
                 q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));  
                 if (q == NULL)  
                         fatal("%s: BN_new failed", __func__);  
                 if ((exponent = BN_new()) == NULL)  
                         fatal("%s: BN_new failed", __func__);  
                 buffer_get_ecpoint(blob,  
                         EC_KEY_get0_group(k->ecdsa), q);  
                 buffer_get_bignum2(blob, exponent);  
                 if (EC_KEY_set_public_key(k->ecdsa, q) != 1)  
                         fatal("%s: EC_KEY_set_public_key failed",  
                             __func__);  
                 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)  
                         fatal("%s: EC_KEY_set_private_key failed",  
                             __func__);  
                 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),  
                     EC_KEY_get0_public_key(k->ecdsa)) != 0)  
                         fatal("%s: bad ECDSA public key", __func__);  
                 if (key_ec_validate_private(k->ecdsa) != 0)  
                         fatal("%s: bad ECDSA private key", __func__);  
                 BN_clear_free(exponent);  
                 EC_POINT_free(q);  
                 break;  
         case KEY_ECDSA_CERT:  
                 cert = buffer_get_string(blob, &len);  
                 if ((k = key_from_blob(cert, len)) == NULL)  
                         fatal("Certificate parse failed");  
                 free(cert);  
                 key_add_private(k);  
                 if ((exponent = BN_new()) == NULL)  
                         fatal("%s: BN_new failed", __func__);  
                 buffer_get_bignum2(blob, exponent);  
                 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)  
                         fatal("%s: EC_KEY_set_private_key failed",  
                             __func__);  
                 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),  
                     EC_KEY_get0_public_key(k->ecdsa)) != 0 ||  
                     key_ec_validate_private(k->ecdsa) != 0)  
                         fatal("%s: bad ECDSA key", __func__);  
                 BN_clear_free(exponent);  
                 break;  
         case KEY_RSA:  
                 k = key_new_private(type);  
                 buffer_get_bignum2(blob, k->rsa->n);  
                 buffer_get_bignum2(blob, k->rsa->e);  
                 buffer_get_bignum2(blob, k->rsa->d);  
                 buffer_get_bignum2(blob, k->rsa->iqmp);  
                 buffer_get_bignum2(blob, k->rsa->p);  
                 buffer_get_bignum2(blob, k->rsa->q);  
   
                 /* Generate additional parameters */  
                 rsa_generate_additional_parameters(k->rsa);  
                 break;  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
                 cert = buffer_get_string(blob, &len);  
                 if ((k = key_from_blob(cert, len)) == NULL)  
                         fatal("Certificate parse failed");  
                 free(cert);  
                 key_add_private(k);  
                 buffer_get_bignum2(blob, k->rsa->d);  
                 buffer_get_bignum2(blob, k->rsa->iqmp);  
                 buffer_get_bignum2(blob, k->rsa->p);  
                 buffer_get_bignum2(blob, k->rsa->q);  
                 break;  
 #endif  
         case KEY_ED25519:  
                 k = key_new_private(type);  
                 k->ed25519_pk = buffer_get_string(blob, &pklen);  
                 k->ed25519_sk = buffer_get_string(blob, &sklen);  
                 if (pklen != ED25519_PK_SZ)  
                         fatal("%s: ed25519 pklen %d != %d",  
                             __func__, pklen, ED25519_PK_SZ);  
                 if (sklen != ED25519_SK_SZ)  
                         fatal("%s: ed25519 sklen %d != %d",  
                             __func__, sklen, ED25519_SK_SZ);  
                 break;  
         case KEY_ED25519_CERT:  
                 cert = buffer_get_string(blob, &len);  
                 if ((k = key_from_blob(cert, len)) == NULL)  
                         fatal("Certificate parse failed");  
                 free(cert);  
                 key_add_private(k);  
                 k->ed25519_pk = buffer_get_string(blob, &pklen);  
                 k->ed25519_sk = buffer_get_string(blob, &sklen);  
                 if (pklen != ED25519_PK_SZ)  
                         fatal("%s: ed25519 pklen %d != %d",  
                             __func__, pklen, ED25519_PK_SZ);  
                 if (sklen != ED25519_SK_SZ)  
                         fatal("%s: ed25519 sklen %d != %d",  
                             __func__, sklen, ED25519_SK_SZ);  
                 break;  
         default:  
                 free(type_name);  
                 buffer_clear(blob);  
                 return NULL;  
         }          }
         free(type_name);          return 1;
   
         /* enable blinding */  
         switch (k->type) {  
 #ifdef WITH_OPENSSL  
         case KEY_RSA:  
         case KEY_RSA_CERT_V00:  
         case KEY_RSA_CERT:  
         case KEY_RSA1:  
                 if (RSA_blinding_on(k->rsa, NULL) != 1) {  
                         error("%s: RSA_blinding_on failed", __func__);  
                         key_free(k);  
                         return NULL;  
                 }  
                 break;  
 #endif  
         }  
         return k;  
 }  }

Legend:
Removed from v.1.117  
changed lines
  Added in v.1.118