Switch to using my libfido2 bindings
This commit is contained in:
parent
129e3187be
commit
ab6cf2ac8a
155
Cargo.lock
generated
155
Cargo.lock
generated
@ -362,6 +362,12 @@ version = "0.3.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -405,17 +411,6 @@ version = "0.1.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
|
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fido2-rs"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"foreign-types",
|
|
||||||
"libfido2-sys",
|
|
||||||
"openssl",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fido_ssh_maker"
|
name = "fido_ssh_maker"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -425,8 +420,8 @@ dependencies = [
|
|||||||
"clap",
|
"clap",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dialoguer",
|
"dialoguer",
|
||||||
"fido2-rs",
|
|
||||||
"gethostname",
|
"gethostname",
|
||||||
|
"libfido2",
|
||||||
"p256",
|
"p256",
|
||||||
"rand",
|
"rand",
|
||||||
"ssh-encoding",
|
"ssh-encoding",
|
||||||
@ -434,21 +429,6 @@ dependencies = [
|
|||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foreign-types"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
|
||||||
dependencies = [
|
|
||||||
"foreign-types-shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foreign-types-shared"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
@ -492,6 +472,12 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -513,6 +499,16 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inout"
|
name = "inout"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
@ -557,6 +553,16 @@ version = "0.2.147"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libfido2"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libfido2-sys",
|
||||||
|
"num_enum",
|
||||||
|
"paste",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfido2-sys"
|
name = "libfido2-sys"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -585,6 +591,12 @@ version = "0.4.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@ -646,48 +658,31 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "num_enum"
|
||||||
version = "1.18.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
checksum = "70bf6736f74634d299d00086f02986875b3c2d924781a6a2cb6c201e73da0ceb"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl"
|
|
||||||
version = "0.10.56"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"num_enum_derive",
|
||||||
"cfg-if",
|
|
||||||
"foreign-types",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"openssl-macros",
|
|
||||||
"openssl-sys",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-macros"
|
name = "num_enum_derive"
|
||||||
version = "0.1.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
checksum = "56ea360eafe1022f7cc56cd7b869ed57330fb2453d0c7831d99b74c65d2f5597"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "once_cell"
|
||||||
version = "0.9.91"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"pkg-config",
|
|
||||||
"vcpkg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "p256"
|
name = "p256"
|
||||||
@ -713,6 +708,12 @@ dependencies = [
|
|||||||
"sha2",
|
"sha2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pem-rfc7468"
|
name = "pem-rfc7468"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@ -770,6 +771,16 @@ dependencies = [
|
|||||||
"elliptic-curve",
|
"elliptic-curve",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.66"
|
version = "1.0.66"
|
||||||
@ -1036,24 +1047,41 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.44"
|
version = "1.0.47"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
|
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.44"
|
version = "1.0.47"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
@ -1302,6 +1330,15 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.5.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -11,8 +11,8 @@ bitflags = "2.4.0"
|
|||||||
clap = { version = "4.3.21", features = ["derive"] }
|
clap = { version = "4.3.21", features = ["derive"] }
|
||||||
ctrlc = "3.4.0"
|
ctrlc = "3.4.0"
|
||||||
dialoguer = "0.10.4"
|
dialoguer = "0.10.4"
|
||||||
fido2-rs = { version = "0.1.0", path = "fido-rs/fido2-rs" }
|
|
||||||
gethostname = "0.4.3"
|
gethostname = "0.4.3"
|
||||||
|
libfido2 = { version = "0.1.0", path = "../libfido2" }
|
||||||
p256 = "0.13.2"
|
p256 = "0.13.2"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
ssh-encoding = { version = "0.2.0" }
|
ssh-encoding = { version = "0.2.0" }
|
||||||
|
3
fido-rs/.gitignore
vendored
3
fido-rs/.gitignore
vendored
@ -1,3 +0,0 @@
|
|||||||
.idea
|
|
||||||
target/
|
|
||||||
Cargo.lock
|
|
@ -1,2 +0,0 @@
|
|||||||
[workspace]
|
|
||||||
members = ["libfido2-sys", "fido2-rs"]
|
|
@ -1,36 +0,0 @@
|
|||||||
# fido-rs
|
|
||||||
|
|
||||||
[libfido2](https://github.com/Yubico/libfido2) bindings for the Rust programming language.
|
|
||||||
|
|
||||||
# Example
|
|
||||||
|
|
||||||
1. Make a credential
|
|
||||||
```rust
|
|
||||||
use fido2_rs::device::Device;
|
|
||||||
use fido2_rs::credentials::Credential;
|
|
||||||
use fido2_rs::credentials::CoseType;
|
|
||||||
use anyhow::Result;
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
let dev = Device::open("windows://hello").expect("unable open windows hello");
|
|
||||||
|
|
||||||
let mut cred = Credential::new();
|
|
||||||
cred.set_client_data(&[1, 2, 3, 4, 5, 6])?;
|
|
||||||
cred.set_rp("fido_rs", "fido example")?;
|
|
||||||
cred.set_user(&[1, 2, 3, 4, 5, 6], "alice", Some("alice"), None)?;
|
|
||||||
cred.set_cose_type(CoseType::RS256)?;
|
|
||||||
|
|
||||||
let _ = dev.make_credential(&mut cred, None)?;
|
|
||||||
dbg!(cred.id());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# Support platform
|
|
||||||
* Windows (MSVC and MinGW)
|
|
||||||
* Linux
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
* [ ] more doc
|
|
||||||
* [x] full bindings to `fido_cred_t` and `fido_assert_t`
|
|
@ -1,20 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "fido2-rs"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["tyan boot <tyanboot@outlook.com>"]
|
|
||||||
license = "MIT"
|
|
||||||
description = "Rust bindings to Yubico fido2"
|
|
||||||
repository = "https://github.com/tyan-boot/fido-rs"
|
|
||||||
keywords = ["fido2", "webauthn"]
|
|
||||||
categories = ["authentication", "api-bindings", "hardware-support"]
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
thiserror = "1.0.37"
|
|
||||||
bitflags = "1.3.2"
|
|
||||||
libfido2-sys = { version = "0.2.0", path = "../libfido2-sys" }
|
|
||||||
openssl = "0.10.45"
|
|
||||||
foreign-types = "0.3"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
anyhow = "1.0.66"
|
|
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 tyan boot
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,30 +0,0 @@
|
|||||||
# fido2-rs
|
|
||||||
|
|
||||||
[![crates.io](https://img.shields.io/crates/v/fido2-rs?style=flat-square)](https://crates.io/crates/fido2-rs)
|
|
||||||
[![MIT](https://img.shields.io/crates/l/libfido2-sys?style=flat-square)](./LICENSE)
|
|
||||||
|
|
||||||
[libfido2](https://github.com/Yubico/libfido2) bindings for the Rust programming language.
|
|
||||||
|
|
||||||
For more details, see [tyan-boot/fido-rs](https://github.com/tyan-boot/fido-rs)
|
|
||||||
|
|
||||||
```rust
|
|
||||||
use fido2_rs::device::Device;
|
|
||||||
use fido2_rs::credentials::Credential;
|
|
||||||
use fido2_rs::credentials::CoseType;
|
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
let dev = Device::open("windows://hello").expect("unable open windows hello");
|
|
||||||
|
|
||||||
let mut cred = Credential::new();
|
|
||||||
cred.set_client_data(&[1, 2, 3, 4, 5, 6])?;
|
|
||||||
cred.set_rp("fido_rs", "fido example")?;
|
|
||||||
cred.set_user(&[1, 2, 3, 4, 5, 6], "alice", Some("alice"), None)?;
|
|
||||||
cred.set_cose_type(CoseType::RS256)?;
|
|
||||||
|
|
||||||
let _ = dev.make_credential(&mut cred, None)?;
|
|
||||||
dbg!(cred.id());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,465 +0,0 @@
|
|||||||
use crate::credentials::{CoseType, Opt};
|
|
||||||
use crate::error::{FidoError, Result};
|
|
||||||
use crate::key::{Eddsa, Rsa, ES256, ES384};
|
|
||||||
use crate::utils::check;
|
|
||||||
use ffi::FIDO_ERR_INVALID_ARGUMENT;
|
|
||||||
use openssl::nid::Nid;
|
|
||||||
use openssl::pkey::{Id, PKey, Public};
|
|
||||||
use std::ffi::CString;
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
macro_rules! impl_assertion_set {
|
|
||||||
($ty:ty, $($f:tt).*) => {
|
|
||||||
impl $ty {
|
|
||||||
/// Set the client data hash of assert by specifying the assertion's unhashed client data.
|
|
||||||
///
|
|
||||||
/// This is required by Windows Hello, which calculates the client data hash internally.
|
|
||||||
///
|
|
||||||
/// For compatibility with Windows Hello, applications should use [AssertRequestBuilder::client_data]
|
|
||||||
/// instead of [AssertRequestBuilder::client_data_hash].
|
|
||||||
pub fn set_client_data(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_clientdata(
|
|
||||||
self.$($f).*.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [AssertRequestBuilder::client_data]
|
|
||||||
pub fn set_client_data_hash(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_clientdata_hash(
|
|
||||||
self.$($f).*.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the relying party id of assert.
|
|
||||||
pub fn set_rp(&mut self, id: impl AsRef<str>) -> Result<()> {
|
|
||||||
let id = CString::new(id.as_ref())?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_rp(self.$($f).*.as_ptr(), id.as_ptr()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the up (user presence) attribute of assert.
|
|
||||||
///
|
|
||||||
/// **Default to [Opt::Omit]**
|
|
||||||
pub fn set_up(&mut self, up: Opt) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_up(self.$($f).*.as_ptr(), up as _))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the uv (user verification) attribute of assert.
|
|
||||||
///
|
|
||||||
/// **Default to [Opt::Omit]**
|
|
||||||
pub fn set_uv(&mut self, uv: Opt) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_uv(self.$($f).*.as_ptr(), uv as _))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the extensions of assert to the bitmask flags.
|
|
||||||
///
|
|
||||||
/// At the moment, only the FIDO_EXT_CRED_BLOB, FIDO_EXT_HMAC_SECRET, and FIDO_EXT_LARGEBLOB_KEY extensions are supported.
|
|
||||||
pub fn set_extensions(&mut self, flags: crate::credentials::Extensions) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_extensions(
|
|
||||||
self.$($f).*.as_ptr(),
|
|
||||||
flags.bits(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allow a credential in a FIDO2 assertion.
|
|
||||||
///
|
|
||||||
/// Add id to the list of credentials allowed in assert.
|
|
||||||
///
|
|
||||||
/// If fails, the existing list of allowed credentials is preserved.
|
|
||||||
pub fn set_allow_credential(&mut self, id: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let id = id.as_ref();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_allow_cred(
|
|
||||||
self.$($f).*.as_ptr(),
|
|
||||||
id.as_ptr(),
|
|
||||||
id.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// FIDO assertions from device, contains one or more assertion.
|
|
||||||
pub struct Assertions {
|
|
||||||
pub(crate) ptr: NonNull<ffi::fido_assert_t>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A single FIDO assertion.
|
|
||||||
pub struct Assertion<'a> {
|
|
||||||
ptr: NonNull<ffi::fido_assert_t>,
|
|
||||||
idx: usize,
|
|
||||||
_p: PhantomData<&'a ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Request to get a assertion.
|
|
||||||
pub struct AssertRequest(pub(crate) Assertions);
|
|
||||||
|
|
||||||
impl_assertion_set!(AssertRequest, 0.ptr);
|
|
||||||
|
|
||||||
impl AssertRequest {
|
|
||||||
/// Return a [AssertRequest]
|
|
||||||
#[allow(clippy::new_without_default)]
|
|
||||||
pub fn new() -> AssertRequest {
|
|
||||||
unsafe {
|
|
||||||
let assert = ffi::fido_assert_new();
|
|
||||||
|
|
||||||
AssertRequest(Assertions {
|
|
||||||
ptr: NonNull::new_unchecked(assert),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// helper for verify an exist single assertion
|
|
||||||
pub struct AssertVerifier(Assertions);
|
|
||||||
|
|
||||||
impl_assertion_set!(AssertVerifier, 0.ptr);
|
|
||||||
|
|
||||||
impl AssertVerifier {
|
|
||||||
/// Return a [AssertVerifier] for verify.
|
|
||||||
#[allow(clippy::new_without_default)]
|
|
||||||
pub fn new() -> AssertVerifier {
|
|
||||||
unsafe {
|
|
||||||
let assert = ffi::fido_assert_new();
|
|
||||||
ffi::fido_assert_set_count(assert, 1);
|
|
||||||
|
|
||||||
AssertVerifier(Assertions {
|
|
||||||
ptr: NonNull::new_unchecked(assert),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the authenticator data part of the statement.
|
|
||||||
///
|
|
||||||
/// A copy of data is made, and no references to the passed data are kept.
|
|
||||||
///
|
|
||||||
/// The authenticator data passed to [AssertVerifier::set_auth_data] must be a CBOR-encoded byte string,
|
|
||||||
/// as obtained from [Assertion::auth_data].
|
|
||||||
///
|
|
||||||
/// Alternatively, a raw binary blob may be passed to [AssertVerifier::set_auth_data_raw]
|
|
||||||
pub fn set_auth_data(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_authdata(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the raw binary authenticator data part of the statement.
|
|
||||||
pub fn set_auth_data_raw(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_authdata_raw(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the signature part of the statement.
|
|
||||||
pub fn set_signature(&mut self, signature: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let signature = signature.as_ref();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_set_sig(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
signature.as_ptr(),
|
|
||||||
signature.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verify whether the signature contained in statement of assert matches the parameters of the assertion.
|
|
||||||
///
|
|
||||||
/// And verify whether the client data hash, relying party ID, user presence and user verification
|
|
||||||
/// attributes of assert have been attested by the holder of the private counterpart of the public key.
|
|
||||||
///
|
|
||||||
/// The `public_key` is a public key of type COSE_ES256, COSE_ES384, COSE_RS256, or COSE_EDDSA.
|
|
||||||
///
|
|
||||||
/// # Return
|
|
||||||
/// On verify success, this method return Ok(()), otherwise return Err.
|
|
||||||
pub fn verify(&self, public_key: PKey<Public>) -> Result<()> {
|
|
||||||
match public_key.id() {
|
|
||||||
Id::ED25519 => {
|
|
||||||
let pk = Eddsa::try_from(public_key)?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_verify(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
CoseType::EDDSA as i32,
|
|
||||||
pk.as_ptr().cast(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Id::RSA => {
|
|
||||||
let pk = Rsa::try_from(public_key)?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_verify(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
CoseType::EDDSA as i32,
|
|
||||||
pk.as_ptr().cast(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Id::EC => {
|
|
||||||
let ec_key = public_key.ec_key()?;
|
|
||||||
let group = ec_key.group();
|
|
||||||
let curve = group
|
|
||||||
.curve_name()
|
|
||||||
.ok_or(FidoError::new(FIDO_ERR_INVALID_ARGUMENT))?;
|
|
||||||
match curve {
|
|
||||||
Nid::X9_62_PRIME256V1 => {
|
|
||||||
let pk = ES256::try_from(ec_key)?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_verify(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
CoseType::ES256 as i32,
|
|
||||||
pk.as_ptr().cast(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Nid::SECP384R1 => {
|
|
||||||
let pk = ES384::try_from(ec_key)?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_assert_verify(
|
|
||||||
self.0.ptr.as_ptr(),
|
|
||||||
0,
|
|
||||||
CoseType::ES384 as i32,
|
|
||||||
pk.as_ptr().cast(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(FidoError::new(FIDO_ERR_INVALID_ARGUMENT))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(FidoError::new(FIDO_ERR_INVALID_ARGUMENT))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Assertions {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let mut ptr = self.ptr.as_ptr();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ffi::fido_assert_free(&mut ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = std::mem::replace(&mut self.ptr, NonNull::dangling());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Assertion<'_> {
|
|
||||||
/// Return relying party ID of assert.
|
|
||||||
pub fn rp_id(&self) -> Option<&str> {
|
|
||||||
let rp_id = unsafe { ffi::fido_assert_rp_id(self.ptr.as_ptr()) };
|
|
||||||
str_or_none!(rp_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user display name of assert.
|
|
||||||
pub fn user_display_name(&self) -> Option<&str> {
|
|
||||||
let display_name =
|
|
||||||
unsafe { ffi::fido_assert_user_display_name(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
str_or_none!(display_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user icon of assert.
|
|
||||||
pub fn user_icon(&self) -> Option<&str> {
|
|
||||||
let icon = unsafe { ffi::fido_assert_user_icon(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
str_or_none!(icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user name of assert.
|
|
||||||
pub fn user_name(&self) -> Option<&str> {
|
|
||||||
let name = unsafe { ffi::fido_assert_user_name(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
str_or_none!(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return CBOR-encoded authenticator data
|
|
||||||
pub fn auth_data(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_authdata_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_authdata_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return client data hash.
|
|
||||||
pub fn client_data_hash(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_clientdata_hash_len(self.ptr.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_clientdata_hash_ptr(self.ptr.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the credBlob attribute.
|
|
||||||
pub fn blob(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_blob_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_blob_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the hmac-secret attribute.
|
|
||||||
///
|
|
||||||
/// The HMAC Secret Extension (hmac-secret) is a CTAP 2.0 extension.
|
|
||||||
///
|
|
||||||
/// Note that the resulting hmac-secret varies according to whether user verification was performed by the authenticator.
|
|
||||||
pub fn hmac_secret(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_hmac_secret_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_hmac_secret_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return largeBlobKey attribute.
|
|
||||||
pub fn large_blob_key(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_largeblob_key_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_largeblob_key_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user ID.
|
|
||||||
pub fn user_id(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_user_id_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_user_id_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return signature
|
|
||||||
pub fn signature(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_sig_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_sig_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return credential ID
|
|
||||||
pub fn id(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_assert_id_len(self.ptr.as_ptr(), self.idx) };
|
|
||||||
let ptr = unsafe { ffi::fido_assert_id_ptr(self.ptr.as_ptr(), self.idx) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return signature count.
|
|
||||||
pub fn counter(&self) -> u32 {
|
|
||||||
unsafe { ffi::fido_assert_sigcount(self.ptr.as_ptr(), self.idx) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return authenticator data flags.
|
|
||||||
pub fn flags(&self) -> u8 {
|
|
||||||
unsafe { ffi::fido_assert_flags(self.ptr.as_ptr(), self.idx) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Assertions {
|
|
||||||
/// Return the number of assertion.
|
|
||||||
pub fn count(&self) -> usize {
|
|
||||||
unsafe { ffi::fido_assert_count(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a iterator of contained assertion
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = Assertion> {
|
|
||||||
let count = self.count();
|
|
||||||
|
|
||||||
AssertionIter {
|
|
||||||
asserts: self,
|
|
||||||
idx: 0,
|
|
||||||
count,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterator of assertion
|
|
||||||
pub struct AssertionIter<'a> {
|
|
||||||
asserts: &'a Assertions,
|
|
||||||
idx: usize,
|
|
||||||
count: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for AssertionIter<'a> {
|
|
||||||
type Item = Assertion<'a>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.idx >= self.count {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let item = Assertion {
|
|
||||||
ptr: self.asserts.ptr,
|
|
||||||
idx: self.idx,
|
|
||||||
_p: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.idx += 1;
|
|
||||||
|
|
||||||
Some(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,195 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::ffi::CStr;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
pub struct CBORInfo {
|
|
||||||
pub(crate) ptr: NonNull<ffi::fido_cbor_info_t>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CBORInfo {
|
|
||||||
pub(crate) fn new() -> CBORInfo {
|
|
||||||
unsafe {
|
|
||||||
CBORInfo {
|
|
||||||
ptr: NonNull::new_unchecked(ffi::fido_cbor_info_new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn aaguid(&self) -> &[u8] {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_aaguid_len(self.ptr.as_ptr());
|
|
||||||
let ptr = ffi::fido_cbor_info_aaguid_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
std::slice::from_raw_parts(ptr, len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn extensions(&self) -> Vec<&str> {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_extensions_len(self.ptr.as_ptr());
|
|
||||||
let ptr = ffi::fido_cbor_info_extensions_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let exts = std::slice::from_raw_parts(ptr, len);
|
|
||||||
|
|
||||||
exts.iter()
|
|
||||||
.map(|it| CStr::from_ptr(*it))
|
|
||||||
.map(|it| it.to_str().expect("invalid utf8"))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn protocols(&self) -> &[u8] {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_protocols_len(self.ptr.as_ptr());
|
|
||||||
let ptr = ffi::fido_cbor_info_protocols_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
std::slice::from_raw_parts(ptr, len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transports(&self) -> Vec<&str> {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_transports_len(self.ptr.as_ptr());
|
|
||||||
let ptr = ffi::fido_cbor_info_transports_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let txs = std::slice::from_raw_parts(ptr, len);
|
|
||||||
|
|
||||||
txs.iter()
|
|
||||||
.map(|it| CStr::from_ptr(*it))
|
|
||||||
.map(|it| it.to_str().expect("invalid utf8"))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn versions(&self) -> Vec<&str> {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_versions_len(self.ptr.as_ptr());
|
|
||||||
let ptr = ffi::fido_cbor_info_versions_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let versions = std::slice::from_raw_parts(ptr, len);
|
|
||||||
|
|
||||||
versions
|
|
||||||
.iter()
|
|
||||||
.map(|it| CStr::from_ptr(*it))
|
|
||||||
.map(|it| it.to_str().expect("invalid utf8"))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn options(&self) -> HashMap<&str, bool> {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_options_len(self.ptr.as_ptr());
|
|
||||||
let names = ffi::fido_cbor_info_options_name_ptr(self.ptr.as_ptr());
|
|
||||||
let values = ffi::fido_cbor_info_options_value_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let names = std::slice::from_raw_parts(names, len);
|
|
||||||
let values = std::slice::from_raw_parts(values, len);
|
|
||||||
|
|
||||||
names
|
|
||||||
.iter()
|
|
||||||
.map(|it| CStr::from_ptr(*it))
|
|
||||||
.map(|it| it.to_str().expect("invalid utf8"))
|
|
||||||
.zip(values)
|
|
||||||
.map(|(k, v)| (k, *v))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn algorithms(&self) -> Vec<(&str, i32)> {
|
|
||||||
unsafe {
|
|
||||||
let count = ffi::fido_cbor_info_algorithm_count(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let mut rets = Vec::with_capacity(count);
|
|
||||||
|
|
||||||
for idx in 0..count {
|
|
||||||
let algo_type = ffi::fido_cbor_info_algorithm_type(self.ptr.as_ptr(), idx);
|
|
||||||
let algo_cose = ffi::fido_cbor_info_algorithm_cose(self.ptr.as_ptr(), idx);
|
|
||||||
|
|
||||||
let algo_type = CStr::from_ptr(algo_type).to_str().expect("invalid utf8");
|
|
||||||
|
|
||||||
rets.push((algo_type, algo_cose))
|
|
||||||
}
|
|
||||||
|
|
||||||
rets
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn certs(&self) -> HashMap<&str, u64> {
|
|
||||||
unsafe {
|
|
||||||
let len = ffi::fido_cbor_info_certs_len(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let names = ffi::fido_cbor_info_certs_name_ptr(self.ptr.as_ptr());
|
|
||||||
let values = ffi::fido_cbor_info_certs_value_ptr(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
let names = std::slice::from_raw_parts(names, len);
|
|
||||||
let values = std::slice::from_raw_parts(values, len);
|
|
||||||
|
|
||||||
names
|
|
||||||
.iter()
|
|
||||||
.map(|it| CStr::from_ptr(*it))
|
|
||||||
.map(|it| it.to_str().expect("invalid utf8"))
|
|
||||||
.zip(values)
|
|
||||||
.map(|(k, v)| (k, *v))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_msg_size(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_maxmsgsiz(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_cred_blob_len(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_maxcredbloblen(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_cred_count_list(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_maxcredcntlst(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_cred_id_len(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_maxcredidlen(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_large_blob(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_maxlargeblob(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_rp_id_minpinlen(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_maxrpid_minpinlen(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn min_pin_len(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_minpinlen(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fw_version(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_fwversion(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uv_attempts(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_uv_attempts(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uv_modality(&self) -> u64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_uv_modality(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rk_remaining(&self) -> i64 {
|
|
||||||
unsafe { ffi::fido_cbor_info_rk_remaining(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_pin_required(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_cbor_info_new_pin_required(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for CBORInfo {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
let mut ptr = self.ptr.as_ptr();
|
|
||||||
ffi::fido_cbor_info_free(&mut ptr);
|
|
||||||
|
|
||||||
let _ = std::mem::replace(&mut self.ptr, NonNull::dangling());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,578 +0,0 @@
|
|||||||
use crate::error::Result;
|
|
||||||
use crate::utils::check;
|
|
||||||
use bitflags::bitflags;
|
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
/// FIDO credential
|
|
||||||
pub struct Credential(pub(crate) NonNull<ffi::fido_cred_t>);
|
|
||||||
|
|
||||||
impl Drop for Credential {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
// `fido_cred_free` set this ptr to `NULL`
|
|
||||||
ffi::fido_cred_free(&mut self.0.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Credential {
|
|
||||||
/// Create a new credential
|
|
||||||
#[allow(clippy::new_without_default)]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
unsafe {
|
|
||||||
let cred = ffi::fido_cred_new();
|
|
||||||
|
|
||||||
Credential(NonNull::new_unchecked(cred))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// If the CTAP 2.1 FIDO_EXT_MINPINLEN extension is enabled on cred, then this function returns
|
|
||||||
/// the minimum PIN length of cred.
|
|
||||||
///
|
|
||||||
/// Otherwise, returns zero.
|
|
||||||
pub fn pin_min_len(&self) -> usize {
|
|
||||||
unsafe { ffi::fido_cred_pin_minlen(self.0.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If the CTAP 2.1 FIDO_EXT_CRED_PROTECT extension is enabled on cred, then this function returns
|
|
||||||
/// the protection of cred.
|
|
||||||
///
|
|
||||||
/// Otherwise, returns [None]
|
|
||||||
pub fn protection(&self) -> Option<Protection> {
|
|
||||||
unsafe {
|
|
||||||
let prot = ffi::fido_cred_prot(self.0.as_ptr());
|
|
||||||
|
|
||||||
match prot {
|
|
||||||
ffi::FIDO_CRED_PROT_UV_OPTIONAL => Some(Protection::UvOptional),
|
|
||||||
ffi::FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID => Some(Protection::UvOptionalWithId),
|
|
||||||
ffi::FIDO_CRED_PROT_UV_REQUIRED => Some(Protection::UvRequired),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the attestation statement format identifier of cred, or [None] if cred does not have a format set.
|
|
||||||
pub fn attestation_format(&self) -> Option<AttestationFormat> {
|
|
||||||
let fmt = unsafe { ffi::fido_cred_fmt(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
if fmt.is_null() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let fmt = unsafe { CStr::from_ptr(fmt).to_str().expect("invalid utf8") };
|
|
||||||
|
|
||||||
match fmt {
|
|
||||||
"packed" => Some(AttestationFormat::Packed),
|
|
||||||
"fido-u2f" => Some(AttestationFormat::FidoU2f),
|
|
||||||
"tpm" => Some(AttestationFormat::Tpm),
|
|
||||||
"none" => Some(AttestationFormat::None),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return relying party ID, or [None] if is not set.
|
|
||||||
pub fn rp_id(&self) -> Option<&str> {
|
|
||||||
let rp_id = unsafe { ffi::fido_cred_rp_id(self.0.as_ptr()) };
|
|
||||||
str_or_none!(rp_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return relying party name, or [None] if is not set.
|
|
||||||
pub fn rp_name(&self) -> Option<&str> {
|
|
||||||
let rp_name = unsafe { ffi::fido_cred_rp_name(self.0.as_ptr()) };
|
|
||||||
str_or_none!(rp_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user name, or [None] if is not set.
|
|
||||||
pub fn user_name(&self) -> Option<&str> {
|
|
||||||
let user_name = unsafe { ffi::fido_cred_rp_id(self.0.as_ptr()) };
|
|
||||||
str_or_none!(user_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user display name, or [None] if is not set.
|
|
||||||
pub fn display_name(&self) -> Option<&str> {
|
|
||||||
let display_name = unsafe { ffi::fido_cred_rp_id(self.0.as_ptr()) };
|
|
||||||
str_or_none!(display_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return CBOR-encoded authenticator data.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn auth_data(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_authdata_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_authdata_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return raw authenticator data.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn auth_data_raw(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_authdata_raw_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_authdata_raw_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return client data hash
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn client_data_hash(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_clientdata_hash_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_clientdata_hash_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return credential ID
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn id(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_id_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_id_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return authenticator attestation GUID
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn attestation_guid(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_aaguid_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_aaguid_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return "largeBlobKey".
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn large_blob_key(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_largeblob_key_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_largeblob_key_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return public key.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn public_key(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_pubkey_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_pubkey_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return signature.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn signature(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_sig_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_sig_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return user ID.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn user_id(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_user_id_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_user_id_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return X509 certificate.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn certificate(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_x5c_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_x5c_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return attestation statement.
|
|
||||||
///
|
|
||||||
/// The slice len will be 0 if is not set.
|
|
||||||
pub fn attestation(&self) -> &[u8] {
|
|
||||||
let len = unsafe { ffi::fido_cred_attstmt_len(self.0.as_ptr()) };
|
|
||||||
let ptr = unsafe { ffi::fido_cred_attstmt_ptr(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
unsafe { std::slice::from_raw_parts(ptr, len) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the COSE algorithm of cred.
|
|
||||||
pub fn cose_type(&self) -> CoseType {
|
|
||||||
unsafe {
|
|
||||||
let cred_type = ffi::fido_cred_type(self.0.as_ptr());
|
|
||||||
|
|
||||||
CoseType::try_from(cred_type).unwrap_or(CoseType::UNSPEC)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the authenticator data flags of cred.
|
|
||||||
pub fn flags(&self) -> u8 {
|
|
||||||
unsafe { ffi::fido_cred_flags(self.0.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the authenticator data signature counter of cred.
|
|
||||||
pub fn counter(&self) -> u32 {
|
|
||||||
unsafe { ffi::fido_cred_sigcount(self.0.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Verifies whether the client data hash, relying party ID, credential ID, type, protection policy,
|
|
||||||
/// minimum PIN length, and resident/discoverable key and user verification attributes of cred
|
|
||||||
/// have been attested by the holder of the private counterpart of the public key contained in the credential's x509 certificate.
|
|
||||||
///
|
|
||||||
/// Please note that the x509 certificate itself is not verified.
|
|
||||||
///
|
|
||||||
/// The attestation statement formats supported by [Credential::verify] are packed, fido-u2f, and tpm.
|
|
||||||
///
|
|
||||||
/// The attestation type implemented by [Credential::verify] is Basic Attestation.
|
|
||||||
pub fn verify(&self) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_verify(self.0.as_ptr()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// verifies whether the client data hash, relying party ID, credential ID, type, protection policy,
|
|
||||||
/// minimum PIN length, and resident/discoverable key and user verification attributes of cred
|
|
||||||
/// have been attested by the holder of the credential's private key.
|
|
||||||
///
|
|
||||||
/// The attestation statement formats supported by [Credential::verify_self] are packed and fido-u2f.
|
|
||||||
///
|
|
||||||
/// The attestation type implemented by [Credential::verify_self] is Self Attestation.
|
|
||||||
pub fn verify_self(&self) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_verify_self(self.0.as_ptr()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set CBOR-encoded authenticator data
|
|
||||||
pub fn set_auth_data(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
dbg!(data.as_ref().len());
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_authdata(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set raw authenticator data
|
|
||||||
pub fn set_auth_data_raw(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_authdata_raw(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set X509 certificate
|
|
||||||
pub fn set_certificate(&mut self, cert: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let cert = cert.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_x509(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
cert.as_ptr(),
|
|
||||||
cert.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the client data hash of cred by specifying the credential's unhashed client data.
|
|
||||||
///
|
|
||||||
/// This is required by Windows Hello, which calculates the client data hash internally.
|
|
||||||
///
|
|
||||||
/// For compatibility with Windows Hello, applications should use [CredentialRequestBuilder::client_data] instead of [CredentialRequestBuilder::client_data_hash]
|
|
||||||
pub fn set_client_data(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_clientdata(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [CredentialRequestBuilder::client_data]
|
|
||||||
pub fn set_client_data_hash(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_clientdata_hash(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set credential ID
|
|
||||||
pub fn set_id(&mut self, id: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let id = id.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_id(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
id.as_ptr(),
|
|
||||||
id.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the relying party id and name parameters of cred
|
|
||||||
pub fn set_rp(&mut self, id: impl AsRef<str>, name: impl AsRef<str>) -> Result<()> {
|
|
||||||
let id = CString::new(id.as_ref())?;
|
|
||||||
let name = CString::new(name.as_ref())?;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_rp(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
id.as_ptr(),
|
|
||||||
name.as_ptr(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See [CredentialRequestBuilder::client_data]
|
|
||||||
pub fn set_signature(&mut self, sig: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let sig = sig.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_sig(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
sig.as_ptr(),
|
|
||||||
sig.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the user attributes of cred.
|
|
||||||
///
|
|
||||||
/// Previously set user attributes are flushed
|
|
||||||
pub fn set_user(
|
|
||||||
&mut self,
|
|
||||||
id: impl AsRef<[u8]>,
|
|
||||||
name: impl AsRef<str>,
|
|
||||||
display_name: Option<&str>,
|
|
||||||
icon: Option<&str>,
|
|
||||||
) -> Result<()> {
|
|
||||||
let id = id.as_ref();
|
|
||||||
let name = CString::new(name.as_ref())?;
|
|
||||||
let display_name = display_name.map(CString::new).transpose()?;
|
|
||||||
let icon = icon.map(CString::new).transpose()?;
|
|
||||||
|
|
||||||
let display_name_ptr = match &display_name {
|
|
||||||
Some(it) => it.as_ptr(),
|
|
||||||
None => std::ptr::null(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let icon_ptr = match &icon {
|
|
||||||
Some(it) => it.as_ptr(),
|
|
||||||
None => std::ptr::null(),
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_user(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
id.as_ptr(),
|
|
||||||
id.len(),
|
|
||||||
name.as_ptr(),
|
|
||||||
display_name_ptr,
|
|
||||||
icon_ptr,
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the extensions of cred to the bitmask flags.
|
|
||||||
///
|
|
||||||
/// Only the FIDO_EXT_CRED_BLOB, FIDO_EXT_CRED_PROTECT, FIDO_EXT_HMAC_SECRET,
|
|
||||||
/// FIDO_EXT_MINPINLEN, and FIDO_EXT_LARGEBLOB_KEY extensions are supported.
|
|
||||||
///
|
|
||||||
/// See [Extensions]
|
|
||||||
pub fn set_extension(&mut self, flags: Extensions) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_extensions(self.0.as_ptr(), flags.bits))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the “credBlob” to be stored with cred.
|
|
||||||
pub fn set_blob(&mut self, data: impl AsRef<[u8]>) -> Result<()> {
|
|
||||||
let data = data.as_ref();
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_blob(
|
|
||||||
self.0.as_ptr(),
|
|
||||||
data.as_ptr(),
|
|
||||||
data.len(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enable the CTAP 2.1 FIDO_EXT_MINPINLEN extension on cred and sets the expected minimum PIN length of cred to len.
|
|
||||||
///
|
|
||||||
/// If len is zero, the FIDO_EXT_MINPINLEN extension is disabled on cred.
|
|
||||||
pub fn set_pin_min_len(&mut self, len: usize) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_pin_minlen(self.0.as_ptr(), len))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enables the CTAP 2.1 FIDO_EXT_CRED_PROTECT extension on cred and sets the protection of cred to the scalar prot.
|
|
||||||
///
|
|
||||||
/// At the moment, only the FIDO_CRED_PROT_UV_OPTIONAL, FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID, and FIDO_CRED_PROT_UV_REQUIRED protections are supported.
|
|
||||||
///
|
|
||||||
/// See [Protection]
|
|
||||||
pub fn set_protection(&mut self, prot: Protection) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_prot(self.0.as_ptr(), prot as i32))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the rk (resident/discoverable key) attribute of cred.
|
|
||||||
pub fn set_rk(&mut self, rk: Opt) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_rk(self.0.as_ptr(), rk as _))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the uv (user verification) attribute of cred.
|
|
||||||
pub fn set_uv(&mut self, uv: Opt) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_uv(self.0.as_ptr(), uv as _))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the attestation statement format identifier of cred.
|
|
||||||
///
|
|
||||||
/// Note that not all authenticators support FIDO2 and therefore may only be able to generate fido-u2f attestation statements.
|
|
||||||
pub fn set_attestation_format(&mut self, fmt: AttestationFormat) -> Result<()> {
|
|
||||||
let fmt = match fmt {
|
|
||||||
AttestationFormat::Packed => CString::new("packed"),
|
|
||||||
AttestationFormat::FidoU2f => CString::new("fido-u2f"),
|
|
||||||
AttestationFormat::Tpm => CString::new("tpm"),
|
|
||||||
AttestationFormat::None => CString::new("none"),
|
|
||||||
};
|
|
||||||
let fmt = fmt.unwrap();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_fmt(self.0.as_ptr(), fmt.as_ptr()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the type of cred.
|
|
||||||
///
|
|
||||||
/// The `type` of a credential may only be set once.
|
|
||||||
///
|
|
||||||
/// Note that not all authenticators support COSE_RS256, COSE_ES384, or COSE_EDDSA.
|
|
||||||
pub fn set_cose_type(&mut self, ty: CoseType) -> Result<()> {
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_cred_set_type(self.0.as_ptr(), ty as i32))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(i32)]
|
|
||||||
pub enum Opt {
|
|
||||||
Omit = 0,
|
|
||||||
False = 1,
|
|
||||||
True = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
#[repr(i32)]
|
|
||||||
pub enum Protection {
|
|
||||||
UvOptional = ffi::FIDO_CRED_PROT_UV_OPTIONAL,
|
|
||||||
UvOptionalWithId = ffi::FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID,
|
|
||||||
UvRequired = ffi::FIDO_CRED_PROT_UV_REQUIRED,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attestation statement format
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum AttestationFormat {
|
|
||||||
Packed,
|
|
||||||
FidoU2f,
|
|
||||||
Tpm,
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// COSE Algorithms type
|
|
||||||
#[repr(i32)]
|
|
||||||
pub enum CoseType {
|
|
||||||
ES256 = ffi::COSE_ES256,
|
|
||||||
ES384 = ffi::COSE_ES384,
|
|
||||||
RS256 = ffi::COSE_RS256,
|
|
||||||
EDDSA = ffi::COSE_EDDSA,
|
|
||||||
UNSPEC = ffi::COSE_UNSPEC,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<i32> for CoseType {
|
|
||||||
type Error = i32;
|
|
||||||
|
|
||||||
fn try_from(value: i32) -> Result<Self, Self::Error> {
|
|
||||||
match value {
|
|
||||||
ffi::COSE_UNSPEC => Ok(CoseType::UNSPEC),
|
|
||||||
ffi::COSE_ES256 => Ok(CoseType::ES256),
|
|
||||||
ffi::COSE_ES384 => Ok(CoseType::ES384),
|
|
||||||
ffi::COSE_RS256 => Ok(CoseType::RS256),
|
|
||||||
ffi::COSE_EDDSA => Ok(CoseType::EDDSA),
|
|
||||||
_ => Err(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// FIDO extensions
|
|
||||||
pub struct Extensions: i32 {
|
|
||||||
const CRED_BLOB = ffi::FIDO_EXT_CRED_BLOB;
|
|
||||||
const CRED_PROTECT = ffi::FIDO_EXT_CRED_PROTECT;
|
|
||||||
const HMAC_SECRET = ffi::FIDO_EXT_HMAC_SECRET;
|
|
||||||
const MIN_PINLEN = ffi::FIDO_EXT_MINPINLEN;
|
|
||||||
const LARGEBLOB_KEY = ffi::FIDO_EXT_LARGEBLOB_KEY;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,390 +0,0 @@
|
|||||||
use crate::assertion::{AssertRequest, Assertions};
|
|
||||||
use crate::cbor::CBORInfo;
|
|
||||||
use crate::credentials::Credential;
|
|
||||||
use crate::error::Result;
|
|
||||||
use crate::utils::check;
|
|
||||||
use bitflags::bitflags;
|
|
||||||
use ffi::fido_dev_t;
|
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
/// Device list.
|
|
||||||
///
|
|
||||||
/// contain fido devices found by the underlying operating system.
|
|
||||||
///
|
|
||||||
/// user can call [DeviceList::list_devices] to start enumerate fido devices.
|
|
||||||
pub struct DeviceList<'a> {
|
|
||||||
ptr: NonNull<ffi::fido_dev_info_t>,
|
|
||||||
idx: usize,
|
|
||||||
found: usize,
|
|
||||||
_p: PhantomData<&'a ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DeviceList<'a> {
|
|
||||||
/// Enumerate up to `max` fido devices found by the underlying operating system.
|
|
||||||
///
|
|
||||||
/// Currently only USB HID devices are supported
|
|
||||||
pub fn list_devices(max: usize) -> DeviceList<'a> {
|
|
||||||
unsafe {
|
|
||||||
let mut found = 0;
|
|
||||||
let ptr = ffi::fido_dev_info_new(max);
|
|
||||||
|
|
||||||
ffi::fido_dev_info_manifest(ptr, max, &mut found);
|
|
||||||
|
|
||||||
DeviceList {
|
|
||||||
ptr: NonNull::new_unchecked(ptr),
|
|
||||||
idx: 0,
|
|
||||||
found,
|
|
||||||
_p: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for DeviceList<'a> {
|
|
||||||
type Item = DeviceInfo<'a>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if self.idx >= self.found {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let ptr = self.ptr.as_ptr();
|
|
||||||
let info = ffi::fido_dev_info_ptr(ptr, self.idx);
|
|
||||||
|
|
||||||
let path = ffi::fido_dev_info_path(info);
|
|
||||||
let path = CStr::from_ptr(path);
|
|
||||||
|
|
||||||
let product_id = ffi::fido_dev_info_product(info);
|
|
||||||
let vendor_id = ffi::fido_dev_info_vendor(info);
|
|
||||||
|
|
||||||
let manufacturer = ffi::fido_dev_info_manufacturer_string(info);
|
|
||||||
let manufacturer = CStr::from_ptr(manufacturer);
|
|
||||||
|
|
||||||
let product = ffi::fido_dev_info_product_string(info);
|
|
||||||
let product = CStr::from_ptr(product);
|
|
||||||
self.idx += 1;
|
|
||||||
|
|
||||||
Some(DeviceInfo {
|
|
||||||
path,
|
|
||||||
product_id,
|
|
||||||
vendor_id,
|
|
||||||
manufacturer,
|
|
||||||
product,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ExactSizeIterator for DeviceList<'a> {
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Drop for DeviceList<'a> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
ffi::fido_dev_info_free(&mut self.ptr.as_ptr(), self.found);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Device info obtained from [DeviceList]
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
||||||
pub struct DeviceInfo<'a> {
|
|
||||||
pub path: &'a CStr,
|
|
||||||
pub product_id: i16,
|
|
||||||
pub vendor_id: i16,
|
|
||||||
pub manufacturer: &'a CStr,
|
|
||||||
pub product: &'a CStr,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DeviceInfo<'a> {
|
|
||||||
/// Open the device specified by this [DeviceInfo]
|
|
||||||
pub fn open(&self) -> Result<Device> {
|
|
||||||
unsafe {
|
|
||||||
let ptr = ffi::fido_dev_new();
|
|
||||||
check(ffi::fido_dev_open(ptr, self.path.as_ptr()))?;
|
|
||||||
|
|
||||||
let ptr = NonNull::new_unchecked(ptr);
|
|
||||||
|
|
||||||
Ok(Device { ptr })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A cancel handle to device, used to cancel a pending requests.
|
|
||||||
///
|
|
||||||
/// This handle can be copy/clone.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
||||||
pub struct DeviceCancel(NonNull<fido_dev_t>);
|
|
||||||
|
|
||||||
impl DeviceCancel {
|
|
||||||
/// Cancel any pending requests on device.
|
|
||||||
pub fn cancel(&self) {
|
|
||||||
unsafe {
|
|
||||||
ffi::fido_dev_cancel(self.0.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A fido device.
|
|
||||||
pub struct Device {
|
|
||||||
ptr: NonNull<fido_dev_t>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Device {
|
|
||||||
/// Open the device pointed to by `path`.
|
|
||||||
///
|
|
||||||
/// If dev claims to be FIDO2, libfido2 will attempt to speak FIDO2 to dev.
|
|
||||||
/// If that fails, libfido2 will fallback to U2F unless the FIDO_DISABLE_U2F_FALLBACK flag
|
|
||||||
/// was set in fido_init(3).
|
|
||||||
pub fn open(path: impl AsRef<str>) -> Result<Device> {
|
|
||||||
let path = CString::new(path.as_ref())?;
|
|
||||||
unsafe {
|
|
||||||
let dev = ffi::fido_dev_new();
|
|
||||||
assert!(!dev.is_null());
|
|
||||||
|
|
||||||
check(ffi::fido_dev_open(dev, path.as_ptr()))?;
|
|
||||||
|
|
||||||
Ok(Device {
|
|
||||||
ptr: NonNull::new_unchecked(dev),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a handle of this device for cancel.
|
|
||||||
pub fn cancel_handle(&self) -> DeviceCancel {
|
|
||||||
DeviceCancel(self.ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// can be used to force CTAP2 communication with dev
|
|
||||||
pub fn force_u2f(&self) {
|
|
||||||
unsafe {
|
|
||||||
ffi::fido_dev_force_u2f(self.ptr.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Can be used to force CTAP1 (U2F) communication with dev
|
|
||||||
pub fn force_fido2(&self) {
|
|
||||||
unsafe {
|
|
||||||
ffi::fido_dev_force_fido2(self.ptr.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev is a FIDO2 device.
|
|
||||||
pub fn is_fido2(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_is_fido2(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev is a Windows Hello device.
|
|
||||||
pub fn is_winhello(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_is_winhello(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev supports CTAP 2.1 Credential Management.
|
|
||||||
pub fn supports_credman(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_supports_credman(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev supports CTAP 2.1 Credential Protection.
|
|
||||||
pub fn supports_cred_prot(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_supports_cred_prot(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev supports CTAP 2.1 UV token permissions.
|
|
||||||
pub fn supports_permission(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_supports_permissions(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev supports CTAP 2.0 Client PINs.
|
|
||||||
pub fn supports_pin(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_supports_pin(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev supports a built-in user verification method.
|
|
||||||
pub fn supports_uv(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_supports_uv(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev has a CTAP 2.0 Client PIN set.
|
|
||||||
pub fn has_pin(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_has_pin(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if dev supports built-in user verification and its user verification feature is configured.
|
|
||||||
pub fn has_uv(&self) -> bool {
|
|
||||||
unsafe { ffi::fido_dev_has_uv(self.ptr.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return CTAPHID protocol info.
|
|
||||||
pub fn ctap_protocol(&self) -> CTAPHIDInfo {
|
|
||||||
unsafe {
|
|
||||||
let protocol = ffi::fido_dev_protocol(self.ptr.as_ptr());
|
|
||||||
let build = ffi::fido_dev_build(self.ptr.as_ptr());
|
|
||||||
let flags = ffi::fido_dev_flags(self.ptr.as_ptr());
|
|
||||||
let flags = CTAPHIDFlags::from_bits_truncate(flags);
|
|
||||||
let major = ffi::fido_dev_major(self.ptr.as_ptr());
|
|
||||||
let minor = ffi::fido_dev_minor(self.ptr.as_ptr());
|
|
||||||
|
|
||||||
CTAPHIDInfo {
|
|
||||||
protocol,
|
|
||||||
build,
|
|
||||||
flags,
|
|
||||||
major,
|
|
||||||
minor,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return device info.
|
|
||||||
pub fn info(&self) -> Result<CBORInfo> {
|
|
||||||
let info = CBORInfo::new();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_dev_get_cbor_info(
|
|
||||||
self.ptr.as_ptr(),
|
|
||||||
info.ptr.as_ptr(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a new credential on a FIDO2 device.
|
|
||||||
///
|
|
||||||
/// Ask the FIDO2 device represented by dev to generate a new credential according to the following parameters defined in cred:
|
|
||||||
/// * type
|
|
||||||
/// * client data hash
|
|
||||||
/// * relying party
|
|
||||||
/// * user attributes
|
|
||||||
/// * list of excluded credential IDs
|
|
||||||
/// * resident/discoverable key and user verification attributes
|
|
||||||
///
|
|
||||||
/// If a PIN is not needed to authenticate the request against dev, then pin may be [None].
|
|
||||||
///
|
|
||||||
/// **Please note that fido_dev_make_cred() is synchronous and will block if necessary.**
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
/// ```rust,no_run
|
|
||||||
/// use fido2_rs::credentials::Credential;
|
|
||||||
/// use fido2_rs::device::Device;
|
|
||||||
/// use fido2_rs::credentials::CoseType;
|
|
||||||
///
|
|
||||||
/// fn main() -> anyhow::Result<()> {
|
|
||||||
/// let dev = Device::open("windows://hello").expect("unable open device");
|
|
||||||
/// let mut cred = Credential::new();
|
|
||||||
/// cred.set_client_data(&[1, 2, 3, 4, 5, 6])?;
|
|
||||||
/// cred.set_rp("fido_rs", "fido example")?;
|
|
||||||
/// cred.set_user(&[1, 2, 3, 4, 5, 6], "alice", Some("alice"), None)?;
|
|
||||||
/// cred.set_cose_type(CoseType::RS256)?;
|
|
||||||
///
|
|
||||||
/// let _ = dev.make_credential(&mut cred, None)?; // and not require pin..
|
|
||||||
///
|
|
||||||
/// dbg!(cred.id());
|
|
||||||
/// Ok(())
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn make_credential(&self, credential: &mut Credential, pin: Option<&str>) -> Result<()> {
|
|
||||||
let pin = pin.map(CString::new).transpose()?;
|
|
||||||
let pin_ptr = match &pin {
|
|
||||||
Some(pin) => pin.as_ptr(),
|
|
||||||
None => std::ptr::null(),
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_dev_make_cred(
|
|
||||||
self.ptr.as_ptr(),
|
|
||||||
credential.0.as_ptr(),
|
|
||||||
pin_ptr,
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Obtains an assertion from a FIDO2 device.
|
|
||||||
///
|
|
||||||
/// Ask the FIDO2 device represented by dev for an assertion according to the following parameters defined in assert:
|
|
||||||
/// * relying party ID
|
|
||||||
/// * client data hash
|
|
||||||
/// * list of allowed credential IDs
|
|
||||||
/// * user presence and user verification attributes
|
|
||||||
///
|
|
||||||
/// If a PIN is not needed to authenticate the request against dev, then pin may be NULL.
|
|
||||||
///
|
|
||||||
/// **Please note that fido_dev_get_assert() is synchronous and will block if necessary.**
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
/// ```rust,no_run
|
|
||||||
/// use fido2_rs::assertion::AssertRequest;
|
|
||||||
/// use fido2_rs::credentials::Opt;
|
|
||||||
/// use fido2_rs::device::Device;
|
|
||||||
///
|
|
||||||
/// fn main() -> anyhow::Result<()> {
|
|
||||||
/// let dev = Device::open("windows://hello")?;
|
|
||||||
/// let mut request = AssertRequest::new(); ///
|
|
||||||
///
|
|
||||||
/// request.set_rp("fido_rs")?;
|
|
||||||
/// request.set_client_data(&[1, 2, 3, 4, 5, 6])?;
|
|
||||||
/// request.set_uv(Opt::True)?;
|
|
||||||
///
|
|
||||||
/// let _assertions = dev.get_assertion(request, None)?;
|
|
||||||
/// Ok(())
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn get_assertion(&self, request: AssertRequest, pin: Option<&str>) -> Result<Assertions> {
|
|
||||||
let pin = pin.map(CString::new).transpose()?;
|
|
||||||
let pin_ptr = match &pin {
|
|
||||||
Some(pin) => pin.as_ptr(),
|
|
||||||
None => std::ptr::null(),
|
|
||||||
};
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
check(ffi::fido_dev_get_assert(
|
|
||||||
self.ptr.as_ptr(),
|
|
||||||
request.0.ptr.as_ptr(),
|
|
||||||
pin_ptr,
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(request.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for Device {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
let _ = ffi::fido_dev_close(self.ptr.as_ptr());
|
|
||||||
ffi::fido_dev_free(&mut self.ptr.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
/// CTAPHID capabilities
|
|
||||||
pub struct CTAPHIDFlags: u8 {
|
|
||||||
const WINK = ffi::FIDO_CAP_WINK as u8;
|
|
||||||
const CBOR = ffi::FIDO_CAP_CBOR as u8;
|
|
||||||
const NMSG = ffi::FIDO_CAP_NMSG as u8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// For the format and meaning of the CTAPHID parameters,
|
|
||||||
/// please refer to the FIDO Client to Authenticator Protocol (CTAP) specification.
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
||||||
pub struct CTAPHIDInfo {
|
|
||||||
/// CTAPHID protocol version identifier of dev
|
|
||||||
pub protocol: u8,
|
|
||||||
/// CTAPHID build version number of dev.
|
|
||||||
pub build: u8,
|
|
||||||
/// CTAPHID capabilities flags of dev.
|
|
||||||
pub flags: CTAPHIDFlags,
|
|
||||||
/// CTAPHID major version number of dev.
|
|
||||||
pub major: u8,
|
|
||||||
/// CTAPHID minor version number of dev.
|
|
||||||
pub minor: u8,
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
use std::ffi::CStr;
|
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
|
|
||||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
|
||||||
|
|
||||||
/// Error type of fido2-rs
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
#[error("libfido2: {0}")]
|
|
||||||
Fido(#[from] FidoError),
|
|
||||||
|
|
||||||
#[error("{0}")]
|
|
||||||
NulError(#[from] std::ffi::NulError),
|
|
||||||
|
|
||||||
#[error("openssl {0}")]
|
|
||||||
Openssl(#[from] openssl::error::ErrorStack),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error from libfido2
|
|
||||||
pub struct FidoError {
|
|
||||||
/// the origin error code
|
|
||||||
pub code: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FidoError {
|
|
||||||
pub(crate) const fn new(code: i32) -> FidoError {
|
|
||||||
FidoError { code }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for FidoError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
<Self as Display>::fmt(self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for FidoError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let err = unsafe {
|
|
||||||
let err = ffi::fido_strerr(self.code);
|
|
||||||
CStr::from_ptr(err)
|
|
||||||
};
|
|
||||||
|
|
||||||
f.debug_struct("Error")
|
|
||||||
.field("code", &self.code)
|
|
||||||
.field("message", &err)
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for FidoError {}
|
|
@ -1,85 +0,0 @@
|
|||||||
use crate::error::FidoError;
|
|
||||||
use openssl::ec::EcKey;
|
|
||||||
use openssl::pkey::{PKey, Public};
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
macro_rules! impl_key {
|
|
||||||
(
|
|
||||||
type CType = $ctype:ty;
|
|
||||||
fn new = $new:expr;
|
|
||||||
$(fn from<$t:ty> = $from:expr;)*
|
|
||||||
fn drop = $drop:expr;
|
|
||||||
|
|
||||||
pub struct $ty:ident;
|
|
||||||
) => {
|
|
||||||
pub struct $ty(NonNull<$ctype>);
|
|
||||||
|
|
||||||
$(impl TryFrom<$t> for $ty {
|
|
||||||
type Error = FidoError;
|
|
||||||
|
|
||||||
fn try_from(value: $t) -> Result<Self, Self::Error> {
|
|
||||||
use foreign_types::ForeignType;
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let pk = $new();
|
|
||||||
crate::utils::check($from(pk, value.as_ptr() as _))?;
|
|
||||||
|
|
||||||
Ok($ty(NonNull::new_unchecked(pk)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})*
|
|
||||||
|
|
||||||
impl Drop for $ty {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
let mut ptr = self.0.as_ptr();
|
|
||||||
unsafe {
|
|
||||||
$drop(&mut ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = std::mem::replace(&mut self.0, NonNull::dangling());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $ty {
|
|
||||||
pub(crate) fn as_ptr(&self) -> *const $ctype {
|
|
||||||
self.0.as_ptr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_key! {
|
|
||||||
type CType = ffi::eddsa_pk_t;
|
|
||||||
fn new = ffi::eddsa_pk_new;
|
|
||||||
fn from<PKey<Public>> = ffi::eddsa_pk_from_EVP_PKEY;
|
|
||||||
fn drop = ffi::eddsa_pk_free;
|
|
||||||
|
|
||||||
pub struct Eddsa;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_key! {
|
|
||||||
type CType = ffi::rs256_pk_t;
|
|
||||||
fn new = ffi::rs256_pk_new;
|
|
||||||
fn from<PKey<Public>> = ffi::rs256_pk_from_EVP_PKEY;
|
|
||||||
fn drop = ffi::rs256_pk_free;
|
|
||||||
|
|
||||||
pub struct Rsa;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_key! {
|
|
||||||
type CType = ffi::es256_pk_t;
|
|
||||||
fn new = ffi::es256_pk_new;
|
|
||||||
fn from<EcKey<Public>> = ffi::es256_pk_from_EC_KEY;
|
|
||||||
fn drop = ffi::es256_pk_free;
|
|
||||||
|
|
||||||
pub struct ES256;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_key! {
|
|
||||||
type CType = ffi::es384_pk_t;
|
|
||||||
fn new = ffi::es384_pk_new;
|
|
||||||
fn from<EcKey<Public>> = ffi::es384_pk_from_EC_KEY;
|
|
||||||
fn drop = ffi::es384_pk_free;
|
|
||||||
|
|
||||||
pub struct ES384;
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
//! Bindings to Yubico libfido2
|
|
||||||
//!
|
|
||||||
//! This crate provides a safe interface to the Yubico libfido2 library.
|
|
||||||
//!
|
|
||||||
//! # Building
|
|
||||||
//!
|
|
||||||
//! There are multiple options available to locate libfido2.
|
|
||||||
//!
|
|
||||||
//! ## Pre-build MSVC binary.
|
|
||||||
//!
|
|
||||||
//! If the rust toolchain is msvc, the `libfido2-sys` crate will download a pre-build binary dll from
|
|
||||||
//! Yubico release.
|
|
||||||
//!
|
|
||||||
//! ## Build from source.
|
|
||||||
//!
|
|
||||||
//! If the target is not msvc(mingw on windows or linux), this crate will build a static library from source.
|
|
||||||
//!
|
|
||||||
//! The build process requires a C compiler, cmake, libcbor, zlib, libcrypto.
|
|
||||||
//!
|
|
||||||
//! ## Automatic
|
|
||||||
//!
|
|
||||||
//! The `libfido2-sys` crate can automatically detect libfido2 installations via vcpkg on Windows and `pkg-config` on Linux.
|
|
||||||
//!
|
|
||||||
//! This method can be enabled by set environment variable `FIDO2_USE_PKG_CONFIG` to any non empty value.
|
|
||||||
//!
|
|
||||||
//! ## Manual
|
|
||||||
//!
|
|
||||||
//! A `FIDO2_LIB_DIR` environment variable can be used to help `libfido2-sys` to find a libfido2 installation.
|
|
||||||
//!
|
|
||||||
//! The directory should contains the libfido2 libraries.
|
|
||||||
//!
|
|
||||||
//! The other dependency like libcbor, libcrypto, zlib will use system version. Currently there is no way to
|
|
||||||
//! set these library directory, but you can put them together in `FIDO2_LIB_DIR`.
|
|
||||||
//!
|
|
||||||
//! # Example
|
|
||||||
//!
|
|
||||||
//! ## Enumerate fido devices on system
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! use fido2_rs::device::DeviceList;
|
|
||||||
//!
|
|
||||||
//! let list = DeviceList::list_devices(4);
|
|
||||||
//! for dev in list {
|
|
||||||
//! println!("{:?}", dev.path);
|
|
||||||
//! }
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! ## Make a credential
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! use fido2_rs::device::Device;
|
|
||||||
//! use fido2_rs::credentials::Credential;
|
|
||||||
//! use fido2_rs::credentials::CoseType;
|
|
||||||
//! use anyhow::Result;
|
|
||||||
//! fn main() -> Result<()> {
|
|
||||||
//! let dev = Device::open("windows://hello").expect("unable open windows hello");
|
|
||||||
//!
|
|
||||||
//! let mut cred = Credential::new();
|
|
||||||
//! cred.set_client_data(&[1, 2, 3, 4, 5, 6])?;
|
|
||||||
//! cred.set_rp("fido_rs", "fido example")?;
|
|
||||||
//! cred.set_user(&[1, 2, 3, 4, 5, 6], "alice", Some("alice"), None)?;
|
|
||||||
//! cred.set_cose_type(CoseType::RS256)?;
|
|
||||||
//!
|
|
||||||
//! let _ = dev.make_credential(&mut cred, None)?;
|
|
||||||
//! dbg!(cred.id());
|
|
||||||
//!
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
extern crate libfido2_sys as ffi;
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
pub mod assertion;
|
|
||||||
mod cbor;
|
|
||||||
pub mod credentials;
|
|
||||||
pub mod device;
|
|
||||||
pub mod error;
|
|
||||||
mod key;
|
|
@ -1,24 +0,0 @@
|
|||||||
use crate::error::FidoError;
|
|
||||||
|
|
||||||
pub(crate) const fn check(code: i32) -> Result<(), FidoError> {
|
|
||||||
match code {
|
|
||||||
0 => Ok(()),
|
|
||||||
_ => Err(FidoError::new(code)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! str_or_none {
|
|
||||||
($ptr:ident) => {
|
|
||||||
if $ptr.is_null() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let $ptr = unsafe {
|
|
||||||
std::ffi::CStr::from_ptr($ptr)
|
|
||||||
.to_str()
|
|
||||||
.expect("invalid utf8")
|
|
||||||
};
|
|
||||||
|
|
||||||
Some($ptr)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "libfido2-sys"
|
|
||||||
version = "0.2.0"
|
|
||||||
authors = ["tyan boot <tyanboot@outlook.com>"]
|
|
||||||
license = "MIT"
|
|
||||||
description = "FFI bindings to Yubico fido2"
|
|
||||||
repository = "https://github.com/tyan-boot/fido-rs"
|
|
||||||
keywords = ["fido2", "webauthn"]
|
|
||||||
categories = ["external-ffi-bindings"]
|
|
||||||
edition = "2021"
|
|
||||||
links = "fido2"
|
|
||||||
|
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
anyhow = "1.0.66"
|
|
||||||
cfg-if = "1.0.0"
|
|
||||||
|
|
||||||
[target.'cfg(target_env = "msvc")'.build-dependencies]
|
|
||||||
vcpkg = "0.2.15"
|
|
||||||
|
|
||||||
[target.'cfg(not(target_env = "msvc"))'.build-dependencies]
|
|
||||||
pkg-config = "0.3.26"
|
|
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2023 tyan boot
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,6 +0,0 @@
|
|||||||
# libfido2-sys
|
|
||||||
|
|
||||||
[![crates.io](https://img.shields.io/crates/v/libfido2-sys?style=flat-square)](https://crates.io/crates/libfido2-sys)
|
|
||||||
[![MIT](https://img.shields.io/crates/l/libfido2-sys?style=flat-square)](./LICENSE)
|
|
||||||
|
|
||||||
FFI bindings to Yubico [libfido2](https://github.com/Yubico/libfido2)
|
|
@ -1,57 +0,0 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use cfg_if::cfg_if;
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
println!("cargo:rerun-if-env-changed=FIDO2_LIB_DIR");
|
|
||||||
println!("cargo:rerun-if-env-changed=FIDO2_USE_PKG_CONFIG");
|
|
||||||
|
|
||||||
if let Ok(dir) = env::var("FIDO2_LIB_DIR") {
|
|
||||||
println!("cargo:rustc-link-search={}", dir);
|
|
||||||
println!("cargo:rustc-link-lib=static=fido2");
|
|
||||||
|
|
||||||
if cfg!(windows) {
|
|
||||||
println!("cargo:rustc-link-lib=hid");
|
|
||||||
println!("cargo:rustc-link-lib=user32");
|
|
||||||
println!("cargo:rustc-link-lib=setupapi");
|
|
||||||
println!("cargo:rustc-link-lib=crypt32");
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(all(windows, target_env = "msvc"))] {
|
|
||||||
// link to pre-build cbor,zlib,crypto
|
|
||||||
println!("cargo:rustc-link-lib=cbor");
|
|
||||||
println!("cargo:rustc-link-lib=zlib1");
|
|
||||||
println!("cargo:rustc-link-lib=crypto-49");
|
|
||||||
} else {
|
|
||||||
println!("cargo:rustc-link-lib=cbor");
|
|
||||||
println!("cargo:rustc-link-lib=z");
|
|
||||||
println!("cargo:rustc-link-lib=crypto");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
find_pkg()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_env = "msvc"))]
|
|
||||||
fn find_pkg() -> Result<()> {
|
|
||||||
let _lib = pkg_config::probe_library("libfido2")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(windows, target_env = "msvc"))]
|
|
||||||
fn find_pkg() -> Result<()> {
|
|
||||||
let _lib = vcpkg::find_package("libfido2")?;
|
|
||||||
|
|
||||||
println!("cargo:rustc-link-lib=hid");
|
|
||||||
println!("cargo:rustc-link-lib=user32");
|
|
||||||
println!("cargo:rustc-link-lib=setupapi");
|
|
||||||
println!("cargo:rustc-link-lib=crypt32");
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
#include <fido.h>
|
|
||||||
#include <fido/rs256.h>
|
|
||||||
#include <fido/es256.h>
|
|
||||||
#include <fido/es384.h>
|
|
||||||
#include <fido/eddsa.h>
|
|
Binary file not shown.
@ -1,856 +0,0 @@
|
|||||||
/* automatically generated by rust-bindgen 0.63.0 */
|
|
||||||
|
|
||||||
pub const FIDO_ERR_SUCCESS: i32 = 0;
|
|
||||||
pub const FIDO_ERR_INVALID_COMMAND: i32 = 1;
|
|
||||||
pub const FIDO_ERR_INVALID_PARAMETER: i32 = 2;
|
|
||||||
pub const FIDO_ERR_INVALID_LENGTH: i32 = 3;
|
|
||||||
pub const FIDO_ERR_INVALID_SEQ: i32 = 4;
|
|
||||||
pub const FIDO_ERR_TIMEOUT: i32 = 5;
|
|
||||||
pub const FIDO_ERR_CHANNEL_BUSY: i32 = 6;
|
|
||||||
pub const FIDO_ERR_LOCK_REQUIRED: i32 = 10;
|
|
||||||
pub const FIDO_ERR_INVALID_CHANNEL: i32 = 11;
|
|
||||||
pub const FIDO_ERR_CBOR_UNEXPECTED_TYPE: i32 = 17;
|
|
||||||
pub const FIDO_ERR_INVALID_CBOR: i32 = 18;
|
|
||||||
pub const FIDO_ERR_MISSING_PARAMETER: i32 = 20;
|
|
||||||
pub const FIDO_ERR_LIMIT_EXCEEDED: i32 = 21;
|
|
||||||
pub const FIDO_ERR_UNSUPPORTED_EXTENSION: i32 = 22;
|
|
||||||
pub const FIDO_ERR_FP_DATABASE_FULL: i32 = 23;
|
|
||||||
pub const FIDO_ERR_LARGEBLOB_STORAGE_FULL: i32 = 24;
|
|
||||||
pub const FIDO_ERR_CREDENTIAL_EXCLUDED: i32 = 25;
|
|
||||||
pub const FIDO_ERR_PROCESSING: i32 = 33;
|
|
||||||
pub const FIDO_ERR_INVALID_CREDENTIAL: i32 = 34;
|
|
||||||
pub const FIDO_ERR_USER_ACTION_PENDING: i32 = 35;
|
|
||||||
pub const FIDO_ERR_OPERATION_PENDING: i32 = 36;
|
|
||||||
pub const FIDO_ERR_NO_OPERATIONS: i32 = 37;
|
|
||||||
pub const FIDO_ERR_UNSUPPORTED_ALGORITHM: i32 = 38;
|
|
||||||
pub const FIDO_ERR_OPERATION_DENIED: i32 = 39;
|
|
||||||
pub const FIDO_ERR_KEY_STORE_FULL: i32 = 40;
|
|
||||||
pub const FIDO_ERR_NOT_BUSY: i32 = 41;
|
|
||||||
pub const FIDO_ERR_NO_OPERATION_PENDING: i32 = 42;
|
|
||||||
pub const FIDO_ERR_UNSUPPORTED_OPTION: i32 = 43;
|
|
||||||
pub const FIDO_ERR_INVALID_OPTION: i32 = 44;
|
|
||||||
pub const FIDO_ERR_KEEPALIVE_CANCEL: i32 = 45;
|
|
||||||
pub const FIDO_ERR_NO_CREDENTIALS: i32 = 46;
|
|
||||||
pub const FIDO_ERR_USER_ACTION_TIMEOUT: i32 = 47;
|
|
||||||
pub const FIDO_ERR_NOT_ALLOWED: i32 = 48;
|
|
||||||
pub const FIDO_ERR_PIN_INVALID: i32 = 49;
|
|
||||||
pub const FIDO_ERR_PIN_BLOCKED: i32 = 50;
|
|
||||||
pub const FIDO_ERR_PIN_AUTH_INVALID: i32 = 51;
|
|
||||||
pub const FIDO_ERR_PIN_AUTH_BLOCKED: i32 = 52;
|
|
||||||
pub const FIDO_ERR_PIN_NOT_SET: i32 = 53;
|
|
||||||
pub const FIDO_ERR_PIN_REQUIRED: i32 = 54;
|
|
||||||
pub const FIDO_ERR_PIN_POLICY_VIOLATION: i32 = 55;
|
|
||||||
pub const FIDO_ERR_PIN_TOKEN_EXPIRED: i32 = 56;
|
|
||||||
pub const FIDO_ERR_REQUEST_TOO_LARGE: i32 = 57;
|
|
||||||
pub const FIDO_ERR_ACTION_TIMEOUT: i32 = 58;
|
|
||||||
pub const FIDO_ERR_UP_REQUIRED: i32 = 59;
|
|
||||||
pub const FIDO_ERR_UV_BLOCKED: i32 = 60;
|
|
||||||
pub const FIDO_ERR_UV_INVALID: i32 = 63;
|
|
||||||
pub const FIDO_ERR_UNAUTHORIZED_PERM: i32 = 64;
|
|
||||||
pub const FIDO_ERR_ERR_OTHER: i32 = 127;
|
|
||||||
pub const FIDO_ERR_SPEC_LAST: i32 = 223;
|
|
||||||
pub const FIDO_OK: i32 = 0;
|
|
||||||
pub const FIDO_ERR_TX: i32 = -1;
|
|
||||||
pub const FIDO_ERR_RX: i32 = -2;
|
|
||||||
pub const FIDO_ERR_RX_NOT_CBOR: i32 = -3;
|
|
||||||
pub const FIDO_ERR_RX_INVALID_CBOR: i32 = -4;
|
|
||||||
pub const FIDO_ERR_INVALID_PARAM: i32 = -5;
|
|
||||||
pub const FIDO_ERR_INVALID_SIG: i32 = -6;
|
|
||||||
pub const FIDO_ERR_INVALID_ARGUMENT: i32 = -7;
|
|
||||||
pub const FIDO_ERR_USER_PRESENCE_REQUIRED: i32 = -8;
|
|
||||||
pub const FIDO_ERR_INTERNAL: i32 = -9;
|
|
||||||
pub const FIDO_ERR_NOTFOUND: i32 = -10;
|
|
||||||
pub const FIDO_ERR_COMPRESS: i32 = -11;
|
|
||||||
pub const CTAP_AUTHDATA_USER_PRESENT: i32 = 1;
|
|
||||||
pub const CTAP_AUTHDATA_USER_VERIFIED: i32 = 4;
|
|
||||||
pub const CTAP_AUTHDATA_ATT_CRED: i32 = 64;
|
|
||||||
pub const CTAP_AUTHDATA_EXT_DATA: i32 = 128;
|
|
||||||
pub const CTAP_CMD_PING: i32 = 1;
|
|
||||||
pub const CTAP_CMD_MSG: i32 = 3;
|
|
||||||
pub const CTAP_CMD_LOCK: i32 = 4;
|
|
||||||
pub const CTAP_CMD_INIT: i32 = 6;
|
|
||||||
pub const CTAP_CMD_WINK: i32 = 8;
|
|
||||||
pub const CTAP_CMD_CBOR: i32 = 16;
|
|
||||||
pub const CTAP_CMD_CANCEL: i32 = 17;
|
|
||||||
pub const CTAP_KEEPALIVE: i32 = 59;
|
|
||||||
pub const CTAP_FRAME_INIT: i32 = 128;
|
|
||||||
pub const CTAP_CBOR_MAKECRED: i32 = 1;
|
|
||||||
pub const CTAP_CBOR_ASSERT: i32 = 2;
|
|
||||||
pub const CTAP_CBOR_GETINFO: i32 = 4;
|
|
||||||
pub const CTAP_CBOR_CLIENT_PIN: i32 = 6;
|
|
||||||
pub const CTAP_CBOR_RESET: i32 = 7;
|
|
||||||
pub const CTAP_CBOR_NEXT_ASSERT: i32 = 8;
|
|
||||||
pub const CTAP_CBOR_LARGEBLOB: i32 = 12;
|
|
||||||
pub const CTAP_CBOR_CONFIG: i32 = 13;
|
|
||||||
pub const CTAP_CBOR_BIO_ENROLL_PRE: i32 = 64;
|
|
||||||
pub const CTAP_CBOR_CRED_MGMT_PRE: i32 = 65;
|
|
||||||
pub const CTAP_PIN_PROTOCOL1: i32 = 1;
|
|
||||||
pub const CTAP_PIN_PROTOCOL2: i32 = 2;
|
|
||||||
pub const U2F_CMD_REGISTER: i32 = 1;
|
|
||||||
pub const U2F_CMD_AUTH: i32 = 2;
|
|
||||||
pub const U2F_AUTH_SIGN: i32 = 3;
|
|
||||||
pub const U2F_AUTH_CHECK: i32 = 7;
|
|
||||||
pub const CTAP_CID_BROADCAST: i64 = 4294967295;
|
|
||||||
pub const CTAP_INIT_HEADER_LEN: i32 = 7;
|
|
||||||
pub const CTAP_CONT_HEADER_LEN: i32 = 5;
|
|
||||||
pub const CTAP_MAX_REPORT_LEN: i32 = 64;
|
|
||||||
pub const CTAP_MIN_REPORT_LEN: i32 = 8;
|
|
||||||
pub const FIDO_RANDOM_DEV: &[u8; 13usize] = b"/dev/urandom\0";
|
|
||||||
pub const FIDO_MAXMSG: i32 = 2048;
|
|
||||||
pub const FIDO_CAP_WINK: i32 = 1;
|
|
||||||
pub const FIDO_CAP_CBOR: i32 = 4;
|
|
||||||
pub const FIDO_CAP_NMSG: i32 = 8;
|
|
||||||
pub const COSE_UNSPEC: i32 = 0;
|
|
||||||
pub const COSE_ES256: i32 = -7;
|
|
||||||
pub const COSE_EDDSA: i32 = -8;
|
|
||||||
pub const COSE_ECDH_ES256: i32 = -25;
|
|
||||||
pub const COSE_ES384: i32 = -35;
|
|
||||||
pub const COSE_RS256: i32 = -257;
|
|
||||||
pub const COSE_RS1: i32 = -65535;
|
|
||||||
pub const COSE_KTY_OKP: i32 = 1;
|
|
||||||
pub const COSE_KTY_EC2: i32 = 2;
|
|
||||||
pub const COSE_KTY_RSA: i32 = 3;
|
|
||||||
pub const COSE_P256: i32 = 1;
|
|
||||||
pub const COSE_P384: i32 = 2;
|
|
||||||
pub const COSE_ED25519: i32 = 6;
|
|
||||||
pub const FIDO_EXT_HMAC_SECRET: i32 = 1;
|
|
||||||
pub const FIDO_EXT_CRED_PROTECT: i32 = 2;
|
|
||||||
pub const FIDO_EXT_LARGEBLOB_KEY: i32 = 4;
|
|
||||||
pub const FIDO_EXT_CRED_BLOB: i32 = 8;
|
|
||||||
pub const FIDO_EXT_MINPINLEN: i32 = 16;
|
|
||||||
pub const FIDO_CRED_PROT_UV_OPTIONAL: i32 = 1;
|
|
||||||
pub const FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID: i32 = 2;
|
|
||||||
pub const FIDO_CRED_PROT_UV_REQUIRED: i32 = 3;
|
|
||||||
pub const FIDO_UV_MODE_TUP: i32 = 1;
|
|
||||||
pub const FIDO_UV_MODE_FP: i32 = 2;
|
|
||||||
pub const FIDO_UV_MODE_PIN: i32 = 4;
|
|
||||||
pub const FIDO_UV_MODE_VOICE: i32 = 8;
|
|
||||||
pub const FIDO_UV_MODE_FACE: i32 = 16;
|
|
||||||
pub const FIDO_UV_MODE_LOCATION: i32 = 32;
|
|
||||||
pub const FIDO_UV_MODE_EYE: i32 = 64;
|
|
||||||
pub const FIDO_UV_MODE_DRAWN: i32 = 128;
|
|
||||||
pub const FIDO_UV_MODE_HAND: i32 = 256;
|
|
||||||
pub const FIDO_UV_MODE_NONE: i32 = 512;
|
|
||||||
pub const FIDO_UV_MODE_ALL: i32 = 1024;
|
|
||||||
pub const FIDO_UV_MODE_EXT_PIN: i32 = 2048;
|
|
||||||
pub const FIDO_UV_MODE_EXT_DRAWN: i32 = 4096;
|
|
||||||
pub const FIDO_DEBUG: i32 = 1;
|
|
||||||
pub const FIDO_DISABLE_U2F_FALLBACK: i32 = 2;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct evp_pkey_st {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type EVP_PKEY = evp_pkey_st;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct rsa_st {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type RSA = rsa_st;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct ec_key_st {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type EC_KEY = ec_key_st;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_dev {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type fido_dev_io_open_t = ::std::option::Option<
|
|
||||||
unsafe extern "C" fn(arg1: *const ::std::os::raw::c_char) -> *mut ::std::os::raw::c_void,
|
|
||||||
>;
|
|
||||||
pub type fido_dev_io_close_t =
|
|
||||||
::std::option::Option<unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void)>;
|
|
||||||
pub type fido_dev_io_read_t = ::std::option::Option<
|
|
||||||
unsafe extern "C" fn(
|
|
||||||
arg1: *mut ::std::os::raw::c_void,
|
|
||||||
arg2: *mut ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
arg4: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int,
|
|
||||||
>;
|
|
||||||
pub type fido_dev_io_write_t = ::std::option::Option<
|
|
||||||
unsafe extern "C" fn(
|
|
||||||
arg1: *mut ::std::os::raw::c_void,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int,
|
|
||||||
>;
|
|
||||||
pub type fido_dev_rx_t = ::std::option::Option<
|
|
||||||
unsafe extern "C" fn(
|
|
||||||
arg1: *mut fido_dev,
|
|
||||||
arg2: u8,
|
|
||||||
arg3: *mut ::std::os::raw::c_uchar,
|
|
||||||
arg4: usize,
|
|
||||||
arg5: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int,
|
|
||||||
>;
|
|
||||||
pub type fido_dev_tx_t = ::std::option::Option<
|
|
||||||
unsafe extern "C" fn(
|
|
||||||
arg1: *mut fido_dev,
|
|
||||||
arg2: u8,
|
|
||||||
arg3: *const ::std::os::raw::c_uchar,
|
|
||||||
arg4: usize,
|
|
||||||
) -> ::std::os::raw::c_int,
|
|
||||||
>;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_dev_io {
|
|
||||||
pub open: fido_dev_io_open_t,
|
|
||||||
pub close: fido_dev_io_close_t,
|
|
||||||
pub read: fido_dev_io_read_t,
|
|
||||||
pub write: fido_dev_io_write_t,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_fido_dev_io() {
|
|
||||||
const UNINIT: ::std::mem::MaybeUninit<fido_dev_io> = ::std::mem::MaybeUninit::uninit();
|
|
||||||
let ptr = UNINIT.as_ptr();
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<fido_dev_io>(),
|
|
||||||
32usize,
|
|
||||||
concat!("Size of: ", stringify!(fido_dev_io))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<fido_dev_io>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(fido_dev_io))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { ::std::ptr::addr_of!((*ptr).open) as usize - ptr as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Offset of field: ",
|
|
||||||
stringify!(fido_dev_io),
|
|
||||||
"::",
|
|
||||||
stringify!(open)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { ::std::ptr::addr_of!((*ptr).close) as usize - ptr as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Offset of field: ",
|
|
||||||
stringify!(fido_dev_io),
|
|
||||||
"::",
|
|
||||||
stringify!(close)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { ::std::ptr::addr_of!((*ptr).read) as usize - ptr as usize },
|
|
||||||
16usize,
|
|
||||||
concat!(
|
|
||||||
"Offset of field: ",
|
|
||||||
stringify!(fido_dev_io),
|
|
||||||
"::",
|
|
||||||
stringify!(read)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { ::std::ptr::addr_of!((*ptr).write) as usize - ptr as usize },
|
|
||||||
24usize,
|
|
||||||
concat!(
|
|
||||||
"Offset of field: ",
|
|
||||||
stringify!(fido_dev_io),
|
|
||||||
"::",
|
|
||||||
stringify!(write)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
pub type fido_dev_io_t = fido_dev_io;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_dev_transport {
|
|
||||||
pub rx: fido_dev_rx_t,
|
|
||||||
pub tx: fido_dev_tx_t,
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn bindgen_test_layout_fido_dev_transport() {
|
|
||||||
const UNINIT: ::std::mem::MaybeUninit<fido_dev_transport> = ::std::mem::MaybeUninit::uninit();
|
|
||||||
let ptr = UNINIT.as_ptr();
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::size_of::<fido_dev_transport>(),
|
|
||||||
16usize,
|
|
||||||
concat!("Size of: ", stringify!(fido_dev_transport))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
::std::mem::align_of::<fido_dev_transport>(),
|
|
||||||
8usize,
|
|
||||||
concat!("Alignment of ", stringify!(fido_dev_transport))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { ::std::ptr::addr_of!((*ptr).rx) as usize - ptr as usize },
|
|
||||||
0usize,
|
|
||||||
concat!(
|
|
||||||
"Offset of field: ",
|
|
||||||
stringify!(fido_dev_transport),
|
|
||||||
"::",
|
|
||||||
stringify!(rx)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
unsafe { ::std::ptr::addr_of!((*ptr).tx) as usize - ptr as usize },
|
|
||||||
8usize,
|
|
||||||
concat!(
|
|
||||||
"Offset of field: ",
|
|
||||||
stringify!(fido_dev_transport),
|
|
||||||
"::",
|
|
||||||
stringify!(tx)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
pub type fido_dev_transport_t = fido_dev_transport;
|
|
||||||
pub const fido_opt_t_FIDO_OPT_OMIT: fido_opt_t = 0;
|
|
||||||
pub const fido_opt_t_FIDO_OPT_FALSE: fido_opt_t = 1;
|
|
||||||
pub const fido_opt_t_FIDO_OPT_TRUE: fido_opt_t = 2;
|
|
||||||
pub type fido_opt_t = ::std::os::raw::c_int;
|
|
||||||
pub type fido_log_handler_t =
|
|
||||||
::std::option::Option<unsafe extern "C" fn(arg1: *const ::std::os::raw::c_char)>;
|
|
||||||
pub type fido_sigset_t = ::std::os::raw::c_int;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_assert {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type fido_assert_t = fido_assert;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_cbor_info {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type fido_cbor_info_t = fido_cbor_info;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_cred {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type fido_cred_t = fido_cred;
|
|
||||||
pub type fido_dev_t = fido_dev;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct fido_dev_info {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type fido_dev_info_t = fido_dev_info;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct es256_pk {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type es256_pk_t = es256_pk;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct es384_pk {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type es384_pk_t = es384_pk;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct rs256_pk {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type rs256_pk_t = rs256_pk;
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub struct eddsa_pk {
|
|
||||||
_unused: [u8; 0],
|
|
||||||
}
|
|
||||||
pub type eddsa_pk_t = eddsa_pk;
|
|
||||||
extern "C" {
|
|
||||||
pub fn fido_strerr(arg1: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_assert_new() -> *mut fido_assert_t;
|
|
||||||
pub fn fido_cred_new() -> *mut fido_cred_t;
|
|
||||||
pub fn fido_dev_new() -> *mut fido_dev_t;
|
|
||||||
pub fn fido_dev_new_with_info(arg1: *const fido_dev_info_t) -> *mut fido_dev_t;
|
|
||||||
pub fn fido_dev_info_new(arg1: usize) -> *mut fido_dev_info_t;
|
|
||||||
pub fn fido_cbor_info_new() -> *mut fido_cbor_info_t;
|
|
||||||
pub fn fido_dev_io_handle(arg1: *const fido_dev_t) -> *mut ::std::os::raw::c_void;
|
|
||||||
pub fn fido_assert_free(arg1: *mut *mut fido_assert_t);
|
|
||||||
pub fn fido_cbor_info_free(arg1: *mut *mut fido_cbor_info_t);
|
|
||||||
pub fn fido_cred_free(arg1: *mut *mut fido_cred_t);
|
|
||||||
pub fn fido_dev_force_fido2(arg1: *mut fido_dev_t);
|
|
||||||
pub fn fido_dev_force_u2f(arg1: *mut fido_dev_t);
|
|
||||||
pub fn fido_dev_free(arg1: *mut *mut fido_dev_t);
|
|
||||||
pub fn fido_dev_info_free(arg1: *mut *mut fido_dev_info_t, arg2: usize);
|
|
||||||
pub fn fido_init(arg1: ::std::os::raw::c_int);
|
|
||||||
pub fn fido_set_log_handler(arg1: fido_log_handler_t);
|
|
||||||
pub fn fido_assert_authdata_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_clientdata_hash_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_hmac_secret_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_id_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_largeblob_key_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_sig_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_user_id_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_blob_ptr(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cbor_info_certs_name_ptr(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
) -> *mut *mut ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cbor_info_extensions_ptr(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
) -> *mut *mut ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cbor_info_options_name_ptr(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
) -> *mut *mut ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cbor_info_transports_ptr(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
) -> *mut *mut ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cbor_info_versions_ptr(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
) -> *mut *mut ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cbor_info_options_value_ptr(arg1: *const fido_cbor_info_t) -> *const bool;
|
|
||||||
pub fn fido_assert_rp_id(arg1: *const fido_assert_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_assert_user_display_name(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_assert_user_icon(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_assert_user_name(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cbor_info_algorithm_type(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cred_display_name(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cred_fmt(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cred_rp_id(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cred_rp_name(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_cred_user_name(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_dev_info_manufacturer_string(
|
|
||||||
arg1: *const fido_dev_info_t,
|
|
||||||
) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_dev_info_path(arg1: *const fido_dev_info_t) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_dev_info_product_string(
|
|
||||||
arg1: *const fido_dev_info_t,
|
|
||||||
) -> *const ::std::os::raw::c_char;
|
|
||||||
pub fn fido_dev_info_ptr(arg1: *const fido_dev_info_t, arg2: usize) -> *const fido_dev_info_t;
|
|
||||||
pub fn fido_cbor_info_protocols_ptr(arg1: *const fido_cbor_info_t) -> *const u8;
|
|
||||||
pub fn fido_cbor_info_certs_value_ptr(arg1: *const fido_cbor_info_t) -> *const u64;
|
|
||||||
pub fn fido_cbor_info_aaguid_ptr(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_aaguid_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_attstmt_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_authdata_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_authdata_raw_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_clientdata_hash_ptr(
|
|
||||||
arg1: *const fido_cred_t,
|
|
||||||
) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_id_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_largeblob_key_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_pubkey_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_sig_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_user_id_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_cred_x5c_ptr(arg1: *const fido_cred_t) -> *const ::std::os::raw::c_uchar;
|
|
||||||
pub fn fido_assert_allow_cred(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_authdata(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: *const ::std::os::raw::c_uchar,
|
|
||||||
arg4: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_authdata_raw(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: *const ::std::os::raw::c_uchar,
|
|
||||||
arg4: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_clientdata(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_clientdata_hash(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_count(arg1: *mut fido_assert_t, arg2: usize) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_extensions(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_hmac_salt(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_hmac_secret(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: *const ::std::os::raw::c_uchar,
|
|
||||||
arg4: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_options(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: bool,
|
|
||||||
arg3: bool,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_rp(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_up(arg1: *mut fido_assert_t, arg2: fido_opt_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_uv(arg1: *mut fido_assert_t, arg2: fido_opt_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_set_sig(
|
|
||||||
arg1: *mut fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: *const ::std::os::raw::c_uchar,
|
|
||||||
arg4: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_verify(
|
|
||||||
arg1: *const fido_assert_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: ::std::os::raw::c_int,
|
|
||||||
arg4: *const ::std::os::raw::c_void,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cbor_info_algorithm_cose(
|
|
||||||
arg1: *const fido_cbor_info_t,
|
|
||||||
arg2: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_exclude(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_prot(arg1: *const fido_cred_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_attstmt(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_authdata(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_authdata_raw(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_blob(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_clientdata(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_clientdata_hash(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_extensions(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_fmt(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_id(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_options(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: bool,
|
|
||||||
arg3: bool,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_pin_minlen(arg1: *mut fido_cred_t, arg2: usize) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_prot(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_rk(arg1: *mut fido_cred_t, arg2: fido_opt_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_rp(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_char,
|
|
||||||
arg3: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_sig(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_type(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_uv(arg1: *mut fido_cred_t, arg2: fido_opt_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_type(arg1: *const fido_cred_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_user(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
arg4: *const ::std::os::raw::c_char,
|
|
||||||
arg5: *const ::std::os::raw::c_char,
|
|
||||||
arg6: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_set_x509(
|
|
||||||
arg1: *mut fido_cred_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_verify(arg1: *const fido_cred_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_cred_verify_self(arg1: *const fido_cred_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_set_sigmask(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const fido_sigset_t,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_cancel(arg1: *mut fido_dev_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_close(arg1: *mut fido_dev_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_get_assert(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut fido_assert_t,
|
|
||||||
arg3: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_get_cbor_info(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut fido_cbor_info_t,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_get_retry_count(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_get_uv_retry_count(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_get_touch_begin(arg1: *mut fido_dev_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_get_touch_status(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut ::std::os::raw::c_int,
|
|
||||||
arg3: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_info_manifest(
|
|
||||||
arg1: *mut fido_dev_info_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: *mut usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_info_set(
|
|
||||||
arg1: *mut fido_dev_info_t,
|
|
||||||
arg2: usize,
|
|
||||||
arg3: *const ::std::os::raw::c_char,
|
|
||||||
arg4: *const ::std::os::raw::c_char,
|
|
||||||
arg5: *const ::std::os::raw::c_char,
|
|
||||||
arg6: *const fido_dev_io_t,
|
|
||||||
arg7: *const fido_dev_transport_t,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_make_cred(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut fido_cred_t,
|
|
||||||
arg3: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_open_with_info(arg1: *mut fido_dev_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_open(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_reset(arg1: *mut fido_dev_t) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_set_io_functions(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const fido_dev_io_t,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_set_pin(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const ::std::os::raw::c_char,
|
|
||||||
arg3: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_set_transport_functions(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const fido_dev_transport_t,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_set_timeout(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: ::std::os::raw::c_int,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_assert_authdata_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_assert_clientdata_hash_len(arg1: *const fido_assert_t) -> usize;
|
|
||||||
pub fn fido_assert_count(arg1: *const fido_assert_t) -> usize;
|
|
||||||
pub fn fido_assert_hmac_secret_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_assert_id_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_assert_largeblob_key_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_assert_sig_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_assert_user_id_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_assert_blob_len(arg1: *const fido_assert_t, arg2: usize) -> usize;
|
|
||||||
pub fn fido_cbor_info_aaguid_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_algorithm_count(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_certs_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_extensions_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_options_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_protocols_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_transports_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cbor_info_versions_len(arg1: *const fido_cbor_info_t) -> usize;
|
|
||||||
pub fn fido_cred_aaguid_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_attstmt_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_authdata_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_authdata_raw_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_clientdata_hash_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_id_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_largeblob_key_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_pin_minlen(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_pubkey_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_sig_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_user_id_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_cred_x5c_len(arg1: *const fido_cred_t) -> usize;
|
|
||||||
pub fn fido_assert_flags(arg1: *const fido_assert_t, arg2: usize) -> u8;
|
|
||||||
pub fn fido_assert_sigcount(arg1: *const fido_assert_t, arg2: usize) -> u32;
|
|
||||||
pub fn fido_cred_flags(arg1: *const fido_cred_t) -> u8;
|
|
||||||
pub fn fido_cred_sigcount(arg1: *const fido_cred_t) -> u32;
|
|
||||||
pub fn fido_dev_protocol(arg1: *const fido_dev_t) -> u8;
|
|
||||||
pub fn fido_dev_major(arg1: *const fido_dev_t) -> u8;
|
|
||||||
pub fn fido_dev_minor(arg1: *const fido_dev_t) -> u8;
|
|
||||||
pub fn fido_dev_build(arg1: *const fido_dev_t) -> u8;
|
|
||||||
pub fn fido_dev_flags(arg1: *const fido_dev_t) -> u8;
|
|
||||||
pub fn fido_dev_info_vendor(arg1: *const fido_dev_info_t) -> i16;
|
|
||||||
pub fn fido_dev_info_product(arg1: *const fido_dev_info_t) -> i16;
|
|
||||||
pub fn fido_cbor_info_fwversion(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_maxcredbloblen(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_maxcredcntlst(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_maxcredidlen(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_maxlargeblob(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_maxmsgsiz(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_maxrpid_minpinlen(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_minpinlen(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_uv_attempts(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_uv_modality(arg1: *const fido_cbor_info_t) -> u64;
|
|
||||||
pub fn fido_cbor_info_rk_remaining(arg1: *const fido_cbor_info_t) -> i64;
|
|
||||||
pub fn fido_dev_has_pin(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_has_uv(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_is_fido2(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_is_winhello(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_supports_credman(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_supports_cred_prot(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_supports_permissions(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_supports_pin(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_dev_supports_uv(arg1: *const fido_dev_t) -> bool;
|
|
||||||
pub fn fido_cbor_info_new_pin_required(arg1: *const fido_cbor_info_t) -> bool;
|
|
||||||
pub fn fido_dev_largeblob_get(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
arg4: *mut *mut ::std::os::raw::c_uchar,
|
|
||||||
arg5: *mut usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_largeblob_set(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
arg4: *const ::std::os::raw::c_uchar,
|
|
||||||
arg5: usize,
|
|
||||||
arg6: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_largeblob_remove(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
arg4: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_largeblob_get_array(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *mut *mut ::std::os::raw::c_uchar,
|
|
||||||
arg3: *mut usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn fido_dev_largeblob_set_array(
|
|
||||||
arg1: *mut fido_dev_t,
|
|
||||||
arg2: *const ::std::os::raw::c_uchar,
|
|
||||||
arg3: usize,
|
|
||||||
arg4: *const ::std::os::raw::c_char,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn rs256_pk_new() -> *mut rs256_pk_t;
|
|
||||||
pub fn rs256_pk_free(arg1: *mut *mut rs256_pk_t);
|
|
||||||
pub fn rs256_pk_to_EVP_PKEY(arg1: *const rs256_pk_t) -> *mut EVP_PKEY;
|
|
||||||
pub fn rs256_pk_from_EVP_PKEY(
|
|
||||||
arg1: *mut rs256_pk_t,
|
|
||||||
arg2: *const EVP_PKEY,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn rs256_pk_from_RSA(arg1: *mut rs256_pk_t, arg2: *const RSA) -> ::std::os::raw::c_int;
|
|
||||||
pub fn rs256_pk_from_ptr(
|
|
||||||
arg1: *mut rs256_pk_t,
|
|
||||||
arg2: *const ::std::os::raw::c_void,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn es256_pk_new() -> *mut es256_pk_t;
|
|
||||||
pub fn es256_pk_free(arg1: *mut *mut es256_pk_t);
|
|
||||||
pub fn es256_pk_to_EVP_PKEY(arg1: *const es256_pk_t) -> *mut EVP_PKEY;
|
|
||||||
pub fn es256_pk_from_EC_KEY(
|
|
||||||
arg1: *mut es256_pk_t,
|
|
||||||
arg2: *const EC_KEY,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn es256_pk_from_EVP_PKEY(
|
|
||||||
arg1: *mut es256_pk_t,
|
|
||||||
arg2: *const EVP_PKEY,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn es256_pk_from_ptr(
|
|
||||||
arg1: *mut es256_pk_t,
|
|
||||||
arg2: *const ::std::os::raw::c_void,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn es384_pk_new() -> *mut es384_pk_t;
|
|
||||||
pub fn es384_pk_free(arg1: *mut *mut es384_pk_t);
|
|
||||||
pub fn es384_pk_to_EVP_PKEY(arg1: *const es384_pk_t) -> *mut EVP_PKEY;
|
|
||||||
pub fn es384_pk_from_EC_KEY(
|
|
||||||
arg1: *mut es384_pk_t,
|
|
||||||
arg2: *const EC_KEY,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn es384_pk_from_EVP_PKEY(
|
|
||||||
arg1: *mut es384_pk_t,
|
|
||||||
arg2: *const EVP_PKEY,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn es384_pk_from_ptr(
|
|
||||||
arg1: *mut es384_pk_t,
|
|
||||||
arg2: *const ::std::os::raw::c_void,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn eddsa_pk_new() -> *mut eddsa_pk_t;
|
|
||||||
pub fn eddsa_pk_free(arg1: *mut *mut eddsa_pk_t);
|
|
||||||
pub fn eddsa_pk_to_EVP_PKEY(arg1: *const eddsa_pk_t) -> *mut EVP_PKEY;
|
|
||||||
pub fn eddsa_pk_from_EVP_PKEY(
|
|
||||||
arg1: *mut eddsa_pk_t,
|
|
||||||
arg2: *const EVP_PKEY,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
pub fn eddsa_pk_from_ptr(
|
|
||||||
arg1: *mut eddsa_pk_t,
|
|
||||||
arg2: *const ::std::os::raw::c_void,
|
|
||||||
arg3: usize,
|
|
||||||
) -> ::std::os::raw::c_int;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
#[allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
|
||||||
mod ffi;
|
|
||||||
|
|
||||||
pub use ffi::*;
|
|
58
src/main.rs
58
src/main.rs
@ -10,11 +10,12 @@ use anyhow::anyhow;
|
|||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::{Parser, ValueEnum};
|
||||||
use dialoguer::{console, Confirm, Password, Select};
|
use dialoguer::{console, Confirm, Password, Select};
|
||||||
use fido2_rs::{
|
// use fido2_rs::{
|
||||||
credentials::{CoseType, Credential, Opt},
|
// credentials::{CoseType, Credential, Opt},
|
||||||
device::DeviceList,
|
// device::DeviceList,
|
||||||
};
|
// };
|
||||||
use gethostname::gethostname;
|
use gethostname::gethostname;
|
||||||
|
use libfido2::{device::DeviceList, cred::{Credential, CredType, CredProtection}, fido_init};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use ssh_encoding::{Decode, Encode, LineEnding};
|
use ssh_encoding::{Decode, Encode, LineEnding};
|
||||||
use ssh_key::{private, PrivateKey};
|
use ssh_key::{private, PrivateKey};
|
||||||
@ -57,11 +58,11 @@ enum KeyTypeArg {
|
|||||||
EcdsaSk,
|
EcdsaSk,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<KeyTypeArg> for CoseType {
|
impl From<KeyTypeArg> for CredType {
|
||||||
fn from(value: KeyTypeArg) -> Self {
|
fn from(value: KeyTypeArg) -> Self {
|
||||||
match value {
|
match value {
|
||||||
KeyTypeArg::Ed25519Sk => Self::EDDSA,
|
KeyTypeArg::Ed25519Sk => Self::Ed25519,
|
||||||
KeyTypeArg::EcdsaSk => Self::ES256,
|
KeyTypeArg::EcdsaSk => Self::Ecdsa256,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,6 +77,7 @@ impl Display for KeyTypeArg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
|
fido_init(false);
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let privkey_path = Path::new(&args.key_name);
|
let privkey_path = Path::new(&args.key_name);
|
||||||
@ -107,11 +109,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
let mut challenge = [0; 32];
|
let mut challenge = [0; 32];
|
||||||
rand::thread_rng().fill_bytes(&mut challenge);
|
rand::thread_rng().fill_bytes(&mut challenge);
|
||||||
|
|
||||||
// Must be leaked to prevent DeviceList from prematurely freeing memory on drop and allowing
|
let devices = DeviceList::get_list(12)?;
|
||||||
// references to freed memory.
|
|
||||||
// Note: Report unsoundness bug
|
|
||||||
let devices_iter = Box::leak(Box::new(DeviceList::list_devices(12)));
|
|
||||||
let devices = devices_iter.collect::<Vec<_>>();
|
|
||||||
let device = if devices.len() > 1 {
|
let device = if devices.len() > 1 {
|
||||||
Select::new()
|
Select::new()
|
||||||
.with_prompt("Select FIDO2 key")
|
.with_prompt("Select FIDO2 key")
|
||||||
@ -119,11 +117,11 @@ fn main() -> anyhow::Result<()> {
|
|||||||
devices
|
devices
|
||||||
.iter()
|
.iter()
|
||||||
.map(|dev| {
|
.map(|dev| {
|
||||||
let product = dev.product.to_string_lossy();
|
let product = dev.product();
|
||||||
if product.is_empty() {
|
if product.is_empty() {
|
||||||
"Unknown".to_string()
|
"Unknown".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{}", dev.product.to_string_lossy())
|
format!("{}", dev.product())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
@ -134,9 +132,9 @@ fn main() -> anyhow::Result<()> {
|
|||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let device = &devices[device].open()?;
|
let mut device = devices[device].open()?;
|
||||||
|
|
||||||
let device_has_pin = device.info().map_or(false, |info| {
|
let device_has_pin = device.get_info().map_or(false, |info| {
|
||||||
info.options().get("clientPin").copied().unwrap_or(false)
|
info.options().get("clientPin").copied().unwrap_or(false)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -146,19 +144,19 @@ fn main() -> anyhow::Result<()> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut credential = Credential::new();
|
let mut credential = Credential::new()?;
|
||||||
credential.set_client_data(&challenge)?;
|
credential.set_clientdata(&challenge)?;
|
||||||
credential.set_cose_type(args.key_type.into())?;
|
credential.set_type(args.key_type.into())?;
|
||||||
credential.set_rk(Opt::Omit)?;
|
credential.set_rk(None)?;
|
||||||
credential.set_rp("ssh:", "")?;
|
credential.set_rp("ssh:", "")?;
|
||||||
credential.set_user([0; 32], "openssh", Some("openssh"), None)?;
|
credential.set_user([0; 32], "openssh", Some("openssh"), None)?;
|
||||||
|
|
||||||
if args.user_verify {
|
if args.user_verify {
|
||||||
credential.set_protection(fido2_rs::credentials::Protection::UvRequired)?;
|
credential.set_prot(CredProtection::UvRequired)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Touch your authenticator now.");
|
println!("Touch your authenticator now.");
|
||||||
device.make_credential(&mut credential, pin.as_deref())?;
|
device.make_cred(&mut credential, pin.as_deref())?;
|
||||||
|
|
||||||
credential.verify()?;
|
credential.verify()?;
|
||||||
|
|
||||||
@ -169,12 +167,12 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
match args.key_type {
|
match args.key_type {
|
||||||
KeyTypeArg::Ed25519Sk => {
|
KeyTypeArg::Ed25519Sk => {
|
||||||
credential.public_key().encode(&mut privkey_bytes)?;
|
credential.pubkey().encode(&mut privkey_bytes)?;
|
||||||
}
|
}
|
||||||
KeyTypeArg::EcdsaSk => {
|
KeyTypeArg::EcdsaSk => {
|
||||||
p256::EncodedPoint::from_affine_coordinates(
|
p256::EncodedPoint::from_affine_coordinates(
|
||||||
(&credential.public_key()[0..32]).into(),
|
(&credential.pubkey()[0..32]).into(),
|
||||||
(&credential.public_key()[32..64]).into(),
|
(&credential.pubkey()[32..64]).into(),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.to_bytes()
|
.to_bytes()
|
||||||
@ -185,7 +183,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
let mut flags = SshSkFlags::UserPresenceRequired;
|
let mut flags = SshSkFlags::UserPresenceRequired;
|
||||||
flags.set(SshSkFlags::UserVerificationRequired, args.user_verify);
|
flags.set(SshSkFlags::UserVerificationRequired, args.user_verify);
|
||||||
privkey_bytes.push(flags.bits());
|
privkey_bytes.push(flags.bits());
|
||||||
credential.id().encode(&mut privkey_bytes)?;
|
credential.cred_id().encode(&mut privkey_bytes)?;
|
||||||
"".encode(&mut privkey_bytes)?;
|
"".encode(&mut privkey_bytes)?;
|
||||||
let comment = if let Some(comment) = args.comment {
|
let comment = if let Some(comment) = args.comment {
|
||||||
comment
|
comment
|
||||||
@ -220,11 +218,11 @@ fn main() -> anyhow::Result<()> {
|
|||||||
);
|
);
|
||||||
if args.write_attestation {
|
if args.write_attestation {
|
||||||
let mut ssh_attest = Vec::new();
|
let mut ssh_attest = Vec::new();
|
||||||
dbg!(credential.auth_data());
|
dbg!(credential.authdata());
|
||||||
"ssh-sk-attest-v01".encode(&mut ssh_attest)?;
|
"ssh-sk-attest-v01".encode(&mut ssh_attest)?;
|
||||||
credential.certificate().encode(&mut ssh_attest)?;
|
credential.x5c().encode(&mut ssh_attest)?;
|
||||||
credential.signature().encode(&mut ssh_attest)?;
|
credential.sig().encode(&mut ssh_attest)?;
|
||||||
credential.auth_data().encode(&mut ssh_attest)?;
|
credential.authdata().encode(&mut ssh_attest)?;
|
||||||
0u32.encode(&mut ssh_attest)?;
|
0u32.encode(&mut ssh_attest)?;
|
||||||
"".encode(&mut ssh_attest)?;
|
"".encode(&mut ssh_attest)?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user