4 Commits

Author SHA1 Message Date
hcyang
81330e5d52 Persist/parse slot_id in/from credential (#569)
* Persist/parse slot_id in/from credential

Persist slot_id into credential_id or the resident credential record
during MakeCredential, and parse it during GetAssertion. Add related
unittests.

* Fix styles

* Move enable_pin_uv back to ctap/mod.rs
2022-11-02 18:08:25 +08:00
hcyang
31774ef316 Add storage test cases for multi-PIN (#567)
* Add storage test cases for multi-PIN

* Fixed proc-macro2 version (#550)

* fixes proc-macro2 in dependencies

* adds missing locked versions, and a verbose print for cargo check

* commits Cargo.lock files

* removes unnecessary Cargo.lock entries

* adds missing Cargo.lock

Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
2022-10-26 11:29:56 +08:00
hcyang
1c6c7a4eae Parse slot_id in use from token state (#546)
* Parse slot_id in use from token state

Support switching to multi-PIN feature and making the default slots 8.
But the command to switch to multi-PIN isn't exposed yet because the
implementation isn't ready.

Main change of this commit is to cache the slot_id in use inside token
state, and retrieve it from token state when needed.

* Fix once_cell dependency (#548)

* fixed version of once_cell

* fixes comments

* removes unnecessary fuzz dependency

* Fix styles

Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
2022-09-22 14:30:52 +08:00
hcyang
078e565ac1 Add basic setup for multi-PIN (#530)
* Add basic setup for multi-PIN

- Reserve the storage keys for maximum of 8 user slots.
- Modify the storage functions to take a slot_id parameter.
- Add the slot_count() customization.
- Assume slot_id as a parameter when needed except these places:
  - Entrance functions of command processing that directly takes the
    command parameter structure. slot_id is set as 0, and will be
    parsed from the parameters when we enable the feature.
  - MakeCredential/GetAssertion/AuthenticatorConfig will take the
    slot_id from active token state when we enable the feature,
    resulting in an `Option<usize>`. Below code will act on the option
    value correctly. When the feature isn't enabled, we're always
    referring to the only PIN slot so set slot_id as Some(0).
  - GetInfo returns verdict of whether PIN is supported and enabled, and
    whether PIN needs to be forced changed. There will be new fields to
    represent those values when the feature is enabled, and the old
    fields will not be populated. So when the feature isn't enabled, we
    can treat slot_id as 0.

Not covered in this commit:
- Unittests for other slots. The existing tests all pass and I plan to
  add unittests for multi-slot case after the codebase allows enabling
  the feature.
- Persisting and checking the slot_id in credentials. This is planned to
  come in the next commit.

* Fix storage and some other style

* Add support for concatenated values

* Switch some storage entries back to multi-entry

* Set bumpalo version for fuzzing (#532)

* maximum working bumpalo version

* explicit comment to explain version locking

* removes incorrect comment

* moves serde version lock to dev dependencies

* removes serde dependencies

* reverts serde removal in crypto library

* Make PIN_PROPERTIES use concatenated storage entry

* Fix bumpalo issue

* Use concatenated storage entry for force_pin_change too

* Fix cargofmt

Co-authored-by: Julien Cretin <cretin@google.com>
Co-authored-by: kaczmarczyck <43844792+kaczmarczyck@users.noreply.github.com>
2022-08-23 23:01:13 +08:00
31 changed files with 5261 additions and 307 deletions

1
.gitignore vendored
View File

@@ -2,7 +2,6 @@ fuzz/artifacts
fuzz/corpus
fuzz/coverage
target/
Cargo.lock
# Local installation of elf2tab.
/elf2tab/

789
Cargo.lock generated Normal file
View File

@@ -0,0 +1,789 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "crypto"
version = "0.1.0"
dependencies = [
"arrayref",
"byteorder",
"hex",
"regex",
"ring",
"rng256",
"serde",
"serde_json",
"subtle",
"untrusted",
]
[[package]]
name = "ctap2"
version = "1.0.0"
dependencies = [
"arbitrary",
"arrayref",
"byteorder",
"crypto",
"ed25519-compact",
"embedded-time",
"enum-iterator",
"lang_items",
"libtock_core",
"libtock_drivers",
"openssl",
"persistent_store",
"rand 0.8.5",
"rng256",
"sk-cbor",
"subtle",
"uuid",
]
[[package]]
name = "derive_arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a012b5e473dc912f0db0546a1c9c6a194ce8494feb66fa0237160926f9e0e6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ed25519-compact"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bee9df587982575886a8682edcee11877894349a805f25629c27f63abe3e9ae8"
[[package]]
name = "embedded-time"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
dependencies = [
"num",
]
[[package]]
name = "enum-iterator"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[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 = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lang_items"
version = "0.1.0"
dependencies = [
"libtock_core",
"libtock_drivers",
"linked_list_allocator",
]
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "linked_list_allocator"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg 1.1.0",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "once_cell"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "openssl"
version = "0.10.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
dependencies = [
"autocfg 1.1.0",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "persistent_store"
version = "0.1.0"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[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 = "rng256"
version = "0.1.0"
dependencies = [
"arrayref",
"libtock_drivers",
"rand 0.6.5",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sk-cbor"
version = "0.1.2"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "web-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[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"

View File

@@ -20,8 +20,6 @@ persistent_store = { path = "libraries/persistent_store" }
byteorder = { version = "1", default-features = false }
arrayref = "0.3.6"
subtle = { version = "2.2", default-features = false, features = ["nightly"] }
# This import explicitly locks the version.
serde_json = { version = "=1.0.69", default-features = false, features = ["alloc"] }
embedded-time = "0.12.1"
arbitrary = { version = "0.4.7", features = ["derive"], optional = true }
rand = { version = "0.8.4", optional = true }

282
bootloader/Cargo.lock generated Normal file
View File

@@ -0,0 +1,282 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aligned"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a785a543aea40f5e4e2e93bb2655d31bc21bb391fff65697150973e383f16bb"
dependencies = [
"as-slice",
]
[[package]]
name = "as-slice"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
dependencies = [
"generic-array 0.12.4",
"generic-array 0.13.3",
"generic-array 0.14.6",
"stable_deref_trait",
]
[[package]]
name = "bare-metal"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
dependencies = [
"rustc_version",
]
[[package]]
name = "bitfield"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
[[package]]
name = "bootloader"
version = "0.1.0"
dependencies = [
"byteorder",
"cortex-m 0.6.7",
"cortex-m-rt",
"cortex-m-rt-macros",
"panic-abort",
"rtt-target",
"tock-registers",
]
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cortex-m"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9075300b07c6a56263b9b582c214d0ff037b00d45ec9fde1cc711490c56f1bb9"
dependencies = [
"aligned",
"bare-metal",
"bitfield",
"cortex-m 0.7.6",
"volatile-register",
]
[[package]]
name = "cortex-m"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0"
dependencies = [
"bare-metal",
"bitfield",
"embedded-hal",
"volatile-register",
]
[[package]]
name = "cortex-m-rt"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c433da385b720d5bb9f52362fa2782420798e68d40d67bfe4b0d992aba5dfe7"
dependencies = [
"cortex-m-rt-macros",
]
[[package]]
name = "cortex-m-rt-macros"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "embedded-hal"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
dependencies = [
"nb 0.1.3",
"void",
]
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "nb"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
dependencies = [
"nb 1.0.0",
]
[[package]]
name = "nb"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae"
[[package]]
name = "panic-abort"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e20e6499bbbc412f280b04a42346b356c6fa0753d5fd22b7bd752ff34c778ee"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rtt-target"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065d6058bb1204f51a562a67209e1817cf714759d5cf845aa45c75fa7b0b9d9b"
dependencies = [
"cortex-m 0.7.6",
"ufmt-write",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tock-registers"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f521a79accce68c417c9c77ce22108056b626126da1932f7e2e9b5bbffee0cea"
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "ufmt-write"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69"
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "vcell"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "volatile-register"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6"
dependencies = [
"vcell",
]

794
fuzz/Cargo.lock generated Normal file
View File

@@ -0,0 +1,794 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "crypto"
version = "0.1.0"
dependencies = [
"arrayref",
"byteorder",
"hex",
"regex",
"ring",
"rng256",
"serde",
"serde_json",
"subtle",
"untrusted",
]
[[package]]
name = "ctap2"
version = "1.0.0"
dependencies = [
"arbitrary",
"arrayref",
"byteorder",
"crypto",
"embedded-time",
"lang_items",
"libtock_core",
"libtock_drivers",
"openssl",
"persistent_store",
"rand 0.8.5",
"rng256",
"sk-cbor",
"subtle",
"uuid",
]
[[package]]
name = "ctap2-fuzz"
version = "0.0.0"
dependencies = [
"fuzz_helper",
"libfuzzer-sys",
]
[[package]]
name = "derive_arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a012b5e473dc912f0db0546a1c9c6a194ce8494feb66fa0237160926f9e0e6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "embedded-time"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
dependencies = [
"num",
]
[[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 = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuzz_helper"
version = "0.1.0"
dependencies = [
"arbitrary",
"arrayref",
"crypto",
"ctap2",
"embedded-time",
"lang_items",
"libtock_drivers",
"rng256",
"sk-cbor",
]
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lang_items"
version = "0.1.0"
dependencies = [
"libtock_core",
"libtock_drivers",
"linked_list_allocator",
]
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "libfuzzer-sys"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "linked_list_allocator"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg 1.1.0",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg 1.1.0",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "once_cell"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "openssl"
version = "0.10.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
dependencies = [
"autocfg 1.1.0",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "persistent_store"
version = "0.1.0"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[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 = "rng256"
version = "0.1.0"
dependencies = [
"arrayref",
"libtock_drivers",
"rand 0.6.5",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sk-cbor"
version = "0.1.2"
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "web-sys"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[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"

View File

@@ -11,8 +11,6 @@ cargo-fuzz = true
[dependencies]
libfuzzer-sys = { version = "0.3" }
fuzz_helper = { path = "fuzz_helper" }
# This import explicitly locks the version.
serde_json = { version = "=1.0.69" }
# Prevent this from interfering with workspaces
[workspace]

7
libraries/cbor/Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "sk-cbor"
version = "0.1.2"

37
libraries/cbor/fuzz/Cargo.lock generated Normal file
View File

@@ -0,0 +1,37 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "libfuzzer-sys"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "sk-cbor"
version = "0.1.2"
[[package]]
name = "sk-cbor-fuzz"
version = "0.0.0"
dependencies = [
"libfuzzer-sys",
"sk-cbor",
]

503
libraries/crypto/Cargo.lock generated Normal file
View File

@@ -0,0 +1,503 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "crypto"
version = "0.1.0"
dependencies = [
"arrayref",
"byteorder",
"hex",
"regex",
"ring",
"rng256",
"serde",
"serde_json",
"subtle",
"untrusted",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
version = "0.3.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "once_cell"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[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 = "rng256"
version = "0.1.0"
dependencies = [
"arrayref",
"libtock_drivers",
"rand",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e466864e431129c7e0d3476b92f20458e5879919a0596c6472738d9fa2d342f8"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "wasm-bindgen"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
[[package]]
name = "web-sys"
version = "0.3.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[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"

100
libraries/persistent_store/Cargo.lock generated Normal file
View File

@@ -0,0 +1,100 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "persistent_store"
version = "0.1.0"
dependencies = [
"tempfile",
]
[[package]]
name = "redox_syscall"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[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"

View File

@@ -1,4 +1,3 @@
/Cargo.lock
/artifacts/
/corpus/
/target/

126
libraries/persistent_store/fuzz/Cargo.lock generated Normal file
View File

@@ -0,0 +1,126 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "fuzz-store"
version = "0.0.0"
dependencies = [
"libfuzzer-sys",
"persistent_store",
"rand_core",
"rand_pcg",
"strum",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "libfuzzer-sys"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf184a4b6b274f82a5df6b357da6055d3e82272327bba281c28bbba6f1664ef"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "persistent_store"
version = "0.1.0"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
[[package]]
name = "rand_pcg"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
dependencies = [
"rand_core",
]
[[package]]
name = "strum"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89a286a7e3b5720b9a477b23253bc50debac207c8d21505f8e70b36792f11b5"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.19.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e61bb0be289045cb80bfce000512e32d09f8337e54c186725da381377ad1f8d5"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "unicode-segmentation"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"

View File

@@ -0,0 +1,242 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Support for concatenated entries.
//!
//! This module permits to store multiple indexed values under the same key by concatenation. Such
//! values must be at most 255 bytes and there can't be more than 255 such values under the same
//! key (they are indexed with a `u8`).
//!
//! The rationale for using those particular constraints is that we want the number of bits to store
//! the index and the number of bits to store the length to fit in an integer number of bytes
//! (because the values are an integer number of bytes). Using only one byte is too restrictive
//! (e.g. 8 values of at most 31 bytes or 16 values of at most 15 bytes). Using 2 bytes is plenty of
//! space, so using one byte for each field makes parsing simpler and faster.
//!
//! The format is thus `(index:u8 length:u8 payload:[u8; length])*`. The concatenation is not
//! particularly sorted.
use crate::{Storage, Store, StoreError, StoreResult};
use alloc::vec::Vec;
use core::cmp::Ordering;
use core::ops::Range;
/// Reads a value from a concatenated entry.
pub fn read(store: &Store<impl Storage>, key: usize, index: u8) -> StoreResult<Option<Vec<u8>>> {
let values = match store.find(key)? {
None => return Ok(None),
Some(x) => x,
};
Ok(find(&values, index)?.map(|range| values[range].to_vec()))
}
/// Writes a value to a concatenated entry.
pub fn write(
store: &mut Store<impl Storage>,
key: usize,
index: u8,
value: &[u8],
) -> StoreResult<()> {
if value.len() > 255 {
return Err(StoreError::InvalidArgument);
}
let mut values = store.find(key)?.unwrap_or(vec![]);
match find(&values, index)? {
None => {
values.push(index);
values.push(value.len() as u8);
values.extend_from_slice(value);
}
Some(mut range) => {
values[range.start - 1] = value.len() as u8;
match range.len().cmp(&value.len()) {
Ordering::Less => {
let diff = value.len() - range.len();
values.resize(values.len() + diff, 0);
values[range.end..].rotate_right(diff);
range.end += diff;
}
Ordering::Equal => (),
Ordering::Greater => {
let diff = range.len() - value.len();
range.end -= diff;
values[range.end..].rotate_left(diff);
values.truncate(values.len() - diff);
}
}
values[range].copy_from_slice(value);
}
}
store.insert(key, &values)
}
/// Deletes the value from a concatenated entry.
pub fn delete(store: &mut Store<impl Storage>, key: usize, index: u8) -> StoreResult<()> {
let mut values = match store.find(key)? {
None => return Ok(()),
Some(x) => x,
};
let mut range = match find(&values, index)? {
None => return Ok(()),
Some(x) => x,
};
range.start -= 2;
values[range.start..].rotate_left(range.len());
values.truncate(values.len() - range.len());
store.insert(key, &values)
}
fn find(values: &[u8], index: u8) -> StoreResult<Option<Range<usize>>> {
let mut pos = 0;
while pos < values.len() {
if pos == values.len() - 1 {
return Err(StoreError::InvalidStorage);
}
let len = values[pos + 1] as usize;
if len > values.len() - 2 || pos > values.len() - 2 - len {
return Err(StoreError::InvalidStorage);
}
if index == values[pos] {
return Ok(Some(pos + 2..pos + 2 + len));
}
pos += 2 + len;
}
Ok(None)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::MINIMAL;
#[test]
fn read_empty_entry() {
let store = MINIMAL.new_store();
assert_eq!(read(&store, 0, 0), Ok(None));
assert_eq!(read(&store, 0, 1), Ok(None));
}
#[test]
fn read_missing_value() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(read(&store, 0, 1), Ok(None));
}
#[test]
fn read_existing_value() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(read(&store, 0, 0), Ok(Some(b"foo".to_vec())));
assert_eq!(read(&store, 0, 2), Ok(Some(b"hello".to_vec())));
}
#[test]
fn read_invalid_entry_too_long() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x08hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(read(&store, 0, 1), Err(StoreError::InvalidStorage));
}
#[test]
fn read_invalid_entry_too_short() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(read(&store, 0, 1), Err(StoreError::InvalidStorage));
}
#[test]
fn write_empty_entry() {
let mut store = MINIMAL.new_store();
assert_eq!(write(&mut store, 0, 0, b"foo"), Ok(()));
assert_eq!(store.find(0), Ok(Some(b"\x00\x03foo".to_vec())));
}
#[test]
fn write_missing_value() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(write(&mut store, 0, 1, b"bar"), Ok(()));
assert_eq!(store.find(0), Ok(Some(b"\x00\x03foo\x01\x03bar".to_vec())));
}
#[test]
fn write_existing_value_same_size() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(write(&mut store, 0, 0, b"bar"), Ok(()));
assert_eq!(
store.find(0),
Ok(Some(b"\x00\x03bar\x02\x05hello".to_vec()))
);
}
#[test]
fn write_existing_value_longer() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(write(&mut store, 0, 0, b"barrage"), Ok(()));
assert_eq!(
store.find(0),
Ok(Some(b"\x00\x07barrage\x02\x05hello".to_vec()))
);
}
#[test]
fn write_existing_value_shorter() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x08football\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(write(&mut store, 0, 0, b"bar"), Ok(()));
assert_eq!(
store.find(0),
Ok(Some(b"\x00\x03bar\x02\x05hello".to_vec()))
);
}
#[test]
fn delete_empty_entry() {
let mut store = MINIMAL.new_store();
assert_eq!(delete(&mut store, 0, 0), Ok(()));
assert_eq!(delete(&mut store, 0, 1), Ok(()));
}
#[test]
fn delete_missing_value() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(delete(&mut store, 0, 1), Ok(()));
assert_eq!(
store.find(0),
Ok(Some(b"\x00\x03foo\x02\x05hello".to_vec()))
);
}
#[test]
fn delete_existing_value() {
let mut store = MINIMAL.new_store();
let value = b"\x00\x03foo\x02\x05hello".to_vec();
store.insert(0, &value).unwrap();
assert_eq!(delete(&mut store, 0, 0), Ok(()));
assert_eq!(store.find(0), Ok(Some(b"\x02\x05hello".to_vec())));
}
}

View File

@@ -363,6 +363,7 @@ extern crate alloc;
#[cfg(feature = "std")]
mod buffer;
pub mod concat;
#[cfg(feature = "std")]
mod driver;
#[cfg(feature = "std")]

255
libraries/rng256/Cargo.lock generated Normal file
View File

@@ -0,0 +1,255 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rng256"
version = "0.1.0"
dependencies = [
"arrayref",
"libtock_drivers",
"rand",
]
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[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"

View File

@@ -241,6 +241,21 @@ pub trait Customization {
/// With P=20 and K=150, we have I=2M which is enough for 500 increments per day
/// for 10 years.
fn max_supported_resident_keys(&self) -> usize;
/// Sets the slot count of the multi-PIN feature.
///
/// # Invariant
///
/// - The slot count may not:
/// - make the storage entries that concatenate data of each slots
/// become larger than the storage page size,
/// - go over u8, as we only reserve 1 byte for the array index for
/// concatenated entries, or
/// - exceed the number of keys we reserve for the storage entries
/// that use unique keys for each slot.
///
/// The upper bound of this is currently 8.
fn slot_count(&self) -> usize;
}
#[derive(Clone)]
@@ -260,6 +275,7 @@ pub struct CustomizationImpl {
pub max_large_blob_array_size: usize,
pub max_rp_ids_length: usize,
pub max_supported_resident_keys: usize,
pub slot_count: usize,
}
pub const DEFAULT_CUSTOMIZATION: CustomizationImpl = CustomizationImpl {
@@ -278,6 +294,7 @@ pub const DEFAULT_CUSTOMIZATION: CustomizationImpl = CustomizationImpl {
max_large_blob_array_size: 2048,
max_rp_ids_length: 8,
max_supported_resident_keys: 150,
slot_count: 8,
};
impl Customization for CustomizationImpl {
@@ -351,6 +368,10 @@ impl Customization for CustomizationImpl {
fn max_supported_resident_keys(&self) -> usize {
self.max_supported_resident_keys
}
fn slot_count(&self) -> usize {
self.slot_count
}
}
#[cfg(feature = "std")]
@@ -423,6 +444,11 @@ pub fn is_valid(customization: &impl Customization) -> bool {
return false;
}
// Slot count should be at most 8.
if customization.slot_count() > 8 {
return false;
}
true
}

View File

@@ -21,12 +21,13 @@ use super::pin_protocol::{verify_pin_uv_auth_token, PinProtocol, SharedSecret};
use super::response::{AuthenticatorClientPinResponse, ResponseData};
use super::status_code::Ctap2StatusCode;
use super::token_state::PinUvAuthTokenState;
use crate::api::customization::Customization;
use crate::ctap::storage;
use crate::env::Env;
use alloc::boxed::Box;
use alloc::str;
use alloc::string::String;
use alloc::vec::Vec;
use alloc::{str, vec};
use crypto::hmac::hmac_256;
use crypto::sha256::Sha256;
use crypto::Hash256;
@@ -78,6 +79,7 @@ fn decrypt_pin(
/// truncated for persistent storage.
fn check_and_store_new_pin(
env: &mut impl Env,
slot_id: usize,
shared_secret: &dyn SharedSecret,
new_pin_enc: Vec<u8>,
) -> Result<(), Ctap2StatusCode> {
@@ -90,7 +92,7 @@ fn check_and_store_new_pin(
let mut pin_hash = [0u8; PIN_AUTH_LENGTH];
pin_hash.copy_from_slice(&Sha256::hash(&pin[..])[..PIN_AUTH_LENGTH]);
// The PIN length is always < PIN_PADDED_LENGTH < 256.
storage::set_pin(env, &pin_hash, pin_length as u8)?;
storage::set_pin(env, slot_id, &pin_hash, pin_length as u8)?;
Ok(())
}
@@ -108,16 +110,16 @@ pub enum PinPermission {
pub struct ClientPin {
pin_protocol_v1: PinProtocol,
pin_protocol_v2: PinProtocol,
consecutive_pin_mismatches: u8,
consecutive_pin_mismatches: Vec<u8>,
pin_uv_auth_token_state: PinUvAuthTokenState,
}
impl ClientPin {
pub fn new(rng: &mut impl Rng256) -> ClientPin {
pub fn new(env: &mut impl Env) -> ClientPin {
ClientPin {
pin_protocol_v1: PinProtocol::new(rng),
pin_protocol_v2: PinProtocol::new(rng),
consecutive_pin_mismatches: 0,
pin_protocol_v1: PinProtocol::new(env.rng()),
pin_protocol_v2: PinProtocol::new(env.rng()),
consecutive_pin_mismatches: vec![0; env.customization().slot_count()],
pin_uv_auth_token_state: PinUvAuthTokenState::new(),
}
}
@@ -159,16 +161,21 @@ impl ClientPin {
fn verify_pin_hash_enc(
&mut self,
env: &mut impl Env,
slot_id: usize,
pin_uv_auth_protocol: PinUvAuthProtocol,
shared_secret: &dyn SharedSecret,
pin_hash_enc: Vec<u8>,
) -> Result<(), Ctap2StatusCode> {
match storage::pin_hash(env)? {
// To prevent out of bounds access in code below.
if slot_id >= self.consecutive_pin_mismatches.len() {
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
}
match storage::pin_hash(env, slot_id)? {
Some(pin_hash) => {
if self.consecutive_pin_mismatches >= 3 {
if self.consecutive_pin_mismatches[slot_id] >= 3 {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED);
}
storage::decr_pin_retries(env)?;
storage::decr_pin_retries(env, slot_id)?;
let pin_hash_dec = shared_secret
.decrypt(&pin_hash_enc)
.map_err(|_| Ctap2StatusCode::CTAP2_ERR_PIN_INVALID)?;
@@ -176,11 +183,11 @@ impl ClientPin {
if !bool::from(pin_hash.ct_eq(&pin_hash_dec)) {
self.get_mut_pin_protocol(pin_uv_auth_protocol)
.regenerate(env.rng());
if storage::pin_retries(env)? == 0 {
if storage::pin_retries(env, slot_id)? == 0 {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_BLOCKED);
}
self.consecutive_pin_mismatches += 1;
if self.consecutive_pin_mismatches >= 3 {
self.consecutive_pin_mismatches[slot_id] += 1;
if self.consecutive_pin_mismatches[slot_id] >= 3 {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED);
}
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID);
@@ -189,20 +196,26 @@ impl ClientPin {
// This status code is not explicitly mentioned in the specification.
None => return Err(Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED),
}
storage::reset_pin_retries(env)?;
self.consecutive_pin_mismatches = 0;
storage::reset_pin_retries(env, slot_id)?;
self.consecutive_pin_mismatches[slot_id] = 0;
Ok(())
}
fn process_get_pin_retries(
&self,
env: &mut impl Env,
_client_pin_params: AuthenticatorClientPinParameters,
) -> Result<AuthenticatorClientPinResponse, Ctap2StatusCode> {
// TODO: Parse slot_id from params if multi-PIN feature is enabled.
let slot_id = 0;
if slot_id >= self.consecutive_pin_mismatches.len() {
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
}
Ok(AuthenticatorClientPinResponse {
key_agreement: None,
pin_uv_auth_token: None,
retries: Some(storage::pin_retries(env)? as u64),
power_cycle_state: Some(self.consecutive_pin_mismatches >= 3),
retries: Some(storage::pin_retries(env, slot_id)? as u64),
power_cycle_state: Some(self.consecutive_pin_mismatches[slot_id] >= 3),
})
}
@@ -234,18 +247,20 @@ impl ClientPin {
new_pin_enc,
..
} = client_pin_params;
// TODO: Parse slot_id from params if multi-PIN feature is enabled.
let slot_id = 0;
let key_agreement = ok_or_missing(key_agreement)?;
let pin_uv_auth_param = ok_or_missing(pin_uv_auth_param)?;
let new_pin_enc = ok_or_missing(new_pin_enc)?;
if storage::pin_hash(env)?.is_some() {
if storage::pin_hash(env, slot_id)?.is_some() {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID);
}
let shared_secret = self.get_shared_secret(pin_uv_auth_protocol, key_agreement)?;
shared_secret.verify(&new_pin_enc, &pin_uv_auth_param)?;
check_and_store_new_pin(env, shared_secret.as_ref(), new_pin_enc)?;
storage::reset_pin_retries(env)?;
check_and_store_new_pin(env, slot_id, shared_secret.as_ref(), new_pin_enc)?;
storage::reset_pin_retries(env, slot_id)?;
Ok(())
}
@@ -262,12 +277,14 @@ impl ClientPin {
pin_hash_enc,
..
} = client_pin_params;
// TODO: Parse slot_id from params if multi-PIN feature is enabled.
let slot_id = 0;
let key_agreement = ok_or_missing(key_agreement)?;
let pin_uv_auth_param = ok_or_missing(pin_uv_auth_param)?;
let new_pin_enc = ok_or_missing(new_pin_enc)?;
let pin_hash_enc = ok_or_missing(pin_hash_enc)?;
if storage::pin_retries(env)? == 0 {
if storage::pin_retries(env, slot_id)? == 0 {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_BLOCKED);
}
let shared_secret = self.get_shared_secret(pin_uv_auth_protocol, key_agreement)?;
@@ -276,12 +293,13 @@ impl ClientPin {
shared_secret.verify(&auth_param_data, &pin_uv_auth_param)?;
self.verify_pin_hash_enc(
env,
slot_id,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc,
)?;
check_and_store_new_pin(env, shared_secret.as_ref(), new_pin_enc)?;
check_and_store_new_pin(env, slot_id, shared_secret.as_ref(), new_pin_enc)?;
self.pin_protocol_v1.reset_pin_uv_auth_token(env.rng());
self.pin_protocol_v2.reset_pin_uv_auth_token(env.rng());
Ok(())
@@ -301,30 +319,33 @@ impl ClientPin {
permissions_rp_id,
..
} = client_pin_params;
// TODO: Parse slot_id from params if multi-PIN feature is enabled.
let slot_id = 0;
let key_agreement = ok_or_missing(key_agreement)?;
let pin_hash_enc = ok_or_missing(pin_hash_enc)?;
if permissions.is_some() || permissions_rp_id.is_some() {
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER);
}
if storage::pin_retries(env)? == 0 {
if storage::pin_retries(env, slot_id)? == 0 {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_BLOCKED);
}
let shared_secret = self.get_shared_secret(pin_uv_auth_protocol, key_agreement)?;
self.verify_pin_hash_enc(
env,
slot_id,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc,
)?;
if storage::has_force_pin_change(env)? {
if storage::has_force_pin_change(env, slot_id)? {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID);
}
self.pin_protocol_v1.reset_pin_uv_auth_token(env.rng());
self.pin_protocol_v2.reset_pin_uv_auth_token(env.rng());
self.pin_uv_auth_token_state
.begin_using_pin_uv_auth_token(now);
.begin_using_pin_uv_auth_token(now, slot_id);
self.pin_uv_auth_token_state.set_default_permissions();
let pin_uv_auth_token = shared_secret.encrypt(
env.rng(),
@@ -391,7 +412,9 @@ impl ClientPin {
now: CtapInstant,
) -> Result<ResponseData, Ctap2StatusCode> {
let response = match client_pin_params.sub_command {
ClientPinSubCommand::GetPinRetries => Some(self.process_get_pin_retries(env)?),
ClientPinSubCommand::GetPinRetries => {
Some(self.process_get_pin_retries(env, client_pin_params)?)
}
ClientPinSubCommand::GetKeyAgreement => {
Some(self.process_get_key_agreement(client_pin_params)?)
}
@@ -446,7 +469,9 @@ impl ClientPin {
self.pin_protocol_v1.reset_pin_uv_auth_token(rng);
self.pin_protocol_v2.regenerate(rng);
self.pin_protocol_v2.reset_pin_uv_auth_token(rng);
self.consecutive_pin_mismatches = 0;
for v in &mut self.consecutive_pin_mismatches {
*v = 0;
}
self.pin_uv_auth_token_state.stop_using_pin_uv_auth_token();
}
@@ -555,24 +580,38 @@ impl ClientPin {
self.pin_uv_auth_token_state.has_permissions_rp_id(rp_id)
}
/// Get the slot_id_in_use of the current pin_uv_auth_token_state if multi-PIN
/// feature is enabled. Otherwise return the default slot (0).
pub fn get_slot_id_in_use_or_default(
&self,
env: &mut impl Env,
) -> Result<Option<usize>, Ctap2StatusCode> {
if storage::has_multi_pin(env)? {
Ok(self.pin_uv_auth_token_state.slot_id_in_use())
} else {
Ok(Some(0))
}
}
#[cfg(test)]
pub fn new_test(
env: &mut impl Env,
slot_id: usize,
key_agreement_key: crypto::ecdh::SecKey,
pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH],
pin_uv_auth_protocol: PinUvAuthProtocol,
) -> ClientPin {
let mut env = crate::env::test::TestEnv::new();
let (key_agreement_key_v1, key_agreement_key_v2) = match pin_uv_auth_protocol {
PinUvAuthProtocol::V1 => (key_agreement_key, crypto::ecdh::SecKey::gensk(env.rng())),
PinUvAuthProtocol::V2 => (crypto::ecdh::SecKey::gensk(env.rng()), key_agreement_key),
};
let mut pin_uv_auth_token_state = PinUvAuthTokenState::new();
pin_uv_auth_token_state.set_permissions(0xFF);
pin_uv_auth_token_state.begin_using_pin_uv_auth_token(CtapInstant::new(0));
pin_uv_auth_token_state.begin_using_pin_uv_auth_token(CtapInstant::new(0), slot_id);
ClientPin {
pin_protocol_v1: PinProtocol::new_test(key_agreement_key_v1, pin_uv_auth_token),
pin_protocol_v2: PinProtocol::new_test(key_agreement_key_v2, pin_uv_auth_token),
consecutive_pin_mismatches: 0,
consecutive_pin_mismatches: vec![0; env.customization().slot_count()],
pin_uv_auth_token_state,
}
}
@@ -592,7 +631,7 @@ mod test {
pin[..4].copy_from_slice(b"1234");
let mut pin_hash = [0u8; 16];
pin_hash.copy_from_slice(&Sha256::hash(&pin[..])[..16]);
storage::set_pin(env, &pin_hash, 4).unwrap();
storage::set_pin(env, 0, &pin_hash, 4).unwrap();
}
/// Fails on PINs bigger than 64 bytes.
@@ -611,6 +650,7 @@ mod test {
/// tests using the wrong combination of PIN protocol and shared secret
/// should fail.
fn create_client_pin_and_shared_secret(
slot_id: usize,
pin_uv_auth_protocol: PinUvAuthProtocol,
) -> (ClientPin, Box<dyn SharedSecret>) {
let mut env = TestEnv::new();
@@ -618,8 +658,13 @@ mod test {
let pk = key_agreement_key.genpk();
let key_agreement = CoseKey::from(pk);
let pin_uv_auth_token = [0x91; PIN_TOKEN_LENGTH];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, pin_uv_auth_protocol);
let client_pin = ClientPin::new_test(
&mut env,
slot_id,
key_agreement_key,
pin_uv_auth_token,
pin_uv_auth_protocol,
);
let shared_secret = client_pin
.get_pin_protocol(pin_uv_auth_protocol)
.decapsulate(key_agreement, pin_uv_auth_protocol)
@@ -635,7 +680,9 @@ mod test {
sub_command: ClientPinSubCommand,
) -> (ClientPin, AuthenticatorClientPinParameters) {
let mut env = TestEnv::new();
let (client_pin, shared_secret) = create_client_pin_and_shared_secret(pin_uv_auth_protocol);
// TODO: Make slot_id a passed parameter once we include it in AuthenticatorClientPinParameters.
let (client_pin, shared_secret) =
create_client_pin_and_shared_secret(0, pin_uv_auth_protocol);
let pin = b"1234";
let mut padded_pin = [0u8; 64];
@@ -677,7 +724,7 @@ mod test {
#[test]
fn test_mix_pin_protocols() {
let mut env = TestEnv::new();
let client_pin = ClientPin::new(env.rng());
let client_pin = ClientPin::new(&mut env);
let pin_protocol_v1 = client_pin.get_pin_protocol(PinUvAuthProtocol::V1);
let pin_protocol_v2 = client_pin.get_pin_protocol(PinUvAuthProtocol::V2);
let message = vec![0xAA; 16];
@@ -718,7 +765,7 @@ mod test {
fn test_helper_verify_pin_hash_enc(pin_uv_auth_protocol: PinUvAuthProtocol) {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
let pin_protocol = client_pin.get_pin_protocol(pin_uv_auth_protocol);
let shared_secret = pin_protocol
.decapsulate(pin_protocol.get_public_key(), pin_uv_auth_protocol)
@@ -728,7 +775,7 @@ mod test {
0x01, 0xD9, 0x88, 0x40, 0x50, 0xBB, 0xD0, 0x7A, 0x23, 0x1A, 0xEB, 0x69, 0xD8, 0x36,
0xC4, 0x12,
];
storage::set_pin(&mut env, &pin_hash, 4).unwrap();
storage::set_pin(&mut env, 0, &pin_hash, 4).unwrap();
let pin_hash_enc = shared_secret
.as_ref()
@@ -737,6 +784,7 @@ mod test {
assert_eq!(
client_pin.verify_pin_hash_enc(
&mut env,
0,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc
@@ -748,6 +796,7 @@ mod test {
assert_eq!(
client_pin.verify_pin_hash_enc(
&mut env,
0,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc
@@ -759,22 +808,24 @@ mod test {
.as_ref()
.encrypt(env.rng(), &pin_hash)
.unwrap();
client_pin.consecutive_pin_mismatches = 3;
client_pin.consecutive_pin_mismatches[0] = 3;
assert_eq!(
client_pin.verify_pin_hash_enc(
&mut env,
0,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc
),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED)
);
client_pin.consecutive_pin_mismatches = 0;
client_pin.consecutive_pin_mismatches[0] = 0;
let pin_hash_enc = vec![0x77; PIN_AUTH_LENGTH - 1];
assert_eq!(
client_pin.verify_pin_hash_enc(
&mut env,
0,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc
@@ -786,6 +837,7 @@ mod test {
assert_eq!(
client_pin.verify_pin_hash_enc(
&mut env,
0,
pin_uv_auth_protocol,
shared_secret.as_ref(),
pin_hash_enc
@@ -813,7 +865,7 @@ mod test {
let expected_response = Some(AuthenticatorClientPinResponse {
key_agreement: None,
pin_uv_auth_token: None,
retries: Some(storage::pin_retries(&mut env).unwrap() as u64),
retries: Some(storage::pin_retries(&mut env, 0).unwrap() as u64),
power_cycle_state: Some(false),
});
assert_eq!(
@@ -821,11 +873,11 @@ mod test {
Ok(ResponseData::AuthenticatorClientPin(expected_response))
);
client_pin.consecutive_pin_mismatches = 3;
client_pin.consecutive_pin_mismatches[0] = 3;
let expected_response = Some(AuthenticatorClientPinResponse {
key_agreement: None,
pin_uv_auth_token: None,
retries: Some(storage::pin_retries(&mut env).unwrap() as u64),
retries: Some(storage::pin_retries(&mut env, 0).unwrap() as u64),
power_cycle_state: Some(true),
});
assert_eq!(
@@ -921,8 +973,8 @@ mod test {
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
while storage::pin_retries(&mut env).unwrap() > 0 {
storage::decr_pin_retries(&mut env).unwrap();
while storage::pin_retries(&mut env, 0).unwrap() > 0 {
storage::decr_pin_retries(&mut env, 0).unwrap();
}
assert_eq!(
client_pin.process_command(&mut env, params, CtapInstant::new(0)),
@@ -1015,7 +1067,7 @@ mod test {
let mut env = TestEnv::new();
set_standard_pin(&mut env);
assert_eq!(storage::force_pin_change(&mut env), Ok(()));
assert_eq!(storage::force_pin_change(&mut env, 0), Ok(()));
assert_eq!(
client_pin.process_command(&mut env, params, CtapInstant::new(0)),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID),
@@ -1125,7 +1177,7 @@ mod test {
let mut env = TestEnv::new();
set_standard_pin(&mut env);
assert_eq!(storage::force_pin_change(&mut env), Ok(()));
assert_eq!(storage::force_pin_change(&mut env, 0), Ok(()));
assert_eq!(
client_pin.process_command(&mut env, params, CtapInstant::new(0)),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID)
@@ -1217,17 +1269,17 @@ mod test {
),
];
for (pin, result) in test_cases {
let old_pin_hash = storage::pin_hash(&mut env).unwrap();
let old_pin_hash = storage::pin_hash(&mut env, 0).unwrap();
let new_pin_enc = encrypt_pin(shared_secret.as_ref(), pin);
assert_eq!(
check_and_store_new_pin(&mut env, shared_secret.as_ref(), new_pin_enc),
check_and_store_new_pin(&mut env, 0, shared_secret.as_ref(), new_pin_enc),
result
);
if result.is_ok() {
assert_ne!(old_pin_hash, storage::pin_hash(&mut env).unwrap());
assert_ne!(old_pin_hash, storage::pin_hash(&mut env, 0).unwrap());
} else {
assert_eq!(old_pin_hash, storage::pin_hash(&mut env).unwrap());
assert_eq!(old_pin_hash, storage::pin_hash(&mut env, 0).unwrap());
}
}
}
@@ -1249,7 +1301,8 @@ mod test {
salt: Vec<u8>,
) -> Result<Vec<u8>, Ctap2StatusCode> {
let mut env = TestEnv::new();
let (client_pin, shared_secret) = create_client_pin_and_shared_secret(pin_uv_auth_protocol);
let (client_pin, shared_secret) =
create_client_pin_and_shared_secret(0, pin_uv_auth_protocol);
let salt_enc = shared_secret.as_ref().encrypt(env.rng(), &salt).unwrap();
let salt_auth = shared_secret.authenticate(&salt_enc);
@@ -1267,7 +1320,8 @@ mod test {
fn test_helper_process_hmac_secret_bad_salt_auth(pin_uv_auth_protocol: PinUvAuthProtocol) {
let mut env = TestEnv::new();
let (client_pin, shared_secret) = create_client_pin_and_shared_secret(pin_uv_auth_protocol);
let (client_pin, shared_secret) =
create_client_pin_and_shared_secret(0, pin_uv_auth_protocol);
let cred_random = [0xC9; 32];
let salt_enc = vec![0x01; 32];
@@ -1383,7 +1437,7 @@ mod test {
#[test]
fn test_has_permission() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
client_pin.pin_uv_auth_token_state.set_permissions(0x7F);
for permission in PinPermission::into_enum_iter() {
assert_eq!(
@@ -1407,7 +1461,7 @@ mod test {
#[test]
fn test_has_no_rp_id_permission() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
assert_eq!(client_pin.has_no_rp_id_permission(), Ok(()));
client_pin
.pin_uv_auth_token_state
@@ -1421,7 +1475,7 @@ mod test {
#[test]
fn test_has_no_or_rp_id_permission() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
assert_eq!(client_pin.has_no_or_rp_id_permission("example.com"), Ok(()));
client_pin
.pin_uv_auth_token_state
@@ -1436,7 +1490,7 @@ mod test {
#[test]
fn test_has_no_or_rp_id_hash_permission() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
let rp_id_hash = Sha256::hash(b"example.com");
assert_eq!(
client_pin.has_no_or_rp_id_hash_permission(&rp_id_hash),
@@ -1458,7 +1512,7 @@ mod test {
#[test]
fn test_ensure_rp_id_permission() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
assert_eq!(client_pin.ensure_rp_id_permission("example.com"), Ok(()));
assert_eq!(
client_pin
@@ -1476,11 +1530,11 @@ mod test {
#[test]
fn test_verify_pin_uv_auth_token() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
let message = [0xAA];
client_pin
.pin_uv_auth_token_state
.begin_using_pin_uv_auth_token(CtapInstant::new(0));
.begin_using_pin_uv_auth_token(CtapInstant::new(0), 0);
let pin_uv_auth_token_v1 = client_pin
.get_pin_protocol(PinUvAuthProtocol::V1)
@@ -1497,6 +1551,7 @@ mod test {
let pin_uv_auth_param_v2_from_v1_token =
authenticate_pin_uv_auth_token(pin_uv_auth_token_v1, &message, PinUvAuthProtocol::V2);
assert_eq!(client_pin.pin_uv_auth_token_state.slot_id_in_use(), Some(0));
assert_eq!(
client_pin.verify_pin_uv_auth_token(
&message,
@@ -1550,7 +1605,7 @@ mod test {
#[test]
fn test_verify_pin_uv_auth_token_not_in_use() {
let mut env = TestEnv::new();
let client_pin = ClientPin::new(env.rng());
let client_pin = ClientPin::new(&mut env);
let message = [0xAA];
let pin_uv_auth_token_v1 = client_pin
@@ -1572,7 +1627,7 @@ mod test {
#[test]
fn test_reset() {
let mut env = TestEnv::new();
let mut client_pin = ClientPin::new(env.rng());
let mut client_pin = ClientPin::new(&mut env);
let public_key_v1 = client_pin.pin_protocol_v1.get_public_key();
let public_key_v2 = client_pin.pin_protocol_v2.get_public_key();
let token_v1 = *client_pin.pin_protocol_v1.get_pin_uv_auth_token();

View File

@@ -55,15 +55,21 @@ fn process_set_min_pin_length(
if new_min_pin_length < store_min_pin_length {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION);
}
let mut force_change_pin = force_change_pin.unwrap_or(false);
if force_change_pin && storage::pin_hash(env)?.is_none() {
let force_change_pin = force_change_pin.unwrap_or(false);
if force_change_pin && !storage::has_pin(env)? {
return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET);
}
if let Some(old_length) = storage::pin_code_point_length(env)? {
force_change_pin |= new_min_pin_length > old_length;
}
if force_change_pin {
storage::force_pin_change(env)?;
for slot_id in 0..env.customization().slot_count() {
if storage::pin_hash(env, slot_id)?.is_none() {
continue;
}
let mut force_change_pin = force_change_pin;
if let Some(old_length) = storage::pin_code_point_length(env, slot_id)? {
force_change_pin |= new_min_pin_length > old_length;
}
if force_change_pin {
storage::force_pin_change(env, slot_id)?;
}
}
storage::set_min_pin_length(env, new_min_pin_length)?;
if let Some(min_pin_length_rp_ids) = min_pin_length_rp_ids {
@@ -85,9 +91,13 @@ pub fn process_config(
pin_uv_auth_protocol,
} = params;
let slot_id = client_pin.get_slot_id_in_use_or_default(env)?;
let enforce_uv =
!matches!(sub_command, ConfigSubCommand::ToggleAlwaysUv) && storage::has_always_uv(env)?;
if storage::pin_hash(env)?.is_some() || enforce_uv {
// If multi-PIN feature is enabled, no PIN is in use, and the command is to turn off alwaysUv,
// the PIN check will be skipped here but an OPERATION_DENIED will still be returned later,
// which is correct behavior.
if (slot_id.is_some() && storage::pin_hash(env, slot_id.unwrap())?.is_some()) || enforce_uv {
let pin_uv_auth_param =
pin_uv_auth_param.ok_or(Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED)?;
let pin_uv_auth_protocol =
@@ -133,8 +143,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let config_params = AuthenticatorConfigParameters {
sub_command: ConfigSubCommand::EnableEnterpriseAttestation,
@@ -160,8 +175,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let config_params = AuthenticatorConfigParameters {
sub_command: ConfigSubCommand::ToggleAlwaysUv,
@@ -195,9 +215,14 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, pin_uv_auth_protocol);
storage::set_pin(&mut env, &[0x88; 16], 4).unwrap();
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
pin_uv_auth_protocol,
);
storage::set_pin(&mut env, 0, &[0x88; 16], 4).unwrap();
let mut config_data = vec![0xFF; 32];
config_data.extend(&[0x0D, ConfigSubCommand::ToggleAlwaysUv as u8]);
@@ -265,8 +290,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
// First, increase minimum PIN length from 4 to 6 without PIN auth.
let min_pin_length = 6;
@@ -277,7 +307,7 @@ mod test {
// Second, increase minimum PIN length from 6 to 8 with PIN auth.
// The stored PIN or its length don't matter since we control the token.
storage::set_pin(&mut env, &[0x88; 16], 8).unwrap();
storage::set_pin(&mut env, 0, &[0x88; 16], 8).unwrap();
let min_pin_length = 8;
let mut config_params = create_min_pin_config_params(min_pin_length, None);
let pin_uv_auth_param = vec![
@@ -309,8 +339,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
// First, set RP IDs without PIN auth.
let min_pin_length = 6;
@@ -329,7 +364,7 @@ mod test {
let min_pin_length = 8;
let min_pin_length_rp_ids = vec!["another.example.com".to_string()];
// The stored PIN or its length don't matter since we control the token.
storage::set_pin(&mut env, &[0x88; 16], 8).unwrap();
storage::set_pin(&mut env, 0, &[0x88; 16], 8).unwrap();
let mut config_params =
create_min_pin_config_params(min_pin_length, Some(min_pin_length_rp_ids.clone()));
let pin_uv_auth_param = vec![
@@ -385,10 +420,15 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
storage::set_pin(&mut env, &[0x88; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0x88; 16], 4).unwrap();
// Increase min PIN, force PIN change.
let min_pin_length = 6;
let mut config_params = create_min_pin_config_params(min_pin_length, None);
@@ -400,7 +440,7 @@ mod test {
let config_response = process_config(&mut env, &mut client_pin, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(storage::min_pin_length(&mut env), Ok(min_pin_length));
assert_eq!(storage::has_force_pin_change(&mut env), Ok(true));
assert_eq!(storage::has_force_pin_change(&mut env, 0), Ok(true));
}
#[test]
@@ -408,10 +448,15 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
storage::set_pin(&mut env, &[0x88; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0x88; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0xE3, 0x74, 0xF4, 0x27, 0xBE, 0x7D, 0x40, 0xB5, 0x71, 0xB6, 0xB4, 0x1A, 0xD2, 0xC1,
0x53, 0xD7,
@@ -431,7 +476,7 @@ mod test {
};
let config_response = process_config(&mut env, &mut client_pin, config_params);
assert_eq!(config_response, Ok(ResponseData::AuthenticatorConfig));
assert_eq!(storage::has_force_pin_change(&mut env), Ok(true));
assert_eq!(storage::has_force_pin_change(&mut env, 0), Ok(true));
}
#[test]
@@ -439,8 +484,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let config_params = AuthenticatorConfigParameters {
sub_command: ConfigSubCommand::VendorPrototype,

View File

@@ -19,7 +19,7 @@ use super::data_formats::{
use super::status_code::Ctap2StatusCode;
use super::{cbor_read, cbor_write};
use crate::api::key_store::KeyStore;
use crate::ctap::data_formats::{extract_byte_string, extract_map};
use crate::ctap::data_formats::{extract_byte_string, extract_map, extract_unsigned};
use crate::env::Env;
use alloc::string::String;
use alloc::vec::Vec;
@@ -48,6 +48,7 @@ struct CredentialSource {
rp_id_hash: [u8; 32],
cred_protect_policy: Option<CredentialProtectionPolicy>,
cred_blob: Option<Vec<u8>>,
slot_id: Option<usize>,
}
// The data fields contained in the credential ID are serialized using CBOR maps.
@@ -57,6 +58,7 @@ enum CredentialSourceField {
RpIdHash = 1,
CredProtectPolicy = 2,
CredBlob = 3,
SlotId = 4,
}
impl From<CredentialSourceField> for sk_cbor::Value {
@@ -84,6 +86,7 @@ fn decrypt_legacy_credential_id(
rp_id_hash: plaintext[32..64].try_into().unwrap(),
cred_protect_policy: None,
cred_blob: None,
slot_id: None,
}))
}
@@ -102,6 +105,7 @@ fn decrypt_cbor_credential_id(
CredentialSourceField::RpIdHash=> rp_id_hash,
CredentialSourceField::CredProtectPolicy => cred_protect_policy,
CredentialSourceField::CredBlob => cred_blob,
CredentialSourceField::SlotId => slot_id,
} = extract_map(cbor_credential_source)?;
}
Ok(match (private_key, rp_id_hash) {
@@ -115,11 +119,19 @@ fn decrypt_cbor_credential_id(
.map(CredentialProtectionPolicy::try_from)
.transpose()?;
let cred_blob = cred_blob.map(extract_byte_string).transpose()?;
let slot_id = match slot_id.map(extract_unsigned).transpose()? {
Some(x) => Some(
usize::try_from(x)
.map_err(|_| Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?,
),
None => None,
};
Some(CredentialSource {
private_key,
rp_id_hash: rp_id_hash.try_into().unwrap(),
cred_protect_policy,
cred_blob,
slot_id,
})
}
_ => None,
@@ -167,6 +179,7 @@ pub fn encrypt_to_credential_id(
rp_id_hash: &[u8; 32],
cred_protect_policy: Option<CredentialProtectionPolicy>,
cred_blob: Option<Vec<u8>>,
slot_id: usize,
) -> Result<Vec<u8>, Ctap2StatusCode> {
let mut payload = Vec::new();
let cbor = cbor_map_options! {
@@ -174,6 +187,7 @@ pub fn encrypt_to_credential_id(
CredentialSourceField::RpIdHash=> rp_id_hash,
CredentialSourceField::CredProtectPolicy => cred_protect_policy,
CredentialSourceField::CredBlob => cred_blob,
CredentialSourceField::SlotId => slot_id as u64,
};
cbor_write(cbor, &mut payload)?;
add_padding(&mut payload)?;
@@ -262,6 +276,7 @@ pub fn decrypt_credential_id(
user_icon: None,
cred_blob: credential_source.cred_blob,
large_blob_key: None,
slot_id: credential_source.slot_id,
}))
}
@@ -282,7 +297,7 @@ mod test {
let rp_id_hash = [0x55; 32];
let encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None).unwrap();
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None, 0).unwrap();
let decrypted_source = decrypt_credential_id(&mut env, encrypted_id, &rp_id_hash)
.unwrap()
.unwrap();
@@ -308,7 +323,7 @@ mod test {
let rp_id_hash = [0x55; 32];
let mut encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None).unwrap();
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None, 0).unwrap();
encrypted_id[0] = UNSUPPORTED_CREDENTIAL_ID_VERSION;
// Override the HMAC to pass the check.
encrypted_id.truncate(&encrypted_id.len() - 32);
@@ -328,7 +343,7 @@ mod test {
let rp_id_hash = [0x55; 32];
let encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None).unwrap();
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None, 0).unwrap();
for i in 0..encrypted_id.len() {
let mut modified_id = encrypted_id.clone();
modified_id[i] ^= 0x01;
@@ -356,7 +371,7 @@ mod test {
let rp_id_hash = [0x55; 32];
let encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None).unwrap();
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None, 0).unwrap();
for length in (1..CBOR_CREDENTIAL_ID_SIZE).step_by(16) {
assert_eq!(
@@ -423,7 +438,7 @@ mod test {
let rp_id_hash = [0x55; 32];
let encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None).unwrap();
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None, 0).unwrap();
assert_eq!(encrypted_id.len(), CBOR_CREDENTIAL_ID_SIZE);
}
@@ -444,6 +459,7 @@ mod test {
&rp_id_hash,
cred_protect_policy,
cred_blob,
0,
);
assert!(encrypted_id.is_ok());
@@ -461,6 +477,7 @@ mod test {
&rp_id_hash,
Some(CredentialProtectionPolicy::UserVerificationRequired),
None,
0,
)
.unwrap();
@@ -481,9 +498,15 @@ mod test {
let rp_id_hash = [0x55; 32];
let cred_blob = Some(vec![0x55; env.customization().max_cred_blob_length()]);
let encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, cred_blob.clone())
.unwrap();
let encrypted_id = encrypt_to_credential_id(
&mut env,
&private_key,
&rp_id_hash,
None,
cred_blob.clone(),
0,
)
.unwrap();
let decrypted_source = decrypt_credential_id(&mut env, encrypted_id, &rp_id_hash)
.unwrap()
@@ -491,4 +514,22 @@ mod test {
assert_eq!(decrypted_source.private_key, private_key);
assert_eq!(decrypted_source.cred_blob, cred_blob);
}
#[test]
fn test_slot_id_persisted() {
let mut env = TestEnv::new();
let private_key = PrivateKey::new(&mut env, SignatureAlgorithm::Es256);
let rp_id_hash = [0x55; 32];
let slot_id = 1;
let encrypted_id =
encrypt_to_credential_id(&mut env, &private_key, &rp_id_hash, None, None, slot_id)
.unwrap();
let decrypted_source = decrypt_credential_id(&mut env, encrypted_id, &rp_id_hash)
.unwrap()
.unwrap();
assert_eq!(decrypted_source.private_key, private_key);
assert_eq!(decrypted_source.slot_id, Some(slot_id));
}
}

View File

@@ -81,6 +81,7 @@ fn enumerate_credentials_response(
user_icon,
cred_blob: _,
large_blob_key,
slot_id: _,
} = credential;
let user = PublicKeyCredentialUserEntity {
user_id: user_handle,
@@ -183,12 +184,17 @@ fn process_enumerate_credentials_begin(
.rp_id_hash
.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?;
client_pin.has_no_or_rp_id_hash_permission(&rp_id_hash[..])?;
// enumerateCredentials needs UV, so slot_id must not be None.
let slot_id = client_pin
.get_slot_id_in_use_or_default(env)?
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?;
let mut iter_result = Ok(());
let iter = storage::iter_credentials(env, &mut iter_result)?;
let mut rp_credentials: Vec<usize> = iter
.filter_map(|(key, credential)| {
let cred_rp_id_hash = Sha256::hash(credential.rp_id.as_bytes());
if cred_rp_id_hash == rp_id_hash.as_slice() {
let slot_id_matches = credential.slot_id.unwrap_or(0) == slot_id;
if cred_rp_id_hash == rp_id_hash.as_slice() && slot_id_matches {
Some(key)
} else {
None
@@ -385,6 +391,7 @@ mod test {
user_icon: Some("icon".to_string()),
cred_blob: None,
large_blob_key: None,
slot_id: None,
}
}
@@ -392,14 +399,19 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, pin_uv_auth_protocol);
let client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
pin_uv_auth_protocol,
);
let credential_source = create_credential_source(&mut env);
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
ctap_state.client_pin = client_pin;
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let management_data = vec![CredentialManagementSubCommand::GetCredsMetadata as u8];
let pin_uv_auth_param = authenticate_pin_uv_auth_token(
&pin_uv_auth_token,
@@ -474,8 +486,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let credential_source1 = create_credential_source(&mut env);
let mut credential_source2 = create_credential_source(&mut env);
credential_source2.rp_id = "another.example.com".to_string();
@@ -486,7 +503,7 @@ mod test {
storage::store_credential(&mut env, credential_source1).unwrap();
storage::store_credential(&mut env, credential_source2).unwrap();
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0x1A, 0xA4, 0x96, 0xDA, 0x62, 0x80, 0x28, 0x13, 0xEB, 0x32, 0xB9, 0xF1, 0xD2, 0xA9,
0xD0, 0xD1,
@@ -568,8 +585,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let credential_source = create_credential_source(&mut env);
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
@@ -582,7 +604,7 @@ mod test {
storage::store_credential(&mut env, credential).unwrap();
}
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0x1A, 0xA4, 0x96, 0xDA, 0x62, 0x80, 0x28, 0x13, 0xEB, 0x32, 0xB9, 0xF1, 0xD2, 0xA9,
0xD0, 0xD1,
@@ -649,8 +671,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let credential_source1 = create_credential_source(&mut env);
let mut credential_source2 = create_credential_source(&mut env);
credential_source2.user_handle = vec![0x02];
@@ -664,7 +691,7 @@ mod test {
storage::store_credential(&mut env, credential_source1).unwrap();
storage::store_credential(&mut env, credential_source2).unwrap();
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0xF8, 0xB0, 0x3C, 0xC1, 0xD5, 0x58, 0x9C, 0xB7, 0x4D, 0x42, 0xA1, 0x64, 0x14, 0x28,
0x2B, 0x68,
@@ -746,13 +773,132 @@ mod test {
);
}
#[test]
fn test_process_enumerate_credentials_multi_pin() {
let mut env = TestEnv::new();
storage::_enable_multi_pin_for_test(&mut env).unwrap();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin = ClientPin::new_test(
&mut env,
1,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
// credential_source1 has no slot_id, so should be treated as slot 0. Only credential_source 2 and 4
// should be discovered.
let credential_source1 = create_credential_source(&mut env);
let mut credential_source2 = create_credential_source(&mut env);
credential_source2.user_handle = vec![0x02];
credential_source2.slot_id = Some(1);
let mut credential_source3 = create_credential_source(&mut env);
credential_source3.user_handle = vec![0x03];
credential_source3.slot_id = Some(2);
let mut credential_source4 = create_credential_source(&mut env);
credential_source4.user_handle = vec![0x04];
credential_source4.slot_id = Some(1);
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
ctap_state.client_pin = client_pin;
storage::store_credential(&mut env, credential_source1).unwrap();
storage::store_credential(&mut env, credential_source2).unwrap();
storage::store_credential(&mut env, credential_source3).unwrap();
storage::store_credential(&mut env, credential_source4).unwrap();
storage::set_pin(&mut env, 1, &[0u8; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0xF8, 0xB0, 0x3C, 0xC1, 0xD5, 0x58, 0x9C, 0xB7, 0x4D, 0x42, 0xA1, 0x64, 0x14, 0x28,
0x2B, 0x68,
]);
let sub_command_params = CredentialManagementSubCommandParameters {
rp_id_hash: Some(Sha256::hash(b"example.com").to_vec()),
credential_id: None,
user: None,
};
// RP ID hash:
// A379A6F6EEAFB9A55E378C118034E2751E682FAB9F2D30AB13D2125586CE1947
let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsBegin,
sub_command_params: Some(sub_command_params),
pin_uv_auth_protocol: Some(PinUvAuthProtocol::V1),
pin_uv_auth_param,
};
let cred_management_response = process_credential_management(
&mut env,
&mut ctap_state.stateful_command_permission,
&mut ctap_state.client_pin,
cred_management_params,
DUMMY_CHANNEL,
CtapInstant::new(0),
);
match cred_management_response.unwrap() {
ResponseData::AuthenticatorCredentialManagement(Some(response)) => {
assert!(response.user.is_some());
assert!(response.public_key.is_some());
assert_eq!(response.total_credentials, Some(2));
}
_ => panic!("Invalid response type"),
};
let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential,
sub_command_params: None,
pin_uv_auth_protocol: None,
pin_uv_auth_param: None,
};
let cred_management_response = process_credential_management(
&mut env,
&mut ctap_state.stateful_command_permission,
&mut ctap_state.client_pin,
cred_management_params,
DUMMY_CHANNEL,
CtapInstant::new(0),
);
match cred_management_response.unwrap() {
ResponseData::AuthenticatorCredentialManagement(Some(response)) => {
assert!(response.user.is_some());
assert!(response.public_key.is_some());
assert_eq!(response.total_credentials, None);
}
_ => panic!("Invalid response type"),
};
let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::EnumerateCredentialsGetNextCredential,
sub_command_params: None,
pin_uv_auth_protocol: None,
pin_uv_auth_param: None,
};
let cred_management_response = process_credential_management(
&mut env,
&mut ctap_state.stateful_command_permission,
&mut ctap_state.client_pin,
cred_management_params,
DUMMY_CHANNEL,
CtapInstant::new(0),
);
assert_eq!(
cred_management_response,
Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED)
);
}
#[test]
fn test_process_delete_credential() {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut credential_source = create_credential_source(&mut env);
credential_source.credential_id = vec![0x1D; 32];
@@ -761,7 +907,7 @@ mod test {
storage::store_credential(&mut env, credential_source).unwrap();
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0xBD, 0xE3, 0xEF, 0x8A, 0x77, 0x01, 0xB1, 0x69, 0x19, 0xE6, 0x62, 0xB9, 0x9B, 0x89,
0x9C, 0x64,
@@ -821,8 +967,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut credential_source = create_credential_source(&mut env);
credential_source.credential_id = vec![0x1D; 32];
@@ -831,7 +982,7 @@ mod test {
storage::store_credential(&mut env, credential_source).unwrap();
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let pin_uv_auth_param = Some(vec![
0xA5, 0x55, 0x8F, 0x03, 0xC3, 0xD3, 0x73, 0x1C, 0x07, 0xDA, 0x1F, 0x8C, 0xC7, 0xBD,
0x9D, 0xB7,
@@ -889,7 +1040,7 @@ mod test {
let mut env = TestEnv::new();
let mut ctap_state = CtapState::new(&mut env, CtapInstant::new(0));
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let cred_management_params = AuthenticatorCredentialManagementParameters {
sub_command: CredentialManagementSubCommand::GetCredsMetadata,

View File

@@ -249,7 +249,7 @@ impl Ctap1Command {
.ecdsa_key(env)
.map_err(|_| Ctap1StatusCode::SW_INTERNAL_EXCEPTION)?;
let pk = sk.genpk();
let key_handle = encrypt_to_credential_id(env, &private_key, &application, None, None)
let key_handle = encrypt_to_credential_id(env, &private_key, &application, None, None, 0)
.map_err(|_| Ctap1StatusCode::SW_INTERNAL_EXCEPTION)?;
if key_handle.len() > 0xFF {
// This is just being defensive with unreachable code.
@@ -320,11 +320,12 @@ impl Ctap1Command {
return Err(Ctap1StatusCode::SW_COND_USE_NOT_SATISFIED);
}
ctap_state
.increment_global_signature_counter(env)
.increment_global_signature_counter(env, 0)
.map_err(|_| Ctap1StatusCode::SW_WRONG_DATA)?;
let mut signature_data = ctap_state
.generate_auth_data(
env,
0,
&application,
Ctap1Command::USER_PRESENCE_INDICATOR_BYTE,
)
@@ -498,7 +499,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let message = create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
let response =
@@ -516,7 +518,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let application = [0x55; 32];
let message = create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
@@ -535,7 +538,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let mut message = create_authenticate_message(
&application,
Ctap1Flags::DontEnforceUpAndSign,
@@ -573,7 +577,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let mut message =
create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
message[0] = 0xEE;
@@ -593,7 +598,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let mut message =
create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
message[1] = 0xEE;
@@ -613,7 +619,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let mut message =
create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle);
message[2] = 0xEE;
@@ -641,7 +648,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let message =
create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle);
@@ -651,7 +659,7 @@ mod test {
Ctap1Command::process_command(&mut env, &message, &mut ctap_state, CtapInstant::new(0))
.unwrap();
assert_eq!(response[0], 0x01);
let global_signature_counter = storage::global_signature_counter(&mut env).unwrap();
let global_signature_counter = storage::global_signature_counter(&mut env, 0).unwrap();
check_signature_counter(
&mut env,
array_ref!(response, 1, 4),
@@ -669,7 +677,8 @@ mod test {
let rp_id = "example.com";
let application = crypto::sha256::Sha256::hash(rp_id.as_bytes());
let key_handle = encrypt_to_credential_id(&mut env, &sk, &application, None, None).unwrap();
let key_handle =
encrypt_to_credential_id(&mut env, &sk, &application, None, None, 0).unwrap();
let message = create_authenticate_message(
&application,
Ctap1Flags::DontEnforceUpAndSign,
@@ -684,7 +693,7 @@ mod test {
)
.unwrap();
assert_eq!(response[0], 0x01);
let global_signature_counter = storage::global_signature_counter(&mut env).unwrap();
let global_signature_counter = storage::global_signature_counter(&mut env, 0).unwrap();
check_signature_counter(
&mut env,
array_ref!(response, 1, 4),

View File

@@ -595,6 +595,7 @@ pub struct PublicKeyCredentialSource {
pub user_icon: Option<String>,
pub cred_blob: Option<Vec<u8>>,
pub large_blob_key: Option<Vec<u8>>,
pub slot_id: Option<usize>,
}
// We serialize credentials for the persistent storage using CBOR maps. Each field of a credential
@@ -613,6 +614,7 @@ enum PublicKeyCredentialSourceField {
CredBlob = 10,
LargeBlobKey = 11,
PrivateKey = 12,
SlotId = 13,
// When a field is removed, its tag should be reserved and not used for new fields. We document
// those reserved tags below.
// Reserved tags:
@@ -639,6 +641,7 @@ impl From<PublicKeyCredentialSource> for cbor::Value {
PublicKeyCredentialSourceField::CredBlob => credential.cred_blob,
PublicKeyCredentialSourceField::LargeBlobKey => credential.large_blob_key,
PublicKeyCredentialSourceField::PrivateKey => credential.private_key,
PublicKeyCredentialSourceField::SlotId => credential.slot_id.map(|x| x as u64),
}
}
}
@@ -661,6 +664,7 @@ impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
PublicKeyCredentialSourceField::CredBlob => cred_blob,
PublicKeyCredentialSourceField::LargeBlobKey => large_blob_key,
PublicKeyCredentialSourceField::PrivateKey => private_key,
PublicKeyCredentialSourceField::SlotId => slot_id,
} = extract_map(cbor_value)?;
}
@@ -687,6 +691,12 @@ impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
.ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?,
(None, Some(k)) => k,
};
let slot_id = match slot_id.map(extract_unsigned).transpose()? {
Some(x) => Some(
usize::try_from(x).map_err(|_| Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?,
),
None => None,
};
// We don't return whether there were unknown fields in the CBOR value. This means that
// deserialization is not injective. In particular deserialization is only an inverse of
@@ -711,6 +721,7 @@ impl TryFrom<cbor::Value> for PublicKeyCredentialSource {
user_icon,
cred_blob,
large_blob_key,
slot_id,
})
}
}
@@ -2229,6 +2240,7 @@ mod test {
user_icon: None,
cred_blob: None,
large_blob_key: None,
slot_id: None,
};
assert_eq!(
@@ -2291,6 +2303,16 @@ mod test {
..credential
};
assert_eq!(
PublicKeyCredentialSource::try_from(cbor::Value::from(credential.clone())),
Ok(credential.clone())
);
let credential = PublicKeyCredentialSource {
slot_id: Some(1),
..credential
};
assert_eq!(
PublicKeyCredentialSource::try_from(cbor::Value::from(credential.clone())),
Ok(credential)
@@ -2315,6 +2337,7 @@ mod test {
user_icon: None,
cred_blob: None,
large_blob_key: None,
slot_id: None,
};
let source_cbor = cbor_map! {
@@ -2347,6 +2370,7 @@ mod test {
user_icon: None,
cred_blob: None,
large_blob_key: None,
slot_id: None,
};
let source_cbor = cbor_map! {

View File

@@ -87,7 +87,9 @@ impl LargeBlobs {
if offset != self.expected_next_offset {
return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_SEQ);
}
if storage::pin_hash(env)?.is_some() || storage::has_always_uv(env)? {
// We only check whether slot 0 has a PIN here because if multi-PIN is enabled,
// has_always_uv will always be true and the condition will always pass.
if storage::pin_hash(env, 0)?.is_some() || storage::has_always_uv(env)? {
let pin_uv_auth_param =
pin_uv_auth_param.ok_or(Ctap2StatusCode::CTAP2_ERR_PUAT_REQUIRED)?;
let pin_uv_auth_protocol =
@@ -147,8 +149,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut large_blobs = LargeBlobs::new();
let large_blob = vec![
@@ -178,8 +185,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 200;
@@ -240,8 +252,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 200;
@@ -286,8 +303,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 200;
@@ -332,8 +354,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut large_blobs = LargeBlobs::new();
let large_blobs_params = AuthenticatorLargeBlobsParameters {
@@ -355,8 +382,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, PinUvAuthProtocol::V1);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
PinUvAuthProtocol::V1,
);
let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 20;
@@ -383,8 +415,13 @@ mod test {
let mut env = TestEnv::new();
let key_agreement_key = crypto::ecdh::SecKey::gensk(env.rng());
let pin_uv_auth_token = [0x55; 32];
let mut client_pin =
ClientPin::new_test(key_agreement_key, pin_uv_auth_token, pin_uv_auth_protocol);
let mut client_pin = ClientPin::new_test(
&mut env,
0,
key_agreement_key,
pin_uv_auth_token,
pin_uv_auth_protocol,
);
let mut large_blobs = LargeBlobs::new();
const BLOB_LEN: usize = 20;
@@ -392,7 +429,7 @@ mod test {
let mut large_blob = vec![0x1B; DATA_LEN];
large_blob.extend_from_slice(&Sha256::hash(&large_blob[..])[..TRUNCATED_HASH_LEN]);
storage::set_pin(&mut env, &[0u8; 16], 4).unwrap();
storage::set_pin(&mut env, 0, &[0u8; 16], 4).unwrap();
let mut large_blob_data = vec![0xFF; 32];
// Command constant and offset bytes.
large_blob_data.extend(&[0x0C, 0x00, 0x00, 0x00, 0x00, 0x00]);

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ use alloc::vec::Vec;
use arrayref::array_ref;
use core::cmp;
use core::convert::TryInto;
use persistent_store::{fragment, StoreUpdate};
use persistent_store::{concat, fragment};
use rng256::Rng256;
use sk_cbor::cbor_array_vec;
@@ -237,9 +237,34 @@ pub fn new_creation_order(env: &mut impl Env) -> Result<u64, Ctap2StatusCode> {
Ok(max.unwrap_or(0).wrapping_add(1))
}
fn check_and_get_key_for_slot(
env: &mut impl Env,
slot_id: usize,
first_key: usize,
key_array: core::ops::Range<usize>,
) -> Result<usize, Ctap2StatusCode> {
if slot_id >= env.customization().slot_count() {
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
}
Ok(if slot_id == 0 {
first_key
} else {
key_array.start + slot_id - 1
})
}
/// Returns the global signature counter.
pub fn global_signature_counter(env: &mut impl Env) -> Result<u32, Ctap2StatusCode> {
match env.store().find(key::GLOBAL_SIGNATURE_COUNTER)? {
pub fn global_signature_counter(
env: &mut impl Env,
slot_id: usize,
) -> Result<u32, Ctap2StatusCode> {
let key = check_and_get_key_for_slot(
env,
slot_id,
key::FIRST_GLOBAL_SIGNATURE_COUNTER,
key::GLOBAL_SIGNATURE_COUNTER,
)?;
match env.store().find(key)? {
None => Ok(INITIAL_SIGNATURE_COUNTER),
Some(value) if value.len() == 4 => Ok(u32::from_ne_bytes(*array_ref!(&value, 0, 4))),
Some(_) => Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR),
@@ -249,13 +274,19 @@ pub fn global_signature_counter(env: &mut impl Env) -> Result<u32, Ctap2StatusCo
/// Increments the global signature counter.
pub fn incr_global_signature_counter(
env: &mut impl Env,
slot_id: usize,
increment: u32,
) -> Result<(), Ctap2StatusCode> {
let old_value = global_signature_counter(env)?;
let key = check_and_get_key_for_slot(
env,
slot_id,
key::FIRST_GLOBAL_SIGNATURE_COUNTER,
key::GLOBAL_SIGNATURE_COUNTER,
)?;
let old_value = global_signature_counter(env, slot_id)?;
// In hopes that servers handle the wrapping gracefully.
let new_value = old_value.wrapping_add(increment);
env.store()
.insert(key::GLOBAL_SIGNATURE_COUNTER, &new_value.to_ne_bytes())?;
env.store().insert(key, &new_value.to_ne_bytes())?;
Ok(())
}
@@ -273,9 +304,22 @@ pub fn cred_random_secret(env: &mut impl Env, has_uv: bool) -> Result<[u8; 32],
}
/// Reads the PIN properties and wraps them into PinProperties.
fn pin_properties(env: &mut impl Env) -> Result<Option<PinProperties>, Ctap2StatusCode> {
let pin_properties = match env.store().find(key::PIN_PROPERTIES)? {
None => return Ok(None),
fn pin_properties(
env: &mut impl Env,
slot_id: usize,
) -> Result<Option<PinProperties>, Ctap2StatusCode> {
let pin_properties = match concat::read(env.store(), key::PIN_PROPERTIES, slot_id as u8)? {
None => {
// Backward compatibility: old implementation where there is only 1 PIN slot
// uses the entry with key `FIRST_PIN_PROPERTIES`.
if slot_id != 0 {
return Ok(None);
}
match env.store().find(key::FIRST_PIN_PROPERTIES)? {
None => return Ok(None),
Some(pin_properties) => pin_properties,
}
}
Some(pin_properties) => pin_properties,
};
const PROPERTIES_LENGTH: usize = PIN_AUTH_LENGTH + 1;
@@ -288,14 +332,30 @@ fn pin_properties(env: &mut impl Env) -> Result<Option<PinProperties>, Ctap2Stat
}
}
/// Returns if PIN is set for at least one slot.
pub fn has_pin(env: &mut impl Env) -> Result<bool, Ctap2StatusCode> {
for slot_id in 0..env.customization().slot_count() {
if pin_hash(env, slot_id)?.is_some() {
return Ok(true);
}
}
Ok(false)
}
/// Returns the PIN hash if defined.
pub fn pin_hash(env: &mut impl Env) -> Result<Option<[u8; PIN_AUTH_LENGTH]>, Ctap2StatusCode> {
Ok(pin_properties(env)?.map(|p| p.hash))
pub fn pin_hash(
env: &mut impl Env,
slot_id: usize,
) -> Result<Option<[u8; PIN_AUTH_LENGTH]>, Ctap2StatusCode> {
Ok(pin_properties(env, slot_id)?.map(|p| p.hash))
}
/// Returns the length of the currently set PIN if defined.
pub fn pin_code_point_length(env: &mut impl Env) -> Result<Option<u8>, Ctap2StatusCode> {
Ok(pin_properties(env)?.map(|p| p.code_point_length))
pub fn pin_code_point_length(
env: &mut impl Env,
slot_id: usize,
) -> Result<Option<u8>, Ctap2StatusCode> {
Ok(pin_properties(env, slot_id)?.map(|p| p.code_point_length))
}
/// Sets the PIN hash and length.
@@ -303,26 +363,32 @@ pub fn pin_code_point_length(env: &mut impl Env) -> Result<Option<u8>, Ctap2Stat
/// If it was already defined, it is updated.
pub fn set_pin(
env: &mut impl Env,
slot_id: usize,
pin_hash: &[u8; PIN_AUTH_LENGTH],
pin_code_point_length: u8,
) -> Result<(), Ctap2StatusCode> {
concat::delete(env.store(), key::FORCE_PIN_CHANGE, slot_id as u8)?;
if slot_id == 0 {
// Backward compatibility: data might be stored in these entries for slot 0 as well.
env.store().remove(key::FIRST_FORCE_PIN_CHANGE)?;
env.store().remove(key::FIRST_PIN_PROPERTIES)?;
}
let mut pin_properties = [0; 1 + PIN_AUTH_LENGTH];
pin_properties[0] = pin_code_point_length;
pin_properties[1..].clone_from_slice(pin_hash);
Ok(env.store().transaction(&[
StoreUpdate::Insert {
key: key::PIN_PROPERTIES,
value: &pin_properties[..],
},
StoreUpdate::Remove {
key: key::FORCE_PIN_CHANGE,
},
])?)
concat::write(
env.store(),
key::PIN_PROPERTIES,
slot_id as u8,
&pin_properties[..],
)?;
Ok(())
}
/// Returns the number of remaining PIN retries.
pub fn pin_retries(env: &mut impl Env) -> Result<u8, Ctap2StatusCode> {
match env.store().find(key::PIN_RETRIES)? {
pub fn pin_retries(env: &mut impl Env, slot_id: usize) -> Result<u8, Ctap2StatusCode> {
let key = check_and_get_key_for_slot(env, slot_id, key::FIRST_PIN_RETRIES, key::PIN_RETRIES)?;
match env.store().find(key)? {
None => Ok(env.customization().max_pin_retries()),
Some(value) if value.len() == 1 => Ok(value[0]),
_ => Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR),
@@ -330,18 +396,20 @@ pub fn pin_retries(env: &mut impl Env) -> Result<u8, Ctap2StatusCode> {
}
/// Decrements the number of remaining PIN retries.
pub fn decr_pin_retries(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
let old_value = pin_retries(env)?;
pub fn decr_pin_retries(env: &mut impl Env, slot_id: usize) -> Result<(), Ctap2StatusCode> {
let key = check_and_get_key_for_slot(env, slot_id, key::FIRST_PIN_RETRIES, key::PIN_RETRIES)?;
let old_value = pin_retries(env, slot_id)?;
let new_value = old_value.saturating_sub(1);
if new_value != old_value {
env.store().insert(key::PIN_RETRIES, &[new_value])?;
env.store().insert(key, &[new_value])?;
}
Ok(())
}
/// Resets the number of remaining PIN retries.
pub fn reset_pin_retries(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
Ok(env.store().remove(key::PIN_RETRIES)?)
pub fn reset_pin_retries(env: &mut impl Env, slot_id: usize) -> Result<(), Ctap2StatusCode> {
let key = check_and_get_key_for_slot(env, slot_id, key::FIRST_PIN_RETRIES, key::PIN_RETRIES)?;
Ok(env.store().remove(key)?)
}
/// Returns the minimum PIN length.
@@ -467,17 +535,34 @@ pub fn reset(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
}
/// Returns whether the PIN needs to be changed before its next usage.
pub fn has_force_pin_change(env: &mut impl Env) -> Result<bool, Ctap2StatusCode> {
match env.store().find(key::FORCE_PIN_CHANGE)? {
None => Ok(false),
pub fn has_force_pin_change(env: &mut impl Env, slot_id: usize) -> Result<bool, Ctap2StatusCode> {
match concat::read(env.store(), key::FORCE_PIN_CHANGE, slot_id as u8)? {
None => {
if slot_id != 0 {
Ok(false)
} else {
// Backward compatibility: old implementation where there is only 1 PIN slot
// uses the entry with key `FIRST_FORCE_PIN_CHANGE`.
match env.store().find(key::FIRST_FORCE_PIN_CHANGE)? {
None => Ok(false),
Some(value) if value.is_empty() => Ok(true),
_ => Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR),
}
}
}
Some(value) if value.is_empty() => Ok(true),
_ => Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR),
}
}
/// Marks the PIN as outdated with respect to the new PIN policy.
pub fn force_pin_change(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
Ok(env.store().insert(key::FORCE_PIN_CHANGE, &[])?)
pub fn force_pin_change(env: &mut impl Env, slot_id: usize) -> Result<(), Ctap2StatusCode> {
Ok(concat::write(
env.store(),
key::FORCE_PIN_CHANGE,
slot_id as u8,
&[],
)?)
}
/// Returns whether enterprise attestation is enabled.
@@ -528,6 +613,25 @@ pub fn toggle_always_uv(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
}
}
/// Returns whether multi-PIN is enabled.
pub fn has_multi_pin(env: &mut impl Env) -> Result<bool, Ctap2StatusCode> {
match env.store().find(key::MULTI_PIN)? {
None => Ok(false),
Some(value) if value.is_empty() => Ok(true),
_ => Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR),
}
}
// TODO: Call this in config_commands after the whole multi-PIN feature is ready.
// Before that, this function only be used for testing purpose.
/// Enables multi-PIN, when disabled.
pub fn _enable_multi_pin_for_test(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
if !has_multi_pin(env)? {
env.store().insert(key::MULTI_PIN, &[])?;
}
Ok(())
}
impl From<persistent_store::StoreError> for Ctap2StatusCode {
fn from(error: persistent_store::StoreError) -> Ctap2StatusCode {
use persistent_store::StoreError;
@@ -651,6 +755,7 @@ mod test {
CredentialProtectionPolicy, PublicKeyCredentialSource, PublicKeyCredentialType,
};
use crate::env::test::TestEnv;
use persistent_store::StoreUpdate;
use rng256::Rng256;
fn create_credential_source(
@@ -672,6 +777,7 @@ mod test {
user_icon: None,
cred_blob: None,
large_blob_key: None,
slot_id: None,
}
}
@@ -868,6 +974,7 @@ mod test {
user_icon: None,
cred_blob: None,
large_blob_key: None,
slot_id: None,
};
assert_eq!(found_credential, Some(expected_credential));
}
@@ -899,8 +1006,8 @@ mod test {
let mut env = TestEnv::new();
// Pin hash is initially not set.
assert!(pin_hash(&mut env).unwrap().is_none());
assert!(pin_code_point_length(&mut env).unwrap().is_none());
assert!(pin_hash(&mut env, 0).unwrap().is_none());
assert!(pin_code_point_length(&mut env, 0).unwrap().is_none());
// Setting the pin sets the pin hash.
let random_data = env.rng().gen_uniform_u8x32();
@@ -909,17 +1016,131 @@ mod test {
let pin_hash_2 = *array_ref!(random_data, PIN_AUTH_LENGTH, PIN_AUTH_LENGTH);
let pin_length_1 = 4;
let pin_length_2 = 63;
set_pin(&mut env, &pin_hash_1, pin_length_1).unwrap();
assert_eq!(pin_hash(&mut env).unwrap(), Some(pin_hash_1));
assert_eq!(pin_code_point_length(&mut env).unwrap(), Some(pin_length_1));
set_pin(&mut env, &pin_hash_2, pin_length_2).unwrap();
assert_eq!(pin_hash(&mut env).unwrap(), Some(pin_hash_2));
assert_eq!(pin_code_point_length(&mut env).unwrap(), Some(pin_length_2));
set_pin(&mut env, 0, &pin_hash_1, pin_length_1).unwrap();
assert_eq!(pin_hash(&mut env, 0).unwrap(), Some(pin_hash_1));
assert_eq!(
pin_code_point_length(&mut env, 0).unwrap(),
Some(pin_length_1)
);
set_pin(&mut env, 0, &pin_hash_2, pin_length_2).unwrap();
assert_eq!(pin_hash(&mut env, 0).unwrap(), Some(pin_hash_2));
assert_eq!(
pin_code_point_length(&mut env, 0).unwrap(),
Some(pin_length_2)
);
// Resetting the storage resets the pin hash.
reset(&mut env).unwrap();
assert!(pin_hash(&mut env).unwrap().is_none());
assert!(pin_code_point_length(&mut env).unwrap().is_none());
assert!(pin_hash(&mut env, 0).unwrap().is_none());
assert!(pin_code_point_length(&mut env, 0).unwrap().is_none());
}
#[test]
fn test_pin_hash_and_length_multi_pin() {
let mut env = TestEnv::new();
for i in 0..env.customization().slot_count() {
// Pin hash is initially not set.
assert!(pin_hash(&mut env, i).unwrap().is_none());
assert!(pin_code_point_length(&mut env, i).unwrap().is_none());
}
// Setting the pin sets the pin hash.
let random_data = env.rng().gen_uniform_u8x32();
assert_eq!(random_data.len(), 2 * PIN_AUTH_LENGTH);
let pin_hash_1 = *array_ref!(random_data, 0, PIN_AUTH_LENGTH);
let pin_hash_2 = *array_ref!(random_data, PIN_AUTH_LENGTH, PIN_AUTH_LENGTH);
let pin_length_1 = 4;
let pin_length_2 = 63;
set_pin(&mut env, 1, &pin_hash_1, pin_length_1).unwrap();
assert_eq!(pin_hash(&mut env, 1).unwrap(), Some(pin_hash_1));
assert_eq!(
pin_code_point_length(&mut env, 1).unwrap(),
Some(pin_length_1)
);
// Other slots aren't affected.
assert!(pin_hash(&mut env, 0).unwrap().is_none());
assert!(pin_code_point_length(&mut env, 0).unwrap().is_none());
set_pin(&mut env, 1, &pin_hash_2, pin_length_2).unwrap();
assert_eq!(pin_hash(&mut env, 1).unwrap(), Some(pin_hash_2));
assert_eq!(
pin_code_point_length(&mut env, 1).unwrap(),
Some(pin_length_2)
);
// Other slots aren't affected.
assert!(pin_hash(&mut env, 0).unwrap().is_none());
assert!(pin_code_point_length(&mut env, 0).unwrap().is_none());
// Set PIN for multiple slots is supported.
set_pin(&mut env, 2, &pin_hash_1, pin_length_1).unwrap();
assert_eq!(pin_hash(&mut env, 2).unwrap(), Some(pin_hash_1));
assert_eq!(
pin_code_point_length(&mut env, 2).unwrap(),
Some(pin_length_1)
);
// Resetting the storage resets the pin hash.
reset(&mut env).unwrap();
for i in 0..env.customization().slot_count() {
assert!(pin_hash(&mut env, i).unwrap().is_none());
assert!(pin_code_point_length(&mut env, i).unwrap().is_none());
}
}
fn set_pin_legacy(
env: &mut impl Env,
pin_hash: &[u8; PIN_AUTH_LENGTH],
pin_code_point_length: u8,
) -> Result<(), Ctap2StatusCode> {
let mut pin_properties = [0; 1 + PIN_AUTH_LENGTH];
pin_properties[0] = pin_code_point_length;
pin_properties[1..].clone_from_slice(pin_hash);
Ok(env.store().transaction(&[
StoreUpdate::Insert {
key: key::FIRST_PIN_PROPERTIES,
value: &pin_properties[..],
},
StoreUpdate::Remove {
key: key::FIRST_FORCE_PIN_CHANGE,
},
])?)
}
#[test]
fn test_pin_hash_and_length_backward_compat() {
let mut env = TestEnv::new();
// Setting the pin sets the pin hash.
let random_data = env.rng().gen_uniform_u8x32();
assert_eq!(random_data.len(), 2 * PIN_AUTH_LENGTH);
let pin_hash_1 = *array_ref!(random_data, 0, PIN_AUTH_LENGTH);
let pin_hash_2 = *array_ref!(random_data, PIN_AUTH_LENGTH, PIN_AUTH_LENGTH);
let pin_length_1 = 4;
let pin_length_2 = 63;
assert!(set_pin_legacy(&mut env, &pin_hash_1, pin_length_1).is_ok());
// Should fallback to read from legacy storage location successfully.
assert_eq!(pin_hash(&mut env, 0).unwrap(), Some(pin_hash_1));
assert_eq!(
pin_code_point_length(&mut env, 0).unwrap(),
Some(pin_length_1)
);
// Fallback logic should only apply to slot 0.
assert!(pin_hash(&mut env, 1).unwrap().is_none());
assert!(pin_code_point_length(&mut env, 1).unwrap().is_none());
// Setting PIN again should use the new storage location, and erase the old one.
set_pin(&mut env, 0, &pin_hash_2, pin_length_2).unwrap();
assert_eq!(pin_hash(&mut env, 0).unwrap(), Some(pin_hash_2));
assert_eq!(
pin_code_point_length(&mut env, 0).unwrap(),
Some(pin_length_2)
);
assert_eq!(env.store().find(key::FIRST_PIN_PROPERTIES), Ok(None));
assert_eq!(env.store().find(key::FIRST_FORCE_PIN_CHANGE), Ok(None));
}
#[test]
@@ -928,24 +1149,76 @@ mod test {
// The pin retries is initially at the maximum.
assert_eq!(
pin_retries(&mut env),
pin_retries(&mut env, 0),
Ok(env.customization().max_pin_retries())
);
// Decrementing the pin retries decrements the pin retries.
for retries in (0..env.customization().max_pin_retries()).rev() {
decr_pin_retries(&mut env).unwrap();
assert_eq!(pin_retries(&mut env), Ok(retries));
decr_pin_retries(&mut env, 0).unwrap();
assert_eq!(pin_retries(&mut env, 0), Ok(retries));
}
// Decrementing the pin retries after zero does not modify the pin retries.
decr_pin_retries(&mut env).unwrap();
assert_eq!(pin_retries(&mut env), Ok(0));
decr_pin_retries(&mut env, 0).unwrap();
assert_eq!(pin_retries(&mut env, 0), Ok(0));
// Resetting the pin retries resets the pin retries.
reset_pin_retries(&mut env).unwrap();
reset_pin_retries(&mut env, 0).unwrap();
assert_eq!(
pin_retries(&mut env),
pin_retries(&mut env, 0),
Ok(env.customization().max_pin_retries())
);
}
#[test]
fn test_pin_retries_multi_pin() {
let mut env = TestEnv::new();
for i in 0..env.customization().slot_count() {
// The pin retries is initially at the maximum.
assert_eq!(
pin_retries(&mut env, i),
Ok(env.customization().max_pin_retries())
);
}
// Decrementing the pin retries decrements the pin retries.
for retries in (0..env.customization().max_pin_retries()).rev() {
decr_pin_retries(&mut env, 1).unwrap();
assert_eq!(pin_retries(&mut env, 1), Ok(retries));
// Other slots shouldn't be affected.
assert_eq!(
pin_retries(&mut env, 2),
Ok(env.customization().max_pin_retries())
);
}
// Decrementing the pin retries after zero does not modify the pin retries.
decr_pin_retries(&mut env, 1).unwrap();
assert_eq!(pin_retries(&mut env, 1), Ok(0));
// Operating on multiple slots is supported.
decr_pin_retries(&mut env, 2).unwrap();
assert_eq!(
pin_retries(&mut env, 2),
Ok(env.customization().max_pin_retries() - 1)
);
// Resetting the pin retries resets the pin retries.
reset_pin_retries(&mut env, 1).unwrap();
assert_eq!(
pin_retries(&mut env, 1),
Ok(env.customization().max_pin_retries())
);
// Other slots shouldn't be affected.
assert_eq!(
pin_retries(&mut env, 2),
Ok(env.customization().max_pin_retries() - 1)
);
assert_eq!(
pin_retries(&mut env, 3),
Ok(env.customization().max_pin_retries())
);
}
@@ -1088,11 +1361,56 @@ mod test {
let mut env = TestEnv::new();
let mut counter_value = 1;
assert_eq!(global_signature_counter(&mut env).unwrap(), counter_value);
assert_eq!(
global_signature_counter(&mut env, 0).unwrap(),
counter_value
);
for increment in 1..10 {
assert!(incr_global_signature_counter(&mut env, increment).is_ok());
assert!(incr_global_signature_counter(&mut env, 0, increment).is_ok());
counter_value += increment;
assert_eq!(global_signature_counter(&mut env).unwrap(), counter_value);
assert_eq!(
global_signature_counter(&mut env, 0).unwrap(),
counter_value
);
}
}
#[test]
fn test_global_signature_counter_multi_pin() {
let mut env = TestEnv::new();
let mut counter_value = 1;
for i in 0..env.customization().slot_count() {
assert_eq!(
global_signature_counter(&mut env, i).unwrap(),
counter_value
);
}
for increment in 1..10 {
assert!(incr_global_signature_counter(&mut env, 1, increment).is_ok());
counter_value += increment;
assert_eq!(
global_signature_counter(&mut env, 1).unwrap(),
counter_value
);
// Other slots aren't affected.
assert_eq!(global_signature_counter(&mut env, 2).unwrap(), 1);
}
let counter_value_for_slot_1 = counter_value;
counter_value = 1;
for increment in 1..10 {
assert!(incr_global_signature_counter(&mut env, 2, increment).is_ok());
counter_value += increment;
assert_eq!(
global_signature_counter(&mut env, 2).unwrap(),
counter_value
);
// Other slots aren't affected.
assert_eq!(
global_signature_counter(&mut env, 1).unwrap(),
counter_value_for_slot_1
);
}
}
@@ -1100,11 +1418,60 @@ mod test {
fn test_force_pin_change() {
let mut env = TestEnv::new();
assert!(!has_force_pin_change(&mut env).unwrap());
assert_eq!(force_pin_change(&mut env), Ok(()));
assert!(has_force_pin_change(&mut env).unwrap());
assert_eq!(set_pin(&mut env, &[0x88; 16], 8), Ok(()));
assert!(!has_force_pin_change(&mut env).unwrap());
assert!(!has_force_pin_change(&mut env, 0).unwrap());
assert_eq!(force_pin_change(&mut env, 0), Ok(()));
assert!(has_force_pin_change(&mut env, 0).unwrap());
assert_eq!(set_pin(&mut env, 0, &[0x88; 16], 8), Ok(()));
assert!(!has_force_pin_change(&mut env, 0).unwrap());
}
#[test]
fn test_force_pin_change_multi_pin() {
let mut env = TestEnv::new();
for i in 0..env.customization().slot_count() {
assert!(!has_force_pin_change(&mut env, i).unwrap());
}
assert_eq!(force_pin_change(&mut env, 1), Ok(()));
assert!(has_force_pin_change(&mut env, 1).unwrap());
// Other slots shouldn't be affected.
assert!(!has_force_pin_change(&mut env, 2).unwrap());
assert_eq!(set_pin(&mut env, 1, &[0x88; 16], 8), Ok(()));
assert!(!has_force_pin_change(&mut env, 1).unwrap());
// Other slots shouldn't be affected.
assert!(!has_force_pin_change(&mut env, 2).unwrap());
// Operating on multiple slots is supported.
assert_eq!(force_pin_change(&mut env, 2), Ok(()));
assert!(has_force_pin_change(&mut env, 2).unwrap());
assert!(!has_force_pin_change(&mut env, 1).unwrap());
}
fn force_pin_change_legacy(env: &mut impl Env) -> Result<(), Ctap2StatusCode> {
Ok(env.store().insert(key::FIRST_FORCE_PIN_CHANGE, &[])?)
}
#[test]
fn test_force_pin_change_backward_compat() {
let mut env = TestEnv::new();
assert!(!has_force_pin_change(&mut env, 0).unwrap());
assert!(!has_force_pin_change(&mut env, 1).unwrap());
assert_eq!(force_pin_change_legacy(&mut env), Ok(()));
// Should fallback to read from legacy storage location successfully.
assert!(has_force_pin_change(&mut env, 0).unwrap());
// Fallback logic should only apply to slot 0.
assert!(!has_force_pin_change(&mut env, 1).unwrap());
assert_eq!(set_pin(&mut env, 0, &[0x88; 16], 8), Ok(()));
assert!(!has_force_pin_change(&mut env, 0).unwrap());
// Old storage location should be cleared.
assert_eq!(env.store().find(key::FIRST_FORCE_PIN_CHANGE), Ok(None));
assert_eq!(force_pin_change(&mut env, 0), Ok(()));
assert!(has_force_pin_change(&mut env, 0).unwrap());
}
#[test]
@@ -1145,6 +1512,15 @@ mod test {
}
}
#[test]
fn test_multi_pin() {
let mut env = TestEnv::new();
assert!(!has_multi_pin(&mut env).unwrap());
assert_eq!(_enable_multi_pin_for_test(&mut env), Ok(()));
assert!(has_multi_pin(&mut env).unwrap());
}
#[test]
fn test_serialize_deserialize_credential() {
let mut env = TestEnv::new();
@@ -1162,6 +1538,7 @@ mod test {
user_icon: Some(String::from("icon")),
cred_blob: Some(vec![0xCB]),
large_blob_key: Some(vec![0x1B]),
slot_id: Some(1),
};
let serialized = serialize_credential(credential.clone()).unwrap();
let reconstructed = deserialize_credential(&serialized).unwrap();

View File

@@ -73,6 +73,37 @@ make_partition! {
// - When adding a (non-persistent) key below this message, make sure its value is bigger or
// equal than NUM_PERSISTENT_KEYS.
/// Whether multi-PIN is enabled.
///
/// The value must be empty. Only presence of the value matters.
MULTI_PIN = 983;
// Start of key arrays for multi-PIN feature: these fields are separated for each slots, so
// a unique key is needed for each slot. However, we reuse the existing fields and rename them
// to `FIRST_{KEY_NAME}` so the upgrade is backward compatible.
// Depending on `Customization::slot_count()`, only a prefix of those keys is used.
/// Whether the PIN needs to be changed each slot.
///
/// The PIN needs to be changed if the slot exists and its data is empty.
FORCE_PIN_CHANGE = 984;
/// The number of PIN retries for each slot, except the first.
PIN_RETRIES = 985..992;
/// The PIN hash and length for each slot.
///
/// If a slot is absent, there is no PIN set for that slot. The first byte represents
/// the length, the following are an array with the hash.
PIN_PROPERTIES = 992;
/// The global signature counters for each slot, except the first.
///
/// If the entry is absent, the counter is 0.
GLOBAL_SIGNATURE_COUNTER = 993..1000;
// End of key arrays for multi-PIN feature.
/// Reserved for future credential-related objects.
///
/// In particular, additional credentials could be added there by reducing the lower bound of
@@ -97,8 +128,10 @@ make_partition! {
/// If this entry exists and is empty, enterprise attestation is enabled.
ENTERPRISE_ATTESTATION = 2039;
/// If this entry exists and is empty, the PIN needs to be changed.
FORCE_PIN_CHANGE = 2040;
/// Whether the PIN needs to be changed for the first slot.
///
/// The PIN needs to be changed if this entry exists and is empty.
FIRST_FORCE_PIN_CHANGE = 2040;
/// The secret of the CredRandom feature.
CRED_RANDOM_SECRET = 2041;
@@ -111,24 +144,22 @@ make_partition! {
/// If the entry is absent, the minimum PIN length is `Customization::default_min_pin_length()`.
MIN_PIN_LENGTH = 2043;
/// The number of PIN retries.
/// The number of PIN retries for the first slot.
///
/// If the entry is absent, the number of PIN retries is `Customization::max_pin_retries()`.
PIN_RETRIES = 2044;
FIRST_PIN_RETRIES = 2044;
/// The PIN hash and length.
/// The PIN hash and length for the first slot.
///
/// If the entry is absent, there is no PIN set. The first byte represents
/// the length, the following are an array with the hash.
PIN_PROPERTIES = 2045;
FIRST_PIN_PROPERTIES = 2045;
/// Reserved for the key store implementation of the environment.
_RESERVED_KEY_STORE = 2046;
/// The global signature counter.
///
/// If the entry is absent, the counter is 0.
GLOBAL_SIGNATURE_COUNTER = 2047;
/// The global signature counter for the first slot.
FIRST_GLOBAL_SIGNATURE_COUNTER = 2047;
}
#[cfg(test)]

View File

@@ -41,7 +41,7 @@ pub struct PinUvAuthTokenState {
permissions_rp_id: Option<String>,
usage_timer: TimedPermission,
user_verified: bool,
in_use: bool,
slot_id_in_use: Option<usize>,
}
impl PinUvAuthTokenState {
@@ -52,13 +52,18 @@ impl PinUvAuthTokenState {
permissions_rp_id: None,
usage_timer: TimedPermission::waiting(),
user_verified: false,
in_use: false,
slot_id_in_use: None,
}
}
/// Returns whether the pinUvAuthToken is active.
pub fn is_in_use(&self) -> bool {
self.in_use
self.slot_id_in_use.is_some()
}
/// Returns the slot id in use.
pub fn slot_id_in_use(&self) -> Option<usize> {
self.slot_id_in_use
}
/// Checks if the permission is granted.
@@ -113,15 +118,15 @@ impl PinUvAuthTokenState {
}
/// Starts the timer for pinUvAuthToken usage.
pub fn begin_using_pin_uv_auth_token(&mut self, now: CtapInstant) {
pub fn begin_using_pin_uv_auth_token(&mut self, now: CtapInstant, slot_id: usize) {
self.user_verified = true;
self.usage_timer = TimedPermission::granted(now, INITIAL_USAGE_TIME_LIMIT);
self.in_use = true;
self.slot_id_in_use = Some(slot_id);
}
/// Updates the usage timer, and disables the pinUvAuthToken on timeout.
pub fn pin_uv_auth_token_usage_timer_observer(&mut self, now: CtapInstant) {
if !self.in_use {
if !self.is_in_use() {
return;
}
self.usage_timer = self.usage_timer.check_expiration(now);
@@ -132,7 +137,7 @@ impl PinUvAuthTokenState {
/// Returns whether the user is verified.
pub fn get_user_verified_flag_value(&self) -> bool {
self.in_use && self.user_verified
self.is_in_use() && self.user_verified
}
/// Consumes the user verification.
@@ -151,7 +156,7 @@ impl PinUvAuthTokenState {
self.permissions_set = 0;
self.usage_timer = TimedPermission::waiting();
self.user_verified = false;
self.in_use = false;
self.slot_id_in_use = None;
}
}
@@ -164,24 +169,28 @@ mod test {
fn test_observer() {
let mut token_state = PinUvAuthTokenState::new();
let mut now: CtapInstant = CtapInstant::new(0);
token_state.begin_using_pin_uv_auth_token(now);
token_state.begin_using_pin_uv_auth_token(now, 0);
assert!(token_state.is_in_use());
assert_eq!(token_state.slot_id_in_use(), Some(0));
now = now + Milliseconds(100_u32);
token_state.pin_uv_auth_token_usage_timer_observer(now);
assert!(token_state.is_in_use());
now = now + INITIAL_USAGE_TIME_LIMIT;
token_state.pin_uv_auth_token_usage_timer_observer(now);
assert!(!token_state.is_in_use());
assert!(token_state.slot_id_in_use().is_none());
}
#[test]
fn test_stop() {
let mut token_state = PinUvAuthTokenState::new();
let now: CtapInstant = CtapInstant::new(0);
token_state.begin_using_pin_uv_auth_token(now);
token_state.begin_using_pin_uv_auth_token(now, 0);
assert!(token_state.is_in_use());
assert_eq!(token_state.slot_id_in_use(), Some(0));
token_state.stop_using_pin_uv_auth_token();
assert!(!token_state.is_in_use());
assert!(token_state.slot_id_in_use().is_none());
}
#[test]
@@ -265,11 +274,11 @@ mod test {
let mut token_state = PinUvAuthTokenState::new();
assert!(!token_state.get_user_verified_flag_value());
let now: CtapInstant = CtapInstant::new(0);
token_state.begin_using_pin_uv_auth_token(now);
token_state.begin_using_pin_uv_auth_token(now, 0);
assert!(token_state.get_user_verified_flag_value());
token_state.clear_user_verified_flag();
assert!(!token_state.get_user_verified_flag_value());
token_state.begin_using_pin_uv_auth_token(now);
token_state.begin_using_pin_uv_auth_token(now, 0);
assert!(token_state.get_user_verified_flag_value());
token_state.stop_using_pin_uv_auth_token();
assert!(!token_state.get_user_verified_flag_value());

View File

@@ -33,6 +33,7 @@ pub struct TestCustomization {
max_large_blob_array_size: usize,
max_rp_ids_length: usize,
max_supported_resident_keys: usize,
slot_count: usize,
}
impl TestCustomization {
@@ -112,6 +113,10 @@ impl Customization for TestCustomization {
fn max_supported_resident_keys(&self) -> usize {
self.max_supported_resident_keys
}
fn slot_count(&self) -> usize {
self.slot_count
}
}
impl From<CustomizationImpl> for TestCustomization {
@@ -132,6 +137,7 @@ impl From<CustomizationImpl> for TestCustomization {
max_large_blob_array_size,
max_rp_ids_length,
max_supported_resident_keys,
slot_count,
} = c;
let default_min_pin_length_rp_ids = default_min_pin_length_rp_ids
@@ -160,6 +166,7 @@ impl From<CustomizationImpl> for TestCustomization {
max_large_blob_array_size,
max_rp_ids_length,
max_supported_resident_keys,
slot_count,
}
}
}

76
third_party/lang-items/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,76 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "lang_items"
version = "0.1.0"
dependencies = [
"libtock_core",
"libtock_drivers",
"linked_list_allocator",
]
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "linked_list_allocator"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "822add9edb1860698b79522510da17bef885171f75aa395cff099d770c609c24"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"

61
third_party/libtock-drivers/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,61 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "libtock_codegen"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "libtock_core"
version = "0.1.0"
dependencies = [
"libtock_codegen",
]
[[package]]
name = "libtock_drivers"
version = "0.1.0"
dependencies = [
"libtock_core",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"

179
tools/heapviz/Cargo.lock generated Normal file
View File

@@ -0,0 +1,179 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "heapviz"
version = "0.1.0"
dependencies = [
"clap",
"lazy_static",
"ncurses",
"regex",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "ncurses"
version = "5.101.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e2c5d34d72657dc4b638a1c25d40aae81e4f1c699062f72f467237920752032"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[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"