Giter VIP home page Giter VIP logo

authenticator-rs's People

Contributors

alex avatar amccreight avatar clarkwang-2013 avatar crote avatar dm0- avatar eijebong avatar fmeum avatar froydnj avatar glandium avatar jbeich avatar jcjones avatar jrmuizel avatar jschanck avatar kvark avatar manishearth avatar mbrubeck avatar micolous avatar msirringhaus avatar qdot avatar reyk avatar rillian avatar rugk avatar ttaubert avatar upsuper avatar valpackett avatar vincentvanlaer avatar zjiaz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

authenticator-rs's Issues

Final buffers have an extra 0x00 appended

The u2f_register and u2f_sign operations' buffers have a 0x00 value appended to them. This is visible in the "main" example as AA values on the end of each string:

Asking a security key to register now...
Register result: BQS8jDTzbDfefi9WJ8Gc73K1jtA9gFYKb/qAdjh+FEnE85/aLrYFm4v9uQhHet8CafAxTm03aGXyVbmKUTU8iQMcQG3Tru3jaByKCrbUd2+VHAU7AYr4exe+Ju8tP5nJABAv9licn9xj01KrbPJ3kcAShXWWuTOVZEyvnE78qONzpVowggGqMIIBUaADAgECAgkA/lb+euH/GA4wCgYIKoZIzj0EAwIwMjEwMC4GA1UEAwwnUGx1Zy11cCBGSURPIEludGVybmFsIEF0dGVzdGF0aW9uIENBICMxMB4XDTE0MTAwMzA4MDY0OFoXDTM0MTAwMzA4MDY0OFowQDE+MDwGA1UEAww1UGx1Zy11cCBGSURPIFByb2R1Y3Rpb24gQXR0ZXN0YXRpb24gI2ZlNTZmZTdhZTFmZjE4MGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR16gZg4pBjdIQ3AACvqjIlPoJ72Eh0k6aGpWhMZcrOCYvov0uHJT3vlrlAIwEG/EYGH31lRsFvFLJavzAZ2PQno0IwQDAdBgNVHQ4EFgQUditEb/KU7TIq5CkJT6mE2IU+NYAwHwYDVR0jBBgwFoAUz6dE8qFiUPA56ZKF49pQ532wOqgwCgYIKoZIzj0EAwIDRwAwRAIga1/qf93OZYQ7Jdam/IpNtzuAseZELqsGd6k+Pbk1HyICIFlbgjJ5IcKPrSBiuSrqB8Q3pU1GpiyL5u77aVuKsUQWMEQCIDLFzD5ygx5Si2oi4RBWv/xEpXBNkLmlFxruVJ2yF0+vAiAYnlGuZ3xS87o3eafg2+2eHjV/WVUZ/PC5F7WntmZ/I5AA
Asking a security key to sign now, with the data from the register...
Sign result: AQAAABkwRgIhAK7Ib2SFxSDyY3vhcaKNxMJs6rUap6g/NnXrqip5GIemAiEAvJwdEAyD7DYUcvJDVOT+M7UCKs+tkYhKf8g0LBcexm2QAA==
Done.

These break the signature checks at Github and at https://demo.yubico.com/u2f

u2f_register must accept a list of already-registered key handles

Like u2f_sign, u2f_register needs to accept an exclusion list of key handles that it can attempt to use before proceeding.

This could be done by having u2f_register accept an array of byte arrays, or defining a function that checks a single key handle at once (is_registered) which can be called serially by the U2FManager.

Refactor U2FManager out of main.rs

U2FManager belongs somewhere other than main.rs.

Perhaps pull that into a state_machine.rs and, similarly, refactor lib.rs's u2f hid support stuff into u2fprotocol.rs

TSAN shows a data race in the unit tests

RUSTFLAGS="-Z sanitizer=thread" rustup run nightly cargo test

running 4 tests
test u2fprotocol::tests::test_init_device ... ok
test u2fprotocol::tests::test_ping_device ... ok
test u2fprotocol::tests::test_sendapdu ... ok
==================
WARNING: ThreadSanitizer: data race (pid=35046)
  Write of size 8 at 0x7e8000284070 by thread T4:
    #0 memmove <null>:65020504 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0xc206)
    #1 pthread_setname_np <null>:63970968 (libsystem_pthread.dylib:x86_64+0x421a)

  Previous write of size 8 at 0x7e8000284070 by thread T1:
    #0 memmove <null>:65020504 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0xc206)
    #1 pthread_setname_np <null>:63970968 (libsystem_pthread.dylib:x86_64+0x421a)

  Thread T4 (tid=5431922, running) created by main thread at:
    #0 pthread_create <null>:65020504 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x7121)
    #1 std::sys::imp::thread::Thread::new::hb0ee40c469bc0ac1 thread.rs:72 (u2fhid-67c8d56994e664bc:x86_64+0x10006d575)
    #2 __rust_maybe_catch_panic lib.rs:98 (u2fhid-67c8d56994e664bc:x86_64+0x10007176c)
    #3 start <null>:63965880 (libdyld.dylib:x86_64+0x5234)

  Thread T1 (tid=5431919, finished) created by main thread at:
    #0 pthread_create <null>:65020504 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x7121)
    #1 std::sys::imp::thread::Thread::new::hb0ee40c469bc0ac1 thread.rs:72 (u2fhid-67c8d56994e664bc:x86_64+0x10006d575)
    #2 __rust_maybe_catch_panic lib.rs:98 (u2fhid-67c8d56994e664bc:x86_64+0x10007176c)
    #3 start <null>:63965880 (libdyld.dylib:x86_64+0x5234)

SUMMARY: ThreadSanitizer: data race (libsystem_pthread.dylib:x86_64+0x421a) in pthread_setname_np
==================
test u2fprotocol::tests::test_sendrecv_multiple ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Upload to crates.io

It seems like this library could be useful to others and having it on crates.io will make it more discoverable.

Fix Clippy linting issues

These are the Clippy linting warnings:

warning: this argument is passed by value, but not consumed in the function body
  --> src/util.rs:48:33
   |
48 | pub fn to_io_err<T: Error>(err: T) -> io::Error {
   |                                 ^ help: consider taking a reference instead: `&T`
   |
   = note: #[warn(needless_pass_by_value)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_pass_by_value

warning: very complex type used. Consider factoring parts into `type` definitions
  --> src/util.rs:53:15
   |
53 |     callback: Arc<Mutex<Option<SendBoxFnOnce<(io::Result<T>,)>>>>,
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(type_complexity)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#type_complexity

warning: use `assert_eq` for better reporting
   --> src/macos/device.rs:107:9
    |
107 |         assert!(bytes.len() == HID_RPT_SIZE + 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[warn(should_assert_eq)] on by default
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#should_assert_eq
    = note: this error originates in a macro outside of the current crate

warning: explicit lifetimes given in parameter types where they could be elided
   --> src/macos/device.rs:139:5
    |
139 | /     fn get_cid<'a>(&'a self) -> &'a [u8; 4] {
140 | |         &self.cid
141 | |     }
    | |_____^
    |
    = note: #[warn(needless_lifetimes)] on by default
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: explicit lifetimes given in parameter types where they could be elided
  --> src/macos/monitor.rs:81:5
   |
81 | /     pub fn events<'a>(&'a self) -> TryIter<'a, Event> {
82 | |         self.rx.try_iter()
83 | |     }
   | |_____^
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: you should consider deriving a `Default` implementation for `platform::PlatformManager`
  --> src/macos/mod.rs:27:5
   |
27 | /     pub fn new() -> Self {
28 | |         Self { thread: None }
29 | |     }
   | |_____^
   |
   = note: #[warn(new_without_default_derive)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#new_without_default_derive
help: try this
   |
21 | #[derive(Default)]
   |

warning: redundant pattern matching, consider using `is_ok()`
   --> src/macos/mod.rs:135:40
    |
135 |                                 if let Ok(_) = u2f_register(device, &blank, &blank) {
    |                                 -------^^^^^--------------------------------------- help: try this: `if u2f_register(device, &blank, &blank).is_ok()`
    |
    = note: #[warn(if_let_redundant_pattern_matching)] on by default
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#if_let_redundant_pattern_matching

warning: explicit lifetimes given in parameter types where they could be elided
  --> src/u2ftypes.rs:18:5
   |
18 |     fn get_cid<'a>(&'a self) -> &'a [u8; 4];
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#needless_lifetimes

warning: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
   --> src/u2ftypes.rs:167:21
    |
167 |     pub fn to_bytes(ins: u8, p1: u8, data: &[u8]) -> io::Result<Vec<u8>> {
    |                     ^^^
    |
    = note: #[warn(wrong_self_convention)] on by default
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#wrong_self_convention

warning: redundant pattern matching, consider using `is_err()`
  --> src/u2fprotocol.rs:23:12
   |
23 |     if let Err(_) = init_device(dev, &nonce) {
   |     -------^^^^^^--------------------------- help: try this: `if init_device(dev, &nonce).is_err()`
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#if_let_redundant_pattern_matching

warning: redundant pattern matching, consider using `is_err()`
  --> src/u2fprotocol.rs:29:12
   |
29 |     if let Err(_) = ping_device(dev, &random) {
   |     -------^^^^^^---------------------------- help: try this: `if ping_device(dev, &random).is_err()`
   |
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#if_let_redundant_pattern_matching

warning: useless use of `vec!`
   --> src/u2fprotocol.rs:171:53
    |
171 |     let mut res = send_apdu(dev, U2F_VERSION, 0x00, &vec![])?;
    |                                                     ^^^^^^^ help: you can use a slice directly: `&[]`
    |
    = note: #[warn(useless_vec)] on by default
    = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#useless_vec

warning: long literal lacking separators
  --> examples/main.rs:52:19
   |
52 |         .register(15000, chall_bytes.clone(), app_bytes.clone(), move |rv| {
   |                   ^^^^^
   |
   = note: #[warn(unreadable_literal)] on by default
   = help: consider: 15_000
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unreadable_literal

warning: long literal lacking separators
  --> examples/main.rs:64:15
   |
64 |         .sign(15000, chall_bytes, app_bytes, vec![key_handle], move |rv| {
   |               ^^^^^
   |
   = help: consider: 15_000
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#unreadable_literal

warning: unused `#[macro_use]` import
  --> examples/main.rs:10:1
   |
10 | #[macro_use]
   | ^^^^^^^^^^^^
   |
   = note: #[warn(unused_imports)] on by default

warning: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices. Consider changing the type to `&[...]`
  --> examples/main.rs:14:65
   |
14 | fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>> {
   |                                                                 ^^^^^^^^
   |
   = note: #[warn(ptr_arg)] on by default
   = help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#ptr_arg

Use core-foundation crate

Currently u2fhid just uses core-foundation-sys directly. It seems like some of the unsafe wrappers around core-foundation-sys could be replaced with safe ones from core-foundation.

Implement an actual WorkQueue for the U2FManager

The first version of the U2FManager was added to provide the right API. Because PlatformManager::cancel() can block however, we need implement a work queue that spawns a thread and has register, sign, and cancel as work items. These corresponds to API calls from PBackground.

Fix test_init_device

The fix for #4 has caused the test for ping to fail:

---- tests::test_init_device stdout ----

	USB send: 00ffffffff860008be87e369afa2756200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

thread 'tests::test_init_device' panicked at 'assertion failed: `(left == right)` (left: `[0, 255, 255, 255, 255, 134, 0, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`, right: `[0, 255, 255, 255, 255, 134, 0, 8, 190, 135, 227, 105, 175, 162, 117, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`)', src/lib.rs:468

The current assertion that the in and out are identical needs to change; the test can just assert that everything is identical except the 8 nonce bytes by slicing around them.

Compile error on OSX with rand 0.6

Works fine with rand v0.5.5

   Compiling rand v0.6.4
error[E0425]: cannot find function `pthread_atfork` in module `libc`
   --> /Users/jcjones/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.6.4/src/rngs/adapter/reseeding.rs:320:28
    |
320 |             unsafe { libc::pthread_atfork(None, None, Some(fork_handler)) };
    |                            ^^^^^^^^^^^^^^ not found in `libc`

linux/hidraw.rs needs tests

Writing tests is really straightforward, we just need to do it. Could probably also add a fuzzing target.

update to winapi 0.3

I'm working on an aarch64 windows Firefox port, and the necessary modifications to winapi are more easily done on the 0.3.x development line rather than the 0.2.x versions. So it'd be great if this code was using 0.3, so when the aarch64 changes land, this code would automatically get upgraded.

KeyHandleMatcher might theoretically not handle re-used dev_refs correctly

From KeyHandleMatcher.update():

// TODO In theory, it might be possible to replace a token between
// `update()` calls while reusing the device_ref/path. We should refactor
// this part of the code and probably merge the KeyHandleMatcher into the
// DeviceMap and Monitor somehow so that we query key handle/token
// assignments right when we start tracking a new device.

I'd certainly favor coming up with a nicer structure for the KHM, DevMap, and Monitor that fits the runloop we have better, yet still maintains some separation of concern.

Respect REQUIRE_USER_VERIFICATION

The flag REQUIRE_USER_VERIFICATION can be passed in by callers, which cannot be satisfied by U2F devices. As such, REQUIRE_USER_VERIFICATION should not permit any U2F devices to complete the operation.

Additionally, REQUIRE_USER_VERIFICATION is mis-defined (but unused) as being both 1 and 2 in src/lib.rs, while it is only 2 in u2fhid-capi.h which will need fixing.

Return consistent custom error codes

We currently usually return io::Errors. We should have a nice list of error codes, maybe defined by the standard, that allow callers of the API to determine the cause of the error and provide better feedback in the JS console.

Yubikey ping packet corruption when device is inserted during polling

I've been using my yubikey in firefox for U2F (on windows) and have noticed it almost never works if I insert the USB device after the registration/sign sequence has begun. I have tried it directly with this library and it also gives problems there with the default example (main). If the key was inserted before starting it works fine, if I insert it after starting while it's polling, it sometimes works but most of the time it will fail.

I tracked the problem down to the ping function returning different bytes than the random bytes that were sent. In fact the sequence returned is pretty much always the same. I think it may be a hardware issue with the yubikey, not with your source code and was wondering if you've come across this issue? My yubikey is a few years old (U2F firmware is 1.1.0) so it might work with newer versions.

Using a USB capture I found out that when the ping request is sent, between the request packet and response packet there is a bunch of CCID/ISO7816 commands (note that my yubikey is in U2F+CCID mode), this is probably windows checking the smartcard type. The bytes that are returned in the ping response actually seem to come from parts of earlier CCID responses, so I suspect the yubikey's memory where the ping request is stored is corrupted by these intervening packets. When the registration is done some time after initialization it works because there is no other simultaneous communication.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.