diff options
author | Colin Watson <cjwatson@debian.org> | 2018-04-03 08:20:28 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2018-04-03 08:20:28 +0100 |
commit | ed6ae9c1a014a08ff5db3d768f01f2e427eeb476 (patch) | |
tree | 601025e307745d351946c01ab13f419ddb6dae29 /sshkey.c | |
parent | 62f54f20bf351468e0124f63cc2902ee40d9b0e9 (diff) | |
parent | a0349a1cc4a18967ad1dbff5389bcdf9da098814 (diff) |
Import openssh_7.7p1.orig.tar.gz
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 743 |
1 files changed, 572 insertions, 171 deletions
@@ -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 | ||
77 | int sshkey_private_serialize_opt(const struct sshkey *key, | ||
78 | struct sshbuf *buf, enum sshkey_serialize_rep); | ||
74 | static int sshkey_from_blob_internal(struct sshbuf *buf, | 79 | static 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 | ||
427 | static struct sshkey_cert * | 441 | static 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 | ||
624 | static int | 646 | static 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 | ||
711 | static int | 740 | static int |
712 | to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) | 741 | to_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) | |||
786 | int | 832 | int |
787 | sshkey_putb(const struct sshkey *key, struct sshbuf *b) | 833 | sshkey_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 | ||
792 | int | 838 | int |
793 | sshkey_puts(const struct sshkey *key, struct sshbuf *b) | 839 | sshkey_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 | ||
807 | int | 854 | int |
855 | sshkey_puts(const struct sshkey *key, struct sshbuf *b) | ||
856 | { | ||
857 | return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT); | ||
858 | } | ||
859 | |||
860 | int | ||
808 | sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) | 861 | sshkey_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 | ||
813 | static int | 866 | static int |
814 | to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain) | 867 | to_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) | |||
844 | int | 898 | int |
845 | sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) | 899 | sshkey_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 | ||
850 | int | 904 | int |
851 | sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) | 905 | sshkey_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 | ||
856 | int | 910 | int |
@@ -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 | ||
1218 | static int | ||
1219 | peek_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 * */ |
1166 | int | 1237 | int |
1167 | sshkey_read(struct sshkey *ret, char **cpp) | 1238 | sshkey_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 | |||
1304 | int | 1400 | int |
1305 | sshkey_to_base64(const struct sshkey *key, char **b64p) | 1401 | sshkey_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 | ||
2052 | int | 2201 | int |
2202 | sshkey_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 | |||
2226 | int | ||
2053 | sshkey_sign(const struct sshkey *key, | 2227 | sshkey_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 | */ |
2088 | int | 2268 | int |
2089 | sshkey_verify(const struct sshkey *key, | 2269 | sshkey_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 | ||
2467 | int | 2694 | int |
2468 | sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) | 2695 | sshkey_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 | ||
2564 | int | 2822 | int |
2823 | sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b) | ||
2824 | { | ||
2825 | return sshkey_private_serialize_opt(key, b, | ||
2826 | SSHKEY_SERIALIZE_DEFAULT); | ||
2827 | } | ||
2828 | |||
2829 | int | ||
2565 | sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) | 2830 | sshkey_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 | */ | ||
3905 | int | ||
3906 | sshkey_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; | ||
3921 | out: | ||
3922 | if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) { | ||
3923 | if (r == 0) | ||
3924 | r = rupdate; | ||
3925 | } | ||
3926 | return r; | ||
3927 | } | ||
3928 | |||
3929 | u_int32_t | ||
3930 | sshkey_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 | |||
3937 | int | ||
3938 | sshkey_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 | |||
3945 | int | ||
3946 | sshkey_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 | ||
3959 | int | ||
3960 | sshkey_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 | |||
3966 | u_int32_t | ||
3967 | sshkey_signatures_left(const struct sshkey *k) | ||
3968 | { | ||
3969 | return 0; | ||
3970 | } | ||
3971 | |||
3972 | int | ||
3973 | sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign) | ||
3974 | { | ||
3975 | return SSH_ERR_INVALID_ARGUMENT; | ||
3976 | } | ||
3977 | |||
3978 | int | ||
3979 | sshkey_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 */ | ||