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