summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c743
1 files changed, 572 insertions, 171 deletions
diff --git a/sshkey.c b/sshkey.c
index c2cf0e036..088872860 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.56 2017/08/12 06:42:52 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.64 2018/03/22 07:05:48 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved. 4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -55,8 +55,11 @@
55#include "digest.h" 55#include "digest.h"
56#define SSHKEY_INTERNAL 56#define SSHKEY_INTERNAL
57#include "sshkey.h" 57#include "sshkey.h"
58#include "sshkey-xmss.h"
58#include "match.h" 59#include "match.h"
59 60
61#include "xmss_fast.h"
62
60/* openssh private key file format */ 63/* openssh private key file format */
61#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" 64#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
62#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" 65#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
@@ -71,6 +74,8 @@
71/* Version identification string for SSH v1 identity files. */ 74/* Version identification string for SSH v1 identity files. */
72#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" 75#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
73 76
77int sshkey_private_serialize_opt(const struct sshkey *key,
78 struct sshbuf *buf, enum sshkey_serialize_rep);
74static int sshkey_from_blob_internal(struct sshbuf *buf, 79static int sshkey_from_blob_internal(struct sshbuf *buf,
75 struct sshkey **keyp, int allow_cert); 80 struct sshkey **keyp, int allow_cert);
76 81
@@ -87,6 +92,11 @@ static const struct keytype keytypes[] = {
87 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 }, 92 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },
88 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", 93 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
89 KEY_ED25519_CERT, 0, 1, 0 }, 94 KEY_ED25519_CERT, 0, 1, 0 },
95#ifdef WITH_XMSS
96 { "ssh-xmss@openssh.com", "XMSS", KEY_XMSS, 0, 0, 0 },
97 { "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT",
98 KEY_XMSS_CERT, 0, 1, 0 },
99#endif /* WITH_XMSS */
90#ifdef WITH_OPENSSL 100#ifdef WITH_OPENSSL
91 { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, 101 { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
92 { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, 102 { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
@@ -275,6 +285,8 @@ sshkey_size(const struct sshkey *k)
275#endif /* WITH_OPENSSL */ 285#endif /* WITH_OPENSSL */
276 case KEY_ED25519: 286 case KEY_ED25519:
277 case KEY_ED25519_CERT: 287 case KEY_ED25519_CERT:
288 case KEY_XMSS:
289 case KEY_XMSS_CERT:
278 return 256; /* XXX */ 290 return 256; /* XXX */
279 } 291 }
280 return 0; 292 return 0;
@@ -288,6 +300,7 @@ sshkey_type_is_valid_ca(int type)
288 case KEY_DSA: 300 case KEY_DSA:
289 case KEY_ECDSA: 301 case KEY_ECDSA:
290 case KEY_ED25519: 302 case KEY_ED25519:
303 case KEY_XMSS:
291 return 1; 304 return 1;
292 default: 305 default:
293 return 0; 306 return 0;
@@ -315,6 +328,8 @@ sshkey_type_plain(int type)
315 return KEY_ECDSA; 328 return KEY_ECDSA;
316 case KEY_ED25519_CERT: 329 case KEY_ED25519_CERT:
317 return KEY_ED25519; 330 return KEY_ED25519;
331 case KEY_XMSS_CERT:
332 return KEY_XMSS;
318 default: 333 default:
319 return type; 334 return type;
320 } 335 }
@@ -421,8 +436,7 @@ cert_free(struct sshkey_cert *cert)
421 free(cert->principals[i]); 436 free(cert->principals[i]);
422 free(cert->principals); 437 free(cert->principals);
423 sshkey_free(cert->signature_key); 438 sshkey_free(cert->signature_key);
424 explicit_bzero(cert, sizeof(*cert)); 439 freezero(cert, sizeof(*cert));
425 free(cert);
426} 440}
427 441
428static struct sshkey_cert * 442static struct sshkey_cert *
@@ -463,6 +477,8 @@ sshkey_new(int type)
463 k->cert = NULL; 477 k->cert = NULL;
464 k->ed25519_sk = NULL; 478 k->ed25519_sk = NULL;
465 k->ed25519_pk = NULL; 479 k->ed25519_pk = NULL;
480 k->xmss_sk = NULL;
481 k->xmss_pk = NULL;
466 switch (k->type) { 482 switch (k->type) {
467#ifdef WITH_OPENSSL 483#ifdef WITH_OPENSSL
468 case KEY_RSA: 484 case KEY_RSA:
@@ -470,8 +486,7 @@ sshkey_new(int type)
470 if ((rsa = RSA_new()) == NULL || 486 if ((rsa = RSA_new()) == NULL ||
471 (rsa->n = BN_new()) == NULL || 487 (rsa->n = BN_new()) == NULL ||
472 (rsa->e = BN_new()) == NULL) { 488 (rsa->e = BN_new()) == NULL) {
473 if (rsa != NULL) 489 RSA_free(rsa);
474 RSA_free(rsa);
475 free(k); 490 free(k);
476 return NULL; 491 return NULL;
477 } 492 }
@@ -484,8 +499,7 @@ sshkey_new(int type)
484 (dsa->q = BN_new()) == NULL || 499 (dsa->q = BN_new()) == NULL ||
485 (dsa->g = BN_new()) == NULL || 500 (dsa->g = BN_new()) == NULL ||
486 (dsa->pub_key = BN_new()) == NULL) { 501 (dsa->pub_key = BN_new()) == NULL) {
487 if (dsa != NULL) 502 DSA_free(dsa);
488 DSA_free(dsa);
489 free(k); 503 free(k);
490 return NULL; 504 return NULL;
491 } 505 }
@@ -498,6 +512,8 @@ sshkey_new(int type)
498#endif /* WITH_OPENSSL */ 512#endif /* WITH_OPENSSL */
499 case KEY_ED25519: 513 case KEY_ED25519:
500 case KEY_ED25519_CERT: 514 case KEY_ED25519_CERT:
515 case KEY_XMSS:
516 case KEY_XMSS_CERT:
501 /* no need to prealloc */ 517 /* no need to prealloc */
502 break; 518 break;
503 case KEY_UNSPEC: 519 case KEY_UNSPEC:
@@ -546,6 +562,8 @@ sshkey_add_private(struct sshkey *k)
546#endif /* WITH_OPENSSL */ 562#endif /* WITH_OPENSSL */
547 case KEY_ED25519: 563 case KEY_ED25519:
548 case KEY_ED25519_CERT: 564 case KEY_ED25519_CERT:
565 case KEY_XMSS:
566 case KEY_XMSS_CERT:
549 /* no need to prealloc */ 567 /* no need to prealloc */
550 break; 568 break;
551 case KEY_UNSPEC: 569 case KEY_UNSPEC:
@@ -579,38 +597,43 @@ sshkey_free(struct sshkey *k)
579#ifdef WITH_OPENSSL 597#ifdef WITH_OPENSSL
580 case KEY_RSA: 598 case KEY_RSA:
581 case KEY_RSA_CERT: 599 case KEY_RSA_CERT:
582 if (k->rsa != NULL) 600 RSA_free(k->rsa);
583 RSA_free(k->rsa);
584 k->rsa = NULL; 601 k->rsa = NULL;
585 break; 602 break;
586 case KEY_DSA: 603 case KEY_DSA:
587 case KEY_DSA_CERT: 604 case KEY_DSA_CERT:
588 if (k->dsa != NULL) 605 DSA_free(k->dsa);
589 DSA_free(k->dsa);
590 k->dsa = NULL; 606 k->dsa = NULL;
591 break; 607 break;
592# ifdef OPENSSL_HAS_ECC 608# ifdef OPENSSL_HAS_ECC
593 case KEY_ECDSA: 609 case KEY_ECDSA:
594 case KEY_ECDSA_CERT: 610 case KEY_ECDSA_CERT:
595 if (k->ecdsa != NULL) 611 EC_KEY_free(k->ecdsa);
596 EC_KEY_free(k->ecdsa);
597 k->ecdsa = NULL; 612 k->ecdsa = NULL;
598 break; 613 break;
599# endif /* OPENSSL_HAS_ECC */ 614# endif /* OPENSSL_HAS_ECC */
600#endif /* WITH_OPENSSL */ 615#endif /* WITH_OPENSSL */
601 case KEY_ED25519: 616 case KEY_ED25519:
602 case KEY_ED25519_CERT: 617 case KEY_ED25519_CERT:
603 if (k->ed25519_pk) { 618 freezero(k->ed25519_pk, ED25519_PK_SZ);
604 explicit_bzero(k->ed25519_pk, ED25519_PK_SZ); 619 k->ed25519_pk = NULL;
605 free(k->ed25519_pk); 620 freezero(k->ed25519_sk, ED25519_SK_SZ);
606 k->ed25519_pk = NULL; 621 k->ed25519_sk = NULL;
607 } 622 break;
608 if (k->ed25519_sk) { 623#ifdef WITH_XMSS
609 explicit_bzero(k->ed25519_sk, ED25519_SK_SZ); 624 case KEY_XMSS:
610 free(k->ed25519_sk); 625 case KEY_XMSS_CERT:
611 k->ed25519_sk = NULL; 626 freezero(k->xmss_pk, sshkey_xmss_pklen(k));
612 } 627 k->xmss_pk = NULL;
613 break; 628 freezero(k->xmss_sk, sshkey_xmss_sklen(k));
629 k->xmss_sk = NULL;
630 sshkey_xmss_free_state(k);
631 free(k->xmss_name);
632 k->xmss_name = NULL;
633 free(k->xmss_filename);
634 k->xmss_filename = NULL;
635 break;
636#endif /* WITH_XMSS */
614 case KEY_UNSPEC: 637 case KEY_UNSPEC:
615 break; 638 break;
616 default: 639 default:
@@ -618,8 +641,7 @@ sshkey_free(struct sshkey *k)
618 } 641 }
619 if (sshkey_is_cert(k)) 642 if (sshkey_is_cert(k))
620 cert_free(k->cert); 643 cert_free(k->cert);
621 explicit_bzero(k, sizeof(*k)); 644 freezero(k, sizeof(*k));
622 free(k);
623} 645}
624 646
625static int 647static int
@@ -691,6 +713,13 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
691 case KEY_ED25519_CERT: 713 case KEY_ED25519_CERT:
692 return a->ed25519_pk != NULL && b->ed25519_pk != NULL && 714 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
693 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0; 715 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
716#ifdef WITH_XMSS
717 case KEY_XMSS:
718 case KEY_XMSS_CERT:
719 return a->xmss_pk != NULL && b->xmss_pk != NULL &&
720 sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
721 memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
722#endif /* WITH_XMSS */
694 default: 723 default:
695 return 0; 724 return 0;
696 } 725 }
@@ -710,7 +739,8 @@ sshkey_equal(const struct sshkey *a, const struct sshkey *b)
710} 739}
711 740
712static int 741static int
713to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) 742to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
743 enum sshkey_serialize_rep opts)
714{ 744{
715 int type, ret = SSH_ERR_INTERNAL_ERROR; 745 int type, ret = SSH_ERR_INTERNAL_ERROR;
716 const char *typename; 746 const char *typename;
@@ -734,6 +764,9 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
734 case KEY_RSA_CERT: 764 case KEY_RSA_CERT:
735#endif /* WITH_OPENSSL */ 765#endif /* WITH_OPENSSL */
736 case KEY_ED25519_CERT: 766 case KEY_ED25519_CERT:
767#ifdef WITH_XMSS
768 case KEY_XMSS_CERT:
769#endif /* WITH_XMSS */
737 /* Use the existing blob */ 770 /* Use the existing blob */
738 /* XXX modified flag? */ 771 /* XXX modified flag? */
739 if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0) 772 if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
@@ -778,6 +811,19 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
778 key->ed25519_pk, ED25519_PK_SZ)) != 0) 811 key->ed25519_pk, ED25519_PK_SZ)) != 0)
779 return ret; 812 return ret;
780 break; 813 break;
814#ifdef WITH_XMSS
815 case KEY_XMSS:
816 if (key->xmss_name == NULL || key->xmss_pk == NULL ||
817 sshkey_xmss_pklen(key) == 0)
818 return SSH_ERR_INVALID_ARGUMENT;
819 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
820 (ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
821 (ret = sshbuf_put_string(b,
822 key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
823 (ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
824 return ret;
825 break;
826#endif /* WITH_XMSS */
781 default: 827 default:
782 return SSH_ERR_KEY_TYPE_UNKNOWN; 828 return SSH_ERR_KEY_TYPE_UNKNOWN;
783 } 829 }
@@ -787,18 +833,19 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
787int 833int
788sshkey_putb(const struct sshkey *key, struct sshbuf *b) 834sshkey_putb(const struct sshkey *key, struct sshbuf *b)
789{ 835{
790 return to_blob_buf(key, b, 0); 836 return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
791} 837}
792 838
793int 839int
794sshkey_puts(const struct sshkey *key, struct sshbuf *b) 840sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
841 enum sshkey_serialize_rep opts)
795{ 842{
796 struct sshbuf *tmp; 843 struct sshbuf *tmp;
797 int r; 844 int r;
798 845
799 if ((tmp = sshbuf_new()) == NULL) 846 if ((tmp = sshbuf_new()) == NULL)
800 return SSH_ERR_ALLOC_FAIL; 847 return SSH_ERR_ALLOC_FAIL;
801 r = to_blob_buf(key, tmp, 0); 848 r = to_blob_buf(key, tmp, 0, opts);
802 if (r == 0) 849 if (r == 0)
803 r = sshbuf_put_stringb(b, tmp); 850 r = sshbuf_put_stringb(b, tmp);
804 sshbuf_free(tmp); 851 sshbuf_free(tmp);
@@ -806,13 +853,20 @@ sshkey_puts(const struct sshkey *key, struct sshbuf *b)
806} 853}
807 854
808int 855int
856sshkey_puts(const struct sshkey *key, struct sshbuf *b)
857{
858 return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
859}
860
861int
809sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) 862sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
810{ 863{
811 return to_blob_buf(key, b, 1); 864 return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
812} 865}
813 866
814static int 867static int
815to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain) 868to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
869 enum sshkey_serialize_rep opts)
816{ 870{
817 int ret = SSH_ERR_INTERNAL_ERROR; 871 int ret = SSH_ERR_INTERNAL_ERROR;
818 size_t len; 872 size_t len;
@@ -824,7 +878,7 @@ to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
824 *blobp = NULL; 878 *blobp = NULL;
825 if ((b = sshbuf_new()) == NULL) 879 if ((b = sshbuf_new()) == NULL)
826 return SSH_ERR_ALLOC_FAIL; 880 return SSH_ERR_ALLOC_FAIL;
827 if ((ret = to_blob_buf(key, b, force_plain)) != 0) 881 if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
828 goto out; 882 goto out;
829 len = sshbuf_len(b); 883 len = sshbuf_len(b);
830 if (lenp != NULL) 884 if (lenp != NULL)
@@ -845,13 +899,13 @@ to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
845int 899int
846sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) 900sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
847{ 901{
848 return to_blob(key, blobp, lenp, 0); 902 return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
849} 903}
850 904
851int 905int
852sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) 906sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
853{ 907{
854 return to_blob(key, blobp, lenp, 1); 908 return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
855} 909}
856 910
857int 911int
@@ -870,7 +924,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
870 r = SSH_ERR_INVALID_ARGUMENT; 924 r = SSH_ERR_INVALID_ARGUMENT;
871 goto out; 925 goto out;
872 } 926 }
873 if ((r = to_blob(k, &blob, &blob_len, 1)) != 0) 927 if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
928 != 0)
874 goto out; 929 goto out;
875 if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { 930 if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
876 r = SSH_ERR_ALLOC_FAIL; 931 r = SSH_ERR_ALLOC_FAIL;
@@ -912,8 +967,7 @@ fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
912 return ret; 967 return ret;
913 if ((r = b64_ntop(dgst_raw, dgst_raw_len, 968 if ((r = b64_ntop(dgst_raw, dgst_raw_len,
914 ret + plen, rlen - plen)) == -1) { 969 ret + plen, rlen - plen)) == -1) {
915 explicit_bzero(ret, rlen); 970 freezero(ret, rlen);
916 free(ret);
917 return NULL; 971 return NULL;
918 } 972 }
919 /* Trim padding characters from end */ 973 /* Trim padding characters from end */
@@ -1162,22 +1216,37 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
1162 return retval; 1216 return retval;
1163} 1217}
1164 1218
1219static int
1220peek_type_nid(const char *s, size_t l, int *nid)
1221{
1222 const struct keytype *kt;
1223
1224 for (kt = keytypes; kt->type != -1; kt++) {
1225 if (kt->name == NULL || strlen(kt->name) != l)
1226 continue;
1227 if (memcmp(s, kt->name, l) == 0) {
1228 *nid = -1;
1229 if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT)
1230 *nid = kt->nid;
1231 return kt->type;
1232 }
1233 }
1234 return KEY_UNSPEC;
1235}
1165 1236
1166/* returns 0 ok, and < 0 error */ 1237/* XXX this can now be made const char * */
1167int 1238int
1168sshkey_read(struct sshkey *ret, char **cpp) 1239sshkey_read(struct sshkey *ret, char **cpp)
1169{ 1240{
1170 struct sshkey *k; 1241 struct sshkey *k;
1171 int retval = SSH_ERR_INVALID_FORMAT; 1242 char *cp, *blobcopy;
1172 char *ep, *cp, *space; 1243 size_t space;
1173 int r, type, curve_nid = -1; 1244 int r, type, curve_nid = -1;
1174 struct sshbuf *blob; 1245 struct sshbuf *blob;
1175 1246
1176 if (ret == NULL) 1247 if (ret == NULL)
1177 return SSH_ERR_INVALID_ARGUMENT; 1248 return SSH_ERR_INVALID_ARGUMENT;
1178 1249
1179 cp = *cpp;
1180
1181 switch (ret->type) { 1250 switch (ret->type) {
1182 case KEY_UNSPEC: 1251 case KEY_UNSPEC:
1183 case KEY_RSA: 1252 case KEY_RSA:
@@ -1188,120 +1257,147 @@ sshkey_read(struct sshkey *ret, char **cpp)
1188 case KEY_ECDSA_CERT: 1257 case KEY_ECDSA_CERT:
1189 case KEY_RSA_CERT: 1258 case KEY_RSA_CERT:
1190 case KEY_ED25519_CERT: 1259 case KEY_ED25519_CERT:
1191 space = strchr(cp, ' '); 1260#ifdef WITH_XMSS
1192 if (space == NULL) 1261 case KEY_XMSS:
1193 return SSH_ERR_INVALID_FORMAT; 1262 case KEY_XMSS_CERT:
1194 *space = '\0'; 1263#endif /* WITH_XMSS */
1195 type = sshkey_type_from_name(cp); 1264 break; /* ok */
1196 if (sshkey_type_plain(type) == KEY_ECDSA && 1265 default:
1197 (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1) 1266 return SSH_ERR_INVALID_ARGUMENT;
1198 return SSH_ERR_EC_CURVE_INVALID; 1267 }
1199 *space = ' '; 1268
1200 if (type == KEY_UNSPEC) 1269 /* Decode type */
1201 return SSH_ERR_INVALID_FORMAT; 1270 cp = *cpp;
1202 cp = space+1; 1271 space = strcspn(cp, " \t");
1203 if (*cp == '\0') 1272 if (space == strlen(cp))
1204 return SSH_ERR_INVALID_FORMAT; 1273 return SSH_ERR_INVALID_FORMAT;
1205 if (ret->type != KEY_UNSPEC && ret->type != type) 1274 if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
1206 return SSH_ERR_KEY_TYPE_MISMATCH; 1275 return SSH_ERR_INVALID_FORMAT;
1207 if ((blob = sshbuf_new()) == NULL) 1276
1208 return SSH_ERR_ALLOC_FAIL; 1277 /* skip whitespace */
1209 /* trim comment */ 1278 for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1210 space = strchr(cp, ' '); 1279 ;
1211 if (space) { 1280 if (*cp == '\0')
1212 /* advance 'space': skip whitespace */ 1281 return SSH_ERR_INVALID_FORMAT;
1213 *space++ = '\0'; 1282 if (ret->type != KEY_UNSPEC && ret->type != type)
1214 while (*space == ' ' || *space == '\t') 1283 return SSH_ERR_KEY_TYPE_MISMATCH;
1215 space++; 1284 if ((blob = sshbuf_new()) == NULL)
1216 ep = space; 1285 return SSH_ERR_ALLOC_FAIL;
1217 } else 1286
1218 ep = cp + strlen(cp); 1287 /* find end of keyblob and decode */
1219 if ((r = sshbuf_b64tod(blob, cp)) != 0) { 1288 space = strcspn(cp, " \t");
1220 sshbuf_free(blob); 1289 if ((blobcopy = strndup(cp, space)) == NULL) {
1221 return r;
1222 }
1223 if ((r = sshkey_from_blob(sshbuf_ptr(blob),
1224 sshbuf_len(blob), &k)) != 0) {
1225 sshbuf_free(blob);
1226 return r;
1227 }
1228 sshbuf_free(blob); 1290 sshbuf_free(blob);
1229 if (k->type != type) { 1291 return SSH_ERR_ALLOC_FAIL;
1230 sshkey_free(k); 1292 }
1231 return SSH_ERR_KEY_TYPE_MISMATCH; 1293 if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
1232 } 1294 free(blobcopy);
1233 if (sshkey_type_plain(type) == KEY_ECDSA && 1295 sshbuf_free(blob);
1234 curve_nid != k->ecdsa_nid) { 1296 return r;
1297 }
1298 free(blobcopy);
1299 if ((r = sshkey_fromb(blob, &k)) != 0) {
1300 sshbuf_free(blob);
1301 return r;
1302 }
1303 sshbuf_free(blob);
1304
1305 /* skip whitespace and leave cp at start of comment */
1306 for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
1307 ;
1308
1309 /* ensure type of blob matches type at start of line */
1310 if (k->type != type) {
1311 sshkey_free(k);
1312 return SSH_ERR_KEY_TYPE_MISMATCH;
1313 }
1314 if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) {
1315 sshkey_free(k);
1316 return SSH_ERR_EC_CURVE_MISMATCH;
1317 }
1318
1319 /* Fill in ret from parsed key */
1320 ret->type = type;
1321 if (sshkey_is_cert(ret)) {
1322 if (!sshkey_is_cert(k)) {
1235 sshkey_free(k); 1323 sshkey_free(k);
1236 return SSH_ERR_EC_CURVE_MISMATCH; 1324 return SSH_ERR_EXPECTED_CERT;
1237 }
1238 ret->type = type;
1239 if (sshkey_is_cert(ret)) {
1240 if (!sshkey_is_cert(k)) {
1241 sshkey_free(k);
1242 return SSH_ERR_EXPECTED_CERT;
1243 }
1244 if (ret->cert != NULL)
1245 cert_free(ret->cert);
1246 ret->cert = k->cert;
1247 k->cert = NULL;
1248 } 1325 }
1249 switch (sshkey_type_plain(ret->type)) { 1326 if (ret->cert != NULL)
1327 cert_free(ret->cert);
1328 ret->cert = k->cert;
1329 k->cert = NULL;
1330 }
1331 switch (sshkey_type_plain(ret->type)) {
1250#ifdef WITH_OPENSSL 1332#ifdef WITH_OPENSSL
1251 case KEY_RSA: 1333 case KEY_RSA:
1252 if (ret->rsa != NULL) 1334 RSA_free(ret->rsa);
1253 RSA_free(ret->rsa); 1335 ret->rsa = k->rsa;
1254 ret->rsa = k->rsa; 1336 k->rsa = NULL;
1255 k->rsa = NULL;
1256#ifdef DEBUG_PK 1337#ifdef DEBUG_PK
1257 RSA_print_fp(stderr, ret->rsa, 8); 1338 RSA_print_fp(stderr, ret->rsa, 8);
1258#endif 1339#endif
1259 break; 1340 break;
1260 case KEY_DSA: 1341 case KEY_DSA:
1261 if (ret->dsa != NULL) 1342 DSA_free(ret->dsa);
1262 DSA_free(ret->dsa); 1343 ret->dsa = k->dsa;
1263 ret->dsa = k->dsa; 1344 k->dsa = NULL;
1264 k->dsa = NULL;
1265#ifdef DEBUG_PK 1345#ifdef DEBUG_PK
1266 DSA_print_fp(stderr, ret->dsa, 8); 1346 DSA_print_fp(stderr, ret->dsa, 8);
1267#endif 1347#endif
1268 break; 1348 break;
1269# ifdef OPENSSL_HAS_ECC 1349# ifdef OPENSSL_HAS_ECC
1270 case KEY_ECDSA: 1350 case KEY_ECDSA:
1271 if (ret->ecdsa != NULL) 1351 EC_KEY_free(ret->ecdsa);
1272 EC_KEY_free(ret->ecdsa); 1352 ret->ecdsa = k->ecdsa;
1273 ret->ecdsa = k->ecdsa; 1353 ret->ecdsa_nid = k->ecdsa_nid;
1274 ret->ecdsa_nid = k->ecdsa_nid; 1354 k->ecdsa = NULL;
1275 k->ecdsa = NULL; 1355 k->ecdsa_nid = -1;
1276 k->ecdsa_nid = -1;
1277#ifdef DEBUG_PK 1356#ifdef DEBUG_PK
1278 sshkey_dump_ec_key(ret->ecdsa); 1357 sshkey_dump_ec_key(ret->ecdsa);
1279#endif 1358#endif
1280 break; 1359 break;
1281# endif /* OPENSSL_HAS_ECC */ 1360# endif /* OPENSSL_HAS_ECC */
1282#endif /* WITH_OPENSSL */ 1361#endif /* WITH_OPENSSL */
1283 case KEY_ED25519: 1362 case KEY_ED25519:
1284 free(ret->ed25519_pk); 1363 freezero(ret->ed25519_pk, ED25519_PK_SZ);
1285 ret->ed25519_pk = k->ed25519_pk; 1364 ret->ed25519_pk = k->ed25519_pk;
1286 k->ed25519_pk = NULL; 1365 k->ed25519_pk = NULL;
1287#ifdef DEBUG_PK 1366#ifdef DEBUG_PK
1288 /* XXX */ 1367 /* XXX */
1289#endif 1368#endif
1290 break;
1291 }
1292 *cpp = ep;
1293 retval = 0;
1294/*XXXX*/
1295 sshkey_free(k);
1296 if (retval != 0)
1297 break;
1298 break; 1369 break;
1370#ifdef WITH_XMSS
1371 case KEY_XMSS:
1372 free(ret->xmss_pk);
1373 ret->xmss_pk = k->xmss_pk;
1374 k->xmss_pk = NULL;
1375 free(ret->xmss_state);
1376 ret->xmss_state = k->xmss_state;
1377 k->xmss_state = NULL;
1378 free(ret->xmss_name);
1379 ret->xmss_name = k->xmss_name;
1380 k->xmss_name = NULL;
1381 free(ret->xmss_filename);
1382 ret->xmss_filename = k->xmss_filename;
1383 k->xmss_filename = NULL;
1384#ifdef DEBUG_PK
1385 /* XXX */
1386#endif
1387 break;
1388#endif /* WITH_XMSS */
1299 default: 1389 default:
1300 return SSH_ERR_INVALID_ARGUMENT; 1390 sshkey_free(k);
1391 return SSH_ERR_INTERNAL_ERROR;
1301 } 1392 }
1302 return retval; 1393 sshkey_free(k);
1394
1395 /* success */
1396 *cpp = cp;
1397 return 0;
1303} 1398}
1304 1399
1400
1305int 1401int
1306sshkey_to_base64(const struct sshkey *key, char **b64p) 1402sshkey_to_base64(const struct sshkey *key, char **b64p)
1307{ 1403{
@@ -1411,10 +1507,8 @@ rsa_generate_private_key(u_int bits, RSA **rsap)
1411 private = NULL; 1507 private = NULL;
1412 ret = 0; 1508 ret = 0;
1413 out: 1509 out:
1414 if (private != NULL) 1510 RSA_free(private);
1415 RSA_free(private); 1511 BN_free(f4);
1416 if (f4 != NULL)
1417 BN_free(f4);
1418 return ret; 1512 return ret;
1419} 1513}
1420 1514
@@ -1442,8 +1536,7 @@ dsa_generate_private_key(u_int bits, DSA **dsap)
1442 private = NULL; 1536 private = NULL;
1443 ret = 0; 1537 ret = 0;
1444 out: 1538 out:
1445 if (private != NULL) 1539 DSA_free(private);
1446 DSA_free(private);
1447 return ret; 1540 return ret;
1448} 1541}
1449 1542
@@ -1522,8 +1615,7 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1522 private = NULL; 1615 private = NULL;
1523 ret = 0; 1616 ret = 0;
1524 out: 1617 out:
1525 if (private != NULL) 1618 EC_KEY_free(private);
1526 EC_KEY_free(private);
1527 return ret; 1619 return ret;
1528} 1620}
1529# endif /* OPENSSL_HAS_ECC */ 1621# endif /* OPENSSL_HAS_ECC */
@@ -1550,6 +1642,11 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1550 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk); 1642 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1551 ret = 0; 1643 ret = 0;
1552 break; 1644 break;
1645#ifdef WITH_XMSS
1646 case KEY_XMSS:
1647 ret = sshkey_xmss_generate_private_key(k, bits);
1648 break;
1649#endif /* WITH_XMSS */
1553#ifdef WITH_OPENSSL 1650#ifdef WITH_OPENSSL
1554 case KEY_DSA: 1651 case KEY_DSA:
1555 ret = dsa_generate_private_key(bits, &k->dsa); 1652 ret = dsa_generate_private_key(bits, &k->dsa);
@@ -1693,6 +1790,29 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1693 memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); 1790 memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1694 } 1791 }
1695 break; 1792 break;
1793#ifdef WITH_XMSS
1794 case KEY_XMSS:
1795 case KEY_XMSS_CERT:
1796 if ((n = sshkey_new(k->type)) == NULL)
1797 return SSH_ERR_ALLOC_FAIL;
1798 if ((ret = sshkey_xmss_init(n, k->xmss_name)) != 0) {
1799 sshkey_free(n);
1800 return ret;
1801 }
1802 if (k->xmss_pk != NULL) {
1803 size_t pklen = sshkey_xmss_pklen(k);
1804 if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
1805 sshkey_free(n);
1806 return SSH_ERR_INTERNAL_ERROR;
1807 }
1808 if ((n->xmss_pk = malloc(pklen)) == NULL) {
1809 sshkey_free(n);
1810 return SSH_ERR_ALLOC_FAIL;
1811 }
1812 memcpy(n->xmss_pk, k->xmss_pk, pklen);
1813 }
1814 break;
1815#endif /* WITH_XMSS */
1696 default: 1816 default:
1697 return SSH_ERR_KEY_TYPE_UNKNOWN; 1817 return SSH_ERR_KEY_TYPE_UNKNOWN;
1698 } 1818 }
@@ -1815,7 +1935,7 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
1815 goto out; 1935 goto out;
1816 } 1936 }
1817 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, 1937 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1818 sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0) 1938 sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
1819 goto out; 1939 goto out;
1820 1940
1821 /* Success */ 1941 /* Success */
@@ -1834,7 +1954,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
1834 int allow_cert) 1954 int allow_cert)
1835{ 1955{
1836 int type, ret = SSH_ERR_INTERNAL_ERROR; 1956 int type, ret = SSH_ERR_INTERNAL_ERROR;
1837 char *ktype = NULL, *curve = NULL; 1957 char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
1838 struct sshkey *key = NULL; 1958 struct sshkey *key = NULL;
1839 size_t len; 1959 size_t len;
1840 u_char *pk = NULL; 1960 u_char *pk = NULL;
@@ -1934,8 +2054,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
1934 ret = SSH_ERR_EC_CURVE_MISMATCH; 2054 ret = SSH_ERR_EC_CURVE_MISMATCH;
1935 goto out; 2055 goto out;
1936 } 2056 }
1937 if (key->ecdsa != NULL) 2057 EC_KEY_free(key->ecdsa);
1938 EC_KEY_free(key->ecdsa);
1939 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) 2058 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
1940 == NULL) { 2059 == NULL) {
1941 ret = SSH_ERR_EC_CURVE_INVALID; 2060 ret = SSH_ERR_EC_CURVE_INVALID;
@@ -1986,6 +2105,36 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
1986 key->ed25519_pk = pk; 2105 key->ed25519_pk = pk;
1987 pk = NULL; 2106 pk = NULL;
1988 break; 2107 break;
2108#ifdef WITH_XMSS
2109 case KEY_XMSS_CERT:
2110 /* Skip nonce */
2111 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2112 ret = SSH_ERR_INVALID_FORMAT;
2113 goto out;
2114 }
2115 /* FALLTHROUGH */
2116 case KEY_XMSS:
2117 if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
2118 goto out;
2119 if ((key = sshkey_new(type)) == NULL) {
2120 ret = SSH_ERR_ALLOC_FAIL;
2121 goto out;
2122 }
2123 if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
2124 goto out;
2125 if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2126 goto out;
2127 if (len == 0 || len != sshkey_xmss_pklen(key)) {
2128 ret = SSH_ERR_INVALID_FORMAT;
2129 goto out;
2130 }
2131 key->xmss_pk = pk;
2132 pk = NULL;
2133 if (type != KEY_XMSS_CERT &&
2134 (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
2135 goto out;
2136 break;
2137#endif /* WITH_XMSS */
1989 case KEY_UNSPEC: 2138 case KEY_UNSPEC:
1990 default: 2139 default:
1991 ret = SSH_ERR_KEY_TYPE_UNKNOWN; 2140 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
@@ -2008,12 +2157,12 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
2008 out: 2157 out:
2009 sshbuf_free(copy); 2158 sshbuf_free(copy);
2010 sshkey_free(key); 2159 sshkey_free(key);
2160 free(xmss_name);
2011 free(ktype); 2161 free(ktype);
2012 free(curve); 2162 free(curve);
2013 free(pk); 2163 free(pk);
2014#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) 2164#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2015 if (q != NULL) 2165 EC_POINT_free(q);
2016 EC_POINT_free(q);
2017#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ 2166#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2018 return ret; 2167 return ret;
2019} 2168}
@@ -2051,6 +2200,31 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
2051} 2200}
2052 2201
2053int 2202int
2203sshkey_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
2204{
2205 int r;
2206 struct sshbuf *b = NULL;
2207 char *sigtype = NULL;
2208
2209 if (sigtypep != NULL)
2210 *sigtypep = NULL;
2211 if ((b = sshbuf_from(sig, siglen)) == NULL)
2212 return SSH_ERR_ALLOC_FAIL;
2213 if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
2214 goto out;
2215 /* success */
2216 if (sigtypep != NULL) {
2217 *sigtypep = sigtype;
2218 sigtype = NULL;
2219 }
2220 r = 0;
2221 out:
2222 free(sigtype);
2223 sshbuf_free(b);
2224 return r;
2225}
2226
2227int
2054sshkey_sign(const struct sshkey *key, 2228sshkey_sign(const struct sshkey *key,
2055 u_char **sigp, size_t *lenp, 2229 u_char **sigp, size_t *lenp,
2056 const u_char *data, size_t datalen, const char *alg, u_int compat) 2230 const u_char *data, size_t datalen, const char *alg, u_int compat)
@@ -2078,6 +2252,11 @@ sshkey_sign(const struct sshkey *key,
2078 case KEY_ED25519: 2252 case KEY_ED25519:
2079 case KEY_ED25519_CERT: 2253 case KEY_ED25519_CERT:
2080 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat); 2254 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2255#ifdef WITH_XMSS
2256 case KEY_XMSS:
2257 case KEY_XMSS_CERT:
2258 return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
2259#endif /* WITH_XMSS */
2081 default: 2260 default:
2082 return SSH_ERR_KEY_TYPE_UNKNOWN; 2261 return SSH_ERR_KEY_TYPE_UNKNOWN;
2083 } 2262 }
@@ -2085,11 +2264,12 @@ sshkey_sign(const struct sshkey *key,
2085 2264
2086/* 2265/*
2087 * ssh_key_verify returns 0 for a correct signature and < 0 on error. 2266 * ssh_key_verify returns 0 for a correct signature and < 0 on error.
2267 * If "alg" specified, then the signature must use that algorithm.
2088 */ 2268 */
2089int 2269int
2090sshkey_verify(const struct sshkey *key, 2270sshkey_verify(const struct sshkey *key,
2091 const u_char *sig, size_t siglen, 2271 const u_char *sig, size_t siglen,
2092 const u_char *data, size_t dlen, u_int compat) 2272 const u_char *data, size_t dlen, const char *alg, u_int compat)
2093{ 2273{
2094 if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) 2274 if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2095 return SSH_ERR_INVALID_ARGUMENT; 2275 return SSH_ERR_INVALID_ARGUMENT;
@@ -2105,11 +2285,16 @@ sshkey_verify(const struct sshkey *key,
2105# endif /* OPENSSL_HAS_ECC */ 2285# endif /* OPENSSL_HAS_ECC */
2106 case KEY_RSA_CERT: 2286 case KEY_RSA_CERT:
2107 case KEY_RSA: 2287 case KEY_RSA:
2108 return ssh_rsa_verify(key, sig, siglen, data, dlen); 2288 return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
2109#endif /* WITH_OPENSSL */ 2289#endif /* WITH_OPENSSL */
2110 case KEY_ED25519: 2290 case KEY_ED25519:
2111 case KEY_ED25519_CERT: 2291 case KEY_ED25519_CERT:
2112 return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat); 2292 return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
2293#ifdef WITH_XMSS
2294 case KEY_XMSS:
2295 case KEY_XMSS_CERT:
2296 return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
2297#endif /* WITH_XMSS */
2113 default: 2298 default:
2114 return SSH_ERR_KEY_TYPE_UNKNOWN; 2299 return SSH_ERR_KEY_TYPE_UNKNOWN;
2115 } 2300 }
@@ -2133,6 +2318,8 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
2133 pk->rsa = NULL; 2318 pk->rsa = NULL;
2134 pk->ed25519_pk = NULL; 2319 pk->ed25519_pk = NULL;
2135 pk->ed25519_sk = NULL; 2320 pk->ed25519_sk = NULL;
2321 pk->xmss_pk = NULL;
2322 pk->xmss_sk = NULL;
2136 2323
2137 switch (k->type) { 2324 switch (k->type) {
2138#ifdef WITH_OPENSSL 2325#ifdef WITH_OPENSSL
@@ -2194,6 +2381,29 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
2194 memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); 2381 memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
2195 } 2382 }
2196 break; 2383 break;
2384#ifdef WITH_XMSS
2385 case KEY_XMSS_CERT:
2386 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2387 goto fail;
2388 /* FALLTHROUGH */
2389 case KEY_XMSS:
2390 if ((ret = sshkey_xmss_init(pk, k->xmss_name)) != 0)
2391 goto fail;
2392 if (k->xmss_pk != NULL) {
2393 size_t pklen = sshkey_xmss_pklen(k);
2394
2395 if (pklen == 0 || sshkey_xmss_pklen(pk) != pklen) {
2396 ret = SSH_ERR_INTERNAL_ERROR;
2397 goto fail;
2398 }
2399 if ((pk->xmss_pk = malloc(pklen)) == NULL) {
2400 ret = SSH_ERR_ALLOC_FAIL;
2401 goto fail;
2402 }
2403 memcpy(pk->xmss_pk, k->xmss_pk, pklen);
2404 }
2405 break;
2406#endif /* WITH_XMSS */
2197 default: 2407 default:
2198 ret = SSH_ERR_KEY_TYPE_UNKNOWN; 2408 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2199 fail: 2409 fail:
@@ -2225,6 +2435,11 @@ sshkey_to_certified(struct sshkey *k)
2225 case KEY_ED25519: 2435 case KEY_ED25519:
2226 newtype = KEY_ED25519_CERT; 2436 newtype = KEY_ED25519_CERT;
2227 break; 2437 break;
2438#ifdef WITH_XMSS
2439 case KEY_XMSS:
2440 newtype = KEY_XMSS_CERT;
2441 break;
2442#endif /* WITH_XMSS */
2228 default: 2443 default:
2229 return SSH_ERR_INVALID_ARGUMENT; 2444 return SSH_ERR_INVALID_ARGUMENT;
2230 } 2445 }
@@ -2309,6 +2524,18 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
2309 k->ed25519_pk, ED25519_PK_SZ)) != 0) 2524 k->ed25519_pk, ED25519_PK_SZ)) != 0)
2310 goto out; 2525 goto out;
2311 break; 2526 break;
2527#ifdef WITH_XMSS
2528 case KEY_XMSS_CERT:
2529 if (k->xmss_name == NULL) {
2530 ret = SSH_ERR_INVALID_ARGUMENT;
2531 goto out;
2532 }
2533 if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
2534 (ret = sshbuf_put_string(cert,
2535 k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
2536 goto out;
2537 break;
2538#endif /* WITH_XMSS */
2312 default: 2539 default:
2313 ret = SSH_ERR_INVALID_ARGUMENT; 2540 ret = SSH_ERR_INVALID_ARGUMENT;
2314 goto out; 2541 goto out;
@@ -2466,7 +2693,8 @@ sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
2466} 2693}
2467 2694
2468int 2695int
2469sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) 2696sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
2697 enum sshkey_serialize_rep opts)
2470{ 2698{
2471 int r = SSH_ERR_INTERNAL_ERROR; 2699 int r = SSH_ERR_INTERNAL_ERROR;
2472 2700
@@ -2552,6 +2780,36 @@ sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
2552 ED25519_SK_SZ)) != 0) 2780 ED25519_SK_SZ)) != 0)
2553 goto out; 2781 goto out;
2554 break; 2782 break;
2783#ifdef WITH_XMSS
2784 case KEY_XMSS:
2785 if (key->xmss_name == NULL) {
2786 r = SSH_ERR_INVALID_ARGUMENT;
2787 goto out;
2788 }
2789 if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
2790 (r = sshbuf_put_string(b, key->xmss_pk,
2791 sshkey_xmss_pklen(key))) != 0 ||
2792 (r = sshbuf_put_string(b, key->xmss_sk,
2793 sshkey_xmss_sklen(key))) != 0 ||
2794 (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
2795 goto out;
2796 break;
2797 case KEY_XMSS_CERT:
2798 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
2799 key->xmss_name == NULL) {
2800 r = SSH_ERR_INVALID_ARGUMENT;
2801 goto out;
2802 }
2803 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2804 (r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
2805 (r = sshbuf_put_string(b, key->xmss_pk,
2806 sshkey_xmss_pklen(key))) != 0 ||
2807 (r = sshbuf_put_string(b, key->xmss_sk,
2808 sshkey_xmss_sklen(key))) != 0 ||
2809 (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
2810 goto out;
2811 break;
2812#endif /* WITH_XMSS */
2555 default: 2813 default:
2556 r = SSH_ERR_INVALID_ARGUMENT; 2814 r = SSH_ERR_INVALID_ARGUMENT;
2557 goto out; 2815 goto out;
@@ -2563,13 +2821,21 @@ sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
2563} 2821}
2564 2822
2565int 2823int
2824sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
2825{
2826 return sshkey_private_serialize_opt(key, b,
2827 SSHKEY_SERIALIZE_DEFAULT);
2828}
2829
2830int
2566sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) 2831sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2567{ 2832{
2568 char *tname = NULL, *curve = NULL; 2833 char *tname = NULL, *curve = NULL, *xmss_name = NULL;
2569 struct sshkey *k = NULL; 2834 struct sshkey *k = NULL;
2570 size_t pklen = 0, sklen = 0; 2835 size_t pklen = 0, sklen = 0;
2571 int type, r = SSH_ERR_INTERNAL_ERROR; 2836 int type, r = SSH_ERR_INTERNAL_ERROR;
2572 u_char *ed25519_pk = NULL, *ed25519_sk = NULL; 2837 u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
2838 u_char *xmss_pk = NULL, *xmss_sk = NULL;
2573#ifdef WITH_OPENSSL 2839#ifdef WITH_OPENSSL
2574 BIGNUM *exponent = NULL; 2840 BIGNUM *exponent = NULL;
2575#endif /* WITH_OPENSSL */ 2841#endif /* WITH_OPENSSL */
@@ -2714,6 +2980,53 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2714 k->ed25519_sk = ed25519_sk; 2980 k->ed25519_sk = ed25519_sk;
2715 ed25519_pk = ed25519_sk = NULL; 2981 ed25519_pk = ed25519_sk = NULL;
2716 break; 2982 break;
2983#ifdef WITH_XMSS
2984 case KEY_XMSS:
2985 if ((k = sshkey_new_private(type)) == NULL) {
2986 r = SSH_ERR_ALLOC_FAIL;
2987 goto out;
2988 }
2989 if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
2990 (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
2991 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
2992 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
2993 goto out;
2994 if (pklen != sshkey_xmss_pklen(k) ||
2995 sklen != sshkey_xmss_sklen(k)) {
2996 r = SSH_ERR_INVALID_FORMAT;
2997 goto out;
2998 }
2999 k->xmss_pk = xmss_pk;
3000 k->xmss_sk = xmss_sk;
3001 xmss_pk = xmss_sk = NULL;
3002 /* optional internal state */
3003 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3004 goto out;
3005 break;
3006 case KEY_XMSS_CERT:
3007 if ((r = sshkey_froms(buf, &k)) != 0 ||
3008 (r = sshkey_add_private(k)) != 0 ||
3009 (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
3010 (r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
3011 (r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
3012 goto out;
3013 if (strcmp(xmss_name, k->xmss_name)) {
3014 r = SSH_ERR_INVALID_FORMAT;
3015 goto out;
3016 }
3017 if (pklen != sshkey_xmss_pklen(k) ||
3018 sklen != sshkey_xmss_sklen(k)) {
3019 r = SSH_ERR_INVALID_FORMAT;
3020 goto out;
3021 }
3022 k->xmss_pk = xmss_pk;
3023 k->xmss_sk = xmss_sk;
3024 xmss_pk = xmss_sk = NULL;
3025 /* optional internal state */
3026 if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
3027 goto out;
3028 break;
3029#endif /* WITH_XMSS */
2717 default: 3030 default:
2718 r = SSH_ERR_KEY_TYPE_UNKNOWN; 3031 r = SSH_ERR_KEY_TYPE_UNKNOWN;
2719 goto out; 3032 goto out;
@@ -2740,18 +3053,14 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2740 free(tname); 3053 free(tname);
2741 free(curve); 3054 free(curve);
2742#ifdef WITH_OPENSSL 3055#ifdef WITH_OPENSSL
2743 if (exponent != NULL) 3056 BN_clear_free(exponent);
2744 BN_clear_free(exponent);
2745#endif /* WITH_OPENSSL */ 3057#endif /* WITH_OPENSSL */
2746 sshkey_free(k); 3058 sshkey_free(k);
2747 if (ed25519_pk != NULL) { 3059 freezero(ed25519_pk, pklen);
2748 explicit_bzero(ed25519_pk, pklen); 3060 freezero(ed25519_sk, sklen);
2749 free(ed25519_pk); 3061 free(xmss_name);
2750 } 3062 freezero(xmss_pk, pklen);
2751 if (ed25519_sk != NULL) { 3063 freezero(xmss_sk, sklen);
2752 explicit_bzero(ed25519_sk, sklen);
2753 free(ed25519_sk);
2754 }
2755 return r; 3064 return r;
2756} 3065}
2757 3066
@@ -2829,8 +3138,7 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2829 ret = 0; 3138 ret = 0;
2830 out: 3139 out:
2831 BN_CTX_free(bnctx); 3140 BN_CTX_free(bnctx);
2832 if (nq != NULL) 3141 EC_POINT_free(nq);
2833 EC_POINT_free(nq);
2834 return ret; 3142 return ret;
2835} 3143}
2836 3144
@@ -3007,7 +3315,8 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
3007 goto out; 3315 goto out;
3008 3316
3009 /* append private key and comment*/ 3317 /* append private key and comment*/
3010 if ((r = sshkey_private_serialize(prv, encrypted)) != 0 || 3318 if ((r = sshkey_private_serialize_opt(prv, encrypted,
3319 SSHKEY_SERIALIZE_FULL)) != 0 ||
3011 (r = sshbuf_put_cstring(encrypted, comment)) != 0) 3320 (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3012 goto out; 3321 goto out;
3013 3322
@@ -3305,7 +3614,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3305 int blen, len = strlen(_passphrase); 3614 int blen, len = strlen(_passphrase);
3306 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; 3615 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3307 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; 3616 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
3308 const u_char *bptr; 3617 char *bptr;
3309 BIO *bio = NULL; 3618 BIO *bio = NULL;
3310 3619
3311 if (len > 0 && len <= 4) 3620 if (len > 0 && len <= 4)
@@ -3368,6 +3677,9 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3368 passphrase, comment); 3677 passphrase, comment);
3369#endif /* WITH_OPENSSL */ 3678#endif /* WITH_OPENSSL */
3370 case KEY_ED25519: 3679 case KEY_ED25519:
3680#ifdef WITH_XMSS
3681 case KEY_XMSS:
3682#endif /* WITH_XMSS */
3371 return sshkey_private_to_blob2(key, blob, passphrase, 3683 return sshkey_private_to_blob2(key, blob, passphrase,
3372 comment, new_format_cipher, new_format_rounds); 3684 comment, new_format_cipher, new_format_rounds);
3373 default: 3685 default:
@@ -3525,8 +3837,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
3525 } 3837 }
3526 out: 3838 out:
3527 BIO_free(bio); 3839 BIO_free(bio);
3528 if (pk != NULL) 3840 EVP_PKEY_free(pk);
3529 EVP_PKEY_free(pk);
3530 sshkey_free(prv); 3841 sshkey_free(prv);
3531 return r; 3842 return r;
3532} 3843}
@@ -3552,6 +3863,9 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3552 passphrase, keyp); 3863 passphrase, keyp);
3553#endif /* WITH_OPENSSL */ 3864#endif /* WITH_OPENSSL */
3554 case KEY_ED25519: 3865 case KEY_ED25519:
3866#ifdef WITH_XMSS
3867 case KEY_XMSS:
3868#endif /* WITH_XMSS */
3555 return sshkey_parse_private2(blob, type, passphrase, 3869 return sshkey_parse_private2(blob, type, passphrase,
3556 keyp, commentp); 3870 keyp, commentp);
3557 case KEY_UNSPEC: 3871 case KEY_UNSPEC:
@@ -3583,3 +3897,90 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
3583 return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, 3897 return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3584 passphrase, keyp, commentp); 3898 passphrase, keyp, commentp);
3585} 3899}
3900
3901#ifdef WITH_XMSS
3902/*
3903 * serialize the key with the current state and forward the state
3904 * maxsign times.
3905 */
3906int
3907sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
3908 u_int32_t maxsign, sshkey_printfn *pr)
3909{
3910 int r, rupdate;
3911
3912 if (maxsign == 0 ||
3913 sshkey_type_plain(k->type) != KEY_XMSS)
3914 return sshkey_private_serialize_opt(k, b,
3915 SSHKEY_SERIALIZE_DEFAULT);
3916 if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
3917 (r = sshkey_private_serialize_opt(k, b,
3918 SSHKEY_SERIALIZE_STATE)) != 0 ||
3919 (r = sshkey_xmss_forward_state(k, maxsign)) != 0)
3920 goto out;
3921 r = 0;
3922out:
3923 if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
3924 if (r == 0)
3925 r = rupdate;
3926 }
3927 return r;
3928}
3929
3930u_int32_t
3931sshkey_signatures_left(const struct sshkey *k)
3932{
3933 if (sshkey_type_plain(k->type) == KEY_XMSS)
3934 return sshkey_xmss_signatures_left(k);
3935 return 0;
3936}
3937
3938int
3939sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
3940{
3941 if (sshkey_type_plain(k->type) != KEY_XMSS)
3942 return SSH_ERR_INVALID_ARGUMENT;
3943 return sshkey_xmss_enable_maxsign(k, maxsign);
3944}
3945
3946int
3947sshkey_set_filename(struct sshkey *k, const char *filename)
3948{
3949 if (k == NULL)
3950 return SSH_ERR_INVALID_ARGUMENT;
3951 if (sshkey_type_plain(k->type) != KEY_XMSS)
3952 return 0;
3953 if (filename == NULL)
3954 return SSH_ERR_INVALID_ARGUMENT;
3955 if ((k->xmss_filename = strdup(filename)) == NULL)
3956 return SSH_ERR_ALLOC_FAIL;
3957 return 0;
3958}
3959#else
3960int
3961sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
3962 u_int32_t maxsign, sshkey_printfn *pr)
3963{
3964 return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
3965}
3966
3967u_int32_t
3968sshkey_signatures_left(const struct sshkey *k)
3969{
3970 return 0;
3971}
3972
3973int
3974sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
3975{
3976 return SSH_ERR_INVALID_ARGUMENT;
3977}
3978
3979int
3980sshkey_set_filename(struct sshkey *k, const char *filename)
3981{
3982 if (k == NULL)
3983 return SSH_ERR_INVALID_ARGUMENT;
3984 return 0;
3985}
3986#endif /* WITH_XMSS */