summaryrefslogtreecommitdiff
path: root/sshkey-xmss.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshkey-xmss.c')
-rw-r--r--sshkey-xmss.c80
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
800int 835int
801sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) 836sshkey_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;