@@ -94,6 +94,15 @@ const uint8_t _hijack_code[U2F_HIJACK_ORIGIN_TOTAL][U2F_APPID_SIZE] = {
94
94
}
95
95
};
96
96
97
+ typedef enum HIJACK_STATE {
98
+ // Do not change the order!
99
+ // Order affects third party integrations that make use of the hijack mode
100
+ HIJACK_STATE_RESPONSE_READY ,
101
+ HIJACK_STATE_PROCESSING_COMMAND ,
102
+ HIJACK_STATE_INCOMPLETE_COMMAND ,
103
+ HIJACK_STATE_IDLE ,
104
+ } HIJACK_STATE ;
105
+
97
106
typedef struct {
98
107
uint8_t reserved ;
99
108
uint8_t appId [U2F_APPID_SIZE ];
@@ -284,31 +293,64 @@ static uint16_t _frame_hijack_report(char *report, uint16_t len, uint16_t report
284
293
285
294
static void _hijack (const U2F_AUTHENTICATE_REQ * req )
286
295
{
287
- static char hijack_cmd [COMMANDER_REPORT_SIZE ] = {0 };
288
- char * report ;
289
- int report_len ;
296
+ static HIJACK_STATE state = HIJACK_STATE_IDLE ;
297
+ static char hijack_io_buffer [COMMANDER_REPORT_SIZE ] = {0 };
298
+ char byte_report [U2F_FRAME_SIZE + 1 ] = {0 };
299
+ uint16_t report_len ;
290
300
size_t kh_len = MIN (U2F_MAX_KH_SIZE - 2 , strlens ((const char * )req -> keyHandle + 2 ));
291
301
uint8_t tot = req -> keyHandle [0 ];
292
302
uint8_t cnt = req -> keyHandle [1 ];
293
303
size_t idx = cnt * (U2F_MAX_KH_SIZE - 2 );
294
304
295
- if (idx + kh_len < sizeof (hijack_cmd )) {
296
- memcpy (hijack_cmd + idx , req -> keyHandle + 2 , kh_len );
297
- hijack_cmd [idx + kh_len ] = '\0' ;
298
- }
305
+ switch (state ) {
306
+ case HIJACK_STATE_PROCESSING_COMMAND :
307
+ // Previous command is still processing, for example, waiting for a touch button press
308
+ byte_report [0 ] = state ;
309
+ report_len = _frame_hijack_report (byte_report , 1 , sizeof (byte_report ));
310
+ u2f_queue_message ((const uint8_t * )byte_report , report_len );
311
+ break ;
312
+ case HIJACK_STATE_RESPONSE_READY :
313
+ // Previous command finished processing; return the response
314
+ report_len = _frame_hijack_report (hijack_io_buffer , strlens (hijack_io_buffer ),
315
+ COMMANDER_REPORT_SIZE );
316
+ u2f_queue_message ((const uint8_t * )hijack_io_buffer , report_len );
317
+ utils_zero (hijack_io_buffer , sizeof (hijack_io_buffer ));
318
+ state = HIJACK_STATE_IDLE ;
319
+ break ;
320
+ case HIJACK_STATE_INCOMPLETE_COMMAND :
321
+ case HIJACK_STATE_IDLE : {
322
+ if (idx + kh_len < sizeof (hijack_io_buffer )) {
323
+ // Fill the buffer with the command to process
324
+ snprintf (hijack_io_buffer + idx , sizeof (hijack_io_buffer ) - idx , "%.*s" ,
325
+ kh_len , req -> keyHandle + 2 );
326
+ }
299
327
300
- if (cnt + 1 < tot ) {
301
- // Need more data. Acknowledge by returning a 1-byte empty report.
302
- char empty_report [U2F_FRAME_SIZE + 1 ] = {0 };
303
- report_len = _frame_hijack_report (empty_report , 1 , sizeof (empty_report ));
304
- u2f_send_message ((const uint8_t * )empty_report , report_len );
305
- return ;
306
- }
328
+ if (cnt + 1 < tot ) {
329
+ // Command string is incomplete; acknowledge receipt of USB frame
330
+ state = HIJACK_STATE_INCOMPLETE_COMMAND ;
331
+ byte_report [0 ] = state ;
332
+ report_len = _frame_hijack_report (byte_report , 1 , sizeof (byte_report ));
333
+ u2f_queue_message ((const uint8_t * )byte_report , report_len );
334
+ break ;
335
+ }
307
336
308
- report = commander (hijack_cmd );
309
- report_len = _frame_hijack_report (report , strlens (report ), COMMANDER_REPORT_SIZE );
310
- utils_zero (hijack_cmd , sizeof (hijack_cmd ));
311
- u2f_send_message ((const uint8_t * )report , report_len );
337
+ // Acknowledge receipt of command
338
+ state = HIJACK_STATE_PROCESSING_COMMAND ;
339
+ byte_report [0 ] = state ;
340
+ report_len = _frame_hijack_report (byte_report , 1 , sizeof (byte_report ));
341
+ u2f_queue_message ((const uint8_t * )byte_report , report_len );
342
+ usb_reply_queue_send ();
343
+
344
+ // Process the command and fill the buffer with the response
345
+ char * report = commander (hijack_io_buffer );
346
+ utils_zero (hijack_io_buffer , sizeof (hijack_io_buffer ));
347
+ snprintf (hijack_io_buffer , sizeof (hijack_io_buffer ), "%s" , report );
348
+ state = HIJACK_STATE_RESPONSE_READY ;
349
+ break ;
350
+ }
351
+ default :
352
+ break ;
353
+ }
312
354
}
313
355
314
356
0 commit comments