1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use std::sync::{mpsc::Sender, Arc, Mutex};
6 
7 use crate::consts::PARAMETER_SIZE;
8 use crate::errors::*;
9 use crate::statecallback::StateCallback;
10 
11 pub trait AuthenticatorTransport {
12     /// The implementation of this method must return quickly and should
13     /// report its status via the status and callback methods
register( &mut self, flags: crate::RegisterFlags, timeout: u64, challenge: Vec<u8>, application: crate::AppId, key_handles: Vec<crate::KeyHandle>, status: Sender<crate::StatusUpdate>, callback: StateCallback<crate::Result<crate::RegisterResult>>, ) -> crate::Result<()>14     fn register(
15         &mut self,
16         flags: crate::RegisterFlags,
17         timeout: u64,
18         challenge: Vec<u8>,
19         application: crate::AppId,
20         key_handles: Vec<crate::KeyHandle>,
21         status: Sender<crate::StatusUpdate>,
22         callback: StateCallback<crate::Result<crate::RegisterResult>>,
23     ) -> crate::Result<()>;
24 
25     /// The implementation of this method must return quickly and should
26     /// report its status via the status and callback methods
sign( &mut self, flags: crate::SignFlags, timeout: u64, challenge: Vec<u8>, app_ids: Vec<crate::AppId>, key_handles: Vec<crate::KeyHandle>, status: Sender<crate::StatusUpdate>, callback: StateCallback<crate::Result<crate::SignResult>>, ) -> crate::Result<()>27     fn sign(
28         &mut self,
29         flags: crate::SignFlags,
30         timeout: u64,
31         challenge: Vec<u8>,
32         app_ids: Vec<crate::AppId>,
33         key_handles: Vec<crate::KeyHandle>,
34         status: Sender<crate::StatusUpdate>,
35         callback: StateCallback<crate::Result<crate::SignResult>>,
36     ) -> crate::Result<()>;
37 
cancel(&mut self) -> crate::Result<()>38     fn cancel(&mut self) -> crate::Result<()>;
39 }
40 
41 pub struct AuthenticatorService {
42     transports: Vec<Arc<Mutex<Box<dyn AuthenticatorTransport + Send>>>>,
43 }
44 
clone_and_configure_cancellation_callback<T>( mut callback: StateCallback<T>, transports_to_cancel: Vec<Arc<Mutex<Box<dyn AuthenticatorTransport + Send>>>>, ) -> StateCallback<T>45 fn clone_and_configure_cancellation_callback<T>(
46     mut callback: StateCallback<T>,
47     transports_to_cancel: Vec<Arc<Mutex<Box<dyn AuthenticatorTransport + Send>>>>,
48 ) -> StateCallback<T> {
49     callback.add_uncloneable_observer(Box::new(move || {
50         debug!(
51             "Callback observer is running, cancelling \
52              {} unchosen transports...",
53             transports_to_cancel.len()
54         );
55         for transport_mutex in &transports_to_cancel {
56             if let Err(e) = transport_mutex.lock().unwrap().cancel() {
57                 error!("Cancellation failed: {:?}", e);
58             }
59         }
60     }));
61     callback
62 }
63 
64 impl AuthenticatorService {
new() -> crate::Result<Self>65     pub fn new() -> crate::Result<Self> {
66         Ok(Self {
67             transports: Vec::new(),
68         })
69     }
70 
71     /// Add any detected platform transports
add_detected_transports(&mut self)72     pub fn add_detected_transports(&mut self) {
73         self.add_u2f_usb_hid_platform_transports();
74     }
75 
add_transport(&mut self, boxed_token: Box<dyn AuthenticatorTransport + Send>)76     fn add_transport(&mut self, boxed_token: Box<dyn AuthenticatorTransport + Send>) {
77         self.transports.push(Arc::new(Mutex::new(boxed_token)))
78     }
79 
add_u2f_usb_hid_platform_transports(&mut self)80     pub fn add_u2f_usb_hid_platform_transports(&mut self) {
81         match crate::U2FManager::new() {
82             Ok(token) => self.add_transport(Box::new(token)),
83             Err(e) => error!("Could not add U2F HID transport: {}", e),
84         }
85     }
86 
87     #[cfg(feature = "webdriver")]
add_webdriver_virtual_bus(&mut self)88     pub fn add_webdriver_virtual_bus(&mut self) {
89         match crate::virtualdevices::webdriver::VirtualManager::new() {
90             Ok(token) => {
91                 println!("WebDriver ready, listening at {}", &token.url());
92                 self.add_transport(Box::new(token));
93             }
94             Err(e) => error!("Could not add WebDriver virtual bus: {}", e),
95         }
96     }
97 
register( &mut self, flags: crate::RegisterFlags, timeout: u64, challenge: Vec<u8>, application: crate::AppId, key_handles: Vec<crate::KeyHandle>, status: Sender<crate::StatusUpdate>, callback: StateCallback<crate::Result<crate::RegisterResult>>, ) -> crate::Result<()>98     pub fn register(
99         &mut self,
100         flags: crate::RegisterFlags,
101         timeout: u64,
102         challenge: Vec<u8>,
103         application: crate::AppId,
104         key_handles: Vec<crate::KeyHandle>,
105         status: Sender<crate::StatusUpdate>,
106         callback: StateCallback<crate::Result<crate::RegisterResult>>,
107     ) -> crate::Result<()> {
108         if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
109             return Err(AuthenticatorError::InvalidRelyingPartyInput);
110         }
111 
112         for key_handle in &key_handles {
113             if key_handle.credential.len() > 256 {
114                 return Err(AuthenticatorError::InvalidRelyingPartyInput);
115             }
116         }
117 
118         let iterable_transports = self.transports.clone();
119         if iterable_transports.is_empty() {
120             return Err(AuthenticatorError::NoConfiguredTransports);
121         }
122 
123         debug!(
124             "register called with {} transports, iterable is {}",
125             self.transports.len(),
126             iterable_transports.len()
127         );
128 
129         for (idx, transport_mutex) in iterable_transports.iter().enumerate() {
130             let mut transports_to_cancel = iterable_transports.clone();
131             transports_to_cancel.remove(idx);
132 
133             debug!(
134                 "register transports_to_cancel {}",
135                 transports_to_cancel.len()
136             );
137 
138             transport_mutex.lock().unwrap().register(
139                 flags,
140                 timeout,
141                 challenge.clone(),
142                 application.clone(),
143                 key_handles.clone(),
144                 status.clone(),
145                 clone_and_configure_cancellation_callback(callback.clone(), transports_to_cancel),
146             )?;
147         }
148 
149         Ok(())
150     }
151 
sign( &mut self, flags: crate::SignFlags, timeout: u64, challenge: Vec<u8>, app_ids: Vec<crate::AppId>, key_handles: Vec<crate::KeyHandle>, status: Sender<crate::StatusUpdate>, callback: StateCallback<crate::Result<crate::SignResult>>, ) -> crate::Result<()>152     pub fn sign(
153         &mut self,
154         flags: crate::SignFlags,
155         timeout: u64,
156         challenge: Vec<u8>,
157         app_ids: Vec<crate::AppId>,
158         key_handles: Vec<crate::KeyHandle>,
159         status: Sender<crate::StatusUpdate>,
160         callback: StateCallback<crate::Result<crate::SignResult>>,
161     ) -> crate::Result<()> {
162         if challenge.len() != PARAMETER_SIZE {
163             return Err(AuthenticatorError::InvalidRelyingPartyInput);
164         }
165 
166         if app_ids.is_empty() {
167             return Err(AuthenticatorError::InvalidRelyingPartyInput);
168         }
169 
170         for app_id in &app_ids {
171             if app_id.len() != PARAMETER_SIZE {
172                 return Err(AuthenticatorError::InvalidRelyingPartyInput);
173             }
174         }
175 
176         for key_handle in &key_handles {
177             if key_handle.credential.len() > 256 {
178                 return Err(AuthenticatorError::InvalidRelyingPartyInput);
179             }
180         }
181 
182         let iterable_transports = self.transports.clone();
183         if iterable_transports.is_empty() {
184             return Err(AuthenticatorError::NoConfiguredTransports);
185         }
186 
187         for (idx, transport_mutex) in iterable_transports.iter().enumerate() {
188             let mut transports_to_cancel = iterable_transports.clone();
189             transports_to_cancel.remove(idx);
190 
191             transport_mutex.lock().unwrap().sign(
192                 flags,
193                 timeout,
194                 challenge.clone(),
195                 app_ids.clone(),
196                 key_handles.clone(),
197                 status.clone(),
198                 clone_and_configure_cancellation_callback(callback.clone(), transports_to_cancel),
199             )?;
200         }
201 
202         Ok(())
203     }
204 
cancel(&mut self) -> crate::Result<()>205     pub fn cancel(&mut self) -> crate::Result<()> {
206         if self.transports.is_empty() {
207             return Err(AuthenticatorError::NoConfiguredTransports);
208         }
209 
210         for transport_mutex in &mut self.transports {
211             transport_mutex.lock().unwrap().cancel()?;
212         }
213 
214         Ok(())
215     }
216 }
217 
218 ////////////////////////////////////////////////////////////////////////
219 // Tests
220 ////////////////////////////////////////////////////////////////////////
221 
222 #[cfg(test)]
223 mod tests {
224     use super::{AuthenticatorService, AuthenticatorTransport};
225     use crate::consts::PARAMETER_SIZE;
226     use crate::statecallback::StateCallback;
227     use crate::{AuthenticatorTransports, KeyHandle, RegisterFlags, SignFlags, StatusUpdate};
228     use std::sync::atomic::{AtomicBool, Ordering};
229     use std::sync::mpsc::{channel, Sender};
230     use std::sync::Arc;
231     use std::{io, thread};
232 
init()233     fn init() {
234         let _ = env_logger::builder().is_test(true).try_init();
235     }
236 
237     pub struct TestTransportDriver {
238         consent: bool,
239         was_cancelled: Arc<AtomicBool>,
240     }
241 
242     impl TestTransportDriver {
new(consent: bool) -> io::Result<Self>243         pub fn new(consent: bool) -> io::Result<Self> {
244             Ok(Self {
245                 consent,
246                 was_cancelled: Arc::new(AtomicBool::new(false)),
247             })
248         }
249     }
250 
251     impl TestTransportDriver {
dev_info(&self) -> crate::u2ftypes::U2FDeviceInfo252         fn dev_info(&self) -> crate::u2ftypes::U2FDeviceInfo {
253             crate::u2ftypes::U2FDeviceInfo {
254                 vendor_name: String::from("Mozilla").into_bytes(),
255                 device_name: String::from("Test Transport Token").into_bytes(),
256                 version_interface: 0,
257                 version_major: 1,
258                 version_minor: 2,
259                 version_build: 3,
260                 cap_flags: 0,
261             }
262         }
263     }
264 
265     impl AuthenticatorTransport for TestTransportDriver {
register( &mut self, _flags: crate::RegisterFlags, _timeout: u64, _challenge: Vec<u8>, _application: crate::AppId, _key_handles: Vec<crate::KeyHandle>, _status: Sender<crate::StatusUpdate>, callback: StateCallback<crate::Result<crate::RegisterResult>>, ) -> crate::Result<()>266         fn register(
267             &mut self,
268             _flags: crate::RegisterFlags,
269             _timeout: u64,
270             _challenge: Vec<u8>,
271             _application: crate::AppId,
272             _key_handles: Vec<crate::KeyHandle>,
273             _status: Sender<crate::StatusUpdate>,
274             callback: StateCallback<crate::Result<crate::RegisterResult>>,
275         ) -> crate::Result<()> {
276             if self.consent {
277                 let rv = Ok((vec![0u8; 16], self.dev_info()));
278                 thread::spawn(move || callback.call(rv));
279             }
280             Ok(())
281         }
282 
sign( &mut self, _flags: crate::SignFlags, _timeout: u64, _challenge: Vec<u8>, _app_ids: Vec<crate::AppId>, _key_handles: Vec<crate::KeyHandle>, _status: Sender<crate::StatusUpdate>, callback: StateCallback<crate::Result<crate::SignResult>>, ) -> crate::Result<()>283         fn sign(
284             &mut self,
285             _flags: crate::SignFlags,
286             _timeout: u64,
287             _challenge: Vec<u8>,
288             _app_ids: Vec<crate::AppId>,
289             _key_handles: Vec<crate::KeyHandle>,
290             _status: Sender<crate::StatusUpdate>,
291             callback: StateCallback<crate::Result<crate::SignResult>>,
292         ) -> crate::Result<()> {
293             if self.consent {
294                 let rv = Ok((vec![0u8; 0], vec![0u8; 0], vec![0u8; 0], self.dev_info()));
295                 thread::spawn(move || callback.call(rv));
296             }
297             Ok(())
298         }
299 
cancel(&mut self) -> crate::Result<()>300         fn cancel(&mut self) -> crate::Result<()> {
301             self.was_cancelled
302                 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
303                 .map_or(
304                     Err(crate::errors::AuthenticatorError::U2FToken(
305                         crate::errors::U2FTokenError::InvalidState,
306                     )),
307                     |_| Ok(()),
308                 )
309         }
310     }
311 
mk_key() -> KeyHandle312     fn mk_key() -> KeyHandle {
313         KeyHandle {
314             credential: vec![0],
315             transports: AuthenticatorTransports::USB,
316         }
317     }
318 
mk_challenge() -> Vec<u8>319     fn mk_challenge() -> Vec<u8> {
320         vec![0x11; PARAMETER_SIZE]
321     }
322 
mk_appid() -> Vec<u8>323     fn mk_appid() -> Vec<u8> {
324         vec![0x22; PARAMETER_SIZE]
325     }
326 
327     #[test]
test_no_challenge()328     fn test_no_challenge() {
329         init();
330         let (status_tx, _) = channel::<StatusUpdate>();
331 
332         let mut s = AuthenticatorService::new().unwrap();
333         s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));
334 
335         assert_matches!(
336             s.register(
337                 RegisterFlags::empty(),
338                 1_000,
339                 vec![],
340                 mk_appid(),
341                 vec![mk_key()],
342                 status_tx.clone(),
343                 StateCallback::new(Box::new(move |_rv| {})),
344             )
345             .unwrap_err(),
346             crate::errors::AuthenticatorError::InvalidRelyingPartyInput
347         );
348 
349         assert_matches!(
350             s.sign(
351                 SignFlags::empty(),
352                 1_000,
353                 vec![],
354                 vec![mk_appid()],
355                 vec![mk_key()],
356                 status_tx,
357                 StateCallback::new(Box::new(move |_rv| {})),
358             )
359             .unwrap_err(),
360             crate::errors::AuthenticatorError::InvalidRelyingPartyInput
361         );
362     }
363 
364     #[test]
test_no_appids()365     fn test_no_appids() {
366         init();
367         let (status_tx, _) = channel::<StatusUpdate>();
368 
369         let mut s = AuthenticatorService::new().unwrap();
370         s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));
371 
372         assert_matches!(
373             s.register(
374                 RegisterFlags::empty(),
375                 1_000,
376                 mk_challenge(),
377                 vec![],
378                 vec![mk_key()],
379                 status_tx.clone(),
380                 StateCallback::new(Box::new(move |_rv| {})),
381             )
382             .unwrap_err(),
383             crate::errors::AuthenticatorError::InvalidRelyingPartyInput
384         );
385 
386         assert_matches!(
387             s.sign(
388                 SignFlags::empty(),
389                 1_000,
390                 mk_challenge(),
391                 vec![],
392                 vec![mk_key()],
393                 status_tx,
394                 StateCallback::new(Box::new(move |_rv| {})),
395             )
396             .unwrap_err(),
397             crate::errors::AuthenticatorError::InvalidRelyingPartyInput
398         );
399     }
400 
401     #[test]
test_no_keys()402     fn test_no_keys() {
403         init();
404         // No Keys is a resident-key use case. For U2F this would time out,
405         // but the actual reactions are up to the service implementation.
406         // This test yields OKs.
407         let (status_tx, _) = channel::<StatusUpdate>();
408 
409         let mut s = AuthenticatorService::new().unwrap();
410         s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));
411 
412         assert_matches!(
413             s.register(
414                 RegisterFlags::empty(),
415                 100,
416                 mk_challenge(),
417                 mk_appid(),
418                 vec![],
419                 status_tx.clone(),
420                 StateCallback::new(Box::new(move |_rv| {})),
421             ),
422             Ok(())
423         );
424 
425         assert_matches!(
426             s.sign(
427                 SignFlags::empty(),
428                 100,
429                 mk_challenge(),
430                 vec![mk_appid()],
431                 vec![],
432                 status_tx,
433                 StateCallback::new(Box::new(move |_rv| {})),
434             ),
435             Ok(())
436         );
437     }
438 
439     #[test]
test_large_keys()440     fn test_large_keys() {
441         init();
442         let (status_tx, _) = channel::<StatusUpdate>();
443 
444         let large_key = KeyHandle {
445             credential: vec![0; 257],
446             transports: AuthenticatorTransports::USB,
447         };
448 
449         let mut s = AuthenticatorService::new().unwrap();
450         s.add_transport(Box::new(TestTransportDriver::new(true).unwrap()));
451 
452         assert_matches!(
453             s.register(
454                 RegisterFlags::empty(),
455                 1_000,
456                 mk_challenge(),
457                 mk_appid(),
458                 vec![large_key.clone()],
459                 status_tx.clone(),
460                 StateCallback::new(Box::new(move |_rv| {})),
461             )
462             .unwrap_err(),
463             crate::errors::AuthenticatorError::InvalidRelyingPartyInput
464         );
465 
466         assert_matches!(
467             s.sign(
468                 SignFlags::empty(),
469                 1_000,
470                 mk_challenge(),
471                 vec![mk_appid()],
472                 vec![large_key],
473                 status_tx,
474                 StateCallback::new(Box::new(move |_rv| {})),
475             )
476             .unwrap_err(),
477             crate::errors::AuthenticatorError::InvalidRelyingPartyInput
478         );
479     }
480 
481     #[test]
test_no_transports()482     fn test_no_transports() {
483         init();
484         let (status_tx, _) = channel::<StatusUpdate>();
485 
486         let mut s = AuthenticatorService::new().unwrap();
487         assert_matches!(
488             s.register(
489                 RegisterFlags::empty(),
490                 1_000,
491                 mk_challenge(),
492                 mk_appid(),
493                 vec![mk_key()],
494                 status_tx.clone(),
495                 StateCallback::new(Box::new(move |_rv| {})),
496             )
497             .unwrap_err(),
498             crate::errors::AuthenticatorError::NoConfiguredTransports
499         );
500 
501         assert_matches!(
502             s.sign(
503                 SignFlags::empty(),
504                 1_000,
505                 mk_challenge(),
506                 vec![mk_appid()],
507                 vec![mk_key()],
508                 status_tx,
509                 StateCallback::new(Box::new(move |_rv| {})),
510             )
511             .unwrap_err(),
512             crate::errors::AuthenticatorError::NoConfiguredTransports
513         );
514 
515         assert_matches!(
516             s.cancel().unwrap_err(),
517             crate::errors::AuthenticatorError::NoConfiguredTransports
518         );
519     }
520 
521     #[test]
test_cancellation_register()522     fn test_cancellation_register() {
523         init();
524         let (status_tx, _) = channel::<StatusUpdate>();
525 
526         let mut s = AuthenticatorService::new().unwrap();
527         let ttd_one = TestTransportDriver::new(true).unwrap();
528         let ttd_two = TestTransportDriver::new(false).unwrap();
529         let ttd_three = TestTransportDriver::new(false).unwrap();
530 
531         let was_cancelled_one = ttd_one.was_cancelled.clone();
532         let was_cancelled_two = ttd_two.was_cancelled.clone();
533         let was_cancelled_three = ttd_three.was_cancelled.clone();
534 
535         s.add_transport(Box::new(ttd_one));
536         s.add_transport(Box::new(ttd_two));
537         s.add_transport(Box::new(ttd_three));
538 
539         let callback = StateCallback::new(Box::new(move |_rv| {}));
540         assert!(s
541             .register(
542                 RegisterFlags::empty(),
543                 1_000,
544                 mk_challenge(),
545                 mk_appid(),
546                 vec![],
547                 status_tx,
548                 callback.clone(),
549             )
550             .is_ok());
551         callback.wait();
552 
553         assert_eq!(was_cancelled_one.load(Ordering::SeqCst), false);
554         assert_eq!(was_cancelled_two.load(Ordering::SeqCst), true);
555         assert_eq!(was_cancelled_three.load(Ordering::SeqCst), true);
556     }
557 
558     #[test]
test_cancellation_sign()559     fn test_cancellation_sign() {
560         init();
561         let (status_tx, _) = channel::<StatusUpdate>();
562 
563         let mut s = AuthenticatorService::new().unwrap();
564         let ttd_one = TestTransportDriver::new(true).unwrap();
565         let ttd_two = TestTransportDriver::new(false).unwrap();
566         let ttd_three = TestTransportDriver::new(false).unwrap();
567 
568         let was_cancelled_one = ttd_one.was_cancelled.clone();
569         let was_cancelled_two = ttd_two.was_cancelled.clone();
570         let was_cancelled_three = ttd_three.was_cancelled.clone();
571 
572         s.add_transport(Box::new(ttd_one));
573         s.add_transport(Box::new(ttd_two));
574         s.add_transport(Box::new(ttd_three));
575 
576         let callback = StateCallback::new(Box::new(move |_rv| {}));
577         assert!(s
578             .sign(
579                 SignFlags::empty(),
580                 1_000,
581                 mk_challenge(),
582                 vec![mk_appid()],
583                 vec![mk_key()],
584                 status_tx,
585                 callback.clone(),
586             )
587             .is_ok());
588         callback.wait();
589 
590         assert_eq!(was_cancelled_one.load(Ordering::SeqCst), false);
591         assert_eq!(was_cancelled_two.load(Ordering::SeqCst), true);
592         assert_eq!(was_cancelled_three.load(Ordering::SeqCst), true);
593     }
594 
595     #[test]
test_cancellation_race()596     fn test_cancellation_race() {
597         init();
598         let (status_tx, _) = channel::<StatusUpdate>();
599 
600         let mut s = AuthenticatorService::new().unwrap();
601         // Let both of these race which one provides consent.
602         let ttd_one = TestTransportDriver::new(true).unwrap();
603         let ttd_two = TestTransportDriver::new(true).unwrap();
604 
605         let was_cancelled_one = ttd_one.was_cancelled.clone();
606         let was_cancelled_two = ttd_two.was_cancelled.clone();
607 
608         s.add_transport(Box::new(ttd_one));
609         s.add_transport(Box::new(ttd_two));
610 
611         let callback = StateCallback::new(Box::new(move |_rv| {}));
612         assert!(s
613             .register(
614                 RegisterFlags::empty(),
615                 1_000,
616                 mk_challenge(),
617                 mk_appid(),
618                 vec![],
619                 status_tx,
620                 callback.clone(),
621             )
622             .is_ok());
623         callback.wait();
624 
625         let one = was_cancelled_one.load(Ordering::SeqCst);
626         let two = was_cancelled_two.load(Ordering::SeqCst);
627         assert_eq!(
628             one ^ two,
629             true,
630             "asserting that one={} xor two={} is true",
631             one,
632             two
633         );
634     }
635 }
636