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