Compare commits
13 Commits
pin_source
...
0.2.15
Author | SHA1 | Date | |
---|---|---|---|
a66fdb0edd
|
|||
0ec859f4a6
|
|||
55bae4161e
|
|||
086c1a0594
|
|||
c2e38eb06f
|
|||
03ef5721e0
|
|||
008e644024
|
|||
e1f762ddc9
|
|||
![]() |
2266754a95 | ||
8811cff6d1
|
|||
99787b614c
|
|||
ee28f87148
|
|||
196356fe3b
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,3 +2,7 @@
|
|||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
.idea/
|
.idea/
|
||||||
*.iml
|
*.iml
|
||||||
|
fido2luks.bash
|
||||||
|
fido2luks.elv
|
||||||
|
fido2luks.fish
|
||||||
|
fido2luks.zsh
|
113
Cargo.lock
generated
113
Cargo.lock
generated
@@ -52,9 +52,9 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
@@ -72,9 +72,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bindgen"
|
name = "bindgen"
|
||||||
version = "0.54.1"
|
version = "0.54.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4d49b80beb70d76cdac92f5681e666f9a697c737c4f4117a67229a0386dc736"
|
checksum = "66c0bb6167449588ff70803f4127f0684f9063097eca5016f37eb52b92c2cf36"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cexpr",
|
"cexpr",
|
||||||
@@ -86,7 +86,7 @@ dependencies = [
|
|||||||
"lazycell",
|
"lazycell",
|
||||||
"log",
|
"log",
|
||||||
"peeking_take_while",
|
"peeking_take_while",
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
@@ -118,9 +118,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.58"
|
version = "1.0.59"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
|
checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cexpr"
|
name = "cexpr"
|
||||||
@@ -150,9 +150,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "2.33.2"
|
version = "2.33.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "10040cdf04294b565d9e0319955430099ec3813a64c952b86a41200ad714ae48"
|
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"atty",
|
"atty",
|
||||||
@@ -188,12 +188,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ee0cc8804d5393478d743b035099520087a5186f3b93fa58cec08fa62407b6"
|
checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
|
"maybe-uninit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -213,7 +213,7 @@ version = "0.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
|
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -239,7 +239,7 @@ version = "0.7.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
@@ -292,10 +292,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"fnv",
|
||||||
"ident_case",
|
"ident_case",
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"strsim 0.9.3",
|
"strsim 0.9.3",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -306,7 +306,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -317,9 +317,9 @@ checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"derive_builder_core",
|
"derive_builder_core",
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -329,9 +329,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
|
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -369,15 +369,15 @@ version = "0.1.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
"synstructure",
|
"synstructure",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fido2luks"
|
name = "fido2luks"
|
||||||
version = "0.2.11"
|
version = "0.2.15"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ctap_hmac",
|
"ctap_hmac",
|
||||||
"failure",
|
"failure",
|
||||||
@@ -474,15 +474,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazycell"
|
name = "lazycell"
|
||||||
version = "1.2.1"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.74"
|
version = "0.2.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcryptsetup-rs"
|
name = "libcryptsetup-rs"
|
||||||
@@ -548,14 +548,14 @@ version = "0.5.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f"
|
checksum = "c198b026e1bbf08a937e94c6c60f9ec4a2267f5b0d2eec9c1b21b061ce2be55f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f"
|
checksum = "4d7559a8a40d0f97e1edea3220f698f78b1c5ab67532e49f68fde3910323b722"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
@@ -587,7 +587,7 @@ version = "0.2.12"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg 1.0.0",
|
"autocfg 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -615,9 +615,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error-attr",
|
"proc-macro-error-attr",
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -627,7 +627,7 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
@@ -643,9 +643,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
|
checksum = "175c513d55719db99da20232b06cda8bab6b83ec2d04e3283edf0213c37c1a29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
@@ -671,7 +671,7 @@ version = "1.0.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -922,9 +922,9 @@ version = "1.0.115"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
|
checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -958,9 +958,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt"
|
name = "structopt"
|
||||||
version = "0.3.16"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de5472fb24d7e80ae84a7801b7978f95a19ec32cb1876faea59ab711eb901976"
|
checksum = "6cc388d94ffabf39b5ed5fadddc40147cb21e605f53db6f8f36a625d27489ac5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@@ -969,15 +969,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structopt-derive"
|
name = "structopt-derive"
|
||||||
version = "0.4.9"
|
version = "0.4.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e0eb37335aeeebe51be42e2dc07f031163fbabfa6ac67d7ea68b5c2f68d5f99"
|
checksum = "5e2513111825077552a6751dfad9e11ce0fba07d7276a3943a037d7e93e64c5f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -993,11 +993,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.38"
|
version = "1.0.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
|
checksum = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
@@ -1008,9 +1008,9 @@ version = "0.12.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.19",
|
"proc-macro2 1.0.20",
|
||||||
"quote 1.0.7",
|
"quote 1.0.7",
|
||||||
"syn 1.0.38",
|
"syn 1.0.40",
|
||||||
"unicode-xid 0.2.1",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1043,11 +1043,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
|
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"wasi",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1102,6 +1103,12 @@ version = "0.9.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
version = "3.1.1"
|
version = "3.1.1"
|
||||||
|
12
Cargo.toml
12
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fido2luks"
|
name = "fido2luks"
|
||||||
version = "0.2.11"
|
version = "0.2.15"
|
||||||
authors = ["shimunn <shimun@shimun.net>"]
|
authors = ["shimunn <shimun@shimun.net>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -25,6 +25,15 @@ serde_json = "1.0.51"
|
|||||||
serde_derive = "1.0.106"
|
serde_derive = "1.0.106"
|
||||||
serde = "1.0.106"
|
serde = "1.0.106"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
ctap_hmac = { version="0.4.2", features = ["request_multiple"] }
|
||||||
|
hex = "0.3.2"
|
||||||
|
ring = "0.13.5"
|
||||||
|
failure = "0.1.5"
|
||||||
|
rpassword = "4.0.1"
|
||||||
|
libcryptsetup-rs = "0.4.1"
|
||||||
|
structopt = "0.3.2"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
@@ -38,6 +47,7 @@ build-depends = "libclang-dev, libcryptsetup-dev"
|
|||||||
extended-description = "Decrypt your LUKS partition using a FIDO2 compatible authenticator"
|
extended-description = "Decrypt your LUKS partition using a FIDO2 compatible authenticator"
|
||||||
assets = [
|
assets = [
|
||||||
["target/release/fido2luks", "usr/bin/", "755"],
|
["target/release/fido2luks", "usr/bin/", "755"],
|
||||||
|
["fido2luks.bash", "usr/share/bash-completion/completions/fido2luks", "644"],
|
||||||
["initramfs-tools/keyscript.sh", "/lib/cryptsetup/scripts/fido2luks", "755" ],
|
["initramfs-tools/keyscript.sh", "/lib/cryptsetup/scripts/fido2luks", "755" ],
|
||||||
["initramfs-tools/hook/fido2luks.sh", "etc/initramfs-tools/hooks/", "755" ],
|
["initramfs-tools/hook/fido2luks.sh", "etc/initramfs-tools/hooks/", "755" ],
|
||||||
["initramfs-tools/fido2luks.conf", "etc/", "644"],
|
["initramfs-tools/fido2luks.conf", "etc/", "644"],
|
||||||
|
25
PKGBUILD
Normal file
25
PKGBUILD
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Maintainer: shimunn <shimun@shimun.net>
|
||||||
|
pkgname=fido2luks
|
||||||
|
pkgver=0.2.12
|
||||||
|
pkgrel=1
|
||||||
|
makedepends=('rust' 'cargo' 'cryptsetup' 'clang')
|
||||||
|
depends=('cryptsetup')
|
||||||
|
arch=('i686' 'x86_64' 'armv6h' 'armv7h')
|
||||||
|
pkgdesc="Decrypt your LUKS partition using a FIDO2 compatible authenticator"
|
||||||
|
url="https://github.com/shimunn/fido2luks"
|
||||||
|
license=('MPL-2.0')
|
||||||
|
|
||||||
|
pkgver() {
|
||||||
|
# Use tag version if possible otherwise concat project version and git ref
|
||||||
|
git describe --exact-match --tags HEAD 2> /dev/null || \
|
||||||
|
echo "$(cargo pkgid | cut -d'#' -f2).$(git describe --always)"
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
cargo build --release --locked --all-features --target-dir=target
|
||||||
|
}
|
||||||
|
|
||||||
|
package() {
|
||||||
|
install -Dm 755 target/release/${pkgname} -t "${pkgdir}/usr/bin"
|
||||||
|
install -Dm 644 ../fido2luks.bash "${pkgdir}/usr/share/bash-completion/completions/fido2luks"
|
||||||
|
}
|
24
build.rs
Normal file
24
build.rs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#![allow(warnings)]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure;
|
||||||
|
extern crate ctap_hmac as ctap;
|
||||||
|
|
||||||
|
#[path = "src/cli_args/mod.rs"]
|
||||||
|
mod cli_args;
|
||||||
|
#[path = "src/error.rs"]
|
||||||
|
mod error;
|
||||||
|
#[path = "src/util.rs"]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
use cli_args::Args;
|
||||||
|
use std::env;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use structopt::clap::Shell;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// generate completion scripts, zsh does panic for some reason
|
||||||
|
for shell in Shell::variants().iter().filter(|shell| **shell != "zsh") {
|
||||||
|
Args::clap().gen_completions(env!("CARGO_PKG_NAME"), Shell::from_str(shell).unwrap(), ".");
|
||||||
|
}
|
||||||
|
}
|
@@ -7,4 +7,8 @@ if [ -z "$FIDO2LUKS_PASSWORD_HELPER" ]; then
|
|||||||
export FIDO2LUKS_PASSWORD_HELPER="plymouth ask-for-password --prompt '$MSG'"
|
export FIDO2LUKS_PASSWORD_HELPER="plymouth ask-for-password --prompt '$MSG'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$FIDO2LUKS_USE_TOKEN" -eq 1 ]; then
|
||||||
|
export FIDO2LUKS_CREDENTIAL_ID="$FIDO2LUKS_CREDENTIAL_ID,$(fido2luks token list --csv $CRYPTTAB_SOURCE)"
|
||||||
|
fi
|
||||||
|
|
||||||
fido2luks print-secret --bin
|
fido2luks print-secret --bin
|
||||||
|
328
src/cli.rs
328
src/cli.rs
@@ -1,150 +1,35 @@
|
|||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
|
use crate::luks::{Fido2LuksToken, LuksDevice};
|
||||||
|
use crate::util::sha256;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
use cli_args::*;
|
||||||
|
|
||||||
|
use structopt::clap::Shell;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use ctap::{FidoCredential, FidoErrorKind};
|
use ctap::{FidoCredential, FidoErrorKind};
|
||||||
use failure::_core::fmt::{Display, Error, Formatter};
|
|
||||||
use failure::_core::str::FromStr;
|
|
||||||
use failure::_core::time::Duration;
|
|
||||||
use std::io::{Read, Write};
|
|
||||||
use std::process::exit;
|
|
||||||
use std::thread;
|
|
||||||
|
|
||||||
use crate::luks::{Fido2LuksToken, LuksDevice};
|
use std::io::{Read, Write};
|
||||||
use crate::util::sha256;
|
use std::str::FromStr;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
pub use cli_args::Args;
|
||||||
pub struct HexEncoded(pub Vec<u8>);
|
|
||||||
|
|
||||||
impl Display for HexEncoded {
|
fn read_pin(ap: &AuthenticatorParameters) -> Fido2LuksResult<String> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
if let Some(src) = ap.pin_source.as_ref() {
|
||||||
f.write_str(&hex::encode(&self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<[u8]> for HexEncoded {
|
|
||||||
fn as_ref(&self) -> &[u8] {
|
|
||||||
&self.0[..]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for HexEncoded {
|
|
||||||
type Err = hex::FromHexError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
Ok(HexEncoded(hex::decode(s)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
|
||||||
pub struct CommaSeparated<T: FromStr + Display>(pub Vec<T>);
|
|
||||||
|
|
||||||
impl<T: Display + FromStr> Display for CommaSeparated<T> {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
|
||||||
for i in &self.0 {
|
|
||||||
f.write_str(&i.to_string())?;
|
|
||||||
f.write_str(",")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Display + FromStr> FromStr for CommaSeparated<T> {
|
|
||||||
type Err = <T as FromStr>::Err;
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
Ok(CommaSeparated(
|
|
||||||
s.split(',')
|
|
||||||
.map(|part| <T as FromStr>::from_str(part))
|
|
||||||
.collect::<Result<Vec<_>, _>>()?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub struct Credentials {
|
|
||||||
/// FIDO credential ids, separated by ',' generate using fido2luks credential
|
|
||||||
#[structopt(name = "credential-id", env = "FIDO2LUKS_CREDENTIAL_ID")]
|
|
||||||
pub ids: CommaSeparated<HexEncoded>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub struct AuthenticatorParameters {
|
|
||||||
/// Request a PIN to unlock the authenticator
|
|
||||||
#[structopt(short = "P", long = "pin", env = "FIDO2LUKS_PIN")]
|
|
||||||
pub pin: bool,
|
|
||||||
|
|
||||||
/// Location to read PIN from
|
|
||||||
#[structopt(long = "pin-source", env = "FIDO2LUKS_PIN_SOURCE")]
|
|
||||||
pub pin_source: Option<PathBuf>,
|
|
||||||
|
|
||||||
/// Await for an authenticator to be connected, timeout after n seconds
|
|
||||||
#[structopt(
|
|
||||||
long = "await-dev",
|
|
||||||
name = "await-dev",
|
|
||||||
env = "FIDO2LUKS_DEVICE_AWAIT",
|
|
||||||
default_value = "15"
|
|
||||||
)]
|
|
||||||
pub await_time: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AuthenticatorParameters {
|
|
||||||
fn read_pin(&self) -> Fido2LuksResult<String> {
|
|
||||||
if let Some(src) = self.pin_source.as_ref() {
|
|
||||||
let mut pin = String::new();
|
let mut pin = String::new();
|
||||||
File::open(src)?.read_to_string(&mut pin)?;
|
File::open(src)?.read_to_string(&mut pin)?;
|
||||||
Ok(pin)
|
Ok(pin.trim_end_matches("\n").to_string()) //remove trailing newline
|
||||||
} else {
|
} else {
|
||||||
util::read_password("Authenticator PIN", false)
|
util::read_password("Authenticator PIN", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub struct LuksParameters {
|
|
||||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
|
||||||
device: PathBuf,
|
|
||||||
|
|
||||||
/// Try to unlock the device using a specifc keyslot, ignore all other slots
|
|
||||||
#[structopt(long = "slot", env = "FIDO2LUKS_DEVICE_SLOT")]
|
|
||||||
slot: Option<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt, Clone)]
|
|
||||||
pub struct LuksModParameters {
|
|
||||||
/// Number of milliseconds required to derive the volume decryption key
|
|
||||||
/// Defaults to 10ms when using an authenticator or the default by cryptsetup when using a password
|
|
||||||
#[structopt(long = "kdf-time", name = "kdf-time")]
|
|
||||||
kdf_time: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub struct SecretParameters {
|
|
||||||
/// Salt for secret generation, defaults to 'ask'
|
|
||||||
///
|
|
||||||
/// Options:{n}
|
|
||||||
/// - ask : Prompt user using password helper{n}
|
|
||||||
/// - file:<PATH> : Will read <FILE>{n}
|
|
||||||
/// - string:<STRING> : Will use <STRING>, which will be handled like a password provided to the 'ask' option{n}
|
|
||||||
#[structopt(
|
|
||||||
name = "salt",
|
|
||||||
long = "salt",
|
|
||||||
env = "FIDO2LUKS_SALT",
|
|
||||||
default_value = "ask"
|
|
||||||
)]
|
|
||||||
pub salt: InputSalt,
|
|
||||||
/// Script used to obtain passwords, overridden by --interactive flag
|
|
||||||
#[structopt(
|
|
||||||
name = "password-helper",
|
|
||||||
env = "FIDO2LUKS_PASSWORD_HELPER",
|
|
||||||
default_value = "/usr/bin/env systemd-ask-password 'Please enter second factor for LUKS disk encryption!'"
|
|
||||||
)]
|
|
||||||
pub password_helper: PasswordHelper,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn derive_secret(
|
fn derive_secret(
|
||||||
credentials: &[HexEncoded],
|
credentials: &[HexEncoded],
|
||||||
@@ -182,167 +67,6 @@ fn derive_secret(
|
|||||||
Ok((sha256(&[salt, &unsalted[..]]), cred.clone()))
|
Ok((sha256(&[salt, &unsalted[..]]), cred.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub struct Args {
|
|
||||||
/// Request passwords via Stdin instead of using the password helper
|
|
||||||
#[structopt(short = "i", long = "interactive")]
|
|
||||||
pub interactive: bool,
|
|
||||||
#[structopt(subcommand)]
|
|
||||||
pub command: Command,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt, Clone)]
|
|
||||||
pub struct OtherSecret {
|
|
||||||
/// Use a keyfile instead of a password
|
|
||||||
#[structopt(short = "d", long = "keyfile", conflicts_with = "fido_device")]
|
|
||||||
keyfile: Option<PathBuf>,
|
|
||||||
/// Use another fido device instead of a password
|
|
||||||
/// Note: this requires for the credential fot the other device to be passed as argument as well
|
|
||||||
#[structopt(short = "f", long = "fido-device", conflicts_with = "keyfile")]
|
|
||||||
fido_device: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub enum Command {
|
|
||||||
#[structopt(name = "print-secret")]
|
|
||||||
PrintSecret {
|
|
||||||
/// Prints the secret as binary instead of hex encoded
|
|
||||||
#[structopt(short = "b", long = "bin")]
|
|
||||||
binary: bool,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
credentials: Credentials,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
authenticator: AuthenticatorParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
secret: SecretParameters,
|
|
||||||
},
|
|
||||||
/// Adds a generated key to the specified LUKS device
|
|
||||||
#[structopt(name = "add-key")]
|
|
||||||
AddKey {
|
|
||||||
#[structopt(flatten)]
|
|
||||||
luks: LuksParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
credentials: Credentials,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
authenticator: AuthenticatorParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
secret: SecretParameters,
|
|
||||||
/// Will wipe all other keys
|
|
||||||
#[structopt(short = "e", long = "exclusive")]
|
|
||||||
exclusive: bool,
|
|
||||||
/// Will add an token to your LUKS 2 header, including the credential id
|
|
||||||
#[structopt(short = "t", long = "token")]
|
|
||||||
token: bool,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
existing_secret: OtherSecret,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
luks_mod: LuksModParameters,
|
|
||||||
},
|
|
||||||
/// Replace a previously added key with a password
|
|
||||||
#[structopt(name = "replace-key")]
|
|
||||||
ReplaceKey {
|
|
||||||
#[structopt(flatten)]
|
|
||||||
luks: LuksParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
credentials: Credentials,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
authenticator: AuthenticatorParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
secret: SecretParameters,
|
|
||||||
/// Add the password and keep the key
|
|
||||||
#[structopt(short = "a", long = "add-password")]
|
|
||||||
add_password: bool,
|
|
||||||
/// Will add an token to your LUKS 2 header, including the credential id
|
|
||||||
#[structopt(short = "t", long = "token")]
|
|
||||||
token: bool,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
replacement: OtherSecret,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
luks_mod: LuksModParameters,
|
|
||||||
},
|
|
||||||
/// Open the LUKS device
|
|
||||||
#[structopt(name = "open")]
|
|
||||||
Open {
|
|
||||||
#[structopt(flatten)]
|
|
||||||
luks: LuksParameters,
|
|
||||||
#[structopt(env = "FIDO2LUKS_MAPPER_NAME")]
|
|
||||||
name: String,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
credentials: Credentials,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
authenticator: AuthenticatorParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
secret: SecretParameters,
|
|
||||||
#[structopt(short = "r", long = "max-retries", default_value = "0")]
|
|
||||||
retries: i32,
|
|
||||||
},
|
|
||||||
/// Open the LUKS device using credentials embedded in the LUKS 2 header
|
|
||||||
#[structopt(name = "open-token")]
|
|
||||||
OpenToken {
|
|
||||||
#[structopt(flatten)]
|
|
||||||
luks: LuksParameters,
|
|
||||||
#[structopt(env = "FIDO2LUKS_MAPPER_NAME")]
|
|
||||||
name: String,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
authenticator: AuthenticatorParameters,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
secret: SecretParameters,
|
|
||||||
#[structopt(short = "r", long = "max-retries", default_value = "0")]
|
|
||||||
retries: i32,
|
|
||||||
},
|
|
||||||
/// Generate a new FIDO credential
|
|
||||||
#[structopt(name = "credential")]
|
|
||||||
Credential {
|
|
||||||
#[structopt(flatten)]
|
|
||||||
authenticator: AuthenticatorParameters,
|
|
||||||
/// Name to be displayed on the authenticator if it has a display
|
|
||||||
#[structopt(env = "FIDO2LUKS_CREDENTIAL_NAME")]
|
|
||||||
name: Option<String>,
|
|
||||||
},
|
|
||||||
/// Check if an authenticator is connected
|
|
||||||
#[structopt(name = "connected")]
|
|
||||||
Connected,
|
|
||||||
Token(TokenCommand),
|
|
||||||
}
|
|
||||||
|
|
||||||
///LUKS2 token related operations
|
|
||||||
#[derive(Debug, StructOpt)]
|
|
||||||
pub enum TokenCommand {
|
|
||||||
/// List all tokens associated with the specified device
|
|
||||||
List {
|
|
||||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
|
||||||
device: PathBuf,
|
|
||||||
/// Dump all credentials as CSV
|
|
||||||
#[structopt(long = "csv")]
|
|
||||||
csv: bool,
|
|
||||||
},
|
|
||||||
/// Add credential to a keyslot
|
|
||||||
Add {
|
|
||||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
|
||||||
device: PathBuf,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
credentials: Credentials,
|
|
||||||
/// Slot to which the credentials will be added
|
|
||||||
#[structopt(long = "slot", env = "FIDO2LUKS_DEVICE_SLOT")]
|
|
||||||
slot: u32,
|
|
||||||
},
|
|
||||||
/// Remove credentials from token(s)
|
|
||||||
Remove {
|
|
||||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
|
||||||
device: PathBuf,
|
|
||||||
#[structopt(flatten)]
|
|
||||||
credentials: Credentials,
|
|
||||||
/// Token from which the credentials will be removed
|
|
||||||
#[structopt(long = "token")]
|
|
||||||
token_id: Option<u32>,
|
|
||||||
},
|
|
||||||
/// Remove all unassigned tokens
|
|
||||||
GC {
|
|
||||||
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
|
||||||
device: PathBuf,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_cmdline() -> Args {
|
pub fn parse_cmdline() -> Args {
|
||||||
Args::from_args()
|
Args::from_args()
|
||||||
}
|
}
|
||||||
@@ -358,7 +82,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
} => {
|
} => {
|
||||||
let pin_string;
|
let pin_string;
|
||||||
let pin = if authenticator.pin {
|
let pin = if authenticator.pin {
|
||||||
pin_string = authenticator.read_pin()?;
|
pin_string = read_pin(authenticator)?;
|
||||||
Some(pin_string.as_ref())
|
Some(pin_string.as_ref())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -375,7 +99,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
} => {
|
} => {
|
||||||
let pin_string;
|
let pin_string;
|
||||||
let pin = if authenticator.pin {
|
let pin = if authenticator.pin {
|
||||||
pin_string = authenticator.read_pin()?;
|
pin_string = read_pin(authenticator)?;
|
||||||
Some(pin_string.as_ref())
|
Some(pin_string.as_ref())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -383,7 +107,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
let salt = if interactive || secret.password_helper == PasswordHelper::Stdin {
|
let salt = if interactive || secret.password_helper == PasswordHelper::Stdin {
|
||||||
util::read_password_hashed("Password", false)
|
util::read_password_hashed("Password", false)
|
||||||
} else {
|
} else {
|
||||||
secret.salt.obtain(&secret.password_helper)
|
secret.salt.obtain_sha256(&secret.password_helper)
|
||||||
}?;
|
}?;
|
||||||
let (secret, _cred) = derive_secret(
|
let (secret, _cred) = derive_secret(
|
||||||
credentials.ids.0.as_slice(),
|
credentials.ids.0.as_slice(),
|
||||||
@@ -419,7 +143,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let pin = if authenticator.pin {
|
let pin = if authenticator.pin {
|
||||||
Some(authenticator.read_pin()?)
|
Some(read_pin(authenticator)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -427,7 +151,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
if interactive || secret.password_helper == PasswordHelper::Stdin {
|
if interactive || secret.password_helper == PasswordHelper::Stdin {
|
||||||
util::read_password_hashed(q, verify)
|
util::read_password_hashed(q, verify)
|
||||||
} else {
|
} else {
|
||||||
secret.salt.obtain(&secret.password_helper)
|
secret.salt.obtain_sha256(&secret.password_helper)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let other_secret = |salt_q: &str,
|
let other_secret = |salt_q: &str,
|
||||||
@@ -535,7 +259,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
} => {
|
} => {
|
||||||
let pin_string;
|
let pin_string;
|
||||||
let pin = if authenticator.pin {
|
let pin = if authenticator.pin {
|
||||||
pin_string = authenticator.read_pin()?;
|
pin_string = read_pin(authenticator)?;
|
||||||
Some(pin_string.as_ref())
|
Some(pin_string.as_ref())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -544,7 +268,7 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
if interactive || secret.password_helper == PasswordHelper::Stdin {
|
if interactive || secret.password_helper == PasswordHelper::Stdin {
|
||||||
util::read_password_hashed(q, verify)
|
util::read_password_hashed(q, verify)
|
||||||
} else {
|
} else {
|
||||||
secret.salt.obtain(&secret.password_helper)
|
secret.salt.obtain_sha256(&secret.password_helper)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -725,5 +449,17 @@ pub fn run_cli() -> Fido2LuksResult<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Command::GenerateCompletions { shell, out_dir } => {
|
||||||
|
Args::clap().gen_completions(
|
||||||
|
env!("CARGO_PKG_NAME"),
|
||||||
|
match shell.as_ref() {
|
||||||
|
"bash" => Shell::Bash,
|
||||||
|
"fish" => Shell::Fish,
|
||||||
|
_ => unreachable!("structopt shouldn't allow us to reach this point"),
|
||||||
|
},
|
||||||
|
&out_dir,
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,33 +10,33 @@ use std::process::Command;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum InputSalt {
|
pub enum SecretInput {
|
||||||
AskPassword,
|
AskPassword,
|
||||||
String(String),
|
String(String),
|
||||||
File { path: PathBuf },
|
File { path: PathBuf },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for InputSalt {
|
impl Default for SecretInput {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
InputSalt::AskPassword
|
SecretInput::AskPassword
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for InputSalt {
|
impl From<&str> for SecretInput {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
let mut parts = s.split(':');
|
let mut parts = s.split(':');
|
||||||
match parts.next() {
|
match parts.next() {
|
||||||
Some("ask") | Some("Ask") => InputSalt::AskPassword,
|
Some("ask") | Some("Ask") => SecretInput::AskPassword,
|
||||||
Some("file") => InputSalt::File {
|
Some("file") => SecretInput::File {
|
||||||
path: parts.collect::<Vec<_>>().join(":").into(),
|
path: parts.collect::<Vec<_>>().join(":").into(),
|
||||||
},
|
},
|
||||||
Some("string") => InputSalt::String(parts.collect::<Vec<_>>().join(":")),
|
Some("string") => SecretInput::String(parts.collect::<Vec<_>>().join(":")),
|
||||||
_ => Self::default(),
|
_ => Self::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for InputSalt {
|
impl FromStr for SecretInput {
|
||||||
type Err = Fido2LuksError;
|
type Err = Fido2LuksError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
@@ -44,21 +44,42 @@ impl FromStr for InputSalt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for InputSalt {
|
impl fmt::Display for SecretInput {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
f.write_str(&match self {
|
f.write_str(&match self {
|
||||||
InputSalt::AskPassword => "ask".to_string(),
|
SecretInput::AskPassword => "ask".to_string(),
|
||||||
InputSalt::String(s) => ["string", s].join(":"),
|
SecretInput::String(s) => ["string", s].join(":"),
|
||||||
InputSalt::File { path } => ["file", path.display().to_string().as_str()].join(":"),
|
SecretInput::File { path } => ["file", path.display().to_string().as_str()].join(":"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputSalt {
|
impl SecretInput {
|
||||||
pub fn obtain(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<[u8; 32]> {
|
pub fn obtain_string(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<String> {
|
||||||
|
Ok(String::from_utf8(self.obtain(password_helper)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn obtain(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<Vec<u8>> {
|
||||||
|
let mut secret = Vec::new();
|
||||||
|
match self {
|
||||||
|
SecretInput::File { path } => {
|
||||||
|
//TODO: replace with try_blocks
|
||||||
|
let mut do_io = || File::open(path)?.read_to_end(&mut secret);
|
||||||
|
do_io().map_err(|cause| Fido2LuksError::KeyfileError { cause })?;
|
||||||
|
}
|
||||||
|
SecretInput::AskPassword => {
|
||||||
|
secret.extend_from_slice(password_helper.obtain()?.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
SecretInput::String(s) => secret.extend_from_slice(s.as_bytes()),
|
||||||
|
}
|
||||||
|
Ok(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn obtain_sha256(&self, password_helper: &PasswordHelper) -> Fido2LuksResult<[u8; 32]> {
|
||||||
let mut digest = digest::Context::new(&digest::SHA256);
|
let mut digest = digest::Context::new(&digest::SHA256);
|
||||||
match self {
|
match self {
|
||||||
InputSalt::File { path } => {
|
SecretInput::File { path } => {
|
||||||
let mut do_io = || {
|
let mut do_io = || {
|
||||||
let mut reader = File::open(path)?;
|
let mut reader = File::open(path)?;
|
||||||
let mut buf = [0u8; 512];
|
let mut buf = [0u8; 512];
|
||||||
@@ -73,10 +94,7 @@ impl InputSalt {
|
|||||||
};
|
};
|
||||||
do_io().map_err(|cause| Fido2LuksError::KeyfileError { cause })?;
|
do_io().map_err(|cause| Fido2LuksError::KeyfileError { cause })?;
|
||||||
}
|
}
|
||||||
InputSalt::AskPassword => {
|
_ => digest.update(self.obtain(password_helper)?.as_slice()),
|
||||||
digest.update(password_helper.obtain()?.as_bytes());
|
|
||||||
}
|
|
||||||
InputSalt::String(s) => digest.update(s.as_bytes()),
|
|
||||||
}
|
}
|
||||||
let mut salt = [0u8; 32];
|
let mut salt = [0u8; 32];
|
||||||
salt.as_mut().copy_from_slice(digest.finish().as_ref());
|
salt.as_mut().copy_from_slice(digest.finish().as_ref());
|
||||||
@@ -157,24 +175,30 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn input_salt_from_str() {
|
fn input_salt_from_str() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"file:/tmp/abc".parse::<InputSalt>().unwrap(),
|
"file:/tmp/abc".parse::<SecretInput>().unwrap(),
|
||||||
InputSalt::File {
|
SecretInput::File {
|
||||||
path: "/tmp/abc".into()
|
path: "/tmp/abc".into()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"string:abc".parse::<InputSalt>().unwrap(),
|
"string:abc".parse::<SecretInput>().unwrap(),
|
||||||
InputSalt::String("abc".into())
|
SecretInput::String("abc".into())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
"ask".parse::<SecretInput>().unwrap(),
|
||||||
|
SecretInput::AskPassword
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
"lol".parse::<SecretInput>().unwrap(),
|
||||||
|
SecretInput::default()
|
||||||
);
|
);
|
||||||
assert_eq!("ask".parse::<InputSalt>().unwrap(), InputSalt::AskPassword);
|
|
||||||
assert_eq!("lol".parse::<InputSalt>().unwrap(), InputSalt::default());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn input_salt_obtain() {
|
fn input_salt_obtain() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
InputSalt::String("abc".into())
|
SecretInput::String("abc".into())
|
||||||
.obtain(&PasswordHelper::Stdin)
|
.obtain_sha256(&PasswordHelper::Stdin)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
[
|
[
|
||||||
186, 120, 22, 191, 143, 1, 207, 234, 65, 65, 64, 222, 93, 174, 34, 35, 176, 3, 97,
|
186, 120, 22, 191, 143, 1, 207, 234, 65, 65, 64, 222, 93, 174, 34, 35, 176, 3, 97,
|
293
src/cli_args/mod.rs
Normal file
293
src/cli_args/mod.rs
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
use std::fmt::{Display, Error, Formatter};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use structopt::clap::AppSettings;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
|
||||||
|
pub use config::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
|
pub struct HexEncoded(pub Vec<u8>);
|
||||||
|
|
||||||
|
impl Display for HexEncoded {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||||
|
f.write_str(&hex::encode(&self.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<[u8]> for HexEncoded {
|
||||||
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
&self.0[..]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for HexEncoded {
|
||||||
|
type Err = hex::FromHexError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(HexEncoded(hex::decode(s)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
|
pub struct CommaSeparated<T: FromStr + Display>(pub Vec<T>);
|
||||||
|
|
||||||
|
impl<T: Display + FromStr> Display for CommaSeparated<T> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||||
|
for i in &self.0 {
|
||||||
|
f.write_str(&i.to_string())?;
|
||||||
|
f.write_str(",")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Display + FromStr> FromStr for CommaSeparated<T> {
|
||||||
|
type Err = <T as FromStr>::Err;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(CommaSeparated(
|
||||||
|
s.split(',')
|
||||||
|
.map(|part| <T as FromStr>::from_str(part))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub struct Credentials {
|
||||||
|
/// FIDO credential ids, separated by ',' generate using fido2luks credential
|
||||||
|
#[structopt(name = "credential-id", env = "FIDO2LUKS_CREDENTIAL_ID")]
|
||||||
|
pub ids: CommaSeparated<HexEncoded>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub struct AuthenticatorParameters {
|
||||||
|
/// Request a PIN to unlock the authenticator
|
||||||
|
#[structopt(short = "P", long = "pin")]
|
||||||
|
pub pin: bool,
|
||||||
|
|
||||||
|
/// Location to read PIN from
|
||||||
|
#[structopt(long = "pin-source", env = "FIDO2LUKS_PIN_SOURCE")]
|
||||||
|
pub pin_source: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Await for an authenticator to be connected, timeout after n seconds
|
||||||
|
#[structopt(
|
||||||
|
long = "await-dev",
|
||||||
|
name = "await-dev",
|
||||||
|
env = "FIDO2LUKS_DEVICE_AWAIT",
|
||||||
|
default_value = "15"
|
||||||
|
)]
|
||||||
|
pub await_time: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub struct LuksParameters {
|
||||||
|
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||||
|
pub device: PathBuf,
|
||||||
|
|
||||||
|
/// Try to unlock the device using a specifc keyslot, ignore all other slots
|
||||||
|
#[structopt(long = "slot", env = "FIDO2LUKS_DEVICE_SLOT")]
|
||||||
|
pub slot: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
|
pub struct LuksModParameters {
|
||||||
|
/// Number of milliseconds required to derive the volume decryption key
|
||||||
|
/// Defaults to 10ms when using an authenticator or the default by cryptsetup when using a password
|
||||||
|
#[structopt(long = "kdf-time", name = "kdf-time")]
|
||||||
|
pub kdf_time: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub struct SecretParameters {
|
||||||
|
/// Salt for secret generation, defaults to 'ask'
|
||||||
|
///
|
||||||
|
/// Options:{n}
|
||||||
|
/// - ask : Prompt user using password helper{n}
|
||||||
|
/// - file:<PATH> : Will read <FILE>{n}
|
||||||
|
/// - string:<STRING> : Will use <STRING>, which will be handled like a password provided to the 'ask' option{n}
|
||||||
|
#[structopt(
|
||||||
|
name = "salt",
|
||||||
|
long = "salt",
|
||||||
|
env = "FIDO2LUKS_SALT",
|
||||||
|
default_value = "ask"
|
||||||
|
)]
|
||||||
|
pub salt: SecretInput,
|
||||||
|
/// Script used to obtain passwords, overridden by --interactive flag
|
||||||
|
#[structopt(
|
||||||
|
name = "password-helper",
|
||||||
|
env = "FIDO2LUKS_PASSWORD_HELPER",
|
||||||
|
default_value = "/usr/bin/env systemd-ask-password 'Please enter second factor for LUKS disk encryption!'"
|
||||||
|
)]
|
||||||
|
pub password_helper: PasswordHelper,
|
||||||
|
}
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub struct Args {
|
||||||
|
/// Request passwords via Stdin instead of using the password helper
|
||||||
|
#[structopt(short = "i", long = "interactive")]
|
||||||
|
pub interactive: bool,
|
||||||
|
#[structopt(subcommand)]
|
||||||
|
pub command: Command,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
|
pub struct OtherSecret {
|
||||||
|
/// Use a keyfile instead of a password
|
||||||
|
#[structopt(short = "d", long = "keyfile", conflicts_with = "fido_device")]
|
||||||
|
pub keyfile: Option<PathBuf>,
|
||||||
|
/// Use another fido device instead of a password
|
||||||
|
/// Note: this requires for the credential fot the other device to be passed as argument as well
|
||||||
|
#[structopt(short = "f", long = "fido-device", conflicts_with = "keyfile")]
|
||||||
|
pub fido_device: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub enum Command {
|
||||||
|
#[structopt(name = "print-secret")]
|
||||||
|
PrintSecret {
|
||||||
|
/// Prints the secret as binary instead of hex encoded
|
||||||
|
#[structopt(short = "b", long = "bin")]
|
||||||
|
binary: bool,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
credentials: Credentials,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
authenticator: AuthenticatorParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
secret: SecretParameters,
|
||||||
|
},
|
||||||
|
/// Adds a generated key to the specified LUKS device
|
||||||
|
#[structopt(name = "add-key")]
|
||||||
|
AddKey {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
luks: LuksParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
credentials: Credentials,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
authenticator: AuthenticatorParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
secret: SecretParameters,
|
||||||
|
/// Will wipe all other keys
|
||||||
|
#[structopt(short = "e", long = "exclusive")]
|
||||||
|
exclusive: bool,
|
||||||
|
/// Will add an token to your LUKS 2 header, including the credential id
|
||||||
|
#[structopt(short = "t", long = "token")]
|
||||||
|
token: bool,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
existing_secret: OtherSecret,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
luks_mod: LuksModParameters,
|
||||||
|
},
|
||||||
|
/// Replace a previously added key with a password
|
||||||
|
#[structopt(name = "replace-key")]
|
||||||
|
ReplaceKey {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
luks: LuksParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
credentials: Credentials,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
authenticator: AuthenticatorParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
secret: SecretParameters,
|
||||||
|
/// Add the password and keep the key
|
||||||
|
#[structopt(short = "a", long = "add-password")]
|
||||||
|
add_password: bool,
|
||||||
|
/// Will add an token to your LUKS 2 header, including the credential id
|
||||||
|
#[structopt(short = "t", long = "token")]
|
||||||
|
token: bool,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
replacement: OtherSecret,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
luks_mod: LuksModParameters,
|
||||||
|
},
|
||||||
|
/// Open the LUKS device
|
||||||
|
#[structopt(name = "open")]
|
||||||
|
Open {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
luks: LuksParameters,
|
||||||
|
#[structopt(env = "FIDO2LUKS_MAPPER_NAME")]
|
||||||
|
name: String,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
credentials: Credentials,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
authenticator: AuthenticatorParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
secret: SecretParameters,
|
||||||
|
#[structopt(short = "r", long = "max-retries", default_value = "0")]
|
||||||
|
retries: i32,
|
||||||
|
},
|
||||||
|
/// Open the LUKS device using credentials embedded in the LUKS 2 header
|
||||||
|
#[structopt(name = "open-token")]
|
||||||
|
OpenToken {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
luks: LuksParameters,
|
||||||
|
#[structopt(env = "FIDO2LUKS_MAPPER_NAME")]
|
||||||
|
name: String,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
authenticator: AuthenticatorParameters,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
secret: SecretParameters,
|
||||||
|
#[structopt(short = "r", long = "max-retries", default_value = "0")]
|
||||||
|
retries: i32,
|
||||||
|
},
|
||||||
|
/// Generate a new FIDO credential
|
||||||
|
#[structopt(name = "credential")]
|
||||||
|
Credential {
|
||||||
|
#[structopt(flatten)]
|
||||||
|
authenticator: AuthenticatorParameters,
|
||||||
|
/// Name to be displayed on the authenticator if it has a display
|
||||||
|
#[structopt(env = "FIDO2LUKS_CREDENTIAL_NAME")]
|
||||||
|
name: Option<String>,
|
||||||
|
},
|
||||||
|
/// Check if an authenticator is connected
|
||||||
|
#[structopt(name = "connected")]
|
||||||
|
Connected,
|
||||||
|
Token(TokenCommand),
|
||||||
|
/// Generate bash completion scripts
|
||||||
|
#[structopt(name = "completions", setting = AppSettings::Hidden)]
|
||||||
|
GenerateCompletions {
|
||||||
|
/// Shell to generate completions for: bash, fish
|
||||||
|
#[structopt(possible_values = &["bash", "fish"])]
|
||||||
|
shell: String,
|
||||||
|
out_dir: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
///LUKS2 token related operations
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub enum TokenCommand {
|
||||||
|
/// List all tokens associated with the specified device
|
||||||
|
List {
|
||||||
|
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||||
|
device: PathBuf,
|
||||||
|
/// Dump all credentials as CSV
|
||||||
|
#[structopt(long = "csv")]
|
||||||
|
csv: bool,
|
||||||
|
},
|
||||||
|
/// Add credential to a keyslot
|
||||||
|
Add {
|
||||||
|
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||||
|
device: PathBuf,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
credentials: Credentials,
|
||||||
|
/// Slot to which the credentials will be added
|
||||||
|
#[structopt(long = "slot", env = "FIDO2LUKS_DEVICE_SLOT")]
|
||||||
|
slot: u32,
|
||||||
|
},
|
||||||
|
/// Remove credentials from token(s)
|
||||||
|
Remove {
|
||||||
|
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||||
|
device: PathBuf,
|
||||||
|
#[structopt(flatten)]
|
||||||
|
credentials: Credentials,
|
||||||
|
/// Token from which the credentials will be removed
|
||||||
|
#[structopt(long = "token")]
|
||||||
|
token_id: Option<u32>,
|
||||||
|
},
|
||||||
|
/// Remove all unassigned tokens
|
||||||
|
GC {
|
||||||
|
#[structopt(env = "FIDO2LUKS_DEVICE")]
|
||||||
|
device: PathBuf,
|
||||||
|
},
|
||||||
|
}
|
@@ -1,5 +1,9 @@
|
|||||||
use ctap::FidoError;
|
use ctap::FidoError;
|
||||||
|
use libcryptsetup_rs::LibcryptErr;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
use std::string::FromUtf8Error;
|
||||||
|
use Fido2LuksError::*;
|
||||||
|
|
||||||
pub type Fido2LuksResult<T> = Result<T, Fido2LuksError>;
|
pub type Fido2LuksResult<T> = Result<T, Fido2LuksError>;
|
||||||
|
|
||||||
@@ -81,11 +85,6 @@ impl From<LuksError> for Fido2LuksError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use libcryptsetup_rs::LibcryptErr;
|
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::string::FromUtf8Error;
|
|
||||||
use Fido2LuksError::*;
|
|
||||||
|
|
||||||
impl From<FidoError> for Fido2LuksError {
|
impl From<FidoError> for Fido2LuksError {
|
||||||
fn from(e: FidoError) -> Self {
|
fn from(e: FidoError) -> Self {
|
||||||
AuthenticatorError { cause: e }
|
AuthenticatorError { cause: e }
|
||||||
|
@@ -4,15 +4,13 @@ extern crate ctap_hmac as ctap;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
use crate::cli::*;
|
use crate::cli::*;
|
||||||
use crate::config::*;
|
|
||||||
use crate::device::*;
|
use crate::device::*;
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod config;
|
pub mod cli_args;
|
||||||
mod device;
|
mod device;
|
||||||
mod error;
|
mod error;
|
||||||
mod luks;
|
mod luks;
|
||||||
@@ -21,10 +19,7 @@ mod util;
|
|||||||
fn main() -> Fido2LuksResult<()> {
|
fn main() -> Fido2LuksResult<()> {
|
||||||
match run_cli() {
|
match run_cli() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("{:?}", e);
|
eprintln!("{:?}", e);
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
eprintln!("{}", e);
|
|
||||||
exit(e.exit_code())
|
exit(e.exit_code())
|
||||||
}
|
}
|
||||||
_ => exit(0),
|
_ => exit(0),
|
||||||
|
Reference in New Issue
Block a user