diff options
Diffstat (limited to 'sshkey-xmss.c')
-rw-r--r-- | sshkey-xmss.c | 80 |
1 files changed, 68 insertions, 12 deletions
diff --git a/sshkey-xmss.c b/sshkey-xmss.c index 9e5f5e475..88e9ddf4d 100644 --- a/sshkey-xmss.c +++ b/sshkey-xmss.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey-xmss.c,v 1.6 2019/10/09 00:02:57 djm Exp $ */ | 1 | /* $OpenBSD: sshkey-xmss.c,v 1.8 2019/11/13 07:53:10 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2017 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2017 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -69,7 +69,7 @@ struct ssh_xmss_state { | |||
69 | u_int32_t maxidx; /* restricted # of signatures */ | 69 | u_int32_t maxidx; /* restricted # of signatures */ |
70 | int have_state; /* .state file exists */ | 70 | int have_state; /* .state file exists */ |
71 | int lockfd; /* locked in sshkey_xmss_get_state() */ | 71 | int lockfd; /* locked in sshkey_xmss_get_state() */ |
72 | int allow_update; /* allow sshkey_xmss_update_state() */ | 72 | u_char allow_update; /* allow sshkey_xmss_update_state() */ |
73 | char *enc_ciphername;/* encrypt state with cipher */ | 73 | char *enc_ciphername;/* encrypt state with cipher */ |
74 | u_char *enc_keyiv; /* encrypt state with key */ | 74 | u_char *enc_keyiv; /* encrypt state with key */ |
75 | u_int32_t enc_keyiv_len; /* length of enc_keyiv */ | 75 | u_int32_t enc_keyiv_len; /* length of enc_keyiv */ |
@@ -716,6 +716,7 @@ sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, | |||
716 | { | 716 | { |
717 | struct ssh_xmss_state *state = k->xmss_state; | 717 | struct ssh_xmss_state *state = k->xmss_state; |
718 | int r = SSH_ERR_INVALID_ARGUMENT; | 718 | int r = SSH_ERR_INVALID_ARGUMENT; |
719 | u_char have_stack, have_filename, have_enc; | ||
719 | 720 | ||
720 | if (state == NULL) | 721 | if (state == NULL) |
721 | return SSH_ERR_INVALID_ARGUMENT; | 722 | return SSH_ERR_INVALID_ARGUMENT; |
@@ -727,9 +728,35 @@ sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, | |||
727 | break; | 728 | break; |
728 | case SSHKEY_SERIALIZE_FULL: | 729 | case SSHKEY_SERIALIZE_FULL: |
729 | if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0) | 730 | if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0) |
730 | break; | 731 | return r; |
731 | r = sshkey_xmss_serialize_state(k, b); | 732 | r = sshkey_xmss_serialize_state(k, b); |
732 | break; | 733 | break; |
734 | case SSHKEY_SERIALIZE_SHIELD: | ||
735 | /* all of stack/filename/enc are optional */ | ||
736 | have_stack = state->stack != NULL; | ||
737 | if ((r = sshbuf_put_u8(b, have_stack)) != 0) | ||
738 | return r; | ||
739 | if (have_stack) { | ||
740 | state->idx = PEEK_U32(k->xmss_sk); /* update */ | ||
741 | if ((r = sshkey_xmss_serialize_state(k, b)) != 0) | ||
742 | return r; | ||
743 | } | ||
744 | have_filename = k->xmss_filename != NULL; | ||
745 | if ((r = sshbuf_put_u8(b, have_filename)) != 0) | ||
746 | return r; | ||
747 | if (have_filename && | ||
748 | (r = sshbuf_put_cstring(b, k->xmss_filename)) != 0) | ||
749 | return r; | ||
750 | have_enc = state->enc_keyiv != NULL; | ||
751 | if ((r = sshbuf_put_u8(b, have_enc)) != 0) | ||
752 | return r; | ||
753 | if (have_enc && | ||
754 | (r = sshkey_xmss_serialize_enc_key(k, b)) != 0) | ||
755 | return r; | ||
756 | if ((r = sshbuf_put_u32(b, state->maxidx)) != 0 || | ||
757 | (r = sshbuf_put_u8(b, state->allow_update)) != 0) | ||
758 | return r; | ||
759 | break; | ||
733 | case SSHKEY_SERIALIZE_DEFAULT: | 760 | case SSHKEY_SERIALIZE_DEFAULT: |
734 | r = 0; | 761 | r = 0; |
735 | break; | 762 | break; |
@@ -748,7 +775,7 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) | |||
748 | u_int32_t i, lh, node; | 775 | u_int32_t i, lh, node; |
749 | size_t ls, lsl, la, lk, ln, lr; | 776 | size_t ls, lsl, la, lk, ln, lr; |
750 | char *magic; | 777 | char *magic; |
751 | int r; | 778 | int r = SSH_ERR_INTERNAL_ERROR; |
752 | 779 | ||
753 | if (state == NULL) | 780 | if (state == NULL) |
754 | return SSH_ERR_INVALID_ARGUMENT; | 781 | return SSH_ERR_INVALID_ARGUMENT; |
@@ -767,9 +794,11 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) | |||
767 | (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 || | 794 | (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 || |
768 | (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 || | 795 | (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 || |
769 | (r = sshbuf_get_u32(b, &lh)) != 0) | 796 | (r = sshbuf_get_u32(b, &lh)) != 0) |
770 | return r; | 797 | goto out; |
771 | if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) | 798 | if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) { |
772 | return SSH_ERR_INVALID_ARGUMENT; | 799 | r = SSH_ERR_INVALID_ARGUMENT; |
800 | goto out; | ||
801 | } | ||
773 | /* XXX check stackoffset */ | 802 | /* XXX check stackoffset */ |
774 | if (ls != num_stack(state) || | 803 | if (ls != num_stack(state) || |
775 | lsl != num_stacklevels(state) || | 804 | lsl != num_stacklevels(state) || |
@@ -777,8 +806,10 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) | |||
777 | lk != num_keep(state) || | 806 | lk != num_keep(state) || |
778 | ln != num_th_nodes(state) || | 807 | ln != num_th_nodes(state) || |
779 | lr != num_retain(state) || | 808 | lr != num_retain(state) || |
780 | lh != num_treehash(state)) | 809 | lh != num_treehash(state)) { |
781 | return SSH_ERR_INVALID_ARGUMENT; | 810 | r = SSH_ERR_INVALID_ARGUMENT; |
811 | goto out; | ||
812 | } | ||
782 | for (i = 0; i < num_treehash(state); i++) { | 813 | for (i = 0; i < num_treehash(state); i++) { |
783 | th = &state->treehash[i]; | 814 | th = &state->treehash[i]; |
784 | if ((r = sshbuf_get_u32(b, &th->h)) != 0 || | 815 | if ((r = sshbuf_get_u32(b, &th->h)) != 0 || |
@@ -786,7 +817,7 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) | |||
786 | (r = sshbuf_get_u32(b, &th->stackusage)) != 0 || | 817 | (r = sshbuf_get_u32(b, &th->stackusage)) != 0 || |
787 | (r = sshbuf_get_u8(b, &th->completed)) != 0 || | 818 | (r = sshbuf_get_u8(b, &th->completed)) != 0 || |
788 | (r = sshbuf_get_u32(b, &node)) != 0) | 819 | (r = sshbuf_get_u32(b, &node)) != 0) |
789 | return r; | 820 | goto out; |
790 | if (node < num_th_nodes(state)) | 821 | if (node < num_th_nodes(state)) |
791 | th->node = &state->th_nodes[node]; | 822 | th->node = &state->th_nodes[node]; |
792 | } | 823 | } |
@@ -794,14 +825,19 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) | |||
794 | xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, | 825 | xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, |
795 | state->stacklevels, state->auth, state->keep, state->treehash, | 826 | state->stacklevels, state->auth, state->keep, state->treehash, |
796 | state->retain, 0); | 827 | state->retain, 0); |
797 | return 0; | 828 | /* success */ |
829 | r = 0; | ||
830 | out: | ||
831 | free(magic); | ||
832 | return r; | ||
798 | } | 833 | } |
799 | 834 | ||
800 | int | 835 | int |
801 | sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) | 836 | sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) |
802 | { | 837 | { |
838 | struct ssh_xmss_state *state = k->xmss_state; | ||
803 | enum sshkey_serialize_rep opts; | 839 | enum sshkey_serialize_rep opts; |
804 | u_char have_state; | 840 | u_char have_state, have_stack, have_filename, have_enc; |
805 | int r; | 841 | int r; |
806 | 842 | ||
807 | if ((r = sshbuf_get_u8(b, &have_state)) != 0) | 843 | if ((r = sshbuf_get_u8(b, &have_state)) != 0) |
@@ -812,6 +848,26 @@ sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) | |||
812 | case SSHKEY_SERIALIZE_DEFAULT: | 848 | case SSHKEY_SERIALIZE_DEFAULT: |
813 | r = 0; | 849 | r = 0; |
814 | break; | 850 | break; |
851 | case SSHKEY_SERIALIZE_SHIELD: | ||
852 | if ((r = sshbuf_get_u8(b, &have_stack)) != 0) | ||
853 | return r; | ||
854 | if (have_stack && | ||
855 | (r = sshkey_xmss_deserialize_state(k, b)) != 0) | ||
856 | return r; | ||
857 | if ((r = sshbuf_get_u8(b, &have_filename)) != 0) | ||
858 | return r; | ||
859 | if (have_filename && | ||
860 | (r = sshbuf_get_cstring(b, &k->xmss_filename, NULL)) != 0) | ||
861 | return r; | ||
862 | if ((r = sshbuf_get_u8(b, &have_enc)) != 0) | ||
863 | return r; | ||
864 | if (have_enc && | ||
865 | (r = sshkey_xmss_deserialize_enc_key(k, b)) != 0) | ||
866 | return r; | ||
867 | if ((r = sshbuf_get_u32(b, &state->maxidx)) != 0 || | ||
868 | (r = sshbuf_get_u8(b, &state->allow_update)) != 0) | ||
869 | return r; | ||
870 | break; | ||
815 | case SSHKEY_SERIALIZE_STATE: | 871 | case SSHKEY_SERIALIZE_STATE: |
816 | if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) | 872 | if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) |
817 | return r; | 873 | return r; |