Switch to libfido2 bindings
This commit is contained in:
parent
6680f4c274
commit
129e3187be
515
Cargo.lock
generated
515
Cargo.lock
generated
@ -2,17 +2,6 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
@ -68,45 +57,6 @@ version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0"
|
||||
dependencies = [
|
||||
"asn1-rs-derive",
|
||||
"asn1-rs-impl",
|
||||
"displaydoc",
|
||||
"nom",
|
||||
"num-traits",
|
||||
"rusticata-macros",
|
||||
"thiserror",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs-derive"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs-impl"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
@ -119,12 +69,6 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
@ -152,15 +96,6 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.13.0"
|
||||
@ -173,15 +108,6 @@ version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cbc"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.82"
|
||||
@ -239,7 +165,7 @@ dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.28",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -304,29 +230,6 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctap-hid-fido2"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3726fa3f7f978ce0a222ea73c13490115f95e7a31db3061d7c4c91bea58ea01a"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"anyhow",
|
||||
"base64",
|
||||
"byteorder",
|
||||
"cbc",
|
||||
"hex",
|
||||
"hidapi",
|
||||
"num",
|
||||
"pad",
|
||||
"ring",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.0"
|
||||
@ -361,15 +264,9 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.28",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.8"
|
||||
@ -377,29 +274,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"pem-rfc7468",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der-parser"
|
||||
version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"displaydoc",
|
||||
"nom",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"rusticata-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929"
|
||||
|
||||
[[package]]
|
||||
name = "dialoguer"
|
||||
version = "0.10.4"
|
||||
@ -424,17 +302,6 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.8"
|
||||
@ -481,6 +348,7 @@ dependencies = [
|
||||
"ff",
|
||||
"generic-array",
|
||||
"group",
|
||||
"pem-rfc7468",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"sec1",
|
||||
@ -537,6 +405,17 @@ version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
|
||||
|
||||
[[package]]
|
||||
name = "fido2-rs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"foreign-types",
|
||||
"libfido2-sys",
|
||||
"openssl",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fido_ssh_maker"
|
||||
version = "0.1.0"
|
||||
@ -544,15 +423,32 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.4.0",
|
||||
"clap",
|
||||
"ctap-hid-fido2",
|
||||
"ctrlc",
|
||||
"dialoguer",
|
||||
"fido2-rs",
|
||||
"gethostname",
|
||||
"p256",
|
||||
"rand",
|
||||
"ssh-encoding",
|
||||
"ssh-key",
|
||||
"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]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@ -596,12 +492,6 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
@ -614,24 +504,6 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hidapi"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "798154e4b6570af74899d71155fb0072d5b17e6aa12f39c8ef22c60fb8ec99e7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
@ -647,7 +519,6 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
@ -662,12 +533,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.64"
|
||||
@ -692,6 +557,16 @@ version = "0.2.147"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "libfido2-sys"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.7"
|
||||
@ -710,18 +585,6 @@ version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.26.2"
|
||||
@ -734,41 +597,6 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.4"
|
||||
@ -786,15 +614,6 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
@ -816,18 +635,6 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.16"
|
||||
@ -838,21 +645,50 @@ dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oid-registry"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p256"
|
||||
version = "0.13.2"
|
||||
@ -877,15 +713,6 @@ dependencies = [
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pad"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.7.0"
|
||||
@ -967,6 +794,7 @@ version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
@ -1009,21 +837,6 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.2"
|
||||
@ -1056,15 +869,6 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusticata-macros"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.8"
|
||||
@ -1078,12 +882,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.3"
|
||||
@ -1104,22 +902,6 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.183"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
|
||||
[[package]]
|
||||
name = "serde_cbor"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
|
||||
dependencies = [
|
||||
"half",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.7"
|
||||
@ -1222,42 +1004,12 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.28"
|
||||
@ -1269,18 +1021,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.0"
|
||||
@ -1311,35 +1051,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1360,24 +1072,18 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
@ -1411,7 +1117,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.28",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -1433,7 +1139,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.28",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -1464,28 +1170,6 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
@ -1618,23 +1302,6 @@ version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
||||
[[package]]
|
||||
name = "x509-parser"
|
||||
version = "0.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"data-encoding",
|
||||
"der-parser",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"oid-registry",
|
||||
"rusticata-macros",
|
||||
"thiserror",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.6.0"
|
||||
|
@ -9,10 +9,12 @@ edition = "2021"
|
||||
anyhow = "1.0.72"
|
||||
bitflags = "2.4.0"
|
||||
clap = { version = "4.3.21", features = ["derive"] }
|
||||
ctap-hid-fido2 = "3.5.0"
|
||||
ctrlc = "3.4.0"
|
||||
dialoguer = "0.10.4"
|
||||
fido2-rs = { version = "0.1.0", path = "fido-rs/fido2-rs" }
|
||||
gethostname = "0.4.3"
|
||||
p256 = "0.13.2"
|
||||
rand = "0.8.5"
|
||||
ssh-encoding = { version = "0.2.0" }
|
||||
ssh-key = { version = "0.6.0", features = ["ed25519"] }
|
||||
whoami = "1.4.1"
|
||||
|
3
fido-rs/.gitignore
vendored
Normal file
3
fido-rs/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.idea
|
||||
target/
|
||||
Cargo.lock
|
2
fido-rs/Cargo.toml
Normal file
2
fido-rs/Cargo.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[workspace]
|
||||
members = ["libfido2-sys", "fido2-rs"]
|
36
fido-rs/README.MD
Normal file
36
fido-rs/README.MD
Normal file
@ -0,0 +1,36 @@
|
||||
# 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`
|
20
fido-rs/fido2-rs/Cargo.toml
Normal file
20
fido-rs/fido2-rs/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
||||
[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"
|
21
fido-rs/fido2-rs/LICENSE
Normal file
21
fido-rs/fido2-rs/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
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.
|
30
fido-rs/fido2-rs/README.MD
Normal file
30
fido-rs/fido2-rs/README.MD
Normal file
@ -0,0 +1,30 @@
|
||||
# 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(())
|
||||
}
|
||||
```
|
465
fido-rs/fido2-rs/src/assertion.rs
Normal file
465
fido-rs/fido2-rs/src/assertion.rs
Normal file
@ -0,0 +1,465 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
195
fido-rs/fido2-rs/src/cbor.rs
Normal file
195
fido-rs/fido2-rs/src/cbor.rs
Normal file
@ -0,0 +1,195 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
578
fido-rs/fido2-rs/src/credentials.rs
Normal file
578
fido-rs/fido2-rs/src/credentials.rs
Normal file
@ -0,0 +1,578 @@
|
||||
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;
|
||||
}
|
||||
}
|
390
fido-rs/fido2-rs/src/device.rs
Normal file
390
fido-rs/fido2-rs/src/device.rs
Normal file
@ -0,0 +1,390 @@
|
||||
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,
|
||||
}
|
51
fido-rs/fido2-rs/src/error.rs
Normal file
51
fido-rs/fido2-rs/src/error.rs
Normal file
@ -0,0 +1,51 @@
|
||||
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 {}
|
85
fido-rs/fido2-rs/src/key.rs
Normal file
85
fido-rs/fido2-rs/src/key.rs
Normal file
@ -0,0 +1,85 @@
|
||||
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;
|
||||
}
|
79
fido-rs/fido2-rs/src/lib.rs
Normal file
79
fido-rs/fido2-rs/src/lib.rs
Normal file
@ -0,0 +1,79 @@
|
||||
//! 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;
|
24
fido-rs/fido2-rs/src/utils.rs
Normal file
24
fido-rs/fido2-rs/src/utils.rs
Normal file
@ -0,0 +1,24 @@
|
||||
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)
|
||||
}
|
||||
};
|
||||
}
|
25
fido-rs/libfido2-sys/Cargo.toml
Normal file
25
fido-rs/libfido2-sys/Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
[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"
|
21
fido-rs/libfido2-sys/LICENSE
Normal file
21
fido-rs/libfido2-sys/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
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.
|
6
fido-rs/libfido2-sys/README.MD
Normal file
6
fido-rs/libfido2-sys/README.MD
Normal file
@ -0,0 +1,6 @@
|
||||
# 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)
|
57
fido-rs/libfido2-sys/build.rs
Normal file
57
fido-rs/libfido2-sys/build.rs
Normal file
@ -0,0 +1,57 @@
|
||||
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(())
|
||||
}
|
5
fido-rs/libfido2-sys/fido2_wrapper.h
Normal file
5
fido-rs/libfido2-sys/fido2_wrapper.h
Normal file
@ -0,0 +1,5 @@
|
||||
#include <fido.h>
|
||||
#include <fido/rs256.h>
|
||||
#include <fido/es256.h>
|
||||
#include <fido/es384.h>
|
||||
#include <fido/eddsa.h>
|
BIN
fido-rs/libfido2-sys/help.txt
Normal file
BIN
fido-rs/libfido2-sys/help.txt
Normal file
Binary file not shown.
856
fido-rs/libfido2-sys/src/ffi.rs
Normal file
856
fido-rs/libfido2-sys/src/ffi.rs
Normal file
@ -0,0 +1,856 @@
|
||||
/* 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;
|
||||
}
|
4
fido-rs/libfido2-sys/src/lib.rs
Normal file
4
fido-rs/libfido2-sys/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#[allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
||||
mod ffi;
|
||||
|
||||
pub use ffi::*;
|
123
src/main.rs
123
src/main.rs
@ -1,7 +1,6 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
fs::Permissions,
|
||||
io::Write,
|
||||
os::unix::prelude::PermissionsExt,
|
||||
path::{Path, PathBuf},
|
||||
process,
|
||||
@ -10,12 +9,13 @@ use std::{
|
||||
use anyhow::anyhow;
|
||||
use bitflags::bitflags;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use ctap_hid_fido2::{
|
||||
fidokey::{CredentialSupportedKeyType, MakeCredentialArgsBuilder},
|
||||
get_fidokey_devices, verifier, FidoKeyHid, LibCfg,
|
||||
};
|
||||
use dialoguer::{console, Confirm, Password, Select};
|
||||
use fido2_rs::{
|
||||
credentials::{CoseType, Credential, Opt},
|
||||
device::DeviceList,
|
||||
};
|
||||
use gethostname::gethostname;
|
||||
use rand::RngCore;
|
||||
use ssh_encoding::{Decode, Encode, LineEnding};
|
||||
use ssh_key::{private, PrivateKey};
|
||||
|
||||
@ -57,11 +57,11 @@ enum KeyTypeArg {
|
||||
EcdsaSk,
|
||||
}
|
||||
|
||||
impl From<KeyTypeArg> for CredentialSupportedKeyType {
|
||||
impl From<KeyTypeArg> for CoseType {
|
||||
fn from(value: KeyTypeArg) -> Self {
|
||||
match value {
|
||||
KeyTypeArg::Ed25519Sk => Self::Ed25519,
|
||||
KeyTypeArg::EcdsaSk => Self::Ecdsa256,
|
||||
KeyTypeArg::Ed25519Sk => Self::EDDSA,
|
||||
KeyTypeArg::EcdsaSk => Self::ES256,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,72 +104,88 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let challenge = verifier::create_challenge();
|
||||
let mut challenge = [0; 32];
|
||||
rand::thread_rng().fill_bytes(&mut challenge);
|
||||
|
||||
let devices = get_fidokey_devices();
|
||||
// Must be leaked to prevent DeviceList from prematurely freeing memory on drop and allowing
|
||||
// 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 idx = Select::new()
|
||||
Select::new()
|
||||
.with_prompt("Select FIDO2 key")
|
||||
.items(
|
||||
devices
|
||||
.iter()
|
||||
.map(|dev| format!("{}", dev.product_string))
|
||||
.map(|dev| {
|
||||
let product = dev.product.to_string_lossy();
|
||||
if product.is_empty() {
|
||||
"Unknown".to_string()
|
||||
} else {
|
||||
format!("{}", dev.product.to_string_lossy())
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
)
|
||||
.default(0)
|
||||
.interact()?;
|
||||
&devices[idx]
|
||||
.interact()?
|
||||
} else {
|
||||
&devices[0]
|
||||
0
|
||||
};
|
||||
let device = &devices[device].open()?;
|
||||
|
||||
let mut libcfg = LibCfg::init();
|
||||
libcfg.keep_alive_msg = "Touch the authenticator now.".into();
|
||||
let device = FidoKeyHid::new(&[device.param.clone()], &libcfg)?;
|
||||
let device_has_pin = device.get_info().map_or(false, |info| {
|
||||
info.options.contains(&("clientPin".into(), true))
|
||||
let device_has_pin = device.info().map_or(false, |info| {
|
||||
info.options().get("clientPin").copied().unwrap_or(false)
|
||||
});
|
||||
|
||||
let pin = if device_has_pin {
|
||||
Password::new()
|
||||
.with_prompt("FIDO2 PIN")
|
||||
.report(false)
|
||||
.interact()?
|
||||
Some(Password::new().with_prompt("FIDO2 PIN").interact()?)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let make_credential_args = if device_has_pin {
|
||||
MakeCredentialArgsBuilder::new("ssh:", &challenge)
|
||||
.pin(&pin)
|
||||
.key_type(args.key_type.into())
|
||||
.build()
|
||||
} else {
|
||||
MakeCredentialArgsBuilder::new("ssh:", &challenge)
|
||||
.without_pin_and_uv()
|
||||
.key_type(args.key_type.into())
|
||||
.build()
|
||||
None
|
||||
};
|
||||
|
||||
let attestation = device.make_credential_with_args(&make_credential_args)?;
|
||||
let verify_result = verifier::verify_attestation("ssh:", &challenge, &attestation);
|
||||
if !verify_result.is_success {
|
||||
return Err(anyhow!("Failed to verify attestation"));
|
||||
let mut credential = Credential::new();
|
||||
credential.set_client_data(&challenge)?;
|
||||
credential.set_cose_type(args.key_type.into())?;
|
||||
credential.set_rk(Opt::Omit)?;
|
||||
credential.set_rp("ssh:", "")?;
|
||||
credential.set_user([0; 32], "openssh", Some("openssh"), None)?;
|
||||
|
||||
if args.user_verify {
|
||||
credential.set_protection(fido2_rs::credentials::Protection::UvRequired)?;
|
||||
}
|
||||
|
||||
println!("Touch your authenticator now.");
|
||||
device.make_credential(&mut credential, pin.as_deref())?;
|
||||
|
||||
credential.verify()?;
|
||||
|
||||
let mut privkey_bytes = Vec::new();
|
||||
if args.key_type == KeyTypeArg::EcdsaSk {
|
||||
"nistp256".encode(&mut privkey_bytes)?;
|
||||
}
|
||||
verify_result
|
||||
.credential_public_key
|
||||
.der
|
||||
.encode(&mut privkey_bytes)?;
|
||||
|
||||
match args.key_type {
|
||||
KeyTypeArg::Ed25519Sk => {
|
||||
credential.public_key().encode(&mut privkey_bytes)?;
|
||||
}
|
||||
KeyTypeArg::EcdsaSk => {
|
||||
p256::EncodedPoint::from_affine_coordinates(
|
||||
(&credential.public_key()[0..32]).into(),
|
||||
(&credential.public_key()[32..64]).into(),
|
||||
false,
|
||||
)
|
||||
.to_bytes()
|
||||
.encode(&mut privkey_bytes)?;
|
||||
}
|
||||
}
|
||||
"ssh:".encode(&mut privkey_bytes)?;
|
||||
let mut flags = SshSkFlags::UserPresenceRequired;
|
||||
flags.set(SshSkFlags::UserVerificationRequired, args.user_verify);
|
||||
privkey_bytes.push(flags.bits());
|
||||
verify_result.credential_id.encode(&mut privkey_bytes)?;
|
||||
credential.id().encode(&mut privkey_bytes)?;
|
||||
"".encode(&mut privkey_bytes)?;
|
||||
let comment = if let Some(comment) = args.comment {
|
||||
comment
|
||||
@ -191,14 +207,6 @@ fn main() -> anyhow::Result<()> {
|
||||
)?,
|
||||
};
|
||||
|
||||
let mut ssh_attest = Vec::new();
|
||||
"ssh-sk-attest-v01".encode(&mut ssh_attest)?;
|
||||
attestation.attstmt_x5c[0].encode(&mut ssh_attest)?;
|
||||
attestation.attstmt_sig.encode(&mut ssh_attest)?;
|
||||
attestation.auth_data.encode(&mut ssh_attest)?;
|
||||
0u32.encode(&mut ssh_attest)?;
|
||||
"".encode(&mut ssh_attest)?;
|
||||
|
||||
std::fs::write(&privkey_path, &*privkey.to_openssh(LineEnding::default())?)?;
|
||||
std::fs::set_permissions(&privkey_path, Permissions::from_mode(0o600))?;
|
||||
println!(
|
||||
@ -211,6 +219,15 @@ fn main() -> anyhow::Result<()> {
|
||||
pubkey_path.to_string_lossy()
|
||||
);
|
||||
if args.write_attestation {
|
||||
let mut ssh_attest = Vec::new();
|
||||
dbg!(credential.auth_data());
|
||||
"ssh-sk-attest-v01".encode(&mut ssh_attest)?;
|
||||
credential.certificate().encode(&mut ssh_attest)?;
|
||||
credential.signature().encode(&mut ssh_attest)?;
|
||||
credential.auth_data().encode(&mut ssh_attest)?;
|
||||
0u32.encode(&mut ssh_attest)?;
|
||||
"".encode(&mut ssh_attest)?;
|
||||
|
||||
std::fs::write(&attest_info_path, &ssh_attest)?;
|
||||
println!(
|
||||
"Your FIDO attestation certificate has been saved in {}",
|
||||
|
Loading…
Reference in New Issue
Block a user