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

Diff for /src/usr.bin/ssh/sshkey.c between version 1.61 and 1.62

version 1.61, 2018/02/14 16:03:32 version 1.62, 2018/02/23 15:58:38
Line 51 
Line 51 
 #include "digest.h"  #include "digest.h"
 #define SSHKEY_INTERNAL  #define SSHKEY_INTERNAL
 #include "sshkey.h"  #include "sshkey.h"
   #include "sshkey-xmss.h"
 #include "match.h"  #include "match.h"
   
   #include "xmss_fast.h"
   
 /* openssh private key file format */  /* openssh private key file format */
 #define MARK_BEGIN              "-----BEGIN OPENSSH PRIVATE KEY-----\n"  #define MARK_BEGIN              "-----BEGIN OPENSSH PRIVATE KEY-----\n"
 #define MARK_END                "-----END OPENSSH PRIVATE KEY-----\n"  #define MARK_END                "-----END OPENSSH PRIVATE KEY-----\n"
Line 67 
Line 70 
 /* Version identification string for SSH v1 identity files. */  /* Version identification string for SSH v1 identity files. */
 #define LEGACY_BEGIN            "SSH PRIVATE KEY FILE FORMAT 1.1\n"  #define LEGACY_BEGIN            "SSH PRIVATE KEY FILE FORMAT 1.1\n"
   
   int     sshkey_private_serialize_opt(const struct sshkey *key,
       struct sshbuf *buf, enum sshkey_serialize_rep);
 static int sshkey_from_blob_internal(struct sshbuf *buf,  static int sshkey_from_blob_internal(struct sshbuf *buf,
     struct sshkey **keyp, int allow_cert);      struct sshkey **keyp, int allow_cert);
   
Line 83 
Line 88 
         { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },          { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },
         { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",          { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
             KEY_ED25519_CERT, 0, 1, 0 },              KEY_ED25519_CERT, 0, 1, 0 },
   #ifdef WITH_XMSS
           { "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 },
           { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT",
               KEY_XMSS_CERT, 0, 1, 0 },
   #endif /* WITH_XMSS */
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },          { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
         { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },          { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
Line 262 
Line 272 
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                 return 256;     /* XXX */                  return 256;     /* XXX */
         }          }
         return 0;          return 0;
Line 275 
Line 287 
         case KEY_DSA:          case KEY_DSA:
         case KEY_ECDSA:          case KEY_ECDSA:
         case KEY_ED25519:          case KEY_ED25519:
           case KEY_XMSS:
                 return 1;                  return 1;
         default:          default:
                 return 0;                  return 0;
Line 302 
Line 315 
                 return KEY_ECDSA;                  return KEY_ECDSA;
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
                 return KEY_ED25519;                  return KEY_ED25519;
           case KEY_XMSS_CERT:
                   return KEY_XMSS;
         default:          default:
                 return type;                  return type;
         }          }
Line 441 
Line 456 
         k->cert = NULL;          k->cert = NULL;
         k->ed25519_sk = NULL;          k->ed25519_sk = NULL;
         k->ed25519_pk = NULL;          k->ed25519_pk = NULL;
           k->xmss_sk = NULL;
           k->xmss_pk = NULL;
         switch (k->type) {          switch (k->type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_RSA:          case KEY_RSA:
Line 474 
Line 491 
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                 /* no need to prealloc */                  /* no need to prealloc */
                 break;                  break;
         case KEY_UNSPEC:          case KEY_UNSPEC:
Line 522 
Line 541 
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                 /* no need to prealloc */                  /* no need to prealloc */
                 break;                  break;
         case KEY_UNSPEC:          case KEY_UNSPEC:
Line 576 
Line 597 
                 freezero(k->ed25519_sk, ED25519_SK_SZ);                  freezero(k->ed25519_sk, ED25519_SK_SZ);
                 k->ed25519_sk = NULL;                  k->ed25519_sk = NULL;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                   freezero(k->xmss_pk, sshkey_xmss_pklen(k));
                   k->xmss_pk = NULL;
                   freezero(k->xmss_sk, sshkey_xmss_sklen(k));
                   k->xmss_sk = NULL;
                   sshkey_xmss_free_state(k);
                   free(k->xmss_name);
                   k->xmss_name = NULL;
                   free(k->xmss_filename);
                   k->xmss_filename = NULL;
                   break;
   #endif /* WITH_XMSS */
         case KEY_UNSPEC:          case KEY_UNSPEC:
                 break;                  break;
         default:          default:
Line 653 
Line 688 
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
                 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&                  return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
                     memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;                      memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
   #ifdef WITH_XMSS
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                   return a->xmss_pk != NULL && b->xmss_pk != NULL &&
                       sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
                       memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
   #endif /* WITH_XMSS */
         default:          default:
                 return 0;                  return 0;
         }          }
Line 672 
Line 714 
 }  }
   
 static int  static int
 to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)  to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
     enum sshkey_serialize_rep opts)
 {  {
         int type, ret = SSH_ERR_INTERNAL_ERROR;          int type, ret = SSH_ERR_INTERNAL_ERROR;
         const char *typename;          const char *typename;
Line 696 
Line 739 
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
   #ifdef WITH_XMSS
           case KEY_XMSS_CERT:
   #endif /* WITH_XMSS */
                 /* Use the existing blob */                  /* Use the existing blob */
                 /* XXX modified flag? */                  /* XXX modified flag? */
                 if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)                  if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
Line 738 
Line 784 
                     key->ed25519_pk, ED25519_PK_SZ)) != 0)                      key->ed25519_pk, ED25519_PK_SZ)) != 0)
                         return ret;                          return ret;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
                   if (key->xmss_name == NULL || key->xmss_pk == NULL ||
                       sshkey_xmss_pklen(key) == 0)
                           return SSH_ERR_INVALID_ARGUMENT;
                   if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
                       (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
                       (ret = sshbuf_put_string(b,
                       key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
                       (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
                           return ret;
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 return SSH_ERR_KEY_TYPE_UNKNOWN;                  return SSH_ERR_KEY_TYPE_UNKNOWN;
         }          }
Line 747 
Line 806 
 int  int
 sshkey_putb(const struct sshkey *key, struct sshbuf *b)  sshkey_putb(const struct sshkey *key, struct sshbuf *b)
 {  {
         return to_blob_buf(key, b, 0);          return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
 }  }
   
 int  int
 sshkey_puts(const struct sshkey *key, struct sshbuf *b)  sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
       enum sshkey_serialize_rep opts)
 {  {
         struct sshbuf *tmp;          struct sshbuf *tmp;
         int r;          int r;
   
         if ((tmp = sshbuf_new()) == NULL)          if ((tmp = sshbuf_new()) == NULL)
                 return SSH_ERR_ALLOC_FAIL;                  return SSH_ERR_ALLOC_FAIL;
         r = to_blob_buf(key, tmp, 0);          r = to_blob_buf(key, tmp, 0, opts);
         if (r == 0)          if (r == 0)
                 r = sshbuf_put_stringb(b, tmp);                  r = sshbuf_put_stringb(b, tmp);
         sshbuf_free(tmp);          sshbuf_free(tmp);
Line 766 
Line 826 
 }  }
   
 int  int
   sshkey_puts(const struct sshkey *key, struct sshbuf *b)
   {
           return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
   }
   
   int
 sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)  sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
 {  {
         return to_blob_buf(key, b, 1);          return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
 }  }
   
 static int  static int
 to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)  to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
       enum sshkey_serialize_rep opts)
 {  {
         int ret = SSH_ERR_INTERNAL_ERROR;          int ret = SSH_ERR_INTERNAL_ERROR;
         size_t len;          size_t len;
Line 784 
Line 851 
                 *blobp = NULL;                  *blobp = NULL;
         if ((b = sshbuf_new()) == NULL)          if ((b = sshbuf_new()) == NULL)
                 return SSH_ERR_ALLOC_FAIL;                  return SSH_ERR_ALLOC_FAIL;
         if ((ret = to_blob_buf(key, b, force_plain)) != 0)          if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
                 goto out;                  goto out;
         len = sshbuf_len(b);          len = sshbuf_len(b);
         if (lenp != NULL)          if (lenp != NULL)
Line 805 
Line 872 
 int  int
 sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)  sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
 {  {
         return to_blob(key, blobp, lenp, 0);          return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
 }  }
   
 int  int
 sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)  sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
 {  {
         return to_blob(key, blobp, lenp, 1);          return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
 }  }
   
 int  int
Line 830 
Line 897 
                 r = SSH_ERR_INVALID_ARGUMENT;                  r = SSH_ERR_INVALID_ARGUMENT;
                 goto out;                  goto out;
         }          }
         if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)          if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
               != 0)
                 goto out;                  goto out;
         if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {          if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
                 r = SSH_ERR_ALLOC_FAIL;                  r = SSH_ERR_ALLOC_FAIL;
Line 1147 
Line 1215 
         case KEY_ECDSA_CERT:          case KEY_ECDSA_CERT:
         case KEY_RSA_CERT:          case KEY_RSA_CERT:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
   #ifdef WITH_XMSS
           case KEY_XMSS:
           case KEY_XMSS_CERT:
   #endif /* WITH_XMSS */
                 space = strchr(cp, ' ');                  space = strchr(cp, ' ');
                 if (space == NULL)                  if (space == NULL)
                         return SSH_ERR_INVALID_FORMAT;                          return SSH_ERR_INVALID_FORMAT;
Line 1242 
Line 1314 
                         /* XXX */                          /* XXX */
 #endif  #endif
                         break;                          break;
   #ifdef WITH_XMSS
                   case KEY_XMSS:
                           free(ret->xmss_pk);
                           ret->xmss_pk = k->xmss_pk;
                           k->xmss_pk = NULL;
                           free(ret->xmss_state);
                           ret->xmss_state = k->xmss_state;
                           k->xmss_state = NULL;
                           free(ret->xmss_name);
                           ret->xmss_name = k->xmss_name;
                           k->xmss_name = NULL;
                           free(ret->xmss_filename);
                           ret->xmss_filename = k->xmss_filename;
                           k->xmss_filename = NULL;
   #ifdef DEBUG_PK
                           /* XXX */
   #endif
                           break;
   #endif /* WITH_XMSS */
                 }                  }
                 *cpp = ep;                  *cpp = ep;
                 retval = 0;                  retval = 0;
Line 1496 
Line 1587 
                 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);                  crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
                 ret = 0;                  ret = 0;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
                   ret = sshkey_xmss_generate_private_key(k, bits);
                   break;
   #endif /* WITH_XMSS */
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         case KEY_DSA:          case KEY_DSA:
                 ret = dsa_generate_private_key(bits, &k->dsa);                  ret = dsa_generate_private_key(bits, &k->dsa);
Line 1635 
Line 1731 
                         memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);                          memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
                 }                  }
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                   if ((n = sshkey_new(k->type)) == NULL)
                           return SSH_ERR_ALLOC_FAIL;
                   if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) {
                           sshkey_free(n);
                           return ret;
                   }
                   if (k->xmss_pk != NULL) {
                           size_t pklen = sshkey_xmss_pklen(k);
                           if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
                                   sshkey_free(n);
                                   return SSH_ERR_INTERNAL_ERROR;
                           }
                           if ((n->xmss_pk = malloc(pklen)) == NULL) {
                                   sshkey_free(n);
                                   return SSH_ERR_ALLOC_FAIL;
                           }
                           memcpy(n->xmss_pk, k->xmss_pk, pklen);
                   }
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 return SSH_ERR_KEY_TYPE_UNKNOWN;                  return SSH_ERR_KEY_TYPE_UNKNOWN;
         }          }
Line 1776 
Line 1895 
     int allow_cert)      int allow_cert)
 {  {
         int type, ret = SSH_ERR_INTERNAL_ERROR;          int type, ret = SSH_ERR_INTERNAL_ERROR;
         char *ktype = NULL, *curve = NULL;          char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
         struct sshkey *key = NULL;          struct sshkey *key = NULL;
         size_t len;          size_t len;
         u_char *pk = NULL;          u_char *pk = NULL;
Line 1925 
Line 2044 
                 key->ed25519_pk = pk;                  key->ed25519_pk = pk;
                 pk = NULL;                  pk = NULL;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS_CERT:
                   /* Skip nonce */
                   if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
                           ret = SSH_ERR_INVALID_FORMAT;
                           goto out;
                   }
                   /* FALLTHROUGH */
           case KEY_XMSS:
                   if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
                           goto out;
                   if ((key = sshkey_new(type)) == NULL) {
                           ret = SSH_ERR_ALLOC_FAIL;
                           goto out;
                   }
                   if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
                           goto out;
                   if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
                           goto out;
                   if (len == 0 || len != sshkey_xmss_pklen(key)) {
                           ret = SSH_ERR_INVALID_FORMAT;
                           goto out;
                   }
                   key->xmss_pk = pk;
                   pk = NULL;
                   if (type != KEY_XMSS_CERT &&
                       (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
                           goto out;
                   break;
   #endif /* WITH_XMSS */
         case KEY_UNSPEC:          case KEY_UNSPEC:
         default:          default:
                 ret = SSH_ERR_KEY_TYPE_UNKNOWN;                  ret = SSH_ERR_KEY_TYPE_UNKNOWN;
Line 1947 
Line 2096 
  out:   out:
         sshbuf_free(copy);          sshbuf_free(copy);
         sshkey_free(key);          sshkey_free(key);
           free(xmss_name);
         free(ktype);          free(ktype);
         free(curve);          free(curve);
         free(pk);          free(pk);
Line 2039 
Line 2189 
         case KEY_ED25519:          case KEY_ED25519:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
                 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);                  return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
   #ifdef WITH_XMSS
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                   return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
   #endif /* WITH_XMSS */
         default:          default:
                 return SSH_ERR_KEY_TYPE_UNKNOWN;                  return SSH_ERR_KEY_TYPE_UNKNOWN;
         }          }
Line 2070 
Line 2225 
         case KEY_ED25519:          case KEY_ED25519:
         case KEY_ED25519_CERT:          case KEY_ED25519_CERT:
                 return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);                  return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
   #ifdef WITH_XMSS
           case KEY_XMSS:
           case KEY_XMSS_CERT:
                   return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
   #endif /* WITH_XMSS */
         default:          default:
                 return SSH_ERR_KEY_TYPE_UNKNOWN;                  return SSH_ERR_KEY_TYPE_UNKNOWN;
         }          }
Line 2093 
Line 2253 
         pk->rsa = NULL;          pk->rsa = NULL;
         pk->ed25519_pk = NULL;          pk->ed25519_pk = NULL;
         pk->ed25519_sk = NULL;          pk->ed25519_sk = NULL;
           pk->xmss_pk = NULL;
           pk->xmss_sk = NULL;
   
         switch (k->type) {          switch (k->type) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
Line 2152 
Line 2314 
                         memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);                          memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
                 }                  }
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS_CERT:
                   if ((ret = sshkey_cert_copy(k, pk)) != 0)
                           goto fail;
                   /* FALLTHROUGH */
           case KEY_XMSS:
                   if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0)
                           goto fail;
                   if (k->xmss_pk != NULL) {
                           size_t pklen = sshkey_xmss_pklen(k);
   
                           if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) {
                                   ret = SSH_ERR_INTERNAL_ERROR;
                                   goto fail;
                           }
                           if ((pk->xmss_pk = malloc(pklen)) == NULL) {
                                   ret = SSH_ERR_ALLOC_FAIL;
                                   goto fail;
                           }
                           memcpy(pk->xmss_pk, k->xmss_pk, pklen);
                   }
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 ret = SSH_ERR_KEY_TYPE_UNKNOWN;                  ret = SSH_ERR_KEY_TYPE_UNKNOWN;
  fail:   fail:
Line 2183 
Line 2368 
         case KEY_ED25519:          case KEY_ED25519:
                 newtype = KEY_ED25519_CERT;                  newtype = KEY_ED25519_CERT;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
                   newtype = KEY_XMSS_CERT;
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 return SSH_ERR_INVALID_ARGUMENT;                  return SSH_ERR_INVALID_ARGUMENT;
         }          }
Line 2265 
Line 2455 
                     k->ed25519_pk, ED25519_PK_SZ)) != 0)                      k->ed25519_pk, ED25519_PK_SZ)) != 0)
                         goto out;                          goto out;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS_CERT:
                   if (k->xmss_name == NULL) {
                           ret = SSH_ERR_INVALID_ARGUMENT;
                           goto out;
                   }
                   if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
                       (ret = sshbuf_put_string(cert,
                       k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
                           goto out;
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 ret = SSH_ERR_INVALID_ARGUMENT;                  ret = SSH_ERR_INVALID_ARGUMENT;
                 goto out;                  goto out;
Line 2422 
Line 2624 
 }  }
   
 int  int
 sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)  sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
       enum sshkey_serialize_rep opts)
 {  {
         int r = SSH_ERR_INTERNAL_ERROR;          int r = SSH_ERR_INTERNAL_ERROR;
   
Line 2506 
Line 2709 
                     ED25519_SK_SZ)) != 0)                      ED25519_SK_SZ)) != 0)
                         goto out;                          goto out;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
                   if (key->xmss_name == NULL) {
                           r = SSH_ERR_INVALID_ARGUMENT;
                           goto out;
                   }
                   if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
                       (r = sshbuf_put_string(b, key->xmss_pk,
                       sshkey_xmss_pklen(key))) != 0 ||
                       (r = sshbuf_put_string(b, key->xmss_sk,
                       sshkey_xmss_sklen(key))) != 0 ||
                       (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
                           goto out;
                   break;
           case KEY_XMSS_CERT:
                   if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
                       key->xmss_name == NULL) {
                           r = SSH_ERR_INVALID_ARGUMENT;
                           goto out;
                   }
                   if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
                       (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
                       (r = sshbuf_put_string(b, key->xmss_pk,
                       sshkey_xmss_pklen(key))) != 0 ||
                       (r = sshbuf_put_string(b, key->xmss_sk,
                       sshkey_xmss_sklen(key))) != 0 ||
                       (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
                           goto out;
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 r = SSH_ERR_INVALID_ARGUMENT;                  r = SSH_ERR_INVALID_ARGUMENT;
                 goto out;                  goto out;
Line 2517 
Line 2750 
 }  }
   
 int  int
   sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
   {
           return sshkey_private_serialize_opt(key, b,
               SSHKEY_SERIALIZE_DEFAULT);
   }
   
   int
 sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)  sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
 {  {
         char *tname = NULL, *curve = NULL;          char *tname = NULL, *curve = NULL, *xmss_name = NULL;
         struct sshkey *k = NULL;          struct sshkey *k = NULL;
         size_t pklen = 0, sklen = 0;          size_t pklen = 0, sklen = 0;
         int type, r = SSH_ERR_INTERNAL_ERROR;          int type, r = SSH_ERR_INTERNAL_ERROR;
         u_char *ed25519_pk = NULL, *ed25519_sk = NULL;          u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
           u_char *xmss_pk = NULL, *xmss_sk = NULL;
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
         BIGNUM *exponent = NULL;          BIGNUM *exponent = NULL;
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
Line 2666 
Line 2907 
                 k->ed25519_sk = ed25519_sk;                  k->ed25519_sk = ed25519_sk;
                 ed25519_pk = ed25519_sk = NULL;                  ed25519_pk = ed25519_sk = NULL;
                 break;                  break;
   #ifdef WITH_XMSS
           case KEY_XMSS:
                   if ((k = sshkey_new_private(type)) == NULL) {
                           r = SSH_ERR_ALLOC_FAIL;
                           goto out;
                   }
                   if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
                       (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
                       (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
                       (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
                           goto out;
                   if (pklen != sshkey_xmss_pklen(k) ||
                       sklen != sshkey_xmss_sklen(k)) {
                           r = SSH_ERR_INVALID_FORMAT;
                           goto out;
                   }
                   k->xmss_pk = xmss_pk;
                   k->xmss_sk = xmss_sk;
                   xmss_pk = xmss_sk = NULL;
                   /* optional internal state */
                   if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
                           goto out;
                   break;
           case KEY_XMSS_CERT:
                   if ((r = sshkey_froms(buf, &k)) != 0 ||
                       (r = sshkey_add_private(k)) != 0 ||
                       (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
                       (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
                           goto out;
                   if (pklen != sshkey_xmss_pklen(k) ||
                       sklen != sshkey_xmss_sklen(k)) {
                           r = SSH_ERR_INVALID_FORMAT;
                           goto out;
                   }
                   k->xmss_pk = xmss_pk;
                   k->xmss_sk = xmss_sk;
                   xmss_pk = xmss_sk = NULL;
                   /* optional internal state */
                   if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
                           goto out;
                   break;
   #endif /* WITH_XMSS */
         default:          default:
                 r = SSH_ERR_KEY_TYPE_UNKNOWN;                  r = SSH_ERR_KEY_TYPE_UNKNOWN;
                 goto out;                  goto out;
Line 2697 
Line 2980 
         sshkey_free(k);          sshkey_free(k);
         freezero(ed25519_pk, pklen);          freezero(ed25519_pk, pklen);
         freezero(ed25519_sk, sklen);          freezero(ed25519_sk, sklen);
           free(xmss_name);
           freezero(xmss_pk, pklen);
           freezero(xmss_sk, sklen);
         return r;          return r;
 }  }
   
Line 2951 
Line 3237 
                 goto out;                  goto out;
   
         /* append private key and comment*/          /* append private key and comment*/
         if ((r = sshkey_private_serialize(prv, encrypted)) != 0 ||          if ((r = sshkey_private_serialize_opt(prv, encrypted,
                SSHKEY_SERIALIZE_FULL)) != 0 ||
             (r = sshbuf_put_cstring(encrypted, comment)) != 0)              (r = sshbuf_put_cstring(encrypted, comment)) != 0)
                 goto out;                  goto out;
   
Line 3310 
Line 3597 
                     passphrase, comment);                      passphrase, comment);
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
   #ifdef WITH_XMSS
           case KEY_XMSS:
   #endif /* WITH_XMSS */
                 return sshkey_private_to_blob2(key, blob, passphrase,                  return sshkey_private_to_blob2(key, blob, passphrase,
                     comment, new_format_cipher, new_format_rounds);                      comment, new_format_cipher, new_format_rounds);
         default:          default:
Line 3491 
Line 3781 
                     passphrase, keyp);                      passphrase, keyp);
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
         case KEY_ED25519:          case KEY_ED25519:
   #ifdef WITH_XMSS
           case KEY_XMSS:
   #endif /* WITH_XMSS */
                 return sshkey_parse_private2(blob, type, passphrase,                  return sshkey_parse_private2(blob, type, passphrase,
                     keyp, commentp);                      keyp, commentp);
         case KEY_UNSPEC:          case KEY_UNSPEC:
Line 3522 
Line 3815 
         return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,          return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
             passphrase, keyp, commentp);              passphrase, keyp, commentp);
 }  }
   
   #ifdef WITH_XMSS
   /*
    * serialize the key with the current state and forward the state
    * maxsign times.
    */
   int
   sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
       u_int32_t maxsign, sshkey_printfn *pr)
   {
           int r, rupdate;
   
           if (maxsign == 0 ||
               sshkey_type_plain(k->type) != KEY_XMSS)
                   return sshkey_private_serialize_opt(k, b,
                       SSHKEY_SERIALIZE_DEFAULT);
           if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
               (r = sshkey_private_serialize_opt(k, b,
               SSHKEY_SERIALIZE_STATE)) != 0 ||
               (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
                   goto out;
           r = 0;
   out:
           if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
                   if (r == 0)
                           r = rupdate;
           }
           return r;
   }
   
   u_int32_t
   sshkey_signatures_left(const struct sshkey *k)
   {
           if (sshkey_type_plain(k->type) == KEY_XMSS)
                   return sshkey_xmss_signatures_left(k);
           return 0;
   }
   
   int
   sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
   {
           if (sshkey_type_plain(k->type) != KEY_XMSS)
                   return SSH_ERR_INVALID_ARGUMENT;
           return sshkey_xmss_enable_maxsign(k, maxsign);
   }
   
   int
   sshkey_set_filename(struct sshkey *k, const char *filename)
   {
           if (k == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
           if (sshkey_type_plain(k->type) != KEY_XMSS)
                   return 0;
           if (filename == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
           if ((k->xmss_filename = strdup(filename)) == NULL)
                   return SSH_ERR_ALLOC_FAIL;
           return 0;
   }
   #else
   int
   sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
       u_int32_t maxsign, sshkey_printfn *pr)
   {
           return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
   }
   
   u_int32_t
   sshkey_signatures_left(const struct sshkey *k)
   {
           return 0;
   }
   
   int
   sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
   {
           return SSH_ERR_INVALID_ARGUMENT;
   }
   
   int
   sshkey_set_filename(struct sshkey *k, const char *filename)
   {
           if (k == NULL)
                   return SSH_ERR_INVALID_ARGUMENT;
           return 0;
   }
   #endif /* WITH_XMSS */

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.62