32
32
#include <usb/u2f/u2f_keys.h>
33
33
#include <usb/usb_packet.h>
34
34
#include <usb/usb_processing.h>
35
+ #include <utils_assert.h>
35
36
#include <version.h>
36
37
#include <wally_crypto.h>
37
38
@@ -68,19 +69,14 @@ typedef enum {
68
69
} u2f_auth_state_t ;
69
70
70
71
typedef struct {
71
- uint32_t cid ;
72
72
/**
73
- * Command that is currently executing
74
- * (blocking) on the U2F stack.
73
+ * CID and last command are used to check that we eventually respond to the right command after
74
+ * the user has confirmed on screen. U2F is normally stateless between transactions, but since
75
+ * we have a display and Yes/No input we can ask the user on the first request and later respond
76
+ * that the user is present only if the user confirmed specifically that app-id.
75
77
*/
78
+ uint32_t cid ;
76
79
uint8_t last_cmd ;
77
- /**
78
- * Keeps track of whether there is an outstanding
79
- * U2F operation going on in the background.
80
- * This is not strictly necessary, but it's useful
81
- * to have as a sanity checking mechanism.
82
- */
83
- bool locked ;
84
80
/**
85
81
* Keeps track of which part of a registration we're currently in.
86
82
*/
@@ -131,30 +127,6 @@ static void _clear_state(void)
131
127
{
132
128
_state .reg = U2F_REGISTER_IDLE ;
133
129
_state .auth = U2F_AUTHENTICATE_IDLE ;
134
- _state .locked = false;
135
- }
136
-
137
- /**
138
- * Unlocks the USB stack. Resets the U2F state.
139
- */
140
- static void _unlock (void )
141
- {
142
- usb_processing_unlock ();
143
- _clear_state ();
144
- }
145
-
146
- /**
147
- * Locks the USB stack to process the given
148
- * U2F request.
149
- *
150
- * @param apdu U2F packet that will own the lock on the USB stack. No other request
151
- * will be processed by the USB stack until this request completes.
152
- */
153
- static void _lock (const USB_APDU * apdu )
154
- {
155
- usb_processing_lock (usb_processing_u2f ());
156
- _state .locked = true;
157
- _state .last_cmd = apdu -> ins ;
158
130
}
159
131
160
132
static component_t * _nudge_label = NULL ;
@@ -183,7 +155,7 @@ static void _start_refresh_webpage_screen(void)
183
155
// Unfortunately unlocking takes more time than U2F is allowed to take. With the current
184
156
// architecture of the firmware we cannot run it concurrently to other requests. Therefore
185
157
// we will call it here, make the user unlock the device and then ask the user to refresh
186
- // the webpage. (refreshing is only needed for some browsers )
158
+ // the webpage. (refreshing is only needed for some FIDO Clients )
187
159
_state .refresh_webpage = _create_refresh_webpage ();
188
160
ui_screen_stack_push (_state .refresh_webpage );
189
161
_state .refresh_webpage_timeout = 0 ;
@@ -421,7 +393,7 @@ static void _register_start(const USB_APDU* apdu, Packet* out_packet)
421
393
const U2F_REGISTER_REQ * reg_request = (const U2F_REGISTER_REQ * )apdu -> data ;
422
394
uint16_t req_error = _register_sanity_check_req (apdu );
423
395
if (req_error ) {
424
- _unlock ();
396
+ _clear_state ();
425
397
_error (req_error , out_packet );
426
398
return ;
427
399
}
@@ -462,7 +434,7 @@ static void _register_continue(const USB_APDU* apdu, Packet* out_packet)
462
434
}
463
435
464
436
/* No more pending operations for U2F register */
465
- _unlock ();
437
+ _clear_state ();
466
438
467
439
if (async_result == ASYNC_OP_FALSE ) {
468
440
_error (U2F_SW_CONDITIONS_NOT_SATISFIED , out_packet );
@@ -582,7 +554,7 @@ static void _authenticate_start(const USB_APDU* apdu, Packet* out_packet)
582
554
{
583
555
uint16_t req_error = _authenticate_sanity_check_req (apdu );
584
556
if (req_error ) {
585
- _unlock ();
557
+ _clear_state ();
586
558
_error (req_error , out_packet );
587
559
return ;
588
560
}
@@ -596,7 +568,7 @@ static void _authenticate_start(const USB_APDU* apdu, Packet* out_packet)
596
568
}
597
569
uint16_t key_error = _authenticate_start_confirm (apdu );
598
570
if (key_error ) {
599
- _unlock ();
571
+ _clear_state ();
600
572
_error (key_error , out_packet );
601
573
return ;
602
574
}
@@ -608,7 +580,7 @@ static void _authenticate_wait_refresh(const USB_APDU* apdu, Packet* out_packet)
608
580
_assert_unlocked ();
609
581
uint16_t key_error = _authenticate_start_confirm (apdu );
610
582
if (key_error ) {
611
- _unlock ();
583
+ _clear_state ();
612
584
_error (key_error , out_packet );
613
585
return ;
614
586
}
@@ -624,10 +596,18 @@ static void _authenticate_continue(const USB_APDU* apdu, Packet* out_packet)
624
596
U2F_AUTHENTICATE_SIG_STR sig_base ;
625
597
uint16_t req_error = _authenticate_sanity_check_req (apdu );
626
598
if (req_error ) {
599
+ _clear_state ();
627
600
_error (req_error , out_packet );
628
601
return ;
629
602
}
630
603
604
+ uint16_t key_error = _authenticate_verify_key_valid (apdu );
605
+ if (key_error ) {
606
+ _clear_state ();
607
+ _error (key_error , out_packet );
608
+ return ;
609
+ }
610
+
631
611
const U2F_AUTHENTICATE_REQ * auth_request = (const U2F_AUTHENTICATE_REQ * )apdu -> data ;
632
612
async_op_result_t async_result =
633
613
u2f_app_confirm_retry (U2F_APP_AUTHENTICATE , auth_request -> appId );
@@ -637,7 +617,7 @@ static void _authenticate_continue(const USB_APDU* apdu, Packet* out_packet)
637
617
}
638
618
639
619
/* No more blocking operations pending for authentication. */
640
- _unlock ();
620
+ _clear_state ();
641
621
642
622
if (async_result == ASYNC_OP_FALSE ) {
643
623
_error (U2F_SW_CONDITIONS_NOT_SATISFIED , out_packet );
@@ -789,12 +769,13 @@ static void _cmd_register(const Packet* in_packet, Packet* out_packet)
789
769
/* Sanity-check our state. */
790
770
if (_state .reg != U2F_REGISTER_IDLE &&
791
771
(_state .last_cmd != U2F_REGISTER || _state .cid != in_packet -> cid )) {
792
- Abort ("U2F reg arbitration failed." );
772
+ util_log ("u2f: ERROR register invalid state" );
773
+ _clear_state ();
774
+ return ;
793
775
}
794
776
795
777
switch (_state .reg ) {
796
778
case U2F_REGISTER_IDLE :
797
- _lock (apdu );
798
779
_register_start (apdu , out_packet );
799
780
break ;
800
781
case U2F_REGISTER_UNLOCKING :
@@ -811,29 +792,6 @@ static void _cmd_register(const Packet* in_packet, Packet* out_packet)
811
792
}
812
793
}
813
794
814
- /**
815
- * Abort an existing registration request.
816
- */
817
- static void _abort_register (void )
818
- {
819
- switch (_state .reg ) {
820
- case U2F_REGISTER_UNLOCKING :
821
- rust_workflow_abort_current ();
822
- _clear_state ();
823
- break ;
824
- case U2F_REGISTER_CONFIRMING :
825
- u2f_app_confirm_abort ();
826
- _clear_state ();
827
- break ;
828
- case U2F_REGISTER_WAIT_REFRESH :
829
- _stop_refresh_webpage_screen ();
830
- _clear_state ();
831
- break ;
832
- default :
833
- Abort ("Bad U2F register abort status" );
834
- }
835
- }
836
-
837
795
/**
838
796
* Processes an incoming registration request.
839
797
*/
@@ -843,12 +801,13 @@ static void _cmd_authenticate(const Packet* in_packet, Packet* out_packet)
843
801
/* Sanity-check our state. */
844
802
if (_state .auth != U2F_AUTHENTICATE_IDLE &&
845
803
(_state .last_cmd != U2F_AUTHENTICATE || _state .cid != in_packet -> cid )) {
846
- Abort ("U2F auth arbitration failed." );
804
+ util_log ("u2f: ERROR authenticate invalid state" );
805
+ _clear_state ();
806
+ return ;
847
807
}
848
808
849
809
switch (_state .auth ) {
850
810
case U2F_AUTHENTICATE_IDLE :
851
- _lock (apdu );
852
811
_authenticate_start (apdu , out_packet );
853
812
break ;
854
813
case U2F_AUTHENTICATE_UNLOCKING :
@@ -865,35 +824,20 @@ static void _cmd_authenticate(const Packet* in_packet, Packet* out_packet)
865
824
}
866
825
}
867
826
868
- /**
869
- * Abort an existing authentication request.
870
- */
871
- static void _abort_authenticate (void )
872
- {
873
- switch (_state .auth ) {
874
- case U2F_AUTHENTICATE_UNLOCKING :
875
- rust_workflow_abort_current ();
876
- _clear_state ();
877
- break ;
878
- case U2F_AUTHENTICATE_CONFIRMING :
879
- u2f_app_confirm_abort ();
880
- _clear_state ();
881
- break ;
882
- case U2F_AUTHENTICATE_WAIT_REFRESH :
883
- _stop_refresh_webpage_screen ();
884
- _clear_state ();
885
- break ;
886
- default :
887
- Abort ("Bad U2F register abort status" );
888
- }
889
- }
890
-
891
827
/**
892
828
* Process a U2F message
893
829
*/
894
830
static void _cmd_msg (const Packet * in_packet , Packet * out_packet , const size_t max_out_len )
895
831
{
896
832
(void )max_out_len ;
833
+
834
+ // Give the user 5s to respond to u2f requests (the FIDO Client in u2f is not required to ping
835
+ // every 200ms like the BitBoxApp does even though most implementations do).
836
+ usb_processing_timeout_reset (-50 );
837
+
838
+ // The usb stack must be locked until we have responded to this request.
839
+ usb_processing_lock (usb_processing_u2f ());
840
+
897
841
// By default always use the recieved cid
898
842
_state .cid = in_packet -> cid ;
899
843
@@ -911,33 +855,27 @@ static void _cmd_msg(const Packet* in_packet, Packet* out_packet, const size_t m
911
855
switch (apdu -> ins ) {
912
856
case U2F_REGISTER :
913
857
_cmd_register (in_packet , out_packet );
858
+ _state .last_cmd = apdu -> ins ;
914
859
break ;
915
860
case U2F_AUTHENTICATE :
916
861
_cmd_authenticate (in_packet , out_packet );
862
+ _state .last_cmd = apdu -> ins ;
917
863
break ;
918
864
case U2F_VERSION :
919
865
_version (apdu , out_packet );
920
866
break ;
921
867
default :
922
868
_error (U2F_SW_INS_NOT_SUPPORTED , out_packet );
923
- return ;
869
+ break ;
924
870
}
925
871
}
926
872
873
+ // U2F only locks USB stack between a request and a response. A request is always immediately
874
+ // followed by a response. New requests must wait until the current one is finished.
927
875
bool u2f_blocking_request_can_go_through (const Packet * in_packet )
928
876
{
929
- if (!_state .locked ) {
930
- Abort ("USB stack thinks we're busy, but we're not." );
931
- }
932
- /*
933
- * Check if this request is the same one we're currently operating on.
934
- * For now, this checks the request type and channel ID only.
935
- * FUTURE: Maybe check that the key handle is maintained between requests?
936
- * so that when we're asking for confirmation, we ask to confirm
937
- * "a particular key handle" instead of "a particular tab".
938
- */
939
- const USB_APDU * apdu = (const USB_APDU * )in_packet -> data_addr ;
940
- return apdu -> ins == _state .last_cmd && in_packet -> cid == _state .cid ;
877
+ (void )in_packet ;
878
+ return false;
941
879
}
942
880
943
881
void u2f_blocked_req_error (Packet * out_packet , const Packet * in_packet )
@@ -980,7 +918,7 @@ static void _process_wait_refresh(void)
980
918
{
981
919
if (_state .refresh_webpage_timeout == 25000 ) {
982
920
_stop_refresh_webpage_screen ();
983
- _unlock ();
921
+ _clear_state ();
984
922
} else {
985
923
_state .refresh_webpage_timeout ++ ;
986
924
/* Prevent the USB watchdog from killing this workflow. */
@@ -1024,16 +962,16 @@ static void _process_authenticate(void)
1024
962
1025
963
void u2f_process (void )
1026
964
{
1027
- if (!_state .locked ) {
1028
- return ;
1029
- }
1030
965
switch (_state .last_cmd ) {
1031
966
case U2F_REGISTER :
1032
967
_process_register ();
1033
968
break ;
1034
969
case U2F_AUTHENTICATE :
1035
970
_process_authenticate ();
1036
971
break ;
972
+ case 0 :
973
+ // initial value
974
+ break ;
1037
975
default :
1038
976
Abort ("Bad U2F process state." );
1039
977
}
@@ -1044,6 +982,8 @@ void u2f_process(void)
1044
982
*/
1045
983
void u2f_device_setup (void )
1046
984
{
985
+ _clear_state ();
986
+ _state .last_cmd = 0 ;
1047
987
const CMD_Callback u2f_cmd_callbacks [] = {
1048
988
{U2FHID_PING , _cmd_ping },
1049
989
{U2FHID_WINK , _cmd_wink },
@@ -1056,17 +996,5 @@ void u2f_device_setup(void)
1056
996
1057
997
void u2f_abort_outstanding_op (void )
1058
998
{
1059
- if (!_state .locked ) {
1060
- Abort ("USB stack thinks U2F is busy, but it's not." );
1061
- }
1062
- switch (_state .last_cmd ) {
1063
- case U2F_REGISTER :
1064
- _abort_register ();
1065
- break ;
1066
- case U2F_AUTHENTICATE :
1067
- _abort_authenticate ();
1068
- break ;
1069
- default :
1070
- Abort ("Invalid U2F status on abort." );
1071
- }
999
+ util_log ("u2f_abort_outstanding_op" );
1072
1000
}
0 commit comments