From f91d2fd3dbe7d97794702ff274b1f44a49ca6cd1 Mon Sep 17 00:00:00 2001 From: Jean-Michel Picod Date: Tue, 28 Jan 2020 15:09:10 +0100 Subject: [PATCH] Initial commit --- .cargo/config | 7 + .github/ISSUE_TEMPLATE.md | 16 + .github/PULL_REQUEST_TEMPLATE.md | 6 + .gitignore | 7 + .gitmodules | 6 + .markdownlint.json | 35 + .travis.yml | 45 + .vscode/extensions.json | 6 + .vscode/settings.json | 7 + Cargo.toml | 35 + LICENSE | 202 + README.md | 116 + deploy.sh | 321 ++ docs/contributing.md | 28 + docs/img/OpenSK.svg | 1 + docs/img/devkit_annotated.jpg | Bin 0 -> 544396 bytes docs/img/dongle_clip.jpg | Bin 0 -> 176028 bytes docs/img/dongle_front.jpg | Bin 0 -> 409378 bytes docs/img/dongle_pads.jpg | Bin 0 -> 130232 bytes docs/install.md | 262 + examples/crypto_bench.rs | 180 + layout.ld | 170 + libraries/cbor/Cargo.toml | 15 + libraries/cbor/src/lib.rs | 29 + libraries/cbor/src/macros.rs | 500 ++ libraries/cbor/src/reader.rs | 811 +++ libraries/cbor/src/values.rs | 268 + libraries/cbor/src/writer.rs | 429 ++ libraries/crypto/Cargo.toml | 29 + libraries/crypto/src/aes256.rs | 541 ++ libraries/crypto/src/cbc.rs | 258 + libraries/crypto/src/ec/exponent256.rs | 346 ++ libraries/crypto/src/ec/gfp256.rs | 260 + libraries/crypto/src/ec/int256.rs | 1181 +++++ libraries/crypto/src/ec/mod.rs | 20 + libraries/crypto/src/ec/montgomery.rs | 1109 ++++ libraries/crypto/src/ec/point.rs | 1034 ++++ libraries/crypto/src/ec/precomputed.rs | 324 ++ libraries/crypto/src/ecdh.rs | 154 + libraries/crypto/src/ecdsa.rs | 643 +++ libraries/crypto/src/hmac.rs | 281 + libraries/crypto/src/lib.rs | 67 + libraries/crypto/src/rng256.rs | 91 + libraries/crypto/src/sha256.rs | 423 ++ libraries/crypto/src/util.rs | 41 + libraries/crypto/tests/aesavs.rs | 103 + libraries/crypto/tests/asn1.rs | 232 + libraries/crypto/tests/data/ECBVarKey256.rsp | 2571 +++++++++ libraries/crypto/tests/data/ECBVarTxt256.rsp | 1291 +++++ .../data/ecdsa_secp256r1_sha256_test.json | 4578 +++++++++++++++++ libraries/crypto/tests/wycheproof.rs | 217 + nrf52840dk_layout.ld | 19 + patches/libtock-rs/01-panic_console.patch | 81 + patches/libtock-rs/02-timer.patch | 72 + patches/libtock-rs/03-public_syscalls.patch | 13 + patches/libtock-rs/04-bigger_heap.patch | 13 + patches/tock/01-persistent-storage.patch | 323 ++ patches/tock/02-usb.patch | 1009 ++++ patches/tock/03-app-memory.patch | 13 + patches/tock/04-rtt.patch | 522 ++ reset.sh | 51 + rules.d/55-opensk.rules | 1 + run_desktop_tests.sh | 72 + rust-toolchain | 1 + rustfmt.toml | 3 + setup.sh | 49 + src/ctap/command.rs | 483 ++ src/ctap/ctap1.rs | 675 +++ src/ctap/data_formats.rs | 1020 ++++ src/ctap/hid/mod.rs | 596 +++ src/ctap/hid/receive.rs | 590 +++ src/ctap/hid/send.rs | 296 ++ src/ctap/mod.rs | 1297 +++++ src/ctap/response.rs | 267 + src/ctap/status_code.rs | 71 + src/ctap/storage.rs | 682 +++ src/ctap/timed_permission.rs | 188 + src/embedded_flash/buffer.rs | 455 ++ src/embedded_flash/mod.rs | 25 + src/embedded_flash/storage.rs | 107 + src/embedded_flash/store/bitfield.rs | 172 + src/embedded_flash/store/format.rs | 514 ++ src/embedded_flash/store/mod.rs | 1028 ++++ src/embedded_flash/syscall.rs | 195 + src/lib.rs | 21 + src/main.rs | 388 ++ src/usb_ctap_hid.rs | 344 ++ third_party/libtock-rs | 1 + third_party/tock | 1 + tools/gen_key_materials.sh | 169 + 90 files changed, 31123 insertions(+) create mode 100644 .cargo/config create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .markdownlint.json create mode 100644 .travis.yml create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100755 deploy.sh create mode 100644 docs/contributing.md create mode 100644 docs/img/OpenSK.svg create mode 100644 docs/img/devkit_annotated.jpg create mode 100644 docs/img/dongle_clip.jpg create mode 100644 docs/img/dongle_front.jpg create mode 100644 docs/img/dongle_pads.jpg create mode 100644 docs/install.md create mode 100644 examples/crypto_bench.rs create mode 100644 layout.ld create mode 100644 libraries/cbor/Cargo.toml create mode 100644 libraries/cbor/src/lib.rs create mode 100644 libraries/cbor/src/macros.rs create mode 100644 libraries/cbor/src/reader.rs create mode 100644 libraries/cbor/src/values.rs create mode 100644 libraries/cbor/src/writer.rs create mode 100644 libraries/crypto/Cargo.toml create mode 100644 libraries/crypto/src/aes256.rs create mode 100644 libraries/crypto/src/cbc.rs create mode 100644 libraries/crypto/src/ec/exponent256.rs create mode 100644 libraries/crypto/src/ec/gfp256.rs create mode 100644 libraries/crypto/src/ec/int256.rs create mode 100644 libraries/crypto/src/ec/mod.rs create mode 100644 libraries/crypto/src/ec/montgomery.rs create mode 100644 libraries/crypto/src/ec/point.rs create mode 100644 libraries/crypto/src/ec/precomputed.rs create mode 100644 libraries/crypto/src/ecdh.rs create mode 100644 libraries/crypto/src/ecdsa.rs create mode 100644 libraries/crypto/src/hmac.rs create mode 100644 libraries/crypto/src/lib.rs create mode 100644 libraries/crypto/src/rng256.rs create mode 100644 libraries/crypto/src/sha256.rs create mode 100644 libraries/crypto/src/util.rs create mode 100644 libraries/crypto/tests/aesavs.rs create mode 100644 libraries/crypto/tests/asn1.rs create mode 100644 libraries/crypto/tests/data/ECBVarKey256.rsp create mode 100644 libraries/crypto/tests/data/ECBVarTxt256.rsp create mode 100644 libraries/crypto/tests/data/ecdsa_secp256r1_sha256_test.json create mode 100644 libraries/crypto/tests/wycheproof.rs create mode 100644 nrf52840dk_layout.ld create mode 100644 patches/libtock-rs/01-panic_console.patch create mode 100644 patches/libtock-rs/02-timer.patch create mode 100644 patches/libtock-rs/03-public_syscalls.patch create mode 100644 patches/libtock-rs/04-bigger_heap.patch create mode 100644 patches/tock/01-persistent-storage.patch create mode 100644 patches/tock/02-usb.patch create mode 100644 patches/tock/03-app-memory.patch create mode 100644 patches/tock/04-rtt.patch create mode 100755 reset.sh create mode 100644 rules.d/55-opensk.rules create mode 100755 run_desktop_tests.sh create mode 100644 rust-toolchain create mode 100644 rustfmt.toml create mode 100755 setup.sh create mode 100644 src/ctap/command.rs create mode 100644 src/ctap/ctap1.rs create mode 100644 src/ctap/data_formats.rs create mode 100644 src/ctap/hid/mod.rs create mode 100644 src/ctap/hid/receive.rs create mode 100644 src/ctap/hid/send.rs create mode 100644 src/ctap/mod.rs create mode 100644 src/ctap/response.rs create mode 100644 src/ctap/status_code.rs create mode 100644 src/ctap/storage.rs create mode 100644 src/ctap/timed_permission.rs create mode 100644 src/embedded_flash/buffer.rs create mode 100644 src/embedded_flash/mod.rs create mode 100644 src/embedded_flash/storage.rs create mode 100644 src/embedded_flash/store/bitfield.rs create mode 100644 src/embedded_flash/store/format.rs create mode 100644 src/embedded_flash/store/mod.rs create mode 100644 src/embedded_flash/syscall.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/usb_ctap_hid.rs create mode 160000 third_party/libtock-rs create mode 160000 third_party/tock create mode 100644 tools/gen_key_materials.sh diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000..92823f7 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,7 @@ +# Target configuration for the CTAP2 app on the nRF52840 chip +[target.thumbv7em-none-eabi] +rustflags = [ + "-C", "link-arg=-Tnrf52840dk_layout.ld", + "-C", "relocation-model=static", + "-D", "warnings", +] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..3c52212 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,16 @@ +## Expected Behavior + + +## Actual Behavior + + +## Steps to Reproduce the Problem + +1. +1. +1. + +## Specifications + +- Version: +- Platform: \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..0787bd9 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,6 @@ +Fixes # + +> It's a good idea to open an issue first for discussion. + +- [ ] Tests pass +- [ ] Appropriate changes to README are included in PR \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..625fa19 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +target/ +Cargo.lock + +# Prevent people from commiting sensitive files. +crypto_data/ +src/ctap/key_material.rs + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b70a516 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "third_party/libtock-rs"] + path = third_party/libtock-rs + url = https://github.com/tock/libtock-rs +[submodule "third_party/tock"] + path = third_party/tock + url = https://github.com/tock/tock diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..e1d84fb --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,35 @@ +{ + "default": true, + "heading-style": { + "style": "atx" + }, + "no-trailing-spaces": { + "br_spaces": 0, + "strict": true + }, + "ul-indent": { + "indent": 4 + }, + "line-length": { + "line_length": 80, + "code_blocks": false + }, + "list-marker-space": { + "ol_single": 2, + "ol_multi": 2, + "ul_single": 3, + "ul_multi": 3 + }, + "no-inline-html": { + "allowed_elements": [ + "img" + ] + }, + "fenced-code-language": true, + "code-block-style": { + "style": "fenced" + }, + "code-fence-style": { + "style": "backtick" + } +} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3cb7c35 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,45 @@ +# Copyright 2019 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. + +language: rust +rust: + - nightly-2020-01-16 + +os: + - linux + +dist: "trusty" # we need python3-pip + +addons: + apt: + packages: + - "python3" + - "python3-pip" + +cache: + - rust + - cargo + +before-install: + - openssl version + +install: + - rustup target add thumbv7em-none-eabi + - rustup component add rustfmt + - cargo install cargo-audit + +script: + - ./setup.sh + - cargo audit + - ./run_desktop_tests.sh diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..755027f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "davidanson.vscode-markdownlint", + "rust-lang.rust" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f502ab1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "editor.formatOnSave": true, + "rust-client.channel": "nightly", + // The toolchain is updated from time to time so let's make sure that RLS is updated too + "rust-client.updateOnStartup": true, + "rust.clippy_preference": "on" +} diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..624c37a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "ctap2" +version = "0.1.0" +authors = [ + "Fabian Kaczmarczyck ", + "Guillaume Endignoux ", + "Jean-Michel Picod ", +] +license = "Apache-2.0" +edition = "2018" + +[dependencies] +libtock = { path = "third_party/libtock-rs" } +cbor = { path = "libraries/cbor" } +crypto = { path = "libraries/crypto" } +byteorder = { version = "1", default-features = false } +arrayref = "0.3.6" +subtle = { version = "2.2", default-features = false, features = ["nightly"] } + +[features] +std = ["cbor/std", "crypto/std", "crypto/derive_debug"] +debug_ctap = ["crypto/derive_debug"] +with_ctap1 = ["crypto/with_ctap1"] +panic_console = ["libtock/panic_console"] + +[dev-dependencies] +elf2tab = "0.4.0" + +[profile.dev] +panic = "abort" +lto = true # Link Time Optimization usually reduces size of binaries and static libraries + +[profile.release] +panic = "abort" +lto = true # Link Time Optimization usually reduces size of binaries and static libraries diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ade3a63 --- /dev/null +++ b/README.md @@ -0,0 +1,116 @@ +# OpenSK logo + +[![Build Status](https://travis-ci.org/google/OpenSK.svg?branch=master)](https://travis-ci.org/google/OpenSK) + +## OpenSK + +This repository contains a Rust implementation of a +[FIDO2](https://fidoalliance.org/fido2/) authenticator. + +We developed this as a [Tock OS](https://tockos.org) application and it has been +successfully tested on the following boards: + +* [Nordic nRF52840-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) +* [Nordic nRF52840-dongle](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle) + +## Disclaimer + +This project is proof-of-concept and a research platform. It's still under +development and as such comes with a few limitations: + +### FIDO2 + +Although we tested and implemented our firmware based on the published +[CTAP2.0 specifications](https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html), +our implementation was not reviewed nor officially tested and doesn't claim to +be FIDO Certified. + +### Cryptography + +We're currently still in the process on making the +[ARM® CryptoCell-310](https://developer.arm.com/ip-products/security-ip/cryptocell-300-family) +embedded in the +[Nordic nRF52840 chip](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fcryptocell.html) +work to get hardware-accelerated cryptography. In the meantime we implemented +the required cryptography algorithms (ECDSA, ECC secp256r1, HMAC-SHA256 and +AES256) in Rust as a placeholder. Those implementations are research-quality +code and haven't been reviewed. They don't provide constant-time guarantees and +are not designed to be resistant against side-channel attacks. + +## Installation + +For a more detailed guide, please refer to our +[installation guide](docs/install.md). + +1. If you just cloned this repository, run the following script (**Note**: you + only need to do this once): + + ```shell + ./setup.sh + ``` + +2. If you have a Nordic development board that doesn't already have Tock OS + installed, you can install both TockOS and the OpenSK application by running + the following command, depending on the board you have: + + ```shell + # Nordic nRF52840-DK board + board=nrf52840dk ./deploy.sh os app + # Nordic nRF52840-Dongle + board=nrf52840_dongle ./deploy.sh os app + ``` + +3. If Tock OS is already installed and you want to install/update the OpenSK + application on your board (**Warning**: it will erase the locally stored + credentials), run: + + ```shell + ./deploy.sh app + ``` + +4. On Linux, you may want to avoid the need for `root` privileges to interact + with the key. For that purpose we provide a udev rule file that can be + installed with the following command: + + ```shell + sudo cp rules.d/55-opensk.rules /etc/udev/rules.d/ && + sudo udevadm control --reload + ``` + +### Customization + +If you build your own security key, depending on the hardware you use, there are +a few things you can personalize: + +1. If you have multiple buttons, choose the buttons responsible for user + presence in main.rs. +2. Decide whether you want to use batch attestation. There is a boolean flag in + `ctap/mod.rs`. It is mandatory for U2F, and you can create your own + self-signed certificate. The flag is used for FIDO2 and has some privacy + implications. Please check + [WebAuthn](https://www.w3.org/TR/webauthn/#attestation) for more + information. +3. Decide whether you want to use signature counters. Currently, only global + signature counters are implemented, as they are the default option for U2F. + The flag in `ctap/mod.rs` only turns them off for FIDO2. The most privacy + preserving solution is individual or no signature counters. Again, please + check [WebAuthn](https://www.w3.org/TR/webauthn/#signature-counter) for + documentation. +4. Depending on your available flash storage, choose an appropriate maximum + number of supported residential keys and number of pages in + `ctap/storage.rs`. + +### 3D printed enclosure + +To protect and carry your key, we partnered with a professional designer and we +are providing a custom enclosure that can be printed on both professional 3D +printers and hobbyist models. + +All the required files can be downloaded from +[Thingiverse](https://www.thingiverse.com/thing:4132768) including the STEP +file, allowing you to easily make the modifications you need to further +customize it. + +## Contributing + +See [Contributing.md](docs/contributing.md). diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..974888d --- /dev/null +++ b/deploy.sh @@ -0,0 +1,321 @@ +#!/usr/bin/env bash +# Copyright 2019 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. + + +set -e + +if [ "x$VERBOSE" != "x" ] +then + set -x +fi + +info_text="$(tput bold)info:$(tput sgr0)" +error_text="$(tput bold)error:$(tput sgr0)" + +tab_folder="target/tab" +# elf2tab requires a file named "cortex-m4", so this path is used for all +# target applications. +elf_file_name="${tab_folder}/cortex-m4.elf" + +# elf2tab 0.4.0 and below uses "-n" flag but 0.5.0-dev changes that "-p" or +# "--package-name" +# We try to be compatible with both versions. +elf2tab_package_param="-n" +if which elf2tab > /dev/null 2>&1 +then + if [ "$(elf2tab --version | cut -d' ' -f2)" = "0.5.0-dev" ] + then + # Short parameter is "-p" but long parameter names should be prefered + # when they are used in scripts. + elf2tab_package_param="--package-name" + fi +else + echo "" + echo "Command elf2tab not found. Have you run the setup.sh script?" + exit 2 +fi + +# We need to specify the board explicitly to be able to flash after 0x80000. +tockloader_flags=( + --jlink + --board="${board:-nrf52840}" + --arch=cortex-m4 + --jlink-device=nrf52840_xxaa + --page-size=4096 +) + +declare -A supported_boards +supported_boards["nrf52840dk"]="Y" +supported_boards["nrf52840_dongle"]="Y" + +declare -A enabled_features=( [with_ctap1]=Y ) + +print_usage () { + cat < + +Example: + In order to install TockOS and a debug version of OpenSK on a Nordic nRF52840-DK + board, you need to run the following command: + board=nrf52840dk $0 --panic-console os app_debug + +Actions: + os + Compiles and installs Tock OS on the selected board. + The target board must be indicated by setting the environment + variable \$board + + app + Compiles and installs OpenSK application. + + app_debug + Compiles and installs OpenSK application in debug mode (i.e. more debug messages + will be sent over the console port such as hexdumps of packets) + + crypto_bench + Compiles and installs the crypto_bench example that tests the performance + of the cryptographic algorithms on the board. + +Options: + --dont-clear-apps + When installing an application, previously installed applications won't + be erased from the board. + + --no-u2f + Compiles OpenSK application without backward compatible support for + U2F/CTAP1 protocol. + + + --regen-keys + Forces the generation of src/ctap/key_materials.rs file. + This won't force re-generate OpenSSL files under crypto_data/ directory. + If the OpenSSL files needs to be re-generated, simply delete them (or + the whole directory). + + --panic-console + In case of application panic, the console will be used to output messages + before starting blinking the LEDs on the board. + +EOH +} + +display_supported_boards () { + echo "$info_text Currently supported boards are:" + for b in ${!supported_boards[@]} + do + if [ -d "third_party/tock/boards/nordic/$b" -a \ + -e "third_party/tock/boards/nordic/$b/Cargo.toml" ] + then + echo " - $b" + fi + done +} + +# Import generate_crypto_materials function +source tools/gen_key_materials.sh + +build_app_padding () { + # On nRF52840, the MMU can have 8 sub-regions and the flash size is 0x1000000. + # By default, applications are flashed at 0x30000 which means the maximum size + # for an application is 0x40000 (an application of size 0x80000 would need 16 + # sub-regions of size 0x10000; sub-regions need to be aligned on their size). + # This padding permits to have the application start at 0x40000 and increase + # the maximum application size to 0x80000 (with 4 sub-regions of size + # 0x40000). + ( + # Version: 2 + echo -n "0200" + # Header size: 0x10 + echo -n "1000" + # Total size: 0x10000 + echo -n "00000100" + # Flags: 0 + echo -n "00000000" + # Checksum + echo -n "02001100" + ) | xxd -p -r > "${tab_folder}/padding.bin" +} + +build_app () { + # Flatten the array + # This is equivalent to the following python snippet: ' '.join(arr).replace(' ', ',') + local feature_list=$(IFS=$'\n'; echo "$@") + if [ "X${feature_list}" != "X" ] + then + feature_list="${feature_list// /,}" + fi + + cargo build \ + --release \ + --target=thumbv7em-none-eabi \ + --features="${feature_list}" + + mkdir -p "target/tab" + cp "target/thumbv7em-none-eabi/release/ctap2" "$elf_file_name" + + elf2tab \ + "${elf2tab_package_param}" "ctap2" \ + -o "${tab_folder}/ctap2.tab" \ + "$elf_file_name" \ + --stack 16384 \ + --app-heap 90000 \ + --kernel-heap 1024 \ + --protected-region-size=64 +} + +build_crypto_bench () { + cargo build \ + --release \ + --target=thumbv7em-none-eabi \ + --example crypto_bench + + mkdir -p "target/tab" + cp "target/thumbv7em-none-eabi/release/examples/crypto_bench" "$elf_file_name" + + elf2tab \ + "${elf2tab_package_param}" "crypto_bench" \ + -o "${tab_folder}/crypto_bench.tab" \ + "$elf_file_name" \ + --stack 16384 \ + --app-heap 90000 \ + --kernel-heap 1024 \ + --protected-region-size=64 +} + +deploy_tock () { + if [ "x$board" = "x" ]; + then + echo "$error_text You must set the board in order to install Tock OS (example: \`board=nrf52840dk $0 os\`)" + display_supported_boards + return 1 + fi + if [ "${supported_boards[$board]+x}" = "x" -a -d "third_party/tock/boards/nordic/$board" ] + then + make -C third_party/tock/boards/nordic/$board flash + else + echo "$error_text The board '$board' doesn't seem to be supported" + display_supported_boards + return 1 + fi +} + +clear_apps=Y +install_os=N +install_app=none + +force_generate=N +has_errors=N + +if [ "$#" -eq "0" ] +then + print_usage + exit 1 +fi + +while [ "$#" -ge "1" ] +do + case "$1" in + --dont-clear-apps) + clear_apps=N + ;; + + --no-u2f) + unset enabled_features["with_ctap1"] + ;; + + --regen-keys) + force_generate=Y + ;; + + --panic-console) + enabled_features["panic_console"]="Y" + ;; + + os) + install_os=Y + ;; + + app) + install_app=ctap2 + ;; + + app_debug) + install_app=ctap2 + enabled_features["debug_ctap"]="Y" + ;; + + crypto_bench) + install_app=crypto_bench + ;; + + *) + echo "$error_text Unsupported option: '"$1"'" + has_errors=Y + ;; + esac + shift 1 +done + +if [ "$has_errors" = "Y" ] +then + echo "" + print_usage + exit 1 +fi + +# Test if we need to update Rust toolchain +# rustc --version outputs a version line such as: +# rustc 1.40.0-nightly (0e8a4b441 2019-10-16) +# The sed regexp turns it into: +# nightly-2019-10-16 +current_toolchain=$(rustc --version | sed -e 's/^rustc [0-9]*\.[0-9]*\.[0-9]*-\(nightly\) ([0-9a-f]* \([0-9]*-[0-9]*-[0-9]*\))$/\1-\2/') +target_toolchain=$(head -n 1 rust-toolchain) + +if [ "x${current_toolchain}" != "x${target_toolchain}" ] +then + rustup install "${target_toolchain}" + rustup target add thumbv7em-none-eabi +fi + +if [ "$install_os" = "Y" ] +then + deploy_tock +fi + +# Don't try to uninstall app if we don't plan to install after. +if [ "$install_app" != "none" -a "$clear_apps" = "Y" ] +then + # Uninstall can fail if there's no app already installed. + # This is fine and we don't want that to stop the script + tockloader uninstall "${tockloader_flags[@]}" -a 0x40000 || true +fi + +if [ "$install_app" = "ctap2" ] +then + generate_crypto_materials "${force_generate}" + build_app "${!enabled_features[@]}" +fi + +if [ "$install_app" = "crypto_bench" ] +then + build_crypto_bench +fi + +if [ "$install_app" != "none" ] +then + build_app_padding + tockloader flash "${tockloader_flags[@]}" -a 0x30000 "${tab_folder}/padding.bin" + tockloader install "${tockloader_flags[@]}" -a 0x40000 "${tab_folder}/${install_app}.tab" +fi diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 0000000..654a071 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,28 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. + +## Community Guidelines + +This project follows [Google's Open Source Community +Guidelines](https://opensource.google/conduct/). diff --git a/docs/img/OpenSK.svg b/docs/img/OpenSK.svg new file mode 100644 index 0000000..df1692d --- /dev/null +++ b/docs/img/OpenSK.svg @@ -0,0 +1 @@ +Mono \ No newline at end of file diff --git a/docs/img/devkit_annotated.jpg b/docs/img/devkit_annotated.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1fff7d32a7ed967842848ac3475bdb45ab22ca9b GIT binary patch literal 544396 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

yfYjTW(hX^pYvzZ9y(-l}VdT9~gdn`y$= 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

  • &DHo8%Ub^vv+Y)FI{Tktq)FvyVN?;`klb#8J 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�oeWFC75mxX%bSd8cPc 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 X{C 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%0AsWe%xF!ht3bw14 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

    ~YWoxf|TzLiyf69j=v0 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�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 `_o8Vj8Ic7jj=c?*xgE;imwCWAo8k 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


    *vA2B(=8f1zx_h%* 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
    )8eI_K+QKl9R>s!Lw#3fDuE6fd9?pJ+y@`F2 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

    2Blpj>MM4Ngag5Z78VGY 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 literal 0 HcmV?d00001 diff --git a/docs/img/dongle_front.jpg b/docs/img/dongle_front.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7d090d792591ab8bed5ef04bd8d31a3d30846950 GIT binary patch literal 409378 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¼I5A-P2hjA;h`Hm(gS+MZ=Uw8+L%qZ8xCuH3#c-gs2Eph6eWHoFP z=IyqZUYJpFb=R}ORhK+Mb5r>1C5K&7Pk%0Fra!;E2uYU|fANi@;E9t4+ci!Nr4`nH zjP_)Hva8-)89r^M-yGX*in^xc{HVB5Y_Qy!@;vO`HF^B2r%+8SGgJ#h?Lsg{(ygoZ zfbld!NRvZ6HaaL?D-OEIFm@g>R#+qpOegX*k01hatGA(Z+e!y%^UyNe&!iOCHJcKhQo0T^tsYLbEA*}q%B!bfJ?~9OHR~zdQ^)Raootjanz7&KW z=nvmM)Gg96mC~-R>u^kVPyYqXRNwT~9l<(yy73~|^9j+H89_epw`)eJBSy3Kyy1_y zek-U>(Jta+%BhSOQw`4Z`$pzo9qM|&BiQ;u%K5UlsRz@A4t&$|b&Jnjgfd>2cFyiE zRj?}K-)E{H{7qJT?#v^B!b!`5q7Vh}gV~S%4(<;~k4RPi3$fpLhEu=md>a5qe>k>E z+&xh-xP?Wa?dEQSFA_;}PH#!Jdrz5Ebxe#&B&v)4QB8aRpDJ^!k>zwH3e)GcDIPM(xocL*mAiYWZN#P%c+@`RI3?1*hy_M%$Y`Bo0Gzkdb_HP zs~ZKOOF(x_aC9UJ*Ce>B1`-Qp=iy+0Y+{+*>a`~k+Dtr%tqeG@=VhX+iA;>9gKLv+ z?{=veEKSpqrRG!))i-3!h%$G0emAB1?(E1zCqG$-Z#=noeC)a`@q3bW^LwF$@T%JV zO4N?2v^SdjZc&5HBY3Mugao^CqbA#2_><-r_8o4$QTT+^R@8Fe##2($*4g z*CQA(dgSN<(We%ow?EgpY!^}c$~Jwl`6mA1-nN5JES=In8;Cu&rrfWhv`EaAJ-N_0 zk(>QVg5k}OX;@;k`Nb#q+ei|s1=5&}Z)Ls)= zbYSnma9PFhhL1PPALP91uCCmln?0i^^&(g&OcaGUribF<#i%q(8AD8rhfcGA+<{jl zoXH~s-N!;7=`MU){c<%UXQCSeMn4o|9Ac$V^xH`0j+Z&ql;Y z*Y{s(>wNW+??hTx;i>ZBK+E>W4ll;Jb|wjF-Tu}*lm3kOBKU-peHVY*54?T;MFx*< zQEGcakl&MD>35$*ch6z`wsm~Y|6JaFAoabF@aQMWGu-Fpv-Qr3X|xg#wTge=BVDQE zGk_m5`#OT)F1Sh=rrSmq46beW3bGo{#vi&`Quw`RFyz^@HxZ;eo{!`2&>ecWGeCke zd>}TNlFAp8QSMPGSTIuDEhL{8?^!*Rt210wKIcoh_^j!vgrR(aUnl(!SkHiRP;!~5 z;-#W8JO3~aqNbPi7V|^RRmWNdWLi?kBwDA-^3U5Fb`Gj(9qu)BD5-e zt>*$+pX_sVkRM0_qsl^}*Ed_V96jckQI`I6I+s7hsaxK)&`keBLAkG!5nIbC3Gi-b<o(nnryMng+qc}&%BA6jz)B?$HK{}NRDgD8)c&# z)AJ=#+0VV2-=p%vyV;liEJ!VD4WUNfz~0 zv2)R$?U?`a)XFTZatF>-hn)YxGkoM(^z+?AuPJj6&U8`Q?cr9@ndGq;o=TuceOJS8PI-}d|?(3;-3G35Fi*4zH;xcVXk9)tU zKUer<8gKx<`w;#uzu{>5kt@%~D`dhC$pH z=!mOiKKFT7qwg)kng^c8{t=X=@k%kz?NNqlShUjPlFaJ~< ze)!(j*u?B|zk4EPJ5HSM3}R=yTf=bgn%%2Mz76M}Ka=kIk7X zY!TV;9OC4wMkNPdnf*E&UEhB_Y9tpXJ$(DtNyS{lJ`Ew^_T*EfS6yYp4Y4J>5hto1 z-`y*%qmbfs?k3gIE^SXrc!|>30M(OD$>VI`og81@jy)01udR32PmS>Tw;Y%5@2$9g zSu(8Tm~GZeY;%4vYIY{qrI(u6FJCOtfIxm1;_pfok6 zvArdHA0g(vMd~+-fcdpDxMxEBH^q*ymNs=K!_rn4)Jq4yV!rq^9-lojen-B?zg?K? zlx6F5(TsUGk{Y~cs_N4r%`cx_>ld=`I}AM(!x?3!(f5;BE{#pOA1LC1NqIM?cHTxL?t=J)$@FxG8KDa*U6);`Es9slC?SYUks>aFN?MkZ!xlcdzfk?Fl30 zjr@2W+&W0@sQ;dODQR~8OU|7hj{D&(lE;H6$9%6kv)(JYXIOVmy6MJVj~?k!&-}E3 zRLs-S$T&op_^~=hHY9V~FMq;ugkj`4JaYOH5N!Z0&D5&5ZN+n(pIoJ#q64 zZ>N)6=Shi6=?^Zo-fjM>tYgpfyyIy^>tn?;A{GjcmhWvv?-?g>m&=G+noK6Wyc;@uX1Ie}mFc1CutPlB ze1=9@Ci-a8RK6biWVKyM~d?2`g&zq}>FJiEbv2SoTF|~cU=MpuE3aTIPbDwZbzjr=0M7A`qj>ogx#BuWm zt8t%qg%)-r_}#vKyvL+&VfWZcl)CzS4^MoUsiaWUu+uZ}E~4`VTEz6ibXeFXvG;~A z*TtMQXn$*7a)$T##@gBZn#qxEiX&2_Zc`O?XI1bV2ZoV9lmeptN1fr zTM2~>nzL8js2d`Z3qQ35o|LNhj4&xGPgl;q@exTm*sks=-#zp};zD@u^yhfzkvB3g zt|qpMhnHfazBeDaQ|S9W;oZVSCd(ExwmX56^=vxl-#gW@G3?wcbA!xgeVEVss8t(| zp&Yk6cy>4iTex-Gu!+RYjF9Quy%GGeI8;_G#eW-L=yBoW*IlXLCoHz8FFUJTt!Kv) zX3ji!$n3h>l5-^UJloc5(dL@$TC=Ln2uF|h8b3k%(iHe3@v8}2Fxua0vdZ!c?4#li zJiK+}Ghv_3%b}rG?ygPvv)mr;hYBoC(%ZaC+U)DZK0axylX}jke;<<#^9|~{aK=rh z*UciXH3Z-2vG3`bc^FbwkjeS3TI`GIo0Ayb3k7Ew;zq6xAK$0?J)aty-LdYwi|}JL z-MH}|)}JbNPEjf=%$vUF8>DE?9ocfz>422LteSsrv%{;^8VD*E;2T+ZQ+(2$-M;y*m|;?C^Hs;1#_PiN-ovBYWT7fJ0Oyma3W2Mus+ zExt!R&qnY=Npzljy6slR9d_IMg1%#wdV~Ay$^Q=kmq2L0*yK-C$WY%`aQT|5Z+m9qiO5J8mEjd?z3^^dJG&03Nq4?2OY2ogvS<>VT|hb^%naEItul&Zf*<&L_i`z_~B zOH3Ce=2+OM#9+d2Mh2XUG>$oA(m9=ojbjFAXxmPgak(c`-@%bZwVA7w9R;xt$Fe8K9}{J&z0`yLeo3_sECyEu^9C6Ei02N%oP4K%!Lg6s-)l zRZ*ok1zgln?yt@yu!(xMSse3yRTA)wco~ES2-5|bCo?35;1VEc%nStP4RU~ zQR$j-x`%i7^ii}M3nj#RMx|xW?#0NgbuH^1#;mT>6VaS@t4CoDIlH5(8eGIjXiFSw zcEswd^Uc9m6%M+|c6z$j-7x%Rrpwg5Wh&MYAXQ9*bG8-t53`x?XsllQDF$D~G&(6T z;fokUZ6^~`cLwTnPYLO73QHqYOe?DT`RR^DGS$xS?}5EFm5>@x7GnkC0ZNK6l$JMA zok2mR3Kn@0;1m=?X0lU3Wqcy~ALNR+(K(}*wa&+R!_w1r+MLP@loWsiZ3!D#lMg~J zXLSx=FgIa4)Y;JOb`HQ)X}TAN+Q*ZlS={a397-n7DLs)n5IDs<&ggm%X4RyZ6)*@I zI)Pa;=kgnu#rJw7^B*-DN)FYWu|frDG@}LUDWpU`OA7cu)4#0MW%6@$Jl&Hmtn_!xc@Y)WQdGXB3^{XF`|QQm8(Cq& zzQb2xL3encNbQ%3Jr$*VfMy0)l$I2n5vDUO#Dyv@N(S11k>Un8l&>V02@9y#%4dz9 z?DCat-SgetBkVVueKBA!7Uob=4Pt_FLNHB&5iBI~E3t7NgV1iZfxc<D`rQ&1Q~+ zw9%|w^>Zy7M<>Z;NG9?H6^kZSmepvtsiB=8pWP^vSHhK2a{5T^FDU?n1(6IH;3gng z1eqvGig5&kH6{}Z2mr#86V;_hNEF;hZC70FX_wIG;F=4@>#S6pm<|dXluneemu{yb z>VAEgztWy)zuBE#8+7$tE{)QZ^+VM zOS*}&6#j8F!3>(T0>s)Y8eUtG#&ruEn{0-`e3WzH3Q3)Mz>Bvcc&V>i4bL z7c}4}K;poY8|;CwH6#lG3}gT;CI)b6H7H0HaA>B;Y!ar}J~LaETI~0my*V)4t>Cjz z0<{7|Xvp-5C@KPZW7)WmK=Ye|1HACu^T@W|q(RNIQ%PGh9W}*$ei}*eH_+_g^;%nx z!21nZrMK=4{dKXE77dQ}m==hN2{gK)$oag|QS}HtajGmUd5#WGIP64JeK{z}Fl%Q}4z%Y!k4Fk#{q*%LpTir4g zUuRiBwb>q{bDobI#*oxfYZbk6+Iu!)jZ=f9oV%kYl^&e-4n<}mPpM($#NFxxdXkf& zNn|*D>y;js&}!t1JoWXP0$zQ$J8o(eig~ok(~Wjnt1YP-s(q}--A%REZy0jx?WGeE z(VLT((d*XVJ2%*_xN^RZ$$b(WNj!|}JnFmYX$(?u0Eir>Kuc0gBRK^VhZAa$q7>QT zkr`#BcqG=_!$x#g&5qK<$5w21Bh5abu$M2ooC^rgG6+ggP0|pw5y*byz^|TPplXb{ z>%HfwoHJH~49E(Z>8@ZYFtn54JEF{c)9Y@I16$3i`Q2lvy0Ed+URjwgwi*F33e}-p zenDH;UMIuRmpTnWab99S6`Ca^Iib6$hHT=bay+M_%v-9PRZY9gdixebGLIuDBt{aF zfRZT3hy_CgM1?6bUST1Y063Jmipg8jOgHofI~I^^G8<-`v$Ps10u246d75@rvL|86 z`w{1^TJjo}byP2gYdPX=9Q5 z8|J@H&ld7tZUq3%03o!XXb9jM)bnq(aqF{@+E10!_~X)fw&5TlB`%u-qN580aQ8wC}@ z(!FZY%==pP%PVY1m$VtT!xEqHrgP$|(VENWnV3g|BG9C!HE9ZrCL>m8*QHJ+2QrYy zP}n78rNxSF$Xn9P`YgkM+UHL52KR?L`QkS~aC6UPhJD4fZaPGPH*j@G$Wz1iOj`Zp*bA$}lG z2bpBTC)KZ*OIs`$3rfHxmNESS;I^vI*)kjp_kWCo49<$$vyP$0yD{ePPR%xw-irnU zRtpA%Bpb;U%BXYew{jbukJjm5M=ts|F~f2?fr9B3?&g-M=`u2OO9=|H*QeNB2_bp$pE8%SxWhW@?k9?KgdFtHzbix@k(=Ook@_u^Zm)!XDA+E~^&wU<8 zM0~Z`EdKxl>h?!9XTv{w`LCi;EM2hWamTImTeFDNPkGx|s$>W%rT*}EU( zPHS+flRZTGUq3f-`S(`pehXI8Lb#FDx$Vuw>#q)e)}Ky;%-*-oUDZ|=dj+(oHW66b zYO+*F61|3Q>eAB9i#k>c*0UX6S5YTg)YNJX3t@>^P%MyeG~@u45&^_yD2-6?2pc`J zk_DInDgeX_Cv{C2@A=hv(PWN&y^2?RvHNCRsC3&?ln71%$u;(u>lwC=q{fD4wQ@7} zwVAmL*^utrAn^8q*c8)8RW#R6=9f9>IAPrx1S%!OO3cQS?L^AxTccpsI#u%iqozI? z^i;vmHFJ$LzD0XKfxS0*t4l|u<`(A>(kw>Ku4w2c%8N>mbz1c0+TS*^9zsV@5>`Rr z1dBpNkzqxfr8v-3-o9)w1(54aT}FDjbZ&5LL>(Qa=Mhtkb<53un6cKjPi2n-IKiR4 zU=5TC-B2j!bL7^`BdFHOVjr`qrdte;Pr2VojHlGptv+k3oY$o4oNU5U(>`5vJZ!sO z^;NRZ%vrsxsh+x18bmL&$vUX-9uV9h)ZM?Jrq>aAanE*;Q|Yd{iZ4f6XG>^Gl%hEi z=&L$+g}ZIKC5p=~U({Q+QvL}1k(HLcBs3`!6nTLuK2QlOUPE}Hl_vyh!T5^I+)%u< zRQ&ts9MCc&KBG(CN0l4TuR#1<1z?1$S!32-ZPP1N^&d7jSPtEB?#a*bBVwjH5=!3# zsJHo+Ymcy#$VUh&aUJV}mYbes@^9=zXlWcbzFtKxdQ z$~p}1pS|aX`x7k0nO8K~snUk>o9!~pdkDfZG?j(4ls>HErZ<8{G9iM%9zh&PJTy@# zvRQ37vNTKg5$ z&LVXkqvZX19+_XsE~m;L@GP#zJ7n8>B~{c=IgWh2Q#PYs;k!4JUu9z`w0L=_y6&!Xq>)x`McKh?IX#lsZlb-W zT3S+C*8#SU>7+W9KDBQ57p|~@0^HQ!FDQ2>pC{kWm7|zG-t*MyCO1Pdn{GvPetXdj zZpuBhtc;~XiEZK6<{DI$4Jt9U7-nR5a*%j2p~Fc=kW|ryD_GL}W^_Q_&{Ws1iOu~L zDp_Fg(v`E-A3S;@*-E~5tSkyR$naXAO|lh2shtN>$yUen7T$+l%+1CD;T~Y~>xlfKQf8QeplitYE}%ffK}a=3t2u2-{JW}P+E;F-Q`$`4go0FkVFzln*fg-h zu&;MCZ5a*7cx^)2tej;5Z8G~wF%=psmWH}&p^|DW?Cw8DL}>4?E+118$zze*`V|%x zc1szcyc8C2k7?!=?|+6eWI-71XMue;VmVI!TB3K7{>S0-pG2XiI^5(FbxC#cnu^Dx z%33VuvaGis=!fTztV>bmI*oN0Ntk7jNf~svOlnAw6iR5fL2NBObL61nuD6)^;Q9~Z zv@zLJ9hE{lry1&>p1logB;NXcdD&iL_;-^#v?jNe2mrE5i}v8hs+sFy7DszQMKfuuI3!Pc{3 zvWaOn*I8Z+rj4^9fL7T-iV`a>)C>CCISDe(KW$rg-2K4W)|?*woK7nx5|SlknFr!D z$vsgX#bmh8Qj#Gi<8Y5z7C_=Ni0##_ON#cXk2(#EjBu83P76xg4KlVanE}kw*%2+- zBy(&@7W0$zgB@+q>2YhZ@*(T;9V5Z+YmK!{imAG4t~60D9Bl&H)?s!E(!OkUzGV{L zNhJhqU1Mz<4n7}@|NsV%YidvbasD&bu`vB^uN%&i?n>BrO(utJelfT>gnUP z&|SSG^G9RSJy$&^Yu&ke}F6z#k2XM0c8y}m~v7y;A+IG-LXP$in3(_8awypG6(T>{^^CZPz##)5$UtO)W(o!aO5~V9jMH%JsyA2FwdX~Z=(a;y%%J3g70`lA z0cBe9dMj>=Lk!tMaj^dYM7aL|PVp(*A&yP;K4ovEF*nxOLKbygJaw^{mlD z5~ED@Gs>`rl~DA}&T7qzM0y`T!_2L5n~RXtUfc%d!3s@x(oy+Be4@3NYwUQh);XP@ z&D`01{)(6DvaltrNn@Ao0&SA;3RQ(5hY%Aa%T66aGf^vNDKHtMe6XaXajjLAbV;|s zn8RwLM>Qx|>~5fNj`wI2sguo1h|N(5hNL0BLYgyCQ+qcd=spjo*GtMSckg-3*-xsy zc-@lHK5Ossb~`I+BSo@o&8n!HYAIp{ibtz7=NXpQ! zKyyna*Kt+)c6j+!@$9JG7Q^(|%%R_0rn)1L-JpvmKAi@pXsBUX2(?tU(HzKCOP}u> z?Ywc2062nBYf>_2tupe0go3~jIN^}-a4%X^5{?4YTGF7^=58%D)L_WgHsj*fw__4e z+ka^D5!Ibk6+X4YQ+v`5E7s8=*IUf<+of~8Zl^HuVpi~y#G=u#@;dnQtMU0uopd%+ z!Q0Sqw=X+?5l^ajLYrB%xo&^$uw^O38=GY6Ejo*U=sTuYUhbD4Bo)!w*LSPl@Y2y0gM(1WB?kn2q{p4LZb>)BQFpNOw=}e4H+E= zu+o;@J_sv(j%q9k{Rlp+QnwJQQWwk@#q}w-xhWA#BZAt zp~1JceE{eBwv@)krnOF$9@)^^e7)0M`kJe!r)GJpvv$+Xoo3kN?5oY?e+>Om$EIIK za%i+g)l8+0Wie>zHk$!oJ!dp>Y&%99tjILiG`~$o)W}p#jHE0%A-ipuIMspx?_bIPP4r<$D@6S8kJK{YGY;y-+ zX4q5f+Z1{ph;ojPrv)Sd%^r)0u#YnX>+;Wd=L1(+Q#;zr;R0PajW=VNxwsoFeY2*v zZ9f}oiIvY)oaffpD9)Ep;{}DfBCPc|&zQ*!yJBJw;M}jegfYpQ_h+rNJ!jXk2X--J60my9T8Znftj~Q`A=|>Chw@r;>nPYlJ zxEKNuf@%@cqo<1cb{=%hX*8~}K=s&HL|L6i#B@5vZ$U~m*vl)I)%3?Nv*BM`w2w^%GorSA8Om$clA^s{QvLD{p}(uKXmpNuX|`E7+I@EFgINS~4U|1) z62rlhM?De7ETeJv&Kt(QW#h|fVtG*JYKv}uHn<+X&faSBPxp_Wd;C4$$ZA6=u5s<~ zC>wE*wnpMMtxi;^vfCC=E!}zcDG<4ZUfMmH63)5zRKbL(n$ zmmgHLl`j5Uz1-&SHd>mC1*fa6*Z5ZqEi`pwnry6fGoN)Ggb6UFf{i*HOp}(W?s>sy zLi2I!1d@2yOrzM%#;LavsDxoiB7pERh+H37o86Xld0`Mujoo+sjK5zQ$V3f*ah>nTmn<*YaBz;I*aZ-{ckqxXe8&*ln zE5n2q)?iLlT=?{dFyn`={I9TTA4YhuYrFNkN6Uk9MzqN(r(8jjlA}dd=iAXU*9pj# z^5>*-%a@Yh+ibR(;=}xz=-l0?r_*;4#lTfKN>MZtt??)xJ`|zus?KOm=x`1zU zvR!qx71rlst8Cqv&uH%UQ)yh1m8zM1dA8zegEL6l_lr)2v#K|Be9!5;(p!gMf-|V{ z8$vbsyBO?jN1Icu;4<7zp=EW-)}LZ(x%tbuPR)_DiSRB zP@Aab^;L}ZT{0`w=iW4S@|y^Fh-R0DYX1P~i{_`WOlZhZL`GwY3ulA^Bm-qOmK&H^ zCrN?QQ((p&N>T%q$|z53k|}R}=6s>`Z4<=eyzX8ke)kFi<;zS8zNo`?BtTuJ;24q->ayk92$>|<;;jT2J3UEtAD^T)08SvJzCisEdJGgAi7g{@n0wt}91&fcvwKGNquIyM5j=rdhJ z=iL%SuCOsFnJTR+u7^E8Q0QaI8+JBg<`%Pyx`O27;1=sOrqbp)mC?DcvzNB37pkyx zS8p@A3fX&4Q?6*D&RenSpPl;k%jfzOMyk2gGCW}R-<#uIc4Se=X(Iz^$?O9-(7r8* zln8m0=0}N`zes$-hfvrnW-R%u_xu$+ES3uPFjt zz_r*t+c}3^Ey#e0FP#=z#?#%lEvuEbt2s|$!w$j5Zq7$_ELYjhRQ7!DgKIR%ZeZto zXWEybQcncKZ0<9ya;vCwyJ=ND@VK=5Q&V9pp4l}sa~$_Ay-KerI=_q9bN>KYnVhO@ ztlcfYHe@HTINe_*@Y>9<{h!$9B3%}Cy7U|jgU`3qv>CGuwkq>v+udZ|Pr&8>07U1V zUFQ8al$-u?&AF&p+Pb&Rx?H(YZxzpk;%Rlx%C&=YO|pwN7_@+uai#e3<7x1tyIS@= zojF9ly7Eq@%AFSLWVG?D_A-CAi>p3>&y^GntIRu%7jt{Vp@{jP_1|*Kglz8&e95BnUzYoJm1z~F8*_4&h4)}=ms;P);rAo^~r2` zN6|TRt~HbLEap_0E$8FNkZ!t(&w2zWG6YcEn&~O4&eJYduoY!+j8?#Y?Ic zv=OkuO;nfj4l`-9tI%(7nudgwuq~@4coP!S*k5}{yz%H*E%c~Xr$2XFG!-uzs|!6{ zJ}jRKX|10M*g=)yOs$s`=P@!!hW%-SWfD_ZS4_>!Z1|b2EA1@kuI;W{bxUng>|nxI z5IO-tV`|d$$yWUX*XC|!cK4Zm7Y9~#StU(B(|&Q$?sij2A4-k9j`t^ee>sNjYcBpb zX(HFW;bv_z)Z?u!28O5V^N@|jLoH19gOYW41&N#1#M?f*j=g)D+aEvm9_RR@(BC_K z7B->Ad$oa;Og$~hUfpjTwE}son_I1FYpvxBtrBZV`tsKIIQM+ukmg8)qVh%z@MZ#0 zq~Cz>7$fijGr|nRKvHM2(TG9GZAzKE9EY=XQk$T?R5nWofD=ZjiJnJ5EV6*uP)b#H z)xSZPr#jqhuUC0CRNcuHwykM#ZC-0aX_Caf1zXj`mg%nQsb$^K_@XOJp`4af+D@W# z-j~k}t`n!29*uyw*2agMy)&BHoSw!fpH#XX#NnCHJYh|z+MJ%iNVAkT^cQ`F>?b+s zE|?PF>snrAbY5xI?sL>qA=*Q<$#m#miZn;sbHMLJuF`Ft~q@j{2Z5P!~ikf?s zo2 z`b~__U%=MYf=c-@)VXuThq__UIvuOcUnMldc9qT+q*Sd&Tb_H&NEv&zynn4xxN@Ug z3R^>IPtR@MCfsn&wcNiRdJ~CV*E6gk)s8=*seR9y>AO!YY(H4^O4-&8xXHsvGbTWd zr`OZ%E=wds3BWv<2^nOenoLOq%s_;bEGsD(O8h`%4QP#Qjch0)y8NT9^eUsFyqp^| z3&2Kb)R8s_b6&#_GijmflOdHZwu|gAk7ySbK95naTQt*Efw8ojy9rHq3R*ynEQNup z&`0v~^@~l2JtxpCCrx?M-NG6ilh!SpPHl6ZH1R1>EyV?Rzpt37tTe7L)RP`|qPmkH z&8Hd)4fAI_)Y?~z-0b^Jdkas6YiV?R^V@T)b(+^$dL0FByU*FGJqD;9bi1Uk`bsOQ zm)12NVidZieA8OawRT+N+2dz=tErZ}#ww7OtmXisL$9B?veJrRI3u?msVdbIRTGp+0r#%HM4jT*c^D zB7LF2s@HGj-#}k5eXlapFHIpPH0(X4h4bn3)5V=8^51vr_mI0-z#0!J9P0HKF6G~? zeC70=^6%R(+9fKQ!EG%(cYbWXmiayNNqgU~oqn0zTSGmA)<%AZ_RMDweuDW=t==T` zZ&N(k)K*Q7WRxJJnZ|E&aV~FqABJoqId!?-+uWCRRdUx%%SeNGUtV3(jpMz+o~FKLLP7lFuW;h{7=- z2`0S*c+-+=FJ9ZXXBn$_xHbSR0U@`l1jtC{7KfL+^l&FiZA%7KT?5$j*`ljWaKD+tJwiJ?};F+fIJzA@_&Ceek-6weThKd))jg+$pM!p1bQ`j{4H; zIEdg#DVI4<=}uqE&uMwfyk9;&Z*cjQ@$wrem#NOq`GoqFKQQJb*&`S(wrs}E`BUrk>sJ-+;U2okI);R`YI zS@k2teFpPSYwf>`d#UmoHbY=-T)ycp~77cM{*gSunUV-8l-N7&i#BIv_u^efkd{kOOL3W9|HQydBR@Qi#Za~8n9FY z<*(^qk!DQY{{YfIgZ&>?1&mcR?aX*|*Qw(;aqVv|cF)MZmgpxI-O>?dv^3s0HU9uS zzR%zl)2s8}r(c=g&55iIve-Fi<1nGf-!*?nd|}aFK6bv?c}KI+3AQ>p4c^Ll+_m&) zG38&SJpJ^G^S{}SSW;+~ARr7Q@FhlM81Vza zD+6RoaV(tXYfNs88UdhcNg6;+G91y1hHU6+wJ(U?%8feMRNLSsB9j|r>a+_=NK;it z1tI6A52o853EQH{4ey^sQ`PysU)N@Bb|YQU4lB{=t+P!AZ#XR~ohWJ$0+*d#bZ_T+y2v%Tm~} zbvf!6)G)nf;ayfRk1D%fR_qyF<WP4A2Y% zR7lf+!bwuh7=yEN8g93vklwmeXdX&en*!2Pgaw4^EklM`u5Ze1WPGNs9pC16^H{Ll z>r>0_wa;Y=dtQWcP2FhQQ3Fv*_|IECF;|?v?tHhRyo01|D(1x9CnvO@7H8%gI;XG9 z#9EqunDG9QT=tYn_IdsFbh+=EYB@XIIfc={>t?*A{5`$Roofb4#b{y)kZHd{$aPPI zbx5;IS*6`(aNE;gDcEykvh#_jH+5?88pyw-WsS0i|=gf9-e&U4NXeuhFIP&(KIIWDWs2g(MRgFop~q0RS%nIS&{Z3P30ffN%u?;5A_ya5bbfL{URT&q{UV z5U2zK)JB<%f<+pj3`r~}H_f}ai6L`qSm^SbZ@7R3Z5dj|UO7ayNz*AB<)vy*XxoJ$ zOI8e0GzOd~Zc<`tcndjcEp2HOmEhJgv7yBZO1BF_5Rl7qN0USwN|(it2Rvr2}QltA^Q23p0E&`O(MiE0#s)PcB#E~8+i zEl}L3mxC}8(mWVY20-v00JRWE48TYdqC5hC$Qdz!1O@={1jY>^kUU@@3<7}g9s|Sz zU?3U+;1UKvG!Ft8GeHmxU~0(;OdtUP2C){fi3l`ASOAj?fJhI(vH*zo0M(&qvb7<5 z69O{TD2)WDkIk&YHH$)2gvwHYkdlOzDh1;nS_mUJ5R$wRsZt0tOhlzX#3;}RB37c- zgH&W-0Z1(_9<(Sis{r6xBRvWMk%khs;f}Pd45eg(34@H00#adF1j#UiTBHF+m=WL@ zl_v(QC0c@YC0fuU3JjDPDkC%ugYl(ND5C;0!2p;TEQ2Hu0s@DK6adT&fJ|VAjARc0 zSp!TIK|l$>Fu=$V0VXm4z{myxfCdMEzykoV1OgC*fD{QJ3CPg^oXfyq0!VnlfB=G! zG6#Z`q|GDBO>hO6P86sl!ZHXN4+INPFcIVn07)}c2_RS*1h5$f4InUK1>itYi6ALb z)g+(XF3&6qwrUpa68UaQ!3&sit6D*K8!UF~n@E!mF90!aD0st@ofJg=a zPy+)X96>pOkSxGJS^{7^0e}_(pcVi?2pKdKKmdv}EQuf<17ZfW7(fsJ0Ps8kL}Lfy zH6#W`5DWt#gbV--jY*PXF@ca?1|VdS9$;h$AT=4_uu1`u;1)ncJYXaY07gI~@r(d@ z0)Q;c!Yl!kGYpF$G8iMtkin2ZB4DtpTD2TH$5K?520RvD7uz4~h15C{!k_D)M z0F1B(O(&6nz<}|P2w^}(FknOznD7`d5(U5+M^5 z2oMz(A~6?1BQh8uBqc&7HYYSSGymEE2mt{A0R;j8&M-~J7=P#=nBhl1e<1x}eEHAb z7Y769#(w_*=>6vyA1*LI>g02un0&d<-_Q0KKQ3@b0C>)G`_3>wU*8`;8OY}$f#*5% zgPil6VBlbmc+b{xfII+s`E$;70MG9S2mm-ebH)enz-RV3{Rf;M8QaG`e_7Zw^_{c# zf%@_C9(XPf8OP#026M&$;EoT=uwakl=ZqWy;GjP)bB~ukJ7+jK#(us<;4`241LPrr z^9@)O4hDZ?+XQo;ABf-v4~*x)00?J}0N*ZrV1RHQFhAIQ4>`_ppRDnM zI6pt$e_ZD|#(us*o-=^?h5-22Kc)xo`vrJCHNgO9fOweZo9~$c}g%4DItUfkV|uGt^H2>6l8P3^~Sj4n5mZ&vw`| z)=#fIfENxN3a-#^pHW~qlh&)^XYM)92%IoyVZco}3K{N6)HwMZ#>cY^BQx&W&NH2i zk}@am0fxa9gA~415>PLd0~j1AB@Q!;>T_h>mO8SKZAvCV+al~mNkt4FAuG@qduE!! z(tCoEqK%ex4U>9v6Op!?6zVM?HcO>$a(0^0{`<7^N{`q!k{@5$KT!1*UDPD-T;j%*vO@Mb9AkKYQpwU{{ZqYV&##k)UH-wXCFkGrmv}~3h61Q zL;(;vM-w2dWez|s@p<65R%TtiaKr=H5BQDS5a5O1M_26Sl$d0$i*Q#BT$rT~d|X7n zrYfgk*bWpe+LWSd$RJSk3{xgNh~i25W%z~v0O?7%HfXO$>B}T14#qAfnUoW8#q>w- zT49PaWG@LFvc$mk4T+P|FT^*BS8VuyFd7+jyWonaR>{l^4~L@|@X8ag30DjvXAut}u}{|S)zXM5t+tU|6a+X9a7UaB5cz+u z4+HW5&e&Y%$nrV*A0H!#aGRrwfz&_%KtuSzozJDR} zoB({gbDzBIJpTZE0ASoq_m{6okqCK8dd$OTIz*mIq5 z1aL|tmfqiWRlBJ9uyBC+!1-@a6-kdsCNu~C0M0}?!xye& zKOyHnA%}`s8>r|W!xB;OT;q&61C4}X`__`b{{SK%^h=P#m-6f#ej^kw**u8n!@
    45ah^Hj^5i>n&IsVCk5~Tyw%CFyOHi&<=;l(5 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%0Dr89tS_B8bNshX&1PSq>yp?Goe0mY@z5dWu{wF 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%0Agc1ZL%+~}FV{blp5c{elB0io% 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 v=r-v2at1~Mff5Atta5}B5)C0&UmqT2 literal 0 HcmV?d00001 diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..502cf02 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,262 @@ +OpenSK logo + +# Installation guide + +This document describes in details how to turn a Nordic nRF52840 board into a +working FIDO2 security key. + +## Pre-requisite + +### Hardware + +You will need one the following supported boards: + +* [Nordic nRF52840-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK) + development kit. This board is more convenient for development and debug + scenarios as the JTAG probe is already on the board. +* [Nordic nRF52840 Dongle](https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF52840-Dongle) + to have a more practical form factor. + +In the case of the Nordic USB dongle, you will also need the following extra +hardware: + +* a [Segger J-Link](https://www.segger.com/products/debug-probes/j-link/) JTAG + probe. +* a + [TC2050 Tag-Connect programming cable](http://www.tag-connect.com/TC2050-IDC-NL-050-ALL). +* a [Tag-Connect TC2050 ARM2010](http://www.tag-connect.com/TC2050-ARM2010) + adaptor +* optionally a + [Tag-Connect TC2050 retainer clip](http://www.tag-connect.com/TC2050-CLIP) + to keep the spring loaded connector pressed to the PCB. + +Although [OpenOCD](http://openocd.org/) should be supported we encountered some +issues while trying to flash a firmware with it. Therefore we suggest at the +moment to use a +[Segger J-Link](https://www.segger.com/products/debug-probes/j-link/) probe +instead. + +This guide **does not** cover how to setup the JTAG probe on your system. + +### Software + +In order to compile and flash a working OpenSK firmware, you will need the +following: + +* a working [Rust](https://rustup.rs/) toolchain installed on your system +* python3 and pip +* the OpenSSL command line tool + +The scripts provided in this project have been tested under Linux and OS X. We +haven't tested them on Windows and other platforms. + +## Compiling the firmware + +### Initial setup + +If you just cloned this repository, you need to run the following script +(_output may differ_): + +```shell +$ ./setup.sh +[-] Applying patch "01-persistent-storage.patch"... DONE. +[-] Applying patch "02-usb.patch"... DONE. +[-] Applying patch "03-app-memory.patch"... DONE. +[-] Applying patch "04-rtt.patch"... DONE. +[-] Applying patch "01-panic_console.patch"... DONE. +[-] Applying patch "02-timer.patch"... DONE. +[-] Applying patch "03-public_syscalls.patch"... DONE. +[-] Applying patch "04-bigger_heap.patch"... DONE. +Signature ok +subject=CN = Google OpenSK CA +Getting Private key +Signature ok +subject=CN = Google OpenSK Hacker Edition +Getting CA Private Key +info: syncing channel updates for 'nightly-2020-01-16-x86_64-unknown-linux-gnu' + + nightly-2020-01-16-x86_64-unknown-linux-gnu unchanged - rustc 1.42.0-nightly (3291ae339 2020-01-15) + +Requirement already up-to-date: tockloader in /usr/lib/python3/dist-packages/tockloader-1.4.0.dev0-py3.7.egg (1.4.0.dev0) +Requirement already satisfied, skipping upgrade: argcomplete>=1.8.2 in /usr/lib/python3/dist-packages (from tockloader) (1.10.0) +Requirement already satisfied, skipping upgrade: colorama>=0.3.7 in /usr/lib/python3/dist-packages (from tockloader) (0.3.7) +Requirement already satisfied, skipping upgrade: crcmod>=1.7 in /usr/lib/python3/dist-packages (from tockloader) (1.7) +Requirement already satisfied, skipping upgrade: pyserial>=3.0.1 in /usr/lib/python3/dist-packages (from tockloader) (3.4) +Requirement already satisfied, skipping upgrade: pytoml>=0.1.11 in /usr/lib/python3/dist-packages (from tockloader) (0.1.21) +info: component 'rust-std' for target 'thumbv7em-none-eabi' is up to date + Updating crates.io index + Ignored package `elf2tab v0.4.0` is already installed, use --force to override +``` + +The script performs the following steps: + +1. Make sure that the git submodules are checked out + +1. Apply our patches that haven't yet been merged upstream to both + [Tock](https://github.com/tock/tock) and + [libtock-rs](https://github.com/tock/libtock-rs) + +1. Generate a self-signed certificate authority as well as a private key and a + corresponding certificate for your OpenSK key signed by this CA. You will be + able to replace them with your own certificate and private key. + +1. Ensure that your Rust toolchain is using the same version that we tested + OpenSK with. + +1. Install [tockloader](https://github.com/tock/tockloader). + +1. Ensure that the Rust toolchain can compile code for ARM devices. + +### Replacing the certificates + +All the generated certificates and private keys are stored in the directory +`crypto_data/`. + +This is the expected content after running our `setup.sh` script: + +File | Purpose +----------------- | -------------------------------------------------------- +`opensk_ca.csr` | Certificate sign request for the Root CA +`opensk_ca.key` | ECC secp256r1 private key used for the Root CA +`opensk_ca.pem` | PEM encoded certificate of the Root CA +`opensk_ca.srl` | File generated by OpenSSL +`opensk_cert.csr` | Certificate sign request for the attestation certificate +`opensk_cert.pem` | PEM encoded certificate used for the authenticator +`opensk.key` | ECC secp256r1 private key used for the autenticator + +If you want to use your own attestation certificate and private key, simply +replace `opensk_cert.pem` and `opensk.key` files. + +Our build script is responsible for converting `opensk_cert.pem` and +`opensk.key` files into the following Rust file: `src/ctap/key_material.rs`. + +### Flashing a firmware + +#### Nordic nRF52840-DK board + +![Nordic development kit](img/devkit_annotated.jpg) + +1. Connect a micro USB cable to the JTAG USB port. + +1. Run our script for compiling/flashing your device (_output may differ_): + + ```shell + $ board=nrf52840dk ./deploy.sh app os + make: Entering directory './third_party/tock/boards/nordic/nrf52840dk' + Compiling kernel v0.1.0 (./third_party/tock/kernel) + Compiling cortexm v0.1.0 (./third_party/tock/arch/cortex-m) + Compiling nrf5x v0.1.0 (./third_party/tock/chips/nrf5x) + Compiling capsules v0.1.0 (./third_party/tock/capsules) + Compiling cortexm4 v0.1.0 (./third_party/tock/arch/cortex-m4) + Compiling nrf52 v0.1.0 (./third_party/tock/chips/nrf52) + Compiling nrf52840 v0.1.0 (./third_party/tock/chips/nrf52840) + Compiling components v0.1.0 (./third_party/tock/boards/components) + Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base) + Compiling nrf52840dk v0.1.0 (./third_party/tock/boards/nordic/nrf52840dk) + Finished release [optimized + debuginfo] target(s) in 11.28s + text data bss dec hex filename + 114688 1760 260384 376832 5c000 target/thumbv7em-none-eabi/release/nrf52840dk + tockloader flash --address 0x00000 --jlink --board nrf52dk target/thumbv7em-none-eabi/release/nrf52840dk.bin + [STATUS ] Flashing binar(y|ies) to board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.324 seconds + + make: Leaving directory './third_party/tock/boards/nordic/nrf52840dk' + [STATUS ] Preparing to uninstall apps... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [ERROR ] No apps are installed on the board + + Compiling libtock v0.1.0 (./third_party/libtock-rs) + Compiling crypto v0.1.0 (./libraries/crypto) + Compiling ctap2 v0.1.0 (.) + Finished release [optimized] target(s) in 7.60s + [STATUS ] Flashing binar(y|ies) to board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.305 seconds + + [STATUS ] Installing app on the board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.975 seconds + ``` + +1. Connect a micro USB cable to the device USB port. + +**Note**: Due to current limitations of our implementation and Tock, you may +have to press the `BOOT/RESET` button, located next to the device USB port on +the board in order to see your OpenSK device on your system. + +#### Nordic nRF52840 Dongle + +![Nordic dongle](img/dongle_front.jpg) + +1. The JTAG probe used for programming won't provide power to the board. + Therefore you will need to use a USB-A extension cable to power the dongle + through its USB port. + +1. Connect the TC2050 cable to the pads below the PCB: + + ![Nordic dongle pads](img/dongle_pads.jpg) + +1. You can use the retainer clip if you have one to avoid maintaining pressure + between the board and the cable: + + ![Nordic dongle retainer clip](img/dongle_clip.jpg) + +1. Run our script for compiling/flashing your device (_output may differ_): + + ```shell + $ board=nrf52840_dongle ./deploy.sh app os + make: Entering directory './third_party/tock/boards/nordic/nrf52840_dongle' + Compiling kernel v0.1.0 (./third_party/tock/kernel) + Compiling cortexm v0.1.0 (./third_party/tock/arch/cortex-m) + Compiling nrf5x v0.1.0 (./third_party/tock/chips/nrf5x) + Compiling capsules v0.1.0 (./third_party/tock/capsules) + Compiling cortexm4 v0.1.0 (./third_party/tock/arch/cortex-m4) + Compiling nrf52 v0.1.0 (./third_party/tock/chips/nrf52) + Compiling nrf52840 v0.1.0 (./third_party/tock/chips/nrf52840) + Compiling components v0.1.0 (./third_party/tock/boards/components) + Compiling nrf52dk_base v0.1.0 (./third_party/tock/boards/nordic/nrf52dk_base) + Compiling nrf52840_dongle v0.1.0 (./third_party/tock/boards/nordic/nrf52840_dongle) + Finished release [optimized + debuginfo] target(s) in 10.47s + text data bss dec hex filename + 110592 1688 252264 364544 59000 target/thumbv7em-none-eabi/release/nrf52840_dongle + tockloader flash --address 0x00000 --jlink --board nrf52dk target/thumbv7em-none-eabi/release/nrf52840_dongle.bin + [STATUS ] Flashing binar(y|ies) to board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.296 seconds + + make: Leaving directory './third_party/tock/boards/nordic/nrf52840_dongle' + [STATUS ] Preparing to uninstall apps... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [ERROR ] No apps are installed on the board + + Compiling libtock v0.1.0 (./third_party/libtock-rs) + Compiling crypto v0.1.0 (./libraries/crypto) + Compiling ctap2 v0.1.0 (.) + Finished release [optimized] target(s) in 7.60s + [STATUS ] Flashing binar(y|ies) to board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.317 seconds + + [STATUS ] Installing app on the board... + [INFO ] Using known arch and jtag-device for known board nrf52dk + [INFO ] Finished in 0.902 seconds + ``` + +1. Remove the programming cable and the USB-A extension cable. + +### Installing the udev rule (Linux only) + +By default on Linux, a USB device will require root privilege in order interact +with it. As it is not recommended to run your web browser with such a high +privileged account, we made a `udev` rule file to allow regular users to +interact with OpenSK authenticators. + +To install it, you need to execute the following commands: + +```shell +sudo cp rules.d/55-opensk.rules /etc/udev/rules.d/ +sudo udevadm control --reload +``` + +Then, you will need to unplug and replug the key for the rule to trigger. diff --git a/examples/crypto_bench.rs b/examples/crypto_bench.rs new file mode 100644 index 0000000..95a82d2 --- /dev/null +++ b/examples/crypto_bench.rs @@ -0,0 +1,180 @@ +// Copyright 2019 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. + +#![no_std] + +#[macro_use] +extern crate alloc; +extern crate crypto; +extern crate libtock; + +use alloc::vec::Vec; +use core::fmt::Write; +use crypto::{ + aes256, cbc, ecdsa, rng256, sha256, Decrypt16BytesBlock, Encrypt16BytesBlock, Hash256, +}; +use libtock::console::Console; +use libtock::timer; +use libtock::timer::Timer; +use libtock::timer::Timestamp; + +fn main() { + let mut console = Console::new(); + // Setup the timer with a dummy callback (we only care about reading the current time, but the + // API forces us to set an alarm callback too). + let mut with_callback = timer::with_callback(|_, _| {}); + let timer = with_callback.init().unwrap(); + + let mut rng = rng256::TockRng256 {}; + + writeln!(console, "****************************************").unwrap(); + writeln!( + console, + "Clock frequency: {} Hz", + timer.clock_frequency().hz() + ) + .unwrap(); + + // AES + bench(&mut console, &timer, "aes256::EncryptionKey::new", || { + aes256::EncryptionKey::new(&[0; 32]); + }); + let ek = aes256::EncryptionKey::new(&[0; 32]); + bench(&mut console, &timer, "aes256::DecryptionKey::new", || { + aes256::DecryptionKey::new(&ek); + }); + let dk = aes256::DecryptionKey::new(&ek); + + bench( + &mut console, + &timer, + "aes256::EncryptionKey::encrypt_block", + || { + ek.encrypt_block(&mut [0; 16]); + }, + ); + bench( + &mut console, + &timer, + "aes256::DecryptionKey::decrypt_block", + || { + dk.decrypt_block(&mut [0; 16]); + }, + ); + + // CBC + let mut blocks = Vec::new(); + for i in 0..8 { + blocks.resize(1 << i, [0; 16]); + bench( + &mut console, + &timer, + &format!("cbc::cbc_encrypt({} bytes)", blocks.len() * 16), + || { + cbc::cbc_encrypt(&ek, [0; 16], &mut blocks); + }, + ); + } + drop(blocks); + + let mut blocks = Vec::new(); + for i in 0..8 { + blocks.resize(1 << i, [0; 16]); + bench( + &mut console, + &timer, + &format!("cbc::cbc_decrypt({} bytes)", blocks.len() * 16), + || { + cbc::cbc_decrypt(&dk, [0; 16], &mut blocks); + }, + ); + } + drop(blocks); + + // SHA-256 + let mut contents = Vec::new(); + for i in 0..8 { + contents.resize(16 << i, 0); + bench( + &mut console, + &timer, + &format!("sha256::Sha256::update({} bytes)", contents.len()), + || { + let mut sha = sha256::Sha256::new(); + sha.update(&contents); + sha.finalize(); + }, + ); + } + drop(contents); + + // ECDSA + bench(&mut console, &timer, "ecdsa::SecKey::gensk", || { + ecdsa::SecKey::gensk(&mut rng); + }); + let k = ecdsa::SecKey::gensk(&mut rng); + bench(&mut console, &timer, "ecdsa::SecKey::genpk", || { + k.genpk(); + }); + bench( + &mut console, + &timer, + "ecdsa::SecKey::sign_rng::", + || { + k.sign_rng::(&[], &mut rng); + }, + ); + bench( + &mut console, + &timer, + "ecdsa::SecKey::sign_rfc6979::", + || { + k.sign_rfc6979::(&[]); + }, + ); + + writeln!(console, "****************************************").unwrap(); + writeln!(console, "All the benchmarks are done.\nHave a nice day!").unwrap(); + writeln!(console, "****************************************").unwrap(); +} + +fn bench(console: &mut Console, timer: &Timer, title: &str, mut f: F) +where + F: FnMut() -> (), +{ + writeln!(console, "****************************************").unwrap(); + writeln!(console, "Benchmarking: {}", title).unwrap(); + writeln!(console, "----------------------------------------").unwrap(); + let mut count = 1; + for _ in 0..30 { + let start = Timestamp::::from_clock_value(timer.get_current_clock()); + for _ in 0..count { + f(); + } + let end = Timestamp::::from_clock_value(timer.get_current_clock()); + let elapsed = (end - start).ms(); + writeln!( + console, + "{} ms elapsed for {} iterations ({} ms/iter)", + elapsed, + count, + elapsed / (count as f64) + ) + .unwrap(); + if elapsed > 1000.0 { + break; + } + count <<= 1; + } +} diff --git a/layout.ld b/layout.ld new file mode 100644 index 0000000..5bc9d0c --- /dev/null +++ b/layout.ld @@ -0,0 +1,170 @@ +/* Userland Generic Layout + * + * Currently, due to incomplete ROPI-RWPI support in rustc (see + * https://github.com/tock/libtock-rs/issues/28), this layout implements static + * linking. An application init script must define the FLASH and SRAM address + * ranges as well as MPU_MIN_ALIGN before including this layout file. + * + * Here is a an example application linker script to get started: + * MEMORY { + * /* FLASH memory region must start immediately *after* the Tock + * * Binary Format headers, which means you need to offset the + * * beginning of FLASH memory region relative to where the + * * application is loaded. + * FLASH (rx) : ORIGIN = 0x10030, LENGTH = 0x0FFD0 + * SRAM (RWX) : ORIGIN = 0x20000, LENGTH = 0x10000 + * } + * STACK_SIZE = 2048; + * MPU_MIN_ALIGN = 8K; + * INCLUDE ../libtock-rs/layout.ld + */ + +ENTRY(_start) + +SECTIONS { + /* Section for just the app crt0 header. + * This must be first so that the app can find it. + */ + .crt0_header : + { + _beginning = .; /* Start of the app in flash. */ + /** + * Populate the header expected by `crt0`: + * + * struct hdr { + * uint32_t got_sym_start; + * uint32_t got_start; + * uint32_t got_size; + * uint32_t data_sym_start; + * uint32_t data_start; + * uint32_t data_size; + * uint32_t bss_start; + * uint32_t bss_size; + * uint32_t reldata_start; + * uint32_t stack_size; + * }; + */ + /* Offset of GOT symbols in flash */ + LONG(LOADADDR(.got) - _beginning); + /* Offset of GOT section in memory */ + LONG(_got); + /* Size of GOT section */ + LONG(SIZEOF(.got)); + /* Offset of data symbols in flash */ + LONG(LOADADDR(.data) - _beginning); + /* Offset of data section in memory */ + LONG(_data); + /* Size of data section */ + LONG(SIZEOF(.data)); + /* Offset of BSS section in memory */ + LONG(_bss); + /* Size of BSS section */ + LONG(SIZEOF(.bss)); + /* First address offset after program flash, where elf2tab places + * .rel.data section */ + LONG(LOADADDR(.endflash) - _beginning); + /* The size of the stack requested by this application */ + LONG(STACK_SIZE); + /* Pad the header out to a multiple of 32 bytes so there is not a gap + * between the header and subsequent .data section. It's unclear why, + * but LLD is aligning sections to a multiple of 32 bytes. */ + . = ALIGN(32); + } > FLASH =0xFF + + /* App state section. Used for persistent app data. + * We put this first because this is what libtock-c does. They provide the + * following explanation: if the app code changes but the persistent data + * doesn't, the app_state can be preserved. + */ + .wfr.app_state : + { + . = ALIGN(4K); + KEEP (*(.app_state)) + . = ALIGN(4K); + } > FLASH =0xFFFFFFFF + + /* Text section, Code! */ + .text : + { + . = ALIGN(4); + _text = .; + KEEP (*(.start)) + *(.text*) + *(.rodata*) + KEEP (*(.syscalls)) + *(.ARM.extab*) + . = ALIGN(4); /* Make sure we're word-aligned here */ + _etext = .; + } > FLASH =0xFF + + /* Application stack */ + .stack : + { + . = . + STACK_SIZE; + + _stack_top_unaligned = .; + . = ALIGN(8); + _stack_top_aligned = .; + } > SRAM + + /* Data section, static initialized variables + * Note: This is placed in Flash after the text section, but needs to be + * moved to SRAM at runtime + */ + .data : AT (_etext) + { + . = ALIGN(4); /* Make sure we're word-aligned here */ + _data = .; + KEEP(*(.data*)) + . = ALIGN(4); /* Make sure we're word-aligned at the end of flash */ + } > SRAM + + /* Global Offset Table */ + .got : + { + . = ALIGN(4); /* Make sure we're word-aligned here */ + _got = .; + *(.got*) + *(.got.plt*) + . = ALIGN(4); + } > SRAM + + /* BSS section, static uninitialized variables */ + .bss : + { + . = ALIGN(4); /* Make sure we're word-aligned here */ + _bss = .; + KEEP(*(.bss*)) + *(COMMON) + . = ALIGN(4); + } > SRAM + + /* End of flash. */ + .endflash : + { + } > FLASH + + /* ARM Exception support + * + * This contains compiler-generated support for unwinding the stack, + * consisting of key-value pairs of function addresses and information on + * how to unwind stack frames. + * https://wiki.linaro.org/KenWerner/Sandbox/libunwind?action=AttachFile&do=get&target=libunwind-LDS.pdf + * + * .ARM.exidx is sorted, so has to go in its own output section. + * + * __NOTE__: It's at the end because we currently don't actually serialize + * it to the binary in elf2tbf. If it was before the RAM sections, it would + * through off our calculations of the header. + */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + /* (C++) Index entries for section unwinding */ + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + PROVIDE_HIDDEN (__exidx_end = .); +} + +ASSERT((_stack_top_aligned - _stack_top_unaligned) == 0, " +STACK_SIZE must be 8 byte multiple") diff --git a/libraries/cbor/Cargo.toml b/libraries/cbor/Cargo.toml new file mode 100644 index 0000000..bcae013 --- /dev/null +++ b/libraries/cbor/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "cbor" +version = "0.1.0" +authors = [ + "Fabian Kaczmarczyck ", + "Guillaume Endignoux ", + "Jean-Michel Picod ", +] +license = "Apache-2.0" +edition = "2018" + +[dependencies] + +[features] +std = [] diff --git a/libraries/cbor/src/lib.rs b/libraries/cbor/src/lib.rs new file mode 100644 index 0000000..00a9c55 --- /dev/null +++ b/libraries/cbor/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2019 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. + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +#[cfg(feature = "std")] +extern crate core; + +#[macro_use] +pub mod macros; +pub mod reader; +pub mod values; +pub mod writer; + +pub use self::reader::read; +pub use self::values::{KeyType, SimpleValue, Value}; +pub use self::writer::write; diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs new file mode 100644 index 0000000..5a3d8f5 --- /dev/null +++ b/libraries/cbor/src/macros.rs @@ -0,0 +1,500 @@ +// Copyright 2019 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. + +#[macro_export] +macro_rules! cbor_map { + // trailing comma case + ( $( $key:expr => $value:expr, )+ ) => { + cbor_map! ( $($key => $value),+ ) + }; + + ( $( $key:expr => $value:expr ),* ) => { + { + // The import is unused if the list is empty. + #[allow(unused_imports)] + use $crate::values::{IntoCborKey, IntoCborValue}; + let mut _map = ::alloc::collections::BTreeMap::new(); + $( + _map.insert($key.into_cbor_key(), $value.into_cbor_value()); + )* + $crate::values::Value::Map(_map) + } + }; +} + +#[macro_export] +macro_rules! cbor_map_options { + // trailing comma case + ( $( $key:expr => $value:expr, )+ ) => { + cbor_map_options! ( $($key => $value),+ ) + }; + + ( $( $key:expr => $value:expr ),* ) => { + { + // The import is unused if the list is empty. + #[allow(unused_imports)] + use $crate::values::{IntoCborKey, IntoCborValueOption}; + let mut _map = ::alloc::collections::BTreeMap::<_, $crate::values::Value>::new(); + $( + { + let opt: Option<$crate::values::Value> = $value.into_cbor_value_option(); + if let Some(val) = opt { + _map.insert($key.into_cbor_key(), val); + } + } + )* + $crate::values::Value::Map(_map) + } + }; +} + +#[macro_export] +macro_rules! cbor_map_btree { + ( $tree:expr ) => { + $crate::values::Value::Map($tree) + }; +} + +#[macro_export] +macro_rules! cbor_array { + // trailing comma case + ( $( $value:expr, )+ ) => { + cbor_array! ( $($value),+ ) + }; + + ( $( $value:expr ),* ) => { + { + // The import is unused if the list is empty. + #[allow(unused_imports)] + use $crate::values::IntoCborValue; + $crate::values::Value::Array(vec![ $( $value.into_cbor_value(), )* ]) + } + }; +} + +#[macro_export] +macro_rules! cbor_array_vec { + ( $vec:expr ) => {{ + use $crate::values::IntoCborValue; + $crate::values::Value::Array($vec.into_iter().map(|x| x.into_cbor_value()).collect()) + }}; +} + +#[cfg(test)] +macro_rules! cbor_true { + ( ) => { + $crate::values::Value::Simple($crate::values::SimpleValue::TrueValue) + }; +} + +#[macro_export] +macro_rules! cbor_false { + ( ) => { + $crate::values::Value::Simple($crate::values::SimpleValue::FalseValue) + }; +} + +#[macro_export] +macro_rules! cbor_null { + ( ) => { + $crate::values::Value::Simple($crate::values::SimpleValue::NullValue) + }; +} + +#[cfg(test)] +macro_rules! cbor_undefined { + ( ) => { + $crate::values::Value::Simple($crate::values::SimpleValue::Undefined) + }; +} + +#[macro_export] +macro_rules! cbor_bool { + ( $x:expr ) => { + $crate::values::Value::bool_value($x) + }; +} + +// For key types, we construct a KeyType and call .into(), which will automatically convert it to a +// KeyType or a Value depending on the context. +#[macro_export] +macro_rules! cbor_unsigned { + ( $x:expr ) => { + cbor_key_unsigned!($x).into() + }; +} + +#[macro_export] +macro_rules! cbor_int { + ( $x:expr ) => { + cbor_key_int!($x).into() + }; +} + +#[macro_export] +macro_rules! cbor_text { + ( $x:expr ) => { + cbor_key_text!($x).into() + }; +} + +#[macro_export] +macro_rules! cbor_bytes { + ( $x:expr ) => { + cbor_key_bytes!($x).into() + }; +} + +// Macro to use with a literal, e.g. cbor_bytes_lit!(b"foo") +#[macro_export] +macro_rules! cbor_bytes_lit { + ( $x:expr ) => { + cbor_bytes!(($x as &[u8]).to_vec()) + }; +} + +// Some explicit macros are also available for contexts where the type is not explicit. +#[macro_export] +macro_rules! cbor_key_unsigned { + ( $x:expr ) => { + $crate::values::KeyType::Unsigned($x) + }; +} + +#[macro_export] +macro_rules! cbor_key_int { + ( $x:expr ) => { + $crate::values::KeyType::integer($x) + }; +} + +#[macro_export] +macro_rules! cbor_key_text { + ( $x:expr ) => { + $crate::values::KeyType::TextString($x.into()) + }; +} + +#[macro_export] +macro_rules! cbor_key_bytes { + ( $x:expr ) => { + $crate::values::KeyType::ByteString($x) + }; +} + +#[cfg(test)] +mod test { + use super::super::values::{KeyType, SimpleValue, Value}; + use alloc::collections::BTreeMap; + + #[test] + fn test_cbor_simple_values() { + assert_eq!(cbor_true!(), Value::Simple(SimpleValue::TrueValue)); + assert_eq!(cbor_false!(), Value::Simple(SimpleValue::FalseValue)); + assert_eq!(cbor_null!(), Value::Simple(SimpleValue::NullValue)); + assert_eq!(cbor_undefined!(), Value::Simple(SimpleValue::Undefined)); + } + + #[test] + fn test_cbor_bool() { + assert_eq!(cbor_bool!(true), Value::Simple(SimpleValue::TrueValue)); + assert_eq!(cbor_bool!(false), Value::Simple(SimpleValue::FalseValue)); + } + + #[test] + fn test_cbor_int_unsigned() { + assert_eq!(cbor_key_int!(0), KeyType::Unsigned(0)); + assert_eq!(cbor_key_int!(1), KeyType::Unsigned(1)); + assert_eq!(cbor_key_int!(123456), KeyType::Unsigned(123456)); + assert_eq!( + cbor_key_int!(std::i64::MAX), + KeyType::Unsigned(std::i64::MAX as u64) + ); + } + + #[test] + fn test_cbor_int_negative() { + assert_eq!(cbor_key_int!(-1), KeyType::Negative(-1)); + assert_eq!(cbor_key_int!(-123456), KeyType::Negative(-123456)); + assert_eq!( + cbor_key_int!(std::i64::MIN), + KeyType::Negative(std::i64::MIN) + ); + } + + #[test] + fn test_cbor_int_literals() { + let a = cbor_array![ + std::i64::MIN, + std::i32::MIN, + -123456, + -1, + 0, + 1, + 123456, + std::i32::MAX, + std::i64::MAX, + std::u64::MAX, + ]; + let b = Value::Array(vec![ + Value::KeyValue(KeyType::Negative(std::i64::MIN)), + Value::KeyValue(KeyType::Negative(std::i32::MIN as i64)), + Value::KeyValue(KeyType::Negative(-123456)), + Value::KeyValue(KeyType::Negative(-1)), + Value::KeyValue(KeyType::Unsigned(0)), + Value::KeyValue(KeyType::Unsigned(1)), + Value::KeyValue(KeyType::Unsigned(123456)), + Value::KeyValue(KeyType::Unsigned(std::i32::MAX as u64)), + Value::KeyValue(KeyType::Unsigned(std::i64::MAX as u64)), + Value::KeyValue(KeyType::Unsigned(std::u64::MAX)), + ]); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_array() { + let a = cbor_array![ + -123, + 456, + true, + cbor_null!(), + "foo", + b"bar", + cbor_array![], + cbor_array![0, 1], + cbor_map! {}, + cbor_map! {2 => 3}, + ]; + let b = Value::Array(vec![ + Value::KeyValue(KeyType::Negative(-123)), + Value::KeyValue(KeyType::Unsigned(456)), + Value::Simple(SimpleValue::TrueValue), + Value::Simple(SimpleValue::NullValue), + Value::KeyValue(KeyType::TextString(String::from("foo"))), + Value::KeyValue(KeyType::ByteString(b"bar".to_vec())), + Value::Array(Vec::new()), + Value::Array(vec![ + Value::KeyValue(KeyType::Unsigned(0)), + Value::KeyValue(KeyType::Unsigned(1)), + ]), + Value::Map(BTreeMap::new()), + Value::Map( + [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + .iter() + .cloned() + .collect(), + ), + ]); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_array_vec_empty() { + let a = cbor_array_vec!(Vec::::new()); + let b = Value::Array(Vec::new()); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_array_vec_int() { + let a = cbor_array_vec!(vec![1, 2, 3, 4]); + let b = Value::Array(vec![ + Value::KeyValue(KeyType::Unsigned(1)), + Value::KeyValue(KeyType::Unsigned(2)), + Value::KeyValue(KeyType::Unsigned(3)), + Value::KeyValue(KeyType::Unsigned(4)), + ]); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_array_vec_text() { + let a = cbor_array_vec!(vec!["a", "b", "c"]); + let b = Value::Array(vec![ + Value::KeyValue(KeyType::TextString(String::from("a"))), + Value::KeyValue(KeyType::TextString(String::from("b"))), + Value::KeyValue(KeyType::TextString(String::from("c"))), + ]); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_array_vec_bytes() { + let a = cbor_array_vec!(vec![b"a", b"b", b"c"]); + let b = Value::Array(vec![ + Value::KeyValue(KeyType::ByteString(b"a".to_vec())), + Value::KeyValue(KeyType::ByteString(b"b".to_vec())), + Value::KeyValue(KeyType::ByteString(b"c".to_vec())), + ]); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_map() { + let a = cbor_map! { + -1 => -23, + 4 => 56, + "foo" => true, + b"bar" => cbor_null!(), + 5 => "foo", + 6 => b"bar", + 7 => cbor_array![], + 8 => cbor_array![0, 1], + 9 => cbor_map!{}, + 10 => cbor_map!{2 => 3}, + }; + let b = Value::Map( + [ + ( + KeyType::Negative(-1), + Value::KeyValue(KeyType::Negative(-23)), + ), + (KeyType::Unsigned(4), Value::KeyValue(KeyType::Unsigned(56))), + ( + KeyType::TextString(String::from("foo")), + Value::Simple(SimpleValue::TrueValue), + ), + ( + KeyType::ByteString(b"bar".to_vec()), + Value::Simple(SimpleValue::NullValue), + ), + ( + KeyType::Unsigned(5), + Value::KeyValue(KeyType::TextString(String::from("foo"))), + ), + ( + KeyType::Unsigned(6), + Value::KeyValue(KeyType::ByteString(b"bar".to_vec())), + ), + (KeyType::Unsigned(7), Value::Array(Vec::new())), + ( + KeyType::Unsigned(8), + Value::Array(vec![ + Value::KeyValue(KeyType::Unsigned(0)), + Value::KeyValue(KeyType::Unsigned(1)), + ]), + ), + (KeyType::Unsigned(9), Value::Map(BTreeMap::new())), + ( + KeyType::Unsigned(10), + Value::Map( + [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + .iter() + .cloned() + .collect(), + ), + ), + ] + .iter() + .cloned() + .collect(), + ); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_map_options() { + let a = cbor_map_options! { + -1 => -23, + 4 => Some(56), + 11 => None::, + "foo" => true, + 12 => None::<&str>, + b"bar" => Some(cbor_null!()), + 13 => None::>, + 5 => "foo", + 14 => None::<&[u8]>, + 6 => Some(b"bar" as &[u8]), + 15 => None::, + 7 => cbor_array![], + 16 => None::, + 8 => Some(cbor_array![0, 1]), + 17 => None::, + 9 => cbor_map!{}, + 18 => None::, + 10 => Some(cbor_map!{2 => 3}), + }; + let b = Value::Map( + [ + ( + KeyType::Negative(-1), + Value::KeyValue(KeyType::Negative(-23)), + ), + (KeyType::Unsigned(4), Value::KeyValue(KeyType::Unsigned(56))), + ( + KeyType::TextString(String::from("foo")), + Value::Simple(SimpleValue::TrueValue), + ), + ( + KeyType::ByteString(b"bar".to_vec()), + Value::Simple(SimpleValue::NullValue), + ), + ( + KeyType::Unsigned(5), + Value::KeyValue(KeyType::TextString(String::from("foo"))), + ), + ( + KeyType::Unsigned(6), + Value::KeyValue(KeyType::ByteString(b"bar".to_vec())), + ), + (KeyType::Unsigned(7), Value::Array(Vec::new())), + ( + KeyType::Unsigned(8), + Value::Array(vec![ + Value::KeyValue(KeyType::Unsigned(0)), + Value::KeyValue(KeyType::Unsigned(1)), + ]), + ), + (KeyType::Unsigned(9), Value::Map(BTreeMap::new())), + ( + KeyType::Unsigned(10), + Value::Map( + [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + .iter() + .cloned() + .collect(), + ), + ), + ] + .iter() + .cloned() + .collect(), + ); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_map_btree_empty() { + let a = cbor_map_btree!(BTreeMap::new()); + let b = Value::Map(BTreeMap::new()); + assert_eq!(a, b); + } + + #[test] + fn test_cbor_map_btree_foo() { + let a = cbor_map_btree!( + [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + .iter() + .cloned() + .collect() + ); + let b = Value::Map( + [(KeyType::Unsigned(2), Value::KeyValue(KeyType::Unsigned(3)))] + .iter() + .cloned() + .collect(), + ); + assert_eq!(a, b); + } +} diff --git a/libraries/cbor/src/reader.rs b/libraries/cbor/src/reader.rs new file mode 100644 index 0000000..0ba6a6c --- /dev/null +++ b/libraries/cbor/src/reader.rs @@ -0,0 +1,811 @@ +// Copyright 2019 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. + +use super::values::{Constants, KeyType, SimpleValue, Value}; +use alloc::collections::BTreeMap; +use alloc::str; +use alloc::vec::Vec; + +#[derive(Debug, PartialEq)] +pub enum DecoderError { + UnsupportedMajorType, + UnknownAdditionalInfo, + IncompleteCborData, + IncorrectMapKeyType, + TooMuchNesting, + InvalidUtf8, + ExtranousData, + OutOfOrderKey, + NonMinimalCborEncoding, + UnsupportedSimpleValue, + UnsupportedFloatingPointValue, + OutOfRangeIntegerValue, +} + +pub fn read(encoded_cbor: &[u8]) -> Result { + let mut reader = Reader::new(encoded_cbor); + let value = reader.decode_complete_data_item(Reader::MAX_NESTING_DEPTH)?; + if !reader.remaining_cbor.is_empty() { + return Err(DecoderError::ExtranousData); + } + Ok(value) +} + +struct Reader<'a> { + remaining_cbor: &'a [u8], +} + +impl<'a> Reader<'a> { + const MAX_NESTING_DEPTH: i8 = 4; + + pub fn new(cbor: &'a [u8]) -> Reader<'a> { + Reader { + remaining_cbor: cbor, + } + } + + pub fn decode_complete_data_item( + &mut self, + remaining_depth: i8, + ) -> Result { + if remaining_depth < 0 { + return Err(DecoderError::TooMuchNesting); + } + + match self.read_bytes(1) { + Some([first_byte]) => { + // Unsigned byte means logical shift, so only zeros get shifted in. + let major_type_value = first_byte >> Constants::MAJOR_TYPE_BIT_SHIFT; + let additional_info = first_byte & Constants::ADDITIONAL_INFORMATION_MASK; + let size_result = self.read_variadic_length_integer(additional_info); + match size_result { + Ok(size_value) => match major_type_value { + 0 => self.decode_value_to_unsigned(size_value), + 1 => self.decode_value_to_negative(size_value), + 2 => self.read_byte_string_content(size_value), + 3 => self.read_text_string_content(size_value), + 4 => self.read_array_content(size_value, remaining_depth), + 5 => self.read_map_content(size_value, remaining_depth), + 7 => self.decode_to_simple_value(size_value, additional_info), + _ => Err(DecoderError::UnsupportedMajorType), + }, + Err(decode_error) => Err(decode_error), + } + } + _ => Err(DecoderError::IncompleteCborData), + } + } + + fn read_bytes(&mut self, num_bytes: usize) -> Option<&[u8]> { + if num_bytes > self.remaining_cbor.len() { + None + } else { + let (left, right) = self.remaining_cbor.split_at(num_bytes); + self.remaining_cbor = right; + Some(left) + } + } + + fn read_variadic_length_integer(&mut self, additional_info: u8) -> Result { + let additional_bytes_num = match additional_info { + 0..=Constants::ADDITIONAL_INFORMATION_MAX_INT => return Ok(additional_info as u64), + Constants::ADDITIONAL_INFORMATION_1_BYTE => 1, + Constants::ADDITIONAL_INFORMATION_2_BYTES => 2, + Constants::ADDITIONAL_INFORMATION_4_BYTES => 4, + Constants::ADDITIONAL_INFORMATION_8_BYTES => 8, + _ => return Err(DecoderError::UnknownAdditionalInfo), + }; + match self.read_bytes(additional_bytes_num) { + Some(bytes) => { + let mut size_value = 0u64; + for byte in bytes { + size_value <<= 8; + size_value += *byte as u64; + } + if (additional_bytes_num == 1 && size_value < 24) + || size_value < (1u64 << (8 * (additional_bytes_num >> 1))) + { + Err(DecoderError::NonMinimalCborEncoding) + } else { + Ok(size_value) + } + } + None => Err(DecoderError::IncompleteCborData), + } + } + + fn decode_value_to_unsigned(&self, size_value: u64) -> Result { + Ok(cbor_unsigned!(size_value)) + } + + fn decode_value_to_negative(&self, size_value: u64) -> Result { + let signed_size = size_value as i64; + if signed_size < 0 { + Err(DecoderError::OutOfRangeIntegerValue) + } else { + Ok(Value::KeyValue(KeyType::Negative(-(size_value as i64) - 1))) + } + } + + fn read_byte_string_content(&mut self, size_value: u64) -> Result { + match self.read_bytes(size_value as usize) { + Some(bytes) => Ok(cbor_bytes_lit!(bytes)), + None => Err(DecoderError::IncompleteCborData), + } + } + + fn read_text_string_content(&mut self, size_value: u64) -> Result { + match self.read_bytes(size_value as usize) { + Some(bytes) => match str::from_utf8(bytes) { + Ok(s) => Ok(cbor_text!(s)), + Err(_) => Err(DecoderError::InvalidUtf8), + }, + None => Err(DecoderError::IncompleteCborData), + } + } + + fn read_array_content( + &mut self, + size_value: u64, + remaining_depth: i8, + ) -> Result { + // Don't set the capacity already, it is an unsanitized input. + let mut value_array = Vec::new(); + for _ in 0..size_value { + value_array.push(self.decode_complete_data_item(remaining_depth - 1)?); + } + Ok(cbor_array_vec!(value_array)) + } + + fn read_map_content( + &mut self, + size_value: u64, + remaining_depth: i8, + ) -> Result { + let mut value_map = BTreeMap::new(); + let mut last_key_option = None; + for _ in 0..size_value { + let key_value = self.decode_complete_data_item(remaining_depth - 1)?; + if let Value::KeyValue(key) = key_value { + if let Some(last_key) = last_key_option { + if last_key >= key { + return Err(DecoderError::OutOfOrderKey); + } + } + last_key_option = Some(key.clone()); + value_map.insert(key, self.decode_complete_data_item(remaining_depth - 1)?); + } else { + return Err(DecoderError::IncorrectMapKeyType); + } + } + Ok(cbor_map_btree!(value_map)) + } + + fn decode_to_simple_value( + &self, + size_value: u64, + additional_info: u8, + ) -> Result { + if additional_info > Constants::ADDITIONAL_INFORMATION_MAX_INT + && additional_info != Constants::ADDITIONAL_INFORMATION_1_BYTE + { + // TODO(kaczmarczyck) the chromium C++ reference allows equality to 24 here, why? + // Also, why not just disallow ANY additional_info != size_value? + return Err(DecoderError::UnsupportedFloatingPointValue); + } + match SimpleValue::from_integer(size_value) { + Some(simple_value) => Ok(Value::Simple(simple_value)), + None => Err(DecoderError::UnsupportedSimpleValue), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_read_unsigned() { + let cases = vec![ + (0, vec![0x00]), + (1, vec![0x01]), + (10, vec![0x0A]), + (23, vec![0x17]), + (24, vec![0x18, 0x18]), + (255, vec![0x18, 0xFF]), + (256, vec![0x19, 0x01, 0x00]), + (65535, vec![0x19, 0xFF, 0xFF]), + (65536, vec![0x1A, 0x00, 0x01, 0x00, 0x00]), + (0xFFFFFFFF, vec![0x1A, 0xFF, 0xFF, 0xFF, 0xFF]), + ( + 0x100000000, + vec![0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00], + ), + ( + std::i64::MAX, + vec![0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + ), + ]; + for (unsigned, mut cbor) in cases { + assert_eq!(read(&cbor), Ok(cbor_int!(unsigned))); + cbor.push(0x01); + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_unsigned_non_minimum_byte_length() { + let encodings = vec![ + // Uint 23 encoded with 1 byte. + vec![0x18, 0x17], + // Uint 255 encoded with 2 bytes. + vec![0x19, 0x00, 0xff], + // Uint 65535 encoded with 4 bytes. + vec![0x1a, 0x00, 0x00, 0xff, 0xff], + // Uint 4294967295 encoded with 8 bytes. + vec![0x1b, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff], + // When decoding byte has more than one syntax error, the first syntax + // error encountered during deserialization is returned as the error code. + vec![ + 0xa2, // map with non-minimally encoded key + 0x17, // key 24 + 0x61, 0x42, // value :"B" + 0x18, 0x17, // key 23 encoded with extra byte + 0x61, 0x45, // value "E" + ], + vec![ + 0xa2, // map with out of order and non-minimally encoded key + 0x18, 0x17, // key 23 encoded with extra byte + 0x61, 0x45, // value "E" + 0x17, // key 23 + 0x61, 0x42, // value :"B" + ], + vec![ + 0xa2, // map with duplicate non-minimally encoded key + 0x18, 0x17, // key 23 encoded with extra byte + 0x61, 0x45, // value "E" + 0x18, 0x17, // key 23 encoded with extra byte + 0x61, 0x42, // value :"B" + ], + ]; + for encoding in encodings { + assert_eq!(read(&encoding), Err(DecoderError::NonMinimalCborEncoding)); + } + } + + #[test] + fn test_read_negative() { + let cases = vec![ + (-1, vec![0x20]), + (-24, vec![0x37]), + (-25, vec![0x38, 0x18]), + (-256, vec![0x38, 0xFF]), + (-1000, vec![0x39, 0x03, 0xE7]), + (-1000000, vec![0x3A, 0x00, 0x0F, 0x42, 0x3F]), + (-4294967296, vec![0x3A, 0xFF, 0xFF, 0xFF, 0xFF]), + ( + std::i64::MIN, + vec![0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + ), + ]; + for (negative, mut cbor) in cases { + assert_eq!(read(&cbor), Ok(cbor_int!(negative))); + cbor.push(0x01); + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_byte_string() { + let cases = vec![ + (Vec::new(), vec![0x40]), + ( + vec![0x01, 0x02, 0x03, 0x04], + vec![0x44, 0x01, 0x02, 0x03, 0x04], + ), + ]; + for (byte_string, mut cbor) in cases { + assert_eq!(read(&cbor), Ok(cbor_bytes!(byte_string))); + cbor.push(0x01); + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_text_string() { + let unicode_3byte = vec![0xE6, 0xB0, 0xB4]; + let cases = vec![ + ("", vec![0x60]), + ("a", vec![0x61, 0x61]), + ("IETF", vec![0x64, 0x49, 0x45, 0x54, 0x46]), + ("\"\\", vec![0x62, 0x22, 0x5C]), + ("ü", vec![0x62, 0xC3, 0xBC]), + ( + std::str::from_utf8(&unicode_3byte).unwrap(), + vec![0x63, 0xE6, 0xB0, 0xB4], + ), + ("𐅑", vec![0x64, 0xF0, 0x90, 0x85, 0x91]), + ]; + for (text_string, mut cbor) in cases { + assert_eq!(read(&cbor), Ok(cbor_text!(text_string))); + cbor.push(0x01); + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_text_string_with_nul() { + let cases = vec![ + ( + "string_without_nul", + vec![ + 0x72, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x5F, 0x77, 0x69, 0x74, 0x68, 0x6F, + 0x75, 0x74, 0x5F, 0x6E, 0x75, 0x6C, + ], + ), + ( + "nul_terminated_string\0", + vec![ + 0x76, 0x6E, 0x75, 0x6C, 0x5F, 0x74, 0x65, 0x72, 0x6D, 0x69, 0x6E, 0x61, 0x74, + 0x65, 0x64, 0x5F, 0x73, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x00, + ], + ), + ( + "embedded\0nul", + vec![ + 0x6C, 0x65, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x00, 0x6E, 0x75, 0x6C, + ], + ), + ( + "trailing_nuls\0\0", + vec![ + 0x6F, 0x74, 0x72, 0x61, 0x69, 0x6C, 0x69, 0x6E, 0x67, 0x5F, 0x6E, 0x75, 0x6C, + 0x73, 0x00, 0x00, + ], + ), + ]; + for (text_string, mut cbor) in cases { + assert_eq!(read(&cbor), Ok(cbor_text!(text_string))); + cbor.push(0x01); + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_text_string_with_invalid_byte_sequence_after_nul() { + assert_eq!( + read(&vec![0x63, 0x00, 0x00, 0xA6]), + Err(DecoderError::InvalidUtf8) + ); + } + + #[test] + fn test_read_array() { + let value_vec: Vec<_> = (1..26).collect(); + let mut test_cbor = vec![ + 0x98, 0x19, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, + 0x19, + ]; + assert_eq!(read(&test_cbor.clone()), Ok(cbor_array_vec!(value_vec))); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_map() { + let value_map = cbor_map! { + 24 => "abc", + "" => ".", + "b" => "B", + "aa" => "AA", + }; + let mut test_cbor = vec![ + 0xa4, // map with 4 key value pairs: + 0x18, 0x18, // 24 + 0x63, 0x61, 0x62, 0x63, // "abc" + 0x60, // "" + 0x61, 0x2e, // "." + 0x61, 0x62, // "b" + 0x61, 0x42, // "B" + 0x62, 0x61, 0x61, // "aa" + 0x62, 0x41, 0x41, // "AA" + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_map_with_unsigned_keys() { + let value_map = cbor_map! { + 1 => "a", + 9 => "b", + 999 => "c", + 1111 => "d", + }; + let mut test_cbor = vec![ + 0xa4, // map with 4 key value pairs: + 0x01, // key : 1 + 0x61, 0x61, // value : "a" + 0x09, // key : 9 + 0x61, 0x62, // value : "b" + 0x19, 0x03, 0xE7, // key : 999 + 0x61, 0x63, // value "c" + 0x19, 0x04, 0x57, // key : 1111 + 0x61, 0x64, // value : "d" + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_map_with_negative_keys() { + let value_map = cbor_map! { + -1 => 1, + -2 => 2, + -100 => 3, + }; + let mut test_cbor = vec![ + 0xA3, // map with 3 key value pairs + 0x20, // key : -1 + 0x01, // value : 1 + 0x21, // key : -2 + 0x02, // value : 2 + 0x38, 0x63, // key : -100 + 0x03, // value : 3 + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_map_with_array() { + let value_map = cbor_map! { + "a" => 1, + "b" => cbor_array![2, 3], + }; + let mut test_cbor = vec![ + 0xa2, // map of 2 pairs + 0x61, 0x61, // "a" + 0x01, 0x61, 0x62, // "b" + 0x82, // array with 2 elements + 0x02, 0x03, + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_map_with_text_string_keys() { + let value_map = cbor_map! { + "k" => "v", + "foo" => "bar", + }; + let mut test_cbor = vec![ + 0xa2, // map of 2 pairs + 0x61, b'k', // text string "k" + 0x61, b'v', 0x63, b'f', b'o', b'o', // text string "foo" + 0x63, b'b', b'a', b'r', + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_map_with_byte_string_keys() { + let value_map = cbor_map! { + b"k" => b"v", + b"foo" => b"bar", + }; + let mut test_cbor = vec![ + 0xa2, // map of 2 pairs + 0x41, b'k', // text string "k" + 0x41, b'v', 0x43, b'f', b'o', b'o', // text string "foo" + 0x43, b'b', b'a', b'r', + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_nested_map() { + let value_map = cbor_map! { + "a" => 1, + "b" => cbor_map! { + "c" => 2, + "d" => 3, + }, + }; + let mut test_cbor = vec![ + 0xa2, // map of 2 pairs + 0x61, 0x61, 0x01, // "a" + 0x61, 0x62, // "b" + 0xa2, // map of 2 pairs + 0x61, 0x63, 0x02, // "c" + 0x61, 0x64, 0x03, // "d" + ]; + assert_eq!(read(&test_cbor), Ok(value_map)); + test_cbor.push(0x01); + assert_eq!(read(&test_cbor), Err(DecoderError::ExtranousData)); + } + + #[test] + fn test_read_integer_out_of_range() { + let cases = vec![ + // The positive case is impossible since we support u64. + // vec![0x1B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + vec![0x3B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::OutOfRangeIntegerValue)); + } + } + + #[test] + fn test_read_simple_value() { + let cases = vec![ + (cbor_false!(), vec![0xF4]), + (cbor_true!(), vec![0xF5]), + (cbor_null!(), vec![0xF6]), + (cbor_undefined!(), vec![0xF7]), + ]; + for (simple, mut cbor) in cases { + assert_eq!(read(&cbor.clone()), Ok(simple)); + cbor.push(0x01); + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_unsupported_floating_point_numbers() { + let cases = vec![ + vec![0xF9, 0x10, 0x00], + vec![0xFA, 0x10, 0x00, 0x00, 0x00], + vec![0xFB, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], + ]; + for cbor in cases { + assert_eq!( + read(&cbor), + Err(DecoderError::UnsupportedFloatingPointValue) + ); + } + } + + #[test] + fn test_read_incomplete_cbor_data_error() { + let cases = vec![ + vec![0x19, 0x03], + vec![0x44, 0x01, 0x02, 0x03], + vec![0x65, 0x49, 0x45, 0x54, 0x46], + vec![0x82, 0x02], + vec![0xA2, 0x61, 0x61, 0x01], + vec![0x18], + vec![0x99], + vec![0xBA], + vec![0x5B], + vec![0x3B], + vec![0x99, 0x01], + vec![0xBA, 0x01, 0x02, 0x03], + vec![0x3B, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::IncompleteCborData)); + } + } + + #[test] + fn test_read_unsupported_map_key_format_error() { + // While CBOR can handle all types as map keys, we only support a subset. + let bad_map_cbor = vec![ + 0xa2, // map of 2 pairs + 0x82, 0x01, 0x02, // invalid key : [1, 2] + 0x02, // value : 2 + 0x61, 0x64, // key : "d" + 0x03, // value : 3 + ]; + assert_eq!(read(&bad_map_cbor), Err(DecoderError::IncorrectMapKeyType)); + } + + #[test] + fn test_read_unknown_additional_info_error() { + let cases = vec![ + vec![0x7C, 0x49, 0x45, 0x54, 0x46], + vec![0x7D, 0x22, 0x5C], + vec![0x7E, 0xC3, 0xBC], + vec![0x7F, 0xE6, 0xB0, 0xB4], + vec![0xFC], + vec![0xFD], + vec![0xFE], + vec![0xFF], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::UnknownAdditionalInfo)); + } + } + + #[test] + fn test_read_too_much_nesting_error() { + let cases = vec![ + vec![0x18, 0x64], + vec![0x44, 0x01, 0x02, 0x03, 0x04], + vec![0x64, 0x49, 0x45, 0x54, 0x46], + vec![0x80], + vec![0xA0], + ]; + for cbor in cases { + let mut reader = Reader::new(&cbor); + assert!(reader.decode_complete_data_item(0).is_ok()); + } + let map_cbor = vec![ + 0xa2, // map of 2 pairs + 0x61, 0x61, // "a" + 0x01, 0x61, 0x62, // "b" + 0x82, // array with 2 elements + 0x02, 0x03, + ]; + let mut reader = Reader::new(&map_cbor); + assert_eq!( + reader.decode_complete_data_item(1), + Err(DecoderError::TooMuchNesting) + ); + reader = Reader::new(&map_cbor); + assert!(reader.decode_complete_data_item(2).is_ok()); + } + + #[test] + fn test_read_out_of_order_key_error() { + let cases = vec![ + vec![ + 0xa2, // map with 2 keys with same major type and length + 0x61, 0x62, // key "b" + 0x61, 0x42, // value "B" + 0x61, 0x61, // key "a" (out of order byte-wise lexically) + 0x61, 0x45, // value "E" + ], + vec![ + 0xa2, // map with 2 keys with different major type + 0x61, 0x62, // key "b" + 0x02, // value 2 + // key 1000 (out of order since lower major type sorts first) + 0x19, 0x03, 0xe8, 0x61, 0x61, // value a + ], + vec![ + 0xa2, // map with 2 keys with same major type + 0x19, 0x03, 0xe8, // key 1000 (out of order due to longer length) + 0x61, 0x61, //value "a" + 0x0a, // key 10 + 0x61, 0x62, // value "b" + ], + vec![ + 0xa2, // map with 2 text string keys + 0x62, b'a', b'a', // key text string "aa" + // (out of order due to longer length) + 0x02, 0x61, b'b', // key "b" + 0x01, + ], + vec![ + 0xa2, // map with 2 byte string keys + 0x42, b'x', b'x', // key byte string "xx" + // (out of order due to longer length) + 0x02, 0x41, b'y', // key byte string "y" + 0x01, + ], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::OutOfOrderKey)); + } + } + + #[test] + fn test_read_duplicate_key_error() { + let map_with_duplicate_key = vec![ + 0xa6, // map of 6 pairs: + 0x60, // "" + 0x61, 0x2e, // "." + 0x61, 0x62, // "b" + 0x61, 0x42, // "B" + 0x61, 0x62, // "b" (Duplicate key) + 0x61, 0x43, // "C" + 0x61, 0x64, // "d" + 0x61, 0x44, // "D" + 0x61, 0x65, // "e" + 0x61, 0x44, // "D" + 0x62, 0x61, 0x61, // "aa" + 0x62, 0x41, 0x41, // "AA" + ]; + assert_eq!( + read(&map_with_duplicate_key), + Err(DecoderError::OutOfOrderKey) + ); + } + + #[test] + fn test_read_incorrect_string_encoding_error() { + let cases = vec![ + vec![0x63, 0xED, 0x9F, 0xBF], + vec![0x63, 0xEE, 0x80, 0x80], + vec![0x63, 0xEF, 0xBF, 0xBD], + ]; + for cbor in cases { + assert!(read(&cbor).is_ok()); + } + let impossible_utf_byte = vec![0x64, 0xFE, 0xFE, 0xFF, 0xFF]; + assert_eq!(read(&impossible_utf_byte), Err(DecoderError::InvalidUtf8)); + } + + #[test] + fn test_read_extranous_cbor_data_error() { + let cases = vec![ + vec![0x19, 0x03, 0x05, 0x00], + vec![0x44, 0x01, 0x02, 0x03, 0x04, 0x00], + vec![0x64, 0x49, 0x45, 0x54, 0x46, 0x00], + vec![0x82, 0x01, 0x02, 0x00], + vec![0xa1, 0x61, 0x63, 0x02, 0x61, 0x64, 0x03], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::ExtranousData)); + } + } + + #[test] + fn test_read_unsupported_simple_type() { + let cases = vec![ + vec![0xE0], + vec![0xF3], + vec![0xF8, 0x18], + vec![0xF8, 0x1C], + vec![0xF8, 0x1D], + vec![0xF8, 0x1E], + vec![0xF8, 0x1F], + vec![0xF8, 0x20], + vec![0xF8, 0xFF], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::UnsupportedSimpleValue)); + } + } + + #[test] + fn test_read_super_long_content_dont_crash() { + let cases = vec![ + vec![0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + vec![0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::IncompleteCborData)); + } + } + + #[test] + fn test_read_unsupported_major_type() { + let cases = vec![ + vec![0xC0], + vec![0xD8, 0xFF], + // multi-dimensional array example using tags + vec![ + 0x82, 0x82, 0x02, 0x03, 0xd8, 0x41, 0x4a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x05, + ], + ]; + for cbor in cases { + assert_eq!(read(&cbor), Err(DecoderError::UnsupportedMajorType)); + } + } +} diff --git a/libraries/cbor/src/values.rs b/libraries/cbor/src/values.rs new file mode 100644 index 0000000..d402730 --- /dev/null +++ b/libraries/cbor/src/values.rs @@ -0,0 +1,268 @@ +// Copyright 2019 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. + +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::cmp::Ordering; + +#[derive(Clone, Debug, PartialEq)] +pub enum Value { + KeyValue(KeyType), + Array(Vec), + Map(BTreeMap), + // TAG is omitted + Simple(SimpleValue), +} + +// The specification recommends to limit the available keys. +// Currently supported are both integer and string types. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum KeyType { + Unsigned(u64), + // We only use 63 bits of information here. + Negative(i64), + ByteString(Vec), + TextString(String), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum SimpleValue { + FalseValue = 20, + TrueValue = 21, + NullValue = 22, + Undefined = 23, +} + +pub struct Constants {} + +impl Constants { + pub const MAJOR_TYPE_BIT_SHIFT: u8 = 5; + pub const ADDITIONAL_INFORMATION_MASK: u8 = 0x1F; + pub const ADDITIONAL_INFORMATION_MAX_INT: u8 = 23; + pub const ADDITIONAL_INFORMATION_1_BYTE: u8 = 24; + pub const ADDITIONAL_INFORMATION_2_BYTES: u8 = 25; + pub const ADDITIONAL_INFORMATION_4_BYTES: u8 = 26; + pub const ADDITIONAL_INFORMATION_8_BYTES: u8 = 27; +} + +impl Value { + pub fn bool_value(b: bool) -> Value { + if b { + Value::Simple(SimpleValue::TrueValue) + } else { + Value::Simple(SimpleValue::FalseValue) + } + } + + pub fn type_label(&self) -> u8 { + match self { + Value::KeyValue(key) => key.type_label(), + Value::Array(_) => 4, + Value::Map(_) => 5, + Value::Simple(_) => 7, + } + } +} + +impl KeyType { + // For simplicity, this only takes i64. Construct directly for the last bit. + pub fn integer(int: i64) -> KeyType { + if int >= 0 { + KeyType::Unsigned(int as u64) + } else { + KeyType::Negative(int) + } + } + + pub fn type_label(&self) -> u8 { + match self { + KeyType::Unsigned(_) => 0, + KeyType::Negative(_) => 1, + KeyType::ByteString(_) => 2, + KeyType::TextString(_) => 3, + } + } +} + +impl Ord for KeyType { + fn cmp(&self, other: &KeyType) -> Ordering { + use super::values::KeyType::{ByteString, Negative, TextString, Unsigned}; + let self_type_value = self.type_label(); + let other_type_value = other.type_label(); + if self_type_value != other_type_value { + return self_type_value.cmp(&other_type_value); + } + match (self, other) { + (Unsigned(u1), Unsigned(u2)) => u1.cmp(u2), + (Negative(n1), Negative(n2)) => n1.cmp(n2).reverse(), + (ByteString(b1), ByteString(b2)) => b1.len().cmp(&b2.len()).then(b1.cmp(b2)), + (TextString(t1), TextString(t2)) => t1.len().cmp(&t2.len()).then(t1.cmp(t2)), + _ => unreachable!(), + } + } +} + +impl PartialOrd for KeyType { + fn partial_cmp(&self, other: &KeyType) -> Option { + Some(self.cmp(other)) + } +} + +impl SimpleValue { + pub fn from_integer(int: u64) -> Option { + match int { + 20 => Some(SimpleValue::FalseValue), + 21 => Some(SimpleValue::TrueValue), + 22 => Some(SimpleValue::NullValue), + 23 => Some(SimpleValue::Undefined), + _ => None, + } + } +} + +impl From for KeyType { + fn from(unsigned: u64) -> Self { + KeyType::Unsigned(unsigned) + } +} + +impl From for KeyType { + fn from(i: i64) -> Self { + KeyType::integer(i) + } +} + +impl From for KeyType { + fn from(i: i32) -> Self { + KeyType::integer(i as i64) + } +} + +impl From> for KeyType { + fn from(bytes: Vec) -> Self { + KeyType::ByteString(bytes) + } +} + +impl From<&[u8]> for KeyType { + fn from(bytes: &[u8]) -> Self { + KeyType::ByteString(bytes.to_vec()) + } +} + +impl From for KeyType { + fn from(text: String) -> Self { + KeyType::TextString(text) + } +} + +impl From<&str> for KeyType { + fn from(text: &str) -> Self { + KeyType::TextString(text.to_string()) + } +} + +impl From for Value +where + KeyType: From, +{ + fn from(t: T) -> Self { + Value::KeyValue(KeyType::from(t)) + } +} + +impl From for Value { + fn from(b: bool) -> Self { + Value::bool_value(b) + } +} + +pub trait IntoCborKey { + fn into_cbor_key(self) -> KeyType; +} + +impl IntoCborKey for T +where + KeyType: From, +{ + fn into_cbor_key(self) -> KeyType { + KeyType::from(self) + } +} + +pub trait IntoCborValue { + fn into_cbor_value(self) -> Value; +} + +impl IntoCborValue for T +where + Value: From, +{ + fn into_cbor_value(self) -> Value { + Value::from(self) + } +} + +pub trait IntoCborValueOption { + fn into_cbor_value_option(self) -> Option; +} + +impl IntoCborValueOption for T +where + Value: From, +{ + fn into_cbor_value_option(self) -> Option { + Some(Value::from(self)) + } +} + +impl IntoCborValueOption for Option +where + Value: From, +{ + fn into_cbor_value_option(self) -> Option { + self.map(Value::from) + } +} + +#[cfg(test)] +mod test { + #[test] + fn test_key_type_ordering() { + assert!(cbor_key_int!(0) < cbor_key_int!(23)); + assert!(cbor_key_int!(23) < cbor_key_int!(24)); + assert!(cbor_key_int!(24) < cbor_key_int!(1000)); + assert!(cbor_key_int!(1000) < cbor_key_int!(1000000)); + assert!(cbor_key_int!(1000000) < cbor_key_int!(std::i64::MAX)); + assert!(cbor_key_int!(std::i64::MAX) < cbor_key_int!(-1)); + assert!(cbor_key_int!(-1) < cbor_key_int!(-23)); + assert!(cbor_key_int!(-23) < cbor_key_int!(-24)); + assert!(cbor_key_int!(-24) < cbor_key_int!(-1000)); + assert!(cbor_key_int!(-1000) < cbor_key_int!(-1000000)); + assert!(cbor_key_int!(-1000000) < cbor_key_int!(std::i64::MIN)); + assert!(cbor_key_int!(std::i64::MIN) < cbor_key_bytes!(vec![])); + assert!(cbor_key_bytes!(vec![]) < cbor_key_bytes!(vec![0x00])); + assert!(cbor_key_bytes!(vec![0x00]) < cbor_key_bytes!(vec![0x01])); + assert!(cbor_key_bytes!(vec![0x01]) < cbor_key_bytes!(vec![0xFF])); + assert!(cbor_key_bytes!(vec![0xFF]) < cbor_key_bytes!(vec![0x00, 0x00])); + assert!(cbor_key_bytes!(vec![0x00, 0x00]) < cbor_key_text!("")); + assert!(cbor_key_text!("") < cbor_key_text!("a")); + assert!(cbor_key_text!("a") < cbor_key_text!("b")); + assert!(cbor_key_text!("b") < cbor_key_text!("aa")); + assert!(cbor_key_int!(1) < cbor_key_bytes!(vec![0x00])); + assert!(cbor_key_int!(1) < cbor_key_text!("s")); + assert!(cbor_key_int!(-1) < cbor_key_text!("s")); + } +} diff --git a/libraries/cbor/src/writer.rs b/libraries/cbor/src/writer.rs new file mode 100644 index 0000000..1273160 --- /dev/null +++ b/libraries/cbor/src/writer.rs @@ -0,0 +1,429 @@ +// Copyright 2019 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. + +use super::values::{Constants, KeyType, Value}; +use alloc::vec::Vec; + +pub fn write(value: Value, encoded_cbor: &mut Vec) -> bool { + let mut writer = Writer::new(encoded_cbor); + writer.encode_cbor(value, Writer::MAX_NESTING_DEPTH) +} + +struct Writer<'a> { + encoded_cbor: &'a mut Vec, +} + +impl<'a> Writer<'a> { + const MAX_NESTING_DEPTH: i8 = 4; + + pub fn new(encoded_cbor: &mut Vec) -> Writer { + Writer { encoded_cbor } + } + + fn encode_cbor(&mut self, value: Value, remaining_depth: i8) -> bool { + if remaining_depth < 0 { + return false; + } + match value { + Value::KeyValue(KeyType::Unsigned(unsigned)) => self.start_item(0, unsigned as u64), + Value::KeyValue(KeyType::Negative(negative)) => { + self.start_item(1, -(negative + 1) as u64) + } + Value::KeyValue(KeyType::ByteString(byte_string)) => { + self.start_item(2, byte_string.len() as u64); + self.encoded_cbor.extend(byte_string); + } + Value::KeyValue(KeyType::TextString(text_string)) => { + self.start_item(3, text_string.len() as u64); + self.encoded_cbor.extend(text_string.into_bytes()); + } + Value::Array(array) => { + self.start_item(4, array.len() as u64); + for el in array { + if !self.encode_cbor(el, remaining_depth - 1) { + return false; + } + } + } + Value::Map(map) => { + self.start_item(5, map.len() as u64); + for (k, v) in map { + if !self.encode_cbor(Value::KeyValue(k), remaining_depth - 1) { + return false; + } + if !self.encode_cbor(v, remaining_depth - 1) { + return false; + } + } + } + Value::Simple(simple_value) => self.start_item(7, simple_value as u64), + } + true + } + + fn start_item(&mut self, type_label: u8, size: u64) { + let (mut first_byte, shift) = match size { + 0..=23 => (size as u8, 0), + 24..=0xFF => (Constants::ADDITIONAL_INFORMATION_1_BYTE, 1), + 0x100..=0xFFFF => (Constants::ADDITIONAL_INFORMATION_2_BYTES, 2), + 0x10000..=0xFFFF_FFFF => (Constants::ADDITIONAL_INFORMATION_4_BYTES, 4), + _ => (Constants::ADDITIONAL_INFORMATION_8_BYTES, 8), + }; + first_byte |= type_label << Constants::MAJOR_TYPE_BIT_SHIFT; + self.encoded_cbor.push(first_byte); + + for i in (0..shift).rev() { + self.encoded_cbor.push((size >> (i * 8)) as u8); + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + fn write_return(value: Value) -> Option> { + let mut encoded_cbor = Vec::new(); + if write(value, &mut encoded_cbor) { + Some(encoded_cbor) + } else { + None + } + } + + #[test] + fn test_write_unsigned() { + let cases = vec![ + (0, vec![0x00]), + (1, vec![0x01]), + (10, vec![0x0A]), + (23, vec![0x17]), + (24, vec![0x18, 0x18]), + (25, vec![0x18, 0x19]), + (100, vec![0x18, 0x64]), + (1000, vec![0x19, 0x03, 0xE8]), + (1000000, vec![0x1A, 0x00, 0x0F, 0x42, 0x40]), + (0xFFFFFFFF, vec![0x1A, 0xFF, 0xFF, 0xFF, 0xFF]), + ( + 0x100000000, + vec![0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00], + ), + ( + std::i64::MAX, + vec![0x1B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + ), + ]; + for (unsigned, correct_cbor) in cases { + assert_eq!(write_return(cbor_int!(unsigned)), Some(correct_cbor)); + } + } + + #[test] + fn test_write_negative() { + let cases = vec![ + (-1, vec![0x20]), + (-10, vec![0x29]), + (-23, vec![0x36]), + (-24, vec![0x37]), + (-25, vec![0x38, 0x18]), + (-100, vec![0x38, 0x63]), + (-1000, vec![0x39, 0x03, 0xE7]), + (-4294967296, vec![0x3A, 0xFF, 0xFF, 0xFF, 0xFF]), + ( + -4294967297, + vec![0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00], + ), + ( + std::i64::MIN, + vec![0x3B, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], + ), + ]; + for (negative, correct_cbor) in cases { + assert_eq!(write_return(cbor_int!(negative)), Some(correct_cbor)); + } + } + + #[test] + fn test_write_byte_string() { + let cases = vec![ + (vec![], vec![0x40]), + ( + vec![0x01, 0x02, 0x03, 0x04], + vec![0x44, 0x01, 0x02, 0x03, 0x04], + ), + ]; + for (byte_string, correct_cbor) in cases { + assert_eq!(write_return(cbor_bytes!(byte_string)), Some(correct_cbor)); + } + } + + #[test] + fn test_write_text_string() { + let unicode_3byte = vec![0xE6, 0xB0, 0xB4]; + let cases = vec![ + ("", vec![0x60]), + ("a", vec![0x61, 0x61]), + ("IETF", vec![0x64, 0x49, 0x45, 0x54, 0x46]), + ("\"\\", vec![0x62, 0x22, 0x5C]), + ("ü", vec![0x62, 0xC3, 0xBC]), + ( + std::str::from_utf8(&unicode_3byte).unwrap(), + vec![0x63, 0xE6, 0xB0, 0xB4], + ), + ("𐅑", vec![0x64, 0xF0, 0x90, 0x85, 0x91]), + ]; + for (text_string, correct_cbor) in cases { + assert_eq!(write_return(cbor_text!(text_string)), Some(correct_cbor)); + } + } + + #[test] + fn test_write_array() { + let value_vec: Vec<_> = (1..26).collect(); + let expected_cbor = vec![ + 0x98, 0x19, // array of 25 elements + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x18, 0x18, 0x19, + ]; + assert_eq!( + write_return(cbor_array_vec!(value_vec)), + Some(expected_cbor) + ); + } + + #[test] + fn test_write_map() { + let value_map = cbor_map! { + "aa" => "AA", + "e" => "E", + "" => ".", + -1 => "k", + -24 => "l", + -25 => "m", + -256 => "n", + -257 => "o", + -65537 => "p", + -4294967296_i64 => "q", + -4294967297_i64 => "r", + std::i64::MIN => "s", + b"a" => 2, + b"bar" => 3, + b"foo" => 4, + 0 => "a", + 23 => "b", + 24 => "c", + std::u8::MAX as i64 => "d", + 256 => "e", + std::u16::MAX as i64 => "f", + 65536 => "g", + std::u32::MAX as i64 => "h", + 4294967296_i64 => "i", + std::i64::MAX => "j", + }; + let expected_cbor = vec![ + 0xb8, 0x19, // map of 25 pairs: + 0x00, // key 0 + 0x61, 0x61, // value "a" + 0x17, // key 23 + 0x61, 0x62, // value "b" + 0x18, 0x18, // key 24 + 0x61, 0x63, // value "c" + 0x18, 0xFF, // key 255 + 0x61, 0x64, // value "d" + 0x19, 0x01, 0x00, // key 256 + 0x61, 0x65, // value "e" + 0x19, 0xFF, 0xFF, // key 65535 + 0x61, 0x66, // value "f" + 0x1A, 0x00, 0x01, 0x00, 0x00, // key 65536 + 0x61, 0x67, // value "g" + 0x1A, 0xFF, 0xFF, 0xFF, 0xFF, // key 4294967295 + 0x61, 0x68, // value "h" + // key 4294967296 + 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x69, // value "i" + // key INT64_MAX + 0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x6a, // value "j" + 0x20, // key -1 + 0x61, 0x6b, // value "k" + 0x37, // key -24 + 0x61, 0x6c, // value "l" + 0x38, 0x18, // key -25 + 0x61, 0x6d, // value "m" + 0x38, 0xFF, // key -256 + 0x61, 0x6e, // value "n" + 0x39, 0x01, 0x00, // key -257 + 0x61, 0x6f, // value "o" + 0x3A, 0x00, 0x01, 0x00, 0x00, // key -65537 + 0x61, 0x70, // value "p" + 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, // key -4294967296 + 0x61, 0x71, // value "q" + // key -4294967297 + 0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x61, 0x72, // value "r" + // key INT64_MIN + 0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x61, 0x73, // value "s" + 0x41, b'a', // byte string "a" + 0x02, 0x43, b'b', b'a', b'r', // byte string "bar" + 0x03, 0x43, b'f', b'o', b'o', // byte string "foo" + 0x04, 0x60, // key "" + 0x61, 0x2e, // value "." + 0x61, 0x65, // key "e" + 0x61, 0x45, // value "E" + 0x62, 0x61, 0x61, // key "aa" + 0x62, 0x41, 0x41, // value "AA" + ]; + assert_eq!(write_return(value_map), Some(expected_cbor)); + } + + #[test] + fn test_write_map_with_array() { + let value_map = cbor_map! { + "a" => 1, + "b" => cbor_array![2, 3], + }; + let expected_cbor = vec![ + 0xa2, // map of 2 pairs + 0x61, 0x61, // "a" + 0x01, 0x61, 0x62, // "b" + 0x82, // array with 2 elements + 0x02, 0x03, + ]; + assert_eq!(write_return(value_map), Some(expected_cbor)); + } + + #[test] + fn test_write_nested_map() { + let value_map = cbor_map! { + "a" => 1, + "b" => cbor_map! { + "c" => 2, + "d" => 3, + }, + }; + let expected_cbor = vec![ + 0xa2, // map of 2 pairs + 0x61, 0x61, // "a" + 0x01, 0x61, 0x62, // "b" + 0xa2, // map of 2 pairs + 0x61, 0x63, // "c" + 0x02, 0x61, 0x64, // "d" + 0x03, + ]; + assert_eq!(write_return(value_map), Some(expected_cbor)); + } + + #[test] + fn test_write_simple() { + let cases = vec![ + (cbor_false!(), vec![0xF4]), + (cbor_true!(), vec![0xF5]), + (cbor_null!(), vec![0xF6]), + (cbor_undefined!(), vec![0xF7]), + ]; + for (value, correct_cbor) in cases { + assert_eq!(write_return(value), Some(correct_cbor)); + } + } + + #[test] + fn test_write_single_levels() { + let simple_array: Value = cbor_array![2]; + let simple_map: Value = cbor_map! {"b" => 3}; + let positive_cases = vec![ + (cbor_int!(1), 0), + (cbor_bytes!(vec![0x01, 0x02, 0x03, 0x04]), 0), + (cbor_text!("a"), 0), + (cbor_array![], 0), + (cbor_map! {}, 0), + (simple_array.clone(), 1), + (simple_map.clone(), 1), + ]; + let negative_cases = vec![(simple_array.clone(), 0), (simple_map.clone(), 0)]; + for (value, level) in positive_cases { + let mut buf = Vec::new(); + let mut writer = Writer::new(&mut buf); + assert!(writer.encode_cbor(value, level)); + } + for (value, level) in negative_cases { + let mut buf = Vec::new(); + let mut writer = Writer::new(&mut buf); + assert!(!writer.encode_cbor(value, level)); + } + } + + #[test] + fn test_write_nested_map_levels() { + let cbor_map: Value = cbor_map! { + "a" => 1, + "b" => cbor_map! { + "c" => 2, + "d" => 3, + }, + }; + + let mut buf = Vec::new(); + let mut writer = Writer::new(&mut buf); + assert!(writer.encode_cbor(cbor_map.clone(), 2)); + writer = Writer::new(&mut buf); + assert!(!writer.encode_cbor(cbor_map, 1)); + } + + #[test] + fn test_write_unbalanced_nested_containers() { + let cbor_array: Value = cbor_array![ + 1, + 2, + 3, + cbor_map! { + "a" => 1, + "b" => cbor_map! { + "c" => 2, + "d" => 3, + }, + }, + ]; + + let mut buf = Vec::new(); + let mut writer = Writer::new(&mut buf); + assert!(writer.encode_cbor(cbor_array.clone(), 3)); + writer = Writer::new(&mut buf); + assert!(!writer.encode_cbor(cbor_array, 2)); + } + + #[test] + fn test_write_overly_nested() { + let cbor_map: Value = cbor_map! { + "a" => 1, + "b" => cbor_map! { + "c" => 2, + "d" => 3, + "h" => cbor_map! { + "e" => 4, + "f" => 5, + "g" => cbor_array![ + 6, + 7, + cbor_array![ + 8 + ] + ], + }, + }, + }; + + let mut buf = Vec::new(); + let mut writer = Writer::new(&mut buf); + assert!(writer.encode_cbor(cbor_map.clone(), 5)); + writer = Writer::new(&mut buf); + assert!(!writer.encode_cbor(cbor_map, 4)); + } +} diff --git a/libraries/crypto/Cargo.toml b/libraries/crypto/Cargo.toml new file mode 100644 index 0000000..d18c5ad --- /dev/null +++ b/libraries/crypto/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "crypto" +version = "0.1.0" +authors = [ + "Fabian Kaczmarczyck ", + "Guillaume Endignoux ", + "Jean-Michel Picod ", +] +license = "Apache-2.0" +edition = "2018" + +[dependencies] +libtock = { path = "../../third_party/libtock-rs" } +cbor = { path = "../cbor" } +arrayref = "0.3.5" +subtle = { version = "2.2", default-features = false, features = ["nightly"] } +byteorder = { version = "1", default-features = false } +hex = { version = "0.3.2", default-features = false, optional = true } +ring = { version = "0.14.6", optional = true } +untrusted = { version = "0.6.2", optional = true } +rand = { version = "0.6.5", optional = true } +serde = { version = "1.0", optional = true, features = ["derive"] } +serde_json = { version = "1.0", optional = true } +regex = { version = "1", optional = true } + +[features] +std = ["cbor/std", "hex", "rand", "ring", "untrusted", "serde", "serde_json", "regex"] +derive_debug = [] +with_ctap1 = [] diff --git a/libraries/crypto/src/aes256.rs b/libraries/crypto/src/aes256.rs new file mode 100644 index 0000000..cdd5905 --- /dev/null +++ b/libraries/crypto/src/aes256.rs @@ -0,0 +1,541 @@ +// Copyright 2019 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. + +use super::util::{xor_block_16, Block16}; +use super::{Decrypt16BytesBlock, Encrypt16BytesBlock}; + +/** A portable and naive textbook implementation of AES-256 **/ +type Word = [u8; 4]; + +/** This structure caches the round keys, to avoid re-computing the key schedule for each block. **/ +pub struct EncryptionKey { + enc_round_keys: [Block16; 15], +} + +pub struct DecryptionKey { + dec_round_keys: [Block16; 15], +} + +impl EncryptionKey { + // Computes the round keys. + pub fn new(key: &[u8; 32]) -> EncryptionKey { + let mut enc_round_keys = [Default::default(); 15]; + + enc_round_keys[0] = *array_ref![key, 0, 16]; + enc_round_keys[1] = *array_ref![key, 16, 16]; + + let mut word: Word = *array_ref![enc_round_keys[1], 12, 4]; + for i in 2..15 { + if i & 1 == 0 { + rotword(&mut word); + subword(&mut word); + word[0] ^= RCON[(i >> 1) - 1]; + } else { + subword(&mut word); + } + + for j in 0..4 { + xorword(&mut word, *array_ref![enc_round_keys[i - 2], 4 * j, 4]); + *array_mut_ref![enc_round_keys[i], 4 * j, 4] = word; + } + } + + EncryptionKey { enc_round_keys } + } +} + +impl Encrypt16BytesBlock for EncryptionKey { + // Encrypt an AES block in place. + fn encrypt_block(&self, block: &mut Block16) { + add_round_key(block, &self.enc_round_keys[0]); + for i in 1..14 { + aes_enc(block, &self.enc_round_keys[i]); + } + aes_enc_last(block, &self.enc_round_keys[14]); + } +} + +impl DecryptionKey { + // Computes the round keys. + pub fn new(key: &EncryptionKey) -> DecryptionKey { + let mut dec_round_keys = [Default::default(); 15]; + dec_round_keys[0] = key.enc_round_keys[14]; + #[allow(clippy::needless_range_loop)] + for i in 1..14 { + let rk = &mut dec_round_keys[i]; + *rk = key.enc_round_keys[14 - i]; + inv_mix_columns(rk); + } + dec_round_keys[14] = key.enc_round_keys[0]; + + DecryptionKey { dec_round_keys } + } +} + +impl Decrypt16BytesBlock for DecryptionKey { + // Decrypt an AES block in place. + fn decrypt_block(&self, block: &mut Block16) { + add_round_key(block, &self.dec_round_keys[0]); + for i in 1..14 { + aes_dec(block, &self.dec_round_keys[i]); + } + aes_dec_last(block, &self.dec_round_keys[14]); + } +} + +/** Helper functions for the key schedule **/ +fn rotword(word: &mut Word) { + let tmp = word[0]; + word[0] = word[1]; + word[1] = word[2]; + word[2] = word[3]; + word[3] = tmp; +} + +fn subword(word: &mut Word) { + for byte in word.iter_mut() { + *byte = SBOX[*byte as usize]; + } +} + +fn xorword(word: &mut Word, src: Word) { + for i in 0..4 { + word[i] ^= src[i]; + } +} + +/** Helper functions for the encryption **/ +fn aes_enc(block: &mut Block16, rkey: &Block16) { + sub_bytes(block); + shift_rows(block); + mix_columns(block); + add_round_key(block, rkey); +} + +fn aes_dec(block: &mut Block16, rkey: &Block16) { + inv_shift_rows(block); + inv_sub_bytes(block); + inv_mix_columns(block); + add_round_key(block, rkey); +} + +fn aes_enc_last(block: &mut Block16, rkey: &Block16) { + sub_bytes(block); + shift_rows(block); + add_round_key(block, rkey); +} + +fn aes_dec_last(block: &mut Block16, rkey: &Block16) { + inv_shift_rows(block); + inv_sub_bytes(block); + add_round_key(block, rkey); +} + +#[inline(always)] +fn add_round_key(block: &mut Block16, rkey: &Block16) { + xor_block_16(block, rkey); +} + +fn sub_bytes(block: &mut Block16) { + for byte in block.iter_mut() { + *byte = SBOX[*byte as usize]; + } +} + +fn inv_sub_bytes(block: &mut Block16) { + for byte in block.iter_mut() { + *byte = SBOX_INV[*byte as usize]; + } +} + +fn shift_rows(block: &mut Block16) { + let tmp = block[1]; + block[1] = block[5]; + block[5] = block[9]; + block[9] = block[13]; + block[13] = tmp; + + block.swap(2, 10); + block.swap(6, 14); + + let tmp = block[3]; + block[3] = block[15]; + block[15] = block[11]; + block[11] = block[7]; + block[7] = tmp; +} + +fn inv_shift_rows(block: &mut Block16) { + let tmp = block[7]; + block[7] = block[11]; + block[11] = block[15]; + block[15] = block[3]; + block[3] = tmp; + + block.swap(2, 10); + block.swap(6, 14); + + let tmp = block[13]; + block[13] = block[9]; + block[9] = block[5]; + block[5] = block[1]; + block[1] = tmp; +} + +// multiplication by 2 in GF(2^256) +fn mul2(x: u8) -> u8 { + (x << 1) ^ (((x >> 7) & 1) * 0x1b) +} + +// multiplication by 3 in GF(2^256) +fn mul3(x: u8) -> u8 { + mul2(x) ^ x +} + +fn mix_columns(block: &mut Block16) { + for i in 0..4 { + let x0 = block[4 * i]; + let x1 = block[4 * i + 1]; + let x2 = block[4 * i + 2]; + let x3 = block[4 * i + 3]; + block[4 * i] = mul2(x0) ^ mul3(x1) ^ x2 ^ x3; + block[4 * i + 1] = x0 ^ mul2(x1) ^ mul3(x2) ^ x3; + block[4 * i + 2] = x0 ^ x1 ^ mul2(x2) ^ mul3(x3); + block[4 * i + 3] = mul3(x0) ^ x1 ^ x2 ^ mul2(x3); + } +} + +// multiplication by 9 in GF(2^256) +fn mul9(x: u8) -> u8 { + mul2(mul2(mul2(x))) ^ x +} + +// multiplication by 11 in GF(2^256) +fn mul11(x: u8) -> u8 { + mul2(mul2(mul2(x)) ^ x) ^ x +} + +// multiplication by 13 in GF(2^256) +fn mul13(x: u8) -> u8 { + mul2(mul2(mul2(x) ^ x)) ^ x +} + +// multiplication by 14 in GF(2^256) +fn mul14(x: u8) -> u8 { + mul2(mul2(mul2(x) ^ x) ^ x) +} + +fn inv_mix_columns(block: &mut Block16) { + for i in 0..4 { + let x0 = block[4 * i]; + let x1 = block[4 * i + 1]; + let x2 = block[4 * i + 2]; + let x3 = block[4 * i + 3]; + block[4 * i] = mul14(x0) ^ mul11(x1) ^ mul13(x2) ^ mul9(x3); + block[4 * i + 1] = mul9(x0) ^ mul14(x1) ^ mul11(x2) ^ mul13(x3); + block[4 * i + 2] = mul13(x0) ^ mul9(x1) ^ mul14(x2) ^ mul11(x3); + block[4 * i + 3] = mul11(x0) ^ mul13(x1) ^ mul9(x2) ^ mul14(x3); + } +} + +/** Constants **/ +// Constants used in the key schedule. +const RCON: [u8; 7] = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40]; + +// AES substitution box. +const SBOX: [u8; 256] = [ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, +]; + +const SBOX_INV: [u8; 256] = [ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, +]; + +#[cfg(test)] +mod test { + use super::*; + + // Test vector from the NIST obtained at: + // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_ECB.pdf + #[test] + fn test_nist_aes256_ecb_encrypt() { + let src = b"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\ + \xe9\x3d\x7e\x11\x73\x93\x17\x2a"; + let key = b"\x60\x3d\xeb\x10\x15\xca\x71\xbe\ + \x2b\x73\xae\xf0\x85\x7d\x77\x81\ + \x1f\x35\x2c\x07\x3b\x61\x08\xd7\ + \x2d\x98\x10\xa3\x09\x14\xdf\xf4"; + let expected = b"\xf3\xee\xd1\xbd\xb5\xd2\xa0\x3c\ + \x06\x4b\x5a\x7e\x3d\xb1\x81\xf8"; + + let mut dst: Block16 = Default::default(); + dst.copy_from_slice(src); + EncryptionKey::new(key).encrypt_block(&mut dst); + assert_eq!(&dst, expected); + } + + #[test] + fn test_nist_aes256_ecb_decrypt() { + let src = b"\xf3\xee\xd1\xbd\xb5\xd2\xa0\x3c\ + \x06\x4b\x5a\x7e\x3d\xb1\x81\xf8"; + let key = b"\x60\x3d\xeb\x10\x15\xca\x71\xbe\ + \x2b\x73\xae\xf0\x85\x7d\x77\x81\ + \x1f\x35\x2c\x07\x3b\x61\x08\xd7\ + \x2d\x98\x10\xa3\x09\x14\xdf\xf4"; + let expected = b"\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\ + \xe9\x3d\x7e\x11\x73\x93\x17\x2a"; + + let mut dst: Block16 = Default::default(); + dst.copy_from_slice(src); + DecryptionKey::new(&EncryptionKey::new(key)).decrypt_block(&mut dst); + assert_eq!(&dst, expected); + } + + #[test] + fn test_encrypt_decrypt() { + // Test that decrypt_block is the inverse of encrypt_block for a bunch of block values. + let key_bytes = b"\x60\x3d\xeb\x10\x15\xca\x71\xbe\ + \x2b\x73\xae\xf0\x85\x7d\x77\x81\ + \x1f\x35\x2c\x07\x3b\x61\x08\xd7\ + \x2d\x98\x10\xa3\x09\x14\xdf\xf4"; + let enc_key = EncryptionKey::new(key_bytes); + let dec_key = DecryptionKey::new(&enc_key); + let mut block: Block16 = [0; 16]; + for i in 0..=255 { + for j in 0..16 { + block[j] = (i + j) as u8; + } + let expected = block; + enc_key.encrypt_block(&mut block); + dec_key.decrypt_block(&mut block); + assert_eq!(block, expected); + } + } + + #[test] + fn test_sbox_is_permutation() { + let mut image = [false; 256]; + for &sboxed in SBOX.iter() { + assert_eq!(image[sboxed as usize], false); + image[sboxed as usize] = true; + } + } + + #[test] + fn test_sbox_inv_is_permutation() { + let mut image = [false; 256]; + for &sboxed in SBOX_INV.iter() { + assert_eq!(image[sboxed as usize], false); + image[sboxed as usize] = true; + } + } + + #[test] + fn test_sbox_inverse() { + for i in 0..=255 { + assert_eq!(SBOX_INV[SBOX[i as usize] as usize], i); + } + } + + #[test] + fn test_subbytes() { + let mut block = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [ + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, + ]; + sub_bytes(&mut block); + assert_eq!(block, expected); + } + + #[test] + fn test_subbytes_inv() { + // Test that inv_sub_bytes is the inverse of sub_bytes for a bunch of block values. + let mut block: Block16 = [0; 16]; + for i in 0..=255 { + for j in 0..16 { + block[j] = (i + j) as u8; + } + let expected = block; + sub_bytes(&mut block); + inv_sub_bytes(&mut block); + assert_eq!(block, expected); + } + } + + #[test] + fn test_shift_rows() { + let mut block = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let expected = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11]; + shift_rows(&mut block); + assert_eq!(block, expected); + } + + #[test] + fn test_shift_rows_inv() { + // Test that inv_shift_rows is the inverse of shift_rows for a bunch of block values. + let mut block: Block16 = [0; 16]; + for i in 0..=255 { + for j in 0..16 { + block[j] = (i + j) as u8; + } + let expected = block; + shift_rows(&mut block); + inv_shift_rows(&mut block); + assert_eq!(block, expected); + } + } + + #[test] + fn test_mix_columns_inv() { + // Test that inv_mix_columns is the inverse of mix_columns for a bunch of block values. + let mut block: Block16 = [0; 16]; + for i in 0..=255 { + for j in 0..16 { + block[j] = (i + j) as u8; + } + let expected = block; + mix_columns(&mut block); + inv_mix_columns(&mut block); + assert_eq!(block, expected); + } + } + + /** Comparison with AES-NI instructions for CPUs that support them **/ + #[cfg(all(target_arch = "x86_64", target_feature = "aes"))] + mod aesni { + use super::super::*; + + fn aes_enc_ni(block: &mut Block16, rkey: &Block16) { + use core::arch::x86_64::{__m128i, _mm_aesenc_si128}; + + unsafe { + let block_mm: __m128i = core::mem::transmute(*block); + let rkey_mm: __m128i = core::mem::transmute(*rkey); + let encrypted_mm: __m128i = _mm_aesenc_si128(block_mm, rkey_mm); + *block = core::mem::transmute(encrypted_mm) + } + } + + fn aes_enc_last_ni(block: &mut Block16, rkey: &Block16) { + use core::arch::x86_64::{__m128i, _mm_aesenclast_si128}; + + unsafe { + let block_mm: __m128i = core::mem::transmute(*block); + let rkey_mm: __m128i = core::mem::transmute(*rkey); + let encrypted_mm: __m128i = _mm_aesenclast_si128(block_mm, rkey_mm); + *block = core::mem::transmute(encrypted_mm) + } + } + + fn aes_dec_ni(block: &mut Block16, rkey: &Block16) { + use core::arch::x86_64::{__m128i, _mm_aesdec_si128}; + + unsafe { + let block_mm: __m128i = core::mem::transmute(*block); + let rkey_mm: __m128i = core::mem::transmute(*rkey); + let decrypted_mm: __m128i = _mm_aesdec_si128(block_mm, rkey_mm); + *block = core::mem::transmute(decrypted_mm) + } + } + + fn aes_dec_last_ni(block: &mut Block16, rkey: &Block16) { + use core::arch::x86_64::{__m128i, _mm_aesdeclast_si128}; + + unsafe { + let block_mm: __m128i = core::mem::transmute(*block); + let rkey_mm: __m128i = core::mem::transmute(*rkey); + let decrypted_mm: __m128i = _mm_aesdeclast_si128(block_mm, rkey_mm); + *block = core::mem::transmute(decrypted_mm) + } + } + + #[test] + fn test_aes_enc_ni() { + let mut block = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let mut block_ni = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let rkey = [ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ]; + aes_enc(&mut block, &rkey); + aes_enc_ni(&mut block_ni, &rkey); + assert_eq!(block, block_ni); + } + + #[test] + fn test_aes_enc_last_ni() { + let mut block = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let mut block_ni = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let rkey = [ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ]; + aes_enc_last(&mut block, &rkey); + aes_enc_last_ni(&mut block_ni, &rkey); + assert_eq!(block, block_ni); + } + + #[test] + fn test_aes_dec_ni() { + let mut block = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let mut block_ni = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let rkey = [ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ]; + aes_dec(&mut block, &rkey); + aes_dec_ni(&mut block_ni, &rkey); + assert_eq!(block, block_ni); + } + + #[test] + fn test_aes_dec_last_ni() { + let mut block = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let mut block_ni = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + let rkey = [ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + ]; + aes_dec_last(&mut block, &rkey); + aes_dec_last_ni(&mut block_ni, &rkey); + assert_eq!(block, block_ni); + } + } +} diff --git a/libraries/crypto/src/cbc.rs b/libraries/crypto/src/cbc.rs new file mode 100644 index 0000000..fd7dcc2 --- /dev/null +++ b/libraries/crypto/src/cbc.rs @@ -0,0 +1,258 @@ +// Copyright 2019 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. + +use super::util::{xor_block_16, Block16}; +use super::{Decrypt16BytesBlock, Encrypt16BytesBlock}; + +pub fn cbc_encrypt(key: &K, mut iv: Block16, blocks: &mut [Block16]) +where + K: Encrypt16BytesBlock, +{ + for block in blocks { + xor_block_16(block, &iv); + key.encrypt_block(block); + iv = *block; + } +} + +pub fn cbc_decrypt(key: &K, mut iv: Block16, blocks: &mut [Block16]) +where + K: Decrypt16BytesBlock, +{ + for block in blocks { + let tmp = *block; + key.decrypt_block(block); + xor_block_16(block, &iv); + iv = tmp; + } +} + +#[cfg(test)] +mod test { + use super::super::aes256; + use super::*; + + #[test] + fn test_cbc_encrypt_decrypt() { + // Test that cbc_decrypt is the inverse of cbc_encrypt for a bunch of block values. + let enc_key = aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ]); + let dec_key = aes256::DecryptionKey::new(&enc_key); + + for len in 0..16 { + let mut blocks: Vec = vec![Default::default(); len]; + for i in 0..len { + for j in 0..16 { + blocks[i][j] = ((len + i) * 16 + j) as u8; + } + } + let iv = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + let expected = blocks.clone(); + + cbc_encrypt(&enc_key, iv, &mut blocks); + cbc_decrypt(&dec_key, iv, &mut blocks); + assert_eq!(blocks, expected); + } + } + + #[test] + fn test_cbc_encrypt_1block_zero_iv() { + let key = aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ]); + + let mut blocks = [[ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]]; + let iv = [0; 16]; + cbc_encrypt(&key, iv, &mut blocks); + + let mut expected = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + key.encrypt_block(&mut expected); + + assert_eq!(blocks, [expected]); + } + + #[test] + fn test_cbc_decrypt_1block_zero_iv() { + let key = aes256::DecryptionKey::new(&aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ])); + + let mut blocks = [[ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]]; + let iv = [0; 16]; + cbc_decrypt(&key, iv, &mut blocks); + + let mut expected = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + key.decrypt_block(&mut expected); + + assert_eq!(blocks, [expected]); + } + + #[test] + fn test_cbc_encrypt_1block() { + let key = aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ]); + + let mut blocks = [[ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]]; + let iv = [ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, + ]; + cbc_encrypt(&key, iv, &mut blocks); + + let mut expected = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + xor_block_16(&mut expected, &iv); + key.encrypt_block(&mut expected); + + assert_eq!(blocks, [expected]); + } + + #[test] + fn test_cbc_decrypt_1block() { + let key = aes256::DecryptionKey::new(&aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ])); + + let mut blocks = [[ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]]; + let iv = [ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, + ]; + cbc_decrypt(&key, iv, &mut blocks); + + let mut expected = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + key.decrypt_block(&mut expected); + xor_block_16(&mut expected, &iv); + + assert_eq!(blocks, [expected]); + } + + #[test] + fn test_cbc_encrypt_2blocks() { + let key = aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ]); + + let mut blocks = [ + [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ], + [ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, + ], + ]; + let iv = [ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, + ]; + cbc_encrypt(&key, iv, &mut blocks); + + let mut expected0 = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + let mut expected1 = [ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, + ]; + xor_block_16(&mut expected0, &iv); + key.encrypt_block(&mut expected0); + xor_block_16(&mut expected1, &expected0); + key.encrypt_block(&mut expected1); + + assert_eq!(blocks, [expected0, expected1]); + } + + #[test] + fn test_cbc_decrypt_2blocks() { + let key = aes256::DecryptionKey::new(&aes256::EncryptionKey::new(&[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, + ])); + + let mut blocks = [ + [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ], + [ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, + ], + ]; + let iv = [ + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f, + ]; + cbc_decrypt(&key, iv, &mut blocks); + + let mut expected0 = [ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2e, 0x2f, + ]; + let mut expected1 = [ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, + 0x4e, 0x4f, + ]; + key.decrypt_block(&mut expected1); + xor_block_16(&mut expected1, &expected0); + key.decrypt_block(&mut expected0); + xor_block_16(&mut expected0, &iv); + + assert_eq!(blocks, [expected0, expected1]); + } +} diff --git a/libraries/crypto/src/ec/exponent256.rs b/libraries/crypto/src/ec/exponent256.rs new file mode 100644 index 0000000..8638eaa --- /dev/null +++ b/libraries/crypto/src/ec/exponent256.rs @@ -0,0 +1,346 @@ +// Copyright 2019 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. + +use super::super::rng256::Rng256; +use super::int256::{Digit, Int256}; +use core::ops::Mul; +use subtle::{self, Choice, ConditionallySelectable, CtOption}; + +// An exponent on the elliptic curve, that is an element modulo the curve order N. +#[derive(Clone, Copy, PartialEq, Eq)] +// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is +// resolved. +#[derive(Default)] +#[cfg_attr(feature = "derive_debug", derive(Debug))] +pub struct ExponentP256 { + int: Int256, +} + +impl ConditionallySelectable for ExponentP256 { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Self { + int: Int256::conditional_select(&a.int, &b.int, choice), + } + } +} + +impl ExponentP256 { + /** Constructors **/ + pub fn from_int_checked(int: Int256) -> CtOption { + CtOption::new(ExponentP256 { int }, int.ct_lt(&Int256::N)) + } + + #[cfg(test)] + // Normally the ExponentP256 type guarantees that its values stay in [0, N[ because N is the + // curve order and therefore exponents >= N are equivalent to their reduction modulo N. + // This unsafe function is only used in tests to check that N is indeed the curve order. + pub unsafe fn from_int_unchecked(int: Int256) -> ExponentP256 { + ExponentP256 { int } + } + + pub fn modn(int: Int256) -> ExponentP256 { + ExponentP256 { + int: int.modd(&Int256::N), + } + } + + /** Helpful getters **/ + pub fn bit(&self, i: usize) -> Digit { + self.int.bit(i) + } + + pub fn to_int(self) -> Int256 { + self.int + } + + pub fn is_zero(&self) -> subtle::Choice { + self.int.is_zero() + } + + pub fn non_zero(self) -> CtOption { + CtOption::new(NonZeroExponentP256 { e: self }, !self.is_zero()) + } + + /** Arithmetic **/ + pub fn mul_top(&self, other: &Int256, other_top: Digit) -> ExponentP256 { + ExponentP256 { + int: Int256::modmul_top(&self.int, other, other_top, &Int256::N), + } + } +} + +/** Arithmetic operators **/ +impl Mul for &ExponentP256 { + type Output = ExponentP256; + + fn mul(self, other: &ExponentP256) -> ExponentP256 { + ExponentP256 { + int: Int256::modmul(&self.int, &other.int, &Int256::N), + } + } +} + +// A non-zero exponent on the elliptic curve. +#[derive(Clone, Copy, PartialEq, Eq)] +// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is +// resolved. +#[derive(Default)] +#[cfg_attr(feature = "derive_debug", derive(Debug))] +pub struct NonZeroExponentP256 { + e: ExponentP256, +} + +impl ConditionallySelectable for NonZeroExponentP256 { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + Self { + e: ExponentP256::conditional_select(&a.e, &b.e, choice), + } + } +} + +impl NonZeroExponentP256 { + /** RNG **/ + // Generates a uniformly distributed element 0 < k < N + pub fn gen_uniform(r: &mut R) -> NonZeroExponentP256 + where + R: Rng256, + { + loop { + let x = Int256::gen_uniform_256(r); + if bool::from(Int256::N_MIN_2.ct_lt(&x)) { + continue; + } + // At this point, x <= n - 2. + // We add 1 so that 0 < result < n. + return NonZeroExponentP256 { + e: ExponentP256 { int: (&x + 1).0 }, + }; + } + } + + /** Constructors **/ + pub fn from_int_checked(int: Int256) -> CtOption { + ExponentP256::from_int_checked(int) + .and_then(|e| CtOption::new(NonZeroExponentP256 { e }, !e.is_zero())) + } + + /** Helpful getters **/ + pub fn to_int(self) -> Int256 { + self.e.to_int() + } + + pub fn as_exponent(&self) -> &ExponentP256 { + &self.e + } + + /** Arithmetic **/ + // Compute the inverse modulo N. This uses Fermat's little theorem for constant-timeness. + pub fn inv(&self) -> NonZeroExponentP256 { + NonZeroExponentP256 { + e: ExponentP256 { + int: self.e.int.modpow(&Int256::N_MIN_2, &Int256::N), + }, + } + } + + #[cfg(test)] + fn inv_vartime(&self) -> NonZeroExponentP256 { + NonZeroExponentP256 { + e: ExponentP256 { + int: self.e.int.modinv_vartime(&Int256::N), + }, + } + } +} + +/** Arithmetic operators **/ +impl Mul for &NonZeroExponentP256 { + type Output = NonZeroExponentP256; + + // The product of two non-zero elements is also non-zero, because the curve order N is prime. + fn mul(self, other: &NonZeroExponentP256) -> NonZeroExponentP256 { + NonZeroExponentP256 { + e: &self.e * &other.e, + } + } +} + +#[cfg(test)] +pub mod test { + use super::super::montgomery::Montgomery; + use super::*; + use crate::util::ToOption; + + const ZERO: ExponentP256 = ExponentP256 { int: Int256::ZERO }; + const ONE: NonZeroExponentP256 = NonZeroExponentP256 { + e: ExponentP256 { int: Int256::ONE }, + }; + const N_MIN_1_INT: Int256 = Int256::new([ + 0xfc632550, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, + ]); + const N_MIN_1: NonZeroExponentP256 = NonZeroExponentP256 { + e: ExponentP256 { int: N_MIN_1_INT }, + }; + + fn get_nonzero_test_values() -> Vec { + let mut values: Vec = Montgomery::PRECOMPUTED + .iter() + .flatten() + .flatten() + .map(|x| { + ExponentP256::modn(x.montgomery_to_field().to_int()) + .non_zero() + .unwrap() + }) + .collect(); + values.extend( + super::super::int256::test::get_nonzero_test_values() + .iter() + .filter_map(|&x| { + let y = ExponentP256::modn(x).non_zero(); + if bool::from(y.is_some()) { + Some(y.unwrap()) + } else { + None + } + }), + ); + values.push(ONE); + values + } + + pub fn get_test_values() -> Vec { + let mut values: Vec = get_nonzero_test_values() + .iter() + .map(|x| *x.as_exponent()) + .collect(); + values.push(ZERO); + values + } + + /** Constructors **/ + #[test] + fn test_from_int_checked() { + assert_eq!( + ExponentP256::from_int_checked(Int256::ZERO).to_option(), + Some(ExponentP256 { int: Int256::ZERO }) + ); + assert_eq!( + ExponentP256::from_int_checked(Int256::ONE).to_option(), + Some(ExponentP256 { int: Int256::ONE }) + ); + assert_eq!( + ExponentP256::from_int_checked(N_MIN_1_INT).to_option(), + Some(ExponentP256 { int: N_MIN_1_INT }) + ); + assert_eq!(ExponentP256::from_int_checked(Int256::N).to_option(), None); + } + + #[test] + fn test_modn() { + assert_eq!( + ExponentP256::modn(Int256::ZERO), + ExponentP256 { int: Int256::ZERO } + ); + assert_eq!( + ExponentP256::modn(Int256::ONE), + ExponentP256 { int: Int256::ONE } + ); + assert_eq!( + ExponentP256::modn(N_MIN_1_INT), + ExponentP256 { int: N_MIN_1_INT } + ); + assert_eq!( + ExponentP256::modn(Int256::N), + ExponentP256 { int: Int256::ZERO } + ); + } + + /** Arithmetic operations: inverse **/ + #[test] + fn test_inv_is_inv_vartime() { + for x in &get_nonzero_test_values() { + assert_eq!(x.inv(), x.inv_vartime()); + } + } + + #[test] + fn test_self_times_inv_is_one() { + for x in &get_nonzero_test_values() { + assert_eq!(x * &x.inv(), ONE); + } + } + + #[test] + fn test_inv_inv() { + for x in get_nonzero_test_values() { + assert_eq!(x.inv().inv(), x); + } + } + + #[test] + fn test_well_known_inverses() { + assert_eq!(ONE.inv(), ONE); + assert_eq!(N_MIN_1.inv(), N_MIN_1); + } + + /** RNG **/ + // Mock rng that samples through a list of values, then panics. + struct StressTestingRng { + values: Vec, + index: usize, + } + + impl StressTestingRng { + pub fn new(values: Vec) -> StressTestingRng { + StressTestingRng { values, index: 0 } + } + } + + impl Rng256 for StressTestingRng { + // This function is unused, as we redefine gen_uniform_u32x8. + fn gen_uniform_u8x32(&mut self) -> [u8; 32] { + unreachable!() + } + + fn gen_uniform_u32x8(&mut self) -> [u32; 8] { + let result = self.values[self.index].digits(); + self.index += 1; + result + } + } + + #[test] + fn test_uniform_non_zero_is_below_n() { + let mut rng = StressTestingRng::new(vec![ + Int256::new([ + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, + ]), + Int256::N, + N_MIN_1.to_int(), + Int256::N_MIN_2, + ]); + + assert_eq!(NonZeroExponentP256::gen_uniform(&mut rng), N_MIN_1); + } + + #[test] + fn test_uniform_n_is_above_zero() { + let mut rng = StressTestingRng::new(vec![Int256::ZERO]); + + assert_eq!(NonZeroExponentP256::gen_uniform(&mut rng), ONE); + } +} diff --git a/libraries/crypto/src/ec/gfp256.rs b/libraries/crypto/src/ec/gfp256.rs new file mode 100644 index 0000000..bb3232c --- /dev/null +++ b/libraries/crypto/src/ec/gfp256.rs @@ -0,0 +1,260 @@ +// Copyright 2019 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. + +use super::int256::{Digit, Int256}; +use core::ops::Mul; +use subtle::Choice; + +// A field element on the elliptic curve, that is an element modulo the prime P. +// This is the format used to serialize coordinates of points on the curve. +// This implements enough methods to validate points and to convert them to/from the Montgomery +// form, which is more convenient to operate on. +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct GFP256 { + int: Int256, +} + +impl GFP256 { + pub const ZERO: GFP256 = GFP256 { int: Int256::ZERO }; + pub const ONE: GFP256 = GFP256 { int: Int256::ONE }; + pub const B: GFP256 = GFP256 { int: Int256::B }; + pub const R: GFP256 = GFP256 { int: Int256::R }; + pub const R_INV: GFP256 = GFP256 { int: Int256::R_INV }; + + /** Constructors **/ + pub fn from_int_checked(int: Int256) -> Option { + if bool::from(int.ct_lt(&Int256::P)) { + Some(GFP256 { int }) + } else { + None + } + } + + /** Helpful getters **/ + pub fn to_int(self) -> Int256 { + self.int + } + + fn is_zero(&self) -> Choice { + self.int.is_zero() + } + + /** Arithmetic **/ + pub fn mul_top(&self, other: &Int256, other_top: Digit) -> GFP256 { + GFP256 { + int: Int256::modmul_top(&self.int, other, other_top, &Int256::P), + } + } + + /** Point validation **/ + // Verify that all of the following are true: + // * y^2 == x^3 - 3x + b mod p + // * 0 < x < p + // * 0 < y < p + // + // Not constant time. + pub fn is_valid_point_vartime(x: &GFP256, y: &GFP256) -> bool { + if bool::from(x.is_zero()) || bool::from(y.is_zero()) { + return false; + } + + // y^2 + let y2 = y * y; + + // x^3 + let x2 = x * x; + let x3 = &x2 * x; + + // x^3 - 3x + b + let mut xx = x3; + xx = xx.sub_vartime(x); + xx = xx.sub_vartime(x); + xx = xx.sub_vartime(x); + xx = xx.add_vartime(&GFP256::B); + + xx == y2 + } + + /** Arithmetic operators **/ + fn add_vartime(self, other: &GFP256) -> GFP256 { + GFP256 { + int: Int256::modadd_vartime(&self.int, &other.int, &Int256::P), + } + } + + fn sub_vartime(self, other: &GFP256) -> GFP256 { + GFP256 { + int: Int256::modsub_vartime(&self.int, &other.int, &Int256::P), + } + } +} + +/** Arithmetic operators **/ +impl Mul for &GFP256 { + type Output = GFP256; + + fn mul(self, other: &GFP256) -> GFP256 { + GFP256 { + int: Int256::modmul(&self.int, &other.int, &Int256::P), + } + } +} + +#[cfg(feature = "derive_debug")] +impl core::fmt::Debug for GFP256 { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "GFP256::{:?}", self.int) + } +} + +#[cfg(test)] +mod test { + use super::super::montgomery::Montgomery; + use super::*; + use core::ops::{Add, Sub}; + + const P_MIN_1_INT: Int256 = Int256::new([ + 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0xffffffff, + ]); + + fn get_test_values() -> Vec { + let mut values: Vec = Montgomery::PRECOMPUTED + .iter() + .flatten() + .flatten() + .map(|x| x.montgomery_to_field()) + .collect(); + values.extend( + super::super::int256::test::get_1bit_one_test_values() + .iter() + .filter_map(|&x| GFP256::from_int_checked(x)), + ); + values.extend( + super::super::int256::test::get_1bit_zero_test_values() + .iter() + .filter_map(|&x| GFP256::from_int_checked(x)), + ); + values.push(GFP256::ZERO); + values.push(GFP256::ONE); + values.push(GFP256::B); + values + } + + /** Arithmetic operators, only for tests as these are not constant time **/ + impl Add for &GFP256 { + type Output = GFP256; + + fn add(self, other: &GFP256) -> GFP256 { + self.add_vartime(other) + } + } + + impl Sub for &GFP256 { + type Output = GFP256; + + fn sub(self, other: &GFP256) -> GFP256 { + self.sub_vartime(other) + } + } + + /** Constructors **/ + #[test] + fn test_from_int_checked() { + assert_eq!( + GFP256::from_int_checked(Int256::ZERO), + Some(GFP256 { int: Int256::ZERO }) + ); + assert_eq!( + GFP256::from_int_checked(Int256::ONE), + Some(GFP256 { int: Int256::ONE }) + ); + assert_eq!( + GFP256::from_int_checked(P_MIN_1_INT), + Some(GFP256 { int: P_MIN_1_INT }) + ); + assert_eq!(GFP256::from_int_checked(Int256::P), None); + } + + /** Point validation **/ + // See point.rs + + /** Arithmetic operators **/ + // Due to the 3 nested loops, this test is super slow with debug assertions enabled. + #[cfg(not(debug_assertions))] + #[test] + fn test_add_is_associative() { + for x in &get_test_values() { + for y in &get_test_values() { + for z in &get_test_values() { + assert_eq!(&(x + y) + z, x + &(y + z)); + } + } + } + } + + #[test] + fn test_add_is_commutative() { + for x in &get_test_values() { + for y in &get_test_values() { + assert_eq!(x + y, y + x); + } + } + } + + #[test] + fn test_add_sub() { + for x in &get_test_values() { + for y in &get_test_values() { + assert_eq!(&(x - y) + y, *x); + assert_eq!(&(x + y) - y, *x); + } + } + } + + // Due to the 3 nested loops, this test is super slow with debug assertions enabled. + #[cfg(not(debug_assertions))] + #[test] + fn test_mul_is_associative() { + for x in &get_test_values() { + for y in &get_test_values() { + for z in &get_test_values() { + assert_eq!(&(x * y) * z, x * &(y * z)); + } + } + } + } + + #[test] + fn test_mul_is_commutative() { + for x in &get_test_values() { + for y in &get_test_values() { + assert_eq!(x * y, y * x); + } + } + } + + // Due to the 3 nested loops, this test is super slow with debug assertions enabled. + #[cfg(not(debug_assertions))] + #[test] + fn test_mul_is_distributive() { + for x in &get_test_values() { + for y in &get_test_values() { + for z in &get_test_values() { + assert_eq!(&(x + y) * z, &(x * z) + &(y * z)); + } + } + } + } +} diff --git a/libraries/crypto/src/ec/int256.rs b/libraries/crypto/src/ec/int256.rs new file mode 100644 index 0000000..2f3a1da --- /dev/null +++ b/libraries/crypto/src/ec/int256.rs @@ -0,0 +1,1181 @@ +// Copyright 2019 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. + +use super::super::rng256::Rng256; +use alloc::vec::Vec; +use byteorder::{BigEndian, ByteOrder}; +use core::ops::{Add, AddAssign, Sub, SubAssign}; +use subtle::{self, Choice, ConditionallySelectable, ConstantTimeEq}; + +const BITS_PER_DIGIT: usize = 32; +const BYTES_PER_DIGIT: usize = BITS_PER_DIGIT >> 3; +const NDIGITS: usize = 8; +pub const NBYTES: usize = NDIGITS * BYTES_PER_DIGIT; + +pub type Digit = u32; +type DoubleDigit = u64; +type SignedDoubleDigit = i64; + +#[derive(Clone, Copy, PartialEq, Eq)] +// TODO: remove this Default once https://github.com/dalek-cryptography/subtle/issues/63 is +// resolved. +#[derive(Default)] +pub struct Int256 { + digits: [Digit; NDIGITS], +} + +impl ConditionallySelectable for Int256 { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let mut digits = [0; NDIGITS]; + for (i, digit) in digits.iter_mut().enumerate() { + *digit = Digit::conditional_select(&a.digits[i], &b.digits[i], choice); + } + Self { digits } + } +} + +/** Arithmetic operations on the secp256r1 field, where elements are represented as 8 digits of + * 32 bits. **/ +#[allow(clippy::unreadable_literal)] +impl Int256 { + /** Constants for the secp256r1 curve. **/ + // Curve order (prime) + pub const N: Int256 = Int256 { + digits: [ + 0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, + ], + }; + // Curve order - 2 + pub const N_MIN_2: Int256 = Int256 { + digits: [ + 0xfc63254f, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, + ], + }; + // Curve field size + pub const P: Int256 = Int256 { + digits: [ + 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0xffffffff, + ], + }; + // Curve b + pub const B: Int256 = Int256 { + digits: [ + 0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0, 0x769886bc, 0xb3ebbd55, 0xaa3a93e7, + 0x5ac635d8, + ], + }; + // 2^257 mod P + pub const R: Int256 = Int256 { + digits: [ + 0x00000002, 0x00000000, 0x00000000, 0xfffffffe, 0xffffffff, 0xffffffff, 0xfffffffd, + 0x00000001, + ], + }; + // 1 / 2^257 mod P + pub const R_INV: Int256 = Int256 { + digits: [ + 0x80000000, 0x00000001, 0xffffffff, 0x00000000, 0x80000001, 0xfffffffe, 0x00000001, + 0x7fffffff, + ], + }; + + pub const ZERO: Int256 = Int256 { digits: [0; 8] }; + pub const ONE: Int256 = Int256 { + digits: [1, 0, 0, 0, 0, 0, 0, 0], + }; + + #[cfg(test)] + pub const fn new(digits: [Digit; NDIGITS]) -> Int256 { + Int256 { digits } + } + + #[cfg(test)] + pub fn digits(self) -> [Digit; NDIGITS] { + self.digits + } + + #[cfg(test)] + fn hamming_weight(&self) -> u32 { + self.digits.iter().map(|d| d.count_ones()).sum() + } + + /** RNG **/ + // Generates a uniformly distributed integer 0 <= x < 2^256 + pub fn gen_uniform_256(r: &mut R) -> Int256 + where + R: Rng256, + { + Int256 { + digits: r.gen_uniform_u32x8(), + } + } + + /** Serialization **/ + pub fn from_bin(src: &[u8; NBYTES]) -> Int256 { + let mut digits = [0; NDIGITS]; + for i in 0..NDIGITS { + digits[NDIGITS - 1 - i] = BigEndian::read_u32(array_ref![src, 4 * i, 4]); + } + Int256 { digits } + } + + pub fn to_bin(&self, dst: &mut [u8; NBYTES]) { + for i in 0..NDIGITS { + BigEndian::write_u32(array_mut_ref![dst, 4 * i, 4], self.digits[NDIGITS - 1 - i]); + } + } + + pub fn to_minimal_encoding(self) -> Vec { + let mut bytes_buffer = [0; NBYTES]; + self.to_bin(&mut bytes_buffer); + match bytes_buffer.iter().position(|x| *x != 0) { + Some(pos) => { + let mut encoding = vec![]; + if bytes_buffer[pos] & 0x80 == 0x80 { + encoding.push(0x00); + } + encoding.extend_from_slice(&bytes_buffer[pos..]); + encoding + } + None => vec![0x00], + } + } + + /** Useful getters **/ + #[inline(always)] + pub fn digit(&self, i: usize) -> Digit { + self.digits[i] + } + + pub fn bit(&self, i: usize) -> Digit { + let digit = i / BITS_PER_DIGIT; + let bit = i & (BITS_PER_DIGIT - 1); + (self.digits[digit] >> bit) & 1 + } + + pub fn is_zero(&self) -> subtle::Choice { + // Best effort constant-time comparison, assuming the compiler doesn't optimize that. + Choice::from( + self.digits + .iter() + .fold(1u8, |acc, x| acc & x.ct_eq(&0).unwrap_u8()), + ) + } + + // Helper function to implement variable-time modular inverse. + #[cfg(test)] + fn is_even(&self) -> bool { + self.digits[0] & 1 == 0 + } + + #[cfg(test)] + fn count_ones(&self) -> u32 { + self.digits.iter().map(|x| x.count_ones()).sum() + } + + /** Arithmetic operations: bit shifts **/ + // Shift left by n bits, and return the result as well as the top digit that was shifted out. + // This is valid only for 0 < n < BITS_PER_DIGIT + pub fn shl(&self, n: usize) -> (Int256, Digit) { + let mut digits = [0; NDIGITS]; + digits[0] = self.digits[0] << n; + #[allow(clippy::needless_range_loop)] + for i in 1..NDIGITS { + digits[i] = (self.digits[i] << n) | (self.digits[i - 1] >> (BITS_PER_DIGIT - n)); + } + + ( + Int256 { digits }, + self.digits[NDIGITS - 1] >> (BITS_PER_DIGIT - n), + ) + } + + // Shift right by n bits. + // This is valid only for 0 < n < BITS_PER_DIGIT + pub fn shr(&self, n: usize) -> Int256 { + let mut digits = [0; NDIGITS]; + #[allow(clippy::needless_range_loop)] + for i in 0..(NDIGITS - 1) { + digits[i] = (self.digits[i] >> n) | (self.digits[i + 1] << (BITS_PER_DIGIT - n)); + } + digits[NDIGITS - 1] = self.digits[NDIGITS - 1] >> n; + + Int256 { digits } + } + + // Helper function to implement variable-time modular inverse. + // Shift right by 1 bit, pushing highbit at the top. + #[cfg(test)] + fn shr1(&self, highbit: Digit) -> Int256 { + let mut digits = [0; NDIGITS]; + for i in 0..(NDIGITS - 1) { + digits[i] = (self.digits[i] >> 1) | (self.digits[i + 1] << (BITS_PER_DIGIT - 1)); + } + digits[NDIGITS - 1] = (self.digits[NDIGITS - 1] >> 1) | (highbit << (BITS_PER_DIGIT - 1)); + + Int256 { digits } + } + + /** Arithmetic operations: addition/substraction **/ + // Reduction modulo modd. + pub fn modd(&self, modd: &Int256) -> Int256 { + let mut digits = self.digits; + let choice = Int256::sub_conditional(&mut digits, modd, 0, Choice::from(1u8)); + Int256::add_conditional(&mut digits, modd, 0, choice); + Int256 { digits } + } + + // Computes: dst[], top += if choice { mod[] } else { 0 } + // Returns: new top digit + fn add_conditional( + dst: &mut [Digit; NDIGITS], + modd: &Int256, + top: Digit, + choice: Choice, + ) -> Digit { + let mut carry: DoubleDigit = 0; + + for (i, digit) in dst.iter_mut().enumerate() { + carry += *digit as DoubleDigit; + carry += u32::conditional_select(&0, &modd.digits[i], choice) as DoubleDigit; + *digit = carry as Digit; + carry >>= BITS_PER_DIGIT; + } + + (carry as Digit) + top + } + + // Computes: dst[], top -= if choice { mod[] } else { 0 } + // Returns: new top digit + fn sub_conditional( + dst: &mut [Digit; NDIGITS], + modd: &Int256, + top: Digit, + choice: Choice, + ) -> Choice { + let mut borrow: SignedDoubleDigit = 0; + + for (i, digit) in dst.iter_mut().enumerate() { + borrow += *digit as SignedDoubleDigit; + borrow -= u32::conditional_select(&0, &modd.digits[i], choice) as SignedDoubleDigit; + *digit = borrow as Digit; + borrow >>= BITS_PER_DIGIT; + } + + ((borrow + (top as SignedDoubleDigit)) as Digit).ct_eq(&!0) + } + + /** Modular arithmetic operations **/ + // Modular addition. + pub fn modadd_vartime(&self, other: &Int256, modd: &Int256) -> Int256 { + let (sum, carry) = (self as &Int256) + other; + let tmp = if carry != 0 { (&sum - modd).0 } else { sum }; + + // At this point, the sum can be >= modd, even without carry. + // We substract modd to handle this case. + tmp.modsub_vartime(modd, modd) + } + + // Modular substraction. + pub fn modsub_vartime(&self, other: &Int256, modd: &Int256) -> Int256 { + let (diff, borrow) = (self as &Int256) - other; + if borrow != 0 { + (&diff + modd).0 + } else { + diff + } + } + + // Requires: the most-significant word of the modulus is 0xffffffff. + // Computes: a * b modulo modd. + pub fn modmul(a: &Int256, b: &Int256, modd: &Int256) -> Int256 { + Int256::modmul_top(a, b, 0, modd) + } + + // Requires: the most-significant word of the modulus is 0xffffffff. + // Computes: a * (b, top_b) modulo modd. + pub fn modmul_top(a: &Int256, b: &Int256, top_b: Digit, modd: &Int256) -> Int256 { + let mut tmp = [0; NDIGITS * 2 + 1]; + let mut top = 0; + + // Multiply/add into tmp. + for i in 0..NDIGITS { + if i != 0 { + tmp[i + NDIGITS - 1] = top; + } + top = Int256::mul_add(array_mut_ref![tmp, i, NDIGITS], a, b.digits[i]); + } + + tmp[2 * NDIGITS - 1] = top; + top = Int256::mul_add(array_mut_ref![tmp, NDIGITS, NDIGITS], a, top_b); + + // Reduce tmp, digit by digit. + for j in 0..=NDIGITS { + let i = NDIGITS - j; + + // Estimate the reducer as top * modd, because the most significant word of modd is + // 0xffffffff. + let mut reducer = Int256::ZERO; + let top_reducer = Int256::mul_add(&mut reducer.digits, modd, top); + top = Int256::sub_top(array_mut_ref![tmp, i, NDIGITS], &reducer, top, top_reducer); + + #[cfg(test)] + assert!(top <= 1); + + let _top = + Int256::sub_conditional(array_mut_ref![tmp, i, NDIGITS], modd, top, top.ct_eq(&1)); + + #[cfg(test)] + assert_eq!(bool::from(_top), false); + + top = tmp[i + NDIGITS - 1]; + } + + let choice = + Int256::sub_conditional(array_mut_ref![tmp, 0, NDIGITS], modd, 0, Choice::from(1u8)); + Int256::add_conditional(array_mut_ref![tmp, 0, NDIGITS], modd, 0, choice); + + Int256 { + digits: *array_ref![tmp, 0, NDIGITS], + } + } + + // Helper function to implement modular multiplication. + // Computes: dst[] += src[] * factor + // Returns: carry digit + fn mul_add(dst: &mut [Digit; NDIGITS], src: &Int256, factor: Digit) -> Digit { + let mut carry: DoubleDigit = 0; + + for (i, digit) in dst.iter_mut().enumerate() { + carry += *digit as DoubleDigit; + carry += (src.digits[i] as DoubleDigit) * (factor as DoubleDigit); + *digit = carry as Digit; + carry >>= BITS_PER_DIGIT; + } + + carry as Digit + } + + // Helper function to implement modular multiplication. + // Computes: dst[], top -= src[], src_top + // Returns: borrow digit (new top) + fn sub_top(dst: &mut [Digit; NDIGITS], src: &Int256, top: Digit, src_top: Digit) -> Digit { + let mut borrow: SignedDoubleDigit = 0; + + for (i, digit) in dst.iter_mut().enumerate() { + borrow += *digit as SignedDoubleDigit; + borrow -= src.digits[i] as SignedDoubleDigit; + *digit = borrow as Digit; + borrow >>= BITS_PER_DIGIT; + } + + borrow += top as SignedDoubleDigit; + borrow -= src_top as SignedDoubleDigit; + + #[cfg(test)] + assert_eq!(borrow >> BITS_PER_DIGIT, 0); + + borrow as Digit + } + + /** Constant-time helpers **/ + // Helper function to implement constant-time modular inverse. + // Best-effort constant time function that computes: + // if idx == 0 { + // *tbl0 = Int256::ONE + // } else { + // *tbl0 = tbl[idx - 1] + // } + fn set_zero_to_idx(tbl0: &mut Int256, tbl: &[Int256; 15], idx: u32) { + *tbl0 = Int256::ONE; + for i in 1u32..16 { + tbl0.conditional_assign(&tbl[(i - 1) as usize], i.ct_eq(&idx)); + } + } + + /** Arithmetic operations: modular exponentiation **/ + pub fn modpow(&self, power: &Int256, modd: &Int256) -> Int256 { + let mut tbl0 = Int256::ZERO; + let mut tbl = [Int256::ZERO; 15]; + // tbl[i-1] = self^i + tbl[0] = *self; + for i in 1..15 { + tbl[i] = Int256::modmul(&tbl[i - 1], self, modd); + } + + let mut result = Int256::ONE; + for j in (0..256).step_by(4) { + let i = 256 - j; + result = Int256::modmul(&result, &result, modd); + result = Int256::modmul(&result, &result, modd); + result = Int256::modmul(&result, &result, modd); + result = Int256::modmul(&result, &result, modd); + + let idx = power.bit(i - 1) << 3 + | power.bit(i - 2) << 2 + | power.bit(i - 3) << 1 + | power.bit(i - 4); + + Int256::set_zero_to_idx(&mut tbl0, &tbl, idx); // tbl0 = tbl[idx-1]; + tbl0 = Int256::modmul(&tbl0, &result, modd); + result.conditional_assign(&tbl0, !idx.ct_eq(&0)); + } + + result + } + + /** Arithmetic operations: modular inverse **/ + // Variable time function to compute modular inverse. This uses Euclid's theorem. + #[cfg(test)] + #[allow(clippy::many_single_char_names)] + pub fn modinv_vartime(&self, modd: &Int256) -> Int256 { + let mut r = Int256::ZERO; + let mut s = Int256::ONE; + let mut u = *modd; + let mut v = *self; + + loop { + if u.is_even() { + u = u.shr1(0); + if r.is_even() { + r = r.shr1(0); + } else { + let (rr, highbit) = &r + modd; + r = rr.shr1(highbit); + } + } else if v.is_even() { + v = v.shr1(0); + if s.is_even() { + s = s.shr1(0); + } else { + let (ss, highbit) = &s + modd; + s = ss.shr1(highbit); + } + } else { + let (w, borrow) = &v - &u; + if borrow == 0 { + v = w; + let (ss, borrow) = &s - &r; + s = if borrow != 0 { (&ss + modd).0 } else { ss }; + if bool::from(v.is_zero()) { + break; + } + } else { + u = (&u - &v).0; + let (rr, borrow) = &r - &s; + r = if borrow != 0 { (&rr + modd).0 } else { rr }; + } + } + } + + r.modd(modd) + } + + /** Comparison between field elements. **/ + // Best-effort constant-time less-than operation. + // FIXME: This code is currently required because subtle only supports constant-time equality + // comparisons. This should be removed once + // https://github.com/dalek-cryptography/subtle/issues/61 is fixed + pub fn ct_lt(&self, other: &Int256) -> Choice { + let mut borrow: SignedDoubleDigit = 0; + + for i in 0..NDIGITS { + // The following statement updates the borrow according to this table. + // +-------------------------------------+----------------+------------------+ + // | self.digits[i].cmp(other.digits[i]) | borrow += ? | resulting borrow | + // +-------------------------------------+----------------+------------------+ + // | Less | ffffffff_xx... | ffffffff_yy... | + // | Equal | 0 | unchanged | + // | Greater | 00000000_xx... | 00000000_yy... | + // +-------------------------------------+----------------+------------------+ + borrow += + (self.digits[i] as SignedDoubleDigit) - (other.digits[i] as SignedDoubleDigit); + // This is a signed shift. After this operation, the borrow can take two values: + // - 00...00 (so far, self >= other) + // - ff...ff (so far, self < other) + borrow >>= BITS_PER_DIGIT; + } + + Choice::from((borrow & 1) as u8) + } + + // Best-effort constant time comparison. + // * 0 = equal + // * 1 = self > other + // * -1 = self < other + #[cfg(test)] + pub fn compare(&self, other: &Int256) -> u32 { + let mut borrow: SignedDoubleDigit = 0; + let mut notzero: Digit = 0; + + for i in 0..NDIGITS { + borrow += + (self.digits[i] as SignedDoubleDigit) - (other.digits[i] as SignedDoubleDigit); + notzero |= (borrow as Digit != 0) as Digit; + borrow >>= BITS_PER_DIGIT; + } + + (borrow as Digit) | notzero + } + + #[cfg(test)] + fn compare_vartime(&self, other: &Int256) -> u32 { + use core::cmp::Ordering; + + for i in 0..NDIGITS { + match self.digits[NDIGITS - i - 1].cmp(&other.digits[NDIGITS - i - 1]) { + Ordering::Equal => continue, + Ordering::Greater => return 1, + Ordering::Less => return 0xffffffff, + } + } + 0 + } +} + +/** Addition with carry **/ +impl Add for &Int256 { + type Output = (Int256, Digit); + + // Returns sum and carry (0 or 1). + fn add(self, other: &Int256) -> (Int256, Digit) { + let mut digits = [0; NDIGITS]; + let mut carry: DoubleDigit = 0; + + for (i, digit) in digits.iter_mut().enumerate() { + carry += (self.digits[i] as DoubleDigit) + (other.digits[i] as DoubleDigit); + *digit = carry as Digit; + carry >>= BITS_PER_DIGIT; + } + + (Int256 { digits }, carry as Digit) + } +} + +impl AddAssign<&Int256> for Int256 { + // Adds to self, ignoring carry. + fn add_assign(&mut self, other: &Int256) { + let mut carry: DoubleDigit = 0; + for i in 0..NDIGITS { + carry += (self.digits[i] as DoubleDigit) + (other.digits[i] as DoubleDigit); + self.digits[i] = carry as Digit; + carry >>= BITS_PER_DIGIT; + } + } +} + +impl Add for &Int256 { + type Output = (Int256, Digit); + + // Returns sum and carry (0 or 1). + fn add(self, digit: Digit) -> (Int256, Digit) { + let mut digits = [0; NDIGITS]; + let mut carry = digit as DoubleDigit; + + for (i, digit) in digits.iter_mut().enumerate() { + carry += self.digits[i] as DoubleDigit; + *digit = carry as Digit; + carry >>= BITS_PER_DIGIT; + } + + (Int256 { digits }, carry as Digit) + } +} + +/** Substraction with borrow **/ +impl Sub for &Int256 { + type Output = (Int256, Digit); + + // Returns difference and borrow (0 or -1). + fn sub(self, other: &Int256) -> (Int256, Digit) { + let mut digits = [0; NDIGITS]; + let mut borrow: SignedDoubleDigit = 0; + + for (i, digit) in digits.iter_mut().enumerate() { + borrow += + (self.digits[i] as SignedDoubleDigit) - (other.digits[i] as SignedDoubleDigit); + *digit = borrow as Digit; + borrow >>= BITS_PER_DIGIT; + } + + (Int256 { digits }, borrow as Digit) + } +} + +impl SubAssign<&Int256> for Int256 { + // Substract from self, ignoring carry. + fn sub_assign(&mut self, other: &Int256) { + let mut borrow: SignedDoubleDigit = 0; + for i in 0..NDIGITS { + borrow += + (self.digits[i] as SignedDoubleDigit) - (other.digits[i] as SignedDoubleDigit); + self.digits[i] = borrow as Digit; + borrow >>= BITS_PER_DIGIT; + } + } +} + +#[cfg(feature = "derive_debug")] +impl core::fmt::Debug for Int256 { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "Int256 {{ digits: {:08x?} }}", self.digits) + } +} + +#[cfg(test)] +pub mod test { + use super::super::montgomery::Montgomery; + use super::*; + + /** Extra constants for tests **/ + const TWO: Int256 = Int256 { + digits: [2, 0, 0, 0, 0, 0, 0, 0], + }; + const P_MIN_1: Int256 = Int256 { + digits: [ + 0xfffffffe, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0xffffffff, + ], + }; + const P_MIN_2: Int256 = Int256 { + digits: [ + 0xfffffffd, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0xffffffff, + ], + }; + + // Generate all 256-bit integers that have exactly one bit set to 1. + pub fn get_1bit_one_test_values() -> Vec { + let mut values = Vec::new(); + for &byte in &[0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80] { + for &int in &[byte, byte << 8, byte << 16, byte << 24] { + values.push(Int256 { + digits: [int, 0, 0, 0, 0, 0, 0, 0], + }); + values.push(Int256 { + digits: [0, int, 0, 0, 0, 0, 0, 0], + }); + values.push(Int256 { + digits: [0, 0, int, 0, 0, 0, 0, 0], + }); + values.push(Int256 { + digits: [0, 0, 0, int, 0, 0, 0, 0], + }); + values.push(Int256 { + digits: [0, 0, 0, 0, int, 0, 0, 0], + }); + values.push(Int256 { + digits: [0, 0, 0, 0, 0, int, 0, 0], + }); + values.push(Int256 { + digits: [0, 0, 0, 0, 0, 0, int, 0], + }); + values.push(Int256 { + digits: [0, 0, 0, 0, 0, 0, 0, int], + }); + } + } + values + } + + // Generate all 256-bit integers that have exactly one bit set to 0. + pub fn get_1bit_zero_test_values() -> Vec { + let values: Vec = get_1bit_one_test_values() + .iter() + .map(|x| { + let mut digits = [Default::default(); NDIGITS]; + for i in 0..NDIGITS { + digits[i] = !x.digits[i]; + } + Int256 { digits } + }) + .collect(); + values + } + + pub fn get_nonzero_test_values() -> Vec { + let mut values: Vec = Montgomery::PRECOMPUTED + .iter() + .flatten() + .flatten() + .map(|x| x.montgomery_to_field().to_int()) + .collect(); + values.append(&mut get_1bit_one_test_values()); + values.append(&mut get_1bit_zero_test_values()); + values.push(Int256::B); + values.push(P_MIN_1); + values.push(P_MIN_2); + values + } + + fn get_test_values() -> Vec { + let mut values = get_nonzero_test_values(); + values.push(Int256::ZERO); + values + } + + #[test] + fn test_1bit_one() { + let values = get_1bit_one_test_values(); + assert_eq!(values.len(), 256); + for x in &values { + assert_eq!(x.hamming_weight(), 1); + } + } + + #[test] + fn test_1bit_zero() { + let values = get_1bit_zero_test_values(); + assert_eq!(values.len(), 256); + for x in &values { + assert_eq!(x.hamming_weight(), 255); + } + } + + /** Serialization **/ + #[test] + fn test_to_bin_from_bin() { + for &x in &get_test_values() { + let mut buf = [Default::default(); NBYTES]; + x.to_bin(&mut buf); + assert_eq!(Int256::from_bin(&buf), x); + } + } + + #[test] + fn test_minimal_encoding_zero() { + let test_int = Int256::ZERO; + let expected_encoding = vec![0x00]; + + assert_eq!(test_int.to_minimal_encoding(), expected_encoding); + } + + #[test] + fn test_minimal_encoding_one() { + let test_int = Int256::ONE; + let expected_encoding = vec![0x01]; + + assert_eq!(test_int.to_minimal_encoding(), expected_encoding); + } + + #[test] + fn test_minimal_encoding_one_full_byte() { + let bytes = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, + ]; + let test_int = Int256::from_bin(&bytes); + let expected_encoding = vec![0x00, 0xFF]; + + assert_eq!(test_int.to_minimal_encoding(), expected_encoding); + } + + #[test] + fn test_minimal_encoding_most_bytes_full() { + let bytes = [ + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + ]; + let test_int = Int256::from_bin(&bytes); + let expected_encoding = bytes.to_vec(); + + assert_eq!(test_int.to_minimal_encoding(), expected_encoding); + } + + #[test] + fn test_minimal_encoding_no_leading_byte() { + let bytes = [ + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + ]; + let test_int = Int256::from_bin(&bytes); + let expected_encoding = bytes.to_vec(); + + assert_eq!(test_int.to_minimal_encoding(), expected_encoding); + } + + #[test] + fn test_minimal_encoding_with_leading_byte() { + let bytes = [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + ]; + let test_int = Int256::from_bin(&bytes); + let mut expected_encoding = vec![0x00]; + expected_encoding.extend(&bytes); + + assert_eq!(test_int.to_minimal_encoding(), expected_encoding); + } + + #[test] + fn test_from_bin_is_big_endian_bits_with_little_endian_words() { + let buf = b"\x01\x23\x45\x67\x89\xab\xcd\xef\ + \x12\x34\x56\x78\x9a\xbc\xde\xf0\ + \x23\x45\x67\x89\xab\xcd\xef\x01\ + \x34\x56\x78\x9a\xbc\xde\xf0\x12"; + assert_eq!( + Int256::from_bin(&buf), + Int256 { + digits: [ + 0xbcdef012, 0x3456789a, 0xabcdef01, 0x23456789, 0x9abcdef0, 0x12345678, + 0x89abcdef, 0x01234567, + ] + } + ); + } + + /** Useful getters **/ + #[test] + fn test_is_zero() { + assert!(bool::from(Int256::ZERO.is_zero())); + for x in get_nonzero_test_values() { + assert!(!bool::from(x.is_zero())); + } + } + + #[test] + fn test_is_even() { + assert!(Int256::ZERO.is_even()); + assert!(!Int256::ONE.is_even()); + assert!(TWO.is_even()); + assert!(!Int256::N.is_even()); + assert!(!Int256::P.is_even()); + assert!(!Int256::B.is_even()); + } + + /** Arithmetic operations: bit shifts **/ + #[test] + fn test_shift_zero() { + for i in 1..BITS_PER_DIGIT { + assert_eq!(Int256::ZERO.shl(i), (Int256::ZERO, 0)); + } + for i in 1..BITS_PER_DIGIT { + assert_eq!(Int256::ZERO.shr(i), Int256::ZERO); + } + } + + #[test] + fn test_shifts() { + let mut a = Int256::ONE; + + // Shift left. + for i in 0..255 { + assert_eq!(a.bit(i), 1); + assert!(!bool::from(a.is_zero())); + let (shifted, carry) = a.shl(1); + assert_eq!(carry, 0); + a = shifted; + assert_eq!(a.bit(i), 0); + assert_eq!(a.count_ones(), 1); + } + + assert_eq!(a.bit(255), 1); + assert!(!bool::from(a.is_zero())); + let (shifted, carry) = a.shl(1); + assert_eq!(carry, 1); + assert_eq!(shifted.bit(255), 0); + assert!(bool::from(shifted.is_zero())); + + // Shift right. + for i in (1..256).rev() { + assert_eq!(a.bit(i), 1); + assert!(!bool::from(a.is_zero())); + a = a.shr(1); + assert_eq!(a.bit(i), 0); + assert_eq!(a.count_ones(), 1); + } + + assert_eq!(a.bit(0), 1); + assert!(!bool::from(a.is_zero())); + a = a.shr(1); + assert_eq!(a.bit(0), 0); + assert!(bool::from(a.is_zero())); + } + + #[test] + fn test_shl_shr1() { + for x in &get_test_values() { + let (shifted, carry) = x.shl(1); + assert_eq!(&shifted.shr1(carry), x); + } + } + + #[test] + fn test_shr1_is_shr_one() { + for x in &get_test_values() { + assert_eq!(x.shr(1), x.shr1(0)); + } + for x in &get_test_values() { + let mut y = *x; + for i in 1..BITS_PER_DIGIT { + y = y.shr1(0); + assert_eq!(x.shr(i), y); + } + } + } + + /** Constant-time helpers **/ + #[test] + fn test_set_zero_to_idx() { + let mut tbl = [Int256::ZERO; 15]; + for (i, x) in tbl.iter_mut().enumerate() { + *x = Int256 { + digits: [i as u32; NDIGITS], + }; + } + + for i in 0..16 { + let mut tbl0 = Int256::ZERO; + Int256::set_zero_to_idx(&mut tbl0, &tbl, i as u32); + if i == 0 { + assert_eq!(tbl0, Int256::ONE); + } else { + assert_eq!(tbl0, tbl[i - 1]); + } + } + } + + /** Arithmetic: constant-time conditional addition/substraction **/ + #[test] + fn test_add_conditional() { + for x in &get_test_values() { + for y in &get_test_values() { + let mut z = *x; + let carry = Int256::add_conditional(&mut z.digits, y, 0, Choice::from(0u8)); + assert_eq!(carry, 0); + assert_eq!(z, *x); + let carry = Int256::add_conditional(&mut z.digits, y, 0, Choice::from(1u8)); + assert_eq!((z, carry), x + y); + } + } + } + + #[test] + fn test_sub_conditional() { + for x in &get_test_values() { + for y in &get_test_values() { + let mut z = *x; + let borrow = Int256::sub_conditional(&mut z.digits, y, 0, Choice::from(0u8)); + assert_eq!(bool::from(borrow), false); + assert_eq!(z, *x); + let borrow = Int256::sub_conditional(&mut z.digits, y, 0, Choice::from(1u8)); + assert_eq!((z, Digit::conditional_select(&0, &!0, borrow)), x - y); + } + } + } + + /** Arithmetic operators **/ + #[test] + fn test_add_sub() { + for x in &get_test_values() { + for y in &get_test_values() { + let (sum, carry) = x + y; + let (diff, borrow) = &sum - y; + assert_eq!(diff, *x); + assert_eq!(carry.wrapping_add(borrow), 0); + } + } + } + + #[test] + fn test_sub_add() { + for x in &get_test_values() { + for y in &get_test_values() { + let (diff, borrow) = x - y; + let (sum, carry) = &diff + y; + assert_eq!(sum, *x); + assert_eq!(carry.wrapping_add(borrow), 0); + } + } + } + + /** Arithmetic: modular exponentiation **/ + #[test] + fn test_modpow() { + const MODULUS: Int256 = Int256::P; + for x in &get_test_values() { + let mut result = Int256::ONE; + let mut power = Int256::ZERO; + + // This test is super slow with debug assertions enabled. + #[cfg(not(debug_assertions))] + const ITERATIONS: u32 = 100; + #[cfg(debug_assertions)] + const ITERATIONS: u32 = 5; + + for _ in 0..ITERATIONS { + assert_eq!(x.modpow(&power, &MODULUS), result); + result = Int256::modmul(&result, x, &MODULUS); + power += &Int256::ONE; + } + } + } + + #[test] + fn test_self_times_modinv_is_one() { + const MODULUS: Int256 = Int256::P; + for x in &get_nonzero_test_values() { + let inv = x.modinv_vartime(&MODULUS); + let product = Int256::modmul(&x, &inv, &MODULUS); + assert_eq!(product, Int256::ONE); + } + } + + #[test] + fn test_modinv_modinv() { + const MODULUS: Int256 = Int256::P; + for &x in &get_nonzero_test_values() { + // By construction, this test only works if x is less than the modulus. + if x.compare(&MODULUS) != 0xffffffff { + continue; + } + assert_eq!(x.modinv_vartime(&MODULUS).modinv_vartime(&MODULUS), x); + } + } + + /** Other arithmetic **/ + #[test] + fn test_add_digit() { + for x in &get_test_values() { + for y in &get_test_values() { + for &digit in &y.digits { + assert_eq!( + x + digit, + x + &Int256 { + digits: [digit, 0, 0, 0, 0, 0, 0, 0] + } + ); + } + } + } + } + + #[test] + fn test_add_assign() { + for x in &get_test_values() { + for y in &get_test_values() { + let mut z = *x; + z += y; + assert_eq!(z, (x + y).0); + } + } + } + + #[test] + fn test_sub_assign() { + for x in &get_test_values() { + for y in &get_test_values() { + let mut z = *x; + z -= y; + assert_eq!(z, (x - y).0); + } + } + } + + #[test] + fn test_mul_add() { + for x in &get_test_values() { + for y in &get_test_values() { + let mut result = *x; + let mut carries = 0; + + // This test is super slow with debug assertions enabled. + #[cfg(not(debug_assertions))] + const ITERATIONS: u32 = 1000; + #[cfg(debug_assertions)] + const ITERATIONS: u32 = 5; + + for factor in 0..ITERATIONS { + let mut z = *x; + let ma_carry = Int256::mul_add(&mut z.digits, y, factor); + assert_eq!(ma_carry, carries); + assert_eq!(z, result); + + let (sum, carry) = &result + y; + result = sum; + carries += carry; + } + } + } + } + + /** Comparison between field elements. **/ + #[test] + fn test_compare() { + for x in &get_test_values() { + for y in &get_test_values() { + let cmp = x.compare(y); + assert!(cmp == 0 || cmp == 1 || cmp == 0xffffffff); + assert_eq!(cmp, x.compare_vartime(y)); + } + } + } + + #[test] + fn test_compare_is_reflexive() { + for x in &get_test_values() { + assert_eq!(x.compare(x), 0); + } + } + + #[test] + fn test_compare_is_antisymetric() { + for x in &get_test_values() { + for y in &get_test_values() { + let a = x.compare(y); + let b = y.compare(x); + assert_eq!(a.wrapping_add(b), 0); + } + } + } + + #[test] + fn test_lt() { + for x in &get_test_values() { + for y in &get_test_values() { + let ct_lt = bool::from(x.ct_lt(y)); + let lt = x.compare_vartime(y) == 0xffffffff; + assert_eq!(ct_lt, lt); + } + } + } + + #[test] + fn test_lt_is_antireflexive() { + for x in &get_test_values() { + assert!(!bool::from(x.ct_lt(x))); + } + } + + #[test] + fn test_lt_is_antisymetric() { + for x in &get_test_values() { + for y in &get_test_values() { + let a = x.ct_lt(y).unwrap_u8(); + let b = y.ct_lt(x).unwrap_u8(); + let c = (x == y) as u8; + assert_eq!(a + b + c, 1); + } + } + } + + // TODO: more tests +} diff --git a/libraries/crypto/src/ec/mod.rs b/libraries/crypto/src/ec/mod.rs new file mode 100644 index 0000000..20c469f --- /dev/null +++ b/libraries/crypto/src/ec/mod.rs @@ -0,0 +1,20 @@ +// Copyright 2019 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. + +pub mod exponent256; +mod gfp256; +pub mod int256; +mod montgomery; +pub mod point; +mod precomputed; diff --git a/libraries/crypto/src/ec/montgomery.rs b/libraries/crypto/src/ec/montgomery.rs new file mode 100644 index 0000000..c197b52 --- /dev/null +++ b/libraries/crypto/src/ec/montgomery.rs @@ -0,0 +1,1109 @@ +// Copyright 2019 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. + +use super::gfp256::GFP256; +use super::int256::Int256; +use super::precomputed; +use core::ops::{Add, Mul, Sub}; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; + +pub const NLIMBS: usize = 9; +pub const BOTTOM_28_BITS: u32 = 0x0fff_ffff; +pub const BOTTOM_29_BITS: u32 = 0x1fff_ffff; + +/** Field element on the secp256r1 curve, represented in Montgomery form **/ +#[derive(Clone, Copy)] +pub struct Montgomery { + // The 9 limbs use 28 or 29 bits, alternatively: even limbs use 29 bits, odd limbs use 28 bits. + // The Montgomery form stores a field element x as (x * 2^257) mod P. + pub limbs: [u32; NLIMBS], +} + +impl ConditionallySelectable for Montgomery { + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let mut limbs = [0; NLIMBS]; + for (i, limb) in limbs.iter_mut().enumerate() { + *limb = u32::conditional_select(&a.limbs[i], &b.limbs[i], choice); + } + Self { limbs } + } +} + +#[allow(clippy::unreadable_literal)] +impl Montgomery { + /** Constants for the secp256r1 field **/ + pub const ZERO: Montgomery = Montgomery { + limbs: [ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, + ], + }; + pub const ONE: Montgomery = Montgomery { + limbs: [ + 0x00000002, 0x00000000, 0x00000000, 0x0ffff800, 0x1fffffff, 0x0fffffff, 0x1fbfffff, + 0x01ffffff, 0x00000000, + ], + }; + pub const A: Montgomery = Montgomery { + limbs: [ + 0x1ffffff8, 0x0fffffff, 0x1fffffff, 0x10001fff, 0x1fffffff, 0x0fffffff, 0x20ffffff, + 0x07ffffff, 0x1fffffff, + ], + }; + pub const B: Montgomery = Montgomery { + limbs: [ + 0x13897bbf, 0x09cdf622, 0x043090d8, 0x002e67c4, 0x176b5678, 0x02afdc84, 0x0d196888, + 0x0b090e90, 0x0b8600c3, + ], + }; + pub const THREE_B: Montgomery = Montgomery { + limbs: [ + 0x1a9c733f, 0x0d69e267, 0x0c91b289, 0x108b2f4c, 0x26420367, 0x180f958d, 0x270c3997, + 0x031b2bb0, 0x0292024b, + ], + }; + const P: Montgomery = Montgomery { + limbs: [ + 0x1fffffff, 0x0fffffff, 0x1fffffff, 0x000003ff, 0x00000000, 0x00000000, 0x00200000, + 0x0f000000, 0x0fffffff, + ], + }; + const TWO_P: Montgomery = Montgomery { + limbs: [ + 0x1ffffffe, 0x0fffffff, 0x1fffffff, 0x000007ff, 0x00000000, 0x00000000, 0x00400000, + 0x0e000000, 0x1fffffff, + ], + }; + // A constant equal to 0 mod p. This is used to implement substraction arithmetic. + const ZERO31: Montgomery = Montgomery { + limbs: [ + (1 << 31) - (1 << 3), + (1 << 30) - (1 << 2), + (1 << 31) - (1 << 2), + (1 << 30) + (1 << 13) - (1 << 2), + (1 << 31) - (1 << 2), + (1 << 30) - (1 << 2), + (1 << 31) + (1 << 24) - (1 << 2), + (1 << 30) - (1 << 27) - (1 << 2), + (1 << 31) - (1 << 2), + ], + }; + + /** Precomputed multiples of the base point of the elliptic curve **/ + pub const fn new(limbs: [u32; NLIMBS]) -> Montgomery { + Montgomery { limbs } + } + + // This contains two tables of 15 points, each represented by its x and y coordinates in + // Montgomery form. + pub const PRECOMPUTED: [[[Montgomery; 2]; 15]; 2] = precomputed::PRECOMPUTED; + + /** Conversion to/from Montgomery form **/ + pub fn field_to_montgomery(gf: &GFP256) -> Montgomery { + let mut limbs = [0; NLIMBS]; + + let mut shifted = (gf * &GFP256::R).to_int(); + for (i, limb) in limbs.iter_mut().enumerate() { + if i & 1 == 0 { + *limb = shifted.digit(0) & BOTTOM_29_BITS; + shifted = shifted.shr(29); + } else { + *limb = shifted.digit(0) & BOTTOM_28_BITS; + shifted = shifted.shr(28); + } + } + + Montgomery { limbs } + } + + pub fn montgomery_to_field(&self) -> GFP256 { + let (mut result, _) = Int256::ZERO.add(self.limbs[NLIMBS - 1]); + let mut top = 0; + + for j in 0..=(NLIMBS - 2) { + let i = NLIMBS - 2 - j; + + let shift = if i & 1 == 0 { 29 } else { 28 }; + let (tmp, top1) = result.shl(shift); + + let (r, top2) = tmp.add(self.limbs[i]); + result = r; + top = top1 | top2; + } + + GFP256::R_INV.mul_top(&result, top) + } + + /** Useful getters **/ + #[inline(always)] + fn get64(&self, i: usize) -> u64 { + self.limbs[i] as u64 + } + + /** Advanced arithmetic **/ + // Squaring. + pub fn square(&self) -> Montgomery { + let mut big_limbs: [u64; 17] = [0; 17]; + + big_limbs[0] = self.get64(0) * self.get64(0); + big_limbs[1] = self.get64(0) * (self.get64(1) << 1); + big_limbs[2] = self.get64(0) * (self.get64(2) << 1) + self.get64(1) * (self.get64(1) << 1); + big_limbs[3] = self.get64(0) * (self.get64(3) << 1) + self.get64(1) * (self.get64(2) << 1); + big_limbs[4] = self.get64(0) * (self.get64(4) << 1) + + self.get64(1) * (self.get64(3) << 2) + + self.get64(2) * self.get64(2); + big_limbs[5] = self.get64(0) * (self.get64(5) << 1) + + self.get64(1) * (self.get64(4) << 1) + + self.get64(2) * (self.get64(3) << 1); + big_limbs[6] = self.get64(0) * (self.get64(6) << 1) + + self.get64(1) * (self.get64(5) << 2) + + self.get64(2) * (self.get64(4) << 1) + + self.get64(3) * (self.get64(3) << 1); + big_limbs[7] = self.get64(0) * (self.get64(7) << 1) + + self.get64(1) * (self.get64(6) << 1) + + self.get64(2) * (self.get64(5) << 1) + + self.get64(3) * (self.get64(4) << 1); + big_limbs[8] = self.get64(0) * (self.get64(8) << 1) + + self.get64(1) * (self.get64(7) << 2) + + self.get64(2) * (self.get64(6) << 1) + + self.get64(3) * (self.get64(5) << 2) + + self.get64(4) * self.get64(4); + big_limbs[9] = self.get64(1) * (self.get64(8) << 1) + + self.get64(2) * (self.get64(7) << 1) + + self.get64(3) * (self.get64(6) << 1) + + self.get64(4) * (self.get64(5) << 1); + big_limbs[10] = self.get64(2) * (self.get64(8) << 1) + + self.get64(3) * (self.get64(7) << 2) + + self.get64(4) * (self.get64(6) << 1) + + self.get64(5) * (self.get64(5) << 1); + big_limbs[11] = self.get64(3) * (self.get64(8) << 1) + + self.get64(4) * (self.get64(7) << 1) + + self.get64(5) * (self.get64(6) << 1); + big_limbs[12] = self.get64(4) * (self.get64(8) << 1) + + self.get64(5) * (self.get64(7) << 2) + + self.get64(6) * self.get64(6); + big_limbs[13] = self.get64(5) * (self.get64(8) << 1) + self.get64(6) * (self.get64(7) << 1); + big_limbs[14] = self.get64(6) * (self.get64(8) << 1) + self.get64(7) * (self.get64(7) << 1); + big_limbs[15] = self.get64(7) * (self.get64(8) << 1); + big_limbs[16] = self.get64(8) * self.get64(8); + + Montgomery::reduce_degree(&big_limbs) + } + + // Modular inverse. + pub fn inv(&self) -> Montgomery { + let mut tmp = self.square(); + tmp = &tmp * self; + let e2 = tmp; // 2^2 - 2^0 + + tmp = tmp.square(); + tmp = tmp.square(); + tmp = &tmp * &e2; + let e4 = tmp; // 2^4 - 2^0 + + for _ in 0..4 { + tmp = tmp.square(); + } + tmp = &tmp * &e4; + let e8 = tmp; // 2^8 - 2^0 + + for _ in 0..8 { + tmp = tmp.square(); + } + tmp = &tmp * &e8; + let e16 = tmp; // 2^16 - 2^0 + + for _ in 0..16 { + tmp = tmp.square(); + } + tmp = &tmp * &e16; + let e32 = tmp; // 2^32 - 2^0 + + for _ in 0..32 { + tmp = tmp.square(); + } + let e64 = tmp; // 2^64 - 2^32 + tmp = &tmp * self; + + for _ in 0..192 { + tmp = tmp.square(); + } // 2^256 - 2^224 + 2^192 + + // 2^64 - 2^0 + let mut tmp2 = &e64 * &e32; + for _ in 0..16 { + tmp2 = tmp2.square(); + } + // 2^80 - 2^0 + tmp2 = &tmp2 * &e16; + for _ in 0..8 { + tmp2 = tmp2.square(); + } + // 2^88 - 2^0 + tmp2 = &tmp2 * &e8; + for _ in 0..4 { + tmp2 = tmp2.square(); + } + // 2^92 - 2^0 + tmp2 = &tmp2 * &e4; + tmp2 = tmp2.square(); + tmp2 = tmp2.square(); + // 2^94 - 2^0 + tmp2 = &tmp2 * &e2; + tmp2 = tmp2.square(); + tmp2 = tmp2.square(); + // 2^96 - 3 + tmp2 = &tmp2 * self; + + // 2^256 - 2^224 + 2^192 + 2^96 - 3 + &tmp2 * &tmp + } + + // Multiplication by 2. + pub fn mul_scalar2(&mut self) { + let mut carry = 0; + + let mut i = 0; + loop { + let next_carry = self.limbs[i] >> 28; + self.limbs[i] <<= 1; + self.limbs[i] &= BOTTOM_29_BITS; + self.limbs[i] += carry; + carry = next_carry + (self.limbs[i] >> 29); + self.limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + let next_carry = self.limbs[i] >> 27; + self.limbs[i] <<= 1; + self.limbs[i] &= BOTTOM_28_BITS; + self.limbs[i] += carry; + carry = next_carry + (self.limbs[i] >> 28); + self.limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + self.reduce_carry(carry); + } + + // Multiplication by 3. + pub fn mul_scalar3(&mut self) { + let mut carry = 0; + + let mut i = 0; + loop { + self.limbs[i] *= 3; + self.limbs[i] += carry; + carry = self.limbs[i] >> 29; + self.limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + self.limbs[i] *= 3; + self.limbs[i] += carry; + carry = self.limbs[i] >> 28; + self.limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + self.reduce_carry(carry); + } + + // Multiplication by 4. + pub fn mul_scalar4(&mut self) { + let mut carry = 0; + + let mut i = 0; + loop { + let next_carry = self.limbs[i] >> 27; + self.limbs[i] <<= 2; + self.limbs[i] &= BOTTOM_29_BITS; + self.limbs[i] += carry; + carry = next_carry + (self.limbs[i] >> 29); + self.limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + let next_carry = self.limbs[i] >> 26; + self.limbs[i] <<= 2; + self.limbs[i] &= BOTTOM_28_BITS; + self.limbs[i] += carry; + carry = next_carry + (self.limbs[i] >> 28); + self.limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + self.reduce_carry(carry); + } + + // Multiplication by 8. + pub fn mul_scalar8(&mut self) { + let mut carry = 0; + + let mut i = 0; + loop { + let next_carry = self.limbs[i] >> 26; + self.limbs[i] <<= 3; + self.limbs[i] &= BOTTOM_29_BITS; + self.limbs[i] += carry; + carry = next_carry + (self.limbs[i] >> 29); + self.limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + let next_carry = self.limbs[i] >> 25; + self.limbs[i] <<= 3; + self.limbs[i] &= BOTTOM_28_BITS; + self.limbs[i] += carry; + carry = next_carry + (self.limbs[i] >> 28); + self.limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + self.reduce_carry(carry); + } + + /** Comparison **/ + pub fn is_zero_vartime(&self) -> bool { + // Reduce to a minimal form. + let tmp = self.reduced_vartime(); + + tmp.limbs == Montgomery::ZERO.limbs + || tmp.limbs == Montgomery::P.limbs + || tmp.limbs == Montgomery::TWO_P.limbs + } + + fn reduced_vartime(&self) -> Montgomery { + let mut reduced = *self; + + // Reduce to a minimal form. + loop { + let mut carry = 0; + let mut i = 0; + loop { + reduced.limbs[i] += carry; + carry = reduced.limbs[i] >> 29; + reduced.limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + reduced.limbs[i] += carry; + carry = reduced.limbs[i] >> 28; + reduced.limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + if carry == 0 { + break; + } + reduced.reduce_carry(carry); + } + + reduced + } + + /** Reduction of saturated limbs **/ + // Adds a multiple of p in order to cancel |carry|, which is a term at 2**257. + // On entry: carry < 2**3, self[0,2,...] < 2**29, self[1,3,...] < 2**28. + // On exit: self[0,2,..] < 2**30, self[1,3,...] < 2**29. + fn reduce_carry(&mut self, carry: u32) { + let carry_choice = carry.ct_eq(&0); + self.limbs[0] += carry << 1; + self.limbs[3] += u32::conditional_select(&0x10000000, &0, carry_choice); + self.limbs[3] -= carry << 11; + self.limbs[4] += u32::conditional_select(&(0x20000000 - 1), &0, carry_choice); + self.limbs[5] += u32::conditional_select(&(0x10000000 - 1), &0, carry_choice); + self.limbs[6] += u32::conditional_select(&(0x20000000 - 1), &0, carry_choice); + self.limbs[6] -= carry << 22; + self.limbs[7] += carry << 25; + self.limbs[7] -= u32::conditional_select(&1, &0, carry_choice); + } + + // Reduce the output of a multiplication or squaring. + fn reduce_degree(big_limbs: &[u64; 17]) -> Montgomery { + let mut limbs: [u32; 18] = Montgomery::propagate_carry(big_limbs); + Montgomery::eliminate_terms(&mut limbs); + Montgomery::compact_limbs(limbs) + } + + // Helper function for reduce_degree(). + // Converts 17 saturated 64-bit limbs to 18 unsaturated limbs of 28 or 29 bits. + fn propagate_carry(big_limbs: &[u64; 17]) -> [u32; 18] { + let mut limbs: [u32; 18] = [0; 18]; + + limbs[0] = (big_limbs[0] as u32) & BOTTOM_29_BITS; + limbs[1] = (big_limbs[0] as u32) >> 29; + limbs[1] |= (((big_limbs[0] >> 32) as u32) << 3) & BOTTOM_28_BITS; + limbs[1] += (big_limbs[1] as u32) & BOTTOM_28_BITS; + let mut carry = limbs[1] >> 28; + limbs[1] &= BOTTOM_28_BITS; + + let mut i = 2; + loop { + limbs[i] = ((big_limbs[i - 2] >> 32) as u32) >> 25; + limbs[i] += (big_limbs[i - 1] as u32) >> 28; + limbs[i] += (((big_limbs[i - 1] >> 32) as u32) << 4) & BOTTOM_29_BITS; + limbs[i] += (big_limbs[i] as u32) & BOTTOM_29_BITS; + limbs[i] += carry; + carry = limbs[i] >> 29; + limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == 17 { + break; + } + + limbs[i] = ((big_limbs[i - 2] >> 32) as u32) >> 25; + limbs[i] += (big_limbs[i - 1] as u32) >> 29; + limbs[i] += (((big_limbs[i - 1] >> 32) as u32) << 3) & BOTTOM_28_BITS; + limbs[i] += (big_limbs[i] as u32) & BOTTOM_28_BITS; + limbs[i] += carry; + carry = limbs[i] >> 28; + limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + limbs[17] = ((big_limbs[15] >> 32) as u32) >> 25; + limbs[17] += (big_limbs[16] as u32) >> 29; + limbs[17] += ((big_limbs[16] >> 32) as u32) << 3; + limbs[17] += carry; + + limbs + } + + // Helper function for reduce_degree(). + // Montgomery elimination of terms. + fn eliminate_terms(limbs: &mut [u32; 18]) { + let mut i = 0; + loop { + limbs[i + 1] += limbs[i] >> 29; + let x = limbs[i] & BOTTOM_29_BITS; + let choice = x.ct_eq(&0); + limbs[i] = 0; + + limbs[i + 3] += (x << 10) & BOTTOM_28_BITS; + limbs[i + 4] += x >> 18; + + limbs[i + 6] += (x << 21) & BOTTOM_29_BITS; + limbs[i + 7] += x >> 8; + + limbs[i + 7] += u32::conditional_select(&0x10000000, &0, choice); + limbs[i + 8] += u32::conditional_select(&x.wrapping_sub(1), &0, choice); + limbs[i + 7] -= (x << 24) & BOTTOM_28_BITS; + limbs[i + 8] -= x >> 4; + + limbs[i + 8] += u32::conditional_select(&0x20000000, &0, choice); + limbs[i + 8] -= x; + limbs[i + 8] += (x << 28) & BOTTOM_29_BITS; + limbs[i + 9] = limbs[i + 9].wrapping_add(u32::conditional_select( + &(x >> 1).wrapping_sub(1), + &0, + choice, + )); + + if i + 1 == NLIMBS { + break; + } + + limbs[i + 2] += limbs[i + 1] >> 28; + let x = limbs[i + 1] & BOTTOM_28_BITS; + let choice = x.ct_eq(&0); + limbs[i + 1] = 0; + + limbs[i + 4] += (x << 11) & BOTTOM_29_BITS; + limbs[i + 5] += x >> 18; + + limbs[i + 7] += (x << 21) & BOTTOM_28_BITS; + limbs[i + 8] += x >> 7; + + limbs[i + 8] += u32::conditional_select(&0x20000000, &0, choice); + limbs[i + 9] += u32::conditional_select(&x.wrapping_sub(1), &0, choice); + limbs[i + 8] -= (x << 25) & BOTTOM_29_BITS; + limbs[i + 9] -= x >> 4; + + limbs[i + 9] += u32::conditional_select(&0x10000000, &0, choice); + limbs[i + 9] -= x; + limbs[i + 10] += u32::conditional_select(&x.wrapping_sub(1), &0, choice); + + i += 2; + } + } + + // Helper function for reduce_degree(). + // Extract the final limbs from Montgomery-eliminated terms. + fn compact_limbs(tmp: [u32; 18]) -> Montgomery { + let mut limbs = [0; NLIMBS]; + let mut carry = 0; + let mut i = 0; + loop { + limbs[i] = tmp[i + 9]; + limbs[i] += carry; + limbs[i] += (tmp[i + 10] << 28) & BOTTOM_29_BITS; + carry = limbs[i] >> 29; + limbs[i] &= BOTTOM_29_BITS; + + i += 1; + + limbs[i] = tmp[i + 9] >> 1; + limbs[i] += carry; + carry = limbs[i] >> 28; + limbs[i] &= BOTTOM_28_BITS; + + i += 1; + if i == 8 { + break; + } + } + + limbs[8] = tmp[17]; + limbs[8] = limbs[8].wrapping_add(carry); + carry = limbs[8] >> 29; + limbs[8] &= BOTTOM_29_BITS; + + let mut result = Montgomery { limbs }; + result.reduce_carry(carry); + result + } +} + +/** Arithmetic operators **/ +// Clippy warns when it sees a subtraction being done in Add implementation +// which here is completely fine. +#[allow(clippy::suspicious_arithmetic_impl)] +impl Add for &Montgomery { + type Output = Montgomery; + + fn add(self, other: &Montgomery) -> Montgomery { + let mut carry = 0; + let mut limbs = [0; NLIMBS]; + + let mut i = 0; + loop { + limbs[i] = self.limbs[i] + other.limbs[i]; + limbs[i] += carry; + carry = limbs[i] >> 29; + limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + limbs[i] = self.limbs[i] + other.limbs[i]; + limbs[i] += carry; + carry = limbs[i] >> 28; + limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + let mut result = Montgomery { limbs }; + result.reduce_carry(carry); + result + } +} + +#[allow(clippy::suspicious_arithmetic_impl)] +// Clippy warns when it sees an addition being done in Sub implementation +// which here is completely fine. +impl Sub for &Montgomery { + type Output = Montgomery; + + fn sub(self, other: &Montgomery) -> Montgomery { + let mut carry = 0; + let mut limbs = [0; NLIMBS]; + + let mut i = 0; + loop { + limbs[i] = self.limbs[i] + (Montgomery::ZERO31.limbs[i] - other.limbs[i]); + limbs[i] += carry; + carry = limbs[i] >> 29; + limbs[i] &= BOTTOM_29_BITS; + + i += 1; + if i == NLIMBS { + break; + } + + limbs[i] = self.limbs[i] + (Montgomery::ZERO31.limbs[i] - other.limbs[i]); + limbs[i] += carry; + carry = limbs[i] >> 28; + limbs[i] &= BOTTOM_28_BITS; + + i += 1; + } + + let mut result = Montgomery { limbs }; + result.reduce_carry(carry); + result + } +} + +impl Mul for &Montgomery { + type Output = Montgomery; + + fn mul(self, other: &Montgomery) -> Montgomery { + let mut big_limbs: [u64; 17] = [0; 17]; + + big_limbs[0] = self.get64(0) * other.get64(0); + big_limbs[1] = self.get64(0) * other.get64(1) + self.get64(1) * other.get64(0); + big_limbs[2] = self.get64(0) * other.get64(2) + + self.get64(1) * (other.get64(1) << 1) + + self.get64(2) * other.get64(0); + big_limbs[3] = self.get64(0) * other.get64(3) + + self.get64(1) * other.get64(2) + + self.get64(2) * other.get64(1) + + self.get64(3) * other.get64(0); + big_limbs[4] = self.get64(0) * other.get64(4) + + self.get64(1) * (other.get64(3) << 1) + + self.get64(2) * other.get64(2) + + self.get64(3) * (other.get64(1) << 1) + + self.get64(4) * other.get64(0); + big_limbs[5] = self.get64(0) * other.get64(5) + + self.get64(1) * other.get64(4) + + self.get64(2) * other.get64(3) + + self.get64(3) * other.get64(2) + + self.get64(4) * other.get64(1) + + self.get64(5) * other.get64(0); + big_limbs[6] = self.get64(0) * other.get64(6) + + self.get64(1) * (other.get64(5) << 1) + + self.get64(2) * other.get64(4) + + self.get64(3) * (other.get64(3) << 1) + + self.get64(4) * other.get64(2) + + self.get64(5) * (other.get64(1) << 1) + + self.get64(6) * other.get64(0); + big_limbs[7] = self.get64(0) * other.get64(7) + + self.get64(1) * other.get64(6) + + self.get64(2) * other.get64(5) + + self.get64(3) * other.get64(4) + + self.get64(4) * other.get64(3) + + self.get64(5) * other.get64(2) + + self.get64(6) * other.get64(1) + + self.get64(7) * other.get64(0); + big_limbs[8] = self.get64(0) * other.get64(8) + + self.get64(1) * (other.get64(7) << 1) + + self.get64(2) * other.get64(6) + + self.get64(3) * (other.get64(5) << 1) + + self.get64(4) * other.get64(4) + + self.get64(5) * (other.get64(3) << 1) + + self.get64(6) * other.get64(2) + + self.get64(7) * (other.get64(1) << 1) + + self.get64(8) * other.get64(0); + big_limbs[9] = self.get64(1) * other.get64(8) + + self.get64(2) * other.get64(7) + + self.get64(3) * other.get64(6) + + self.get64(4) * other.get64(5) + + self.get64(5) * other.get64(4) + + self.get64(6) * other.get64(3) + + self.get64(7) * other.get64(2) + + self.get64(8) * other.get64(1); + big_limbs[10] = self.get64(2) * other.get64(8) + + self.get64(3) * (other.get64(7) << 1) + + self.get64(4) * other.get64(6) + + self.get64(5) * (other.get64(5) << 1) + + self.get64(6) * other.get64(4) + + self.get64(7) * (other.get64(3) << 1) + + self.get64(8) * other.get64(2); + big_limbs[11] = self.get64(3) * other.get64(8) + + self.get64(4) * other.get64(7) + + self.get64(5) * other.get64(6) + + self.get64(6) * other.get64(5) + + self.get64(7) * other.get64(4) + + self.get64(8) * other.get64(3); + big_limbs[12] = self.get64(4) * other.get64(8) + + self.get64(5) * (other.get64(7) << 1) + + self.get64(6) * other.get64(6) + + self.get64(7) * (other.get64(5) << 1) + + self.get64(8) * other.get64(4); + big_limbs[13] = self.get64(5) * other.get64(8) + + self.get64(6) * other.get64(7) + + self.get64(7) * other.get64(6) + + self.get64(8) * other.get64(5); + big_limbs[14] = self.get64(6) * other.get64(8) + + self.get64(7) * (other.get64(7) << 1) + + self.get64(8) * other.get64(6); + big_limbs[15] = self.get64(7) * other.get64(8) + self.get64(8) * other.get64(7); + big_limbs[16] = self.get64(8) * other.get64(8); + + Montgomery::reduce_degree(&big_limbs) + } +} + +#[cfg(test)] +pub mod test { + use super::*; + + impl PartialEq for Montgomery { + fn eq(&self, other: &Montgomery) -> bool { + (self - other).is_zero_vartime() + } + } + + impl core::fmt::Debug for Montgomery { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "Montgomery {{ limbs: {:08x?} }}", self.limbs) + } + } + + pub fn get_nonzero_test_values() -> Vec { + let mut values: Vec = Montgomery::PRECOMPUTED + .iter() + .flatten() + .flatten() + .cloned() + .collect(); + values.push(Montgomery::ONE); + values.push(Montgomery::A); + values.push(Montgomery::B); + values.push(Montgomery::THREE_B); + // TODO: Add more test values. + values + } + + fn get_test_values() -> Vec { + let mut values = get_nonzero_test_values(); + values.push(Montgomery::ZERO); + values + } + + /** Constants for the secp256r1 field **/ + #[test] + fn test_zero31_is_zero_mod_p() { + assert!(Montgomery::ZERO31.is_zero_vartime()); + } + + #[test] + fn test_2p() { + assert_eq!( + Montgomery::TWO_P.limbs, + (&Montgomery::P + &Montgomery::P).limbs + ); + } + + #[test] + fn test_a() { + // a == -3 + let mut a = GFP256::ZERO; + a = &a - &GFP256::ONE; + a = &a - &GFP256::ONE; + a = &a - &GFP256::ONE; + assert_eq!(Montgomery::A, Montgomery::field_to_montgomery(&a)); + } + + #[test] + fn test_b() { + assert_eq!(Montgomery::B, Montgomery::field_to_montgomery(&GFP256::B)); + } + + #[test] + fn test_3b() { + let mut b3 = GFP256::B; + b3 = &b3 + &GFP256::B; + b3 = &b3 + &GFP256::B; + assert_eq!(Montgomery::THREE_B, Montgomery::field_to_montgomery(&b3)); + } + + /** Conversion to/from Montgomery form **/ + #[test] + fn test_conversion_round_trip() { + for x in get_test_values() { + assert_eq!(x, Montgomery::field_to_montgomery(&x.montgomery_to_field())); + } + } + + #[test] + fn test_conversion_for_constants() { + assert_eq!( + Montgomery::ZERO.limbs, + Montgomery::field_to_montgomery(&GFP256::ZERO).limbs + ); + assert_eq!( + Montgomery::ONE.limbs, + Montgomery::field_to_montgomery(&GFP256::ONE).limbs + ); + } + + /** Constant-time helpers **/ + + /** Arithmetic operators **/ + #[test] + fn test_add_is_associative() { + for x in &get_test_values() { + for y in &get_test_values() { + for z in &get_test_values() { + assert_eq!(&(x + y) + z, x + &(y + z)); + } + } + } + } + + #[test] + fn test_add_is_commutative() { + for x in &get_test_values() { + for y in &get_test_values() { + assert_eq!(x + y, y + x); + } + } + } + + #[test] + fn test_add_sub() { + for x in &get_test_values() { + for y in &get_test_values() { + assert_eq!(&(x - y) + y, *x); + assert_eq!(&(x + y) - y, *x); + } + } + } + + #[test] + fn test_mul_is_associative() { + for x in &get_test_values() { + for y in &get_test_values() { + for z in &get_test_values() { + assert_eq!(&(x * y) * z, x * &(y * z)); + } + } + } + } + + #[test] + fn test_mul_is_commutative() { + for x in &get_test_values() { + for y in &get_test_values() { + assert_eq!(x * y, y * x); + } + } + } + + #[test] + fn test_mul_is_distributive() { + for x in &get_test_values() { + for y in &get_test_values() { + for z in &get_test_values() { + assert_eq!(&(x + y) * z, &(x * z) + &(y * z)); + } + } + } + } + + /** Advanced arithmetic **/ + #[test] + fn test_square_is_mul_self() { + for x in &get_test_values() { + let multiplied = x * x; + let squared = x.square(); + assert_eq!(multiplied, squared); + } + } + + #[test] + fn test_self_times_inv_is_one() { + for x in &get_nonzero_test_values() { + let inv = x.inv(); + let product = x * &inv; + assert_eq!(product, Montgomery::ONE); + } + } + + #[test] + fn test_inv_inv() { + for x in get_nonzero_test_values() { + assert_eq!(x.inv().inv(), x); + } + } + + #[test] + fn test_well_known_inverses() { + assert_eq!(Montgomery::ONE.inv(), Montgomery::ONE); + let p_min_1 = &Montgomery::P - &Montgomery::ONE; + assert_eq!(p_min_1.inv(), p_min_1); + } + + #[test] + fn test_mul_scalar2_from_add() { + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar2(); + + let added = &x + &x; + + assert_eq!(multiplied, added); + } + } + + #[test] + fn test_mul_scalar2_from_mul() { + let two = &Montgomery::ONE + &Montgomery::ONE; + + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar2(); + + assert_eq!(multiplied, &x * &two); + } + } + + #[test] + fn test_mul_scalar3_from_add() { + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar3(); + + let mut added = x; + for _ in 0..2 { + added = &added + &x; + } + + assert_eq!(multiplied, added); + } + } + + #[test] + fn test_mul_scalar3_from_mul() { + let mut three = Montgomery::ONE; + for _ in 0..2 { + three = &three + &Montgomery::ONE; + } + + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar3(); + + assert_eq!(multiplied, &x * &three); + } + } + + #[test] + fn test_mul_scalar4_from_add() { + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar4(); + + let mut added = x; + for _ in 0..3 { + added = &added + &x; + } + + assert_eq!(multiplied, added); + } + } + + #[test] + fn test_mul_scalar4_from_mul() { + let mut four = Montgomery::ONE; + for _ in 0..3 { + four = &four + &Montgomery::ONE; + } + + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar4(); + + assert_eq!(multiplied, &x * &four); + } + } + + #[test] + fn test_mul_scalar8_from_add() { + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar8(); + + let mut added = x; + for _ in 0..7 { + added = &added + &x; + } + + assert_eq!(multiplied, added); + } + } + + #[test] + fn test_mul_scalar8_from_mul() { + let mut eight = Montgomery::ONE; + for _ in 0..7 { + eight = &eight + &Montgomery::ONE; + } + + for x in get_test_values() { + let mut multiplied = x; + multiplied.mul_scalar8(); + + assert_eq!(multiplied, &x * &eight); + } + } + + /** Comparison **/ + #[test] + fn test_is_zero() { + assert!(Montgomery::ZERO.is_zero_vartime()); + for x in get_nonzero_test_values() { + assert!(!x.is_zero_vartime()); + } + } + + /** Reduction of saturated limbs **/ + #[test] + fn test_reduced_carry_is_one() { + let mut x = Montgomery::ZERO; + x.reduce_carry(1); + assert_eq!(x.limbs, Montgomery::ONE.limbs); + } + + #[test] + fn test_reduce_carry_works_until_8() { + let mut reduced = Montgomery::ZERO; + for i in 0..8 { + let mut x = Montgomery::ZERO; + x.reduce_carry(i); + assert_eq!(x.limbs, reduced.limbs); + reduced = &reduced + &Montgomery::ONE; + } + } + + #[test] + fn test_reduce_no_carry_is_noop() { + for x in get_test_values() { + let mut y = x; + y.reduce_carry(0); + assert_eq!(y.limbs, x.limbs); + } + } + + #[test] + fn test_reduce_degree() { + // TODO: Add a meaningful test for this. + } +} diff --git a/libraries/crypto/src/ec/point.rs b/libraries/crypto/src/ec/point.rs new file mode 100644 index 0000000..d9a6a76 --- /dev/null +++ b/libraries/crypto/src/ec/point.rs @@ -0,0 +1,1034 @@ +// Copyright 2019 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. + +use super::exponent256::ExponentP256; +use super::gfp256::GFP256; +use super::int256::Int256; +use super::montgomery::Montgomery; +use core::ops::Add; +use subtle::{Choice, ConditionallySelectable, ConstantTimeEq}; + +// A point on the elliptic curve is represented by two field elements. +// The "direct" representation with GFP256 (integer modulo p) is used for serialization of public +// keys. +#[derive(Clone, Copy)] +pub struct PointP256 { + x: GFP256, + y: GFP256, +} + +impl PointP256 { + // The point at infinity. + // Although this point is not "valid" on the curve (as it doesn't have an order of N), it is + // useful for tests. + #[cfg(test)] + const INFINITY: PointP256 = PointP256 { + x: GFP256::ZERO, + y: GFP256::ZERO, + }; + + /** Serialization **/ + // This uses uncompressed point format from "SEC 1: Elliptic Curve Cryptography" ("Standards for + // Efficient Cryptography"). + #[cfg(feature = "std")] + pub fn from_bytes_uncompressed_vartime(bytes: &[u8]) -> Option { + if bytes.len() != 65 || bytes[0] != 0x04 { + None + } else { + PointP256::new_checked_vartime( + Int256::from_bin(array_ref![bytes, 1, 32]), + Int256::from_bin(array_ref![bytes, 33, 32]), + ) + } + } + + #[cfg(test)] + pub fn to_bytes_uncompressed(&self, bytes: &mut [u8; 65]) { + bytes[0] = 0x04; + self.x.to_int().to_bin(array_mut_ref![bytes, 1, 32]); + self.y.to_int().to_bin(array_mut_ref![bytes, 33, 32]); + } + + /** Constructors **/ + pub fn new_checked_vartime(x: Int256, y: Int256) -> Option { + let gfx = GFP256::from_int_checked(x)?; + let gfy = GFP256::from_int_checked(y)?; + if GFP256::is_valid_point_vartime(&gfx, &gfy) { + Some(PointP256 { x: gfx, y: gfy }) + } else { + None + } + } + + fn from_projective(point: &PointProjective) -> PointP256 { + PointP256::from_affine(&point.to_affine()) + } + + fn from_affine(affine: &PointAffine) -> PointP256 { + PointP256 { + x: affine.x.montgomery_to_field(), + y: affine.y.montgomery_to_field(), + } + } + + fn to_affine(&self) -> PointAffine { + PointAffine { + x: Montgomery::field_to_montgomery(&self.x), + y: Montgomery::field_to_montgomery(&self.y), + } + } + + /** Useful getters **/ + #[cfg(test)] + pub fn is_valid_vartime(&self) -> bool { + GFP256::is_valid_point_vartime(&self.x, &self.y) + } + + pub fn getx(self) -> GFP256 { + self.x + } + + pub fn gety(self) -> GFP256 { + self.y + } + + /** Arithmetic **/ + pub fn base_point_mul(n: &ExponentP256) -> PointP256 { + let point = PointProjective::scalar_base_mul(n); + PointP256::from_projective(&point) + } + + pub fn mul(&self, n: &ExponentP256) -> PointP256 { + let p = self.to_affine(); + let point = p.scalar_mul(n); + PointP256::from_projective(&point) + } + + // Computes n1*G + n2*self + #[cfg(feature = "std")] + pub fn points_mul(&self, n1: &ExponentP256, n2: &ExponentP256) -> PointP256 { + let p = self.to_affine(); + let p1 = PointProjective::scalar_base_mul(n1); + let p2 = p.scalar_mul(n2); + + let point = &p1 + &p2; + PointP256::from_projective(&point) + } +} + +// A point on the elliptic curve in projective form. +// This uses Montgomery representation for field elements. +// This is in projective coordinates, i.e. it represents the point { x: x / z, y: y / z }. +// This representation is more convenient to implement complete formulas for elliptic curve +// arithmetic. +#[derive(Clone, Copy)] +pub struct PointProjective { + x: Montgomery, + y: Montgomery, + z: Montgomery, +} + +impl ConditionallySelectable for PointProjective { + #[allow(clippy::many_single_char_names)] + fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self { + let x = Montgomery::conditional_select(&a.x, &b.x, choice); + let y = Montgomery::conditional_select(&a.y, &b.y, choice); + let z = Montgomery::conditional_select(&a.z, &b.z, choice); + Self { x, y, z } + } +} + +// Equivalent to PointProjective { x, y, z: 1 } +#[derive(Clone, Copy)] +pub struct PointAffine { + x: Montgomery, + y: Montgomery, +} + +impl PointProjective { + #[cfg(test)] + pub const INFINITY: PointProjective = PointProjective { + x: Montgomery::ZERO, + y: Montgomery::ONE, + z: Montgomery::ZERO, + }; + + /** Constructors **/ + pub fn from_affine(point: &PointAffine) -> PointProjective { + PointProjective { + x: point.x, + y: point.y, + z: Montgomery::ONE, + } + } + + #[cfg(test)] + // Construct a point in projective coordinates, with a given z value. + // This point is equivalent to { x, y, z: 1 } + pub fn from_affine_shuffled(point: &PointAffine, z: Montgomery) -> PointProjective { + PointProjective { + x: &point.x * &z, + y: &point.y * &z, + z, + } + } + + fn to_affine(&self) -> PointAffine { + let zinv = self.z.inv(); + let x = &self.x * &zinv; + let y = &self.y * &zinv; + PointAffine { x, y } + } + + /** Constant-time helpers **/ + fn select_point(table: &[PointProjective; 15], index: u32) -> PointProjective { + let mut point = PointProjective { + x: Montgomery::ZERO, + y: Montgomery::ZERO, + z: Montgomery::ZERO, + }; + + for i in 0..15 { + let choice = (i + 1).ct_eq(&index); + point.conditional_assign(&table[i as usize], choice); + } + + point + } + + /** Arithmetic **/ + // Complete formula from https://eprint.iacr.org/2015/1060.pdf, Algorithm 5. + fn add_mixed(&self, other: &PointAffine) -> PointProjective { + // Steps 1-2 (same as add). + let mut t0 = &self.x * &other.x; + let t1 = &self.y * &other.y; + let mut t2 = self.z; + + // Steps 3-7 (same as add). + let t3 = &self.x + &self.y; + let t4 = &other.x + &other.y; + let t3 = &t3 * &t4; + let t4 = &t0 + &t1; + let t3 = &t3 - &t4; + + // Steps 8-11 (add_mixed optimization). + let t4 = &other.y * &self.z; + let t4 = &t4 + &self.y; + let y = &other.x * &self.z; + let y = &y + &self.x; + + // Steps 12-17 (same as add). + let z = &Montgomery::B * &t2; + let mut x = &y - &z; + x.mul_scalar3(); // 14-15 + let z = &t1 - &x; + let x = &t1 + &x; + + // Steps 18-22 (same as add). + let y = &Montgomery::B * &y; + t2.mul_scalar3(); // 19-20 + let y = &y - &t2; + let mut y = &y - &t0; + + // Steps 23-27 (same as add). + y.mul_scalar3(); // 23-24 + t0.mul_scalar3(); // 25-26 + let t0 = &t0 - &t2; + + // Steps 28-36 (same as add). + let t1 = &t4 * &y; + let t2 = &t0 * &y; + let y = &x * &z; + let y = &y + &t2; + let x = &t3 * &x; + let x = &x - &t1; + let z = &t4 * &z; + let t1 = &t3 * &t0; + let z = &z + &t1; + + PointProjective { x, y, z } + } + + // Complete formula from https://eprint.iacr.org/2015/1060.pdf, Algorithm 6. + fn double(&self) -> PointProjective { + // Steps 1-3 (same as add). + let mut t0 = self.x.square(); + let t1 = self.y.square(); + let mut t2 = self.z.square(); + + // Steps 4-7. + let mut t3 = &self.x * &self.y; + t3.mul_scalar2(); + let mut z = &self.x * &self.z; + z.mul_scalar2(); + + // Steps 8-13 (same as add). + let y = &Montgomery::B * &t2; + let mut y = &y - &z; + y.mul_scalar3(); // 10-11 + let x = &t1 - &y; + let y = &t1 + &y; + + // Steps 14-15. + let y = &x * &y; + let x = &x * &t3; + + // Steps 16-20 (same as add). + t2.mul_scalar3(); // 16-17 + let z = &Montgomery::B * &z; + let z = &z - &t2; + let mut z = &z - &t0; + + // Steps 21-26 (same as add). + z.mul_scalar3(); // 21-22 + t0.mul_scalar3(); // 23-24 + let t0 = &t0 - &t2; + + // Steps 27-34. + let t0 = &t0 * &z; + let y = &y + &t0; + let mut t0 = &self.y * &self.z; + t0.mul_scalar2(); + let z = &t0 * &z; + let x = &x - &z; + let mut z = &t0 * &t1; + z.mul_scalar4(); // 33-34 + + PointProjective { x, y, z } + } + + // Compute scalar*G + fn scalar_base_mul(scalar: &ExponentP256) -> PointProjective { + let mut n = PointProjective { + x: Montgomery::ZERO, + y: Montgomery::ZERO, + z: Montgomery::ZERO, + }; + let mut choice_n_is_inf = Choice::from(1u8); + + for i in 0..32 { + if i != 0 { + n = n.double(); + } + + for table_offset in 0..2 { + let j = 32 * table_offset; + let bit0 = scalar.bit(31 - i + j); + let bit1 = scalar.bit(95 - i + j); + let bit2 = scalar.bit(159 - i + j); + let bit3 = scalar.bit(223 - i + j); + let index = bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3); + + let p = PointAffine::select_point(&Montgomery::PRECOMPUTED[table_offset], index); + let t = n.add_mixed(&p); + + n.conditional_assign(&PointProjective::from_affine(&p), choice_n_is_inf); + + let choice_p_is_inf = index.ct_eq(&0); + n.conditional_assign(&t, !(choice_p_is_inf | choice_n_is_inf)); + + choice_n_is_inf &= choice_p_is_inf; + } + } + + n + } + + // Complete formula from https://eprint.iacr.org/2015/1060.pdf, Algorithm 1. + #[cfg(test)] + fn add_complete_general(self, other: &PointProjective) -> PointProjective { + // Steps 1-3. + let t0 = &self.x * &other.x; + let t1 = &self.y * &other.y; + let t2 = &self.z * &other.z; + + // Steps 4-8. + let t3 = &self.x + &self.y; + let t4 = &other.x + &other.y; + let t3 = &t3 * &t4; + let t4 = &t0 + &t1; + let t3 = &t3 - &t4; + + // Steps 9-13. + let t4 = &self.x + &self.z; + let t5 = &other.x + &other.z; + let t4 = &t4 * &t5; + let t5 = &t0 + &t2; + let t4 = &t4 - &t5; + + // Steps 14-18. + let t5 = &self.y + &self.z; + let x = &other.y + &other.z; + let t5 = &t5 * &x; + let x = &t1 + &t2; + let t5 = &t5 - &x; + + // Steps 19-24. + let z = &Montgomery::A * &t4; + let x = &Montgomery::THREE_B * &t2; + let z = &x + &z; + let x = &t1 - &z; + let z = &t1 + &z; + let y = &x * &z; + + // Steps 25-34. + let t1 = &t0 + &t0; + let t1 = &t1 + &t0; + let t2 = &Montgomery::A * &t2; + let t4 = &Montgomery::THREE_B * &t4; + let t1 = &t1 + &t2; + let t2 = &t0 - &t2; + let t2 = &Montgomery::A * &t2; + let t4 = &t4 + &t2; + let t0 = &t1 * &t4; + let y = &y + &t0; + + // Steps 35-37. + let t0 = &t5 * &t4; + let x = &t3 * &x; + let x = &x - &t0; + + // Steps 38-40. + let t0 = &t3 * &t1; + let z = &t5 * &z; + let z = &z + &t0; + + PointProjective { x, y, z } + } +} + +impl PointAffine { + /** Constant-time helpers **/ + fn select_point(table: &[[Montgomery; 2]; 15], index: u32) -> PointAffine { + let mut x = Montgomery::ZERO; + let mut y = Montgomery::ZERO; + + for i in 0..15 { + let choice = (i + 1).ct_eq(&index); + x.conditional_assign(&table[i as usize][0], choice); + y.conditional_assign(&table[i as usize][1], choice); + } + + PointAffine { x, y } + } + + /** Arithmetic **/ + fn scalar_mul(&self, scalar: &ExponentP256) -> PointProjective { + let mut precomp = [PointProjective { + x: Montgomery::ZERO, + y: Montgomery::ZERO, + z: Montgomery::ZERO, + }; 15]; + + precomp[0] = PointProjective::from_affine(self); + + for i in (1..15).step_by(2) { + precomp[i] = precomp[i >> 1].double(); + precomp[i + 1] = precomp[i].add_mixed(self); + } + + let mut n = PointProjective { + x: Montgomery::ZERO, + y: Montgomery::ZERO, + z: Montgomery::ZERO, + }; + let mut choice_n_is_inf = Choice::from(1u8); + + for i in (0..256).step_by(4) { + if i != 0 { + n = n.double(); + n = n.double(); + n = n.double(); + n = n.double(); + } + let index = scalar.bit(255 - i) << 3 + | scalar.bit(255 - i - 1) << 2 + | scalar.bit(255 - i - 2) << 1 + | scalar.bit(255 - i - 3); + + let p = PointProjective::select_point(&precomp, index); + let t = n.add(&p); + + n.conditional_assign(&p, choice_n_is_inf); + + let choice_p_is_inf = index.ct_eq(&0); + n.conditional_assign(&t, !(choice_p_is_inf | choice_n_is_inf)); + + choice_n_is_inf &= choice_p_is_inf; + } + + n + } +} + +/** Arithmetic operators **/ +#[allow(clippy::suspicious_arithmetic_impl)] +impl Add for &PointProjective { + type Output = PointProjective; + + // Complete formula from https://eprint.iacr.org/2015/1060.pdf, Algorithm 4. + fn add(self, other: &PointProjective) -> PointProjective { + // Steps 1-3. + let mut t0 = &self.x * &other.x; + let t1 = &self.y * &other.y; + let mut t2 = &self.z * &other.z; + + // Steps 4-8. + let t3 = &self.x + &self.y; + let t4 = &other.x + &other.y; + let t3 = &t3 * &t4; + let t4 = &t0 + &t1; + let t3 = &t3 - &t4; + + // Steps 9-13. + let t4 = &self.y + &self.z; + let x = &other.y + &other.z; + let t4 = &t4 * &x; + let x = &t1 + &t2; + let t4 = &t4 - &x; + + // Steps 14-18. + let x = &self.x + &self.z; + let y = &other.x + &other.z; + let x = &x * &y; + let y = &t0 + &t2; + let y = &x - &y; + + // Steps 19-24. + let z = &Montgomery::B * &t2; + let mut x = &y - &z; + x.mul_scalar3(); // 21-22 + let z = &t1 - &x; + let x = &t1 + &x; + + // Steps 25-29. + let y = &Montgomery::B * &y; + t2.mul_scalar3(); // 26-27 + let y = &y - &t2; + let mut y = &y - &t0; + + // Steps 30-34. + y.mul_scalar3(); // 30-31 + t0.mul_scalar3(); // 32-33 + let t0 = &t0 - &t2; + + // Steps 35-43. + let t1 = &t4 * &y; + let t2 = &t0 * &y; + let y = &x * &z; + let y = &y + &t2; + let x = &t3 * &x; + let x = &x - &t1; + let z = &t4 * &z; + let t1 = &t3 * &t0; + let z = &z + &t1; + + PointProjective { x, y, z } + } +} + +#[cfg(feature = "derive_debug")] +impl core::fmt::Debug for PointP256 { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("PointP256") + .field("x", &self.x) + .field("y", &self.y) + .finish() + } +} + +#[cfg(feature = "derive_debug")] +impl PartialEq for PointP256 { + fn eq(&self, other: &PointP256) -> bool { + self.x == other.x && self.y == other.y + } +} + +#[cfg(test)] +pub mod test { + use super::*; + + impl PartialEq for PointAffine { + fn eq(&self, other: &PointAffine) -> bool { + self.x == other.x && self.y == other.y + } + } + + impl core::fmt::Debug for PointAffine { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("PointAffine") + .field("x", &self.x) + .field("y", &self.y) + .finish() + } + } + + impl PartialEq for PointProjective { + fn eq(&self, other: &PointProjective) -> bool { + self.to_affine() == other.to_affine() + } + } + + impl core::fmt::Debug for PointProjective { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + f.debug_struct("PointProjective") + .field("x", &self.x) + .field("y", &self.y) + .field("z", &self.z) + .finish() + } + } + + pub fn precomputed(i: usize, j: usize) -> PointAffine { + PointAffine { + x: Montgomery::PRECOMPUTED[i][j][0], + y: Montgomery::PRECOMPUTED[i][j][1], + } + } + + fn get_test_values_affine() -> Vec { + let mut values = Vec::new(); + for table in 0..2 { + for index in 0..15 { + values.push(precomputed(table, index)); + } + } + values + } + + fn get_test_values_projective() -> Vec { + let mut values: Vec<_> = get_test_values_affine() + .iter() + .map(|p| PointProjective::from_affine(p)) + .collect(); + values.push(PointProjective::INFINITY); + values + } + + fn get_test_values() -> Vec { + get_test_values_affine() + .iter() + .map(|p| PointP256::from_affine(p)) + .collect() + } + + /** Serialization **/ + #[test] + fn test_to_bytes_from_bytes() { + for &x in &get_test_values() { + let mut buf = [Default::default(); 65]; + x.to_bytes_uncompressed(&mut buf); + assert_eq!(PointP256::from_bytes_uncompressed_vartime(&buf), Some(x)); + } + } + + #[test] + fn test_from_bytes_infinity_is_invalid() { + let mut buf = [0; 65]; + buf[0] = 0x04; + assert_eq!(PointP256::from_bytes_uncompressed_vartime(&buf), None); + } + + /** Conversion between point types **/ + #[test] + fn test_convert_p256_affine() { + for x in &get_test_values_affine() { + assert_eq!(PointP256::from_affine(x).to_affine(), *x); + } + } + + #[test] + fn test_convert_projective_affine() { + for x in &get_test_values_affine() { + assert_eq!(PointProjective::from_affine(x).to_affine(), *x); + } + } + + #[test] + fn test_projective_shuffle() { + for x in &get_test_values_affine() { + for &shuffle in &super::super::montgomery::test::get_nonzero_test_values() { + assert_eq!( + PointProjective::from_affine_shuffled(x, shuffle).to_affine(), + *x + ); + } + } + } + + /** Point validation **/ + // Edge cases generated with the following Sage script. + // + // ``` + // k = GF(2^256 - 2^224 + 2^192 + 2^96 - 1, 't'); + // R = PolynomialRing(k, 'u'); + // u = R.gen() + // b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + // + // def print_point(x, y): + // print "x = 0x%x" % x + // print "y = 0x%x" % y + // print "x^3 - 3*x + b = 0x%x" % (x^3 - 3*x + b) + // print "y^2 = 0x%x" % y^2 + // + // def find_point_at_x(x): + // f = x^3 - 3*x + b - u^2 + // r = f.roots() + // if len(r) > 0: + // y = r[0][0] + // print_point(x, y) + // + // def find_point_at_y(y): + // f = u^3 - 3*u + b - y^2 + // r = f.roots() + // if len(r) > 0: + // x = r[0][0] + // print_point(x, y) + // + // ITERATIONS = 16 + // + // print "*" * 40 + // print "Small x" + // print "*" * 40 + // for i in range(ITERATIONS): + // x = k(i) + // find_point_at_x(x) + // + // print "*" * 40 + // print "Small y" + // print "*" * 40 + // for i in range(ITERATIONS): + // y = k(i) + // find_point_at_y(y) + // + // print "*" * 40 + // print "High-weight x" + // print "*" * 40 + // for i in range(ITERATIONS): + // x = k(2^255 - 1 - 2^i) + // find_point_at_x(x) + // + // print "*" * 40 + // print "High-weight y" + // print "*" * 40 + // for i in range(ITERATIONS): + // y = k(2^255 - 1 - 2^i) + // find_point_at_y(y) + // ``` + #[rustfmt::skip] + const POINTS_SMALL_X: &[[[u32; 8]; 2]] = &[ +[ + [0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], + [0xcdb70433, 0xccbea3f7, 0x9b265c3a, 0xee35afc4, 0x667e8521, 0x016ec431, 0x55a7e7fa, 0xba6dbc45], +], +[ + [0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], + [0x7d7ddc34, 0xddf2aed7, 0xf0183f16, 0x232efd48, 0xcc8dffb8, 0xb9967a1a, 0xabdaf53e, 0xc94db3d2], +], +[ + [0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], + [0x636041b3, 0x2242d085, 0xd631ff69, 0x27249b16, 0x3f37f6a6, 0xd624d1d2, 0xca290db0, 0xb706288a], +], +[ + [0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], + [0x8fe7b297, 0xdb1812e4, 0x3c63a432, 0xfbc52276, 0xd33315cb, 0xcaaa94f7, 0x2caf2e23, 0x8e14e843], +], +[ + [0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], + [0xb2b74387, 0x6abbc3b4, 0x9de5be82, 0xc726c883, 0x6c4b6500, 0xc653e363, 0xcb0680c1, 0x93fbd29a], +], + ]; + #[rustfmt::skip] + const POINTS_SMALL_Y: &[[[u32; 8]; 2]] = &[ +[ + [0x0069d2c7, 0x875d877f, 0x7b70f611, 0x6375e8a9, 0x95dbac0d, 0x10db6dd0, 0xab9c6e9e, 0x8d0177eb], + [0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], +], +[ + [0x7607ce12, 0xc9fe1bd7, 0x8b283fbb, 0x53eb03e0, 0xddcaac96, 0xa62f56d3, 0xc6825c8a, 0xcfe9c22c], + [0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], +], +[ + [0xde8de1d7, 0xb176f692, 0x841022ca, 0x4cffaf35, 0xeb345f84, 0x0a92738c, 0x46cd60d8, 0xd7325d76], + [0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], +], +[ + [0x87914a78, 0x077d5a71, 0x8e3dc5b2, 0x979131e2, 0x97d7ab3f, 0x731dbdaf, 0x1da31d68, 0x9b21c2de], + [0x00000006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], +], +[ + [0xd56ac453, 0xd7acceae, 0xc6693e4f, 0xcffa296d, 0xe4df51fc, 0x564d94b7, 0xbc9f7da8, 0xb2ed6eac], + [0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000], +], + ]; + #[rustfmt::skip] + const POINTS_HIGH_WEIGHT: &[[[u32; 8]; 2]] = &[ +// High-weight x coordinate. +[ + [0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefffffff], + [0xf0e94c90, 0x722ff8d6, 0x66ebf289, 0x9b17896c, 0x334f0e43, 0xc4e1c5d1, 0x1ea63e81, 0xa120f8da], +], +[ + [0xfffffffd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefffffff], + [0x5ad8aa4b, 0x717d6de4, 0x2af77820, 0x04ce8429, 0xefb80898, 0xd004a68e, 0xe4b30001, 0x887ce5d3], +], +// High-weight y coordinate. +[ + [0x98619b11, 0xae2e447c, 0x02bcee26, 0x1fcb1b9b, 0xed3ee2d9, 0xefb6ff97, 0x77ee5948, 0xe063d049], + [0xfffffffd, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefffffff], +], +[ + [0xcaf4e99c, 0x494eac75, 0x3237de43, 0x695ba4d4, 0x68339d6f, 0xbca064f3, 0x4910c02a, 0xaefca662], + [0xfffffffb, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xefffffff], +], + ]; + + #[test] + fn test_zero_x_point() { + // Even though this point verifies the equation y^2 = x^3 - 3x + b, none of the (x, y) + // coordinates is allowed to be zero. + #[rustfmt::skip] + let x = Int256::new( + [0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000] + ); + #[rustfmt::skip] + let y = Int256::new( + [0xe8b06c0b, 0xd7407a95, 0xe25178e8, 0xabe3d50d, 0x7b5f9449, 0xdbcc42a2, 0xf1d07c29, 0x99b7a386] + ); + assert!(PointP256::new_checked_vartime(x, y).is_none()); + } + + #[test] + fn test_small_x_points() { + for p in POINTS_SMALL_X { + let x = Int256::new(p[0]); + let y = Int256::new(p[1]); + // These points are valid. + assert!(PointP256::new_checked_vartime(x, y).is_some()); + // Adding p to the x coordinate doesn't invalidate the equation y^2 = x^3 - 3x + b (as + // we work in GF(p)), however the coordinates must be serialized in a canonical form + // modulo p. + assert!(PointP256::new_checked_vartime((&x + &Int256::P).0, y).is_none()); + } + } + + #[test] + fn test_small_y_points() { + for p in POINTS_SMALL_Y { + let x = Int256::new(p[0]); + let y = Int256::new(p[1]); + // These points are valid. + assert!(PointP256::new_checked_vartime(x, y).is_some()); + // Adding p to the y coordinate doesn't invalidate the equation y^2 = x^3 - 3x + b (as + // we work in GF(p)), however the coordinates must be serialized in a canonical form + // modulo p. + assert!(PointP256::new_checked_vartime(x, (&y + &Int256::P).0).is_none()); + } + } + + #[test] + fn test_high_weight_points() { + // These points are all valid, with one coordinate of high Hamming weight. This is a sanity + // check that arithmetic works on such high weight values. + for p in POINTS_HIGH_WEIGHT { + let x = Int256::new(p[0]); + let y = Int256::new(p[1]); + assert!(PointP256::new_checked_vartime(x, y).is_some()); + } + } + + #[test] + fn test_infinity_is_invalid() { + assert!(PointP256::new_checked_vartime( + PointP256::INFINITY.x.to_int(), + PointP256::INFINITY.y.to_int() + ) + .is_none()); + } + + /** Constant-time helpers **/ + #[test] + fn test_select_point_projective() { + let mut table = Vec::new(); + for i in 0..15 { + table.push(PointProjective::from_affine(&precomputed(0, i))); + } + + assert_eq!( + PointProjective::select_point(array_ref![table, 0, 15], 0), + PointProjective { + x: Montgomery::ZERO, + y: Montgomery::ZERO, + z: Montgomery::ZERO, + } + ); + for index in 1..16 { + assert_eq!( + PointProjective::select_point(array_ref![table, 0, 15], index as u32), + table[index - 1] + ); + } + } + + #[test] + fn test_select_point_affine() { + let table = &Montgomery::PRECOMPUTED[0]; + + assert_eq!( + PointAffine::select_point(table, 0), + PointAffine { + x: Montgomery::ZERO, + y: Montgomery::ZERO, + } + ); + for index in 1..16 { + assert_eq!( + PointAffine::select_point(table, index as u32), + precomputed(0, index - 1) + ); + } + } + + /** Arithmetic operators **/ + #[test] + fn test_add_is_add_complete_general() { + for x in &get_test_values_projective() { + for y in &get_test_values_projective() { + let left = x.add_complete_general(y); + let right = x + y; + assert_eq!(left, right); + } + } + } + + #[test] + fn test_add_is_associative() { + for x in &get_test_values_projective() { + for y in &get_test_values_projective() { + for z in &get_test_values_projective() { + // (x + y) + z + let left = &(x + y) + z; + // x + (y + z) + let right = x + &(y + z); + assert_eq!(left, right); + } + } + } + } + + #[test] + fn test_add_is_commutative() { + for x in &get_test_values_projective() { + for y in &get_test_values_projective() { + assert_eq!(x + y, y + x); + } + } + } + + #[test] + fn test_add_mixed() { + for x in &get_test_values_projective() { + for y in &get_test_values_affine() { + assert_eq!(x.add_mixed(y), x + &PointProjective::from_affine(y)); + } + } + } + + #[test] + fn test_double() { + for x in &get_test_values_projective() { + println!("doubling {:?}", x); + assert_eq!(x.double(), x + x); + } + } + + #[test] + fn test_add_infinity() { + for &x in &get_test_values_projective() { + assert_eq!(&x + &PointProjective::INFINITY, x); + } + } + + #[test] + fn test_add_mixed_infinity() { + for x in &get_test_values_affine() { + assert_eq!( + PointProjective::INFINITY.add_mixed(x), + PointProjective::from_affine(x) + ); + } + } + + #[test] + fn test_double_infinity() { + assert_eq!( + PointProjective::INFINITY.double(), + PointProjective::INFINITY + ); + } + + #[test] + fn test_generator_is_valid_point() { + let gen = precomputed(0, 0); + assert!(PointP256::from_affine(&gen).is_valid_vartime()); + } + + #[test] + fn test_generator_has_correct_order() { + let gen = precomputed(0, 0); + // Normally the ExponentP256 type guarantees that its values stay in [0, N[ because N is + // the curve order and therefore exponents >= N are equivalent to their reduction modulo N. + // In this test we check that N is indeed the curve order and therefore we need an unsafe + // block to construct an exponent of N. + let order = unsafe { ExponentP256::from_int_unchecked(Int256::N) }; + assert_eq!( + PointP256::from_projective(&gen.scalar_mul(&order)), + PointP256::INFINITY + ); + } + + #[test] + fn test_scalar_base_mul_is_scalar_mul_generator() { + let gen = precomputed(0, 0); + // TODO: more scalars + for scalar in &super::super::exponent256::test::get_test_values() { + assert_eq!( + PointProjective::scalar_base_mul(scalar), + gen.scalar_mul(scalar) + ); + } + } + + #[test] + fn test_base_point_mul_is_mul_generator() { + let gen = precomputed(0, 0); + // TODO: more scalars + for scalar in &super::super::exponent256::test::get_test_values() { + assert_eq!( + PointP256::base_point_mul(scalar), + PointP256::from_affine(&gen).mul(scalar) + ); + } + } + + // Helper function to compute the point 2^power * p. + pub fn power_of_two(mut p: PointProjective, power: usize) -> PointProjective { + for _ in 0..power { + p = p.double(); + } + p + } + + // TODO: more tests +} diff --git a/libraries/crypto/src/ec/precomputed.rs b/libraries/crypto/src/ec/precomputed.rs new file mode 100644 index 0000000..809fad6 --- /dev/null +++ b/libraries/crypto/src/ec/precomputed.rs @@ -0,0 +1,324 @@ +// Copyright 2019 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. + +use super::montgomery::{Montgomery, NLIMBS}; + +pub const PRECOMPUTED: [[[Montgomery; 2]; 15]; 2] = [ + [ + [ + Montgomery::new(PRECOMPUTED_LIMBS[0]), + Montgomery::new(PRECOMPUTED_LIMBS[1]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[2]), + Montgomery::new(PRECOMPUTED_LIMBS[3]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[4]), + Montgomery::new(PRECOMPUTED_LIMBS[5]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[6]), + Montgomery::new(PRECOMPUTED_LIMBS[7]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[8]), + Montgomery::new(PRECOMPUTED_LIMBS[9]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[10]), + Montgomery::new(PRECOMPUTED_LIMBS[11]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[12]), + Montgomery::new(PRECOMPUTED_LIMBS[13]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[14]), + Montgomery::new(PRECOMPUTED_LIMBS[15]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[16]), + Montgomery::new(PRECOMPUTED_LIMBS[17]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[18]), + Montgomery::new(PRECOMPUTED_LIMBS[19]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[20]), + Montgomery::new(PRECOMPUTED_LIMBS[21]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[22]), + Montgomery::new(PRECOMPUTED_LIMBS[23]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[24]), + Montgomery::new(PRECOMPUTED_LIMBS[25]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[26]), + Montgomery::new(PRECOMPUTED_LIMBS[27]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[28]), + Montgomery::new(PRECOMPUTED_LIMBS[29]), + ], + ], + [ + [ + Montgomery::new(PRECOMPUTED_LIMBS[30]), + Montgomery::new(PRECOMPUTED_LIMBS[31]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[32]), + Montgomery::new(PRECOMPUTED_LIMBS[33]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[34]), + Montgomery::new(PRECOMPUTED_LIMBS[35]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[36]), + Montgomery::new(PRECOMPUTED_LIMBS[37]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[38]), + Montgomery::new(PRECOMPUTED_LIMBS[39]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[40]), + Montgomery::new(PRECOMPUTED_LIMBS[41]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[42]), + Montgomery::new(PRECOMPUTED_LIMBS[43]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[44]), + Montgomery::new(PRECOMPUTED_LIMBS[45]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[46]), + Montgomery::new(PRECOMPUTED_LIMBS[47]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[48]), + Montgomery::new(PRECOMPUTED_LIMBS[49]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[50]), + Montgomery::new(PRECOMPUTED_LIMBS[51]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[52]), + Montgomery::new(PRECOMPUTED_LIMBS[53]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[54]), + Montgomery::new(PRECOMPUTED_LIMBS[55]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[56]), + Montgomery::new(PRECOMPUTED_LIMBS[57]), + ], + [ + Montgomery::new(PRECOMPUTED_LIMBS[58]), + Montgomery::new(PRECOMPUTED_LIMBS[59]), + ], + ], +]; + +#[rustfmt::skip] +#[allow(clippy::unreadable_literal)] +const PRECOMPUTED_LIMBS: [[u32; NLIMBS]; 60] = [ +[0x11522878, 0x0e730d41, 0x0db60179, 0x04afe2ff, 0x12883add, 0x0caddd88, 0x119e7edc, 0x0d4a6eab, 0x03120bee], +[0x1d2aac15, 0x0f25357c, 0x19e45cdd, 0x05c721d0, 0x1992c5a5, 0x0a237487, 0x0154ba21, 0x014b10bb, 0x00ae3fe3], +[0x0d41a576, 0x0922fc51, 0x0234994f, 0x060b60d3, 0x164586ae, 0x0ce95f18, 0x1fe49073, 0x03fa36cc, 0x05ebcd2c], +[0x0b402f2f, 0x015c70bf, 0x1561925c, 0x05a26704, 0x0da91e90, 0x0cdc1c7f, 0x1ea12446, 0x0e1ade1e, 0x0ec91f22], +[0x026f7778, 0x0566847e, 0x0a0bec9e, 0x0234f453, 0x1a31f21a, 0x0d85e75c, 0x056c7109, 0x0a267a00, 0x0b57c050], +[0x0098fb57, 0x0aa837cc, 0x060c0792, 0x0cfa5e19, 0x061bab9e, 0x0589e39b, 0x00a324c5, 0x07d6dee7, 0x02976e4b], +[0x1fc4124a, 0x0a8c244b, 0x1ce86762, 0x0cd61c7e, 0x1831c8e0, 0x075774e1, 0x1d96a5a9, 0x0843a649, 0x0c3ab0fa], +[0x06e2e7d5, 0x07673a2a, 0x178b65e8, 0x04003e9b, 0x1a1f11c2, 0x007816ea, 0x0f643e11, 0x058c43df, 0x0f423fc2], +[0x19633ffa, 0x0891f2b2, 0x123c231c, 0x046add8c, 0x054700dd, 0x059e2b17, 0x172db40f, 0x083e277d, 0x0b0dd609], +[0x0fd1da12, 0x035c6e52, 0x19ede20c, 0x0d19e0c0, 0x097d0f40, 0x0b015b19, 0x0449e3f5, 0x00e10c9e, 0x033ab581], +[0x056a67ab, 0x0577734d, 0x1dddc062, 0x0c57b10d, 0x0149b39d, 0x026a9e7b, 0x0c35df9f, 0x048764cd, 0x076dbcca], +[0x0ca4b366, 0x0e9303ab, 0x1a7480e7, 0x057e9e81, 0x1e13eb50, 0x0f466cf3, 0x06f16b20, 0x04ba3173, 0x0c168c33], +[0x15cb5439, 0x06a38e11, 0x073658bd, 0x0b29564f, 0x03f6dc5b, 0x0053b97e, 0x1322c4c0, 0x065dd7ff, 0x03a1e4f6], +[0x14e614aa, 0x09246317, 0x1bc83aca, 0x0ad97eed, 0x0d38ce4a, 0x0f82b006, 0x0341f077, 0x0a6add89, 0x04894acd], +[0x09f162d5, 0x0f8410ef, 0x1b266a56, 0x00d7f223, 0x03e0cb92, 0x0e39b672, 0x06a2901a, 0x069a8556, 0x0007e7c0], +[0x09b7d8d3, 0x00309a80, 0x1ad05f7f, 0x0c2fb5dd, 0x0cbfd41d, 0x09ceb638, 0x1051825c, 0x0da0cf5b, 0x0812e881], +[0x06f35669, 0x06a56f2c, 0x1df8d184, 0x00345820, 0x1477d477, 0x01645db1, 0x0be80c51, 0x0c22be3e, 0x0e35e65a], +[0x1aeb7aa0, 0x0c375315, 0x0f67bc99, 0x07fdd7b9, 0x191fc1be, 0x0061235d, 0x02c184e9, 0x01c5a839, 0x047a1e26], +[0x0b7cb456, 0x093e225d, 0x14f3c6ed, 0x0ccc1ac9, 0x17fe37f3, 0x04988989, 0x1a90c502, 0x02f32042, 0x0a17769b], +[0x0afd8c7c, 0x08191c6e, 0x1dcdb237, 0x016200c0, 0x107b32a1, 0x066c08db, 0x10d06a02, 0x0003fc93, 0x05620023], +[0x16722b27, 0x068b5c59, 0x0270fcfc, 0x0fad0ecc, 0x0e5de1c2, 0x0eab466b, 0x02fc513c, 0x0407f75c, 0x0baab133], +[0x09705fe9, 0x0b88b8e7, 0x0734c993, 0x01e1ff8f, 0x19156970, 0x0abd0f00, 0x10469ea7, 0x03293ac0, 0x0cdc98aa], +[0x01d843fd, 0x0e14bfe8, 0x15be825f, 0x008b5212, 0x0eb3fb67, 0x081cbd29, 0x0bc62f16, 0x02b6fcc7, 0x0f5a4e29], +[0x13560b66, 0x0c0b6ac2, 0x051ae690, 0x0d41e271, 0x0f3e9bd4, 0x01d70aab, 0x01029f72, 0x073e1c35, 0x0ee70fbc], +[0x0ad81baf, 0x09ecc49a, 0x086c741e, 0x0fe6be30, 0x176752e7, 0x0023d416, 0x1f83de85, 0x027de188, 0x066f70b8], +[0x181cd51f, 0x096b6e4c, 0x188f2335, 0x0a5df759, 0x17a77eb6, 0x0feb0e73, 0x154ae914, 0x02f3ec51, 0x03826b59], +[0x0b91f17d, 0x01c72949, 0x1362bf0a, 0x0e23fddf, 0x0a5614b0, 0x000f7d8f, 0x00079061, 0x0823d9d2, 0x08213f39], +[0x1128ae0b, 0x0d095d05, 0x0b85c0c2, 0x01ecb2ef, 0x024ddc84, 0x0e35e901, 0x18411a4a, 0x0f5ddc3d, 0x03786689], +[0x052260e8, 0x05ae3564, 0x0542b10d, 0x08d93a45, 0x19952aa4, 0x0996cc41, 0x1051a729, 0x04be3499, 0x052b23aa], +[0x109f307e, 0x06f5b6bb, 0x1f84e1e7, 0x077a0cfa, 0x10c4df3f, 0x025a02ea, 0x0b048035, 0x0e31de66, 0x0c6ecaa3], +[0x028ea335, 0x02886024, 0x1372f020, 0x00f55d35, 0x15e4684c, 0x0f2a9e17, 0x1a4a7529, 0x0cb7beb1, 0x0b2a78a1], +[0x1ab21f1f, 0x06361ccf, 0x06c9179d, 0x0b135627, 0x1267b974, 0x04408bad, 0x1cbff658, 0x0e3d6511, 0x00c7d76f], +[0x01cc7a69, 0x0e7ee31b, 0x054fab4f, 0x002b914f, 0x1ad27a30, 0x0cd3579e, 0x0c50124c, 0x050daa90, 0x00b13f72], +[0x0b06aa75, 0x070f5cc6, 0x1649e5aa, 0x084a5312, 0x0329043c, 0x041c4011, 0x13d32411, 0x0b04a838, 0x0d760d2d], +[0x1713b532, 0x0baa0c03, 0x084022ab, 0x06bcf5c1, 0x02f45379, 0x018ae070, 0x18c9e11e, 0x020bca9a, 0x066f496b], +[0x03eef294, 0x067500d2, 0x0d7f613c, 0x002dbbeb, 0x0b741038, 0x0e04133f, 0x1582968d, 0x0be985f7, 0x01acbc1a], +[0x1a6a939f, 0x033e50f6, 0x0d665ed4, 0x0b4b7bd6, 0x1e5a3799, 0x06b33847, 0x17fa56ff, 0x065ef930, 0x0021dc4a], +[0x02b37659, 0x0450fe17, 0x0b357b65, 0x0df5efac, 0x15397bef, 0x09d35a7f, 0x112ac15f, 0x0624e62e, 0x0a90ae2f], +[0x107eecd2, 0x01f69bbe, 0x077d6bce, 0x05741394, 0x13c684fc, 0x0950c910, 0x0725522b, 0x0dc78583, 0x040eeabb], +[0x1fde328a, 0x0bd61d96, 0x0d28c387, 0x09e77d89, 0x12550c40, 0x0759cb7d, 0x0367ef34, 0x0ae2a960, 0x091b8bdc], +[0x093462a9, 0x00f469ef, 0x0b2e9aef, 0x0d2ca771, 0x054e1f42, 0x007aaa49, 0x06316abb, 0x02413c8e, 0x05425bf9], +[0x1bed3e3a, 0x0f272274, 0x1f5e7326, 0x06416517, 0x0ea27072, 0x09cedea7, 0x006e7633, 0x07c91952, 0x0d806dce], +[0x08e2a7e1, 0x0e421e1a, 0x0418c9e1, 0x01dbc890, 0x1b395c36, 0x0a1dc175, 0x1dc4ef73, 0x08956f34, 0x0e4b5cf2], +[0x1b0d3a18, 0x03194a36, 0x06c2641f, 0x0e44124c, 0x0a2f4eaa, 0x0a8c25ba, 0x0f927ed7, 0x0627b614, 0x07371cca], +[0x0ba16694, 0x0417bc03, 0x07c0a7e3, 0x09c35c19, 0x1168a205, 0x08b6b00d, 0x10e3edc9, 0x09c19bf2, 0x05882229], +[0x1b2b4162, 0x0a5cef1a, 0x1543622b, 0x09bd433e, 0x0364e04d, 0x07480792, 0x05c9b5b3, 0x0e85ff25, 0x0408ef57], +[0x1814cfa4, 0x0121b41b, 0x0d248a0f, 0x03b05222, 0x039bb16a, 0x0c75966d, 0x0a038113, 0x0a4a1769, 0x011fbc6c], +[0x0917e50e, 0x0eec3da8, 0x169d6eac, 0x010c1699, 0x0a416153, 0x0f724912, 0x15cd60b7, 0x04acbad9, 0x05efc5fa], +[0x0f150ed7, 0x00122b51, 0x1104b40a, 0x0cb7f442, 0x0fbb28ff, 0x06ac53ca, 0x196142cc, 0x07bf0fa9, 0x00957651], +[0x04e0f215, 0x0ed439f8, 0x03f46bd5, 0x05ace82f, 0x110916b6, 0x006db078, 0x0ffd7d57, 0x0f2ecaac, 0x0ca86dec], +[0x15d6b2da, 0x0965ecc9, 0x1c92b4c2, 0x001f3811, 0x1cb080f5, 0x02d8b804, 0x19d1c12d, 0x0f20bd46, 0x01951fa7], +[0x0a3656c3, 0x0523a425, 0x0fcd0692, 0x0d44ddc8, 0x131f0f5b, 0x0af80e4a, 0x0cd9fc74, 0x099bb618, 0x02db944c], +[0x0a673090, 0x01c210e1, 0x178c8d23, 0x01474383, 0x10b8743d, 0x0985a55b, 0x02e74779, 0x00576138, 0x09587927], +[0x133130fa, 0x0be05516, 0x09f4d619, 0x0bb62570, 0x099ec591, 0x0d9468fe, 0x1d07782d, 0x0fc72e0b, 0x0701b298], +[0x1863863b, 0x085954b8, 0x121a0c36, 0x09e7fedf, 0x0f64b429, 0x09b9d71e, 0x14e2f5d8, 0x0f858d3a, 0x0942eea8], +[0x0da5b765, 0x06edafff, 0x0a9d18cc, 0x0c65e4ba, 0x1c747e86, 0x0e4ea915, 0x1981d7a1, 0x08395659, 0x052ed4e2], +[0x087d43b7, 0x037ab11b, 0x19d292ce, 0x0f8d4692, 0x18c3053f, 0x08863e13, 0x04c146c0, 0x06bdf55a, 0x04e4457d], +[0x16152289, 0x0ac78ec2, 0x1a59c5a2, 0x02028b97, 0x071c2d01, 0x0295851f, 0x0404747b, 0x0878558d, 0x07d29aa4], +[0x13d8341f, 0x08daefd7, 0x139c972d, 0x06b7ea75, 0x0d4a9dde, 0x0ff163d8, 0x081d55d7, 0x0a5bef68, 0x0b7b30d8], +[0x0be73d6f, 0x0aa88141, 0x0d976c81, 0x07e7a9cc, 0x18beb771, 0x0d773cbd, 0x13f51951, 0x09d0c177, 0x01c49a78], +]; + +#[cfg(test)] +mod test { + use super::super::montgomery::{BOTTOM_28_BITS, BOTTOM_29_BITS}; + use super::super::point::test::{power_of_two, precomputed}; + use super::super::point::PointProjective; + use super::*; + + #[test] + fn test_precomputed_bits() { + for x in PRECOMPUTED_LIMBS.iter() { + for (i, &limb) in x.iter().enumerate() { + if i & 1 == 0 { + assert_eq!(limb & BOTTOM_29_BITS, limb); + } else { + assert_eq!(limb & BOTTOM_28_BITS, limb); + } + } + } + } + + #[test] + fn test_precomputed_powers_of_g_are_correct() { + let gen = PointProjective::from_affine(&precomputed(0, 0)); + let g32 = power_of_two(gen, 32); + let g64 = power_of_two(gen, 64); + let g96 = power_of_two(gen, 96); + let g128 = power_of_two(gen, 128); + let g160 = power_of_two(gen, 160); + let g192 = power_of_two(gen, 192); + let g224 = power_of_two(gen, 224); + + assert_eq!( + PointProjective::from_affine(&precomputed(0, 0b0001 - 1)), + gen + ); + assert_eq!( + PointProjective::from_affine(&precomputed(0, 0b0010 - 1)), + g64 + ); + assert_eq!( + PointProjective::from_affine(&precomputed(0, 0b0100 - 1)), + g128 + ); + assert_eq!( + PointProjective::from_affine(&precomputed(0, 0b1000 - 1)), + g192 + ); + assert_eq!( + PointProjective::from_affine(&precomputed(1, 0b0001 - 1)), + g32 + ); + assert_eq!( + PointProjective::from_affine(&precomputed(1, 0b0010 - 1)), + g96 + ); + assert_eq!( + PointProjective::from_affine(&precomputed(1, 0b0100 - 1)), + g160 + ); + assert_eq!( + PointProjective::from_affine(&precomputed(1, 0b1000 - 1)), + g224 + ); + } + + #[test] + fn test_precomputed_table_0_is_correct() { + let gen = PointProjective::from_affine(&precomputed(0, 0)); + let g64 = power_of_two(gen, 64); + let g128 = power_of_two(gen, 128); + let g192 = power_of_two(gen, 192); + + for i in 1..16 { + let mut x = PointProjective::INFINITY; + if i & 1 != 0 { + x = &x + &gen; + } + if i & 2 != 0 { + x = &x + &g64; + } + if i & 4 != 0 { + x = &x + &g128; + } + if i & 8 != 0 { + x = &x + &g192; + } + assert_eq!(PointProjective::from_affine(&precomputed(0, i - 1)), x); + } + } + + #[test] + fn test_precomputed_table_1_is_correct() { + let gen = PointProjective::from_affine(&precomputed(0, 0)); + let g32 = power_of_two(gen, 32); + let g96 = power_of_two(gen, 96); + let g160 = power_of_two(gen, 160); + let g224 = power_of_two(gen, 224); + + for i in 1..16 { + let mut x = PointProjective::INFINITY; + if i & 1 != 0 { + x = &x + &g32; + } + if i & 2 != 0 { + x = &x + &g96; + } + if i & 4 != 0 { + x = &x + &g160; + } + if i & 8 != 0 { + x = &x + &g224; + } + assert_eq!(PointProjective::from_affine(&precomputed(1, i - 1)), x); + } + } +} diff --git a/libraries/crypto/src/ecdh.rs b/libraries/crypto/src/ecdh.rs new file mode 100644 index 0000000..7a4b250 --- /dev/null +++ b/libraries/crypto/src/ecdh.rs @@ -0,0 +1,154 @@ +// Copyright 2019 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. + +use super::ec::exponent256::NonZeroExponentP256; +use super::ec::int256; +use super::ec::int256::Int256; +use super::ec::point::PointP256; +use super::rng256::Rng256; +use super::sha256::Sha256; +use super::Hash256; + +pub const NBYTES: usize = int256::NBYTES; + +pub struct SecKey { + a: NonZeroExponentP256, +} + +#[cfg_attr(feature = "derive_debug", derive(Clone, PartialEq, Debug))] +pub struct PubKey { + p: PointP256, +} + +impl SecKey { + pub fn gensk(rng: &mut R) -> SecKey + where + R: Rng256, + { + SecKey { + a: NonZeroExponentP256::gen_uniform(rng), + } + } + + pub fn genpk(&self) -> PubKey { + PubKey { + p: PointP256::base_point_mul(self.a.as_exponent()), + } + } + + fn exchange_raw(&self, other: &PubKey) -> PointP256 { + // At this point, the PubKey type guarantees that other.p is a valid point on the curve. + // It's the responsibility of the caller to handle errors when converting serialized bytes + // to a PubKey. + other.p.mul(self.a.as_exponent()) + // TODO: Do we need to check that the exchanged point is not infinite, and if yes handle + // the error? The following argument should be reviewed: + // + // In principle this isn't needed on the P-256 curve, which has a prime order and a + // cofactor of 1. + // + // Some pointers on this: + // - https://www.secg.org/sec1-v2.pdf + } + + // DH key agreement method defined in the FIDO2 specification, Section 5.5.4. "Getting + // sharedSecret from Authenticator" + pub fn exchange_x_sha256(&self, other: &PubKey) -> [u8; 32] { + let p = self.exchange_raw(other); + let mut x: [u8; 32] = [Default::default(); 32]; + p.getx().to_int().to_bin(&mut x); + Sha256::hash(&x) + } +} + +impl PubKey { + #[cfg(test)] + fn from_bytes_uncompressed(bytes: &[u8]) -> Option { + PointP256::from_bytes_uncompressed_vartime(bytes).map(|p| PubKey { p }) + } + + #[cfg(test)] + fn to_bytes_uncompressed(&self, bytes: &mut [u8; 65]) { + self.p.to_bytes_uncompressed(bytes); + } + + pub fn from_coordinates(x: &[u8; NBYTES], y: &[u8; NBYTES]) -> Option { + PointP256::new_checked_vartime(Int256::from_bin(x), Int256::from_bin(y)) + .map(|p| PubKey { p }) + } + + pub fn to_coordinates(&self, x: &mut [u8; NBYTES], y: &mut [u8; NBYTES]) { + self.p.getx().to_int().to_bin(x); + self.p.gety().to_int().to_bin(y); + } +} + +#[cfg(test)] +mod test { + use super::super::rng256::ThreadRng256; + use super::*; + + // Run more test iterations in release mode, as the code should be faster. + #[cfg(not(debug_assertions))] + const ITERATIONS: u32 = 10000; + #[cfg(debug_assertions)] + const ITERATIONS: u32 = 1000; + + /** Test that key generation creates valid keys **/ + #[test] + fn test_gen_pub_is_valid_random() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let sk = SecKey::gensk(&mut rng); + let pk = sk.genpk(); + assert!(pk.p.is_valid_vartime()); + } + } + + /** Test that the exchanged key is the same on both sides **/ + #[test] + fn test_exchange_x_sha256_is_symmetric() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let sk_a = SecKey::gensk(&mut rng); + let pk_a = sk_a.genpk(); + let sk_b = SecKey::gensk(&mut rng); + let pk_b = sk_b.genpk(); + assert_eq!(sk_a.exchange_x_sha256(&pk_b), sk_b.exchange_x_sha256(&pk_a)); + } + } + + #[test] + fn test_exchange_x_sha256_bytes_is_symmetric() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let sk_a = SecKey::gensk(&mut rng); + let mut pk_bytes_a = [Default::default(); 65]; + sk_a.genpk().to_bytes_uncompressed(&mut pk_bytes_a); + + let sk_b = SecKey::gensk(&mut rng); + let mut pk_bytes_b = [Default::default(); 65]; + sk_b.genpk().to_bytes_uncompressed(&mut pk_bytes_b); + + let pk_a = PubKey::from_bytes_uncompressed(&pk_bytes_a).unwrap(); + let pk_b = PubKey::from_bytes_uncompressed(&pk_bytes_b).unwrap(); + assert_eq!(sk_a.exchange_x_sha256(&pk_b), sk_b.exchange_x_sha256(&pk_a)); + } + } + + // TODO: tests with invalid public shares. +} diff --git a/libraries/crypto/src/ecdsa.rs b/libraries/crypto/src/ecdsa.rs new file mode 100644 index 0000000..2d39311 --- /dev/null +++ b/libraries/crypto/src/ecdsa.rs @@ -0,0 +1,643 @@ +// Copyright 2019 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. + +use super::ec::exponent256::{ExponentP256, NonZeroExponentP256}; +use super::ec::int256; +use super::ec::int256::Int256; +use super::ec::point::PointP256; +use super::hmac::hmac_256; +use super::rng256::Rng256; +use super::{Hash256, HashBlockSize64Bytes}; +use alloc::vec::Vec; +use core::marker::PhantomData; + +#[derive(Clone, PartialEq)] +#[cfg_attr(feature = "derive_debug", derive(Debug))] +pub struct SecKey { + k: NonZeroExponentP256, +} + +pub struct Signature { + r: NonZeroExponentP256, + s: NonZeroExponentP256, +} + +pub struct PubKey { + p: PointP256, +} + +impl SecKey { + pub fn gensk(rng: &mut R) -> SecKey + where + R: Rng256, + { + SecKey { + k: NonZeroExponentP256::gen_uniform(rng), + } + } + + pub fn genpk(&self) -> PubKey { + PubKey { + p: PointP256::base_point_mul(self.k.as_exponent()), + } + } + + // ECDSA signature based on a RNG to generate a suitable randomization parameter. + // Under the hood, rejection sampling is used to make sure that the randomization parameter is + // uniformly distributed. + // The provided RNG must be cryptographically secure; otherwise this method is insecure. + pub fn sign_rng(&self, msg: &[u8], rng: &mut R) -> Signature + where + H: Hash256, + R: Rng256, + { + let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg))); + + loop { + let k = NonZeroExponentP256::gen_uniform(rng); + if let Some(sign) = self.try_sign(&k, &m) { + return sign; + } + } + } + + // Deterministic ECDSA signature based on RFC 6979 to generate a suitable randomization + // parameter. + pub fn sign_rfc6979(&self, msg: &[u8]) -> Signature + where + H: Hash256 + HashBlockSize64Bytes, + { + let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg))); + + let mut rfc_6979 = Rfc6979::::new(self, &msg); + loop { + let k = NonZeroExponentP256::from_int_checked(rfc_6979.next()); + // The branching here is fine. By design the algorithm of RFC 6976 has a running time + // that depends on the sequence of generated k. + if bool::from(k.is_none()) { + continue; + } + let k = k.unwrap(); + + if let Some(sign) = self.try_sign(&k, &m) { + return sign; + } + } + } + + // Try signing a curve element given a randomization parameter k. If no signature can be + // obtained from this k, None is returned and the caller should try again with another value. + fn try_sign(&self, k: &NonZeroExponentP256, msg: &ExponentP256) -> Option { + let r = ExponentP256::modn(PointP256::base_point_mul(k.as_exponent()).getx().to_int()); + // The branching here is fine because all this reveals is that k generated an unsuitable r. + let r = r.non_zero(); + if bool::from(r.is_none()) { + return None; + } + let r = r.unwrap(); + + let (s, top) = &(&r * &self.k).to_int() + &msg.to_int(); + let s = k.inv().as_exponent().mul_top(&s, top); + + // The branching here is fine because all this reveals is that k generated an unsuitable s. + let s = s.non_zero(); + if bool::from(s.is_none()) { + return None; + } + let s = s.unwrap(); + + Some(Signature { r, s }) + } + + #[cfg(test)] + pub fn get_k_rfc6979(&self, msg: &[u8]) -> NonZeroExponentP256 + where + H: Hash256 + HashBlockSize64Bytes, + { + let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg))); + + let mut rfc_6979 = Rfc6979::::new(self, &msg); + loop { + let k = NonZeroExponentP256::from_int_checked(rfc_6979.next()); + if bool::from(k.is_none()) { + continue; + } + let k = k.unwrap(); + if self.try_sign(&k, &m).is_some() { + return k; + } + } + } + + pub fn from_bytes(bytes: &[u8; 32]) -> Option { + let k = NonZeroExponentP256::from_int_checked(Int256::from_bin(bytes)); + // The branching here is fine because all this reveals is whether the key was invalid. + if bool::from(k.is_none()) { + return None; + } + let k = k.unwrap(); + Some(SecKey { k }) + } + + pub fn to_bytes(&self, bytes: &mut [u8; 32]) { + self.k.to_int().to_bin(bytes); + } +} + +impl Signature { + pub fn to_asn1_der(&self) -> Vec { + const DER_INTEGER_TYPE: u8 = 0x02; + const DER_DEF_LENGTH_SEQUENCE: u8 = 0x30; + + let r_encoding = self.r.to_int().to_minimal_encoding(); + let s_encoding = self.s.to_int().to_minimal_encoding(); + // We rely on the encoding to be short enough such that + // sum of lengths + 4 still fits into 7 bits. + #[cfg(test)] + assert!(r_encoding.len() <= 33); + #[cfg(test)] + assert!(s_encoding.len() <= 33); + // The ASN1 of a signature is a two member sequence. Its length is the + // sum of the integer encoding lengths and 2 header bytes per integer. + let mut encoding = vec![ + DER_DEF_LENGTH_SEQUENCE, + (r_encoding.len() + s_encoding.len() + 4) as u8, + ]; + encoding.push(DER_INTEGER_TYPE); + encoding.push(r_encoding.len() as u8); + encoding.extend(r_encoding); + encoding.push(DER_INTEGER_TYPE); + encoding.push(s_encoding.len() as u8); + encoding.extend(s_encoding); + encoding + } + + #[cfg(feature = "std")] + pub fn from_bytes(bytes: &[u8]) -> Option { + if bytes.len() != 64 { + None + } else { + let r = + NonZeroExponentP256::from_int_checked(Int256::from_bin(array_ref![bytes, 0, 32])); + let s = + NonZeroExponentP256::from_int_checked(Int256::from_bin(array_ref![bytes, 32, 32])); + if bool::from(r.is_none()) || bool::from(s.is_none()) { + return None; + } + let r = r.unwrap(); + let s = s.unwrap(); + Some(Signature { r, s }) + } + } + + #[cfg(test)] + fn to_bytes(&self, bytes: &mut [u8; 64]) { + self.r.to_int().to_bin(array_mut_ref![bytes, 0, 32]); + self.s.to_int().to_bin(array_mut_ref![bytes, 32, 32]); + } +} + +impl PubKey { + pub const ES256_ALGORITHM: i64 = -7; + #[cfg(feature = "with_ctap1")] + const UNCOMPRESSED_LENGTH: usize = 1 + 2 * int256::NBYTES; + + #[cfg(feature = "std")] + pub fn from_bytes_uncompressed(bytes: &[u8]) -> Option { + PointP256::from_bytes_uncompressed_vartime(bytes).map(|p| PubKey { p }) + } + + #[cfg(test)] + fn to_bytes_uncompressed(&self, bytes: &mut [u8; 65]) { + self.p.to_bytes_uncompressed(bytes); + } + + #[cfg(feature = "with_ctap1")] + pub fn to_uncompressed(&self) -> [u8; PubKey::UNCOMPRESSED_LENGTH] { + // Formatting according to: + // https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html#overview + const B0_BYTE_MARKER: u8 = 0x04; + let mut representation = [0; PubKey::UNCOMPRESSED_LENGTH]; + let (marker, x, y) = + mut_array_refs![&mut representation, 1, int256::NBYTES, int256::NBYTES]; + marker[0] = B0_BYTE_MARKER; + self.p.getx().to_int().to_bin(x); + self.p.gety().to_int().to_bin(y); + representation + } + + // Encodes the key according to CBOR Object Signing and Encryption, defined in RFC 8152. + pub fn to_cose_key(&self) -> Option> { + const EC2_KEY_TYPE: i64 = 2; + const P_256_CURVE: i64 = 1; + let mut x_bytes = vec![0; int256::NBYTES]; + self.p + .getx() + .to_int() + .to_bin(array_mut_ref![x_bytes.as_mut_slice(), 0, int256::NBYTES]); + let x_byte_cbor: cbor::Value = cbor_bytes!(x_bytes); + let mut y_bytes = vec![0; int256::NBYTES]; + self.p + .gety() + .to_int() + .to_bin(array_mut_ref![y_bytes.as_mut_slice(), 0, int256::NBYTES]); + let y_byte_cbor: cbor::Value = cbor_bytes!(y_bytes); + let cbor_value = cbor_map_options! { + 1 => EC2_KEY_TYPE, + 3 => PubKey::ES256_ALGORITHM, + -1 => P_256_CURVE, + -2 => x_byte_cbor, + -3 => y_byte_cbor, + }; + let mut encoded_key = Vec::new(); + if cbor::write(cbor_value, &mut encoded_key) { + Some(encoded_key) + } else { + None + } + } + + #[cfg(feature = "std")] + pub fn verify_vartime(&self, msg: &[u8], sign: &Signature) -> bool + where + H: Hash256, + { + let m = ExponentP256::modn(Int256::from_bin(&H::hash(msg))); + + let v = sign.s.inv(); + let u = &m * v.as_exponent(); + let v = &sign.r * &v; + + let u = self.p.points_mul(&u, v.as_exponent()).getx(); + + ExponentP256::modn(u.to_int()) == *sign.r.as_exponent() + } +} + +struct Rfc6979 +where + H: Hash256 + HashBlockSize64Bytes, +{ + k: [u8; 32], + v: [u8; 32], + hash_marker: PhantomData, +} + +impl Rfc6979 +where + H: Hash256 + HashBlockSize64Bytes, +{ + pub fn new(sk: &SecKey, msg: &[u8]) -> Rfc6979 { + let h1 = H::hash(msg); + let v = [0x01; 32]; + let k = [0x00; 32]; + + let mut contents = [0; 3 * 32 + 1]; + let (contents_v, marker, contents_k, contents_h1) = + mut_array_refs![&mut contents, 32, 1, 32, 32]; + contents_v.copy_from_slice(&v); + marker[0] = 0x00; + Int256::to_bin(&sk.k.to_int(), contents_k); + Int256::to_bin(&Int256::from_bin(&h1).modd(&Int256::N), contents_h1); + + let k = hmac_256::(&k, &contents); + let v = hmac_256::(&k, &v); + + let (contents_v, marker, _) = mut_array_refs![&mut contents, 32, 1, 64]; + contents_v.copy_from_slice(&v); + marker[0] = 0x01; + + let k = hmac_256::(&k, &contents); + let v = hmac_256::(&k, &v); + + Rfc6979 { + k, + v, + hash_marker: PhantomData, + } + } + + fn next(&mut self) -> Int256 { + // Note: at this step, the logic from RFC 6979 is simplified, because the HMAC produces 256 + // bits and we need 256 bits. + let t = hmac_256::(&self.k, &self.v); + let result = Int256::from_bin(&t); + + let mut v1 = [0; 33]; + v1[..32].copy_from_slice(&self.v); + v1[32] = 0x00; + self.k = hmac_256::(&self.k, &v1); + self.v = hmac_256::(&self.k, &self.v); + + result + } +} + +#[cfg(test)] +mod test { + use super::super::rng256::ThreadRng256; + use super::super::sha256::Sha256; + use super::*; + extern crate hex; + extern crate ring; + extern crate untrusted; + + // Run more test iterations in release mode, as the code should be faster. + #[cfg(not(debug_assertions))] + const ITERATIONS: u32 = 10000; + #[cfg(debug_assertions)] + const ITERATIONS: u32 = 1000; + + /** Test that key generation creates valid keys **/ + #[test] + fn test_genpk_is_valid_random() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let sk = SecKey::gensk(&mut rng); + let pk = sk.genpk(); + assert!(pk.p.is_valid_vartime()); + } + } + + /** Serialization **/ + #[test] + fn test_seckey_to_bytes_from_bytes() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let sk = SecKey::gensk(&mut rng); + let mut bytes = [0; 32]; + sk.to_bytes(&mut bytes); + let decoded_sk = SecKey::from_bytes(&bytes); + assert_eq!(decoded_sk, Some(sk)); + } + } + + #[test] + fn test_seckey_from_bytes_zero() { + // Zero is not a valid exponent for a secret key. + let bytes = [0; 32]; + let sk = SecKey::from_bytes(&bytes); + assert!(sk.is_none()); + } + + #[test] + fn test_seckey_from_bytes_n() { + let mut bytes = [0; 32]; + Int256::N.to_bin(&mut bytes); + let sk = SecKey::from_bytes(&bytes); + assert!(sk.is_none()); + } + + #[test] + fn test_seckey_from_bytes_ge_n() { + let bytes = [0xFF; 32]; + let sk = SecKey::from_bytes(&bytes); + assert!(sk.is_none()); + } + + /** Test vectors from RFC6979 **/ + fn int256_from_hex(x: &str) -> Int256 { + let bytes = hex::decode(x).unwrap(); + assert_eq!(bytes.len(), 32); + Int256::from_bin(array_ref![bytes.as_slice(), 0, 32]) + } + + // Test vectors from RFC6979, Section A.2.5. + const RFC6979_X: &str = "C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"; + const RFC6979_UX: &str = "60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"; + const RFC6979_UY: &str = "7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"; + + #[test] + fn test_rfc6979_keypair() { + let sk = SecKey { + k: NonZeroExponentP256::from_int_checked(int256_from_hex(RFC6979_X)).unwrap(), + }; + let pk = sk.genpk(); + assert_eq!(pk.p.getx().to_int(), int256_from_hex(RFC6979_UX)); + assert_eq!(pk.p.gety().to_int(), int256_from_hex(RFC6979_UY)); + } + + fn test_rfc6979(msg: &str, k: &str, r: &str, s: &str) { + let sk = SecKey { + k: NonZeroExponentP256::from_int_checked(int256_from_hex(RFC6979_X)).unwrap(), + }; + assert_eq!( + sk.get_k_rfc6979::(msg.as_bytes()).to_int(), + int256_from_hex(k) + ); + let sign = sk.sign_rfc6979::(msg.as_bytes()); + assert_eq!(sign.r.to_int(), int256_from_hex(r)); + assert_eq!(sign.s.to_int(), int256_from_hex(s)); + } + + #[test] + fn test_rfc6979_sample() { + let msg = "sample"; + let k = "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60"; + let r = "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716"; + let s = "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8"; + test_rfc6979(msg, k, r, s); + } + + #[test] + fn test_rfc6979_test() { + let msg = "test"; + let k = "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0"; + let r = "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367"; + let s = "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083"; + test_rfc6979(msg, k, r, s); + } + + /** Tests that sign and verify are consistent **/ + // Test that signed messages are correctly verified. + #[test] + fn test_sign_rfc6979_verify_random() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let msg = rng.gen_uniform_u8x32(); + let sk = SecKey::gensk(&mut rng); + let pk = sk.genpk(); + let sign = sk.sign_rfc6979::(&msg); + assert!(pk.verify_vartime::(&msg, &sign)); + } + } + + // Test that signed messages are correctly verified. + #[test] + fn test_sign_verify_random() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let msg = rng.gen_uniform_u8x32(); + let sk = SecKey::gensk(&mut rng); + let pk = sk.genpk(); + let sign = sk.sign_rng::(&msg, &mut rng); + assert!(pk.verify_vartime::(&msg, &sign)); + } + } + + /** Tests that this code is compatible with the ring crate **/ + // Test that the ring crate works properly. + #[test] + fn test_ring_sign_ring_verify() { + use ring::rand::SecureRandom; + use ring::signature::KeyPair; + + let ring_rng = ring::rand::SystemRandom::new(); + + for _ in 0..ITERATIONS { + let mut msg_bytes: [u8; 64] = [Default::default(); 64]; + ring_rng.fill(&mut msg_bytes).unwrap(); + let msg = untrusted::Input::from(&msg_bytes); + + let pkcs8_bytes = ring::signature::EcdsaKeyPair::generate_pkcs8( + &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING, + &ring_rng, + ) + .unwrap(); + let key_pair = ring::signature::EcdsaKeyPair::from_pkcs8( + &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING, + untrusted::Input::from(pkcs8_bytes.as_ref()), + ) + .unwrap(); + let public_key_bytes = key_pair.public_key().as_ref(); + + let sig = key_pair.sign(&ring_rng, msg).unwrap(); + let sig_bytes = sig.as_ref(); + + assert!(ring::signature::verify( + &ring::signature::ECDSA_P256_SHA256_FIXED, + untrusted::Input::from(public_key_bytes), + msg, + untrusted::Input::from(sig_bytes) + ) + .is_ok()); + } + } + + // Test that messages signed by the ring crate are correctly verified by this code. + #[test] + fn test_ring_sign_self_verify() { + use ring::rand::SecureRandom; + use ring::signature::KeyPair; + + let ring_rng = ring::rand::SystemRandom::new(); + + for _ in 0..ITERATIONS { + let mut msg_bytes: [u8; 64] = [Default::default(); 64]; + ring_rng.fill(&mut msg_bytes).unwrap(); + + let pkcs8_bytes = ring::signature::EcdsaKeyPair::generate_pkcs8( + &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING, + &ring_rng, + ) + .unwrap(); + let key_pair = ring::signature::EcdsaKeyPair::from_pkcs8( + &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING, + untrusted::Input::from(pkcs8_bytes.as_ref()), + ) + .unwrap(); + let public_key_bytes = key_pair.public_key().as_ref(); + + let sig = key_pair + .sign(&ring_rng, untrusted::Input::from(&msg_bytes)) + .unwrap(); + let sig_bytes = sig.as_ref(); + + let pk = PubKey::from_bytes_uncompressed(public_key_bytes).unwrap(); + let sign = Signature::from_bytes(sig_bytes).unwrap(); + assert!(pk.verify_vartime::(&msg_bytes, &sign)); + } + } + + // Test that messages signed by this code are correctly verified by the ring crate. + #[test] + fn test_self_sign_ring_verify() { + let mut rng = ThreadRng256 {}; + + for _ in 0..ITERATIONS { + let msg_bytes = rng.gen_uniform_u8x32(); + let sk = SecKey::gensk(&mut rng); + let pk = sk.genpk(); + let sign = sk.sign_rng::(&msg_bytes, &mut rng); + + let mut public_key_bytes: [u8; 65] = [Default::default(); 65]; + pk.to_bytes_uncompressed(&mut public_key_bytes); + let mut sig_bytes: [u8; 64] = [Default::default(); 64]; + sign.to_bytes(&mut sig_bytes); + + assert!(ring::signature::verify( + &ring::signature::ECDSA_P256_SHA256_FIXED, + untrusted::Input::from(&public_key_bytes), + untrusted::Input::from(&msg_bytes), + untrusted::Input::from(&sig_bytes) + ) + .is_ok()); + } + } + + #[test] + fn test_signature_to_asn1_der_short_encodings() { + let r_bytes = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + ]; + let r = NonZeroExponentP256::from_int_checked(Int256::from_bin(&r_bytes)).unwrap(); + let s_bytes = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, + ]; + let s = NonZeroExponentP256::from_int_checked(Int256::from_bin(&s_bytes)).unwrap(); + let signature = Signature { r, s }; + let expected_encoding = vec![0x30, 0x07, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0xFF]; + + assert_eq!(signature.to_asn1_der(), expected_encoding); + } + + #[test] + fn test_signature_to_asn1_der_long_encodings() { + let r_bytes = [ + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, + ]; + let r = NonZeroExponentP256::from_int_checked(Int256::from_bin(&r_bytes)).unwrap(); + let s_bytes = [ + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, + ]; + let s = NonZeroExponentP256::from_int_checked(Int256::from_bin(&s_bytes)).unwrap(); + let signature = Signature { r, s }; + let expected_encoding = vec![ + 0x30, 0x46, 0x02, 0x21, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x02, 0x21, 0x00, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, + ]; + + assert_eq!(signature.to_asn1_der(), expected_encoding); + } + + // TODO: Test edge-cases and compare the behavior with ring. + // - Invalid public key (at infinity, values not less than the prime p), but ring doesn't + // directly exposes key validation in its API. +} diff --git a/libraries/crypto/src/hmac.rs b/libraries/crypto/src/hmac.rs new file mode 100644 index 0000000..f09e2b9 --- /dev/null +++ b/libraries/crypto/src/hmac.rs @@ -0,0 +1,281 @@ +// Copyright 2019 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. + +use super::{Hash256, HashBlockSize64Bytes}; +use subtle::ConstantTimeEq; + +const BLOCK_SIZE: usize = 64; +const HASH_SIZE: usize = 32; + +pub fn verify_hmac_256(key: &[u8], contents: &[u8], mac: &[u8; HASH_SIZE]) -> bool +where + H: Hash256 + HashBlockSize64Bytes, +{ + let expected_mac = hmac_256::(key, contents); + bool::from(expected_mac.ct_eq(mac)) +} + +// FIDO2's PIN verification is just matching the first 16 bytes of the HMAC +// against the pin ¯\_(ツ)_/¯ +pub fn verify_hmac_256_first_128bits(key: &[u8], contents: &[u8], pin: &[u8; 16]) -> bool +where + H: Hash256 + HashBlockSize64Bytes, +{ + let expected_mac = hmac_256::(key, contents); + bool::from(array_ref![expected_mac, 0, 16].ct_eq(pin)) +} + +pub fn hmac_256(key: &[u8], contents: &[u8]) -> [u8; HASH_SIZE] +where + H: Hash256 + HashBlockSize64Bytes, +{ + let mut ipad: [u8; BLOCK_SIZE] = [0x36; BLOCK_SIZE]; + let mut opad: [u8; BLOCK_SIZE] = [0x5c; BLOCK_SIZE]; + if key.len() <= BLOCK_SIZE { + xor_pads(&mut ipad, &mut opad, key); + } else { + xor_pads(&mut ipad, &mut opad, &H::hash(key)); + } + + let mut ihasher = H::new(); + ihasher.update(&ipad); + ihasher.update(contents); + let ihash = ihasher.finalize(); + + let mut ohasher = H::new(); + ohasher.update(&opad); + ohasher.update(&ihash); + + ohasher.finalize() +} + +fn xor_pads(ipad: &mut [u8; BLOCK_SIZE], opad: &mut [u8; BLOCK_SIZE], key: &[u8]) { + for (i, k) in key.iter().enumerate() { + ipad[i] ^= k; + opad[i] ^= k; + } +} + +#[cfg(test)] +mod test { + use super::super::sha256::Sha256; + use super::*; + extern crate hex; + + #[test] + fn test_verify_hmac_valid() { + // Test for various lengths of the key and contents. + for len in 0..128 { + let key = vec![0; len]; + let contents = vec![0; len]; + let mac = hmac_256::(&key, &contents); + assert!(verify_hmac_256::(&key, &contents, &mac)); + } + } + + #[test] + fn test_verify_hmac_invalid() { + // Test for various lengths of the key and contents. + for len in 0..128 { + let key = vec![0; len]; + let contents = vec![0; len]; + let mac = hmac_256::(&key, &contents); + + // Check that invalid MACs don't verify, by changing any byte of the valid MAC. + for i in 0..HASH_SIZE { + let mut bad_mac = mac; + bad_mac[i] ^= 0x01; + assert!(!verify_hmac_256::(&key, &contents, &bad_mac)); + } + } + } + + #[test] + fn test_hmac_sha256_empty() { + let mut buf = [0; 96]; + buf[..64].copy_from_slice(&[0x5c; 64]); + buf[64..].copy_from_slice(&Sha256::hash(&[0x36; 64])); + assert_eq!(hmac_256::(&[], &[]), Sha256::hash(&buf)); + } + + #[test] + fn test_hmac_sha256_examples() { + assert_eq!( + hmac_256::(&[], &[]), + hex::decode("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad") + .unwrap() + .as_slice() + ); + assert_eq!( + hmac_256::(b"key", b"The quick brown fox jumps over the lazy dog"), + hex::decode("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8") + .unwrap() + .as_slice() + ); + } + + #[test] + fn test_hash_sha256_for_various_lengths() { + // This test makes sure that the key hashing and hash padding are implemented properly. + // + // Test vectors generated with the following Python script: + // + // import hashlib + // import hmac + // for n in range(128): + // print('b"' + hmac.new('A' * n, 'A' * n, hashlib.sha256).hexdigest() + '",') + // + let hashes: [&[u8; 64]; 128] = [ + b"b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad", + b"ff333794c5afd126a4e75aef1a35595a846e9e1d4053017d78d7aa3d8373182a", + b"7c1d0c177d40e7fa03cd1fa9cfc314888985aecde8f586edfb05e71e5f109c20", + b"8f7afbaef39ad155ba09bcbb386a08257731fc06fb2c1d3cff451af5386c0e7d", + b"a4dbd2915084ba3bed9306ba674c1eb22fae1dffd971c95b62ab17f0711480cd", + b"f59d521db107b4265d995f197b189de468b984816d2a01dc8ca3fcfc24d6ff37", + b"29e0656a90f3975e41c8b7e55d225353c3bb8bc0b36328c8066a61763df70b83", + b"25a85cdd13b683f3cac732fa1f19757afffe7013ddbea6e441af883379bf4232", + b"5d0b0812ecb57fb4be7f29a8978cc4f2c35b32417cc9854e2702f7fb08f6d84d", + b"d5e12df428ebd9d991a280c714c9197b977520a7fea87200177cf03618868cb3", + b"fa311e0cd19106ab33f8ee84cafdc2f03be787679c1fe7b6e64df2b2e7466ca2", + b"9a481f04a2f40d561e8e6c4850498699b36e915993153e9f9b5a4485cb0541b1", + b"c8ae9a117e3a5c9125cc21c7f9df09de50de1a6846caf13586d1e5efdfcc1ce6", + b"5ef3a488aaffb5db9173ef59e65c2dd27f4cd1a10e1b464ef5bf82d2e35eddd5", + b"e5753e8febbb38a97c1dfee23a6103fc58416b7172bab834fe5684b00800abd5", + b"0ed714c729a3db2ffde2c4ccb9f5da498c5a73a2c7010d463a7b5da8d18127aa", + b"950918cfdb0cb20f327ba0b5095d53c0befb66b9f639d389020453fcf18e8c40", + b"699470b9775ec45e9024394e7ebb16463534ed7a617bafddca11a3a0e61a3694", + b"95e8c0520fc4dc4c85e00e3868c16ab22a82e8c71ca8ea329ae1ecef0ee3968a", + b"7964fba6a123164167cbf51dc2c53948e13b2fee67d09f532e8b7bc56447c091", + b"c7d07a5f715b3ea44c258de03f2000ba79a44dd8213feb6e6006e1c3becbedff", + b"3eb1a7bf7e4f5c2d9b8cc12667ada8d7773cb9e9424104a30063778567df9422", + b"19cc344ad67db96ea936ef15cc751b29fa0409f5c9894d2cfeb100d604653ffc", + b"91001e472df16d68ee8033cd13d76a26543ccdfe1426cc6e969759b05ee7d115", + b"65f1f4670f8537f37263dabedce049b0e7d1e71f741781413cc2d5c81ecd6ac3", + b"0cf5de0ada8b717296a34fc386a8b77f60b607a48a899bee37650891a616dae7", + b"de3d56f0c83c992163aac087c999ed8eb5a039f21b0536a1967e747868dafd56", + b"0bc3fd1d46d2dc4e2d357d1f6b437d168051d6f19975223505fc2d0abddc3faa", + b"1e30596f4144ca58f3e306548cd079cc92a51ab825a4ad3246393c22283af640", + b"c2fbc726bf3eb7f0216c7e1d5f5b475a93b033b3f901a4a4dca6bbefc65b68b2", + b"1c4ef56d530bb8b627df49ea7b31cf9520e067a2fd0c671896103e146dd4564a", + b"9aeed0f7808bd6c13ce54aa5724484f41bd7cbb5e39fd1d7730befbbf056a957", + b"e58aa85e83553b7fec841cbaf42cede943b6b7ded22661cd3b1867effe91b745", + b"790fc5689193ac57c97dd25729003f2a0d8d3e5f9d2a39e007b794282a51cd3e", + b"be067b95a45cdc0060d2c3757597d8d9b858128435e93346c28ce2e82a68e951", + b"8734f497f5cd2c8667c7d8e1c2328e7e11fa80fc26c7d933937490d37718871f", + b"e8a2d0e77dfad5b046bcff0340a975300b051a21ac403dd802348511a80ba8c8", + b"4afec38787117ab6e71c34a4be7575643d8e74fc16b9d5666157fd9aee0f6e86", + b"ac8b2831d636384d1d3ff5dd77b249860bd88d5aa9af3e1d4ee70be2a1b03db9", + b"e92e1ab3934d3ed2073973204aaba03de3bc4e864cc74677b560c42971b26ab1", + b"312effff0c19cf410b9e227654211133f29276c781baadbe00a1e8319e06e361", + b"d46158da3c64439f8f176fd5e3d5ac59dcaa6c0835715c5ef30abedf34b13c59", + b"693d18266ec508515b9a3839e5336918d41ec7891feadd684b49c03093bd2061", + b"440b6a14be7bc2a1ec475a197fe4bea720d1214883e4d1e2029cf0f75fcdba29", + b"ca8e30319508df21a851a06f543f59bf6fd3b241e5a52b36fb674b0d9d5e8f67", + b"fa4f327635ff5c7051d6968daf5ffcc827bbd0da1e1c56d59918895bc418be98", + b"0e6d0dd75bc42aa6e245a212ff027bc701a7ef61179b335365a29f545bcf45e0", + b"57a08bef7822c2111ac79062240e725611322543f10758763c1c6467021c4fe7", + b"29768d5fb640a46e0129303128669eb3c7fb357ef1c49506f6300cc8e451d5e2", + b"009a868f1065ccb4227dc28084484263495ad90378dc928fc61d361eef2d072e", + b"6808e39e343af0fd53309fc02b05da1a0e68b87d5cd434e94521c635a78d7fdb", + b"8fe1668eba03be5444e0956396ac9d81ac1c4a7beb6a01151ad679f5ca0cd206", + b"01f41c1cc6d9d260ec3d938d681fc476415aae96a318862a492ba1a56f1b0a88", + b"3100bc758eeccb959376b334f999a2b4e5fcced5b5d4956510a86b654f1f0c04", + b"6225330aedced9909d4a190dba55e807624f44e7c6e0c50cac5e4ccf8e2e0029", + b"783111276f7218e3e525c83cdf117e2d5ce251f6a04beabb65ef565f513a9301", + b"4b365ab05720ad517f46df03ff441f9e0769a2ce5279663b7d90eb7d980625ef", + b"52431871c39a881c63df82860e32ccf05c1addbc630aaa580733f2e6a2fff5a6", + b"f017486486b0e308a10862e910f22545c29670daa26bf0c6791827a7f9f625a4", + b"85efd1eface951759a4642e882d0ef8d0be58afd483e0945d03a7a35fac789ac", + b"880872df19c7ff14105ba59cebc07d9e9d7e67f4896a14acae5346c66c6ce2da", + b"85ba2aa3634c619d604a964d62ae3c97f9eba7fcb7e4db2ebfa2bd23338c2d60", + b"5aa9736d405016676878fcc63e84b286cfbc843799ea786d089b2200281d5a5c", + b"30f43d84f3d5ffac60323a126fe321c6cc1e9c440249a8d69abe172494cba7ae", + b"7dce62ce40f8f4cda666341730e7dfcde8839eed4236c58ae273e6687d229d85", + b"83d670a41779f63fad0ece766a19920e0cfdd9d02f5a5900c888de21f6ae0526", + b"bb2acf0d6d39e58b09204dedcc2fe68ad829ba471a077e6e03246d8a0b0c0858", + b"1f94db9ee970a9fcc9089865eb2aa485765345f6d4de54815507ce363bc20711", + b"b4bceedc935c574935117f7ad280a7d858da7ca5a6b0920b4975111206fcac77", + b"b9da394c337e9aa150c12e54c574978773ff953270f5aefde88a766e9874c260", + b"1769fcb5d31c8c09868e4e3dcd9db92b4cccefb5660e72bfc52159fda9da8518", + b"d8ceb568f85e30cb48cabf8e84d577369033511cbbdac6a7996cf9f397c2e203", + b"64c35795b87cbb02afcdc6a5e6bacb10d98cdd1bd810ccf12c847fbdcf4d2634", + b"76ccd4e2b71a826128b60bc9fe33613d82f0ae1f57fa192f107ed54d25a842e0", + b"095450e0f61a4201bb2197371247bb7ced09056d86e901202ecc561c3568e032", + b"0e928f8e201fd3019f11037bf164cc3d719ecf08e6eac985f429702c41f25d0a", + b"135f37174ff19409cef67f3263511ed9286901090eec2b54d9444036308a72cf", + b"51eafe6978c32396022a31230b8b9120ac7bd79ad7a3303e6b6979063275c9b8", + b"fd2fb9443156429b2bc042248bf022f18ee6ed11fefea222893c49e8fef6a17e", + b"ed9a240e63644aa55c71fb339d79e1a38de71002c30baf14af38359c513de2e0", + b"c925e74d4740558277a55fe57ba88ed05ce8f5d5c35c19e7228adc09351ecfa4", + b"cd99660a7c2aded095152bc6d5fa160077355819fbf421acb95ab39ad8c27862", + b"42cf7593a535a1e79299c2839f4e0ffba5b429cb0df6c77d3fe86b6a1535d505", + b"348c6014dcb0cd583862c09ad24aa5d93e81e2f6ca4b04f4e77e50067f34e625", + b"8b00c1d89bd10b24bda2c8f6e45c4112112baacab29d0330b377d811a7b0184e", + b"dfe3960732f8e5958085a581859f6ccf40169df965bb8ff5feb4b0229a02c6f8", + b"de0aa4189c97d17df38c0ea3bc9376287076939afd515336d5d7d851f81f2517", + b"543190454858ff5396a1de3f753f84bdd2869fd2b59e3a89f090ce06bd94d626", + b"541ddbe00a0237c5c8bd043e6cced9ce78209dd83b057272cd46c2cc2f39a88c", + b"11c82017445f7e295d4c734a40cf28793df855dd321d507d4a0f3e212293ca2b", + b"cda1ecd6ca2f3858352985b4833170589e17e1f7f464e279cc78051911b8e8d3", + b"5feb471949318b26898b3339ac7a66e464a752223cf764aa0af9292fe087c39a", + b"eb48e5de63ecd22f7b305c7e74ce8cc714ab858cf834cf485727868e017e473e", + b"03428482b5208a35032777c7d628a6c8f3b07c5c87c641ddfb3adf46ffefe449", + b"a8e0cd1dfcf6e1a29ba032d3889fca2f25e3fad1a9b1c36e4978e48945b06092", + b"6cf4280b75da3bb22ddee9a9a3fdd1d0cd04627c00f73b608e44be9ce84869db", + b"9fa7648f23c405938b6fb8eaf6a24c476dafd05625a9a8f6c52e1abb9d432a76", + b"2906f0a6276e9a1ba4fbca2f335d9f7d3c331684814ac5407145d86891ba37f7", + b"1b667ee18a909e3f828f2bd6a162e3aa1361f3801b7cbc863b1b54a1ccfbf580", + b"a75e75962b3f950f7718839ef06cc09112806dbf88b142e369cf1ef99069c226", + b"71b2e2f6d66f13b919a842843b201c25249ff4b4caa4c7ab079b2980de8a18f6", + b"c4a9e73df196f876f5a3af1c8836504ee61daac5d9e15cc043a511310c22ddd8", + b"88e3303a6a2ab03430652fea942ae7cd96618fae4addcf8e92989d542777e496", + b"9a727095299564e2f5e1598f1a4095a2a000cb9196fe4eb13447932af777be3c", + b"5643a1c72b189d462236a43afc7d0b9504cbf81b4fa9a6c9cca49bd50da299df", + b"caebc47e2204fe19e757372c2e0469a34051415a09c927e63be7747903d80af5", + b"e5c9fd4bd27e7a55958cb5f66ff88baf80ab40d9690e81a9cf03ada5bd08cd44", + b"dc606eb9a631ca3f080f6d6f610444201608f47b5b49c75c2c0ec03ba9000009", + b"bce230b32a7dc676fb98a4a3d41c4171e9e173e840b92c194fb1dc4accc079b9", + b"51542ff3b57cd2ff6b1542649f7a44dbed32194b98c3af32b6ff3eefe6b490cf", + b"703f5dea8c9e3ed75c691fc17699b9648a65a331add554fa3613ddcb7267565a", + b"d74f9f60763467ce0b35ced0630ecf58605da0ca49e058de21524b5c532b5de8", + b"e9dacaf1fefaad6d9d372affab8fb5216004fb3fa7a9b86b25ecd00e583c22a5", + b"abe2c75f1ac881b743da99c543506c4b7532f3fc445fa8cbf1df22689770d66a", + b"7be506d2fd6dc79f0b14ddfff0147c79d78d99140547efcd03d0a73819b84c5a", + b"78dbc5c946ee8aa147ccfa8b5d9231c95c4257d8c79bd219ab95d53303367309", + b"1d75ee600f2ba216d211189493d793aa610aa57ccbfc4d9a7f44194e7166a062", + b"368a4d0ae1b139d71f35ba5f917a7ad4c18e6aa51b095cb135193dcd09e299b4", + b"a9d3202db927be8f0d15d2dfb83ea09db32fec3b1fc10a6acfb91da8c3c5eaf3", + b"c2284f8efeee554cc29a8802aadd7cd88e84561d353282ee31322ed497a3336c", + b"7695648a111e2ea51013f03c9de91d81a2435a7777f303e51d027750f8381680", + b"719fc44e0f64f7da9ac5d33d9ca912fdc839bb4535c66a21f0804f2cdf800666", + b"6940c082413b0c1ced6f9cb6583588c472ff72b48b00a4fb6d2710d7ac4dad99", + b"af1f26fcf070d9f5926dd41db3c09ec6b4c3f2208775cf983330cd0ff5aa239e", + b"ae50df4404a7f46146d8112bfb1cde876e591abe5ef1640e27c4d178a84b6335", + b"50f91f48df7f0f96af954be7e1b518bac537173cea38be300d98761da1d9b10f", + b"9c9aee382b3e3417e87352bdcb48837e88335e9dd0112fc22ecf61e766a6ac43", + b"d53cee1696c613f988520cf9c923c7cb6e6933b4faf57e640867d5f45a0f2569", + ]; + + let mut input = Vec::new(); + for i in 0..128 { + assert_eq!( + hmac_256::(&input, &input), + hex::decode(hashes[i] as &[u8]).unwrap().as_slice() + ); + input.push(b'A'); + } + } + + // TODO: more tests +} diff --git a/libraries/crypto/src/lib.rs b/libraries/crypto/src/lib.rs new file mode 100644 index 0000000..bfc129e --- /dev/null +++ b/libraries/crypto/src/lib.rs @@ -0,0 +1,67 @@ +// Copyright 2019 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. + +#![cfg_attr(not(feature = "std"), no_std)] +#![feature(wrapping_int_impl)] + +#[macro_use] +extern crate alloc; +extern crate subtle; +#[macro_use] +extern crate arrayref; +extern crate byteorder; +extern crate libtock; +#[macro_use] +extern crate cbor; + +pub mod aes256; +pub mod cbc; +mod ec; +pub mod ecdh; +pub mod ecdsa; +pub mod hmac; +pub mod rng256; +pub mod sha256; +pub mod util; + +// Trait for hash functions that returns a 256-bit hash. +// The type must be Sized (size known at compile time) so that we can instanciate one on the stack +// in the hash() method. +pub trait Hash256: Sized { + fn new() -> Self; + fn update(&mut self, contents: &[u8]); + fn finalize(self) -> [u8; 32]; + + fn hash(contents: &[u8]) -> [u8; 32] { + let mut h = Self::new(); + h.update(contents); + h.finalize() + } +} + +// Traits for block ciphers that operate on 16-byte blocks. +pub trait Encrypt16BytesBlock { + fn encrypt_block(&self, block: &mut [u8; 16]); +} + +pub trait Decrypt16BytesBlock { + fn decrypt_block(&self, block: &mut [u8; 16]); +} + +// Trait for hash functions that operate on 64-byte input blocks. +pub trait HashBlockSize64Bytes { + type State; + + fn hash_block(state: &mut Self::State, block: &[u8; 64]); +} diff --git a/libraries/crypto/src/rng256.rs b/libraries/crypto/src/rng256.rs new file mode 100644 index 0000000..572e21e --- /dev/null +++ b/libraries/crypto/src/rng256.rs @@ -0,0 +1,91 @@ +// Copyright 2019 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. + +use libtock::rng; + +// Lightweight RNG trait to generate uniformly distributed 256 bits. +pub trait Rng256 { + fn gen_uniform_u8x32(&mut self) -> [u8; 32]; + + fn gen_uniform_u32x8(&mut self) -> [u32; 8] { + bytes_to_u32(self.gen_uniform_u8x32()) + } +} + +// The TockOS rng driver fills a buffer of bytes, but we need 32-bit words for ECDSA. +// This function does the conversion in safe Rust, using the native endianness to avoid unnecessary +// instructions. +// An unsafe one-line equivalent could be implemented with mem::transmute, but let's use safe Rust +// when possible. +fn bytes_to_u32(bytes: [u8; 32]) -> [u32; 8] { + let mut result: [u32; 8] = [Default::default(); 8]; + for (i, r) in result.iter_mut().enumerate() { + *r = u32::from_ne_bytes(*array_ref![bytes, 4 * i, 4]); + } + result +} + +// RNG backed by the TockOS rng driver. +pub struct TockRng256 {} + +impl Rng256 for TockRng256 { + fn gen_uniform_u8x32(&mut self) -> [u8; 32] { + let mut buf: [u8; 32] = [Default::default(); 32]; + rng::fill_buffer(&mut buf); + buf + } +} + +// For tests on the desktop, we use the cryptographically secure thread rng as entropy source. +#[cfg(feature = "std")] +pub struct ThreadRng256 {} + +#[cfg(feature = "std")] +impl Rng256 for ThreadRng256 { + fn gen_uniform_u8x32(&mut self) -> [u8; 32] { + use rand::Rng; + + let mut rng = rand::thread_rng(); + let mut result = [Default::default(); 32]; + rng.fill(&mut result); + result + } +} + +#[cfg(test)] +pub mod test { + use super::*; + + #[test] + fn test_bytes_to_u32() { + // This tests that all bytes of the input are indeed used in the output, once each. + // Otherwise the result of gen_uniform_u32x8 wouldn't be uniformly distributed. + let bytes = b"\x00\x01\x02\x03\x04\x05\x06\x07\ + \x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\ + \x10\x11\x12\x13\x14\x15\x16\x17\ + \x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"; + #[cfg(target_endian = "big")] + let expected = [ + 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617, 0x18191a1b, + 0x1c1d1e1f, + ]; + #[cfg(target_endian = "little")] + let expected = [ + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, + 0x1f1e1d1c, + ]; + + assert_eq!(bytes_to_u32(*bytes), expected); + } +} diff --git a/libraries/crypto/src/sha256.rs b/libraries/crypto/src/sha256.rs new file mode 100644 index 0000000..7ad54a8 --- /dev/null +++ b/libraries/crypto/src/sha256.rs @@ -0,0 +1,423 @@ +// Copyright 2019 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. + +use super::{Hash256, HashBlockSize64Bytes}; +use byteorder::{BigEndian, ByteOrder}; +use core::num::Wrapping; + +const BLOCK_SIZE: usize = 64; + +pub struct Sha256 { + state: [Wrapping; 8], + block: [u8; BLOCK_SIZE], + total_len: usize, +} + +impl Hash256 for Sha256 { + fn new() -> Self { + Sha256 { + state: Sha256::H, + block: [0; BLOCK_SIZE], + total_len: 0, + } + } + + fn update(&mut self, mut contents: &[u8]) { + let cursor_in_block = self.total_len % BLOCK_SIZE; + let left_in_block = BLOCK_SIZE - cursor_in_block; + + // Increment the total length before we mutate the contents slice. + self.total_len += contents.len(); + + if contents.len() < left_in_block { + // The contents don't fill the current block. Simply copy the bytes. + self.block[cursor_in_block..(cursor_in_block + contents.len())] + .copy_from_slice(contents); + } else { + // First, fill and process the current block. + let (this_block, rest) = contents.split_at(left_in_block); + self.block[cursor_in_block..].copy_from_slice(this_block); + Sha256::hash_block(&mut self.state, &self.block); + contents = rest; + + // Process full blocks. + while contents.len() >= 64 { + let (block, rest) = contents.split_at(64); + Sha256::hash_block(&mut self.state, array_ref![block, 0, 64]); + contents = rest; + } + + // Copy the last block for further processing. + self.block[..contents.len()].copy_from_slice(contents); + } + } + + fn finalize(mut self) -> [u8; 32] { + // Last block and padding. + let cursor_in_block = self.total_len % BLOCK_SIZE; + self.block[cursor_in_block] = 0x80; + // Clear the rest of the block. + for byte in self.block[(cursor_in_block + 1)..].iter_mut() { + *byte = 0; + } + + if cursor_in_block >= 56 { + // Padding doesn't fit in this block, so we first hash this block and then hash a + // padding block. + Sha256::hash_block(&mut self.state, &self.block); + // Clear buffer for the padding block. + for byte in self.block.iter_mut() { + *byte = 0; + } + } + + // The last 8 bytes of the last block contain the length of the contents. It must be + // expressed in bits, whereas `total_len` is in bytes. + BigEndian::write_u64(array_mut_ref![self.block, 56, 8], self.total_len as u64 * 8); + Sha256::hash_block(&mut self.state, &self.block); + + // Encode the state's 32-bit words into bytes, using big-endian. + let mut result: [u8; 32] = [0; 32]; + for i in 0..8 { + BigEndian::write_u32(array_mut_ref![result, 4 * i, 4], self.state[i].0); + } + result + } +} + +impl HashBlockSize64Bytes for Sha256 { + type State = [Wrapping; 8]; + + #[allow(clippy::many_single_char_names)] + fn hash_block(state: &mut Self::State, block: &[u8; 64]) { + let mut w: [Wrapping; 64] = [Wrapping(0); 64]; + + // Read the block as big-endian 32-bit words. + for (i, item) in w.iter_mut().take(16).enumerate() { + *item = Wrapping(BigEndian::read_u32(array_ref![block, 4 * i, 4])); + } + + for i in 16..64 { + w[i] = w[i - 16] + Sha256::ssig0(w[i - 15]) + w[i - 7] + Sha256::ssig1(w[i - 2]); + } + + let mut a = state[0]; + let mut b = state[1]; + let mut c = state[2]; + let mut d = state[3]; + let mut e = state[4]; + let mut f = state[5]; + let mut g = state[6]; + let mut h = state[7]; + + for (i, item) in w.iter().enumerate() { + let tmp1 = + h + Sha256::bsig1(e) + Sha256::choice(e, f, g) + Wrapping(Sha256::K[i]) + *item; + let tmp2 = Sha256::bsig0(a) + Sha256::majority(a, b, c); + + h = g; + g = f; + f = e; + e = d + tmp1; + d = c; + c = b; + b = a; + a = tmp1 + tmp2; + } + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + } +} + +impl Sha256 { + // SHA-256 constants. + #[allow(clippy::unreadable_literal)] + const H: [Wrapping; 8] = [ + Wrapping(0x6a09e667), + Wrapping(0xbb67ae85), + Wrapping(0x3c6ef372), + Wrapping(0xa54ff53a), + Wrapping(0x510e527f), + Wrapping(0x9b05688c), + Wrapping(0x1f83d9ab), + Wrapping(0x5be0cd19), + ]; + + #[allow(clippy::unreadable_literal)] + const K: [u32; 64] = [ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, + 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, + 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, + 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, + 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, + 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, + 0xc67178f2, + ]; + + // SHA-256 helper functions. + #[inline(always)] + fn choice(e: Wrapping, f: Wrapping, g: Wrapping) -> Wrapping { + (e & f) ^ (!e & g) + } + + #[inline(always)] + fn majority(a: Wrapping, b: Wrapping, c: Wrapping) -> Wrapping { + (a & b) ^ (a & c) ^ (b & c) + } + + #[inline(always)] + fn bsig0(x: Wrapping) -> Wrapping { + x.rotate_right(2) ^ x.rotate_right(13) ^ x.rotate_right(22) + } + + #[inline(always)] + fn bsig1(x: Wrapping) -> Wrapping { + x.rotate_right(6) ^ x.rotate_right(11) ^ x.rotate_right(25) + } + + #[inline(always)] + fn ssig0(x: Wrapping) -> Wrapping { + x.rotate_right(7) ^ x.rotate_right(18) ^ (x >> 3) + } + + #[inline(always)] + fn ssig1(x: Wrapping) -> Wrapping { + x.rotate_right(17) ^ x.rotate_right(19) ^ (x >> 10) + } +} + +#[cfg(test)] +mod test { + use super::*; + extern crate hex; + + #[test] + fn test_choice() { + assert_eq!( + Sha256::choice( + Wrapping(0b00001111), + Wrapping(0b00110011), + Wrapping(0b01010101) + ), + Wrapping(0b01010011) + ); + } + + #[test] + fn test_majority() { + assert_eq!( + Sha256::majority( + Wrapping(0b00001111), + Wrapping(0b00110011), + Wrapping(0b01010101) + ), + Wrapping(0b00010111) + ); + } + + #[test] + fn test_hash_empty() { + assert_eq!( + Sha256::hash(&[]), + hex::decode("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855") + .unwrap() + .as_slice() + ); + } + + #[test] + fn test_update_for_various_splits() { + // Test vector generated with the following Python script: + // + // import hashlib + // print(hashlib.sha256('A' * 512).hexdigest()) + // + let input = vec![b'A'; 512]; + let hash = hex::decode("32beecb58a128af8248504600bd203dcc676adf41045300485655e6b8780a01d") + .unwrap(); + + for i in 0..512 { + for j in i..512 { + let mut h = Sha256::new(); + h.update(&input[..i]); + h.update(&input[i..j]); + h.update(&input[j..]); + assert_eq!(h.finalize(), hash.as_slice()); + } + } + } + + #[test] + fn test_hash_for_various_lengths() { + // This test makes sure that the padding is implemented properly. + // + // Test vectors generated with the following Python script: + // + // import hashlib + // for n in range(128): + // print('b"' + hashlib.sha256('A' * n).hexdigest() + '",') + // + let hashes: [&[u8; 64]; 128] = [ + b"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + b"559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd", + b"58bb119c35513a451d24dc20ef0e9031ec85b35bfc919d263e7e5d9868909cb5", + b"cb1ad2119d8fafb69566510ee712661f9f14b83385006ef92aec47f523a38358", + b"63c1dd951ffedf6f7fd968ad4efa39b8ed584f162f46e715114ee184f8de9201", + b"11770b3ea657fe68cba19675143e4715c8de9d763d3c21a85af6b7513d43997d", + b"69dc6c3210e25e62c5938ff4e841e81ce3c7d2cde583553478a77d7fcb389f30", + b"0f0cf9286f065a2f38e3c4e4886578e35af4050c108e507998a05888c98667ea", + b"c34ab6abb7b2bb595bc25c3b388c872fd1d575819a8f55cc689510285e212385", + b"e5f9176ecd90317cf2d4673926c9db65475b0b58e7f468586ddaef280a98cdbd", + b"1d65bf29403e4fb1767522a107c827b8884d16640cf0e3b18c4c1dd107e0d49d", + b"dd20088919031875b7bcca29995545dd40ca994be0558183f9b942b51b3b2249", + b"0592cedeabbf836d8d1c7456417c7653ac208f71e904d3d0ab37faf711021aff", + b"3461164897596e65b79bc0b7bee8cc7685487e37f52ecf0b34c000329675b859", + b"14f99c4b0a6493e3a3f52022cd75276b4cff9a7c8eef74793267f687b600af96", + b"6f9f84c09a5950e1ea7888f17922a69e5292dcbcb1e682ddfc977a9b4ea1a8c0", + b"991204fba2b6216d476282d375ab88d20e6108d109aecded97ef424ddd114706", + b"444074d5328d52b4e0036d37b1b6ea0a9fe3b0c96872d1157fbf01b6fdb2ce8d", + b"d273c6b6de3f5260e123348e0feb270126fa06e164bb82818df7c71b30ab0ef5", + b"234b7f9389f9b521f407805760775940d79a48188338d02a1fe654e826a83f69", + b"edfcaac579024f574adbcaa3c13e4fd2b7f1797826afe679f2144af2cb5c062d", + b"f48de1653fdfa9b637b7fb4da9c169a1f2be6a1ec001e3d2cca44c669a693ecf", + b"8a5bdb4cc15164126c6ef2668de9dd240d299ce6397a42c95a9411b93d080ed8", + b"1786ac1492c6c922c2734e4d3d8e9b030cfba291a72bc135989c49fc31171ac2", + b"1bda9f0aed80857d43c9329457f28b1ca29f736a0c539901e1ba16a909eb07b4", + b"6724431fc312ba42c98b38b8595a49749419526aa89722c77a85c6c813dfdb5a", + b"06f469c97c14e84c74853bb96aa79305eb4f6635291bf1202c4fdadb82706204", + b"568f214d529544bf4430513c2993495a5b434611533c63d1cf095b51c5e1f8af", + b"c84f7630cbe823fc4d80f605b98294592f15b14db1f78d6f18e686c1f8cb5ded", + b"a7951e0ca2e9612a985a36747309822a67a9b8c1a5abd848c03e82216c85f1b3", + b"37b9403cf88cc2639d0a118d757a43a0ff6d4871823707ab6a8bb56bc68e8e79", + b"55ee740f58335c97d42c32125218eb7c325fbe34206912f1aa7af7fd6580c9a1", + b"22a48051594c1949deed7040850c1f0f8764537f5191be56732d16a54c1d8153", + b"5d873590851b7b00b60490c8e6966b3409c385adcc9590d801f0e03e268b5ba5", + b"1e98a405718c430a4067d75125015a947a971449bc433b078418438c48bc6046", + b"015c50632207f69408c05d20e36facfad9bde74c727f933023f54cd6e8b87372", + b"a3b99d59dbb025726312e812c2821cfbe55189f515414bdabd5e3d284c8ad6f9", + b"7d24c321bfb2a5b6d2c7a3c2948855cef421d08352dc296ed95c6f645fcce441", + b"876fc5bf6bde065afea543aceb645ce17ffe3c9d8df9c6073ab31f3a562f4257", + b"b9b515854e040b8de31d85d597aba28db4467fd0a7d6eb77a31005f4a67a8fb3", + b"f0a2fb80ac0699075fb6c7b0ee2bcc204a1d909ee3149571216ec9cc1d4b9f8e", + b"b78244167af116f2b3597b4a81421bd2b28f3d8bf616025a5ae424f689fd7632", + b"d85ce644bf4e82cee032eaa5c3d9030a090276d9bae3703112bdfc6f8fdde307", + b"0f007385b6f9d4b7eeb2748605afe1a984a0a3bfa3f014d09e2a784ce9e5cd1a", + b"b06b3f20c246db70a136e3ae4787d0df96db4f693d215c21883d3c19700fb276", + b"ac752ced452069c55c7567a0717b87615824c568dc98c8626ac85fc34b234c3b", + b"91a07088de2d0fe9f31567b05d290e65feb06758d000ec463f7f5a6e82ce00a5", + b"abf6c5d1b6512e188f1da6a72e974f7b98b5bac62453f1748c8f9ab180803fdb", + b"4739dcdbab0c377161c539af55d47c5c90c87807d0728aabe91697b66e29096c", + b"ff85f0693c8e6bbeeaa1f90c32e1159b9b545d830ffe58cd80cb94d9d8140d21", + b"509ddb85fdf92f197d32570c005cdcb6dffa398f088bd1a013459f6fb1f730ef", + b"1d31616e307323bd80775ae7483fce654a3b65bced7134c22e179a2e25155009", + b"3e1ae21112ec8fad05e3676e1940da52d56771162142aac4d73743e7df70b686", + b"5f2671f97427c8873e5af72686d244e4c8126a4f618983bae880a48a834a0607", + b"2d0009d7df28cdc6b5a4c36063d97415a8fe99515317458fcb0b0e2a821dbcb9", + b"8963cc0afd622cc7574ac2011f93a3059b3d65548a77542a1559e3d202e6ab00", + b"6ea719cefa4b31862035a7fa606b7cc3602f46231117d135cc7119b3c1412314", + b"a00df74fbdadd9eb0e7742a019e5b2d77374de5417eba5b7a0730a60cce5e7bf", + b"cee244d999f8cf49f2a4ee4d89695130c9c95c33538cedf0306881ebd42714d2", + b"5b29354ee33cba5b924ded5e3c873a76e1d12527d824ace01ff9683d24e06816", + b"c5fb235befd875b915fa6c4702a7abb93cacf3d7c414b71cbeff9e1b0a9fbd41", + b"0ae45129ef1edf64309559f6cb7bb0af16eff14ad82f24d55fa029c1b4144078", + b"5a2aafcacb9828e41fb7c8f8098952638645874b3a8ca45d2523fb2d5fc7166d", + b"1b58d00f5b1fbd2a1884d666a2be33c2fa7463dff32cd60ef200c0f750a6b70f", + b"d53eda7a637c99cc7fb566d96e9fa109bf15c478410a3f5eb4d4c4e26cd081f6", + b"836203944f4c0280461ad73d31457c22ba19d1d99e232dc231000085899e00a2", + b"fd8afe9151793a84a21af054ba985d1486a705561e2a50d4a50f814664f5e806", + b"f495547fca5a5a2c40dccebefe40160efb8bc2888e8afef712b096b5f2585b44", + b"ba31b89f9486439fdf551f597fede0c10260f9b404866dba4a6555375f486359", + b"46f23cc7ccba8af67978bea568e63cd045be72aba974132b1b14cc59277329f1", + b"01d3a187638cc1a7740a74fbeb57aa2648dbdec42d497321912bf393d283ccd1", + b"96b437b3df7c62fc877a121b087899f5e36a58f6d87ba52d997e92bb016aa575", + b"6a6d691ac9ba70955046757cd685b6257773ff3ad93f43d4d4812c5b106f4b5b", + b"beb869adc22a7e8fbd5af12cbf3ad36dd92dca6ebf52ef3441ed6cd0dff24dc6", + b"0f40cb2f3661d73dfaec511e8ebea082fb1f77db45bf8c9ba7c9708da6ba6301", + b"ddd5d1ecc7af6a5b0d18e0825004d3bc9d52e2cdf14bc00c7474f16941a64acc", + b"6a10b9a8a33d7814ce73679ace5c43657aa6d63169ce215fd85177c77a94147d", + b"9d887d47c78267827dac4afb2cbdcc593d1b89c1d0c1f22c3800cae7916962cd", + b"e45ca598e970afb0f1f57bd34e87065839d2fac524421048fbec489f68e1fd0d", + b"1581baebc5f9dcfd89c658b3c3303203fc0e2f93e3f9e0b593d8b2b8112c6eda", + b"d9b1f3e2c6d528668a73f22575c44ed9f98d9c684964761b621417efd80d7a60", + b"9feacd760dfda20e5e0accf9ddeb8b5c01276a56dc3518046a26f5276fe15041", + b"6aacf5279e24979684fab16fb5495c3ac1dfcf7138b0825376af83473d07cae9", + b"cd2f0deb953014ee400eddef094602d9676e0fd2269d22818f0d5bc198d44d8d", + b"ff9265df14681e44d170fd2b10c6cdf3991f731601d6b89cafe39691d3b42559", + b"6c99e32b005a3a4956b9406ab15411e666c7f67982db170ae1fb111ec634b9c4", + b"e1659ad54063a379f77fee108a376a6a7d5ae3d0c437bf847203963bd0078dfc", + b"572d07a66fccf05d5f73c913552e12d9ffb39a15d01a8fd48cd6aaaab86f4f14", + b"ca97d312ef8551820844548f300f9528f27d53f6ad3910ed2709f2b35c9591f3", + b"97654dc78f4f7d4cec4b4870e6ee0a87abacc89337ed0629e2e511e4466df56d", + b"fde923c1ed5e5cd32c629bdf341db32c0f72ba8f1e2afd9c194e87e0e3d9da5f", + b"d6624a66f3bcc4adef8a17abf9eeb1fbf23746165b2f90f9cb3a679a58e4958e", + b"8676909e9578a790f84be31fe94f4d22488f912b754ee816ba0a5c4a392305a5", + b"57f65fd8a95ff738b95dba0f1606025535e34591f1b58b00d33958093808360c", + b"f6afcaf794fe0e04d6ec18bbde55412a60c0c5ef55e75223b817e97f208bbccc", + b"6121f27b52c1f17ddce365143ba58a720fa303707faa32a4e5e89029f34ac618", + b"69d62c062d67d8d2ce9068c1898fb9746c911839aa88ad1628d090f4c8e47f05", + b"eb9f8b69313e19e14b1043b3cac05d18d40321536ad485be8145007aefa9295d", + b"b1cfb0f511886ca07ade919740ca95e1b3d998ba7cb66ba2badd53be28f5f509", + b"d0118863549f990558685da9090ca8eae8c809c5545c4aa85f8e5eec413b2555", + b"d82c6aa133a0fc25b087f46ad7ed2a3042772e612e015571e61753ff55ba6da8", + b"aac76dab773c00c8ad4bb128147945c70798eae5a2511fef01e853c6e3051ab9", + b"ccd77d7adb6178ee3e3560ba4583044a36b296257ae4c5cfead96d46af31fccd", + b"3c4f48a886b2de7e908d6a626074e7515265cc9d1188c161cf159fd376d3d5f8", + b"7f9578a31905e95a16cc9d3e7b57dc3158a23dccf359a1f2cf09e73eb13e5cde", + b"770492ebaee89a20d19f9972c3e3d0c7d51c9baaedf06fdfe9a7b69da3394779", + b"893785aaddea396621c31dc5d465e2775cbc6b7423dc3498e80aa5da7a6a819d", + b"1b2b69fbec485ef3f347ee6dc9c87d73505e45b5c9b02599b823ac94f5d642a1", + b"724b4b3d3e8ac7588561ca00eec11693f6b85c03bb6b1302d458a7a4ce4b39e4", + b"6a30ef4094128b6fa463b70cb21d141da92711d80ea94c9b73fb8a0471cc49a9", + b"50968cf735e3f6a47834ae3745816234f72fd156aef1bec4b6a7d3a3151773bc", + b"3ed01dd816dc93ea2d445681df11aa24e9fd1441de429eb0ee7816ccc09a2b7a", + b"64bdc48c731313c7b37c1f1d13d6265ac7a2604ff630b50f591a86e610cb3005", + b"96666c386cf99a74ec9eb55a5545aa90a3e53a8bbbe74cd3334b32d4968a3214", + b"33555a41335654a29d5b7799bf180915e09095d21991dacf071583957b9e3f35", + b"ffd391d554ce0672ae818a149dd55325f4cb933c97017b8148934474355d5a88", + b"cf2050114ccaefd8a0ea6cf31d85e0232eadc8fd61277ff16496d2234b55c7d7", + b"e42142b4243d5a2c59a2977d0385d49eab288085f8d38ead3ae5d87145c562ec", + b"3bb810492422cc5c7466d86dcd8095b0d87e97634656a3fa5fe2270a2244c16b", + b"17d2f0f7197a6612e311d141781f2b9539c4aef7affd729246c401890e000dde", + b"a4f4256159ea6fb23b27eb8c5eb9cfb9083475985f355a85c78de8f2fef2b3ac", + b"a36c4cf85204c67047c00d5dcc16677978839af0f0fde7ff973c98b66e244552", + b"4a596559f450ce5e3a777d952d8d2ed8611e9f3facc8400483371f6eadc4bdb2", + b"64855e54c94d14ab53afc6109d3c0033c665fab85b57c0e7d4e8da55b3b26952", + b"a2ee2228d4798988ce3ac273c0cd8b9bbc4e3e58413eb22dfbe6395758659a2b", + b"35c28ee2e25f5ad70384f1ca9723f520c955fb5fe9f2e56b9dc809479a9ca8cc", + b"da3f6a7f55f821760330dd14495e68e7d153b05e472d38459d4728d63ad9df26", + b"026134f6117e45a37c5c2dc2f330bdd274c6dc087526b91ecec4d6dac9bb7346", + ]; + + let mut input = Vec::new(); + for i in 0..128 { + assert_eq!( + Sha256::hash(&input), + hex::decode(hashes[i] as &[u8]).unwrap().as_slice() + ); + input.push(b'A'); + } + } + + // TODO: more tests +} diff --git a/libraries/crypto/src/util.rs b/libraries/crypto/src/util.rs new file mode 100644 index 0000000..47a5ec5 --- /dev/null +++ b/libraries/crypto/src/util.rs @@ -0,0 +1,41 @@ +// Copyright 2019 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. + +#[cfg(test)] +use subtle::CtOption; + +pub type Block16 = [u8; 16]; + +#[inline(always)] +pub fn xor_block_16(block: &mut Block16, mask: &Block16) { + for i in 0..16 { + block[i] ^= mask[i]; + } +} + +#[cfg(test)] +pub trait ToOption { + fn to_option(self) -> Option; +} + +#[cfg(test)] +impl ToOption for CtOption { + fn to_option(self) -> Option { + if bool::from(self.is_some()) { + Some(self.unwrap()) + } else { + None + } + } +} diff --git a/libraries/crypto/tests/aesavs.rs b/libraries/crypto/tests/aesavs.rs new file mode 100644 index 0000000..e3798e4 --- /dev/null +++ b/libraries/crypto/tests/aesavs.rs @@ -0,0 +1,103 @@ +// Copyright 2019 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. + +/// Test vectors for AES-ECB from NIST's validation suite. +/// +/// See also https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/AESAVS.pdf +#[macro_use] +extern crate arrayref; +extern crate hex; +extern crate regex; + +use crypto::{aes256, Decrypt16BytesBlock, Encrypt16BytesBlock}; +use regex::Regex; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::Path; + +#[test] +fn aesavs() { + // These data files are taken from https://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip. + test_aesavs_file("tests/data/ECBVarKey256.rsp"); + test_aesavs_file("tests/data/ECBVarTxt256.rsp"); +} + +fn test_aesavs_file>(path: P) { + // Implements some custom parsing for NIST's test vectors. + let re_count = Regex::new("^COUNT = ([0-9]+)$").unwrap(); + let re_key = Regex::new("^KEY = ([0-9a-f]{64})$").unwrap(); + let re_plaintext = Regex::new("^PLAINTEXT = ([0-9a-f]{32})$").unwrap(); + let re_ciphertext = Regex::new("^CIPHERTEXT = ([0-9a-f]{32})$").unwrap(); + + let file = BufReader::new(File::open(path).unwrap()); + let mut lines = file.lines(); + + loop { + let line = lines.next().unwrap().unwrap(); + if line == "[ENCRYPT]" { + break; + } + } + + for i in 0.. { + // empty line + let line = lines.next().unwrap().unwrap(); + assert_eq!(line, ""); + + let line = lines.next().unwrap().unwrap(); + if line == "[DECRYPT]" { + // Skip the decryption tests, they are the same as the encryption tests. + break; + } + // "COUNT = " + let captures = re_count.captures(&line).unwrap(); + let count = captures.get(1).unwrap().as_str().parse::().unwrap(); + assert_eq!(count, i); + + // "KEY = " + let line = lines.next().unwrap().unwrap(); + let captures = re_key.captures(&line).unwrap(); + let key = hex::decode(captures.get(1).unwrap().as_str()).unwrap(); + assert_eq!(key.len(), 32); + + // "PLAINTEXT = " + let line = lines.next().unwrap().unwrap(); + let captures = re_plaintext.captures(&line).unwrap(); + let plaintext = hex::decode(captures.get(1).unwrap().as_str()).unwrap(); + assert_eq!(plaintext.len(), 16); + + // "CIPHERTEXT = " + let line = lines.next().unwrap().unwrap(); + let captures = re_ciphertext.captures(&line).unwrap(); + let ciphertext = hex::decode(captures.get(1).unwrap().as_str()).unwrap(); + assert_eq!(ciphertext.len(), 16); + + { + let encryption_key = aes256::EncryptionKey::new(array_ref![key, 0, 32]); + let mut block: [u8; 16] = [Default::default(); 16]; + block.copy_from_slice(&plaintext); + encryption_key.encrypt_block(&mut block); + assert_eq!(&block, ciphertext.as_slice()); + } + + { + let encryption_key = aes256::EncryptionKey::new(array_ref![key, 0, 32]); + let decryption_key = aes256::DecryptionKey::new(&encryption_key); + let mut block: [u8; 16] = [Default::default(); 16]; + block.copy_from_slice(&ciphertext); + decryption_key.decrypt_block(&mut block); + assert_eq!(&block, plaintext.as_slice()); + } + } +} diff --git a/libraries/crypto/tests/asn1.rs b/libraries/crypto/tests/asn1.rs new file mode 100644 index 0000000..6056253 --- /dev/null +++ b/libraries/crypto/tests/asn1.rs @@ -0,0 +1,232 @@ +// Copyright 2019 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. + +/// A minimalist parser for ASN.1 encoded ECDSA signatures in DER form. +use arrayref::mut_array_refs; +use crypto::ecdsa; +use std::convert::TryFrom; +use std::io::Read; + +#[derive(Debug)] +pub enum Asn1Error { + IoError(std::io::Error), + InvalidTagClass, + InvalidLongFormEncoding, + ArithmeticOverflow, + ExpectedSequenceTag(Tag), + ExpectedIntegerTag(Tag), + InvalidSequenceLen(usize), + InvalidIntegerLen(usize), + UnexpectedTrailingBytes, + InvalidSignature, +} + +impl From for Asn1Error { + fn from(e: std::io::Error) -> Asn1Error { + Asn1Error::IoError(e) + } +} + +#[derive(PartialEq, Debug)] +pub enum TagClass { + Universal = 0, + Application = 1, + ContextSpecific = 2, + Private = 3, +} + +impl TryFrom for TagClass { + type Error = Asn1Error; + + fn try_from(x: u8) -> Result { + match x { + 0 => Ok(TagClass::Universal), + 1 => Ok(TagClass::Application), + 2 => Ok(TagClass::ContextSpecific), + 3 => Ok(TagClass::Private), + _ => Err(Asn1Error::InvalidTagClass), + } + } +} + +#[allow(dead_code)] +enum UniversalTag { + Boolean = 1, + Integer = 2, + BitString = 3, + OctetString = 4, + Null = 5, + ObjectIdentifier = 6, + Utf8String = 12, + Sequence = 16, + Set = 17, + PrintableString = 19, + UtcTime = 23, + GeneralizedTime = 24, +} + +#[derive(Debug)] +pub struct Tag { + class: TagClass, + constructed: bool, + number: u64, +} + +impl Tag { + fn is_sequence(&self) -> bool { + self.class == TagClass::Universal + && self.constructed + && self.number == UniversalTag::Sequence as u64 + } + + fn is_number(&self) -> bool { + self.class == TagClass::Universal + && !self.constructed + && self.number == UniversalTag::Integer as u64 + } + + // Parse an ASN.1 tag encoded in DER form. + fn parse(input: &mut R) -> Result { + let mut buf = [0u8; 1]; + + input.read_exact(&mut buf)?; + let mut tag = buf[0]; + let class = TagClass::try_from(tag >> 6)?; + let constructed = tag & 0x20 != 0; + tag &= 0x1F; + + if tag < 31 { + // Short tag number + let number = tag as u64; + Ok(Tag { + class, + constructed, + number, + }) + } else { + // Long tag number + let mut number: u64 = 0; + loop { + input.read_exact(&mut buf)?; + let x = buf[0]; + if number == 0 && x == 0 { + return Err(Asn1Error::InvalidLongFormEncoding); + } + if number >> ((8 * std::mem::size_of::()) - 7) != 0 { + return Err(Asn1Error::ArithmeticOverflow); + } + number = (number << 7) | (x & 0x7F) as u64; + if (x & 0x80) == 0 { + if number < 31 { + return Err(Asn1Error::InvalidLongFormEncoding); + } + return Ok(Tag { + class, + constructed, + number, + }); + } + } + } + } +} + +// Parse an ASN.1 length encoded in DER form. +fn parse_len(input: &mut R) -> Result { + let mut buf = [0u8; 1]; + + input.read_exact(&mut buf)?; + let first_byte = buf[0]; + if (first_byte & 0x80) == 0 { + // Short form + Ok(first_byte as usize) + } else { + // Long form + let nbytes = (first_byte & 0x7F) as usize; + + let mut length: usize = 0; + for _ in 0..nbytes { + input.read_exact(&mut buf)?; + let x = buf[0]; + if length == 0 && x == 0 { + return Err(Asn1Error::InvalidLongFormEncoding); + } + if length >> (8 * (std::mem::size_of::() - 1)) != 0 { + return Err(Asn1Error::ArithmeticOverflow); + } + length = (length << 8) | x as usize; + } + if length < 0x80 { + return Err(Asn1Error::InvalidLongFormEncoding); + } + Ok(length) + } +} + +fn parse_coordinate(mut input: R, bytes: &mut [u8; 32]) -> Result { + let tag = Tag::parse(&mut input)?; + if !tag.is_number() { + return Err(Asn1Error::ExpectedIntegerTag(tag)); + } + let len = parse_len(&mut input)?; + if len > 33 { + return Err(Asn1Error::InvalidIntegerLen(len)); + } + + let mut buf = vec![0; len]; + input.read_exact(&mut buf)?; + + if len == 33 { + if buf.remove(0) != 0 { + return Err(Asn1Error::InvalidIntegerLen(len)); + } + } + + bytes[(32 - buf.len())..].copy_from_slice(&buf); + Ok(len) +} + +pub fn parse_signature(mut input: R) -> Result { + let tag = Tag::parse(&mut input)?; + if !tag.is_sequence() { + return Err(Asn1Error::ExpectedSequenceTag(tag)); + } + let len = parse_len(&mut input)?; + + let mut bytes = [0; 64]; + let (xbytes, ybytes) = mut_array_refs![&mut bytes, 32, 32]; + + let xlen = parse_coordinate(&mut input, xbytes)?; + let ylen = parse_coordinate(&mut input, ybytes)?; + + // Each coordinate has, besides (x|y)len bytes of integer, one byte for the tag and one + // byte for the length (the length is at most 33 and therefore encoded on one byte). + if len != xlen + ylen + 4 { + return Err(Asn1Error::InvalidSequenceLen(len)); + } + + // Check for unexpected bytes at the end. + let is_eof = { + let mut buf = [0u8; 1]; + match input.read_exact(&mut buf) { + Ok(_) => false, + Err(e) => e.kind() == std::io::ErrorKind::UnexpectedEof, + } + }; + if !is_eof { + return Err(Asn1Error::UnexpectedTrailingBytes); + } + + ecdsa::Signature::from_bytes(&bytes).ok_or(Asn1Error::InvalidSignature) +} diff --git a/libraries/crypto/tests/data/ECBVarKey256.rsp b/libraries/crypto/tests/data/ECBVarKey256.rsp new file mode 100644 index 0000000..bfdd1a8 --- /dev/null +++ b/libraries/crypto/tests/data/ECBVarKey256.rsp @@ -0,0 +1,2571 @@ +# CAVS 11.1 +# Config info for aes_values +# AESVS VarKey test data for ECB +# State : Encrypt and Decrypt +# Key Length : 256 +# Generated on Fri Apr 22 15:11:30 2011 + +[ENCRYPT] + +COUNT = 0 +KEY = 8000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e35a6dcb19b201a01ebcfa8aa22b5759 + +COUNT = 1 +KEY = c000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b29169cdcf2d83e838125a12ee6aa400 + +COUNT = 2 +KEY = e000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d8f3a72fc3cdf74dfaf6c3e6b97b2fa6 + +COUNT = 3 +KEY = f000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1c777679d50037c79491a94da76a9a35 + +COUNT = 4 +KEY = f800000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9cf4893ecafa0a0247a898e040691559 + +COUNT = 5 +KEY = fc00000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8fbb413703735326310a269bd3aa94b2 + +COUNT = 6 +KEY = fe00000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 60e32246bed2b0e859e55c1cc6b26502 + +COUNT = 7 +KEY = ff00000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ec52a212f80a09df6317021bc2a9819e + +COUNT = 8 +KEY = ff80000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f23e5b600eb70dbccf6c0b1d9a68182c + +COUNT = 9 +KEY = ffc0000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a3f599d63a82a968c33fe26590745970 + +COUNT = 10 +KEY = ffe0000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d1ccb9b1337002cbac42c520b5d67722 + +COUNT = 11 +KEY = fff0000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cc111f6c37cf40a1159d00fb59fb0488 + +COUNT = 12 +KEY = fff8000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dc43b51ab609052372989a26e9cdd714 + +COUNT = 13 +KEY = fffc000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4dcede8da9e2578f39703d4433dc6459 + +COUNT = 14 +KEY = fffe000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1a4c1c263bbccfafc11782894685e3a8 + +COUNT = 15 +KEY = ffff000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 937ad84880db50613423d6d527a2823d + +COUNT = 16 +KEY = ffff800000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 610b71dfc688e150d8152c5b35ebc14d + +COUNT = 17 +KEY = ffffc00000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 27ef2495dabf323885aab39c80f18d8b + +COUNT = 18 +KEY = ffffe00000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 633cafea395bc03adae3a1e2068e4b4e + +COUNT = 19 +KEY = fffff00000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6e1b482b53761cf631819b749a6f3724 + +COUNT = 20 +KEY = fffff80000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 976e6f851ab52c771998dbb2d71c75a9 + +COUNT = 21 +KEY = fffffc0000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 85f2ba84f8c307cf525e124c3e22e6cc + +COUNT = 22 +KEY = fffffe0000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6bcca98bf6a835fa64955f72de4115fe + +COUNT = 23 +KEY = ffffff0000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2c75e2d36eebd65411f14fd0eb1d2a06 + +COUNT = 24 +KEY = ffffff8000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bd49295006250ffca5100b6007a0eade + +COUNT = 25 +KEY = ffffffc000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a190527d0ef7c70f459cd3940df316ec + +COUNT = 26 +KEY = ffffffe000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bbd1097a62433f79449fa97d4ee80dbf + +COUNT = 27 +KEY = fffffff000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 07058e408f5b99b0e0f061a1761b5b3b + +COUNT = 28 +KEY = fffffff800000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5fd1f13fa0f31e37fabde328f894eac2 + +COUNT = 29 +KEY = fffffffc00000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fc4af7c948df26e2ef3e01c1ee5b8f6f + +COUNT = 30 +KEY = fffffffe00000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 829fd7208fb92d44a074a677ee9861ac + +COUNT = 31 +KEY = ffffffff00000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ad9fc613a703251b54c64a0e76431711 + +COUNT = 32 +KEY = ffffffff80000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 33ac9eccc4cc75e2711618f80b1548e8 + +COUNT = 33 +KEY = ffffffffc0000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2025c74b8ad8f4cda17ee2049c4c902d + +COUNT = 34 +KEY = ffffffffe0000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f85ca05fe528f1ce9b790166e8d551e7 + +COUNT = 35 +KEY = fffffffff0000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6f6238d8966048d4967154e0dad5a6c9 + +COUNT = 36 +KEY = fffffffff8000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f2b21b4e7640a9b3346de8b82fb41e49 + +COUNT = 37 +KEY = fffffffffc000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f836f251ad1d11d49dc344628b1884e1 + +COUNT = 38 +KEY = fffffffffe000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 077e9470ae7abea5a9769d49182628c3 + +COUNT = 39 +KEY = ffffffffff000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e0dcc2d27fc9865633f85223cf0d611f + +COUNT = 40 +KEY = ffffffffff800000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = be66cfea2fecd6bf0ec7b4352c99bcaa + +COUNT = 41 +KEY = ffffffffffc00000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = df31144f87a2ef523facdcf21a427804 + +COUNT = 42 +KEY = ffffffffffe00000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b5bb0f5629fb6aae5e1839a3c3625d63 + +COUNT = 43 +KEY = fffffffffff00000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3c9db3335306fe1ec612bdbfae6b6028 + +COUNT = 44 +KEY = fffffffffff80000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3dd5c34634a79d3cfcc8339760e6f5f4 + +COUNT = 45 +KEY = fffffffffffc0000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 82bda118a3ed7af314fa2ccc5c07b761 + +COUNT = 46 +KEY = fffffffffffe0000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2937a64f7d4f46fe6fea3b349ec78e38 + +COUNT = 47 +KEY = ffffffffffff0000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 225f068c28476605735ad671bb8f39f3 + +COUNT = 48 +KEY = ffffffffffff8000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ae682c5ecd71898e08942ac9aa89875c + +COUNT = 49 +KEY = ffffffffffffc000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5e031cb9d676c3022d7f26227e85c38f + +COUNT = 50 +KEY = ffffffffffffe000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a78463fb064db5d52bb64bfef64f2dda + +COUNT = 51 +KEY = fffffffffffff000000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8aa9b75e784593876c53a00eae5af52b + +COUNT = 52 +KEY = fffffffffffff800000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3f84566df23da48af692722fe980573a + +COUNT = 53 +KEY = fffffffffffffc00000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 31690b5ed41c7eb42a1e83270a7ff0e6 + +COUNT = 54 +KEY = fffffffffffffe00000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 77dd7702646d55f08365e477d3590eda + +COUNT = 55 +KEY = ffffffffffffff00000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4c022ac62b3cb78d739cc67b3e20bb7e + +COUNT = 56 +KEY = ffffffffffffff80000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 092fa137ce18b5dfe7906f550bb13370 + +COUNT = 57 +KEY = ffffffffffffffc0000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3e0cdadf2e68353c0027672c97144dd3 + +COUNT = 58 +KEY = ffffffffffffffe0000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d8c4b200b383fc1f2b2ea677618a1d27 + +COUNT = 59 +KEY = fffffffffffffff0000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 11825f99b0e9bb3477c1c0713b015aac + +COUNT = 60 +KEY = fffffffffffffff8000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f8b9fffb5c187f7ddc7ab10f4fb77576 + +COUNT = 61 +KEY = fffffffffffffffc000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ffb4e87a32b37d6f2c8328d3b5377802 + +COUNT = 62 +KEY = fffffffffffffffe000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d276c13a5d220f4da9224e74896391ce + +COUNT = 63 +KEY = ffffffffffffffff000000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 94efe7a0e2e031e2536da01df799c927 + +COUNT = 64 +KEY = ffffffffffffffff800000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8f8fd822680a85974e53a5a8eb9d38de + +COUNT = 65 +KEY = ffffffffffffffffc00000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e0f0a91b2e45f8cc37b7805a3042588d + +COUNT = 66 +KEY = ffffffffffffffffe00000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 597a6252255e46d6364dbeeda31e279c + +COUNT = 67 +KEY = fffffffffffffffff00000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f51a0f694442b8f05571797fec7ee8bf + +COUNT = 68 +KEY = fffffffffffffffff80000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9ff071b165b5198a93dddeebc54d09b5 + +COUNT = 69 +KEY = fffffffffffffffffc0000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c20a19fd5758b0c4bc1a5df89cf73877 + +COUNT = 70 +KEY = fffffffffffffffffe0000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 97120166307119ca2280e9315668e96f + +COUNT = 71 +KEY = ffffffffffffffffff0000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4b3b9f1e099c2a09dc091e90e4f18f0a + +COUNT = 72 +KEY = ffffffffffffffffff8000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = eb040b891d4b37f6851f7ec219cd3f6d + +COUNT = 73 +KEY = ffffffffffffffffffc000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9f0fdec08b7fd79aa39535bea42db92a + +COUNT = 74 +KEY = ffffffffffffffffffe000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2e70f168fc74bf911df240bcd2cef236 + +COUNT = 75 +KEY = fffffffffffffffffff000000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 462ccd7f5fd1108dbc152f3cacad328b + +COUNT = 76 +KEY = fffffffffffffffffff800000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a4af534a7d0b643a01868785d86dfb95 + +COUNT = 77 +KEY = fffffffffffffffffffc00000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ab980296197e1a5022326c31da4bf6f3 + +COUNT = 78 +KEY = fffffffffffffffffffe00000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f97d57b3333b6281b07d486db2d4e20c + +COUNT = 79 +KEY = ffffffffffffffffffff00000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f33fa36720231afe4c759ade6bd62eb6 + +COUNT = 80 +KEY = ffffffffffffffffffff80000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fdcfac0c02ca538343c68117e0a15938 + +COUNT = 81 +KEY = ffffffffffffffffffffc0000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ad4916f5ee5772be764fc027b8a6e539 + +COUNT = 82 +KEY = ffffffffffffffffffffe0000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2e16873e1678610d7e14c02d002ea845 + +COUNT = 83 +KEY = fffffffffffffffffffff0000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4e6e627c1acc51340053a8236d579576 + +COUNT = 84 +KEY = fffffffffffffffffffff8000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ab0c8410aeeead92feec1eb430d652cb + +COUNT = 85 +KEY = fffffffffffffffffffffc000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e86f7e23e835e114977f60e1a592202e + +COUNT = 86 +KEY = fffffffffffffffffffffe000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e68ad5055a367041fade09d9a70a794b + +COUNT = 87 +KEY = ffffffffffffffffffffff000000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0791823a3c666bb6162825e78606a7fe + +COUNT = 88 +KEY = ffffffffffffffffffffff800000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dcca366a9bf47b7b868b77e25c18a364 + +COUNT = 89 +KEY = ffffffffffffffffffffffc00000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 684c9efc237e4a442965f84bce20247a + +COUNT = 90 +KEY = ffffffffffffffffffffffe00000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a858411ffbe63fdb9c8aa1bfaed67b52 + +COUNT = 91 +KEY = fffffffffffffffffffffff00000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 04bc3da2179c3015498b0e03910db5b8 + +COUNT = 92 +KEY = fffffffffffffffffffffff80000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 40071eeab3f935dbc25d00841460260f + +COUNT = 93 +KEY = fffffffffffffffffffffffc0000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0ebd7c30ed2016e08ba806ddb008bcc8 + +COUNT = 94 +KEY = fffffffffffffffffffffffe0000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 15c6becf0f4cec7129cbd22d1a79b1b8 + +COUNT = 95 +KEY = ffffffffffffffffffffffff0000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0aeede5b91f721700e9e62edbf60b781 + +COUNT = 96 +KEY = ffffffffffffffffffffffff8000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 266581af0dcfbed1585e0a242c64b8df + +COUNT = 97 +KEY = ffffffffffffffffffffffffc000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6693dc911662ae473216ba22189a511a + +COUNT = 98 +KEY = ffffffffffffffffffffffffe000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7606fa36d86473e6fb3a1bb0e2c0adf5 + +COUNT = 99 +KEY = fffffffffffffffffffffffff000000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 112078e9e11fbb78e26ffb8899e96b9a + +COUNT = 100 +KEY = fffffffffffffffffffffffff800000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 40b264e921e9e4a82694589ef3798262 + +COUNT = 101 +KEY = fffffffffffffffffffffffffc00000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8d4595cb4fa7026715f55bd68e2882f9 + +COUNT = 102 +KEY = fffffffffffffffffffffffffe00000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b588a302bdbc09197df1edae68926ed9 + +COUNT = 103 +KEY = ffffffffffffffffffffffffff00000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 33f7502390b8a4a221cfecd0666624ba + +COUNT = 104 +KEY = ffffffffffffffffffffffffff80000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3d20253adbce3be2373767c4d822c566 + +COUNT = 105 +KEY = ffffffffffffffffffffffffffc0000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a42734a3929bf84cf0116c9856a3c18c + +COUNT = 106 +KEY = ffffffffffffffffffffffffffe0000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e3abc4939457422bb957da3c56938c6d + +COUNT = 107 +KEY = fffffffffffffffffffffffffff0000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 972bdd2e7c525130fadc8f76fc6f4b3f + +COUNT = 108 +KEY = fffffffffffffffffffffffffff8000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 84a83d7b94c699cbcb8a7d9b61f64093 + +COUNT = 109 +KEY = fffffffffffffffffffffffffffc000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ce61d63514aded03d43e6ebfc3a9001f + +COUNT = 110 +KEY = fffffffffffffffffffffffffffe000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6c839dd58eeae6b8a36af48ed63d2dc9 + +COUNT = 111 +KEY = ffffffffffffffffffffffffffff000000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cd5ece55b8da3bf622c4100df5de46f9 + +COUNT = 112 +KEY = ffffffffffffffffffffffffffff800000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3b6f46f40e0ac5fc0a9c1105f800f48d + +COUNT = 113 +KEY = ffffffffffffffffffffffffffffc00000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba26d47da3aeb028de4fb5b3a854a24b + +COUNT = 114 +KEY = ffffffffffffffffffffffffffffe00000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 87f53bf620d3677268445212904389d5 + +COUNT = 115 +KEY = fffffffffffffffffffffffffffff00000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 10617d28b5e0f4605492b182a5d7f9f6 + +COUNT = 116 +KEY = fffffffffffffffffffffffffffff80000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9aaec4fabbf6fae2a71feff02e372b39 + +COUNT = 117 +KEY = fffffffffffffffffffffffffffffc0000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3a90c62d88b5c42809abf782488ed130 + +COUNT = 118 +KEY = fffffffffffffffffffffffffffffe0000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = f1f1c5a40899e15772857ccb65c7a09a + +COUNT = 119 +KEY = ffffffffffffffffffffffffffffff0000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 190843d29b25a3897c692ce1dd81ee52 + +COUNT = 120 +KEY = ffffffffffffffffffffffffffffff8000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a866bc65b6941d86e8420a7ffb0964db + +COUNT = 121 +KEY = ffffffffffffffffffffffffffffffc000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8193c6ff85225ced4255e92f6e078a14 + +COUNT = 122 +KEY = ffffffffffffffffffffffffffffffe000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9661cb2424d7d4a380d547f9e7ec1cb9 + +COUNT = 123 +KEY = fffffffffffffffffffffffffffffff000000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 86f93d9ec08453a071e2e2877877a9c8 + +COUNT = 124 +KEY = fffffffffffffffffffffffffffffff800000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 27eefa80ce6a4a9d598e3fec365434d2 + +COUNT = 125 +KEY = fffffffffffffffffffffffffffffffc00000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d62068444578e3ab39ce7ec95dd045dc + +COUNT = 126 +KEY = fffffffffffffffffffffffffffffffe00000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b5f71d4dd9a71fe5d8bc8ba7e6ea3048 + +COUNT = 127 +KEY = ffffffffffffffffffffffffffffffff00000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6825a347ac479d4f9d95c5cb8d3fd7e9 + +COUNT = 128 +KEY = ffffffffffffffffffffffffffffffff80000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e3714e94a5778955cc0346358e94783a + +COUNT = 129 +KEY = ffffffffffffffffffffffffffffffffc0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d836b44bb29e0c7d89fa4b2d4b677d2a + +COUNT = 130 +KEY = ffffffffffffffffffffffffffffffffe0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5d454b75021d76d4b84f873a8f877b92 + +COUNT = 131 +KEY = fffffffffffffffffffffffffffffffff0000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c3498f7eced2095314fc28115885b33f + +COUNT = 132 +KEY = fffffffffffffffffffffffffffffffff8000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6e668856539ad8e405bd123fe6c88530 + +COUNT = 133 +KEY = fffffffffffffffffffffffffffffffffc000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8680db7f3a87b8605543cfdbe6754076 + +COUNT = 134 +KEY = fffffffffffffffffffffffffffffffffe000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6c5d03b13069c3658b3179be91b0800c + +COUNT = 135 +KEY = ffffffffffffffffffffffffffffffffff000000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ef1b384ac4d93eda00c92add0995ea5f + +COUNT = 136 +KEY = ffffffffffffffffffffffffffffffffff800000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bf8115805471741bd5ad20a03944790f + +COUNT = 137 +KEY = ffffffffffffffffffffffffffffffffffc00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c64c24b6894b038b3c0d09b1df068b0b + +COUNT = 138 +KEY = ffffffffffffffffffffffffffffffffffe00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3967a10cffe27d0178545fbf6a40544b + +COUNT = 139 +KEY = fffffffffffffffffffffffffffffffffff00000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7c85e9c95de1a9ec5a5363a8a053472d + +COUNT = 140 +KEY = fffffffffffffffffffffffffffffffffff80000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a9eec03c8abec7ba68315c2c8c2316e0 + +COUNT = 141 +KEY = fffffffffffffffffffffffffffffffffffc0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cac8e414c2f388227ae14986fc983524 + +COUNT = 142 +KEY = fffffffffffffffffffffffffffffffffffe0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5d942b7f4622ce056c3ce3ce5f1dd9d6 + +COUNT = 143 +KEY = ffffffffffffffffffffffffffffffffffff0000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d240d648ce21a3020282c3f1b528a0b6 + +COUNT = 144 +KEY = ffffffffffffffffffffffffffffffffffff8000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 45d089c36d5c5a4efc689e3b0de10dd5 + +COUNT = 145 +KEY = ffffffffffffffffffffffffffffffffffffc000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b4da5df4becb5462e03a0ed00d295629 + +COUNT = 146 +KEY = ffffffffffffffffffffffffffffffffffffe000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = dcf4e129136c1a4b7a0f38935cc34b2b + +COUNT = 147 +KEY = fffffffffffffffffffffffffffffffffffff000000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d9a4c7618b0ce48a3d5aee1a1c0114c4 + +COUNT = 148 +KEY = fffffffffffffffffffffffffffffffffffff800000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca352df025c65c7b0bf306fbee0f36ba + +COUNT = 149 +KEY = fffffffffffffffffffffffffffffffffffffc00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 238aca23fd3409f38af63378ed2f5473 + +COUNT = 150 +KEY = fffffffffffffffffffffffffffffffffffffe00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 59836a0e06a79691b36667d5380d8188 + +COUNT = 151 +KEY = ffffffffffffffffffffffffffffffffffffff00000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 33905080f7acf1cdae0a91fc3e85aee4 + +COUNT = 152 +KEY = ffffffffffffffffffffffffffffffffffffff80000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 72c9e4646dbc3d6320fc6689d93e8833 + +COUNT = 153 +KEY = ffffffffffffffffffffffffffffffffffffffc0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba77413dea5925b7f5417ea47ff19f59 + +COUNT = 154 +KEY = ffffffffffffffffffffffffffffffffffffffe0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6cae8129f843d86dc786a0fb1a184970 + +COUNT = 155 +KEY = fffffffffffffffffffffffffffffffffffffff0000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fcfefb534100796eebbd990206754e19 + +COUNT = 156 +KEY = fffffffffffffffffffffffffffffffffffffff8000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8c791d5fdddf470da04f3e6dc4a5b5b5 + +COUNT = 157 +KEY = fffffffffffffffffffffffffffffffffffffffc000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c93bbdc07a4611ae4bb266ea5034a387 + +COUNT = 158 +KEY = fffffffffffffffffffffffffffffffffffffffe000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c102e38e489aa74762f3efc5bb23205a + +COUNT = 159 +KEY = ffffffffffffffffffffffffffffffffffffffff000000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 93201481665cbafc1fcc220bc545fb3d + +COUNT = 160 +KEY = ffffffffffffffffffffffffffffffffffffffff800000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4960757ec6ce68cf195e454cfd0f32ca + +COUNT = 161 +KEY = ffffffffffffffffffffffffffffffffffffffffc00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = feec7ce6a6cbd07c043416737f1bbb33 + +COUNT = 162 +KEY = ffffffffffffffffffffffffffffffffffffffffe00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 11c5413904487a805d70a8edd9c35527 + +COUNT = 163 +KEY = fffffffffffffffffffffffffffffffffffffffff00000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 347846b2b2e36f1f0324c86f7f1b98e2 + +COUNT = 164 +KEY = fffffffffffffffffffffffffffffffffffffffff80000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 332eee1a0cbd19ca2d69b426894044f0 + +COUNT = 165 +KEY = fffffffffffffffffffffffffffffffffffffffffc0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 866b5b3977ba6efa5128efbda9ff03cd + +COUNT = 166 +KEY = fffffffffffffffffffffffffffffffffffffffffe0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cc1445ee94c0f08cdee5c344ecd1e233 + +COUNT = 167 +KEY = ffffffffffffffffffffffffffffffffffffffffff0000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = be288319029363c2622feba4b05dfdfe + +COUNT = 168 +KEY = ffffffffffffffffffffffffffffffffffffffffff8000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cfd1875523f3cd21c395651e6ee15e56 + +COUNT = 169 +KEY = ffffffffffffffffffffffffffffffffffffffffffc000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cb5a408657837c53bf16f9d8465dce19 + +COUNT = 170 +KEY = ffffffffffffffffffffffffffffffffffffffffffe000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca0bf42cb107f55ccff2fc09ee08ca15 + +COUNT = 171 +KEY = fffffffffffffffffffffffffffffffffffffffffff000000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = fdd9bbb4a7dc2e4a23536a5880a2db67 + +COUNT = 172 +KEY = fffffffffffffffffffffffffffffffffffffffffff800000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ede447b362c484993dec9442a3b46aef + +COUNT = 173 +KEY = fffffffffffffffffffffffffffffffffffffffffffc00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 10dffb05904bff7c4781df780ad26837 + +COUNT = 174 +KEY = fffffffffffffffffffffffffffffffffffffffffffe00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c33bc13e8de88ac25232aa7496398783 + +COUNT = 175 +KEY = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca359c70803a3b2a3d542e8781dea975 + +COUNT = 176 +KEY = ffffffffffffffffffffffffffffffffffffffffffff80000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = bcc65b526f88d05b89ce8a52021fdb06 + +COUNT = 177 +KEY = ffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = db91a38855c8c4643851fbfb358b0109 + +COUNT = 178 +KEY = ffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ca6e8893a114ae8e27d5ab03a5499610 + +COUNT = 179 +KEY = fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6629d2b8df97da728cdd8b1e7f945077 + +COUNT = 180 +KEY = fffffffffffffffffffffffffffffffffffffffffffff8000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4570a5a18cfc0dd582f1d88d5c9a1720 + +COUNT = 181 +KEY = fffffffffffffffffffffffffffffffffffffffffffffc000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 72bc65aa8e89562e3f274d45af1cd10b + +COUNT = 182 +KEY = fffffffffffffffffffffffffffffffffffffffffffffe000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 98551da1a6503276ae1c77625f9ea615 + +COUNT = 183 +KEY = ffffffffffffffffffffffffffffffffffffffffffffff000000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 0ddfe51ced7e3f4ae927daa3fe452cee + +COUNT = 184 +KEY = ffffffffffffffffffffffffffffffffffffffffffffff800000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = db826251e4ce384b80218b0e1da1dd4c + +COUNT = 185 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2cacf728b88abbad7011ed0e64a1680c + +COUNT = 186 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 330d8ee7c5677e099ac74c9994ee4cfb + +COUNT = 187 +KEY = fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = edf61ae362e882ddc0167474a7a77f3a + +COUNT = 188 +KEY = fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6168b00ba7859e0970ecfd757efecf7c + +COUNT = 189 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d1415447866230d28bb1ea18a4cdfd02 + +COUNT = 190 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 516183392f7a8763afec68a060264141 + +COUNT = 191 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 77565c8d73cfd4130b4aa14d8911710f + +COUNT = 192 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 37232a4ed21ccc27c19c9610078cabac + +COUNT = 193 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 804f32ea71828c7d329077e712231666 + +COUNT = 194 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d64424f23cb97215e9c2c6f28d29eab7 + +COUNT = 195 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 023e82b533f68c75c238cebdb2ee89a2 + +COUNT = 196 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffff800000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 193a3d24157a51f1ee0893f6777417e7 + +COUNT = 197 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 84ecacfcd400084d078612b1945f2ef5 + +COUNT = 198 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1dcd8bb173259eb33a5242b0de31a455 + +COUNT = 199 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 35e9eddbc375e792c19992c19165012b + +COUNT = 200 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8a772231c01dfdd7c98e4cfddcc0807a + +COUNT = 201 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6eda7ff6b8319180ff0d6e65629d01c3 + +COUNT = 202 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = c267ef0e2d01a993944dd397101413cb + +COUNT = 203 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e9f80e9d845bcc0f62926af72eabca39 + +COUNT = 204 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 6702990727aa0878637b45dcd3a3b074 + +COUNT = 205 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2e2e647d5360e09230a5d738ca33471e + +COUNT = 206 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1f56413c7add6f43d1d56e4f02190330 + +COUNT = 207 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 69cd0606e15af729d6bca143016d9842 + +COUNT = 208 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a085d7c1a500873a20099c4caa3c3f5b + +COUNT = 209 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4fc0d230f8891415b87b83f95f2e09d1 + +COUNT = 210 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4327d08c523d8eba697a4336507d1f42 + +COUNT = 211 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7a15aab82701efa5ae36ab1d6b76290f + +COUNT = 212 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5bf0051893a18bb30e139a58fed0fa54 + +COUNT = 213 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 97e8adf65638fd9cdf3bc22c17fe4dbd + +COUNT = 214 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1ee6ee326583a0586491c96418d1a35d + +COUNT = 215 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 26b549c2ec756f82ecc48008e529956b + +COUNT = 216 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 70377b6da669b072129e057cc28e9ca5 + +COUNT = 217 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9c94b8b0cb8bcc919072262b3fa05ad9 + +COUNT = 218 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2fbb83dfd0d7abcb05cd28cad2dfb523 + +COUNT = 219 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 96877803de77744bb970d0a91f4debae + +COUNT = 220 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7379f3370cf6e5ce12ae5969c8eea312 + +COUNT = 221 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 02dc99fa3d4f98ce80985e7233889313 + +COUNT = 222 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1e38e759075ba5cab6457da51844295a + +COUNT = 223 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 70bed8dbf615868a1f9d9b05d3e7a267 + +COUNT = 224 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 234b148b8cb1d8c32b287e896903d150 + +COUNT = 225 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 294b033df4da853f4be3e243f7e513f4 + +COUNT = 226 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3f58c950f0367160adec45f2441e7411 + +COUNT = 227 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 37f655536a704e5ace182d742a820cf4 + +COUNT = 228 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ea7bd6bb63418731aeac790fe42d61e8 + +COUNT = 229 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = e74a4c999b4c064e48bb1e413f51e5ea + +COUNT = 230 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = ba9ebefdb4ccf30f296cecb3bc1943e8 + +COUNT = 231 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3194367a4898c502c13bb7478640a72d + +COUNT = 232 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = da797713263d6f33a5478a65ef60d412 + +COUNT = 233 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d1ac39bb1ef86b9c1344f214679aa376 + +COUNT = 234 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2fdea9e650532be5bc0e7325337fd363 + +COUNT = 235 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d3a204dbd9c2af158b6ca67a5156ce4a + +COUNT = 236 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 3a0a0e75a8da36735aee6684d965a778 + +COUNT = 237 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 52fc3e620492ea99641ea168da5b6d52 + +COUNT = 238 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d2e0c7f15b4772467d2cfc873000b2ca + +COUNT = 239 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 563531135e0c4d70a38f8bdb190ba04e + +COUNT = 240 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = a8a39a0f5663f4c0fe5f2d3cafff421a + +COUNT = 241 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = d94b5e90db354c1e42f61fabe167b2c0 + +COUNT = 242 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 50e6d3c9b6698a7cd276f96b1473f35a + +COUNT = 243 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 9338f08e0ebee96905d8f2e825208f43 + +COUNT = 244 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 8b378c86672aa54a3a266ba19d2580ca + +COUNT = 245 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cca7c3086f5f9511b31233da7cab9160 + +COUNT = 246 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 5b40ff4ec9be536ba23035fa4f06064c + +COUNT = 247 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 60eb5af8416b257149372194e8b88749 + +COUNT = 248 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 2f005a8aed8a361c92e440c15520cbd1 + +COUNT = 249 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 7b03627611678a997717578807a800e2 + +COUNT = 250 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = cf78618f74f6f3696e0a4779b90b5a77 + +COUNT = 251 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 03720371a04962eaea0a852e69972858 + +COUNT = 252 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 1f8a8133aa8ccf70e2bd3285831ca6b7 + +COUNT = 253 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 27936bd27fb1468fc8b48bc483321725 + +COUNT = 254 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = b07d4f3e2cd2ef2eb545980754dfea0f + +COUNT = 255 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +PLAINTEXT = 00000000000000000000000000000000 +CIPHERTEXT = 4bf85f1b5d54adbc307b0a048389adcb + +[DECRYPT] + +COUNT = 0 +KEY = 8000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = e35a6dcb19b201a01ebcfa8aa22b5759 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 1 +KEY = c000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = b29169cdcf2d83e838125a12ee6aa400 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 2 +KEY = e000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = d8f3a72fc3cdf74dfaf6c3e6b97b2fa6 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 3 +KEY = f000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1c777679d50037c79491a94da76a9a35 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 4 +KEY = f800000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9cf4893ecafa0a0247a898e040691559 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 5 +KEY = fc00000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8fbb413703735326310a269bd3aa94b2 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 6 +KEY = fe00000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 60e32246bed2b0e859e55c1cc6b26502 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 7 +KEY = ff00000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ec52a212f80a09df6317021bc2a9819e +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 8 +KEY = ff80000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = f23e5b600eb70dbccf6c0b1d9a68182c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 9 +KEY = ffc0000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a3f599d63a82a968c33fe26590745970 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 10 +KEY = ffe0000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = d1ccb9b1337002cbac42c520b5d67722 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 11 +KEY = fff0000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = cc111f6c37cf40a1159d00fb59fb0488 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 12 +KEY = fff8000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = dc43b51ab609052372989a26e9cdd714 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 13 +KEY = fffc000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 4dcede8da9e2578f39703d4433dc6459 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 14 +KEY = fffe000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1a4c1c263bbccfafc11782894685e3a8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 15 +KEY = ffff000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 937ad84880db50613423d6d527a2823d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 16 +KEY = ffff800000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 610b71dfc688e150d8152c5b35ebc14d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 17 +KEY = ffffc00000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 27ef2495dabf323885aab39c80f18d8b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 18 +KEY = ffffe00000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 633cafea395bc03adae3a1e2068e4b4e +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 19 +KEY = fffff00000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 6e1b482b53761cf631819b749a6f3724 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 20 +KEY = fffff80000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 976e6f851ab52c771998dbb2d71c75a9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 21 +KEY = fffffc0000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 85f2ba84f8c307cf525e124c3e22e6cc +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 22 +KEY = fffffe0000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 6bcca98bf6a835fa64955f72de4115fe +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 23 +KEY = ffffff0000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2c75e2d36eebd65411f14fd0eb1d2a06 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 24 +KEY = ffffff8000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = bd49295006250ffca5100b6007a0eade +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 25 +KEY = ffffffc000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a190527d0ef7c70f459cd3940df316ec +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 26 +KEY = ffffffe000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = bbd1097a62433f79449fa97d4ee80dbf +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 27 +KEY = fffffff000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 07058e408f5b99b0e0f061a1761b5b3b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 28 +KEY = fffffff800000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 5fd1f13fa0f31e37fabde328f894eac2 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 29 +KEY = fffffffc00000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = fc4af7c948df26e2ef3e01c1ee5b8f6f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 30 +KEY = fffffffe00000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 829fd7208fb92d44a074a677ee9861ac +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 31 +KEY = ffffffff00000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ad9fc613a703251b54c64a0e76431711 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 32 +KEY = ffffffff80000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 33ac9eccc4cc75e2711618f80b1548e8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 33 +KEY = ffffffffc0000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2025c74b8ad8f4cda17ee2049c4c902d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 34 +KEY = ffffffffe0000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = f85ca05fe528f1ce9b790166e8d551e7 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 35 +KEY = fffffffff0000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 6f6238d8966048d4967154e0dad5a6c9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 36 +KEY = fffffffff8000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = f2b21b4e7640a9b3346de8b82fb41e49 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 37 +KEY = fffffffffc000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = f836f251ad1d11d49dc344628b1884e1 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 38 +KEY = fffffffffe000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 077e9470ae7abea5a9769d49182628c3 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 39 +KEY = ffffffffff000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = e0dcc2d27fc9865633f85223cf0d611f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 40 +KEY = ffffffffff800000000000000000000000000000000000000000000000000000 +CIPHERTEXT = be66cfea2fecd6bf0ec7b4352c99bcaa +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 41 +KEY = ffffffffffc00000000000000000000000000000000000000000000000000000 +CIPHERTEXT = df31144f87a2ef523facdcf21a427804 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 42 +KEY = ffffffffffe00000000000000000000000000000000000000000000000000000 +CIPHERTEXT = b5bb0f5629fb6aae5e1839a3c3625d63 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 43 +KEY = fffffffffff00000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3c9db3335306fe1ec612bdbfae6b6028 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 44 +KEY = fffffffffff80000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3dd5c34634a79d3cfcc8339760e6f5f4 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 45 +KEY = fffffffffffc0000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 82bda118a3ed7af314fa2ccc5c07b761 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 46 +KEY = fffffffffffe0000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2937a64f7d4f46fe6fea3b349ec78e38 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 47 +KEY = ffffffffffff0000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 225f068c28476605735ad671bb8f39f3 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 48 +KEY = ffffffffffff8000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ae682c5ecd71898e08942ac9aa89875c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 49 +KEY = ffffffffffffc000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 5e031cb9d676c3022d7f26227e85c38f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 50 +KEY = ffffffffffffe000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a78463fb064db5d52bb64bfef64f2dda +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 51 +KEY = fffffffffffff000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8aa9b75e784593876c53a00eae5af52b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 52 +KEY = fffffffffffff800000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3f84566df23da48af692722fe980573a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 53 +KEY = fffffffffffffc00000000000000000000000000000000000000000000000000 +CIPHERTEXT = 31690b5ed41c7eb42a1e83270a7ff0e6 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 54 +KEY = fffffffffffffe00000000000000000000000000000000000000000000000000 +CIPHERTEXT = 77dd7702646d55f08365e477d3590eda +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 55 +KEY = ffffffffffffff00000000000000000000000000000000000000000000000000 +CIPHERTEXT = 4c022ac62b3cb78d739cc67b3e20bb7e +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 56 +KEY = ffffffffffffff80000000000000000000000000000000000000000000000000 +CIPHERTEXT = 092fa137ce18b5dfe7906f550bb13370 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 57 +KEY = ffffffffffffffc0000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3e0cdadf2e68353c0027672c97144dd3 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 58 +KEY = ffffffffffffffe0000000000000000000000000000000000000000000000000 +CIPHERTEXT = d8c4b200b383fc1f2b2ea677618a1d27 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 59 +KEY = fffffffffffffff0000000000000000000000000000000000000000000000000 +CIPHERTEXT = 11825f99b0e9bb3477c1c0713b015aac +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 60 +KEY = fffffffffffffff8000000000000000000000000000000000000000000000000 +CIPHERTEXT = f8b9fffb5c187f7ddc7ab10f4fb77576 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 61 +KEY = fffffffffffffffc000000000000000000000000000000000000000000000000 +CIPHERTEXT = ffb4e87a32b37d6f2c8328d3b5377802 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 62 +KEY = fffffffffffffffe000000000000000000000000000000000000000000000000 +CIPHERTEXT = d276c13a5d220f4da9224e74896391ce +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 63 +KEY = ffffffffffffffff000000000000000000000000000000000000000000000000 +CIPHERTEXT = 94efe7a0e2e031e2536da01df799c927 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 64 +KEY = ffffffffffffffff800000000000000000000000000000000000000000000000 +CIPHERTEXT = 8f8fd822680a85974e53a5a8eb9d38de +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 65 +KEY = ffffffffffffffffc00000000000000000000000000000000000000000000000 +CIPHERTEXT = e0f0a91b2e45f8cc37b7805a3042588d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 66 +KEY = ffffffffffffffffe00000000000000000000000000000000000000000000000 +CIPHERTEXT = 597a6252255e46d6364dbeeda31e279c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 67 +KEY = fffffffffffffffff00000000000000000000000000000000000000000000000 +CIPHERTEXT = f51a0f694442b8f05571797fec7ee8bf +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 68 +KEY = fffffffffffffffff80000000000000000000000000000000000000000000000 +CIPHERTEXT = 9ff071b165b5198a93dddeebc54d09b5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 69 +KEY = fffffffffffffffffc0000000000000000000000000000000000000000000000 +CIPHERTEXT = c20a19fd5758b0c4bc1a5df89cf73877 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 70 +KEY = fffffffffffffffffe0000000000000000000000000000000000000000000000 +CIPHERTEXT = 97120166307119ca2280e9315668e96f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 71 +KEY = ffffffffffffffffff0000000000000000000000000000000000000000000000 +CIPHERTEXT = 4b3b9f1e099c2a09dc091e90e4f18f0a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 72 +KEY = ffffffffffffffffff8000000000000000000000000000000000000000000000 +CIPHERTEXT = eb040b891d4b37f6851f7ec219cd3f6d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 73 +KEY = ffffffffffffffffffc000000000000000000000000000000000000000000000 +CIPHERTEXT = 9f0fdec08b7fd79aa39535bea42db92a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 74 +KEY = ffffffffffffffffffe000000000000000000000000000000000000000000000 +CIPHERTEXT = 2e70f168fc74bf911df240bcd2cef236 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 75 +KEY = fffffffffffffffffff000000000000000000000000000000000000000000000 +CIPHERTEXT = 462ccd7f5fd1108dbc152f3cacad328b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 76 +KEY = fffffffffffffffffff800000000000000000000000000000000000000000000 +CIPHERTEXT = a4af534a7d0b643a01868785d86dfb95 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 77 +KEY = fffffffffffffffffffc00000000000000000000000000000000000000000000 +CIPHERTEXT = ab980296197e1a5022326c31da4bf6f3 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 78 +KEY = fffffffffffffffffffe00000000000000000000000000000000000000000000 +CIPHERTEXT = f97d57b3333b6281b07d486db2d4e20c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 79 +KEY = ffffffffffffffffffff00000000000000000000000000000000000000000000 +CIPHERTEXT = f33fa36720231afe4c759ade6bd62eb6 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 80 +KEY = ffffffffffffffffffff80000000000000000000000000000000000000000000 +CIPHERTEXT = fdcfac0c02ca538343c68117e0a15938 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 81 +KEY = ffffffffffffffffffffc0000000000000000000000000000000000000000000 +CIPHERTEXT = ad4916f5ee5772be764fc027b8a6e539 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 82 +KEY = ffffffffffffffffffffe0000000000000000000000000000000000000000000 +CIPHERTEXT = 2e16873e1678610d7e14c02d002ea845 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 83 +KEY = fffffffffffffffffffff0000000000000000000000000000000000000000000 +CIPHERTEXT = 4e6e627c1acc51340053a8236d579576 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 84 +KEY = fffffffffffffffffffff8000000000000000000000000000000000000000000 +CIPHERTEXT = ab0c8410aeeead92feec1eb430d652cb +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 85 +KEY = fffffffffffffffffffffc000000000000000000000000000000000000000000 +CIPHERTEXT = e86f7e23e835e114977f60e1a592202e +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 86 +KEY = fffffffffffffffffffffe000000000000000000000000000000000000000000 +CIPHERTEXT = e68ad5055a367041fade09d9a70a794b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 87 +KEY = ffffffffffffffffffffff000000000000000000000000000000000000000000 +CIPHERTEXT = 0791823a3c666bb6162825e78606a7fe +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 88 +KEY = ffffffffffffffffffffff800000000000000000000000000000000000000000 +CIPHERTEXT = dcca366a9bf47b7b868b77e25c18a364 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 89 +KEY = ffffffffffffffffffffffc00000000000000000000000000000000000000000 +CIPHERTEXT = 684c9efc237e4a442965f84bce20247a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 90 +KEY = ffffffffffffffffffffffe00000000000000000000000000000000000000000 +CIPHERTEXT = a858411ffbe63fdb9c8aa1bfaed67b52 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 91 +KEY = fffffffffffffffffffffff00000000000000000000000000000000000000000 +CIPHERTEXT = 04bc3da2179c3015498b0e03910db5b8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 92 +KEY = fffffffffffffffffffffff80000000000000000000000000000000000000000 +CIPHERTEXT = 40071eeab3f935dbc25d00841460260f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 93 +KEY = fffffffffffffffffffffffc0000000000000000000000000000000000000000 +CIPHERTEXT = 0ebd7c30ed2016e08ba806ddb008bcc8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 94 +KEY = fffffffffffffffffffffffe0000000000000000000000000000000000000000 +CIPHERTEXT = 15c6becf0f4cec7129cbd22d1a79b1b8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 95 +KEY = ffffffffffffffffffffffff0000000000000000000000000000000000000000 +CIPHERTEXT = 0aeede5b91f721700e9e62edbf60b781 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 96 +KEY = ffffffffffffffffffffffff8000000000000000000000000000000000000000 +CIPHERTEXT = 266581af0dcfbed1585e0a242c64b8df +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 97 +KEY = ffffffffffffffffffffffffc000000000000000000000000000000000000000 +CIPHERTEXT = 6693dc911662ae473216ba22189a511a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 98 +KEY = ffffffffffffffffffffffffe000000000000000000000000000000000000000 +CIPHERTEXT = 7606fa36d86473e6fb3a1bb0e2c0adf5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 99 +KEY = fffffffffffffffffffffffff000000000000000000000000000000000000000 +CIPHERTEXT = 112078e9e11fbb78e26ffb8899e96b9a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 100 +KEY = fffffffffffffffffffffffff800000000000000000000000000000000000000 +CIPHERTEXT = 40b264e921e9e4a82694589ef3798262 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 101 +KEY = fffffffffffffffffffffffffc00000000000000000000000000000000000000 +CIPHERTEXT = 8d4595cb4fa7026715f55bd68e2882f9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 102 +KEY = fffffffffffffffffffffffffe00000000000000000000000000000000000000 +CIPHERTEXT = b588a302bdbc09197df1edae68926ed9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 103 +KEY = ffffffffffffffffffffffffff00000000000000000000000000000000000000 +CIPHERTEXT = 33f7502390b8a4a221cfecd0666624ba +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 104 +KEY = ffffffffffffffffffffffffff80000000000000000000000000000000000000 +CIPHERTEXT = 3d20253adbce3be2373767c4d822c566 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 105 +KEY = ffffffffffffffffffffffffffc0000000000000000000000000000000000000 +CIPHERTEXT = a42734a3929bf84cf0116c9856a3c18c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 106 +KEY = ffffffffffffffffffffffffffe0000000000000000000000000000000000000 +CIPHERTEXT = e3abc4939457422bb957da3c56938c6d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 107 +KEY = fffffffffffffffffffffffffff0000000000000000000000000000000000000 +CIPHERTEXT = 972bdd2e7c525130fadc8f76fc6f4b3f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 108 +KEY = fffffffffffffffffffffffffff8000000000000000000000000000000000000 +CIPHERTEXT = 84a83d7b94c699cbcb8a7d9b61f64093 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 109 +KEY = fffffffffffffffffffffffffffc000000000000000000000000000000000000 +CIPHERTEXT = ce61d63514aded03d43e6ebfc3a9001f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 110 +KEY = fffffffffffffffffffffffffffe000000000000000000000000000000000000 +CIPHERTEXT = 6c839dd58eeae6b8a36af48ed63d2dc9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 111 +KEY = ffffffffffffffffffffffffffff000000000000000000000000000000000000 +CIPHERTEXT = cd5ece55b8da3bf622c4100df5de46f9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 112 +KEY = ffffffffffffffffffffffffffff800000000000000000000000000000000000 +CIPHERTEXT = 3b6f46f40e0ac5fc0a9c1105f800f48d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 113 +KEY = ffffffffffffffffffffffffffffc00000000000000000000000000000000000 +CIPHERTEXT = ba26d47da3aeb028de4fb5b3a854a24b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 114 +KEY = ffffffffffffffffffffffffffffe00000000000000000000000000000000000 +CIPHERTEXT = 87f53bf620d3677268445212904389d5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 115 +KEY = fffffffffffffffffffffffffffff00000000000000000000000000000000000 +CIPHERTEXT = 10617d28b5e0f4605492b182a5d7f9f6 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 116 +KEY = fffffffffffffffffffffffffffff80000000000000000000000000000000000 +CIPHERTEXT = 9aaec4fabbf6fae2a71feff02e372b39 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 117 +KEY = fffffffffffffffffffffffffffffc0000000000000000000000000000000000 +CIPHERTEXT = 3a90c62d88b5c42809abf782488ed130 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 118 +KEY = fffffffffffffffffffffffffffffe0000000000000000000000000000000000 +CIPHERTEXT = f1f1c5a40899e15772857ccb65c7a09a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 119 +KEY = ffffffffffffffffffffffffffffff0000000000000000000000000000000000 +CIPHERTEXT = 190843d29b25a3897c692ce1dd81ee52 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 120 +KEY = ffffffffffffffffffffffffffffff8000000000000000000000000000000000 +CIPHERTEXT = a866bc65b6941d86e8420a7ffb0964db +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 121 +KEY = ffffffffffffffffffffffffffffffc000000000000000000000000000000000 +CIPHERTEXT = 8193c6ff85225ced4255e92f6e078a14 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 122 +KEY = ffffffffffffffffffffffffffffffe000000000000000000000000000000000 +CIPHERTEXT = 9661cb2424d7d4a380d547f9e7ec1cb9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 123 +KEY = fffffffffffffffffffffffffffffff000000000000000000000000000000000 +CIPHERTEXT = 86f93d9ec08453a071e2e2877877a9c8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 124 +KEY = fffffffffffffffffffffffffffffff800000000000000000000000000000000 +CIPHERTEXT = 27eefa80ce6a4a9d598e3fec365434d2 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 125 +KEY = fffffffffffffffffffffffffffffffc00000000000000000000000000000000 +CIPHERTEXT = d62068444578e3ab39ce7ec95dd045dc +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 126 +KEY = fffffffffffffffffffffffffffffffe00000000000000000000000000000000 +CIPHERTEXT = b5f71d4dd9a71fe5d8bc8ba7e6ea3048 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 127 +KEY = ffffffffffffffffffffffffffffffff00000000000000000000000000000000 +CIPHERTEXT = 6825a347ac479d4f9d95c5cb8d3fd7e9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 128 +KEY = ffffffffffffffffffffffffffffffff80000000000000000000000000000000 +CIPHERTEXT = e3714e94a5778955cc0346358e94783a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 129 +KEY = ffffffffffffffffffffffffffffffffc0000000000000000000000000000000 +CIPHERTEXT = d836b44bb29e0c7d89fa4b2d4b677d2a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 130 +KEY = ffffffffffffffffffffffffffffffffe0000000000000000000000000000000 +CIPHERTEXT = 5d454b75021d76d4b84f873a8f877b92 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 131 +KEY = fffffffffffffffffffffffffffffffff0000000000000000000000000000000 +CIPHERTEXT = c3498f7eced2095314fc28115885b33f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 132 +KEY = fffffffffffffffffffffffffffffffff8000000000000000000000000000000 +CIPHERTEXT = 6e668856539ad8e405bd123fe6c88530 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 133 +KEY = fffffffffffffffffffffffffffffffffc000000000000000000000000000000 +CIPHERTEXT = 8680db7f3a87b8605543cfdbe6754076 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 134 +KEY = fffffffffffffffffffffffffffffffffe000000000000000000000000000000 +CIPHERTEXT = 6c5d03b13069c3658b3179be91b0800c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 135 +KEY = ffffffffffffffffffffffffffffffffff000000000000000000000000000000 +CIPHERTEXT = ef1b384ac4d93eda00c92add0995ea5f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 136 +KEY = ffffffffffffffffffffffffffffffffff800000000000000000000000000000 +CIPHERTEXT = bf8115805471741bd5ad20a03944790f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 137 +KEY = ffffffffffffffffffffffffffffffffffc00000000000000000000000000000 +CIPHERTEXT = c64c24b6894b038b3c0d09b1df068b0b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 138 +KEY = ffffffffffffffffffffffffffffffffffe00000000000000000000000000000 +CIPHERTEXT = 3967a10cffe27d0178545fbf6a40544b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 139 +KEY = fffffffffffffffffffffffffffffffffff00000000000000000000000000000 +CIPHERTEXT = 7c85e9c95de1a9ec5a5363a8a053472d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 140 +KEY = fffffffffffffffffffffffffffffffffff80000000000000000000000000000 +CIPHERTEXT = a9eec03c8abec7ba68315c2c8c2316e0 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 141 +KEY = fffffffffffffffffffffffffffffffffffc0000000000000000000000000000 +CIPHERTEXT = cac8e414c2f388227ae14986fc983524 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 142 +KEY = fffffffffffffffffffffffffffffffffffe0000000000000000000000000000 +CIPHERTEXT = 5d942b7f4622ce056c3ce3ce5f1dd9d6 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 143 +KEY = ffffffffffffffffffffffffffffffffffff0000000000000000000000000000 +CIPHERTEXT = d240d648ce21a3020282c3f1b528a0b6 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 144 +KEY = ffffffffffffffffffffffffffffffffffff8000000000000000000000000000 +CIPHERTEXT = 45d089c36d5c5a4efc689e3b0de10dd5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 145 +KEY = ffffffffffffffffffffffffffffffffffffc000000000000000000000000000 +CIPHERTEXT = b4da5df4becb5462e03a0ed00d295629 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 146 +KEY = ffffffffffffffffffffffffffffffffffffe000000000000000000000000000 +CIPHERTEXT = dcf4e129136c1a4b7a0f38935cc34b2b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 147 +KEY = fffffffffffffffffffffffffffffffffffff000000000000000000000000000 +CIPHERTEXT = d9a4c7618b0ce48a3d5aee1a1c0114c4 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 148 +KEY = fffffffffffffffffffffffffffffffffffff800000000000000000000000000 +CIPHERTEXT = ca352df025c65c7b0bf306fbee0f36ba +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 149 +KEY = fffffffffffffffffffffffffffffffffffffc00000000000000000000000000 +CIPHERTEXT = 238aca23fd3409f38af63378ed2f5473 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 150 +KEY = fffffffffffffffffffffffffffffffffffffe00000000000000000000000000 +CIPHERTEXT = 59836a0e06a79691b36667d5380d8188 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 151 +KEY = ffffffffffffffffffffffffffffffffffffff00000000000000000000000000 +CIPHERTEXT = 33905080f7acf1cdae0a91fc3e85aee4 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 152 +KEY = ffffffffffffffffffffffffffffffffffffff80000000000000000000000000 +CIPHERTEXT = 72c9e4646dbc3d6320fc6689d93e8833 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 153 +KEY = ffffffffffffffffffffffffffffffffffffffc0000000000000000000000000 +CIPHERTEXT = ba77413dea5925b7f5417ea47ff19f59 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 154 +KEY = ffffffffffffffffffffffffffffffffffffffe0000000000000000000000000 +CIPHERTEXT = 6cae8129f843d86dc786a0fb1a184970 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 155 +KEY = fffffffffffffffffffffffffffffffffffffff0000000000000000000000000 +CIPHERTEXT = fcfefb534100796eebbd990206754e19 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 156 +KEY = fffffffffffffffffffffffffffffffffffffff8000000000000000000000000 +CIPHERTEXT = 8c791d5fdddf470da04f3e6dc4a5b5b5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 157 +KEY = fffffffffffffffffffffffffffffffffffffffc000000000000000000000000 +CIPHERTEXT = c93bbdc07a4611ae4bb266ea5034a387 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 158 +KEY = fffffffffffffffffffffffffffffffffffffffe000000000000000000000000 +CIPHERTEXT = c102e38e489aa74762f3efc5bb23205a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 159 +KEY = ffffffffffffffffffffffffffffffffffffffff000000000000000000000000 +CIPHERTEXT = 93201481665cbafc1fcc220bc545fb3d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 160 +KEY = ffffffffffffffffffffffffffffffffffffffff800000000000000000000000 +CIPHERTEXT = 4960757ec6ce68cf195e454cfd0f32ca +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 161 +KEY = ffffffffffffffffffffffffffffffffffffffffc00000000000000000000000 +CIPHERTEXT = feec7ce6a6cbd07c043416737f1bbb33 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 162 +KEY = ffffffffffffffffffffffffffffffffffffffffe00000000000000000000000 +CIPHERTEXT = 11c5413904487a805d70a8edd9c35527 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 163 +KEY = fffffffffffffffffffffffffffffffffffffffff00000000000000000000000 +CIPHERTEXT = 347846b2b2e36f1f0324c86f7f1b98e2 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 164 +KEY = fffffffffffffffffffffffffffffffffffffffff80000000000000000000000 +CIPHERTEXT = 332eee1a0cbd19ca2d69b426894044f0 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 165 +KEY = fffffffffffffffffffffffffffffffffffffffffc0000000000000000000000 +CIPHERTEXT = 866b5b3977ba6efa5128efbda9ff03cd +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 166 +KEY = fffffffffffffffffffffffffffffffffffffffffe0000000000000000000000 +CIPHERTEXT = cc1445ee94c0f08cdee5c344ecd1e233 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 167 +KEY = ffffffffffffffffffffffffffffffffffffffffff0000000000000000000000 +CIPHERTEXT = be288319029363c2622feba4b05dfdfe +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 168 +KEY = ffffffffffffffffffffffffffffffffffffffffff8000000000000000000000 +CIPHERTEXT = cfd1875523f3cd21c395651e6ee15e56 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 169 +KEY = ffffffffffffffffffffffffffffffffffffffffffc000000000000000000000 +CIPHERTEXT = cb5a408657837c53bf16f9d8465dce19 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 170 +KEY = ffffffffffffffffffffffffffffffffffffffffffe000000000000000000000 +CIPHERTEXT = ca0bf42cb107f55ccff2fc09ee08ca15 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 171 +KEY = fffffffffffffffffffffffffffffffffffffffffff000000000000000000000 +CIPHERTEXT = fdd9bbb4a7dc2e4a23536a5880a2db67 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 172 +KEY = fffffffffffffffffffffffffffffffffffffffffff800000000000000000000 +CIPHERTEXT = ede447b362c484993dec9442a3b46aef +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 173 +KEY = fffffffffffffffffffffffffffffffffffffffffffc00000000000000000000 +CIPHERTEXT = 10dffb05904bff7c4781df780ad26837 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 174 +KEY = fffffffffffffffffffffffffffffffffffffffffffe00000000000000000000 +CIPHERTEXT = c33bc13e8de88ac25232aa7496398783 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 175 +KEY = ffffffffffffffffffffffffffffffffffffffffffff00000000000000000000 +CIPHERTEXT = ca359c70803a3b2a3d542e8781dea975 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 176 +KEY = ffffffffffffffffffffffffffffffffffffffffffff80000000000000000000 +CIPHERTEXT = bcc65b526f88d05b89ce8a52021fdb06 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 177 +KEY = ffffffffffffffffffffffffffffffffffffffffffffc0000000000000000000 +CIPHERTEXT = db91a38855c8c4643851fbfb358b0109 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 178 +KEY = ffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000 +CIPHERTEXT = ca6e8893a114ae8e27d5ab03a5499610 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 179 +KEY = fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000 +CIPHERTEXT = 6629d2b8df97da728cdd8b1e7f945077 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 180 +KEY = fffffffffffffffffffffffffffffffffffffffffffff8000000000000000000 +CIPHERTEXT = 4570a5a18cfc0dd582f1d88d5c9a1720 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 181 +KEY = fffffffffffffffffffffffffffffffffffffffffffffc000000000000000000 +CIPHERTEXT = 72bc65aa8e89562e3f274d45af1cd10b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 182 +KEY = fffffffffffffffffffffffffffffffffffffffffffffe000000000000000000 +CIPHERTEXT = 98551da1a6503276ae1c77625f9ea615 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 183 +KEY = ffffffffffffffffffffffffffffffffffffffffffffff000000000000000000 +CIPHERTEXT = 0ddfe51ced7e3f4ae927daa3fe452cee +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 184 +KEY = ffffffffffffffffffffffffffffffffffffffffffffff800000000000000000 +CIPHERTEXT = db826251e4ce384b80218b0e1da1dd4c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 185 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000 +CIPHERTEXT = 2cacf728b88abbad7011ed0e64a1680c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 186 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000 +CIPHERTEXT = 330d8ee7c5677e099ac74c9994ee4cfb +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 187 +KEY = fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000 +CIPHERTEXT = edf61ae362e882ddc0167474a7a77f3a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 188 +KEY = fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000 +CIPHERTEXT = 6168b00ba7859e0970ecfd757efecf7c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 189 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000 +CIPHERTEXT = d1415447866230d28bb1ea18a4cdfd02 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 190 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000 +CIPHERTEXT = 516183392f7a8763afec68a060264141 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 191 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000 +CIPHERTEXT = 77565c8d73cfd4130b4aa14d8911710f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 192 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000 +CIPHERTEXT = 37232a4ed21ccc27c19c9610078cabac +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 193 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffc000000000000000 +CIPHERTEXT = 804f32ea71828c7d329077e712231666 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 194 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000 +CIPHERTEXT = d64424f23cb97215e9c2c6f28d29eab7 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 195 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000 +CIPHERTEXT = 023e82b533f68c75c238cebdb2ee89a2 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 196 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffff800000000000000 +CIPHERTEXT = 193a3d24157a51f1ee0893f6777417e7 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 197 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000 +CIPHERTEXT = 84ecacfcd400084d078612b1945f2ef5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 198 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000 +CIPHERTEXT = 1dcd8bb173259eb33a5242b0de31a455 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 199 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000 +CIPHERTEXT = 35e9eddbc375e792c19992c19165012b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 200 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000 +CIPHERTEXT = 8a772231c01dfdd7c98e4cfddcc0807a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 201 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000000 +CIPHERTEXT = 6eda7ff6b8319180ff0d6e65629d01c3 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 202 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000 +CIPHERTEXT = c267ef0e2d01a993944dd397101413cb +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 203 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000 +CIPHERTEXT = e9f80e9d845bcc0f62926af72eabca39 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 204 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000 +CIPHERTEXT = 6702990727aa0878637b45dcd3a3b074 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 205 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffc000000000000 +CIPHERTEXT = 2e2e647d5360e09230a5d738ca33471e +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 206 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000 +CIPHERTEXT = 1f56413c7add6f43d1d56e4f02190330 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 207 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000 +CIPHERTEXT = 69cd0606e15af729d6bca143016d9842 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 208 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000 +CIPHERTEXT = a085d7c1a500873a20099c4caa3c3f5b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 209 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000 +CIPHERTEXT = 4fc0d230f8891415b87b83f95f2e09d1 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 210 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000 +CIPHERTEXT = 4327d08c523d8eba697a4336507d1f42 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 211 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000 +CIPHERTEXT = 7a15aab82701efa5ae36ab1d6b76290f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 212 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000 +CIPHERTEXT = 5bf0051893a18bb30e139a58fed0fa54 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 213 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000000 +CIPHERTEXT = 97e8adf65638fd9cdf3bc22c17fe4dbd +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 214 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000 +CIPHERTEXT = 1ee6ee326583a0586491c96418d1a35d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 215 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000 +CIPHERTEXT = 26b549c2ec756f82ecc48008e529956b +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 216 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000 +CIPHERTEXT = 70377b6da669b072129e057cc28e9ca5 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 217 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000000 +CIPHERTEXT = 9c94b8b0cb8bcc919072262b3fa05ad9 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 218 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000 +CIPHERTEXT = 2fbb83dfd0d7abcb05cd28cad2dfb523 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 219 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000 +CIPHERTEXT = 96877803de77744bb970d0a91f4debae +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 220 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000 +CIPHERTEXT = 7379f3370cf6e5ce12ae5969c8eea312 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 221 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000 +CIPHERTEXT = 02dc99fa3d4f98ce80985e7233889313 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 222 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 +CIPHERTEXT = 1e38e759075ba5cab6457da51844295a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 223 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000 +CIPHERTEXT = 70bed8dbf615868a1f9d9b05d3e7a267 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 224 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 +CIPHERTEXT = 234b148b8cb1d8c32b287e896903d150 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 225 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000000 +CIPHERTEXT = 294b033df4da853f4be3e243f7e513f4 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 226 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000 +CIPHERTEXT = 3f58c950f0367160adec45f2441e7411 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 227 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000 +CIPHERTEXT = 37f655536a704e5ace182d742a820cf4 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 228 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000 +CIPHERTEXT = ea7bd6bb63418731aeac790fe42d61e8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 229 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000000 +CIPHERTEXT = e74a4c999b4c064e48bb1e413f51e5ea +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 230 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000 +CIPHERTEXT = ba9ebefdb4ccf30f296cecb3bc1943e8 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 231 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000 +CIPHERTEXT = 3194367a4898c502c13bb7478640a72d +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 232 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000 +CIPHERTEXT = da797713263d6f33a5478a65ef60d412 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 233 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000 +CIPHERTEXT = d1ac39bb1ef86b9c1344f214679aa376 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 234 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000 +CIPHERTEXT = 2fdea9e650532be5bc0e7325337fd363 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 235 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000 +CIPHERTEXT = d3a204dbd9c2af158b6ca67a5156ce4a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 236 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000 +CIPHERTEXT = 3a0a0e75a8da36735aee6684d965a778 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 237 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0000 +CIPHERTEXT = 52fc3e620492ea99641ea168da5b6d52 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 238 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000 +CIPHERTEXT = d2e0c7f15b4772467d2cfc873000b2ca +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 239 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000 +CIPHERTEXT = 563531135e0c4d70a38f8bdb190ba04e +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 240 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 +CIPHERTEXT = a8a39a0f5663f4c0fe5f2d3cafff421a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 241 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc000 +CIPHERTEXT = d94b5e90db354c1e42f61fabe167b2c0 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 242 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000 +CIPHERTEXT = 50e6d3c9b6698a7cd276f96b1473f35a +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 243 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000 +CIPHERTEXT = 9338f08e0ebee96905d8f2e825208f43 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 244 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800 +CIPHERTEXT = 8b378c86672aa54a3a266ba19d2580ca +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 245 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00 +CIPHERTEXT = cca7c3086f5f9511b31233da7cab9160 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 246 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00 +CIPHERTEXT = 5b40ff4ec9be536ba23035fa4f06064c +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 247 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 +CIPHERTEXT = 60eb5af8416b257149372194e8b88749 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 248 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 +CIPHERTEXT = 2f005a8aed8a361c92e440c15520cbd1 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 249 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0 +CIPHERTEXT = 7b03627611678a997717578807a800e2 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 250 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 +CIPHERTEXT = cf78618f74f6f3696e0a4779b90b5a77 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 251 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0 +CIPHERTEXT = 03720371a04962eaea0a852e69972858 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 252 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 +CIPHERTEXT = 1f8a8133aa8ccf70e2bd3285831ca6b7 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 253 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc +CIPHERTEXT = 27936bd27fb1468fc8b48bc483321725 +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 254 +KEY = fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe +CIPHERTEXT = b07d4f3e2cd2ef2eb545980754dfea0f +PLAINTEXT = 00000000000000000000000000000000 + +COUNT = 255 +KEY = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +CIPHERTEXT = 4bf85f1b5d54adbc307b0a048389adcb +PLAINTEXT = 00000000000000000000000000000000 + diff --git a/libraries/crypto/tests/data/ECBVarTxt256.rsp b/libraries/crypto/tests/data/ECBVarTxt256.rsp new file mode 100644 index 0000000..6833f60 --- /dev/null +++ b/libraries/crypto/tests/data/ECBVarTxt256.rsp @@ -0,0 +1,1291 @@ +# CAVS 11.1 +# Config info for aes_values +# AESVS VarTxt test data for ECB +# State : Encrypt and Decrypt +# Key Length : 256 +# Generated on Fri Apr 22 15:11:30 2011 + +[ENCRYPT] + +COUNT = 0 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = 80000000000000000000000000000000 +CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e + +COUNT = 1 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = c0000000000000000000000000000000 +CIPHERTEXT = 0a6bdc6d4c1e6280301fd8e97ddbe601 + +COUNT = 2 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = e0000000000000000000000000000000 +CIPHERTEXT = 9b80eefb7ebe2d2b16247aa0efc72f5d + +COUNT = 3 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = f0000000000000000000000000000000 +CIPHERTEXT = 7f2c5ece07a98d8bee13c51177395ff7 + +COUNT = 4 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = f8000000000000000000000000000000 +CIPHERTEXT = 7818d800dcf6f4be1e0e94f403d1e4c2 + +COUNT = 5 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fc000000000000000000000000000000 +CIPHERTEXT = e74cd1c92f0919c35a0324123d6177d3 + +COUNT = 6 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fe000000000000000000000000000000 +CIPHERTEXT = 8092a4dcf2da7e77e93bdd371dfed82e + +COUNT = 7 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ff000000000000000000000000000000 +CIPHERTEXT = 49af6b372135acef10132e548f217b17 + +COUNT = 8 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ff800000000000000000000000000000 +CIPHERTEXT = 8bcd40f94ebb63b9f7909676e667f1e7 + +COUNT = 9 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffc00000000000000000000000000000 +CIPHERTEXT = fe1cffb83f45dcfb38b29be438dbd3ab + +COUNT = 10 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffe00000000000000000000000000000 +CIPHERTEXT = 0dc58a8d886623705aec15cb1e70dc0e + +COUNT = 11 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fff00000000000000000000000000000 +CIPHERTEXT = c218faa16056bd0774c3e8d79c35a5e4 + +COUNT = 12 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fff80000000000000000000000000000 +CIPHERTEXT = 047bba83f7aa841731504e012208fc9e + +COUNT = 13 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffc0000000000000000000000000000 +CIPHERTEXT = dc8f0e4915fd81ba70a331310882f6da + +COUNT = 14 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffe0000000000000000000000000000 +CIPHERTEXT = 1569859ea6b7206c30bf4fd0cbfac33c + +COUNT = 15 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffff0000000000000000000000000000 +CIPHERTEXT = 300ade92f88f48fa2df730ec16ef44cd + +COUNT = 16 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffff8000000000000000000000000000 +CIPHERTEXT = 1fe6cc3c05965dc08eb0590c95ac71d0 + +COUNT = 17 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffc000000000000000000000000000 +CIPHERTEXT = 59e858eaaa97fec38111275b6cf5abc0 + +COUNT = 18 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffe000000000000000000000000000 +CIPHERTEXT = 2239455e7afe3b0616100288cc5a723b + +COUNT = 19 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffff000000000000000000000000000 +CIPHERTEXT = 3ee500c5c8d63479717163e55c5c4522 + +COUNT = 20 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffff800000000000000000000000000 +CIPHERTEXT = d5e38bf15f16d90e3e214041d774daa8 + +COUNT = 21 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffc00000000000000000000000000 +CIPHERTEXT = b1f4066e6f4f187dfe5f2ad1b17819d0 + +COUNT = 22 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffe00000000000000000000000000 +CIPHERTEXT = 6ef4cc4de49b11065d7af2909854794a + +COUNT = 23 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffff00000000000000000000000000 +CIPHERTEXT = ac86bc606b6640c309e782f232bf367f + +COUNT = 24 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffff80000000000000000000000000 +CIPHERTEXT = 36aff0ef7bf3280772cf4cac80a0d2b2 + +COUNT = 25 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffc0000000000000000000000000 +CIPHERTEXT = 1f8eedea0f62a1406d58cfc3ecea72cf + +COUNT = 26 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffe0000000000000000000000000 +CIPHERTEXT = abf4154a3375a1d3e6b1d454438f95a6 + +COUNT = 27 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffff0000000000000000000000000 +CIPHERTEXT = 96f96e9d607f6615fc192061ee648b07 + +COUNT = 28 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffff8000000000000000000000000 +CIPHERTEXT = cf37cdaaa0d2d536c71857634c792064 + +COUNT = 29 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffc000000000000000000000000 +CIPHERTEXT = fbd6640c80245c2b805373f130703127 + +COUNT = 30 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffe000000000000000000000000 +CIPHERTEXT = 8d6a8afe55a6e481badae0d146f436db + +COUNT = 31 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffff000000000000000000000000 +CIPHERTEXT = 6a4981f2915e3e68af6c22385dd06756 + +COUNT = 32 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffff800000000000000000000000 +CIPHERTEXT = 42a1136e5f8d8d21d3101998642d573b + +COUNT = 33 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffc00000000000000000000000 +CIPHERTEXT = 9b471596dc69ae1586cee6158b0b0181 + +COUNT = 34 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffe00000000000000000000000 +CIPHERTEXT = 753665c4af1eff33aa8b628bf8741cfd + +COUNT = 35 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffff00000000000000000000000 +CIPHERTEXT = 9a682acf40be01f5b2a4193c9a82404d + +COUNT = 36 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffff80000000000000000000000 +CIPHERTEXT = 54fafe26e4287f17d1935f87eb9ade01 + +COUNT = 37 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffc0000000000000000000000 +CIPHERTEXT = 49d541b2e74cfe73e6a8e8225f7bd449 + +COUNT = 38 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffe0000000000000000000000 +CIPHERTEXT = 11a45530f624ff6f76a1b3826626ff7b + +COUNT = 39 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffff0000000000000000000000 +CIPHERTEXT = f96b0c4a8bc6c86130289f60b43b8fba + +COUNT = 40 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffff8000000000000000000000 +CIPHERTEXT = 48c7d0e80834ebdc35b6735f76b46c8b + +COUNT = 41 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffc000000000000000000000 +CIPHERTEXT = 2463531ab54d66955e73edc4cb8eaa45 + +COUNT = 42 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffe000000000000000000000 +CIPHERTEXT = ac9bd8e2530469134b9d5b065d4f565b + +COUNT = 43 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffff000000000000000000000 +CIPHERTEXT = 3f5f9106d0e52f973d4890e6f37e8a00 + +COUNT = 44 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffff800000000000000000000 +CIPHERTEXT = 20ebc86f1304d272e2e207e59db639f0 + +COUNT = 45 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffc00000000000000000000 +CIPHERTEXT = e67ae6426bf9526c972cff072b52252c + +COUNT = 46 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffe00000000000000000000 +CIPHERTEXT = 1a518dddaf9efa0d002cc58d107edfc8 + +COUNT = 47 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffff00000000000000000000 +CIPHERTEXT = ead731af4d3a2fe3b34bed047942a49f + +COUNT = 48 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffff80000000000000000000 +CIPHERTEXT = b1d4efe40242f83e93b6c8d7efb5eae9 + +COUNT = 49 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffc0000000000000000000 +CIPHERTEXT = cd2b1fec11fd906c5c7630099443610a + +COUNT = 50 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffe0000000000000000000 +CIPHERTEXT = a1853fe47fe29289d153161d06387d21 + +COUNT = 51 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffff0000000000000000000 +CIPHERTEXT = 4632154179a555c17ea604d0889fab14 + +COUNT = 52 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffff8000000000000000000 +CIPHERTEXT = dd27cac6401a022e8f38f9f93e774417 + +COUNT = 53 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffc000000000000000000 +CIPHERTEXT = c090313eb98674f35f3123385fb95d4d + +COUNT = 54 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffe000000000000000000 +CIPHERTEXT = cc3526262b92f02edce548f716b9f45c + +COUNT = 55 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffff000000000000000000 +CIPHERTEXT = c0838d1a2b16a7c7f0dfcc433c399c33 + +COUNT = 56 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffff800000000000000000 +CIPHERTEXT = 0d9ac756eb297695eed4d382eb126d26 + +COUNT = 57 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffc00000000000000000 +CIPHERTEXT = 56ede9dda3f6f141bff1757fa689c3e1 + +COUNT = 58 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffe00000000000000000 +CIPHERTEXT = 768f520efe0f23e61d3ec8ad9ce91774 + +COUNT = 59 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffff00000000000000000 +CIPHERTEXT = b1144ddfa75755213390e7c596660490 + +COUNT = 60 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffff80000000000000000 +CIPHERTEXT = 1d7c0c4040b355b9d107a99325e3b050 + +COUNT = 61 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffc0000000000000000 +CIPHERTEXT = d8e2bb1ae8ee3dcf5bf7d6c38da82a1a + +COUNT = 62 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffe0000000000000000 +CIPHERTEXT = faf82d178af25a9886a47e7f789b98d7 + +COUNT = 63 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffff0000000000000000 +CIPHERTEXT = 9b58dbfd77fe5aca9cfc190cd1b82d19 + +COUNT = 64 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffff8000000000000000 +CIPHERTEXT = 77f392089042e478ac16c0c86a0b5db5 + +COUNT = 65 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffc000000000000000 +CIPHERTEXT = 19f08e3420ee69b477ca1420281c4782 + +COUNT = 66 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffe000000000000000 +CIPHERTEXT = a1b19beee4e117139f74b3c53fdcb875 + +COUNT = 67 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffff000000000000000 +CIPHERTEXT = a37a5869b218a9f3a0868d19aea0ad6a + +COUNT = 68 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffff800000000000000 +CIPHERTEXT = bc3594e865bcd0261b13202731f33580 + +COUNT = 69 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffc00000000000000 +CIPHERTEXT = 811441ce1d309eee7185e8c752c07557 + +COUNT = 70 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffe00000000000000 +CIPHERTEXT = 959971ce4134190563518e700b9874d1 + +COUNT = 71 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffff00000000000000 +CIPHERTEXT = 76b5614a042707c98e2132e2e805fe63 + +COUNT = 72 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffff80000000000000 +CIPHERTEXT = 7d9fa6a57530d0f036fec31c230b0cc6 + +COUNT = 73 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffc0000000000000 +CIPHERTEXT = 964153a83bf6989a4ba80daa91c3e081 + +COUNT = 74 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffe0000000000000 +CIPHERTEXT = a013014d4ce8054cf2591d06f6f2f176 + +COUNT = 75 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffff0000000000000 +CIPHERTEXT = d1c5f6399bf382502e385eee1474a869 + +COUNT = 76 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffff8000000000000 +CIPHERTEXT = 0007e20b8298ec354f0f5fe7470f36bd + +COUNT = 77 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffc000000000000 +CIPHERTEXT = b95ba05b332da61ef63a2b31fcad9879 + +COUNT = 78 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffe000000000000 +CIPHERTEXT = 4620a49bd967491561669ab25dce45f4 + +COUNT = 79 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffff000000000000 +CIPHERTEXT = 12e71214ae8e04f0bb63d7425c6f14d5 + +COUNT = 80 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffff800000000000 +CIPHERTEXT = 4cc42fc1407b008fe350907c092e80ac + +COUNT = 81 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffc00000000000 +CIPHERTEXT = 08b244ce7cbc8ee97fbba808cb146fda + +COUNT = 82 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffe00000000000 +CIPHERTEXT = 39b333e8694f21546ad1edd9d87ed95b + +COUNT = 83 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffff00000000000 +CIPHERTEXT = 3b271f8ab2e6e4a20ba8090f43ba78f3 + +COUNT = 84 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffff80000000000 +CIPHERTEXT = 9ad983f3bf651cd0393f0a73cccdea50 + +COUNT = 85 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffc0000000000 +CIPHERTEXT = 8f476cbff75c1f725ce18e4bbcd19b32 + +COUNT = 86 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffe0000000000 +CIPHERTEXT = 905b6267f1d6ab5320835a133f096f2a + +COUNT = 87 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffff0000000000 +CIPHERTEXT = 145b60d6d0193c23f4221848a892d61a + +COUNT = 88 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffff8000000000 +CIPHERTEXT = 55cfb3fb6d75cad0445bbc8dafa25b0f + +COUNT = 89 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffc000000000 +CIPHERTEXT = 7b8e7098e357ef71237d46d8b075b0f5 + +COUNT = 90 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffe000000000 +CIPHERTEXT = 2bf27229901eb40f2df9d8398d1505ae + +COUNT = 91 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffff000000000 +CIPHERTEXT = 83a63402a77f9ad5c1e931a931ecd706 + +COUNT = 92 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffff800000000 +CIPHERTEXT = 6f8ba6521152d31f2bada1843e26b973 + +COUNT = 93 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffc00000000 +CIPHERTEXT = e5c3b8e30fd2d8e6239b17b44bd23bbd + +COUNT = 94 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffe00000000 +CIPHERTEXT = 1ac1f7102c59933e8b2ddc3f14e94baa + +COUNT = 95 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffff00000000 +CIPHERTEXT = 21d9ba49f276b45f11af8fc71a088e3d + +COUNT = 96 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffff80000000 +CIPHERTEXT = 649f1cddc3792b4638635a392bc9bade + +COUNT = 97 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffc0000000 +CIPHERTEXT = e2775e4b59c1bc2e31a2078c11b5a08c + +COUNT = 98 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffe0000000 +CIPHERTEXT = 2be1fae5048a25582a679ca10905eb80 + +COUNT = 99 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffff0000000 +CIPHERTEXT = da86f292c6f41ea34fb2068df75ecc29 + +COUNT = 100 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffff8000000 +CIPHERTEXT = 220df19f85d69b1b562fa69a3c5beca5 + +COUNT = 101 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffc000000 +CIPHERTEXT = 1f11d5d0355e0b556ccdb6c7f5083b4d + +COUNT = 102 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffe000000 +CIPHERTEXT = 62526b78be79cb384633c91f83b4151b + +COUNT = 103 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffff000000 +CIPHERTEXT = 90ddbcb950843592dd47bbef00fdc876 + +COUNT = 104 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffff800000 +CIPHERTEXT = 2fd0e41c5b8402277354a7391d2618e2 + +COUNT = 105 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffc00000 +CIPHERTEXT = 3cdf13e72dee4c581bafec70b85f9660 + +COUNT = 106 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffe00000 +CIPHERTEXT = afa2ffc137577092e2b654fa199d2c43 + +COUNT = 107 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffff00000 +CIPHERTEXT = 8d683ee63e60d208e343ce48dbc44cac + +COUNT = 108 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffff80000 +CIPHERTEXT = 705a4ef8ba2133729c20185c3d3a4763 + +COUNT = 109 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffc0000 +CIPHERTEXT = 0861a861c3db4e94194211b77ed761b9 + +COUNT = 110 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffe0000 +CIPHERTEXT = 4b00c27e8b26da7eab9d3a88dec8b031 + +COUNT = 111 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffff0000 +CIPHERTEXT = 5f397bf03084820cc8810d52e5b666e9 + +COUNT = 112 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffff8000 +CIPHERTEXT = 63fafabb72c07bfbd3ddc9b1203104b8 + +COUNT = 113 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffc000 +CIPHERTEXT = 683e2140585b18452dd4ffbb93c95df9 + +COUNT = 114 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffe000 +CIPHERTEXT = 286894e48e537f8763b56707d7d155c8 + +COUNT = 115 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffff000 +CIPHERTEXT = a423deabc173dcf7e2c4c53e77d37cd1 + +COUNT = 116 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffff800 +CIPHERTEXT = eb8168313e1cfdfdb5e986d5429cf172 + +COUNT = 117 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffc00 +CIPHERTEXT = 27127daafc9accd2fb334ec3eba52323 + +COUNT = 118 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffe00 +CIPHERTEXT = ee0715b96f72e3f7a22a5064fc592f4c + +COUNT = 119 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffff00 +CIPHERTEXT = 29ee526770f2a11dcfa989d1ce88830f + +COUNT = 120 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffff80 +CIPHERTEXT = 0493370e054b09871130fe49af730a5a + +COUNT = 121 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffc0 +CIPHERTEXT = 9b7b940f6c509f9e44a4ee140448ee46 + +COUNT = 122 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffe0 +CIPHERTEXT = 2915be4a1ecfdcbe3e023811a12bb6c7 + +COUNT = 123 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffff0 +CIPHERTEXT = 7240e524bc51d8c4d440b1be55d1062c + +COUNT = 124 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffff8 +CIPHERTEXT = da63039d38cb4612b2dc36ba26684b93 + +COUNT = 125 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffffc +CIPHERTEXT = 0f59cb5a4b522e2ac56c1a64f558ad9a + +COUNT = 126 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = fffffffffffffffffffffffffffffffe +CIPHERTEXT = 7bfe9d876c6d63c1d035da8fe21c409d + +COUNT = 127 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +PLAINTEXT = ffffffffffffffffffffffffffffffff +CIPHERTEXT = acdace8078a32b1a182bfa4987ca1347 + +[DECRYPT] + +COUNT = 0 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e +PLAINTEXT = 80000000000000000000000000000000 + +COUNT = 1 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0a6bdc6d4c1e6280301fd8e97ddbe601 +PLAINTEXT = c0000000000000000000000000000000 + +COUNT = 2 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9b80eefb7ebe2d2b16247aa0efc72f5d +PLAINTEXT = e0000000000000000000000000000000 + +COUNT = 3 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 7f2c5ece07a98d8bee13c51177395ff7 +PLAINTEXT = f0000000000000000000000000000000 + +COUNT = 4 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 7818d800dcf6f4be1e0e94f403d1e4c2 +PLAINTEXT = f8000000000000000000000000000000 + +COUNT = 5 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = e74cd1c92f0919c35a0324123d6177d3 +PLAINTEXT = fc000000000000000000000000000000 + +COUNT = 6 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8092a4dcf2da7e77e93bdd371dfed82e +PLAINTEXT = fe000000000000000000000000000000 + +COUNT = 7 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 49af6b372135acef10132e548f217b17 +PLAINTEXT = ff000000000000000000000000000000 + +COUNT = 8 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8bcd40f94ebb63b9f7909676e667f1e7 +PLAINTEXT = ff800000000000000000000000000000 + +COUNT = 9 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = fe1cffb83f45dcfb38b29be438dbd3ab +PLAINTEXT = ffc00000000000000000000000000000 + +COUNT = 10 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0dc58a8d886623705aec15cb1e70dc0e +PLAINTEXT = ffe00000000000000000000000000000 + +COUNT = 11 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = c218faa16056bd0774c3e8d79c35a5e4 +PLAINTEXT = fff00000000000000000000000000000 + +COUNT = 12 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 047bba83f7aa841731504e012208fc9e +PLAINTEXT = fff80000000000000000000000000000 + +COUNT = 13 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = dc8f0e4915fd81ba70a331310882f6da +PLAINTEXT = fffc0000000000000000000000000000 + +COUNT = 14 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1569859ea6b7206c30bf4fd0cbfac33c +PLAINTEXT = fffe0000000000000000000000000000 + +COUNT = 15 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 300ade92f88f48fa2df730ec16ef44cd +PLAINTEXT = ffff0000000000000000000000000000 + +COUNT = 16 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1fe6cc3c05965dc08eb0590c95ac71d0 +PLAINTEXT = ffff8000000000000000000000000000 + +COUNT = 17 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 59e858eaaa97fec38111275b6cf5abc0 +PLAINTEXT = ffffc000000000000000000000000000 + +COUNT = 18 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2239455e7afe3b0616100288cc5a723b +PLAINTEXT = ffffe000000000000000000000000000 + +COUNT = 19 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3ee500c5c8d63479717163e55c5c4522 +PLAINTEXT = fffff000000000000000000000000000 + +COUNT = 20 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = d5e38bf15f16d90e3e214041d774daa8 +PLAINTEXT = fffff800000000000000000000000000 + +COUNT = 21 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = b1f4066e6f4f187dfe5f2ad1b17819d0 +PLAINTEXT = fffffc00000000000000000000000000 + +COUNT = 22 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 6ef4cc4de49b11065d7af2909854794a +PLAINTEXT = fffffe00000000000000000000000000 + +COUNT = 23 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ac86bc606b6640c309e782f232bf367f +PLAINTEXT = ffffff00000000000000000000000000 + +COUNT = 24 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 36aff0ef7bf3280772cf4cac80a0d2b2 +PLAINTEXT = ffffff80000000000000000000000000 + +COUNT = 25 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1f8eedea0f62a1406d58cfc3ecea72cf +PLAINTEXT = ffffffc0000000000000000000000000 + +COUNT = 26 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = abf4154a3375a1d3e6b1d454438f95a6 +PLAINTEXT = ffffffe0000000000000000000000000 + +COUNT = 27 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 96f96e9d607f6615fc192061ee648b07 +PLAINTEXT = fffffff0000000000000000000000000 + +COUNT = 28 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = cf37cdaaa0d2d536c71857634c792064 +PLAINTEXT = fffffff8000000000000000000000000 + +COUNT = 29 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = fbd6640c80245c2b805373f130703127 +PLAINTEXT = fffffffc000000000000000000000000 + +COUNT = 30 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8d6a8afe55a6e481badae0d146f436db +PLAINTEXT = fffffffe000000000000000000000000 + +COUNT = 31 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 6a4981f2915e3e68af6c22385dd06756 +PLAINTEXT = ffffffff000000000000000000000000 + +COUNT = 32 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 42a1136e5f8d8d21d3101998642d573b +PLAINTEXT = ffffffff800000000000000000000000 + +COUNT = 33 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9b471596dc69ae1586cee6158b0b0181 +PLAINTEXT = ffffffffc00000000000000000000000 + +COUNT = 34 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 753665c4af1eff33aa8b628bf8741cfd +PLAINTEXT = ffffffffe00000000000000000000000 + +COUNT = 35 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9a682acf40be01f5b2a4193c9a82404d +PLAINTEXT = fffffffff00000000000000000000000 + +COUNT = 36 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 54fafe26e4287f17d1935f87eb9ade01 +PLAINTEXT = fffffffff80000000000000000000000 + +COUNT = 37 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 49d541b2e74cfe73e6a8e8225f7bd449 +PLAINTEXT = fffffffffc0000000000000000000000 + +COUNT = 38 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 11a45530f624ff6f76a1b3826626ff7b +PLAINTEXT = fffffffffe0000000000000000000000 + +COUNT = 39 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = f96b0c4a8bc6c86130289f60b43b8fba +PLAINTEXT = ffffffffff0000000000000000000000 + +COUNT = 40 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 48c7d0e80834ebdc35b6735f76b46c8b +PLAINTEXT = ffffffffff8000000000000000000000 + +COUNT = 41 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2463531ab54d66955e73edc4cb8eaa45 +PLAINTEXT = ffffffffffc000000000000000000000 + +COUNT = 42 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ac9bd8e2530469134b9d5b065d4f565b +PLAINTEXT = ffffffffffe000000000000000000000 + +COUNT = 43 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3f5f9106d0e52f973d4890e6f37e8a00 +PLAINTEXT = fffffffffff000000000000000000000 + +COUNT = 44 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 20ebc86f1304d272e2e207e59db639f0 +PLAINTEXT = fffffffffff800000000000000000000 + +COUNT = 45 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = e67ae6426bf9526c972cff072b52252c +PLAINTEXT = fffffffffffc00000000000000000000 + +COUNT = 46 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1a518dddaf9efa0d002cc58d107edfc8 +PLAINTEXT = fffffffffffe00000000000000000000 + +COUNT = 47 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ead731af4d3a2fe3b34bed047942a49f +PLAINTEXT = ffffffffffff00000000000000000000 + +COUNT = 48 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = b1d4efe40242f83e93b6c8d7efb5eae9 +PLAINTEXT = ffffffffffff80000000000000000000 + +COUNT = 49 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = cd2b1fec11fd906c5c7630099443610a +PLAINTEXT = ffffffffffffc0000000000000000000 + +COUNT = 50 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a1853fe47fe29289d153161d06387d21 +PLAINTEXT = ffffffffffffe0000000000000000000 + +COUNT = 51 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 4632154179a555c17ea604d0889fab14 +PLAINTEXT = fffffffffffff0000000000000000000 + +COUNT = 52 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = dd27cac6401a022e8f38f9f93e774417 +PLAINTEXT = fffffffffffff8000000000000000000 + +COUNT = 53 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = c090313eb98674f35f3123385fb95d4d +PLAINTEXT = fffffffffffffc000000000000000000 + +COUNT = 54 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = cc3526262b92f02edce548f716b9f45c +PLAINTEXT = fffffffffffffe000000000000000000 + +COUNT = 55 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = c0838d1a2b16a7c7f0dfcc433c399c33 +PLAINTEXT = ffffffffffffff000000000000000000 + +COUNT = 56 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0d9ac756eb297695eed4d382eb126d26 +PLAINTEXT = ffffffffffffff800000000000000000 + +COUNT = 57 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 56ede9dda3f6f141bff1757fa689c3e1 +PLAINTEXT = ffffffffffffffc00000000000000000 + +COUNT = 58 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 768f520efe0f23e61d3ec8ad9ce91774 +PLAINTEXT = ffffffffffffffe00000000000000000 + +COUNT = 59 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = b1144ddfa75755213390e7c596660490 +PLAINTEXT = fffffffffffffff00000000000000000 + +COUNT = 60 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1d7c0c4040b355b9d107a99325e3b050 +PLAINTEXT = fffffffffffffff80000000000000000 + +COUNT = 61 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = d8e2bb1ae8ee3dcf5bf7d6c38da82a1a +PLAINTEXT = fffffffffffffffc0000000000000000 + +COUNT = 62 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = faf82d178af25a9886a47e7f789b98d7 +PLAINTEXT = fffffffffffffffe0000000000000000 + +COUNT = 63 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9b58dbfd77fe5aca9cfc190cd1b82d19 +PLAINTEXT = ffffffffffffffff0000000000000000 + +COUNT = 64 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 77f392089042e478ac16c0c86a0b5db5 +PLAINTEXT = ffffffffffffffff8000000000000000 + +COUNT = 65 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 19f08e3420ee69b477ca1420281c4782 +PLAINTEXT = ffffffffffffffffc000000000000000 + +COUNT = 66 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a1b19beee4e117139f74b3c53fdcb875 +PLAINTEXT = ffffffffffffffffe000000000000000 + +COUNT = 67 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a37a5869b218a9f3a0868d19aea0ad6a +PLAINTEXT = fffffffffffffffff000000000000000 + +COUNT = 68 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = bc3594e865bcd0261b13202731f33580 +PLAINTEXT = fffffffffffffffff800000000000000 + +COUNT = 69 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 811441ce1d309eee7185e8c752c07557 +PLAINTEXT = fffffffffffffffffc00000000000000 + +COUNT = 70 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 959971ce4134190563518e700b9874d1 +PLAINTEXT = fffffffffffffffffe00000000000000 + +COUNT = 71 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 76b5614a042707c98e2132e2e805fe63 +PLAINTEXT = ffffffffffffffffff00000000000000 + +COUNT = 72 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 7d9fa6a57530d0f036fec31c230b0cc6 +PLAINTEXT = ffffffffffffffffff80000000000000 + +COUNT = 73 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 964153a83bf6989a4ba80daa91c3e081 +PLAINTEXT = ffffffffffffffffffc0000000000000 + +COUNT = 74 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a013014d4ce8054cf2591d06f6f2f176 +PLAINTEXT = ffffffffffffffffffe0000000000000 + +COUNT = 75 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = d1c5f6399bf382502e385eee1474a869 +PLAINTEXT = fffffffffffffffffff0000000000000 + +COUNT = 76 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0007e20b8298ec354f0f5fe7470f36bd +PLAINTEXT = fffffffffffffffffff8000000000000 + +COUNT = 77 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = b95ba05b332da61ef63a2b31fcad9879 +PLAINTEXT = fffffffffffffffffffc000000000000 + +COUNT = 78 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 4620a49bd967491561669ab25dce45f4 +PLAINTEXT = fffffffffffffffffffe000000000000 + +COUNT = 79 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 12e71214ae8e04f0bb63d7425c6f14d5 +PLAINTEXT = ffffffffffffffffffff000000000000 + +COUNT = 80 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 4cc42fc1407b008fe350907c092e80ac +PLAINTEXT = ffffffffffffffffffff800000000000 + +COUNT = 81 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 08b244ce7cbc8ee97fbba808cb146fda +PLAINTEXT = ffffffffffffffffffffc00000000000 + +COUNT = 82 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 39b333e8694f21546ad1edd9d87ed95b +PLAINTEXT = ffffffffffffffffffffe00000000000 + +COUNT = 83 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3b271f8ab2e6e4a20ba8090f43ba78f3 +PLAINTEXT = fffffffffffffffffffff00000000000 + +COUNT = 84 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9ad983f3bf651cd0393f0a73cccdea50 +PLAINTEXT = fffffffffffffffffffff80000000000 + +COUNT = 85 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8f476cbff75c1f725ce18e4bbcd19b32 +PLAINTEXT = fffffffffffffffffffffc0000000000 + +COUNT = 86 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 905b6267f1d6ab5320835a133f096f2a +PLAINTEXT = fffffffffffffffffffffe0000000000 + +COUNT = 87 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 145b60d6d0193c23f4221848a892d61a +PLAINTEXT = ffffffffffffffffffffff0000000000 + +COUNT = 88 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 55cfb3fb6d75cad0445bbc8dafa25b0f +PLAINTEXT = ffffffffffffffffffffff8000000000 + +COUNT = 89 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 7b8e7098e357ef71237d46d8b075b0f5 +PLAINTEXT = ffffffffffffffffffffffc000000000 + +COUNT = 90 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2bf27229901eb40f2df9d8398d1505ae +PLAINTEXT = ffffffffffffffffffffffe000000000 + +COUNT = 91 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 83a63402a77f9ad5c1e931a931ecd706 +PLAINTEXT = fffffffffffffffffffffff000000000 + +COUNT = 92 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 6f8ba6521152d31f2bada1843e26b973 +PLAINTEXT = fffffffffffffffffffffff800000000 + +COUNT = 93 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = e5c3b8e30fd2d8e6239b17b44bd23bbd +PLAINTEXT = fffffffffffffffffffffffc00000000 + +COUNT = 94 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1ac1f7102c59933e8b2ddc3f14e94baa +PLAINTEXT = fffffffffffffffffffffffe00000000 + +COUNT = 95 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 21d9ba49f276b45f11af8fc71a088e3d +PLAINTEXT = ffffffffffffffffffffffff00000000 + +COUNT = 96 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 649f1cddc3792b4638635a392bc9bade +PLAINTEXT = ffffffffffffffffffffffff80000000 + +COUNT = 97 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = e2775e4b59c1bc2e31a2078c11b5a08c +PLAINTEXT = ffffffffffffffffffffffffc0000000 + +COUNT = 98 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2be1fae5048a25582a679ca10905eb80 +PLAINTEXT = ffffffffffffffffffffffffe0000000 + +COUNT = 99 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = da86f292c6f41ea34fb2068df75ecc29 +PLAINTEXT = fffffffffffffffffffffffff0000000 + +COUNT = 100 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 220df19f85d69b1b562fa69a3c5beca5 +PLAINTEXT = fffffffffffffffffffffffff8000000 + +COUNT = 101 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 1f11d5d0355e0b556ccdb6c7f5083b4d +PLAINTEXT = fffffffffffffffffffffffffc000000 + +COUNT = 102 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 62526b78be79cb384633c91f83b4151b +PLAINTEXT = fffffffffffffffffffffffffe000000 + +COUNT = 103 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 90ddbcb950843592dd47bbef00fdc876 +PLAINTEXT = ffffffffffffffffffffffffff000000 + +COUNT = 104 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2fd0e41c5b8402277354a7391d2618e2 +PLAINTEXT = ffffffffffffffffffffffffff800000 + +COUNT = 105 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 3cdf13e72dee4c581bafec70b85f9660 +PLAINTEXT = ffffffffffffffffffffffffffc00000 + +COUNT = 106 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = afa2ffc137577092e2b654fa199d2c43 +PLAINTEXT = ffffffffffffffffffffffffffe00000 + +COUNT = 107 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 8d683ee63e60d208e343ce48dbc44cac +PLAINTEXT = fffffffffffffffffffffffffff00000 + +COUNT = 108 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 705a4ef8ba2133729c20185c3d3a4763 +PLAINTEXT = fffffffffffffffffffffffffff80000 + +COUNT = 109 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0861a861c3db4e94194211b77ed761b9 +PLAINTEXT = fffffffffffffffffffffffffffc0000 + +COUNT = 110 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 4b00c27e8b26da7eab9d3a88dec8b031 +PLAINTEXT = fffffffffffffffffffffffffffe0000 + +COUNT = 111 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 5f397bf03084820cc8810d52e5b666e9 +PLAINTEXT = ffffffffffffffffffffffffffff0000 + +COUNT = 112 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 63fafabb72c07bfbd3ddc9b1203104b8 +PLAINTEXT = ffffffffffffffffffffffffffff8000 + +COUNT = 113 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 683e2140585b18452dd4ffbb93c95df9 +PLAINTEXT = ffffffffffffffffffffffffffffc000 + +COUNT = 114 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 286894e48e537f8763b56707d7d155c8 +PLAINTEXT = ffffffffffffffffffffffffffffe000 + +COUNT = 115 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = a423deabc173dcf7e2c4c53e77d37cd1 +PLAINTEXT = fffffffffffffffffffffffffffff000 + +COUNT = 116 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = eb8168313e1cfdfdb5e986d5429cf172 +PLAINTEXT = fffffffffffffffffffffffffffff800 + +COUNT = 117 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 27127daafc9accd2fb334ec3eba52323 +PLAINTEXT = fffffffffffffffffffffffffffffc00 + +COUNT = 118 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = ee0715b96f72e3f7a22a5064fc592f4c +PLAINTEXT = fffffffffffffffffffffffffffffe00 + +COUNT = 119 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 29ee526770f2a11dcfa989d1ce88830f +PLAINTEXT = ffffffffffffffffffffffffffffff00 + +COUNT = 120 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0493370e054b09871130fe49af730a5a +PLAINTEXT = ffffffffffffffffffffffffffffff80 + +COUNT = 121 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 9b7b940f6c509f9e44a4ee140448ee46 +PLAINTEXT = ffffffffffffffffffffffffffffffc0 + +COUNT = 122 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 2915be4a1ecfdcbe3e023811a12bb6c7 +PLAINTEXT = ffffffffffffffffffffffffffffffe0 + +COUNT = 123 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 7240e524bc51d8c4d440b1be55d1062c +PLAINTEXT = fffffffffffffffffffffffffffffff0 + +COUNT = 124 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = da63039d38cb4612b2dc36ba26684b93 +PLAINTEXT = fffffffffffffffffffffffffffffff8 + +COUNT = 125 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 0f59cb5a4b522e2ac56c1a64f558ad9a +PLAINTEXT = fffffffffffffffffffffffffffffffc + +COUNT = 126 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = 7bfe9d876c6d63c1d035da8fe21c409d +PLAINTEXT = fffffffffffffffffffffffffffffffe + +COUNT = 127 +KEY = 0000000000000000000000000000000000000000000000000000000000000000 +CIPHERTEXT = acdace8078a32b1a182bfa4987ca1347 +PLAINTEXT = ffffffffffffffffffffffffffffffff + diff --git a/libraries/crypto/tests/data/ecdsa_secp256r1_sha256_test.json b/libraries/crypto/tests/data/ecdsa_secp256r1_sha256_test.json new file mode 100644 index 0000000..0b8ab9f --- /dev/null +++ b/libraries/crypto/tests/data/ecdsa_secp256r1_sha256_test.json @@ -0,0 +1,4578 @@ +{ + "algorithm" : "ECDSA", + "generatorVersion" : "0.8r12", + "numberOfTests" : 387, + "header" : [ + "Test vectors of type EcdsaVerify are meant for the verification", + "of ASN encoded ECDSA signatures." + ], + "notes" : { + "BER" : "This is a signature with correct values for (r, s) but using some alternative BER encoding instead of DER encoding. Implementations should not accept such signatures to limit signature malleability.", + "EdgeCase" : "Edge case values such as r=1 and s=0 can lead to forgeries if the ECDSA implementation does not check boundaries and computes s^(-1)==0.", + "MissingZero" : "Some implementations of ECDSA and DSA incorrectly encode r and s by not including leading zeros in the ASN encoding of integers when necessary. Hence, some implementations (e.g. jdk) allow signatures with incorrect ASN encodings assuming that the signature is otherwise valid.", + "PointDuplication" : "Some implementations of ECDSA do not handle duplication and points at infinity correctly. This is a test vector that has been specially crafted to check for such an omission." + }, + "schema" : "ecdsa_verify_schema.json", + "testGroups" : [ + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "wx" : "2927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838", + "wy" : "00c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKSexBRK64+3c/kZ4KBKLrSkDJpkZ\n9whgacjE32xzKDjHeHlk6qwA5ZIfsUmKYPRgZ2az2WhQAVWNGpdOc0FRPg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 1, + "comment" : "signature malleability", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 2, + "comment" : "Legacy:ASN encoding of s misses leading 0", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "acceptable", + "flags" : [ + "MissingZero" + ] + }, + { + "tcId" : 3, + "comment" : "valid", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 4, + "comment" : "long form encoding of length of sequence", + "msg" : "313233343030", + "sig" : "30814502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 5, + "comment" : "length of sequence contains leading 0", + "msg" : "313233343030", + "sig" : "3082004502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 6, + "comment" : "wrong length of sequence", + "msg" : "313233343030", + "sig" : "304602202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 7, + "comment" : "wrong length of sequence", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 8, + "comment" : "uint32 overflow in length of sequence", + "msg" : "313233343030", + "sig" : "3085010000004502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 9, + "comment" : "uint64 overflow in length of sequence", + "msg" : "313233343030", + "sig" : "308901000000000000004502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 10, + "comment" : "length of sequence = 2**31 - 1", + "msg" : "313233343030", + "sig" : "30847fffffff02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 11, + "comment" : "length of sequence = 2**32 - 1", + "msg" : "313233343030", + "sig" : "3084ffffffff02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 12, + "comment" : "length of sequence = 2**40 - 1", + "msg" : "313233343030", + "sig" : "3085ffffffffff02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 13, + "comment" : "length of sequence = 2**64 - 1", + "msg" : "313233343030", + "sig" : "3088ffffffffffffffff02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 14, + "comment" : "incorrect length of sequence", + "msg" : "313233343030", + "sig" : "30ff02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 15, + "comment" : "indefinite length without termination", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 16, + "comment" : "indefinite length without termination", + "msg" : "313233343030", + "sig" : "304502802ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 17, + "comment" : "indefinite length without termination", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18028000b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 18, + "comment" : "removing sequence", + "msg" : "313233343030", + "sig" : "", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 19, + "comment" : "lonely sequence tag", + "msg" : "313233343030", + "sig" : "30", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 20, + "comment" : "appending 0's to sequence", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 21, + "comment" : "prepending 0's to sequence", + "msg" : "313233343030", + "sig" : "3047000002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 22, + "comment" : "appending unused 0's to sequence", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 23, + "comment" : "appending null value to sequence", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0500", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 24, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "304a498177304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 25, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "30492500304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 26, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "3047304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0004deadbeef", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 27, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "304a222549817702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 28, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "30492224250002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 29, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "304d222202202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180004deadbeef022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 30, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "304a02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e182226498177022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 31, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "304902202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1822252500022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 32, + "comment" : "including garbage", + "msg" : "313233343030", + "sig" : "304d02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e182223022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0004deadbeef", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 33, + "comment" : "including undefined tags", + "msg" : "313233343030", + "sig" : "304daa00bb00cd00304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 34, + "comment" : "including undefined tags", + "msg" : "313233343030", + "sig" : "304baa02aabb304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 35, + "comment" : "including undefined tags", + "msg" : "313233343030", + "sig" : "304d2228aa00bb00cd0002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 36, + "comment" : "including undefined tags", + "msg" : "313233343030", + "sig" : "304b2226aa02aabb02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 37, + "comment" : "including undefined tags", + "msg" : "313233343030", + "sig" : "304d02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e182229aa00bb00cd00022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 38, + "comment" : "including undefined tags", + "msg" : "313233343030", + "sig" : "304b02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e182227aa02aabb022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 39, + "comment" : "truncated length of sequence", + "msg" : "313233343030", + "sig" : "3081", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 40, + "comment" : "using composition with indefinite length", + "msg" : "313233343030", + "sig" : "3080304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 41, + "comment" : "using composition with indefinite length", + "msg" : "313233343030", + "sig" : "3049228002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180000022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 42, + "comment" : "using composition with indefinite length", + "msg" : "313233343030", + "sig" : "304902202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e182280022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 43, + "comment" : "using composition with wrong tag", + "msg" : "313233343030", + "sig" : "3080314502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 44, + "comment" : "using composition with wrong tag", + "msg" : "313233343030", + "sig" : "3049228003202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180000022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 45, + "comment" : "using composition with wrong tag", + "msg" : "313233343030", + "sig" : "304902202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e182280032100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 46, + "comment" : "Replacing sequence with NULL", + "msg" : "313233343030", + "sig" : "0500", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 47, + "comment" : "changing tag value of sequence", + "msg" : "313233343030", + "sig" : "2e4502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 48, + "comment" : "changing tag value of sequence", + "msg" : "313233343030", + "sig" : "2f4502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 49, + "comment" : "changing tag value of sequence", + "msg" : "313233343030", + "sig" : "314502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 50, + "comment" : "changing tag value of sequence", + "msg" : "313233343030", + "sig" : "324502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 51, + "comment" : "changing tag value of sequence", + "msg" : "313233343030", + "sig" : "ff4502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 52, + "comment" : "dropping value of sequence", + "msg" : "313233343030", + "sig" : "3000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 53, + "comment" : "using composition for sequence", + "msg" : "313233343030", + "sig" : "30493001023044202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 54, + "comment" : "truncated sequence", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 55, + "comment" : "truncated sequence", + "msg" : "313233343030", + "sig" : "3044202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 56, + "comment" : "indefinite length", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 57, + "comment" : "indefinite length with truncated delimiter", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db00", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 58, + "comment" : "indefinite length with additional element", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db05000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 59, + "comment" : "indefinite length with truncated element", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db060811220000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 60, + "comment" : "indefinite length with garbage", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000fe02beef", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 61, + "comment" : "indefinite length with nonempty EOC", + "msg" : "313233343030", + "sig" : "308002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0002beef", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 62, + "comment" : "prepend empty sequence", + "msg" : "313233343030", + "sig" : "3047300002202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 63, + "comment" : "append empty sequence", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db3000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 64, + "comment" : "append garbage with high tag number", + "msg" : "313233343030", + "sig" : "304802202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847dbbf7f00", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 65, + "comment" : "sequence of sequence", + "msg" : "313233343030", + "sig" : "3047304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 66, + "comment" : "truncated sequence: removed last 1 elements", + "msg" : "313233343030", + "sig" : "302202202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 67, + "comment" : "repeating element in sequence", + "msg" : "313233343030", + "sig" : "306802202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 68, + "comment" : "long form encoding of length of integer", + "msg" : "313233343030", + "sig" : "30460281202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 69, + "comment" : "long form encoding of length of integer", + "msg" : "313233343030", + "sig" : "304602202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802812100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 70, + "comment" : "length of integer contains leading 0", + "msg" : "313233343030", + "sig" : "3047028200202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 71, + "comment" : "length of integer contains leading 0", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180282002100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 72, + "comment" : "wrong length of integer", + "msg" : "313233343030", + "sig" : "304502212ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 73, + "comment" : "wrong length of integer", + "msg" : "313233343030", + "sig" : "3045021f2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 74, + "comment" : "wrong length of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022200b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 75, + "comment" : "wrong length of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022000b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 76, + "comment" : "uint32 overflow in length of integer", + "msg" : "313233343030", + "sig" : "304a028501000000202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 77, + "comment" : "uint32 overflow in length of integer", + "msg" : "313233343030", + "sig" : "304a02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180285010000002100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 78, + "comment" : "uint64 overflow in length of integer", + "msg" : "313233343030", + "sig" : "304e02890100000000000000202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 79, + "comment" : "uint64 overflow in length of integer", + "msg" : "313233343030", + "sig" : "304e02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18028901000000000000002100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 80, + "comment" : "length of integer = 2**31 - 1", + "msg" : "313233343030", + "sig" : "304902847fffffff2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 81, + "comment" : "length of integer = 2**31 - 1", + "msg" : "313233343030", + "sig" : "304902202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802847fffffff00b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 82, + "comment" : "length of integer = 2**32 - 1", + "msg" : "313233343030", + "sig" : "30490284ffffffff2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 83, + "comment" : "length of integer = 2**32 - 1", + "msg" : "313233343030", + "sig" : "304902202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180284ffffffff00b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 84, + "comment" : "length of integer = 2**40 - 1", + "msg" : "313233343030", + "sig" : "304a0285ffffffffff2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 85, + "comment" : "length of integer = 2**40 - 1", + "msg" : "313233343030", + "sig" : "304a02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180285ffffffffff00b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 86, + "comment" : "length of integer = 2**64 - 1", + "msg" : "313233343030", + "sig" : "304d0288ffffffffffffffff2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 87, + "comment" : "length of integer = 2**64 - 1", + "msg" : "313233343030", + "sig" : "304d02202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180288ffffffffffffffff00b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 88, + "comment" : "incorrect length of integer", + "msg" : "313233343030", + "sig" : "304502ff2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 89, + "comment" : "incorrect length of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802ff00b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 90, + "comment" : "removing integer", + "msg" : "313233343030", + "sig" : "3023022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 91, + "comment" : "lonely integer tag", + "msg" : "313233343030", + "sig" : "302402022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 92, + "comment" : "lonely integer tag", + "msg" : "313233343030", + "sig" : "302302202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 93, + "comment" : "appending 0's to integer", + "msg" : "313233343030", + "sig" : "304702222ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180000022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 94, + "comment" : "appending 0's to integer", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022300b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 95, + "comment" : "prepending 0's to integer", + "msg" : "313233343030", + "sig" : "3047022200002ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 96, + "comment" : "prepending 0's to integer", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180223000000b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [ + "BER" + ] + }, + { + "tcId" : 97, + "comment" : "appending unused 0's to integer", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180000022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 98, + "comment" : "appending null value to integer", + "msg" : "313233343030", + "sig" : "304702222ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180500022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 99, + "comment" : "appending null value to integer", + "msg" : "313233343030", + "sig" : "304702202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022300b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db0500", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 100, + "comment" : "truncated length of integer", + "msg" : "313233343030", + "sig" : "30250281022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 101, + "comment" : "truncated length of integer", + "msg" : "313233343030", + "sig" : "302402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180281", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 102, + "comment" : "Replacing integer with NULL", + "msg" : "313233343030", + "sig" : "30250500022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 103, + "comment" : "Replacing integer with NULL", + "msg" : "313233343030", + "sig" : "302402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180500", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 104, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304500202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 105, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304501202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 106, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304503202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 107, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304504202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 108, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "3045ff202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 109, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18002100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 110, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18012100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 111, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18032100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 112, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18042100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 113, + "comment" : "changing tag value of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18ff2100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 114, + "comment" : "dropping value of integer", + "msg" : "313233343030", + "sig" : "30250200022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 115, + "comment" : "dropping value of integer", + "msg" : "313233343030", + "sig" : "302402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180200", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 116, + "comment" : "using composition for integer", + "msg" : "313233343030", + "sig" : "3049222402012b021fa3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 117, + "comment" : "using composition for integer", + "msg" : "313233343030", + "sig" : "304902202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1822250201000220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 118, + "comment" : "modify first byte of integer", + "msg" : "313233343030", + "sig" : "3045022029a3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 119, + "comment" : "modify first byte of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022102b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 120, + "comment" : "modify last byte of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e98022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 121, + "comment" : "modify last byte of integer", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b491568475b", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 122, + "comment" : "truncated integer", + "msg" : "313233343030", + "sig" : "3044021f2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 123, + "comment" : "truncated integer", + "msg" : "313233343030", + "sig" : "3044021fa3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 124, + "comment" : "truncated integer", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022000b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 125, + "comment" : "leading ff in integer", + "msg" : "313233343030", + "sig" : "30460221ff2ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 126, + "comment" : "leading ff in integer", + "msg" : "313233343030", + "sig" : "304602202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180222ff00b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 127, + "comment" : "replaced integer by infinity", + "msg" : "313233343030", + "sig" : "3026090180022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 128, + "comment" : "replaced integer by infinity", + "msg" : "313233343030", + "sig" : "302502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18090180", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 129, + "comment" : "replacing integer with zero", + "msg" : "313233343030", + "sig" : "3026020100022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 130, + "comment" : "replacing integer with zero", + "msg" : "313233343030", + "sig" : "302502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18020100", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 131, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "30460221012ba3a8bd6b94d5ed80a6d9d1190a436ebccc0833490686deac8635bcb9bf5369022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 132, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "30460221ff2ba3a8bf6b94d5eb80a6d9d1190a436f42fe12d7fad749d4c512a036c0f908c7022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 133, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "30450220d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 134, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "3046022100d45c5740946b2a147f59262ee6f5bc90bd01ed280528b62b3aed5fc93f06f739022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 135, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "30460221fed45c5742946b2a127f59262ee6f5bc914333f7ccb6f979215379ca434640ac97022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 136, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "30460221012ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 137, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "3046022100d45c5741946b2a137f59262ee6f5bc91001af27a5e1117a64733950642a3d1e8022100b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 138, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022101b329f478a2bbd0a6c384ee1493b1f518276e0e4a5375928d6fcd160c11cb6d2c", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 139, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f47aa2bbd0a4c384ee1493b1f518ada018ef05465583885980861905228a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 140, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180221ff4cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b825", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 141, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180221fe4cd60b875d442f593c7b11eb6c4e0ae7d891f1b5ac8a6d729032e9f3ee3492d4", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 142, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "304502202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e18022101b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 143, + "comment" : "Modified r or s, e.g. by adding or subtracting the order of the group", + "msg" : "313233343030", + "sig" : "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b865d442f5a3c7b11eb6c4e0ae79578ec6353a20bf783ecb4b6ea97b825", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 144, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3006020100020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 145, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3006020100020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 146, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30060201000201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 147, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020100022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 148, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020100022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 149, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020100022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 150, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020100022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 151, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020100022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 152, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3008020100090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 153, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3006020100090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 154, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3006020101020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 155, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3006020101020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 156, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30060201010201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 157, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020101022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 158, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020101022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 159, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020101022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 160, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 161, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026020101022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 162, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3008020101090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 163, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3006020101090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 164, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30060201ff020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 165, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30060201ff020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 166, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30060201ff0201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 167, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30260201ff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 168, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30260201ff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 169, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30260201ff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 170, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30260201ff022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 171, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30260201ff022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 172, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30080201ff090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 173, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "30060201ff090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 174, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 175, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 176, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325510201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 177, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 178, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 179, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 180, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 181, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 182, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3028022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 183, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 184, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 185, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 186, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325500201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 187, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 188, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 189, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 190, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 191, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 192, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3028022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 193, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 194, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 195, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 196, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325520201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 197, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 198, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 199, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 200, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 201, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 202, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3028022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 203, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 204, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 205, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 206, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff0201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 207, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 208, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 209, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 210, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 211, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 212, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3028022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 213, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 214, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000001000000000000000000000000020100", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 215, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000001000000000000000000000000020101", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 216, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff000000010000000000000000000000010000000000000000000000000201ff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 217, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000001000000000000000000000000022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 218, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000001000000000000000000000000022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 219, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000001000000000000000000000000022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 220, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000001000000000000000000000000022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 221, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000001000000000000000000000000022100ffffffff00000001000000000000000000000001000000000000000000000000", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 222, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3028022100ffffffff00000001000000000000000000000001000000000000000000000000090380fe01", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 223, + "comment" : "Signature with special case values for r and s", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000001000000000000000000000001000000000000000000000000090142", + "result" : "invalid", + "flags" : [ + "EdgeCase" + ] + }, + { + "tcId" : 224, + "comment" : "Signature encoding contains wrong types.", + "msg" : "313233343030", + "sig" : "30060201010c0130", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 225, + "comment" : "Signature encoding contains wrong types.", + "msg" : "313233343030", + "sig" : "30050201010c00", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 226, + "comment" : "Signature encoding contains wrong types.", + "msg" : "313233343030", + "sig" : "30090c0225730c03732573", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 227, + "comment" : "Signature encoding contains wrong types.", + "msg" : "313233343030", + "sig" : "30080201013003020100", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 228, + "comment" : "Signature encoding contains wrong types.", + "msg" : "313233343030", + "sig" : "3003020101", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 229, + "comment" : "Signature encoding contains wrong types.", + "msg" : "313233343030", + "sig" : "3006020101010100", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 230, + "comment" : "Edge case for Shamir multiplication", + "msg" : "3639383139", + "sig" : "3044022064a1aab5000d0e804f3e2fc02bdee9be8ff312334e2ba16d11547c97711c898e02206af015971cc30be6d1a206d4e013e0997772a2f91d73286ffd683b9bb2cf4f1b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 231, + "comment" : "special case hash", + "msg" : "343236343739373234", + "sig" : "3044022016aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf2660220252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 232, + "comment" : "special case hash", + "msg" : "37313338363834383931", + "sig" : "30450221009cc98be2347d469bf476dfc26b9b733df2d26d6ef524af917c665baccb23c8820220093496459effe2d8d70727b82462f61d0ec1b7847929d10ea631dacb16b56c32", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 233, + "comment" : "special case hash", + "msg" : "3130333539333331363638", + "sig" : "3044022073b3c90ecd390028058164524dde892703dce3dea0d53fa8093999f07ab8aa4302202f67b0b8e20636695bb7d8bf0a651c802ed25a395387b5f4188c0c4075c88634", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 234, + "comment" : "special case hash", + "msg" : "33393439343031323135", + "sig" : "3046022100bfab3098252847b328fadf2f89b95c851a7f0eb390763378f37e90119d5ba3dd022100bdd64e234e832b1067c2d058ccb44d978195ccebb65c2aaf1e2da9b8b4987e3b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 235, + "comment" : "special case hash", + "msg" : "31333434323933303739", + "sig" : "30440220204a9784074b246d8bf8bf04a4ceb1c1f1c9aaab168b1596d17093c5cd21d2cd022051cce41670636783dc06a759c8847868a406c2506fe17975582fe648d1d88b52", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 236, + "comment" : "special case hash", + "msg" : "33373036323131373132", + "sig" : "3046022100ed66dc34f551ac82f63d4aa4f81fe2cb0031a91d1314f835027bca0f1ceeaa0302210099ca123aa09b13cd194a422e18d5fda167623c3f6e5d4d6abb8953d67c0c48c7", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 237, + "comment" : "special case hash", + "msg" : "333433363838373132", + "sig" : "30450220060b700bef665c68899d44f2356a578d126b062023ccc3c056bf0f60a237012b0221008d186c027832965f4fcc78a3366ca95dedbb410cbef3f26d6be5d581c11d3610", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 238, + "comment" : "special case hash", + "msg" : "31333531353330333730", + "sig" : "30460221009f6adfe8d5eb5b2c24d7aa7934b6cf29c93ea76cd313c9132bb0c8e38c96831d022100b26a9c9e40e55ee0890c944cf271756c906a33e66b5bd15e051593883b5e9902", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 239, + "comment" : "special case hash", + "msg" : "36353533323033313236", + "sig" : "3045022100a1af03ca91677b673ad2f33615e56174a1abf6da168cebfa8868f4ba273f16b7022020aa73ffe48afa6435cd258b173d0c2377d69022e7d098d75caf24c8c5e06b1c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 240, + "comment" : "special case hash", + "msg" : "31353634333436363033", + "sig" : "3045022100fdc70602766f8eed11a6c99a71c973d5659355507b843da6e327a28c11893db902203df5349688a085b137b1eacf456a9e9e0f6d15ec0078ca60a7f83f2b10d21350", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 241, + "comment" : "special case hash", + "msg" : "34343239353339313137", + "sig" : "3046022100b516a314f2fce530d6537f6a6c49966c23456f63c643cf8e0dc738f7b876e675022100d39ffd033c92b6d717dd536fbc5efdf1967c4bd80954479ba66b0120cd16fff2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 242, + "comment" : "special case hash", + "msg" : "3130393533323631333531", + "sig" : "304402203b2cbf046eac45842ecb7984d475831582717bebb6492fd0a485c101e29ff0a802204c9b7b47a98b0f82de512bc9313aaf51701099cac5f76e68c8595fc1c1d99258", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 243, + "comment" : "special case hash", + "msg" : "35393837333530303431", + "sig" : "3044022030c87d35e636f540841f14af54e2f9edd79d0312cfa1ab656c3fb15bfde48dcf022047c15a5a82d24b75c85a692bd6ecafeb71409ede23efd08e0db9abf6340677ed", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 244, + "comment" : "special case hash", + "msg" : "33343633303036383738", + "sig" : "3044022038686ff0fda2cef6bc43b58cfe6647b9e2e8176d168dec3c68ff262113760f520220067ec3b651f422669601662167fa8717e976e2db5e6a4cf7c2ddabb3fde9d67d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 245, + "comment" : "special case hash", + "msg" : "39383137333230323837", + "sig" : "3044022044a3e23bf314f2b344fc25c7f2de8b6af3e17d27f5ee844b225985ab6e2775cf02202d48e223205e98041ddc87be532abed584f0411f5729500493c9cc3f4dd15e86", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 246, + "comment" : "special case hash", + "msg" : "33323232303431303436", + "sig" : "304402202ded5b7ec8e90e7bf11f967a3d95110c41b99db3b5aa8d330eb9d638781688e902207d5792c53628155e1bfc46fb1a67e3088de049c328ae1f44ec69238a009808f9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 247, + "comment" : "special case hash", + "msg" : "36363636333037313034", + "sig" : "3046022100bdae7bcb580bf335efd3bc3d31870f923eaccafcd40ec2f605976f15137d8b8f022100f6dfa12f19e525270b0106eecfe257499f373a4fb318994f24838122ce7ec3c7", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 248, + "comment" : "special case hash", + "msg" : "31303335393531383938", + "sig" : "3045022050f9c4f0cd6940e162720957ffff513799209b78596956d21ece251c2401f1c6022100d7033a0a787d338e889defaaabb106b95a4355e411a59c32aa5167dfab244726", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 249, + "comment" : "special case hash", + "msg" : "31383436353937313935", + "sig" : "3045022100f612820687604fa01906066a378d67540982e29575d019aabe90924ead5c860d02203f9367702dd7dd4f75ea98afd20e328a1a99f4857b316525328230ce294b0fef", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 250, + "comment" : "special case hash", + "msg" : "33313336303436313839", + "sig" : "30460221009505e407657d6e8bc93db5da7aa6f5081f61980c1949f56b0f2f507da5782a7a022100c60d31904e3669738ffbeccab6c3656c08e0ed5cb92b3cfa5e7f71784f9c5021", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 251, + "comment" : "special case hash", + "msg" : "32363633373834323534", + "sig" : "3046022100bbd16fbbb656b6d0d83e6a7787cd691b08735aed371732723e1c68a40404517d0221009d8e35dba96028b7787d91315be675877d2d097be5e8ee34560e3e7fd25c0f00", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 252, + "comment" : "special case hash", + "msg" : "31363532313030353234", + "sig" : "304402202ec9760122db98fd06ea76848d35a6da442d2ceef7559a30cf57c61e92df327e02207ab271da90859479701fccf86e462ee3393fb6814c27b760c4963625c0a19878", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 253, + "comment" : "special case hash", + "msg" : "35373438303831363936", + "sig" : "3044022054e76b7683b6650baa6a7fc49b1c51eed9ba9dd463221f7a4f1005a89fe00c5902202ea076886c773eb937ec1cc8374b7915cfd11b1c1ae1166152f2f7806a31c8fd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 254, + "comment" : "special case hash", + "msg" : "36333433393133343638", + "sig" : "304402205291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c9466022065d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 255, + "comment" : "special case hash", + "msg" : "31353431313033353938", + "sig" : "30450220207a3241812d75d947419dc58efb05e8003b33fc17eb50f9d15166a88479f107022100cdee749f2e492b213ce80b32d0574f62f1c5d70793cf55e382d5caadf7592767", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 256, + "comment" : "special case hash", + "msg" : "3130343738353830313238", + "sig" : "304502206554e49f82a855204328ac94913bf01bbe84437a355a0a37c0dee3cf81aa7728022100aea00de2507ddaf5c94e1e126980d3df16250a2eaebc8be486effe7f22b4f929", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 257, + "comment" : "special case hash", + "msg" : "3130353336323835353638", + "sig" : "3046022100a54c5062648339d2bff06f71c88216c26c6e19b4d80a8c602990ac82707efdfc022100e99bbe7fcfafae3e69fd016777517aa01056317f467ad09aff09be73c9731b0d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 258, + "comment" : "special case hash", + "msg" : "393533393034313035", + "sig" : "3045022100975bd7157a8d363b309f1f444012b1a1d23096593133e71b4ca8b059cff37eaf02207faa7a28b1c822baa241793f2abc930bd4c69840fe090f2aacc46786bf919622", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 259, + "comment" : "special case hash", + "msg" : "393738383438303339", + "sig" : "304402205694a6f84b8f875c276afd2ebcfe4d61de9ec90305afb1357b95b3e0da43885e02200dffad9ffd0b757d8051dec02ebdf70d8ee2dc5c7870c0823b6ccc7c679cbaa4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 260, + "comment" : "special case hash", + "msg" : "33363130363732343432", + "sig" : "3045022100a0c30e8026fdb2b4b4968a27d16a6d08f7098f1a98d21620d7454ba9790f1ba602205e470453a8a399f15baf463f9deceb53acc5ca64459149688bd2760c65424339", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 261, + "comment" : "special case hash", + "msg" : "31303534323430373035", + "sig" : "30440220614ea84acf736527dd73602cd4bb4eea1dfebebd5ad8aca52aa0228cf7b99a880220737cc85f5f2d2f60d1b8183f3ed490e4de14368e96a9482c2a4dd193195c902f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 262, + "comment" : "special case hash", + "msg" : "35313734343438313937", + "sig" : "3045022100bead6734ebe44b810d3fb2ea00b1732945377338febfd439a8d74dfbd0f942fa02206bb18eae36616a7d3cad35919fd21a8af4bbe7a10f73b3e036a46b103ef56e2a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 263, + "comment" : "special case hash", + "msg" : "31393637353631323531", + "sig" : "30440220499625479e161dacd4db9d9ce64854c98d922cbf212703e9654fae182df9bad2022042c177cf37b8193a0131108d97819edd9439936028864ac195b64fca76d9d693", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 264, + "comment" : "special case hash", + "msg" : "33343437323533333433", + "sig" : "3045022008f16b8093a8fb4d66a2c8065b541b3d31e3bfe694f6b89c50fb1aaa6ff6c9b20221009d6455e2d5d1779748573b611cb95d4a21f967410399b39b535ba3e5af81ca2e", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 265, + "comment" : "special case hash", + "msg" : "333638323634333138", + "sig" : "3046022100be26231b6191658a19dd72ddb99ed8f8c579b6938d19bce8eed8dc2b338cb5f8022100e1d9a32ee56cffed37f0f22b2dcb57d5c943c14f79694a03b9c5e96952575c89", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 266, + "comment" : "special case hash", + "msg" : "33323631313938363038", + "sig" : "3045022015e76880898316b16204ac920a02d58045f36a229d4aa4f812638c455abe0443022100e74d357d3fcb5c8c5337bd6aba4178b455ca10e226e13f9638196506a1939123", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 267, + "comment" : "special case hash", + "msg" : "39363738373831303934", + "sig" : "30440220352ecb53f8df2c503a45f9846fc28d1d31e6307d3ddbffc1132315cc07f16dad02201348dfa9c482c558e1d05c5242ca1c39436726ecd28258b1899792887dd0a3c6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 268, + "comment" : "special case hash", + "msg" : "34393538383233383233", + "sig" : "304402204a40801a7e606ba78a0da9882ab23c7677b8642349ed3d652c5bfa5f2a9558fb02203a49b64848d682ef7f605f2832f7384bdc24ed2925825bf8ea77dc5981725782", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 269, + "comment" : "special case hash", + "msg" : "383234363337383337", + "sig" : "3045022100eacc5e1a8304a74d2be412b078924b3bb3511bac855c05c9e5e9e44df3d61e9602207451cd8e18d6ed1885dd827714847f96ec4bb0ed4c36ce9808db8f714204f6d1", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 270, + "comment" : "special case hash", + "msg" : "3131303230383333373736", + "sig" : "304502202f7a5e9e5771d424f30f67fdab61e8ce4f8cd1214882adb65f7de94c31577052022100ac4e69808345809b44acb0b2bd889175fb75dd050c5a449ab9528f8f78daa10c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 271, + "comment" : "special case hash", + "msg" : "313333383731363438", + "sig" : "3045022100ffcda40f792ce4d93e7e0f0e95e1a2147dddd7f6487621c30a03d710b3300219022079938b55f8a17f7ed7ba9ade8f2065a1fa77618f0b67add8d58c422c2453a49a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 272, + "comment" : "special case hash", + "msg" : "333232313434313632", + "sig" : "304602210081f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8022100cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f74300", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 273, + "comment" : "special case hash", + "msg" : "3130363836363535353436", + "sig" : "3045022100dfc8bf520445cbb8ee1596fb073ea283ea130251a6fdffa5c3f5f2aaf75ca8080220048e33efce147c9dd92823640e338e68bfd7d0dc7a4905b3a7ac711e577e90e7", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 274, + "comment" : "special case hash", + "msg" : "3632313535323436", + "sig" : "3046022100ad019f74c6941d20efda70b46c53db166503a0e393e932f688227688ba6a576202210093320eb7ca0710255346bdbb3102cdcf7964ef2e0988e712bc05efe16c199345", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 275, + "comment" : "special case hash", + "msg" : "37303330383138373734", + "sig" : "3046022100ac8096842e8add68c34e78ce11dd71e4b54316bd3ebf7fffdeb7bd5a3ebc1883022100f5ca2f4f23d674502d4caf85d187215d36e3ce9f0ce219709f21a3aac003b7a8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 276, + "comment" : "special case hash", + "msg" : "35393234353233373434", + "sig" : "30440220677b2d3a59b18a5ff939b70ea002250889ddcd7b7b9d776854b4943693fb92f702206b4ba856ade7677bf30307b21f3ccda35d2f63aee81efd0bab6972cc0795db55", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 277, + "comment" : "special case hash", + "msg" : "31343935353836363231", + "sig" : "30450220479e1ded14bcaed0379ba8e1b73d3115d84d31d4b7c30e1f05e1fc0d5957cfb0022100918f79e35b3d89487cf634a4f05b2e0c30857ca879f97c771e877027355b2443", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 278, + "comment" : "special case hash", + "msg" : "34303035333134343036", + "sig" : "3044022043dfccd0edb9e280d9a58f01164d55c3d711e14b12ac5cf3b64840ead512a0a302201dbe33fa8ba84533cd5c4934365b3442ca1174899b78ef9a3199f49584389772", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 279, + "comment" : "special case hash", + "msg" : "33303936343537353132", + "sig" : "304402205b09ab637bd4caf0f4c7c7e4bca592fea20e9087c259d26a38bb4085f0bbff11022045b7eb467b6748af618e9d80d6fdcd6aa24964e5a13f885bca8101de08eb0d75", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 280, + "comment" : "special case hash", + "msg" : "32373834303235363230", + "sig" : "304502205e9b1c5a028070df5728c5c8af9b74e0667afa570a6cfa0114a5039ed15ee06f022100b1360907e2d9785ead362bb8d7bd661b6c29eeffd3c5037744edaeb9ad990c20", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 281, + "comment" : "special case hash", + "msg" : "32363138373837343138", + "sig" : "304502200671a0a85c2b72d54a2fb0990e34538b4890050f5a5712f6d1a7a5fb8578f32e022100db1846bab6b7361479ab9c3285ca41291808f27fd5bd4fdac720e5854713694c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 282, + "comment" : "special case hash", + "msg" : "31363432363235323632", + "sig" : "304402207673f8526748446477dbbb0590a45492c5d7d69859d301abbaedb35b2095103a02203dc70ddf9c6b524d886bed9e6af02e0e4dec0d417a414fed3807ef4422913d7c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 283, + "comment" : "special case hash", + "msg" : "36383234313839343336", + "sig" : "304402207f085441070ecd2bb21285089ebb1aa6450d1a06c36d3ff39dfd657a796d12b50220249712012029870a2459d18d47da9aa492a5e6cb4b2d8dafa9e4c5c54a2b9a8b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 284, + "comment" : "special case hash", + "msg" : "343834323435343235", + "sig" : "3046022100914c67fb61dd1e27c867398ea7322d5ab76df04bc5aa6683a8e0f30a5d287348022100fa07474031481dda4953e3ac1959ee8cea7e66ec412b38d6c96d28f6d37304ea", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "040ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "wx" : "0ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103", + "wy" : "00c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040ad99500288d466940031d72a9f5445a4d43784640855bf0a69874d2de5fe103c5011e6ef2c42dcd50d5d3d29f99ae6eba2c80c9244f4c5422f0979ff0c3ba5e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECtmVACiNRmlAAx1yqfVEWk1DeEZA\nhVvwpph00t5f4QPFAR5u8sQtzVDV09Kfma5uuiyAySRPTFQi8Jef8MO6Xg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 285, + "comment" : "k*G has a large x-coordinate", + "msg" : "313233343030", + "sig" : "303502104319055358e8617b0c46353d039cdaab022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 286, + "comment" : "r too large", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000001000000000000000000000000fffffffffffffffffffffffc022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04ab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45", + "wx" : "00ab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c582204554", + "wy" : "19235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004ab05fd9d0de26b9ce6f4819652d9fc69193d0aa398f0fba8013e09c58220455419235271228c786759095d12b75af0692dd4103f19f6a8c32f49435a1e9b8d45", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqwX9nQ3ia5zm9IGWUtn8aRk9CqOY\n8PuoAT4JxYIgRVQZI1JxIox4Z1kJXRK3WvBpLdQQPxn2qMMvSUNaHpuNRQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 287, + "comment" : "r,s are large", + "msg" : "313233343030", + "sig" : "3046022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95", + "wx" : "0080984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c56", + "wy" : "11feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000480984f39a1ff38a86a68aa4201b6be5dfbfecf876219710b07badf6fdd4c6c5611feb97390d9826e7a06dfb41871c940d74415ed3cac2089f1445019bb55ed95", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgJhPOaH/OKhqaKpCAba+Xfv+z4di\nGXELB7rfb91MbFYR/rlzkNmCbnoG37QYcclA10QV7TysIInxRFAZu1XtlQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 288, + "comment" : "r and s^-1 have a large Hamming weight", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100909135bdb6799286170f5ead2de4f6511453fe50914f3df2de54a36383df8dd4", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "044201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e", + "wx" : "4201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c05", + "wy" : "0095c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044201b4272944201c3294f5baa9a3232b6dd687495fcc19a70a95bc602b4f7c0595c37eba9ee8171c1bb5ac6feaf753bc36f463e3aef16629572c0c0a8fb0800e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQgG0JylEIBwylPW6qaMjK23Wh0lf\nzBmnCpW8YCtPfAWVw366nugXHBu1rG/q91O8NvRj467xZilXLAwKj7CADg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 289, + "comment" : "r and s^-1 have a large Hamming weight", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022027b4577ca009376f71303fd5dd227dcef5deb773ad5f5a84360644669ca249a5", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b", + "wx" : "00a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957", + "wy" : "5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac9575d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpxr2TeUSakpOAreSLWbOlBXOiKTJ\n0lUU2RCCyHJayVddR3I8j75YC7Np/snCZl2OMKQ1uZMmRUgufJ8R6HIpaw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 290, + "comment" : "small r and s", + "msg" : "313233343030", + "sig" : "3006020105020101", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "046627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5", + "wx" : "6627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b1572", + "wy" : "6170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046627cec4f0731ea23fc2931f90ebe5b7572f597d20df08fc2b31ee8ef16b15726170ed77d8d0a14fc5c9c3c4c9be7f0d3ee18f709bb275eaf2073e258fe694a5", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZifOxPBzHqI/wpMfkOvlt1cvWX0g\n3wj8KzHujvFrFXJhcO132NChT8XJw8TJvn8NPuGPcJuyderyBz4lj+aUpQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 291, + "comment" : "small r and s", + "msg" : "313233343030", + "sig" : "3006020105020103", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813", + "wx" : "5a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bf", + "wy" : "00ef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045a7c8825e85691cce1f5e7544c54e73f14afc010cb731343262ca7ec5a77f5bfef6edf62a4497c1bd7b147fb6c3d22af3c39bfce95f30e13a16d3d7b2812f813", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWnyIJehWkczh9edUTFTnPxSvwBDL\ncxNDJiyn7Fp39b/vbt9ipEl8G9exR/tsPSKvPDm/zpXzDhOhbT17KBL4Ew==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 292, + "comment" : "small r and s", + "msg" : "313233343030", + "sig" : "3006020105020105", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", + "wx" : "00cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c737", + "wy" : "70af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cbe0c29132cd738364fedd603152990c048e5e2fff996d883fa6caca7978c73770af6a8ce44cb41224b2603606f4c04d188e80bff7cc31ad5189d4ab0d70e8c1", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEy+DCkTLNc4Nk/t1gMVKZDASOXi//\nmW2IP6bKynl4xzdwr2qM5Ey0EiSyYDYG9MBNGI6Av/fMMa1RidSrDXDowQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 293, + "comment" : "small r and s", + "msg" : "313233343030", + "sig" : "3006020105020106", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 294, + "comment" : "r is larger than n", + "msg" : "313233343030", + "sig" : "3026022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632556020106", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "044be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56", + "wx" : "4be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e139", + "wy" : "20f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044be4178097002f0deab68f0d9a130e0ed33a6795d02a20796db83444b037e13920f13051e0eecdcfce4dacea0f50d1f247caa669f193c1b4075b51ae296d2d56", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES+QXgJcALw3qto8NmhMODtM6Z5XQ\nKiB5bbg0RLA34Tkg8TBR4O7Nz85NrOoPUNHyR8qmafGTwbQHW1GuKW0tVg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 295, + "comment" : "s is larger than n", + "msg" : "313233343030", + "sig" : "3026020105022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc75fbd8", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1", + "wx" : "00d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9", + "wy" : "00971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d0f73792203716afd4be4329faa48d269f15313ebbba379d7783c97bf3e890d9971f4a3206605bec21782bf5e275c714417e8f566549e6bc68690d2363c89cc1", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0Pc3kiA3Fq/UvkMp+qSNJp8VMT67\nujedd4PJe/PokNmXH0oyBmBb7CF4K/XidccUQX6PVmVJ5rxoaQ0jY8icwQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 296, + "comment" : "small r and s^-1", + "msg" : "313233343030", + "sig" : "3027020201000221008f1e3c7862c58b16bb76eddbb76eddbb516af4f63f2d74d76e0d28c9bb75ea88", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "044838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b", + "wx" : "4838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05f", + "wy" : "00fa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044838b2be35a6276a80ef9e228140f9d9b96ce83b7a254f71ccdebbb8054ce05ffa9cbc123c919b19e00238198d04069043bd660a828814051fcb8aac738a6c6b", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESDiyvjWmJ2qA754igUD52bls6Dt6\nJU9xzN67uAVM4F/6nLwSPJGbGeACOBmNBAaQQ71mCoKIFAUfy4qsc4psaw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 297, + "comment" : "smallish r and s^-1", + "msg" : "313233343030", + "sig" : "302c02072d9b4d347952d6022100ef3043e7329581dbb3974497710ab11505ee1c87ff907beebadd195a0ffe6d7a", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "047393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526", + "wx" : "7393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64", + "wy" : "00e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200047393983ca30a520bbc4783dc9960746aab444ef520c0a8e771119aa4e74b0f64e9d7be1ab01a0bf626e709863e6a486dbaf32793afccf774e2c6cd27b1857526", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc5OYPKMKUgu8R4PcmWB0aqtETvUg\nwKjncRGapOdLD2Tp174asBoL9ibnCYY+akhtuvMnk6/M93Tixs0nsYV1Jg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 298, + "comment" : "100-bit r and small s^-1", + "msg" : "313233343030", + "sig" : "3032020d1033e67e37b32b445580bf4eff0221008b748b74000000008b748b748b748b7466e769ad4a16d3dcd87129b8e91d1b4d", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b", + "wx" : "5ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5", + "wy" : "00fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045ac331a1103fe966697379f356a937f350588a05477e308851b8a502d5dfcdc5fe9993df4b57939b2b8da095bf6d794265204cfe03be995a02e65d408c871c0b", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWsMxoRA/6WZpc3nzVqk381BYigVH\nfjCIUbilAtXfzcX+mZPfS1eTmyuNoJW/bXlCZSBM/gO+mVoC5l1AjIccCw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 299, + "comment" : "small r and 100 bit s^-1", + "msg" : "313233343030", + "sig" : "302702020100022100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "041d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9", + "wx" : "1d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509", + "wy" : "00dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200041d209be8de2de877095a399d3904c74cc458d926e27bb8e58e5eae5767c41509dd59e04c214f7b18dce351fc2a549893a6860e80163f38cc60a4f2c9d040d8c9", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHSCb6N4t6HcJWjmdOQTHTMRY2Sbi\ne7jljl6uV2fEFQndWeBMIU97GNzjUfwqVJiTpoYOgBY/OMxgpPLJ0EDYyQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 300, + "comment" : "100-bit r and s^-1", + "msg" : "313233343030", + "sig" : "3032020d062522bbd3ecbe7c39e93e7c25022100ef9f6ba4d97c09d03178fa20b4aaad83be3cf9cb824a879fec3270fc4b81ef5b", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e", + "wx" : "083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99", + "wy" : "00915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004083539fbee44625e3acaafa2fcb41349392cef0633a1b8fabecee0c133b10e99915c1ebe7bf00df8535196770a58047ae2a402f26326bb7d41d4d7616337911e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECDU5++5EYl46yq+i/LQTSTks7wYz\nobj6vs7gwTOxDpmRXB6+e/AN+FNRlncKWAR64qQC8mMmu31B1NdhYzeRHg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 301, + "comment" : "r and s^-1 are close to n", + "msg" : "313233343030", + "sig" : "3045022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6324d50220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "048aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", + "wx" : "008aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e19373874", + "wy" : "05bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200048aeb368a7027a4d64abdea37390c0c1d6a26f399e2d9734de1eb3d0e1937387405bd13834715e1dbae9b875cf07bd55e1b6691c7f7536aef3b19bf7a4adf576d", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEius2inAnpNZKveo3OQwMHWom85ni\n2XNN4es9Dhk3OHQFvRODRxXh266bh1zwe9VeG2aRx/dTau87Gb96St9XbQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 302, + "comment" : "s == 1", + "msg" : "313233343030", + "sig" : "30250220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70020101", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 303, + "comment" : "s == 0", + "msg" : "313233343030", + "sig" : "30250220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70020100", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47", + "wx" : "00b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f287", + "wy" : "1b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004b533d4695dd5b8c5e07757e55e6e516f7e2c88fa0239e23f60e8ec07dd70f2871b134ee58cc583278456863f33c3a85d881f7d4a39850143e29d4eaf009afe47", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtTPUaV3VuMXgd1flXm5Rb34siPoC\nOeI/YOjsB91w8ocbE07ljMWDJ4RWhj8zw6hdiB99SjmFAUPinU6vAJr+Rw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 304, + "comment" : "point at infinity during verify", + "msg" : "313233343030", + "sig" : "304402207fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a80220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd", + "wx" : "00f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86", + "wy" : "00f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f50d371b91bfb1d7d14e1323523bc3aa8cbf2c57f9e284de628c8b4536787b86f94ad887ac94d527247cd2e7d0c8b1291c553c9730405380b14cbb209f5fa2dd", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9Q03G5G/sdfRThMjUjvDqoy/LFf5\n4oTeYoyLRTZ4e4b5StiHrJTVJyR80ufQyLEpHFU8lzBAU4CxTLsgn1+i3Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 305, + "comment" : "edge case for signature malleability", + "msg" : "313233343030", + "sig" : "304402207fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a902207fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a8", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0468ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30", + "wx" : "68ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d946", + "wy" : "0097bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000468ec6e298eafe16539156ce57a14b04a7047c221bafc3a582eaeb0d857c4d94697bed1af17850117fdb39b2324f220a5698ed16c426a27335bb385ac8ca6fb30", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaOxuKY6v4WU5FWzlehSwSnBHwiG6\n/DpYLq6w2FfE2UaXvtGvF4UBF/2zmyMk8iClaY7RbEJqJzNbs4WsjKb7MA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 306, + "comment" : "edge case for signature malleability", + "msg" : "313233343030", + "sig" : "304402207fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a902207fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192a9", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0469da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002", + "wx" : "69da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b8", + "wy" : "66d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000469da0364734d2e530fece94019265fefb781a0f1b08f6c8897bdf6557927c8b866d2d3c7dcd518b23d726960f069ad71a933d86ef8abbcce8b20f71e2a847002", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEadoDZHNNLlMP7OlAGSZf77eBoPGw\nj2yIl732VXknyLhm0tPH3NUYsj1yaWDwaa1xqTPYbvirvM6LIPceKoRwAg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 307, + "comment" : "u1 == 1", + "msg" : "313233343030", + "sig" : "30450220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04d8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1", + "wx" : "00d8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff32", + "wy" : "33e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d8adc00023a8edc02576e2b63e3e30621a471e2b2320620187bf067a1ac1ff3233e2b50ec09807accb36131fff95ed12a09a86b4ea9690aa32861576ba2362e1", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2K3AACOo7cAlduK2Pj4wYhpHHisj\nIGIBh78GehrB/zIz4rUOwJgHrMs2Ex//le0SoJqGtOqWkKoyhhV2uiNi4Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 308, + "comment" : "u1 == n - 1", + "msg" : "313233343030", + "sig" : "30440220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70022044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "043623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe", + "wx" : "3623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab785", + "wy" : "008db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043623ac973ced0a56fa6d882f03a7d5c7edca02cfc7b2401fab3690dbe75ab7858db06908e64b28613da7257e737f39793da8e713ba0643b92e9bb3252be7f8fe", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENiOslzztClb6bYgvA6fVx+3KAs/H\nskAfqzaQ2+dat4WNsGkI5ksoYT2nJX5zfzl5PajnE7oGQ7kum7MlK+f4/g==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 309, + "comment" : "u2 == 1", + "msg" : "313233343030", + "sig" : "30440220555555550000000055555555555555553ef7a8e48d07df81a693439654210c700220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9", + "wx" : "00cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1", + "wy" : "00e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004cf04ea77e9622523d894b93ff52dc3027b31959503b6fa3890e5e04263f922f1e8528fb7c006b3983c8b8400e57b4ed71740c2f3975438821199bedeaecab2e9", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzwTqd+liJSPYlLk/9S3DAnsxlZUD\ntvo4kOXgQmP5IvHoUo+3wAazmDyLhADle07XF0DC85dUOIIRmb7ersqy6Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 310, + "comment" : "u2 == n - 1", + "msg" : "313233343030", + "sig" : "30450220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70022100aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206", + "wx" : "00db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff77350", + "wy" : "4f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004db7a2c8a1ab573e5929dc24077b508d7e683d49227996bda3e9f78dbeff773504f417f3bc9a88075c2e0aadd5a13311730cf7cc76a82f11a36eaf08a6c99a206", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE23osihq1c+WSncJAd7UI1+aD1JIn\nmWvaPp942+/3c1BPQX87yaiAdcLgqt1aEzEXMM98x2qC8Ro26vCKbJmiBg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 311, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100e91e1ba60fdedb76a46bcb51dc0b8b4b7e019f0a28721885fa5d3a8196623397", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff", + "wx" : "00dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f", + "wy" : "1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004dead11c7a5b396862f21974dc4752fadeff994efe9bbd05ab413765ea80b6e1f1de3f0640e8ac6edcf89cff53c40e265bb94078a343736df07aa0318fc7fe1ff", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3q0Rx6WzloYvIZdNxHUvre/5lO/p\nu9BatBN2XqgLbh8d4/BkDorG7c+Jz/U8QOJlu5QHijQ3Nt8HqgMY/H/h/w==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 312, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100fdea5843ffeb73af94313ba4831b53fe24f799e525b1e8e8c87b59b95b430ad9", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd", + "wx" : "00d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9", + "wy" : "00986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d0bc472e0d7c81ebaed3a6ef96c18613bb1fea6f994326fbe80e00dfde67c7e9986c723ea4843d48389b946f64ad56c83ad70ff17ba85335667d1bb9fa619efd", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0LxHLg18geuu06bvlsGGE7sf6m+Z\nQyb76A4A395nx+mYbHI+pIQ9SDiblG9krVbIOtcP8XuoUzVmfRu5+mGe/Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 313, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022003ffcabf2f1b4d2a65190db1680d62bb994e41c5251cd73b3c3dfc5e5bafc035", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add", + "wx" : "00a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c32", + "wy" : "6337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a0a44ca947d66a2acb736008b9c08d1ab2ad03776e02640f78495d458dd51c326337fe5cf8c4604b1f1c409dc2d872d4294a4762420df43a30a2392e40426add", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoKRMqUfWairLc2AIucCNGrKtA3du\nAmQPeEldRY3VHDJjN/5c+MRgSx8cQJ3C2HLUKUpHYkIN9DowojkuQEJq3Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 314, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02204dfbc401f971cd304b33dfdb17d0fed0fe4c1a88ae648e0d2847f74977534989", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd", + "wx" : "00c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b7", + "wy" : "3877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004c9c2115290d008b45fb65fad0f602389298c25420b775019d42b62c3ce8a96b73877d25a8080dc02d987ca730f0405c2c9dbefac46f9e601cc3f06e9713973fd", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEycIRUpDQCLRftl+tD2AjiSmMJUIL\nd1AZ1Ctiw86Klrc4d9JagIDcAtmHynMPBAXCydvvrEb55gHMPwbpcTlz/Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 315, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100bc4024761cd2ffd43dfdb17d0fed112b988977055cd3a8e54971eba9cda5ca71", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71", + "wx" : "5eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e", + "wy" : "5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045eca1ef4c287dddc66b8bccf1b88e8a24c0018962f3c5e7efa83bc1a5ff6033e5e79c4cb2c245b8c45abdce8a8e4da758d92a607c32cd407ecaef22f1c934a71", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXsoe9MKH3dxmuLzPG4jookwAGJYv\nPF5++oO8Gl/2Az5eecTLLCRbjEWr3Oio5Np1jZKmB8Ms1AfsrvIvHJNKcQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 316, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0220788048ed39a5ffa77bfb62fa1fda2257742bf35d128fb3459f2a0c909ee86f91", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9", + "wx" : "5caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47a", + "wy" : "00deb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045caaa030e7fdf0e4936bc7ab5a96353e0a01e4130c3f8bf22d473e317029a47adeb6adc462f7058f2a20d371e9702254e9b201642005b3ceda926b42b178bef9", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXKqgMOf98OSTa8erWpY1PgoB5BMM\nP4vyLUc+MXAppHretq3EYvcFjyog03HpcCJU6bIBZCAFs87akmtCsXi++Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 317, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0220476d9131fd381bd917d0fed112bc9e0a5924b5ed5b11167edd8b23582b3cb15e", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf", + "wx" : "00c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b098", + "wy" : "6237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004c2fd20bac06e555bb8ac0ce69eb1ea20f83a1fc3501c8a66469b1a31f619b0986237050779f52b615bd7b8d76a25fc95ca2ed32525c75f27ffc87ac397e6cbaf", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwv0gusBuVVu4rAzmnrHqIPg6H8NQ\nHIpmRpsaMfYZsJhiNwUHefUrYVvXuNdqJfyVyi7TJSXHXyf/yHrDl+bLrw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 318, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0221008374253e3e21bd154448d0a8f640fe46fafa8b19ce78d538f6cc0a19662d3601", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "043fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4", + "wx" : "3fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced", + "wy" : "03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043fd6a1ca7f77fb3b0bbe726c372010068426e11ea6ae78ce17bedae4bba86ced03ce5516406bf8cfaab8745eac1cd69018ad6f50b5461872ddfc56e0db3c8ff4", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEP9ahyn93+zsLvnJsNyAQBoQm4R6m\nrnjOF77a5LuobO0DzlUWQGv4z6q4dF6sHNaQGK1vULVGGHLd/Fbg2zyP9A==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 319, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0220357cfd3be4d01d413c5b9ede36cba5452c11ee7fe14879e749ae6a2d897a52d6", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "049cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544", + "wx" : "009cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114", + "wy" : "00b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200049cb8e51e27a5ae3b624a60d6dc32734e4989db20e9bca3ede1edf7b086911114b4c104ab3c677e4b36d6556e8ad5f523410a19f2e277aa895fc57322b4427544", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnLjlHielrjtiSmDW3DJzTkmJ2yDp\nvKPt4e33sIaRERS0wQSrPGd+SzbWVW6K1fUjQQoZ8uJ3qolfxXMitEJ1RA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 320, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022029798c5c0ee287d4a5e8e6b799fd86b8df5225298e6ffc807cd2f2bc27a0a6d8", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04a3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f", + "wx" : "00a3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a", + "wy" : "4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a3e52c156dcaf10502620b7955bc2b40bc78ef3d569e1223c262512d8f49602a4a2039f31c1097024ad3cc86e57321de032355463486164cf192944977df147f", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEo+UsFW3K8QUCYgt5VbwrQLx47z1W\nnhIjwmJRLY9JYCpKIDnzHBCXAkrTzIblcyHeAyNVRjSGFkzxkpRJd98Ufw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 321, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02200b70f22c781092452dca1a5711fa3a5a1f72add1bf52c2ff7cae4820b30078dd", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04f19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509", + "wx" : "00f19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88", + "wy" : "00cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f19b78928720d5bee8e670fb90010fb15c37bf91b58a5157c3f3c059b2655e88cf701ec962fb4a11dcf273f5dc357e58468560c7cfeb942d074abd4329260509", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8Zt4kocg1b7o5nD7kAEPsVw3v5G1\nilFXw/PAWbJlXojPcB7JYvtKEdzyc/XcNX5YRoVgx8/rlC0HSr1DKSYFCQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 322, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022016e1e458f021248a5b9434ae23f474b43ee55ba37ea585fef95c90416600f1ba", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0483a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e", + "wx" : "0083a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8", + "wy" : "00c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000483a744459ecdfb01a5cf52b27a05bb7337482d242f235d7b4cb89345545c90a8c05d49337b9649813287de9ffe90355fd905df5f3c32945828121f37cc50de6e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg6dERZ7N+wGlz1KyegW7czdILSQv\nI117TLiTRVRckKjAXUkze5ZJgTKH3p/+kDVf2QXfXzwylFgoEh83zFDebg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 323, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02202252d6856831b6cf895e4f0535eeaf0e5e5809753df848fe760ad86219016a97", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff", + "wx" : "00dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7", + "wy" : "00bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004dd13c6b34c56982ddae124f039dfd23f4b19bbe88cee8e528ae51e5d6f3a21d7bfad4c2e6f263fe5eb59ca974d039fc0e4c3345692fb5320bdae4bd3b42a45ff", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3RPGs0xWmC3a4STwOd/SP0sZu+iM\n7o5SiuUeXW86Ide/rUwubyY/5etZypdNA5/A5MM0VpL7UyC9rkvTtCpF/w==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 324, + "comment" : "edge case for u1", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02210081ffe55f178da695b28c86d8b406b15dab1a9e39661a3ae017fbe390ac0972c3", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0467e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0", + "wx" : "67e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460", + "wy" : "00a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000467e6f659cdde869a2f65f094e94e5b4dfad636bbf95192feeed01b0f3deb7460a37e0a51f258b7aeb51dfe592f5cfd5685bbe58712c8d9233c62886437c38ba0", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZ+b2Wc3ehpovZfCU6U5bTfrWNrv5\nUZL+7tAbDz3rdGCjfgpR8li3rrUd/lkvXP1WhbvlhxLI2SM8YohkN8OLoA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 325, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02207fffffffaaaaaaaaffffffffffffffffe9a2538f37b28a2c513dee40fecbb71a", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "042eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0", + "wx" : "2eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf", + "wy" : "00805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042eb6412505aec05c6545f029932087e490d05511e8ec1f599617bb367f9ecaaf805f51efcc4803403f9b1ae0124890f06a43fedcddb31830f6669af292895cb0", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELrZBJQWuwFxlRfApkyCH5JDQVRHo\n7B9Zlhe7Nn+eyq+AX1HvzEgDQD+bGuASSJDwakP+3N2zGDD2ZprykolcsA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 326, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100b62f26b5f2a2b26f6de86d42ad8a13da3ab3cccd0459b201de009e526adf21f2", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0484db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe", + "wx" : "0084db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f35", + "wy" : "6d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000484db645868eab35e3a9fd80e056e2e855435e3a6b68d75a50a854625fe0d7f356d2589ac655edc9a11ef3e075eddda9abf92e72171570ef7bf43a2ee39338cfe", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhNtkWGjqs146n9gOBW4uhVQ146a2\njXWlCoVGJf4NfzVtJYmsZV7cmhHvPgde3dqav5LnIXFXDve/Q6LuOTOM/g==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 327, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100bb1d9ac949dd748cd02bbbe749bd351cd57b38bb61403d700686aa7b4c90851e", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0491b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd", + "wx" : "0091b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad663", + "wy" : "49aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000491b9e47c56278662d75c0983b22ca8ea6aa5059b7a2ff7637eb2975e386ad66349aa8ff283d0f77c18d6d11dc062165fd13c3c0310679c1408302a16854ecfbd", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkbnkfFYnhmLXXAmDsiyo6mqlBZt6\nL/djfrKXXjhq1mNJqo/yg9D3fBjW0R3AYhZf0Tw8AxBnnBQIMCoWhU7PvQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 328, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022066755a00638cdaec1c732513ca0234ece52545dac11f816e818f725b4f60aaf2", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432", + "wx" : "00f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834d", + "wy" : "00f97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f3ec2f13caf04d0192b47fb4c5311fb6d4dc6b0a9e802e5327f7ec5ee8e4834df97e3e468b7d0db867d6ecfe81e2b0f9531df87efdb47c1338ac321fefe5a432", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8+wvE8rwTQGStH+0xTEfttTcawqe\ngC5TJ/fsXujkg035fj5Gi30NuGfW7P6B4rD5Ux34fv20fBM4rDIf7+WkMg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 329, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022055a00c9fcdaebb6032513ca0234ecfffe98ebe492fdf02e48ca48e982beb3669", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72", + "wx" : "00d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc88", + "wy" : "5ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d92b200aefcab6ac7dafd9acaf2fa10b3180235b8f46b4503e4693c670fccc885ef2f3aebf5b317475336256768f7c19efb7352d27e4cccadc85b6b8ab922c72", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2SsgCu/Ktqx9r9msry+hCzGAI1uP\nRrRQPkaTxnD8zIhe8vOuv1sxdHUzYlZ2j3wZ77c1LSfkzMrchba4q5Iscg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 330, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100ab40193f9b5d76c064a27940469d9fffd31d7c925fbe05c919491d3057d66cd2", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "040a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489", + "wx" : "0a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cd", + "wy" : "00e6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040a88361eb92ecca2625b38e5f98bbabb96bf179b3d76fc48140a3bcd881523cde6bdf56033f84a5054035597375d90866aa2c96b86a41ccf6edebf47298ad489", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECog2HrkuzKJiWzjl+Yu6u5a/F5s9\ndvxIFAo7zYgVI83mvfVgM/hKUFQDVZc3XZCGaqLJa4akHM9u3r9HKYrUiQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 331, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100ca0234ebb5fdcb13ca0234ecffffffffcb0dadbbc7f549f8a26b4408d0dc8600", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93", + "wx" : "00d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e8", + "wy" : "68612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d0fb17ccd8fafe827e0c1afc5d8d80366e2b20e7f14a563a2ba50469d84375e868612569d39e2bb9f554355564646de99ac602cc6349cf8c1e236a7de7637d93", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0PsXzNj6/oJ+DBr8XY2ANm4rIOfx\nSlY6K6UEadhDdehoYSVp054rufVUNVVkZG3pmsYCzGNJz4weI2p952N9kw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 332, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100bfffffff3ea3677e082b9310572620ae19933a9e65b285598711c77298815ad3", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75", + "wx" : "00836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb276", + "wy" : "009ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004836f33bbc1dc0d3d3abbcef0d91f11e2ac4181076c9af0a22b1e4309d3edb2769ab443ff6f901e30c773867582997c2bec2b0cb8120d760236f3a95bbe881f75", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg28zu8HcDT06u87w2R8R4qxBgQds\nmvCiKx5DCdPtsnaatEP/b5AeMMdzhnWCmXwr7CsMuBINdgI286lbvogfdQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 333, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0220266666663bbbbbbbe6666666666666665b37902e023fab7c8f055d86e5cc41f4", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0492f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697", + "wx" : "0092f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8", + "wy" : "033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000492f99fbe973ed4a299719baee4b432741237034dec8d72ba5103cb33e55feeb8033dd0e91134c734174889f3ebcf1b7a1ac05767289280ee7a794cebd6e69697", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkvmfvpc+1KKZcZuu5LQydBI3A03s\njXK6UQPLM+Vf7rgDPdDpETTHNBdIifPrzxt6GsBXZyiSgO56eUzr1uaWlw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 334, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100bfffffff36db6db7a492492492492492146c573f4c6dfc8d08a443e258970b09", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2", + "wx" : "00d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09e", + "wy" : "00ff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004d35ba58da30197d378e618ec0fa7e2e2d12cffd73ebbb2049d130bba434af09eff83986e6875e41ea432b7585a49b3a6c77cbb3c47919f8e82874c794635c1d2", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE01uljaMBl9N45hjsD6fi4tEs/9c+\nu7IEnRMLukNK8J7/g5huaHXkHqQyt1haSbOmx3y7PEeRn46Ch0x5RjXB0g==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 335, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304502207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd022100bfffffff2aaaaaab7fffffffffffffffc815d0e60b3e596ecb1ad3a27cfd49c4", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "048651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28", + "wx" : "008651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224", + "wy" : "00e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200048651ce490f1b46d73f3ff475149be29136697334a519d7ddab0725c8d0793224e11c65bd8ca92dc8bc9ae82911f0b52751ce21dd9003ae60900bd825f590cc28", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhlHOSQ8bRtc/P/R1FJvikTZpczSl\nGdfdqwclyNB5MiThHGW9jKktyLya6CkR8LUnUc4h3ZADrmCQC9gl9ZDMKA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 336, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02207fffffff55555555ffffffffffffffffd344a71e6f651458a27bdc81fd976e37", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "046d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37", + "wx" : "6d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6d", + "wy" : "00ef6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046d8e1b12c831a0da8795650ff95f101ed921d9e2f72b15b1cdaca9826b9cfc6def6d63e2bc5c089570394a4bc9f892d5e6c7a6a637b20469a58c106ad486bf37", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbY4bEsgxoNqHlWUP+V8QHtkh2eL3\nKxWxzaypgmuc/G3vbWPivFwIlXA5SkvJ+JLV5sempjeyBGmljBBq1Ia/Nw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 337, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02203fffffff800000007fffffffffffffffde737d56d38bcf4279dce5617e3192aa", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "040ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3", + "wx" : "0ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e1542", + "wy" : "008911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040ae580bae933b4ef2997cbdbb0922328ca9a410f627a0f7dff24cb4d920e15428911e7f8cc365a8a88eb81421a361ccc2b99e309d8dcd9a98ba83c3949d893e3", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECuWAuukztO8pl8vbsJIjKMqaQQ9i\neg99/yTLTZIOFUKJEef4zDZaiojrgUIaNhzMK5njCdjc2amLqDw5SdiT4w==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 338, + "comment" : "edge case for u2", + "msg" : "313233343030", + "sig" : "304402207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd02205d8ecd64a4eeba466815ddf3a4de9a8e6abd9c5db0a01eb80343553da648428f", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9", + "wx" : "5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963", + "wy" : "00838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963838a40f2a36092e9004e92d8d940cf5638550ce672ce8b8d4e15eba5499249e9", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW4Ev1SGq+mmDWoSczm+962mDtELS\nRE/nDhNMAn/EaWODikDyo2CS6QBOktjZQM9WOFUM5nLOi41OFeulSZJJ6Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 339, + "comment" : "point duplication during verification", + "msg" : "313233343030", + "sig" : "304502206f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569022100bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b", + "result" : "valid", + "flags" : [ + "PointDuplication" + ] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616", + "wx" : "5b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc46963", + "wy" : "7c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045b812fd521aafa69835a849cce6fbdeb6983b442d2444fe70e134c027fc469637c75bf0c5c9f6d17ffb16d2726bf30a9c7aaf31a8d317472b1ea145ab66db616", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW4Ev1SGq+mmDWoSczm+962mDtELS\nRE/nDhNMAn/EaWN8db8MXJ9tF/+xbScmvzCpx6rzGo0xdHKx6hRatm22Fg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 340, + "comment" : "duplication bug", + "msg" : "313233343030", + "sig" : "304502206f2347cab7dd76858fe0555ac3bc99048c4aacafdfb6bcbe05ea6c42c4934569022100bb726660235793aa9957a61e76e00c2c435109cf9a15dd624d53f4301047856b", + "result" : "invalid", + "flags" : [ + "PointDuplication" + ] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "046adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9", + "wx" : "6adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a6", + "wy" : "47e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046adda82b90261b0f319faa0d878665a6b6da497f09c903176222c34acfef72a647e6f50dcc40ad5d9b59f7602bb222fad71a41bf5e1f9df4959a364c62e488d9", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEat2oK5AmGw8xn6oNh4ZlprbaSX8J\nyQMXYiLDSs/vcqZH5vUNzECtXZtZ92ArsiL61xpBv14fnfSVmjZMYuSI2Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 341, + "comment" : "point with x-coordinate 0", + "msg" : "313233343030", + "sig" : "30250201010220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "042fca0d0a47914de77ed56e7eccc3276a601120c6df0069c825c8f6a01c9f382065f3450a1d17c6b24989a39beb1c7decfca8384fbdc294418e5d807b3c6ed7de", + "wx" : "2fca0d0a47914de77ed56e7eccc3276a601120c6df0069c825c8f6a01c9f3820", + "wy" : "65f3450a1d17c6b24989a39beb1c7decfca8384fbdc294418e5d807b3c6ed7de" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042fca0d0a47914de77ed56e7eccc3276a601120c6df0069c825c8f6a01c9f382065f3450a1d17c6b24989a39beb1c7decfca8384fbdc294418e5d807b3c6ed7de", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL8oNCkeRTed+1W5+zMMnamARIMbf\nAGnIJcj2oByfOCBl80UKHRfGskmJo5vrHH3s/Kg4T73ClEGOXYB7PG7X3g==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 342, + "comment" : "point with x-coordinate 0", + "msg" : "313233343030", + "sig" : "3045022101000000000000000000000000000000000000000000000000000000000000000002203333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7", + "wx" : "00dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d250", + "wy" : "45d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004dd86d3b5f4a13e8511083b78002081c53ff467f11ebd98a51a633db76665d25045d5c8200c89f2fa10d849349226d21d8dfaed6ff8d5cb3e1b7e17474ebc18f7", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3YbTtfShPoURCDt4ACCBxT/0Z/Ee\nvZilGmM9t2Zl0lBF1cggDIny+hDYSTSSJtIdjfrtb/jVyz4bfhdHTrwY9w==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 343, + "comment" : "comparison with point at infinity ", + "msg" : "313233343030", + "sig" : "30440220555555550000000055555555555555553ef7a8e48d07df81a693439654210c7002203333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aa9", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "044fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280", + "wx" : "4fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5", + "wy" : "00d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044fea55b32cb32aca0c12c4cd0abfb4e64b0f5a516e578c016591a93f5a0fbcc5d7d3fd10b2be668c547b212f6bb14c88f0fecd38a8a4b2c785ed3be62ce4b280", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAET+pVsyyzKsoMEsTNCr+05ksPWlFu\nV4wBZZGpP1oPvMXX0/0Qsr5mjFR7IS9rsUyI8P7NOKiksseF7TvmLOSygA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 344, + "comment" : "extreme value for k and edgecase s", + "msg" : "313233343030", + "sig" : "304402207cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc476699780220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04c6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e", + "wx" : "00c6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107", + "wy" : "00bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004c6a771527024227792170a6f8eee735bf32b7f98af669ead299802e32d7c3107bc3b4b5e65ab887bbd343572b3e5619261fe3a073e2ffd78412f726867db589e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExqdxUnAkIneSFwpvju5zW/Mrf5iv\nZp6tKZgC4y18MQe8O0teZauIe700NXKz5WGSYf46Bz4v/XhBL3JoZ9tYng==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 345, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304502207cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978022100b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6", + "wx" : "00851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956ef", + "wy" : "00cee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004851c2bbad08e54ec7a9af99f49f03644d6ec6d59b207fec98de85a7d15b956efcee9960283045075684b410be8d0f7494b91aa2379f60727319f10ddeb0fe9d6", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhRwrutCOVOx6mvmfSfA2RNbsbVmy\nB/7JjehafRW5Vu/O6ZYCgwRQdWhLQQvo0PdJS5GqI3n2BycxnxDd6w/p1g==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 346, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304502207cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978022100cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04f6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f", + "wx" : "00f6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f", + "wy" : "008f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004f6417c8a670584e388676949e53da7fc55911ff68318d1bf3061205acb19c48f8f2b743df34ad0f72674acb7505929784779cd9ac916c3669ead43026ab6d43f", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9kF8imcFhOOIZ2lJ5T2n/FWRH/aD\nGNG/MGEgWssZxI+PK3Q980rQ9yZ0rLdQWSl4R3nNmskWw2aerUMCarbUPw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 347, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304402207cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997802203333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371", + "wx" : "501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a0643", + "wy" : "008673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUBQhJ3vkWl7v7GxjmTDWNgMlZa9C\nDPM3P1V/qn+KBkOGc9bLYHbhz83H3+c4TI5crAjXRQHyrm6JytGV0KoTcQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 348, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304402207cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978022049249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "040d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5", + "wx" : "0d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb34", + "wy" : "3195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200040d935bf9ffc115a527735f729ca8a4ca23ee01a4894adf0e3415ac84e808bb343195a3762fea29ed38912bd9ea6c4fde70c3050893a4375850ce61d82eba33c5", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDZNb+f/BFaUnc19ynKikyiPuAaSJ\nSt8ONBWshOgIuzQxlaN2L+op7TiRK9nqbE/ecMMFCJOkN1hQzmHYLrozxQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 349, + "comment" : "extreme value for k", + "msg" : "313233343030", + "sig" : "304402207cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978022016a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "045e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de", + "wx" : "5e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca21", + "wy" : "5de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200045e59f50708646be8a589355014308e60b668fb670196206c41e748e64e4dca215de37fee5c97bcaf7144d5b459982f52eeeafbdf03aacbafef38e213624a01de", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXln1Bwhka+iliTVQFDCOYLZo+2cB\nliBsQedI5k5NyiFd43/uXJe8r3FE1bRZmC9S7ur73wOqy6/vOOITYkoB3g==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 350, + "comment" : "extreme value for k and edgecase s", + "msg" : "313233343030", + "sig" : "304402206b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2960220555555550000000055555555555555553ef7a8e48d07df81a693439654210c70", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667", + "wx" : "169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e", + "wy" : "7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004169fb797325843faff2f7a5b5445da9e2fd6226f7ef90ef0bfe924104b02db8e7bbb8de662c7b9b1cf9b22f7a2e582bd46d581d68878efb2b861b131d8a1d667", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFp+3lzJYQ/r/L3pbVEXani/WIm9+\n+Q7wv+kkEEsC2457u43mYse5sc+bIvei5YK9RtWB1oh477K4YbEx2KHWZw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 351, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304502206b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296022100b6db6db6249249254924924924924924625bd7a09bec4ca81bcdd9f8fd6b63cc", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5", + "wx" : "271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b54898148754", + "wy" : "0a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004271cd89c000143096b62d4e9e4ca885aef2f7023d18affdaf8b7b548981487540a1c6e954e32108435b55fa385b0f76481a609b9149ccb4b02b2ca47fe8e4da5", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJxzYnAABQwlrYtTp5MqIWu8vcCPR\niv/a+Le1SJgUh1QKHG6VTjIQhDW1X6OFsPdkgaYJuRScy0sCsspH/o5NpQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 352, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304502206b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296022100cccccccc00000000cccccccccccccccc971f2ef152794b9d8fc7d568c9e8eaa7", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "043d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df", + "wx" : "3d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12", + "wy" : "00e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043d0bc7ed8f09d2cb7ddb46ebc1ed799ab1563a9ab84bf524587a220afe499c12e22dc3b3c103824a4f378d96adb0a408abf19ce7d68aa6244f78cb216fa3f8df", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPQvH7Y8J0st920brwe15mrFWOpq4\nS/UkWHoiCv5JnBLiLcOzwQOCSk83jZatsKQIq/Gc59aKpiRPeMshb6P43w==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 353, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304402206b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c29602203333333300000000333333333333333325c7cbbc549e52e763f1f55a327a3aaa", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316", + "wx" : "00a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b7", + "wy" : "2e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004a6c885ade1a4c566f9bb010d066974abb281797fa701288c721bcbd23663a9b72e424b690957168d193a6096fc77a2b004a9c7d467e007e1f2058458f98af316", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpsiFreGkxWb5uwENBml0q7KBeX+n\nASiMchvL0jZjqbcuQktpCVcWjRk6YJb8d6KwBKnH1GfgB+HyBYRY+YrzFg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 354, + "comment" : "extreme value for k and s^-1", + "msg" : "313233343030", + "sig" : "304402206b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296022049249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "048d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d", + "wx" : "008d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c", + "wy" : "4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200048d3c2c2c3b765ba8289e6ac3812572a25bf75df62d87ab7330c3bdbad9ebfa5c4c6845442d66935b238578d43aec54f7caa1621d1af241d4632e0b780c423f5d", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjTwsLDt2W6gonmrDgSVyolv3XfYt\nh6tzMMO9utnr+lxMaEVELWaTWyOFeNQ67FT3yqFiHRryQdRjLgt4DEI/XQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 355, + "comment" : "extreme value for k", + "msg" : "313233343030", + "sig" : "304402206b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296022016a4502e2781e11ac82cbc9d1edd8c981584d13e18411e2f6e0478c34416e3bb", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "wx" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "wy" : "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaxfR8uEsQkf4vOblY6RA8ncDfYEt\n6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9Q==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 356, + "comment" : "testing point duplication", + "msg" : "313233343030", + "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230220249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 357, + "comment" : "testing point duplication", + "msg" : "313233343030", + "sig" : "3044022044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e0220249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "wx" : "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "wy" : "00b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296b01cbd1c01e58065711814b583f061e9d431cca994cea1313449bf97c840ae0a", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaxfR8uEsQkf4vOblY6RA8ncDfYEt\n6zOg9KE5RdiYwpawHL0cAeWAZXEYFLWD8GHp1DHMqZTOoTE0Sb+XyECuCg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 358, + "comment" : "testing point duplication", + "msg" : "313233343030", + "sig" : "3045022100bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050230220249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 359, + "comment" : "testing point duplication", + "msg" : "313233343030", + "sig" : "3044022044a5ad0ad0636d9f12bc9e0a6bdd5e1cbcb012ea7bf091fcec15b0c43202d52e0220249249246db6db6ddb6db6db6db6db6dad4591868595a8ee6bf5f864ff7be0c2", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0404aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "wx" : "04aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad5", + "wy" : "0087d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000404aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBKrsc2NXJvIT+4qeZNo7hjLkFJWp\nRNAEW1IuunJA+tWH2TFXmKqjpboBd1eHztBeqve04J/IHW0apUboNl1SXQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 360, + "comment" : "pseudorandom signature", + "msg" : "", + "sig" : "3045022100b292a619339f6e567a305c951c0dcbcc42d16e47f219f9e98e76e09d8770b34a02200177e60492c5a8242f76f07bfe3661bde59ec2a17ce5bd2dab2abebdf89a62e2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 361, + "comment" : "pseudorandom signature", + "msg" : "4d7367", + "sig" : "30450220530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23022100d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 362, + "comment" : "pseudorandom signature", + "msg" : "313233343030", + "sig" : "3046022100a8ea150cb80125d7381c4c1f1da8e9de2711f9917060406a73d7904519e51388022100f3ab9fa68bd47973a73b2d40480c2ba50c22c9d76ec217257288293285449b86", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 363, + "comment" : "pseudorandom signature", + "msg" : "0000000000000000000000000000000000000000", + "sig" : "3045022100986e65933ef2ed4ee5aada139f52b70539aaf63f00a91f29c69178490d57fb7102203dafedfb8da6189d372308cbf1489bbbdabf0c0217d1c0ff0f701aaa7a694b9c", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "044f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "wx" : "4f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000", + "wy" : "00ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200044f337ccfd67726a805e4f1600ae2849df3807eca117380239fbd816900000000ed9dea124cc8c396416411e988c30f427eb504af43a3146cd5df7ea60666d685", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETzN8z9Z3JqgF5PFgCuKEnfOAfsoR\nc4Ajn72BaQAAAADtneoSTMjDlkFkEemIww9CfrUEr0OjFGzV336mBmbWhQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 364, + "comment" : "x-coordinate of the public key has many trailing 0's", + "msg" : "4d657373616765", + "sig" : "3046022100d434e262a49eab7781e353a3565e482550dd0fd5defa013c7f29745eff3569f10221009b0c0a93f267fb6052fd8077be769c2b98953195d7bc10de844218305c6ba17a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 365, + "comment" : "x-coordinate of the public key has many trailing 0's", + "msg" : "4d657373616765", + "sig" : "304402200fe774355c04d060f76d79fd7a772e421463489221bf0a33add0be9b1979110b0220500dcba1c69a8fbd43fa4f57f743ce124ca8b91a1f325f3fac6181175df55737", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 366, + "comment" : "x-coordinate of the public key has many trailing 0's", + "msg" : "4d657373616765", + "sig" : "3045022100bb40bf217bed3fb3950c7d39f03d36dc8e3b2cd79693f125bfd06595ee1135e30220541bf3532351ebb032710bdb6a1bf1bfc89a1e291ac692b3fa4780745bb55677", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "wx" : "3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f497265004935", + "wy" : "0084fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f49726500493584fa174d791c72bf2ce3880a8960dd2a7c7a1338a82f85a9e59cdbde80000000", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPPA9YU2JOc/UmaB4c/rCgWGPBrj/\nh+gBXD9JcmUASTWE+hdNeRxyvyzjiAqJYN0qfHoTOKgvhanlnNvegAAAAA==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 367, + "comment" : "y-coordinate of the public key has many trailing 0's", + "msg" : "4d657373616765", + "sig" : "30440220664eb7ee6db84a34df3c86ea31389a5405badd5ca99231ff556d3e75a233e73a022059f3c752e52eca46137642490a51560ce0badc678754b8f72e51a2901426a1bd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 368, + "comment" : "y-coordinate of the public key has many trailing 0's", + "msg" : "4d657373616765", + "sig" : "304502204cd0429bbabd2827009d6fcd843d4ce39c3e42e2d1631fd001985a79d1fd8b430221009638bf12dd682f60be7ef1d0e0d98f08b7bca77a1a2b869ae466189d2acdabe3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 369, + "comment" : "y-coordinate of the public key has many trailing 0's", + "msg" : "4d657373616765", + "sig" : "3046022100e56c6ea2d1b017091c44d8b6cb62b9f460e3ce9aed5e5fd41e8added97c56c04022100a308ec31f281e955be20b457e463440b4fcf2b80258078207fc1378180f89b55", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "wx" : "3cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f497265004935", + "wy" : "7b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200043cf03d614d8939cfd499a07873fac281618f06b8ff87e8015c3f4972650049357b05e8b186e38d41d31c77f5769f22d58385ecc857d07a561a6324217fffffff", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPPA9YU2JOc/UmaB4c/rCgWGPBrj/\nh+gBXD9JcmUASTV7BeixhuONQdMcd/V2nyLVg4XsyFfQelYaYyQhf////w==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 370, + "comment" : "y-coordinate of the public key has many trailing 1's", + "msg" : "4d657373616765", + "sig" : "304402201158a08d291500b4cabed3346d891eee57c176356a2624fb011f8fbbf34668300220228a8c486a736006e082325b85290c5bc91f378b75d487dda46798c18f285519", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 371, + "comment" : "y-coordinate of the public key has many trailing 1's", + "msg" : "4d657373616765", + "sig" : "3045022100b1db9289649f59410ea36b0c0fc8d6aa2687b29176939dd23e0dde56d309fa9d02203e1535e4280559015b0dbd987366dcf43a6d1af5c23c7d584e1c3f48a1251336", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 372, + "comment" : "y-coordinate of the public key has many trailing 1's", + "msg" : "4d657373616765", + "sig" : "3046022100b7b16e762286cb96446aa8d4e6e7578b0a341a79f2dd1a220ac6f0ca4e24ed86022100ddc60a700a139b04661c547d07bbb0721780146df799ccf55e55234ecb8f12bc", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "042829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "wx" : "2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffff", + "wy" : "00a01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d030107034200042829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKCnDH6ouQA40TtlLyj/NBUWVbrz+\nitD236X/jv////+gGq+vAA5SWFhVr6dnat4oQRMJkFLfV+frO9N+vrkiLg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 373, + "comment" : "x-coordinate of the public key has many trailing 1's", + "msg" : "4d657373616765", + "sig" : "3045022100d82a7c2717261187c8e00d8df963ff35d796edad36bc6e6bd1c91c670d9105b402203dcabddaf8fcaa61f4603e7cbac0f3c0351ecd5988efb23f680d07debd139929", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 374, + "comment" : "x-coordinate of the public key has many trailing 1's", + "msg" : "4d657373616765", + "sig" : "304402205eb9c8845de68eb13d5befe719f462d77787802baff30ce96a5cba063254af7802202c026ae9be2e2a5e7ca0ff9bbd92fb6e44972186228ee9a62b87ddbe2ef66fb5", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 375, + "comment" : "x-coordinate of the public key has many trailing 1's", + "msg" : "4d657373616765", + "sig" : "304602210096843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28022100f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "wx" : "00fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f5", + "wy" : "5a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004fffffff948081e6a0458dd8f9e738f2665ff9059ad6aac0708318c4ca9a7a4f55a8abcba2dda8474311ee54149b973cae0c0fb89557ad0bf78e6529a1663bd73", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE////+UgIHmoEWN2PnnOPJmX/kFmt\naqwHCDGMTKmnpPVairy6LdqEdDEe5UFJuXPK4MD7iVV60L945lKaFmO9cw==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 376, + "comment" : "x-coordinate of the public key is large", + "msg" : "4d657373616765", + "sig" : "30440220766456dce1857c906f9996af729339464d27e9d98edc2d0e3b760297067421f60220402385ecadae0d8081dccaf5d19037ec4e55376eced699e93646bfbbf19d0b41", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 377, + "comment" : "x-coordinate of the public key is large", + "msg" : "4d657373616765", + "sig" : "3046022100c605c4b2edeab20419e6518a11b2dbc2b97ed8b07cced0b19c34f777de7b9fd9022100edf0f612c5f46e03c719647bc8af1b29b2cde2eda700fb1cff5e159d47326dba", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 378, + "comment" : "x-coordinate of the public key is large", + "msg" : "4d657373616765", + "sig" : "3046022100d48b68e6cabfe03cf6141c9ac54141f210e64485d9929ad7b732bfe3b7eb8a84022100feedae50c61bd00e19dc26f9b7e2265e4508c389109ad2f208f0772315b6c941", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "0400000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "wx" : "03fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e", + "wy" : "1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d0301070342000400000003fa15f963949d5f03a6f5c7f86f9e0015eeb23aebbff1173937ba748e1099872070e8e87c555fa13659cca5d7fadcfcb0023ea889548ca48af2ba7e71", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAAAAA/oV+WOUnV8DpvXH+G+eABXu\nsjrrv/EXOTe6dI4QmYcgcOjofFVfoTZZzKXX+tz8sAI+qIlUjKSK8rp+cQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 379, + "comment" : "x-coordinate of the public key is small", + "msg" : "4d657373616765", + "sig" : "3046022100b7c81457d4aeb6aa65957098569f0479710ad7f6595d5874c35a93d12a5dd4c7022100b7961a0b652878c2d568069a432ca18a1a9199f2ca574dad4b9e3a05c0a1cdb3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 380, + "comment" : "x-coordinate of the public key is small", + "msg" : "4d657373616765", + "sig" : "304402206b01332ddb6edfa9a30a1321d5858e1ee3cf97e263e669f8de5e9652e76ff3f702205939545fced457309a6a04ace2bd0f70139c8f7d86b02cb1cc58f9e69e96cd5a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 381, + "comment" : "x-coordinate of the public key is small", + "msg" : "4d657373616765", + "sig" : "3046022100efdb884720eaeadc349f9fc356b6c0344101cd2fd8436b7d0e6a4fb93f106361022100f24bee6ad5dc05f7613975473aadf3aacba9e77de7d69b6ce48cb60d8113385d", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "wx" : "00bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015", + "wy" : "1352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvLspFMefBF6qbsu8YSgWs75dLWeW\ncH2BJen4UcGK8BUAAAAAE1K7Sg+i6kzOuatj3WhK3loRJ7zzAKaYpxk7wg==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 382, + "comment" : "y-coordinate of the public key is small", + "msg" : "4d657373616765", + "sig" : "3044022031230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb0702200f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beff", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 383, + "comment" : "y-coordinate of the public key is small", + "msg" : "4d657373616765", + "sig" : "3046022100caa797da65b320ab0d5c470cda0b36b294359c7db9841d679174db34c4855743022100cf543a62f23e212745391aaf7505f345123d2685ee3b941d3de6d9b36242e5a0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 384, + "comment" : "y-coordinate of the public key is small", + "msg" : "4d657373616765", + "sig" : "304502207e5f0ab5d900d3d3d7867657e5d6d36519bc54084536e7d21c336ed8001859450221009450c07f201faec94b82dfb322e5ac676688294aad35aa72e727ff0b19b646aa", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "key" : { + "curve" : "secp256r1", + "keySize" : 256, + "type" : "EcPublicKey", + "uncompressed" : "04bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "wx" : "00bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015", + "wy" : "00fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d" + }, + "keyDer" : "3059301306072a8648ce3d020106082a8648ce3d03010703420004bcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015fffffffeecad44b6f05d15b33146549c2297b522a5eed8430cff596758e6c43d", + "keyPem" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvLspFMefBF6qbsu8YSgWs75dLWeW\ncH2BJen4UcGK8BX////+7K1EtvBdFbMxRlScIpe1IqXu2EMM/1lnWObEPQ==\n-----END PUBLIC KEY-----", + "sha" : "SHA-256", + "type" : "EcdsaVerify", + "tests" : [ + { + "tcId" : 385, + "comment" : "y-coordinate of the public key is large", + "msg" : "4d657373616765", + "sig" : "3046022100d7d70c581ae9e3f66dc6a480bf037ae23f8a1e4a2136fe4b03aa69f0ca25b35602210089c460f8a5a5c2bbba962c8a3ee833a413e85658e62a59e2af41d9127cc47224", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 386, + "comment" : "y-coordinate of the public key is large", + "msg" : "4d657373616765", + "sig" : "30440220341c1b9ff3c83dd5e0dfa0bf68bcdf4bb7aa20c625975e5eeee34bb396266b34022072b69f061b750fd5121b22b11366fad549c634e77765a017902a67099e0a4469", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 387, + "comment" : "y-coordinate of the public key is large", + "msg" : "4d657373616765", + "sig" : "3045022070bebe684cdcb5ca72a42f0d873879359bd1781a591809947628d313a3814f67022100aec03aca8f5587a4d535fa31027bbe9cc0e464b1c3577f4c2dcde6b2094798a9", + "result" : "valid", + "flags" : [] + } + ] + } + ] +} diff --git a/libraries/crypto/tests/wycheproof.rs b/libraries/crypto/tests/wycheproof.rs new file mode 100644 index 0000000..910a768 --- /dev/null +++ b/libraries/crypto/tests/wycheproof.rs @@ -0,0 +1,217 @@ +// Copyright 2019 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. + +use crypto::ecdsa; +use serde::Deserialize; +use std::collections::HashMap; +use std::error::Error; +use std::fs::File; +use std::io::BufReader; +use std::path::Path; + +mod asn1; + +#[test] +fn wycheproof() { + let wycheproof = load_tests("tests/data/ecdsa_secp256r1_sha256_test.json").unwrap(); + wycheproof.type_check(); + assert!(wycheproof.run_tests()); +} + +fn load_tests>(path: P) -> Result> { + let file = File::open(path)?; + let wycheproof = serde_json::from_reader(BufReader::new(file))?; + Ok(wycheproof) +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct Wycheproof { + algorithm: String, + #[allow(dead_code)] + generatorVersion: String, + #[allow(dead_code)] + numberOfTests: u32, + #[allow(dead_code)] + header: Vec, + notes: HashMap, + schema: String, + testGroups: Vec, +} + +impl Wycheproof { + fn type_check(&self) { + assert_eq!(self.algorithm, "ECDSA"); + assert_eq!(self.schema, "ecdsa_verify_schema.json"); + for group in &self.testGroups { + group.type_check(); + } + } + + fn run_tests(&self) -> bool { + let mut result = true; + for group in &self.testGroups { + result &= group.run_tests(&self.notes); + } + result + } +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct TestGroup { + key: Key, + #[allow(dead_code)] + keyDer: String, + #[allow(dead_code)] + keyPem: String, + sha: String, + r#type: String, + tests: Vec, +} + +impl TestGroup { + fn type_check(&self) { + self.key.type_check(); + assert_eq!(self.sha, "SHA-256"); + assert_eq!(self.r#type, "EcdsaVerify"); + for test in &self.tests { + test.type_check(); + } + } + + fn run_tests(&self, notes: &HashMap) -> bool { + let key = self.key.get_key(); + let mut result = true; + for test in &self.tests { + result &= test.run_test(&key, notes); + } + result + } +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct Key { + curve: String, + keySize: u32, + r#type: String, + uncompressed: String, + #[allow(dead_code)] + wx: String, + #[allow(dead_code)] + wy: String, +} + +impl Key { + fn type_check(&self) { + assert_eq!(self.curve, "secp256r1"); + assert_eq!(self.keySize, 256); + assert_eq!(self.r#type, "EcPublicKey"); + assert_eq!(self.uncompressed.len(), 130); + } + + fn get_key(&self) -> Option { + let bytes = hex::decode(&self.uncompressed).unwrap(); + ecdsa::PubKey::from_bytes_uncompressed(&bytes) + } +} + +#[derive(Deserialize, Debug)] +#[allow(non_camel_case_types)] +enum TestResult { + valid, + invalid, + acceptable, +} + +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct TestCase { + tcId: u32, + comment: String, + msg: String, + sig: String, + result: TestResult, + flags: Vec, +} + +impl TestCase { + fn type_check(&self) { + // Nothing to do. + } + + fn print(&self, notes: &HashMap, error_msg: &str) { + println!("Test case #{} => {}", self.tcId, error_msg); + println!(" {}", self.comment); + println!(" result = {:?}", self.result); + for f in &self.flags { + println!( + " flag {} = {}", + f, + notes.get(f).map_or("unknown flag", |x| &x) + ); + } + } + + fn run_test(&self, key: &Option, notes: &HashMap) -> bool { + match key { + None => { + let pass = match self.result { + TestResult::invalid | TestResult::acceptable => true, + TestResult::valid => false, + }; + if !pass { + self.print(notes, "Invalid public key"); + } + pass + } + Some(k) => { + let msg = hex::decode(&self.msg).unwrap(); + let sig = hex::decode(&self.sig).unwrap(); + match asn1::parse_signature(sig.as_slice()) { + Err(e) => { + let pass = match self.result { + TestResult::invalid | TestResult::acceptable => true, + TestResult::valid => false, + }; + if !pass { + self.print(notes, "Invalid ASN.1 encoding for the signature"); + println!(" {:?}", e); + } + pass + } + Ok(signature) => { + let verified = k.verify_vartime::(&msg, &signature); + let pass = match self.result { + TestResult::acceptable => true, + TestResult::valid => verified, + TestResult::invalid => !verified, + }; + if !pass { + self.print( + notes, + &format!( + "Expected {:?} result, but the signature verification was {}", + self.result, verified + ), + ); + } + pass + } + } + } + } + } +} diff --git a/nrf52840dk_layout.ld b/nrf52840dk_layout.ld new file mode 100644 index 0000000..218b6bb --- /dev/null +++ b/nrf52840dk_layout.ld @@ -0,0 +1,19 @@ +/* Layout for the nRF52840-DK and nRF52840 dongle, used by the + * app in this repository. + */ + +MEMORY { + /* The application region is 64 bytes (0x40) */ + FLASH (rx) : ORIGIN = 0x00040040, LENGTH = 0x000BFFC0 + SRAM (rwx) : ORIGIN = 0x20020000, LENGTH = 128K +} + +/* + * Any change to STACK_SIZE should be accompanied by a corresponding change to + * `elf2tab`'s `--stack` option + */ +STACK_SIZE = 16384; + +MPU_MIN_ALIGN = 8K; + +INCLUDE layout.ld diff --git a/patches/libtock-rs/01-panic_console.patch b/patches/libtock-rs/01-panic_console.patch new file mode 100644 index 0000000..dd8f31c --- /dev/null +++ b/patches/libtock-rs/01-panic_console.patch @@ -0,0 +1,81 @@ +diff --git a/Cargo.toml b/Cargo.toml +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -7,6 +7,9 @@ + + [dependencies] + linked_list_allocator = "0.6.4" ++ ++[features] ++panic_console = [] + + [dev-dependencies] + corepack = { version = "0.4.0", default-features = false, features = ["alloc"] } +diff --git a/src/lang_items.rs b/src/lang_items.rs +index ab2c945..deef73b 100644 +--- a/src/lang_items.rs ++++ b/src/lang_items.rs +@@ -18,10 +18,14 @@ + //! `rustc_main`. That's covered by the `_start` function in the root of this + //! crate. + ++#[cfg(feature = "panic_console")] ++use crate::console::Console; + use crate::led; + use crate::timer; + use crate::timer::Duration; + use core::alloc::Layout; ++#[cfg(feature = "panic_console")] ++use core::fmt::Write; + use core::panic::PanicInfo; + + #[lang = "start"] +@@ -42,11 +46,7 @@ + } + } + +-#[panic_handler] +-fn panic_handler(_info: &PanicInfo) -> ! { ++fn flash_all_leds() -> ! { +- // Signal a panic using the LowLevelDebug capsule (if available). +- super::debug::low_level_status_code(1); +- + // Flash all LEDs (if available). + loop { + for led in led::all() { +@@ -60,6 +59,34 @@ + } + } + ++#[cfg(feature = "panic_console")] ++#[panic_handler] ++fn panic_handler(info: &PanicInfo) -> ! { ++ // Signal a panic using the LowLevelDebug capsule (if available). ++ super::debug::low_level_status_code(1); ++ ++ let mut console = Console::new(); ++ writeln!(console, "{}", info).ok(); ++ // Force the kernel to report the panic cause, by reading an invalid address. ++ // The memory protection unit should be setup by the Tock kernel to prevent apps from accessing ++ // address zero. ++ unsafe { ++ core::ptr::read_volatile(0 as *const usize); ++ } ++ // We still flash the LEDs in case for some reason the previous line didn't cause a crash in ++ // the kernel. ++ flash_all_leds(); ++} ++ ++#[cfg(not(feature = "panic_console"))] ++#[panic_handler] ++fn panic_handler(_info: &PanicInfo) -> ! { ++ // Signal a panic using the LowLevelDebug capsule (if available). ++ super::debug::low_level_status_code(1); ++ ++ flash_all_leds(); ++} ++ + #[alloc_error_handler] + fn cycle_leds(_: Layout) -> ! { + loop { + diff --git a/patches/libtock-rs/02-timer.patch b/patches/libtock-rs/02-timer.patch new file mode 100644 index 0000000..7b8a5d9 --- /dev/null +++ b/patches/libtock-rs/02-timer.patch @@ -0,0 +1,72 @@ +diff --git a/src/timer.rs b/src/timer.rs +index ae60b07..2e7d544 100644 +--- a/src/timer.rs ++++ b/src/timer.rs +@@ -178,7 +178,7 @@ impl<'a> Timer<'a> { + } + } + +-#[derive(Copy, Clone, Debug)] ++#[derive(Copy, Clone, Debug, PartialEq)] + pub struct ClockFrequency { + hz: usize, + } +@@ -196,21 +196,53 @@ pub struct ClockValue { + } + + impl ClockValue { ++ pub const fn new(num_ticks: isize, clock_hz: usize) -> ClockValue { ++ ClockValue { ++ num_ticks, ++ clock_frequency: ClockFrequency { hz: clock_hz }, ++ } ++ } ++ + pub fn num_ticks(&self) -> isize { + self.num_ticks + } + ++ // Computes (value * factor) / divisor, even when value * factor >= isize::MAX. ++ fn scale_int(value: isize, factor: isize, divisor: isize) -> isize { ++ // As long as isize is not i64, this should be fine. If not, this is an alternative: ++ // factor * (value / divisor) + ((value % divisor) * factor) / divisor ++ ((value as i64 * factor as i64) / divisor as i64) as isize ++ } ++ + pub fn ms(&self) -> isize { +- if self.num_ticks.abs() < isize::MAX / 1000 { +- (1000 * self.num_ticks) / self.clock_frequency.hz() as isize +- } else { +- 1000 * (self.num_ticks / self.clock_frequency.hz() as isize) +- } ++ ClockValue::scale_int(self.num_ticks, 1000, self.clock_frequency.hz() as isize) + } + + pub fn ms_f64(&self) -> f64 { + 1000.0 * (self.num_ticks as f64) / (self.clock_frequency.hz() as f64) + } ++ ++ pub fn wrapping_add(self, duration: Duration) -> ClockValue { ++ // This is a precision preserving formula for scaling an isize. ++ let duration_ticks = ++ ClockValue::scale_int(duration.ms, self.clock_frequency.hz() as isize, 1000); ++ ClockValue { ++ num_ticks: self.num_ticks.wrapping_add(duration_ticks), ++ clock_frequency: self.clock_frequency, ++ } ++ } ++ ++ pub fn wrapping_sub(self, other: ClockValue) -> Option> { ++ if self.clock_frequency == other.clock_frequency { ++ let clock_duration = ClockValue { ++ num_ticks: self.num_ticks - other.num_ticks, ++ clock_frequency: self.clock_frequency, ++ }; ++ Some(Duration::from_ms(clock_duration.ms())) ++ } else { ++ None ++ } ++ } + } + + pub struct Alarm { diff --git a/patches/libtock-rs/03-public_syscalls.patch b/patches/libtock-rs/03-public_syscalls.patch new file mode 100644 index 0000000..109b6cb --- /dev/null +++ b/patches/libtock-rs/03-public_syscalls.patch @@ -0,0 +1,13 @@ +diff --git a/src/lib.rs b/src/lib.rs +index 1d4f26b..c1483e9 100644 +--- a/src/lib.rs ++++ b/src/lib.rs +@@ -42,7 +42,7 @@ pub mod syscalls; + + #[cfg(not(any(target_arch = "arm", target_arch = "riscv32")))] + #[path = "syscalls_mock.rs"] +-mod syscalls; ++pub mod syscalls; + + #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] + #[global_allocator] diff --git a/patches/libtock-rs/04-bigger_heap.patch b/patches/libtock-rs/04-bigger_heap.patch new file mode 100644 index 0000000..098737d --- /dev/null +++ b/patches/libtock-rs/04-bigger_heap.patch @@ -0,0 +1,13 @@ +diff --git a/src/entry_point.rs b/src/entry_point.rs +index a24958c..e907e33 100644 +--- a/src/entry_point.rs ++++ b/src/entry_point.rs +@@ -348,7 +348,7 @@ pub unsafe extern "C" fn rust_start(app_start: usize, stacktop: usize, app_heap_ + // Heap size is set using `elf2tab` with `--app-heap` option, which is + // currently at 1024. If you change the `elf2tab` heap size, make sure to + // make the corresponding change here. +- const HEAP_SIZE: usize = 1024; ++ const HEAP_SIZE: usize = 90000; + + // we could have also bss_end for app_heap_start + let app_heap_start = app_heap_break; diff --git a/patches/tock/01-persistent-storage.patch b/patches/tock/01-persistent-storage.patch new file mode 100644 index 0000000..1a356a3 --- /dev/null +++ b/patches/tock/01-persistent-storage.patch @@ -0,0 +1,323 @@ +diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs +index ddac9dbd..7e2a3298 100644 +--- a/boards/nordic/nrf52dk_base/src/lib.rs ++++ b/boards/nordic/nrf52dk_base/src/lib.rs +@@ -105,6 +105,7 @@ pub struct Platform { + // The nRF52dk does not have the flash chip on it, so we make this optional. + nonvolatile_storage: + Option<&'static capsules::nonvolatile_storage_driver::NonvolatileStorage<'static>>, ++ nvmc: &'static nrf52::nvmc::SyscallDriver, + } + + impl kernel::Platform for Platform { +@@ -128,6 +129,7 @@ impl kernel::Platform for Platform { + capsules::nonvolatile_storage_driver::DRIVER_NUM => { + f(self.nonvolatile_storage.map_or(None, |nv| Some(nv))) + } ++ nrf52::nvmc::DRIVER_NUM => f(Some(self.nvmc)), + kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), + _ => f(None), + } +@@ -408,6 +410,14 @@ pub unsafe fn setup_board( + None + }; + ++ let nvmc = static_init!( ++ nrf52::nvmc::SyscallDriver, ++ nrf52::nvmc::SyscallDriver::new( ++ &nrf52::nvmc::NVMC, ++ board_kernel.create_grant(&memory_allocation_capability) ++ ) ++ ); ++ + // Start all of the clocks. Low power operation will require a better + // approach than this. + nrf52::clock::CLOCK.low_stop(); +@@ -441,6 +451,7 @@ pub unsafe fn setup_board( + alarm: alarm, + nonvolatile_storage: nonvolatile_storage, + ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), ++ nvmc: nvmc, + }; + + platform.pconsole.start(); +diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs +index 5abd2d84..5a726fdb 100644 +--- a/chips/nrf52/src/nvmc.rs ++++ b/chips/nrf52/src/nvmc.rs +@@ -3,6 +3,7 @@ + //! Used in order read and write to internal flash. + + use core::cell::Cell; ++use core::convert::TryFrom; + use core::ops::{Index, IndexMut}; + use kernel::common::cells::OptionalCell; + use kernel::common::cells::TakeCell; +@@ -11,7 +12,7 @@ use kernel::common::deferred_call::DeferredCall; + use kernel::common::registers::{register_bitfields, ReadOnly, ReadWrite}; + use kernel::common::StaticRef; + use kernel::hil; +-use kernel::ReturnCode; ++use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared}; + + use crate::deferred_call_tasks::DeferredCallTask; + +@@ -141,7 +142,13 @@ register_bitfields! [u32, + static DEFERRED_CALL: DeferredCall = + unsafe { DeferredCall::new(DeferredCallTask::Nvmc) }; + ++type WORD = u32; ++const WORD_SIZE: usize = core::mem::size_of::(); + const PAGE_SIZE: usize = 4096; ++const MAX_WORD_WRITES: usize = 2; ++const MAX_PAGE_ERASES: usize = 10000; ++const WORD_MASK: usize = WORD_SIZE - 1; ++const PAGE_MASK: usize = PAGE_SIZE - 1; + + /// This is a wrapper around a u8 array that is sized to a single page for the + /// nrf. Users of this module must pass an object of this type to use the +@@ -215,6 +222,11 @@ impl Nvmc { + } + } + ++ pub fn configure_readonly(&self) { ++ let regs = &*self.registers; ++ regs.config.write(Configuration::WEN::Ren); ++ } ++ + /// Configure the NVMC to allow writes to flash. + pub fn configure_writeable(&self) { + let regs = &*self.registers; +@@ -230,7 +242,7 @@ impl Nvmc { + let regs = &*self.registers; + regs.config.write(Configuration::WEN::Een); + while !self.is_ready() {} +- regs.erasepage.write(ErasePage::ERASEPAGE.val(0x10001000)); ++ regs.eraseuicr.write(EraseUicr::ERASEUICR::ERASE); + while !self.is_ready() {} + } + +@@ -314,7 +326,7 @@ impl Nvmc { + // Put the NVMC in write mode. + regs.config.write(Configuration::WEN::Wen); + +- for i in (0..data.len()).step_by(4) { ++ for i in (0..data.len()).step_by(WORD_SIZE) { + let word: u32 = (data[i + 0] as u32) << 0 + | (data[i + 1] as u32) << 8 + | (data[i + 2] as u32) << 16 +@@ -374,3 +386,178 @@ impl hil::flash::Flash for Nvmc { + self.erase_page(page_number) + } + } ++ ++/// Provides access to the writeable flash regions of the application. ++/// ++/// The purpose of this driver is to provide low-level access to the embedded flash of nRF52 boards ++/// to allow applications to implement flash-aware (like wear-leveling) data-structures. The driver ++/// only permits applications to operate on their writeable flash regions. The API is blocking since ++/// the CPU is halted during write and erase operations. ++/// ++/// Supported boards: ++/// - nRF52840 (tested) ++/// - nRF52833 ++/// - nRF52811 ++/// - nRF52810 ++/// ++/// The maximum number of writes for the nRF52832 board is not per word but per block (512 bytes) ++/// and as such doesn't exactly fit this API. However, it could be safely supported by returning ++/// either 1 for the maximum number of word writes (i.e. the flash can only be written once before ++/// being erased) or 8 for the word size (i.e. the write granularity is doubled). In both cases, ++/// only 128 writes per block are permitted while the flash supports 181. ++/// ++/// # Syscalls ++/// ++/// - COMMAND(0): Check the driver. ++/// - COMMAND(1, 0): Get the word size (always 4). ++/// - COMMAND(1, 1): Get the page size (always 4096). ++/// - COMMAND(1, 2): Get the maximum number of word writes between page erasures (always 2). ++/// - COMMAND(1, 3): Get the maximum number page erasures in the lifetime of the flash (always ++/// 10000). ++/// - COMMAND(2, ptr): Write the allow slice to the flash region starting at `ptr`. ++/// - `ptr` must be word-aligned. ++/// - The allow slice length must be word aligned. ++/// - The region starting at `ptr` of the same length as the allow slice must be in a writeable ++/// flash region. ++/// - COMMAND(3, ptr): Erase a page. ++/// - `ptr` must be page-aligned. ++/// - The page starting at `ptr` must be in a writeable flash region. ++/// - ALLOW(0): The allow slice for COMMAND(2). ++pub struct SyscallDriver { ++ nvmc: &'static Nvmc, ++ apps: Grant, ++} ++ ++pub const DRIVER_NUM: usize = 0x50003; ++ ++#[derive(Default)] ++pub struct App { ++ /// The allow slice for COMMAND(2). ++ slice: Option>, ++} ++ ++impl SyscallDriver { ++ pub fn new(nvmc: &'static Nvmc, apps: Grant) -> SyscallDriver { ++ SyscallDriver { nvmc, apps } ++ } ++} ++ ++fn is_write_needed(old: u32, new: u32) -> bool { ++ // No need to write if it would not modify the current value. ++ old & new != old ++} ++ ++impl SyscallDriver { ++ /// Writes a word-aligned slice at a word-aligned address. ++ /// ++ /// Words are written only if necessary, i.e. if writing the new value would change the current ++ /// value. This can be used to simplify recovery operations (e.g. if power is lost during a ++ /// write operation). The application doesn't need to check which prefix has already been ++ /// written and may repeat the complete write that was interrupted. ++ /// ++ /// # Safety ++ /// ++ /// The words in this range must have been written less than `MAX_WORD_WRITES` since their last ++ /// page erasure. ++ /// ++ /// # Errors ++ /// ++ /// Fails with `EINVAL` if any of the following conditions does not hold: ++ /// - `ptr` must be word-aligned. ++ /// - `slice.len()` must be word-aligned. ++ /// - The slice starting at `ptr` of length `slice.len()` must fit in a writeable flash region. ++ fn write_slice(&self, appid: AppId, ptr: usize, slice: &[u8]) -> ReturnCode { ++ if !appid.in_writeable_flash_region(ptr, slice.len()) { ++ return ReturnCode::EINVAL; ++ } ++ if ptr & WORD_MASK != 0 || slice.len() & WORD_MASK != 0 { ++ return ReturnCode::EINVAL; ++ } ++ self.nvmc.configure_writeable(); ++ for (i, chunk) in slice.chunks(WORD_SIZE).enumerate() { ++ // `unwrap` cannot fail because `slice.len()` is word-aligned (see above). ++ let val = WORD::from_ne_bytes(<[u8; WORD_SIZE]>::try_from(chunk).unwrap()); ++ let loc = unsafe { &*(ptr as *const VolatileCell).add(i) }; ++ if is_write_needed(loc.get(), val) { ++ loc.set(val); ++ } ++ } ++ while !self.nvmc.is_ready() {} ++ self.nvmc.configure_readonly(); ++ ReturnCode::SUCCESS ++ } ++ ++ /// Erases a page at a page-aligned address. ++ /// ++ /// # Errors ++ /// ++ /// Fails with `EINVAL` if any of the following conditions does not hold: ++ /// - `ptr` must be page-aligned. ++ /// - The slice starting at `ptr` of length `PAGE_SIZE` must fit in a writeable flash region. ++ fn erase_page(&self, appid: AppId, ptr: usize) -> ReturnCode { ++ if !appid.in_writeable_flash_region(ptr, PAGE_SIZE) { ++ return ReturnCode::EINVAL; ++ } ++ if ptr & PAGE_MASK != 0 { ++ return ReturnCode::EINVAL; ++ } ++ self.nvmc.erase_page_helper(ptr / PAGE_SIZE); ++ self.nvmc.configure_readonly(); ++ ReturnCode::SUCCESS ++ } ++} ++ ++impl Driver for SyscallDriver { ++ fn subscribe(&self, _: usize, _: Option, _: AppId) -> ReturnCode { ++ ReturnCode::ENOSUPPORT ++ } ++ ++ fn command(&self, cmd: usize, arg: usize, _: usize, appid: AppId) -> ReturnCode { ++ match (cmd, arg) { ++ (0, _) => ReturnCode::SUCCESS, ++ ++ (1, 0) => ReturnCode::SuccessWithValue { value: WORD_SIZE }, ++ (1, 1) => ReturnCode::SuccessWithValue { value: PAGE_SIZE }, ++ (1, 2) => ReturnCode::SuccessWithValue { ++ value: MAX_WORD_WRITES, ++ }, ++ (1, 3) => ReturnCode::SuccessWithValue { ++ value: MAX_PAGE_ERASES, ++ }, ++ (1, _) => ReturnCode::EINVAL, ++ ++ (2, ptr) => self ++ .apps ++ .enter(appid, |app, _| { ++ let slice = match app.slice.take() { ++ None => return ReturnCode::EINVAL, ++ Some(slice) => slice, ++ }; ++ self.write_slice(appid, ptr, slice.as_ref()) ++ }) ++ .unwrap_or_else(|err| err.into()), ++ ++ (3, ptr) => self.erase_page(appid, ptr), ++ ++ _ => ReturnCode::ENOSUPPORT, ++ } ++ } ++ ++ fn allow( ++ &self, ++ appid: AppId, ++ allow_num: usize, ++ slice: Option>, ++ ) -> ReturnCode { ++ match allow_num { ++ 0 => self ++ .apps ++ .enter(appid, |app, _| { ++ app.slice = slice; ++ ReturnCode::SUCCESS ++ }) ++ .unwrap_or_else(|err| err.into()), ++ _ => ReturnCode::ENOSUPPORT, ++ } ++ } ++} +diff --git a/kernel/src/callback.rs b/kernel/src/callback.rs +index 95b25cc0..a7d8bc5c 100644 +--- a/kernel/src/callback.rs ++++ b/kernel/src/callback.rs +@@ -50,6 +50,31 @@ impl AppId { + (start, end) + }) + } ++ ++ pub fn in_writeable_flash_region(&self, ptr: usize, len: usize) -> bool { ++ self.kernel.process_map_or(false, self.idx, |process| { ++ let ptr = match ptr.checked_sub(process.flash_start() as usize) { ++ None => return false, ++ Some(ptr) => ptr, ++ }; ++ (0..process.number_writeable_flash_regions()).any(|i| { ++ let (region_ptr, region_len) = process.get_writeable_flash_region(i); ++ let region_ptr = region_ptr as usize; ++ let region_len = region_len as usize; ++ // We want to check the 2 following inequalities: ++ // (1) `region_ptr <= ptr` ++ // (2) `ptr + len <= region_ptr + region_len` ++ // However, the second one may overflow written as is. We introduce a third ++ // inequality to solve this issue: ++ // (3) `len <= region_len` ++ // Using this third inequality, we can rewrite the second one as: ++ // (4) `ptr - region_ptr <= region_len - len` ++ // This fourth inequality is equivalent to the second one but doesn't overflow when ++ // the first and third inequalities hold. ++ region_ptr <= ptr && len <= region_len && ptr - region_ptr <= region_len - len ++ }) ++ }) ++ } + } + + /// Type to uniquely identify a callback subscription across all drivers. diff --git a/patches/tock/02-usb.patch b/patches/tock/02-usb.patch new file mode 100644 index 0000000..0ba33d8 --- /dev/null +++ b/patches/tock/02-usb.patch @@ -0,0 +1,1009 @@ +diff --git a/boards/nordic/nrf52840_dongle/src/main.rs b/boards/nordic/nrf52840_dongle/src/main.rs +index 5a9da538..75043d13 100644 +--- a/boards/nordic/nrf52840_dongle/src/main.rs ++++ b/boards/nordic/nrf52840_dongle/src/main.rs +@@ -140,6 +140,7 @@ pub unsafe fn reset_handler() { + FAULT_RESPONSE, + nrf52840::uicr::Regulator0Output::V3_0, + false, ++ &Some(&nrf52840::usbd::USBD), + chip, + ); + } +diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs +index 0b19ea3f..bd71dfbe 100644 +--- a/boards/nordic/nrf52840dk/src/main.rs ++++ b/boards/nordic/nrf52840dk/src/main.rs +@@ -252,6 +252,7 @@ pub unsafe fn reset_handler() { + FAULT_RESPONSE, + nrf52840::uicr::Regulator0Output::DEFAULT, + false, ++ &Some(&nrf52840::usbd::USBD), + chip, + ); + } +diff --git a/boards/nordic/nrf52dk/src/main.rs b/boards/nordic/nrf52dk/src/main.rs +index b49518ff..39f996c4 100644 +--- a/boards/nordic/nrf52dk/src/main.rs ++++ b/boards/nordic/nrf52dk/src/main.rs +@@ -209,6 +209,7 @@ pub unsafe fn reset_handler() { + FAULT_RESPONSE, + nrf52832::uicr::Regulator0Output::DEFAULT, + false, ++ &None, + chip, + ); + } +diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs +index 7e2a3298..d391e455 100644 +--- a/boards/nordic/nrf52dk_base/src/lib.rs ++++ b/boards/nordic/nrf52dk_base/src/lib.rs +@@ -102,6 +102,13 @@ pub struct Platform { + 'static, + capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>, + >, ++ usb: Option< ++ &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< ++ 'static, ++ 'static, ++ nrf52::usbd::Usbd<'static>, ++ >, ++ >, + // The nRF52dk does not have the flash chip on it, so we make this optional. + nonvolatile_storage: + Option<&'static capsules::nonvolatile_storage_driver::NonvolatileStorage<'static>>, +@@ -130,6 +137,9 @@ impl kernel::Platform for Platform { + f(self.nonvolatile_storage.map_or(None, |nv| Some(nv))) + } + nrf52::nvmc::DRIVER_NUM => f(Some(self.nvmc)), ++ capsules::usb::usb_ctap::DRIVER_NUM => { ++ f(self.usb.map(|ctap| ctap as &dyn kernel::Driver)) ++ } + kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), + _ => f(None), + } +@@ -157,6 +167,7 @@ pub unsafe fn setup_board( + app_fault_response: kernel::procs::FaultResponse, + reg_vout: Regulator0Output, + nfc_as_gpios: bool, ++ usb: &Option<&'static nrf52::usbd::Usbd<'static>>, + chip: &'static nrf52::chip::NRF52, + ) { + // Make non-volatile memory writable and activate the reset button +@@ -418,6 +429,44 @@ pub unsafe fn setup_board( + ) + ); + ++ // Configure USB controller if supported ++ let usb_driver: Option< ++ &'static capsules::usb::usb_ctap::CtapUsbSyscallDriver< ++ 'static, ++ 'static, ++ nrf52::usbd::Usbd<'static>, ++ >, ++ > = usb.map(|driver| { ++ let usb_ctap = static_init!( ++ capsules::usb::usbc_ctap_hid::ClientCtapHID< ++ 'static, ++ 'static, ++ nrf52::usbd::Usbd<'static>, ++ >, ++ capsules::usb::usbc_ctap_hid::ClientCtapHID::new(driver) ++ ); ++ driver.set_client(usb_ctap); ++ ++ // Enable power events to be sent to USB controller ++ nrf52::power::POWER.set_usb_client(driver); ++ nrf52::power::POWER.enable_interrupts(); ++ ++ // Configure the USB userspace driver ++ let usb_driver = static_init!( ++ capsules::usb::usb_ctap::CtapUsbSyscallDriver< ++ 'static, ++ 'static, ++ nrf52::usbd::Usbd<'static>, ++ >, ++ capsules::usb::usb_ctap::CtapUsbSyscallDriver::new( ++ usb_ctap, ++ board_kernel.create_grant(&memory_allocation_capability) ++ ) ++ ); ++ usb_ctap.set_client(usb_driver); ++ usb_driver as &'static _ ++ }); ++ + // Start all of the clocks. Low power operation will require a better + // approach than this. + nrf52::clock::CLOCK.low_stop(); +@@ -449,6 +498,7 @@ pub unsafe fn setup_board( + rng: rng, + temp: temp, + alarm: alarm, ++ usb: usb_driver, + nonvolatile_storage: nonvolatile_storage, + ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), + nvmc: nvmc, +diff --git a/capsules/src/driver.rs b/capsules/src/driver.rs +index 9305e6a7..40466f44 100644 +--- a/capsules/src/driver.rs ++++ b/capsules/src/driver.rs +@@ -24,6 +24,7 @@ pub enum NUM { + Spi = 0x20001, + UsbUser = 0x20005, + I2cMasterSlave = 0x20006, ++ UsbCtap = 0x20009, + + // Radio + BleAdvertising = 0x30000, +diff --git a/capsules/src/usb/mod.rs b/capsules/src/usb/mod.rs +index e5c8d6ad..7af3da2e 100644 +--- a/capsules/src/usb/mod.rs ++++ b/capsules/src/usb/mod.rs +@@ -1,4 +1,6 @@ + pub mod descriptors; ++pub mod usb_ctap; + pub mod usb_user; + pub mod usbc_client; + pub mod usbc_client_ctrl; ++pub mod usbc_ctap_hid; +diff --git a/capsules/src/usb/usb_ctap.rs b/capsules/src/usb/usb_ctap.rs +new file mode 100644 +index 00000000..da3d16d8 +--- /dev/null ++++ b/capsules/src/usb/usb_ctap.rs +@@ -0,0 +1,355 @@ ++use super::usbc_ctap_hid::ClientCtapHID; ++use kernel::hil; ++use kernel::hil::usb::Client; ++use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared}; ++ ++/// Syscall number ++use crate::driver; ++pub const DRIVER_NUM: usize = driver::NUM::UsbCtap as usize; ++ ++pub const CTAP_CMD_CHECK: usize = 0; ++pub const CTAP_CMD_CONNECT: usize = 1; ++pub const CTAP_CMD_TRANSMIT: usize = 2; ++pub const CTAP_CMD_RECEIVE: usize = 3; ++pub const CTAP_CMD_TRANSMIT_OR_RECEIVE: usize = 4; ++pub const CTAP_CMD_CANCEL: usize = 5; ++ ++pub const CTAP_ALLOW_TRANSMIT: usize = 1; ++pub const CTAP_ALLOW_RECEIVE: usize = 2; ++pub const CTAP_ALLOW_TRANSMIT_OR_RECEIVE: usize = 3; ++ ++pub const CTAP_SUBSCRIBE_TRANSMIT: usize = 1; ++pub const CTAP_SUBSCRIBE_RECEIVE: usize = 2; ++pub const CTAP_SUBSCRIBE_TRANSMIT_OR_RECEIVE: usize = 3; ++ ++pub const CTAP_CALLBACK_TRANSMITED: usize = 1; ++pub const CTAP_CALLBACK_RECEIVED: usize = 2; ++ ++#[derive(Clone, Copy, PartialEq, Eq)] ++enum Side { ++ Transmit, ++ Receive, ++ TransmitOrReceive, ++} ++ ++impl Side { ++ fn can_transmit(&self) -> bool { ++ match self { ++ Side::Transmit | Side::TransmitOrReceive => true, ++ Side::Receive => false, ++ } ++ } ++ ++ fn can_receive(&self) -> bool { ++ match self { ++ Side::Receive | Side::TransmitOrReceive => true, ++ Side::Transmit => false, ++ } ++ } ++} ++ ++#[derive(Default)] ++pub struct App { ++ // Only one app can be connected to this driver, to avoid needing to route packets among apps. ++ // This field tracks this status. ++ connected: bool, ++ // Currently enabled transaction side. Subscribing to a callback or allowing a buffer ++ // automatically sets the corresponding side. Clearing both the callback and the buffer resets ++ // the side to None. ++ side: Option, ++ callback: Option, ++ buffer: Option>, ++ // Whether the app is waiting for the kernel signaling a packet transfer. ++ waiting: bool, ++} ++ ++impl App { ++ fn check_side(&mut self) { ++ if self.callback.is_none() && self.buffer.is_none() && !self.waiting { ++ self.side = None; ++ } ++ } ++ ++ fn set_side(&mut self, side: Side) -> bool { ++ match self.side { ++ None => { ++ self.side = Some(side); ++ true ++ } ++ Some(app_side) => side == app_side, ++ } ++ } ++ ++ fn is_ready_for_command(&self, side: Side) -> bool { ++ self.buffer.is_some() && self.callback.is_some() && self.side == Some(side) ++ } ++} ++ ++pub trait CtapUsbClient { ++ // Whether this client is ready to receive a packet. This must be checked before calling ++ // packet_received(). ++ fn can_receive_packet(&self) -> bool; ++ ++ // Signal to the client that a packet has been received. ++ fn packet_received(&self, packet: &[u8; 64]); ++ ++ // Signal to the client that a packet has been transmitted. ++ fn packet_transmitted(&self); ++} ++ ++pub struct CtapUsbSyscallDriver<'a, 'b, C: 'a> { ++ usb_client: &'a ClientCtapHID<'a, 'b, C>, ++ apps: Grant, ++} ++ ++impl<'a, 'b, C: hil::usb::UsbController<'a>> CtapUsbSyscallDriver<'a, 'b, C> { ++ pub fn new(usb_client: &'a ClientCtapHID<'a, 'b, C>, apps: Grant) -> Self { ++ CtapUsbSyscallDriver { usb_client, apps } ++ } ++} ++ ++impl<'a, 'b, C: hil::usb::UsbController<'a>> CtapUsbClient for CtapUsbSyscallDriver<'a, 'b, C> { ++ fn can_receive_packet(&self) -> bool { ++ let mut result = false; ++ for app in self.apps.iter() { ++ app.enter(|app, _| { ++ if app.connected { ++ result = app.waiting ++ && app.side.map_or(false, |side| side.can_receive()) ++ && app.buffer.is_some(); ++ } ++ }); ++ } ++ result ++ } ++ ++ fn packet_received(&self, packet: &[u8; 64]) { ++ for app in self.apps.iter() { ++ app.enter(|app, _| { ++ if app.connected && app.waiting && app.side.map_or(false, |side| side.can_receive()) ++ { ++ if let Some(buf) = &mut app.buffer { ++ // Copy the packet to the app's allowed buffer. ++ buf.as_mut().copy_from_slice(packet); ++ app.waiting = false; ++ // Signal to the app that a packet is ready. ++ app.callback ++ .map(|mut cb| cb.schedule(CTAP_CALLBACK_RECEIVED, 0, 0)); ++ } ++ } ++ }); ++ } ++ } ++ ++ fn packet_transmitted(&self) { ++ for app in self.apps.iter() { ++ app.enter(|app, _| { ++ if app.connected ++ && app.waiting ++ && app.side.map_or(false, |side| side.can_transmit()) ++ { ++ app.waiting = false; ++ // Signal to the app that the packet was sent. ++ app.callback ++ .map(|mut cb| cb.schedule(CTAP_CALLBACK_TRANSMITED, 0, 0)); ++ } ++ }); ++ } ++ } ++} ++ ++impl<'a, 'b, C: hil::usb::UsbController<'a>> Driver for CtapUsbSyscallDriver<'a, 'b, C> { ++ fn allow( ++ &self, ++ appid: AppId, ++ allow_num: usize, ++ slice: Option>, ++ ) -> ReturnCode { ++ let side = match allow_num { ++ CTAP_ALLOW_TRANSMIT => Side::Transmit, ++ CTAP_ALLOW_RECEIVE => Side::Receive, ++ CTAP_ALLOW_TRANSMIT_OR_RECEIVE => Side::TransmitOrReceive, ++ _ => return ReturnCode::ENOSUPPORT, ++ }; ++ self.apps ++ .enter(appid, |app, _| { ++ if !app.connected { ++ ReturnCode::ERESERVE ++ } else { ++ if let Some(buf) = &slice { ++ if buf.len() != 64 { ++ return ReturnCode::EINVAL; ++ } ++ } ++ if !app.set_side(side) { ++ return ReturnCode::EALREADY; ++ } ++ app.buffer = slice; ++ app.check_side(); ++ ReturnCode::SUCCESS ++ } ++ }) ++ .unwrap_or_else(|err| err.into()) ++ } ++ ++ fn subscribe( ++ &self, ++ subscribe_num: usize, ++ callback: Option, ++ appid: AppId, ++ ) -> ReturnCode { ++ let side = match subscribe_num { ++ CTAP_SUBSCRIBE_TRANSMIT => Side::Transmit, ++ CTAP_SUBSCRIBE_RECEIVE => Side::Receive, ++ CTAP_SUBSCRIBE_TRANSMIT_OR_RECEIVE => Side::TransmitOrReceive, ++ _ => return ReturnCode::ENOSUPPORT, ++ }; ++ self.apps ++ .enter(appid, |app, _| { ++ if !app.connected { ++ ReturnCode::ERESERVE ++ } else { ++ if !app.set_side(side) { ++ return ReturnCode::EALREADY; ++ } ++ app.callback = callback; ++ app.check_side(); ++ ReturnCode::SUCCESS ++ } ++ }) ++ .unwrap_or_else(|err| err.into()) ++ } ++ ++ fn command(&self, cmd_num: usize, _arg1: usize, _arg2: usize, appid: AppId) -> ReturnCode { ++ match cmd_num { ++ CTAP_CMD_CHECK => ReturnCode::SUCCESS, ++ CTAP_CMD_CONNECT => { ++ // First, check if any app is already connected to this driver. ++ let mut busy = false; ++ for app in self.apps.iter() { ++ app.enter(|app, _| { ++ busy |= app.connected; ++ }); ++ } ++ ++ self.apps ++ .enter(appid, |app, _| { ++ if app.connected { ++ ReturnCode::EALREADY ++ } else if busy { ++ ReturnCode::EBUSY ++ } else { ++ self.usb_client.enable(); ++ self.usb_client.attach(); ++ app.connected = true; ++ ReturnCode::SUCCESS ++ } ++ }) ++ .unwrap_or_else(|err| err.into()) ++ } ++ CTAP_CMD_TRANSMIT => self ++ .apps ++ .enter(appid, |app, _| { ++ if !app.connected { ++ ReturnCode::ERESERVE ++ } else { ++ if app.is_ready_for_command(Side::Transmit) { ++ if app.waiting { ++ ReturnCode::EALREADY ++ } else if self ++ .usb_client ++ .transmit_packet(app.buffer.as_ref().unwrap().as_ref()) ++ { ++ app.waiting = true; ++ ReturnCode::SUCCESS ++ } else { ++ ReturnCode::EBUSY ++ } ++ } else { ++ ReturnCode::EINVAL ++ } ++ } ++ }) ++ .unwrap_or_else(|err| err.into()), ++ CTAP_CMD_RECEIVE => self ++ .apps ++ .enter(appid, |app, _| { ++ if !app.connected { ++ ReturnCode::ERESERVE ++ } else { ++ if app.is_ready_for_command(Side::Receive) { ++ if app.waiting { ++ ReturnCode::EALREADY ++ } else { ++ app.waiting = true; ++ self.usb_client.receive_packet(); ++ ReturnCode::SUCCESS ++ } ++ } else { ++ ReturnCode::EINVAL ++ } ++ } ++ }) ++ .unwrap_or_else(|err| err.into()), ++ CTAP_CMD_TRANSMIT_OR_RECEIVE => self ++ .apps ++ .enter(appid, |app, _| { ++ if !app.connected { ++ ReturnCode::ERESERVE ++ } else { ++ if app.is_ready_for_command(Side::TransmitOrReceive) { ++ if app.waiting { ++ ReturnCode::EALREADY ++ } else { ++ // Indicates to the driver that we can receive any pending packet. ++ app.waiting = true; ++ self.usb_client.receive_packet(); ++ ++ if !app.waiting { ++ // The call to receive_packet() collected a pending packet. ++ ReturnCode::SUCCESS ++ } else { ++ // Indicates to the driver that we have a packet to send. ++ if self ++ .usb_client ++ .transmit_packet(app.buffer.as_ref().unwrap().as_ref()) ++ { ++ ReturnCode::SUCCESS ++ } else { ++ ReturnCode::EBUSY ++ } ++ } ++ } ++ } else { ++ ReturnCode::EINVAL ++ } ++ } ++ }) ++ .unwrap_or_else(|err| err.into()), ++ CTAP_CMD_CANCEL => self ++ .apps ++ .enter(appid, |app, _| { ++ if !app.connected { ++ ReturnCode::ERESERVE ++ } else { ++ if app.waiting { ++ // FIXME: if cancellation failed, the app should still wait. But that ++ // doesn't work yet. ++ app.waiting = false; ++ if self.usb_client.cancel_transaction() { ++ ReturnCode::SUCCESS ++ } else { ++ // Cannot cancel now because the transaction is already in process. ++ // The app should wait for the callback instead. ++ ReturnCode::EBUSY ++ } ++ } else { ++ ReturnCode::EALREADY ++ } ++ } ++ }) ++ .unwrap_or_else(|err| err.into()), ++ _ => ReturnCode::ENOSUPPORT, ++ } ++ } ++} +diff --git a/capsules/src/usb/usbc_ctap_hid.rs b/capsules/src/usb/usbc_ctap_hid.rs +new file mode 100644 +index 00000000..fdf7263a +--- /dev/null ++++ b/capsules/src/usb/usbc_ctap_hid.rs +@@ -0,0 +1,352 @@ ++//! A USB HID client of the USB hardware interface ++ ++use super::descriptors::Buffer64; ++use super::descriptors::ConfigurationDescriptor; ++use super::descriptors::DescriptorType; ++use super::descriptors::DeviceDescriptor; ++use super::descriptors::EndpointAddress; ++use super::descriptors::EndpointDescriptor; ++use super::descriptors::HIDCountryCode; ++use super::descriptors::HIDDescriptor; ++use super::descriptors::HIDSubordinateDescriptor; ++use super::descriptors::InterfaceDescriptor; ++use super::descriptors::ReportDescriptor; ++use super::descriptors::TransferDirection; ++use super::usb_ctap::CtapUsbClient; ++use super::usbc_client_ctrl::ClientCtrl; ++use core::cell::Cell; ++use kernel::common::cells::OptionalCell; ++use kernel::debug; ++use kernel::hil; ++use kernel::hil::usb::TransferType; ++ ++const VENDOR_ID: u16 = 0x1915; // Nordic Semiconductor ++const PRODUCT_ID: u16 = 0x521f; // nRF52840 Dongle (PCA10059) ++ ++static LANGUAGES: &'static [u16; 1] = &[ ++ 0x0409, // English (United States) ++]; ++ ++static STRINGS: &'static [&'static str] = &[ ++ // Manufacturer ++ "Nordic Semiconductor ASA", ++ // Product ++ "OpenSK", ++ // Serial number ++ "v0.1", ++]; ++ ++static ENDPOINTS: &'static [EndpointDescriptor] = &[ ++ EndpointDescriptor { ++ endpoint_address: EndpointAddress::new_const(1, TransferDirection::HostToDevice), ++ transfer_type: TransferType::Interrupt, ++ max_packet_size: 64, ++ interval: 5, ++ }, ++ EndpointDescriptor { ++ endpoint_address: EndpointAddress::new_const(1, TransferDirection::DeviceToHost), ++ transfer_type: TransferType::Interrupt, ++ max_packet_size: 64, ++ interval: 5, ++ }, ++]; ++ ++static CTAP_REPORT_DESCRIPTOR: &'static [u8] = &[ ++ 0x06, 0xD0, 0xF1, // HID_UsagePage ( FIDO_USAGE_PAGE ), ++ 0x09, 0x01, // HID_Usage ( FIDO_USAGE_CTAPHID ), ++ 0xA1, 0x01, // HID_Collection ( HID_Application ), ++ 0x09, 0x20, // HID_Usage ( FIDO_USAGE_DATA_IN ), ++ 0x15, 0x00, // HID_LogicalMin ( 0 ), ++ 0x26, 0xFF, 0x00, // HID_LogicalMaxS ( 0xff ), ++ 0x75, 0x08, // HID_ReportSize ( 8 ), ++ 0x95, 0x40, // HID_ReportCount ( HID_INPUT_REPORT_BYTES ), ++ 0x81, 0x02, // HID_Input ( HID_Data | HID_Absolute | HID_Variable ), ++ 0x09, 0x21, // HID_Usage ( FIDO_USAGE_DATA_OUT ), ++ 0x15, 0x00, // HID_LogicalMin ( 0 ), ++ 0x26, 0xFF, 0x00, // HID_LogicalMaxS ( 0xff ), ++ 0x75, 0x08, // HID_ReportSize ( 8 ), ++ 0x95, 0x40, // HID_ReportCount ( HID_OUTPUT_REPORT_BYTES ), ++ 0x91, 0x02, // HID_Output ( HID_Data | HID_Absolute | HID_Variable ), ++ 0xC0, // HID_EndCollection ++]; ++ ++static CTAP_REPORT: ReportDescriptor<'static> = ReportDescriptor { ++ desc: CTAP_REPORT_DESCRIPTOR, ++}; ++ ++static HID_SUB_DESCRIPTORS: &'static [HIDSubordinateDescriptor] = &[HIDSubordinateDescriptor { ++ typ: DescriptorType::Report, ++ len: CTAP_REPORT_DESCRIPTOR.len() as u16, ++}]; ++ ++static HID: HIDDescriptor<'static> = HIDDescriptor { ++ hid_class: 0x0110, ++ country_code: HIDCountryCode::NotSupported, ++ sub_descriptors: HID_SUB_DESCRIPTORS, ++}; ++ ++pub struct ClientCtapHID<'a, 'b, C: 'a> { ++ client_ctrl: ClientCtrl<'a, 'static, C>, ++ ++ // A 64-byte buffer for the endpoint ++ buffer: Buffer64, ++ ++ // Interaction with the client ++ client: OptionalCell<&'b dyn CtapUsbClient>, ++ tx_packet: OptionalCell<[u8; 64]>, ++ pending_in: Cell, ++ pending_out: Cell, ++ delayed_out: Cell, ++} ++ ++impl<'a, 'b, C: hil::usb::UsbController<'a>> ClientCtapHID<'a, 'b, C> { ++ pub fn new(controller: &'a C) -> Self { ++ ClientCtapHID { ++ client_ctrl: ClientCtrl::new( ++ controller, ++ DeviceDescriptor { ++ // TODO: set this field at the board level. ++ max_packet_size_ep0: 64, ++ vendor_id: VENDOR_ID, ++ product_id: PRODUCT_ID, ++ manufacturer_string: 1, ++ product_string: 2, ++ serial_number_string: 3, ++ ..Default::default() ++ }, ++ ConfigurationDescriptor { ++ // Must be non-zero, otherwise dmesg prints the following error: ++ // [...] usb 2-3: config 0 descriptor?? ++ configuration_value: 1, ++ ..Default::default() ++ }, ++ // Interface declared in the FIDO2 specification, section 8.1.8.1 ++ InterfaceDescriptor { ++ interface_class: 0x03, // HID ++ interface_subclass: 0x00, ++ interface_protocol: 0x00, ++ ..Default::default() ++ }, ++ ENDPOINTS, ++ Some(&HID), ++ Some(&CTAP_REPORT), ++ LANGUAGES, ++ STRINGS, ++ ), ++ buffer: Default::default(), ++ client: OptionalCell::empty(), ++ tx_packet: OptionalCell::empty(), ++ pending_in: Cell::new(false), ++ pending_out: Cell::new(false), ++ delayed_out: Cell::new(false), ++ } ++ } ++ ++ pub fn set_client(&'a self, client: &'b dyn CtapUsbClient) { ++ self.client.set(client); ++ } ++ ++ pub fn transmit_packet(&'a self, packet: &[u8]) -> bool { ++ if self.pending_in.get() { ++ // The previous packet has not yet been transmitted, reject the new one. ++ false ++ } else { ++ self.pending_in.set(true); ++ let mut buf: [u8; 64] = [0; 64]; ++ buf.copy_from_slice(packet); ++ self.tx_packet.set(buf); ++ // Alert the controller that we now have data to send on the Interrupt IN endpoint. ++ self.controller().endpoint_resume_in(1); ++ true ++ } ++ } ++ ++ pub fn receive_packet(&'a self) -> bool { ++ if self.pending_out.get() { ++ // The previous packet has not yet been received, reject the new one. ++ false ++ } else { ++ self.pending_out.set(true); ++ // In case we reported Delay before, send the pending packet back to the client. ++ // Otherwise, there's nothing to do, the controller will send us a packet_out when a ++ // packet arrives. ++ if self.delayed_out.take() { ++ if self.send_packet_to_client() { ++ // If that succeeds, alert the controller that we can now ++ // receive data on the Interrupt OUT endpoint. ++ self.controller().endpoint_resume_out(1); ++ } ++ } ++ true ++ } ++ } ++ ++ // Send an OUT packet available in the controller back to the client. ++ // This returns false if the client is not ready to receive a packet, and true if the client ++ // successfully accepted the packet. ++ fn send_packet_to_client(&'a self) -> bool { ++ // Copy the packet into a buffer to send to the client. ++ let mut buf: [u8; 64] = [0; 64]; ++ for (i, x) in self.buffer.buf.iter().enumerate() { ++ buf[i] = x.get(); ++ } ++ ++ assert!(!self.delayed_out.get()); ++ ++ // Notify the client ++ if self ++ .client ++ .map_or(false, |client| client.can_receive_packet()) ++ { ++ assert!(self.pending_out.take()); ++ ++ // Clear any pending packet on the transmitting side. ++ // It's up to the client to handle the received packet and decide if this packet ++ // should be re-transmitted or not. ++ self.cancel_in_transaction(); ++ ++ self.client.map(|client| client.packet_received(&buf)); ++ true ++ } else { ++ // Cannot receive now, indicate a delay to the controller. ++ self.delayed_out.set(true); ++ false ++ } ++ } ++ ++ pub fn cancel_transaction(&'a self) -> bool { ++ self.cancel_in_transaction() | self.cancel_out_transaction() ++ } ++ ++ fn cancel_in_transaction(&'a self) -> bool { ++ self.tx_packet.take(); ++ let result = self.pending_in.take(); ++ if result { ++ self.controller().endpoint_cancel_in(1); ++ } ++ result ++ } ++ ++ fn cancel_out_transaction(&'a self) -> bool { ++ self.pending_out.take() ++ } ++ ++ #[inline] ++ fn controller(&'a self) -> &'a C { ++ self.client_ctrl.controller() ++ } ++} ++ ++impl<'a, 'b, C: hil::usb::UsbController<'a>> hil::usb::Client<'a> for ClientCtapHID<'a, 'b, C> { ++ fn enable(&'a self) { ++ // Set up the default control endpoint ++ self.client_ctrl.enable(); ++ ++ // Set up the interrupt in-out endpoint ++ self.controller().endpoint_set_buffer(1, &self.buffer.buf); ++ self.controller() ++ .endpoint_in_out_enable(TransferType::Interrupt, 1); ++ } ++ ++ fn attach(&'a self) { ++ self.client_ctrl.attach(); ++ } ++ ++ fn bus_reset(&'a self) { ++ // Should the client initiate reconfiguration here? ++ // For now, the hardware layer does it. ++ ++ debug!("Bus reset"); ++ } ++ ++ /// Handle a Control Setup transaction ++ fn ctrl_setup(&'a self, endpoint: usize) -> hil::usb::CtrlSetupResult { ++ self.client_ctrl.ctrl_setup(endpoint) ++ } ++ ++ /// Handle a Control In transaction ++ fn ctrl_in(&'a self, endpoint: usize) -> hil::usb::CtrlInResult { ++ self.client_ctrl.ctrl_in(endpoint) ++ } ++ ++ /// Handle a Control Out transaction ++ fn ctrl_out(&'a self, endpoint: usize, packet_bytes: u32) -> hil::usb::CtrlOutResult { ++ self.client_ctrl.ctrl_out(endpoint, packet_bytes) ++ } ++ ++ fn ctrl_status(&'a self, endpoint: usize) { ++ self.client_ctrl.ctrl_status(endpoint) ++ } ++ ++ /// Handle the completion of a Control transfer ++ fn ctrl_status_complete(&'a self, endpoint: usize) { ++ self.client_ctrl.ctrl_status_complete(endpoint) ++ } ++ ++ /// Handle a Bulk/Interrupt IN transaction ++ fn packet_in(&'a self, transfer_type: TransferType, endpoint: usize) -> hil::usb::InResult { ++ match transfer_type { ++ TransferType::Bulk => hil::usb::InResult::Error, ++ TransferType::Interrupt => { ++ if endpoint != 1 { ++ return hil::usb::InResult::Error; ++ } ++ ++ if let Some(packet) = self.tx_packet.take() { ++ let buf = &self.buffer.buf; ++ for i in 0..64 { ++ buf[i].set(packet[i]); ++ } ++ ++ hil::usb::InResult::Packet(64) ++ } else { ++ // Nothing to send ++ hil::usb::InResult::Delay ++ } ++ } ++ TransferType::Control | TransferType::Isochronous => unreachable!(), ++ } ++ } ++ ++ /// Handle a Bulk/Interrupt OUT transaction ++ fn packet_out( ++ &'a self, ++ transfer_type: TransferType, ++ endpoint: usize, ++ packet_bytes: u32, ++ ) -> hil::usb::OutResult { ++ match transfer_type { ++ TransferType::Bulk => hil::usb::OutResult::Error, ++ TransferType::Interrupt => { ++ if endpoint != 1 { ++ return hil::usb::OutResult::Error; ++ } ++ ++ if packet_bytes != 64 { ++ // Cannot process this packet ++ hil::usb::OutResult::Error ++ } else { ++ if self.send_packet_to_client() { ++ hil::usb::OutResult::Ok ++ } else { ++ hil::usb::OutResult::Delay ++ } ++ } ++ } ++ TransferType::Control | TransferType::Isochronous => unreachable!(), ++ } ++ } ++ ++ fn packet_transmitted(&'a self, endpoint: usize) { ++ if endpoint != 1 { ++ panic!("Unexpected transmission on ep {}", endpoint); ++ } ++ ++ if self.tx_packet.is_some() { ++ panic!("Unexpected tx_packet while a packet was being transmitted."); ++ } ++ self.pending_in.set(false); ++ // Notify the client ++ self.client.map(|client| client.packet_transmitted()); ++ } ++} +diff --git a/chips/nrf52/src/usbd.rs b/chips/nrf52/src/usbd.rs +index 8ddb5895..8c1992cc 100644 +--- a/chips/nrf52/src/usbd.rs ++++ b/chips/nrf52/src/usbd.rs +@@ -1499,7 +1499,23 @@ impl<'a> Usbd<'a> { + if epdatastatus.is_set(status_epin(endpoint)) { + let (transfer_type, direction, state) = + self.descriptors[endpoint].state.get().bulk_state(); +- assert_eq!(state, BulkState::InData); ++ match state { ++ BulkState::InData => { ++ // Totally expected state. Nothing to do. ++ } ++ BulkState::Init => { ++ internal_warn!( ++ "Received a stale epdata IN in an unexpected state: {:?}", ++ state ++ ); ++ } ++ BulkState::OutDelay ++ | BulkState::OutData ++ | BulkState::OutDma ++ | BulkState::InDma => { ++ internal_err!("Unexpected state: {:?}", state); ++ } ++ } + self.descriptors[endpoint].state.set(EndpointState::Bulk( + transfer_type, + direction, +@@ -1677,7 +1693,7 @@ impl<'a> Usbd<'a> { + } + + fn transmit_in(&self, endpoint: usize) { +- debug_info!("transmit_in({})", endpoint); ++ debug_events!("transmit_in({})", endpoint); + let regs = &*self.registers; + + self.client.map(|client| { +@@ -1717,7 +1733,7 @@ impl<'a> Usbd<'a> { + } + + fn transmit_out(&self, endpoint: usize) { +- debug_info!("transmit_out({})", endpoint); ++ debug_events!("transmit_out({})", endpoint); + + let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state(); + // Starting the DMA can only happen in the OutData state, i.e. after an EPDATA event. +@@ -1882,11 +1898,13 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> { + } + + fn endpoint_resume_in(&self, endpoint: usize) { ++ debug_events!("endpoint_resume_in({})", endpoint); ++ + let (_, direction, _) = self.descriptors[endpoint].state.get().bulk_state(); + assert!(direction.has_in()); + + if self.dma_pending.get() { +- debug_info!("requesting resume_in[{}]", endpoint); ++ debug_events!("requesting resume_in[{}]", endpoint); + // A DMA is already pending. Schedule the resume for later. + self.descriptors[endpoint].request_transmit_in.set(true); + } else { +@@ -1896,6 +1914,8 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> { + } + + fn endpoint_resume_out(&self, endpoint: usize) { ++ debug_events!("endpoint_resume_out({})", endpoint); ++ + let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state(); + assert!(direction.has_out()); + +@@ -1914,7 +1934,7 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> { + // happened in the meantime. This pending transaction will now + // continue in transmit_out(). + if self.dma_pending.get() { +- debug_info!("requesting resume_out[{}]", endpoint); ++ debug_events!("requesting resume_out[{}]", endpoint); + // A DMA is already pending. Schedule the resume for later. + self.descriptors[endpoint].request_transmit_out.set(true); + } else { +@@ -1927,6 +1947,20 @@ impl<'a> hil::usb::UsbController<'a> for Usbd<'a> { + } + } + } ++ ++ fn endpoint_cancel_in(&self, endpoint: usize) { ++ debug_events!("endpoint_cancel_in({})", endpoint); ++ ++ let (transfer_type, direction, state) = self.descriptors[endpoint].state.get().bulk_state(); ++ assert!(direction.has_in()); ++ assert_eq!(state, BulkState::InData); ++ ++ self.descriptors[endpoint].state.set(EndpointState::Bulk( ++ transfer_type, ++ direction, ++ BulkState::Init, ++ )); ++ } + } + + fn status_epin(ep: usize) -> Field { +diff --git a/chips/nrf52840/src/lib.rs b/chips/nrf52840/src/lib.rs +index 0c281276..7e9f7d1e 100644 +--- a/chips/nrf52840/src/lib.rs ++++ b/chips/nrf52840/src/lib.rs +@@ -2,7 +2,7 @@ + + pub use nrf52::{ + adc, aes, ble_radio, clock, constants, crt1, ficr, i2c, ieee802154_radio, init, nvmc, pinmux, +- ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, ++ ppi, pwm, rtc, spi, temperature, timer, trng, uart, uicr, usbd, + }; + pub mod chip; + pub mod gpio; +diff --git a/chips/sam4l/src/usbc/mod.rs b/chips/sam4l/src/usbc/mod.rs +index 35f3bb7c..28a0b9f9 100644 +--- a/chips/sam4l/src/usbc/mod.rs ++++ b/chips/sam4l/src/usbc/mod.rs +@@ -1547,6 +1547,10 @@ impl hil::usb::UsbController<'a> for Usbc<'a> { + requests.resume_out = true; + self.requests[endpoint].set(requests); + } ++ ++ fn endpoint_cancel_in(&self, _endpoint: usize) { ++ unimplemented!() ++ } + } + + /// Static state to manage the USBC +diff --git a/kernel/src/hil/usb.rs b/kernel/src/hil/usb.rs +index 846f5e93..64610fa5 100644 +--- a/kernel/src/hil/usb.rs ++++ b/kernel/src/hil/usb.rs +@@ -27,6 +27,8 @@ pub trait UsbController<'a> { + fn endpoint_resume_in(&self, endpoint: usize); + + fn endpoint_resume_out(&self, endpoint: usize); ++ ++ fn endpoint_cancel_in(&self, endpoint: usize); + } + + #[derive(Clone, Copy, Debug)] diff --git a/patches/tock/03-app-memory.patch b/patches/tock/03-app-memory.patch new file mode 100644 index 0000000..355375c --- /dev/null +++ b/patches/tock/03-app-memory.patch @@ -0,0 +1,13 @@ +diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs +index bd71dfbe..e8247905 100644 +--- a/boards/nordic/nrf52840dk/src/main.rs ++++ b/boards/nordic/nrf52840dk/src/main.rs +@@ -113,7 +113,7 @@ const FAULT_RESPONSE: kernel::procs::FaultResponse = kernel::procs::FaultRespons + const NUM_PROCS: usize = 8; + + #[link_section = ".app_memory"] +-static mut APP_MEMORY: [u8; 245760] = [0; 245760]; ++static mut APP_MEMORY: [u8; 0x3A000] = [0; 0x3A000]; + + static mut PROCESSES: [Option<&'static dyn kernel::procs::ProcessType>; NUM_PROCS] = + [None, None, None, None, None, None, None, None]; diff --git a/patches/tock/04-rtt.patch b/patches/tock/04-rtt.patch new file mode 100644 index 0000000..70bb382 --- /dev/null +++ b/patches/tock/04-rtt.patch @@ -0,0 +1,522 @@ +diff --git a/boards/acd52832/src/main.rs b/boards/acd52832/src/main.rs +index c844ccaf..d60bbc00 100644 +--- a/boards/acd52832/src/main.rs ++++ b/boards/acd52832/src/main.rs +@@ -304,23 +304,26 @@ pub unsafe fn reset_handler() { + ); + + // RTT communication channel ++ let name = b"Terminal\0"; ++ let up_buffer_name = name; ++ let down_buffer_name = name; ++ let up_buffer = static_init!([u8; 1024], [0; 1024]); ++ let down_buffer = static_init!([u8; 32], [0; 32]); ++ + let rtt_memory = static_init!( + capsules::segger_rtt::SeggerRttMemory, +- capsules::segger_rtt::SeggerRttMemory::new( +- b"Terminal\0", +- &mut capsules::segger_rtt::UP_BUFFER, +- b"Terminal\0", +- &mut capsules::segger_rtt::DOWN_BUFFER ++ capsules::segger_rtt::SeggerRttMemory::new_raw( ++ up_buffer_name, ++ up_buffer.as_ptr(), ++ up_buffer.len(), ++ down_buffer_name, ++ down_buffer.as_ptr(), ++ down_buffer.len() + ) + ); + let rtt = static_init!( + capsules::segger_rtt::SeggerRtt>, +- capsules::segger_rtt::SeggerRtt::new( +- virtual_alarm_rtt, +- rtt_memory, +- &mut capsules::segger_rtt::UP_BUFFER, +- &mut capsules::segger_rtt::DOWN_BUFFER +- ) ++ capsules::segger_rtt::SeggerRtt::new(virtual_alarm_rtt, rtt_memory, up_buffer, down_buffer) + ); + hil::time::Alarm::set_client(virtual_alarm_rtt, rtt); + +diff --git a/boards/nordic/nrf52840_dongle/src/main.rs b/boards/nordic/nrf52840_dongle/src/main.rs +index 31d0b392..5a9da538 100644 +--- a/boards/nordic/nrf52840_dongle/src/main.rs ++++ b/boards/nordic/nrf52840_dongle/src/main.rs +@@ -11,7 +11,7 @@ use kernel::component::Component; + #[allow(unused_imports)] + use kernel::{debug, debug_gpio, debug_verbose, static_init}; + use nrf52840::gpio::Pin; +-use nrf52dk_base::{SpiPins, UartPins}; ++use nrf52dk_base::{SpiPins, UartChannel, UartPins}; + + // The nRF52840 Dongle LEDs + const LED1_PIN: Pin = Pin::P0_06; +@@ -130,7 +130,7 @@ pub unsafe fn reset_handler() { + LED2_G_PIN, + LED2_B_PIN, + led, +- &UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD), ++ UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)), + &SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK), + &None, + button, +diff --git a/boards/nordic/nrf52840dk/Cargo.toml b/boards/nordic/nrf52840dk/Cargo.toml +index 171c497f..9d16f679 100644 +--- a/boards/nordic/nrf52840dk/Cargo.toml ++++ b/boards/nordic/nrf52840dk/Cargo.toml +@@ -17,6 +17,10 @@ lto = true + opt-level = "z" + debug = true + ++[features] ++usb_debugging = [] ++default = ["usb_debugging"] ++ + [dependencies] + components = { path = "../../components" } + cortexm4 = { path = "../../../arch/cortex-m4" } +diff --git a/boards/nordic/nrf52840dk/src/io.rs b/boards/nordic/nrf52840dk/src/io.rs +index 4c4f3bf3..608fa9ca 100644 +--- a/boards/nordic/nrf52840dk/src/io.rs ++++ b/boards/nordic/nrf52840dk/src/io.rs +@@ -1,19 +1,46 @@ + use core::fmt::Write; + use core::panic::PanicInfo; + use cortexm4; ++#[cfg(feature = "usb_debugging")] ++use kernel::common::cells::TakeCell; + use kernel::debug; + use kernel::debug::IoWrite; + use kernel::hil::led; ++#[cfg(not(feature = "usb_debugging"))] + use kernel::hil::uart::{self, Configure}; + use nrf52840::gpio::Pin; + + use crate::PROCESSES; + + struct Writer { ++ #[cfg(not(feature = "usb_debugging"))] + initialized: bool, ++ #[cfg(feature = "usb_debugging")] ++ rtt_memory: TakeCell<'static, capsules::segger_rtt::SeggerRttMemory<'static>>, + } + ++#[cfg(not(feature = "usb_debugging"))] + static mut WRITER: Writer = Writer { initialized: false }; ++#[cfg(feature = "usb_debugging")] ++static mut WRITER: Writer = Writer { ++ rtt_memory: TakeCell::empty(), ++}; ++ ++#[cfg(feature = "usb_debugging")] ++fn wait() { ++ let mut x = 0; ++ for i in 0..5000 { ++ unsafe { core::ptr::write_volatile(&mut x as *mut _, i) }; ++ } ++} ++ ++/// Set the RTT memory buffer used to output panic messages. ++#[cfg(feature = "usb_debugging")] ++pub unsafe fn set_rtt_memory( ++ rtt_memory: &'static mut capsules::segger_rtt::SeggerRttMemory<'static>, ++) { ++ WRITER.rtt_memory.replace(rtt_memory); ++} + + impl Write for Writer { + fn write_str(&mut self, s: &str) -> ::core::fmt::Result { +@@ -23,6 +50,7 @@ impl Write for Writer { + } + + impl IoWrite for Writer { ++ #[cfg(not(feature = "usb_debugging"))] + fn write(&mut self, buf: &[u8]) { + let uart = unsafe { &mut nrf52840::uart::UARTE0 }; + if !self.initialized { +@@ -42,6 +70,30 @@ impl IoWrite for Writer { + while !uart.tx_ready() {} + } + } ++ ++ #[cfg(feature = "usb_debugging")] ++ fn write(&mut self, buf: &[u8]) { ++ // TODO: initialize if needed. ++ self.rtt_memory.map(|rtt_memory| { ++ let up_buffer = &mut rtt_memory.up_buffer; ++ let buffer_len = up_buffer.length.get(); ++ let buffer = unsafe { ++ core::slice::from_raw_parts_mut( ++ up_buffer.buffer.get() as *mut u8, ++ buffer_len as usize, ++ ) ++ }; ++ ++ let mut write_position = up_buffer.write_position.get(); ++ ++ for &c in buf { ++ buffer[write_position as usize] = c; ++ write_position = (write_position + 1) % buffer_len; ++ up_buffer.write_position.set(write_position); ++ wait(); ++ } ++ }); ++ } + } + + #[cfg(not(test))] +diff --git a/boards/nordic/nrf52840dk/src/main.rs b/boards/nordic/nrf52840dk/src/main.rs +index 57c42436..0b19ea3f 100644 +--- a/boards/nordic/nrf52840dk/src/main.rs ++++ b/boards/nordic/nrf52840dk/src/main.rs +@@ -68,7 +68,9 @@ use kernel::component::Component; + #[allow(unused_imports)] + use kernel::{debug, debug_gpio, debug_verbose, static_init}; + use nrf52840::gpio::Pin; +-use nrf52dk_base::{SpiMX25R6435FPins, SpiPins, UartPins}; ++#[cfg(not(feature = "usb_debugging"))] ++use nrf52dk_base::UartPins; ++use nrf52dk_base::{SpiMX25R6435FPins, SpiPins, UartChannel}; + + // The nRF52840DK LEDs (see back of board) + const LED1_PIN: Pin = Pin::P0_13; +@@ -83,9 +85,13 @@ const BUTTON3_PIN: Pin = Pin::P0_24; + const BUTTON4_PIN: Pin = Pin::P0_25; + const BUTTON_RST_PIN: Pin = Pin::P0_18; + ++#[cfg(not(feature = "usb_debugging"))] + const UART_RTS: Pin = Pin::P0_05; ++#[cfg(not(feature = "usb_debugging"))] + const UART_TXD: Pin = Pin::P0_06; ++#[cfg(not(feature = "usb_debugging"))] + const UART_CTS: Pin = Pin::P0_07; ++#[cfg(not(feature = "usb_debugging"))] + const UART_RXD: Pin = Pin::P0_08; + + const SPI_MOSI: Pin = Pin::P0_20; +@@ -123,6 +129,37 @@ pub unsafe fn reset_handler() { + // Loads relocations and clears BSS + nrf52840::init(); + ++ // Initialize Segger RTT as early as possible so that any panic beyond this point can use the ++ // RTT memory object. ++ #[cfg(feature = "usb_debugging")] ++ let (up_buffer, down_buffer, rtt_memory) = { ++ let name = b"Terminal\0"; ++ let up_buffer_name = name; ++ let down_buffer_name = name; ++ let up_buffer = static_init!([u8; 1024], [0; 1024]); ++ let down_buffer = static_init!([u8; 32], [0; 32]); ++ ++ let rtt_memory = static_init!( ++ capsules::segger_rtt::SeggerRttMemory, ++ capsules::segger_rtt::SeggerRttMemory::new_raw( ++ up_buffer_name, ++ up_buffer.as_ptr(), ++ up_buffer.len(), ++ down_buffer_name, ++ down_buffer.as_ptr(), ++ down_buffer.len() ++ ) ++ ); ++ ++ (up_buffer, down_buffer, rtt_memory) ++ }; ++ ++ // XXX: This is inherently unsafe as it aliases the mutable reference to rtt_memory. This ++ // aliases reference is only used inside a panic handler, which should be OK, but maybe we ++ // should use a const reference to rtt_memory and leverage interior mutability instead. ++ #[cfg(feature = "usb_debugging")] ++ self::io::set_rtt_memory(&mut *(rtt_memory as *mut _)); ++ + let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&PROCESSES)); + let gpio = components::gpio::GpioComponent::new(board_kernel).finalize( + components::gpio_component_helper!( +@@ -198,7 +235,10 @@ pub unsafe fn reset_handler() { + LED2_PIN, + LED3_PIN, + led, +- &UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD), ++ #[cfg(feature = "usb_debugging")] ++ UartChannel::Rtt(up_buffer, down_buffer, rtt_memory), ++ #[cfg(not(feature = "usb_debugging"))] ++ UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)), + &SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK), + &Some(SpiMX25R6435FPins::new( + SPI_MX25R6435F_CHIP_SELECT, +diff --git a/boards/nordic/nrf52dk/src/main.rs b/boards/nordic/nrf52dk/src/main.rs +index 693f1e18..b49518ff 100644 +--- a/boards/nordic/nrf52dk/src/main.rs ++++ b/boards/nordic/nrf52dk/src/main.rs +@@ -68,7 +68,7 @@ use kernel::component::Component; + #[allow(unused_imports)] + use kernel::{debug, debug_gpio, debug_verbose, static_init}; + use nrf52832::gpio::Pin; +-use nrf52dk_base::{SpiPins, UartPins}; ++use nrf52dk_base::{SpiPins, UartChannel, UartPins}; + + // The nRF52 DK LEDs (see back of board) + const LED1_PIN: Pin = Pin::P0_17; +@@ -199,7 +199,7 @@ pub unsafe fn reset_handler() { + LED2_PIN, + LED3_PIN, + led, +- &UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD), ++ UartChannel::Pins(UartPins::new(UART_RTS, UART_TXD, UART_CTS, UART_RXD)), + &SpiPins::new(SPI_MOSI, SPI_MISO, SPI_CLK), + &None, + button, +diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs +index 17be93a4..ddac9dbd 100644 +--- a/boards/nordic/nrf52dk_base/src/lib.rs ++++ b/boards/nordic/nrf52dk_base/src/lib.rs +@@ -70,6 +70,15 @@ impl UartPins { + } + } + ++pub enum UartChannel<'a> { ++ Pins(UartPins), ++ Rtt( ++ &'a mut [u8], ++ &'a mut [u8], ++ &'a mut capsules::segger_rtt::SeggerRttMemory<'a>, ++ ), ++} ++ + /// Supported drivers by the platform + pub struct Platform { + ble_radio: &'static capsules::ble_advertising_driver::BLE< +@@ -136,7 +145,7 @@ pub unsafe fn setup_board( + debug_pin2_index: Pin, + debug_pin3_index: Pin, + led: &'static capsules::led::LED<'static>, +- uart_pins: &UartPins, ++ uart_channel: UartChannel<'static>, + spi_pins: &SpiPins, + mx25r6435f: &Option, + button: &'static capsules::button::Button<'static>, +@@ -232,6 +241,38 @@ pub unsafe fn setup_board( + let alarm = components::alarm::AlarmDriverComponent::new(board_kernel, mux_alarm) + .finalize(components::alarm_component_helper!(nrf52::rtc::Rtc)); + ++ let channel: &dyn kernel::hil::uart::Uart = match uart_channel { ++ UartChannel::Pins(uart_pins) => { ++ nrf52::uart::UARTE0.initialize( ++ nrf52::pinmux::Pinmux::new(uart_pins.txd as u32), ++ nrf52::pinmux::Pinmux::new(uart_pins.rxd as u32), ++ Some(nrf52::pinmux::Pinmux::new(uart_pins.cts as u32)), ++ Some(nrf52::pinmux::Pinmux::new(uart_pins.rts as u32)), ++ ); ++ &nrf52::uart::UARTE0 ++ } ++ UartChannel::Rtt(up_buffer, down_buffer, rtt_memory) => { ++ // Virtual alarm for the Segger RTT communication channel ++ let virtual_alarm_rtt = static_init!( ++ capsules::virtual_alarm::VirtualMuxAlarm<'static, nrf52::rtc::Rtc>, ++ capsules::virtual_alarm::VirtualMuxAlarm::new(mux_alarm) ++ ); ++ ++ // RTT communication channel ++ let rtt = static_init!( ++ capsules::segger_rtt::SeggerRtt>, ++ capsules::segger_rtt::SeggerRtt::new( ++ virtual_alarm_rtt, ++ rtt_memory, ++ up_buffer, ++ down_buffer ++ ) ++ ); ++ hil::time::Alarm::set_client(virtual_alarm_rtt, rtt); ++ rtt ++ } ++ }; ++ + let dynamic_deferred_call_clients = + static_init!([DynamicDeferredCallClientState; 2], Default::default()); + let dynamic_deferred_caller = static_init!( +@@ -241,19 +282,10 @@ pub unsafe fn setup_board( + DynamicDeferredCall::set_global_instance(dynamic_deferred_caller); + + // Create a shared UART channel for the console and for kernel debug. +- let uart_mux = components::console::UartMuxComponent::new( +- &nrf52::uart::UARTE0, +- 115200, +- dynamic_deferred_caller, +- ) +- .finalize(()); +- +- nrf52::uart::UARTE0.initialize( +- nrf52::pinmux::Pinmux::new(uart_pins.txd as u32), +- nrf52::pinmux::Pinmux::new(uart_pins.rxd as u32), +- Some(nrf52::pinmux::Pinmux::new(uart_pins.cts as u32)), +- Some(nrf52::pinmux::Pinmux::new(uart_pins.rts as u32)), +- ); ++ let uart_mux = ++ components::console::UartMuxComponent::new(channel, 115200, dynamic_deferred_caller) ++ .finalize(()); ++ + let pconsole = + components::process_console::ProcessConsoleComponent::new(board_kernel, uart_mux) + .finalize(()); +diff --git a/capsules/src/segger_rtt.rs b/capsules/src/segger_rtt.rs +index 1bf93fc1..33103c57 100644 +--- a/capsules/src/segger_rtt.rs ++++ b/capsules/src/segger_rtt.rs +@@ -91,67 +91,69 @@ + //! ``` + + use core::cell::Cell; +-use kernel::common::cells::{OptionalCell, TakeCell}; ++use core::marker::PhantomData; ++use kernel::common::cells::{OptionalCell, TakeCell, VolatileCell}; + use kernel::hil; + use kernel::hil::time::Frequency; + use kernel::hil::uart; + use kernel::ReturnCode; + +-/// Buffer for transmitting to the host. +-pub static mut UP_BUFFER: [u8; 1024] = [0; 1024]; +- +-/// Buffer for receiving messages from the host. +-pub static mut DOWN_BUFFER: [u8; 32] = [0; 32]; +- + /// This structure is defined by the segger RTT protocol. It must exist in + /// memory in exactly this form so that the segger JTAG tool can find it in the + /// chip's memory and read and write messages to the appropriate buffers. + #[repr(C)] +-pub struct SeggerRttMemory { +- id: [u8; 16], +- number_up_buffers: u32, +- number_down_buffers: u32, +- up_buffer: SeggerRttBuffer, +- down_buffer: SeggerRttBuffer, ++pub struct SeggerRttMemory<'a> { ++ id: VolatileCell<[u8; 16]>, ++ number_up_buffers: VolatileCell, ++ number_down_buffers: VolatileCell, ++ pub up_buffer: SeggerRttBuffer<'a>, ++ down_buffer: SeggerRttBuffer<'a>, + } + + #[repr(C)] +-pub struct SeggerRttBuffer { +- name: *const u8, // Pointer to the name of this channel. Must be a 4 byte thin pointer. +- buffer: *const u8, // Pointer to the buffer for this channel. +- length: u32, +- write_position: u32, +- read_position: u32, +- flags: u32, ++pub struct SeggerRttBuffer<'a> { ++ name: VolatileCell<*const u8>, // Pointer to the name of this channel. Must be a 4 byte thin pointer. ++ pub buffer: VolatileCell<*const u8>, // Pointer to the buffer for this channel. ++ pub length: VolatileCell, ++ pub write_position: VolatileCell, ++ read_position: VolatileCell, ++ flags: VolatileCell, ++ _lifetime: PhantomData<&'a [u8]>, + } + +-impl SeggerRttMemory { +- pub fn new( ++impl SeggerRttMemory<'a> { ++ pub fn new_raw( + up_buffer_name: &'a [u8], +- up_buffer: &'static mut [u8], +- down_buffer_name: &'static [u8], +- down_buffer: &'static mut [u8], +- ) -> SeggerRttMemory { ++ up_buffer_ptr: *const u8, ++ up_buffer_len: usize, ++ down_buffer_name: &'a [u8], ++ down_buffer_ptr: *const u8, ++ down_buffer_len: usize, ++ ) -> SeggerRttMemory<'a> { + SeggerRttMemory { ++ // TODO: only write this ID when the object is fully initialized, to avoid having ++ // these bytes elsewhere in (flash) memory. + // Must be "SEGGER RTT". +- id: *b"SEGGER RTT\0\0\0\0\0\0", +- number_up_buffers: 1, +- number_down_buffers: 1, ++ id: VolatileCell::new(*b"SEGGER RTT\0\0\0\0\0\0"), ++ number_up_buffers: VolatileCell::new(1), ++ number_down_buffers: VolatileCell::new(1), + up_buffer: SeggerRttBuffer { +- name: up_buffer_name.as_ptr(), +- buffer: up_buffer.as_ptr(), +- length: 1024, +- write_position: 0, +- read_position: 0, +- flags: 0, ++ name: VolatileCell::new(up_buffer_name.as_ptr()), ++ buffer: VolatileCell::new(up_buffer_ptr), ++ length: VolatileCell::new(up_buffer_len as u32), ++ write_position: VolatileCell::new(0), ++ read_position: VolatileCell::new(0), ++ flags: VolatileCell::new(0), ++ _lifetime: PhantomData, + }, + down_buffer: SeggerRttBuffer { +- name: down_buffer_name.as_ptr(), +- buffer: down_buffer.as_ptr(), +- length: 32, +- write_position: 0, +- read_position: 0, +- flags: 0, ++ name: VolatileCell::new(down_buffer_name.as_ptr()), ++ buffer: VolatileCell::new(down_buffer_ptr), ++ length: VolatileCell::new(down_buffer_len as u32), ++ write_position: VolatileCell::new(0), ++ read_position: VolatileCell::new(0), ++ flags: VolatileCell::new(0), ++ _lifetime: PhantomData, + }, + } + } +@@ -159,9 +161,9 @@ impl SeggerRttMemory { + + pub struct SeggerRtt<'a, A: hil::time::Alarm<'a>> { + alarm: &'a A, // Dummy alarm so we can get a callback. +- config: TakeCell<'a, SeggerRttMemory>, +- up_buffer: TakeCell<'static, [u8]>, +- _down_buffer: TakeCell<'static, [u8]>, ++ config: TakeCell<'a, SeggerRttMemory<'a>>, ++ up_buffer: TakeCell<'a, [u8]>, ++ _down_buffer: TakeCell<'a, [u8]>, + client: OptionalCell<&'a dyn uart::TransmitClient>, + client_buffer: TakeCell<'static, [u8]>, + tx_len: Cell, +@@ -170,9 +172,9 @@ pub struct SeggerRtt<'a, A: hil::time::Alarm<'a>> { + impl<'a, A: hil::time::Alarm<'a>> SeggerRtt<'a, A> { + pub fn new( + alarm: &'a A, +- config: &'a mut SeggerRttMemory, +- up_buffer: &'static mut [u8], +- down_buffer: &'static mut [u8], ++ config: &'a mut SeggerRttMemory<'a>, ++ up_buffer: &'a mut [u8], ++ down_buffer: &'a mut [u8], + ) -> SeggerRtt<'a, A> { + SeggerRtt { + alarm: alarm, +@@ -205,15 +207,15 @@ impl<'a, A: hil::time::Alarm<'a>> uart::Transmit<'a> for SeggerRtt<'a, A> { + // Copy the incoming data into the buffer. Once we increment + // the `write_position` the RTT listener will go ahead and read + // the message from us. +- let mut index = config.up_buffer.write_position as usize; +- let buffer_len = config.up_buffer.length as usize; ++ let mut index = config.up_buffer.write_position.get() as usize; ++ let buffer_len = config.up_buffer.length.get() as usize; + + for i in 0..tx_len { + buffer[(i + index) % buffer_len] = tx_data[i]; + } + + index = (index + tx_len) % buffer_len; +- config.up_buffer.write_position = index as u32; ++ config.up_buffer.write_position.set(index as u32); + self.tx_len.set(tx_len); + // Save the client buffer so we can pass it back with the callback. + self.client_buffer.replace(tx_data); diff --git a/reset.sh b/reset.sh new file mode 100755 index 0000000..8067c4a --- /dev/null +++ b/reset.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Copyright 2019 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. + +echo "$(tput bold)This script will restore the repository to a clean state$(tput sgr0)" +echo "$(tput bold)Any pending change will be lost.$(tput sgr0)" +echo "" + +accept='' +while + case "$accept" in + [Yy]) + # Start echoeing the commands to the screen + set -x + # Reset the submodules + git submodule foreach 'git reset --hard && git clean -fxd' + # Reset also the main repository + git reset --hard && git clean -fxd + + set +x + echo "DONE." + # And break the loop + false + ;; + + [Nn]) + echo "Nothing was done. Repository was left untouched." + # Don't do anything but break the while loop to exit + false + ;; + + *) + # Continue looping + true + ;; + esac +do + echo "$(tput bold)Are you sure you want to continue? [y/n]$(tput sgr0)" + read -s -n 1 accept +done diff --git a/rules.d/55-opensk.rules b/rules.d/55-opensk.rules new file mode 100644 index 0000000..b1c8c60 --- /dev/null +++ b/rules.d/55-opensk.rules @@ -0,0 +1 @@ +SUBSYSTEM=="hidraw", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1915", ATTRS{idProduct}=="521f", ATTRS{product}=="OpenSK", MODE="0660", GROUP="logindev", TAG+="uaccess" diff --git a/run_desktop_tests.sh b/run_desktop_tests.sh new file mode 100755 index 0000000..11786e7 --- /dev/null +++ b/run_desktop_tests.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Copyright 2019 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. + +set -eu + +# Ensure we have the key_material.rs file before running the tests +if [ ! -f src/ctap/key_material.rs ] +then + echo "$(tput bold)ERROR:$(tput sgr0) Cannot find src/ctap/key_material.rs file." + echo "Please make sure that you have run the following script: ./setup.sh" + exit 2 +fi + +set -x + +echo "Checking formatting..." +cargo fmt --all -- --check +cd libraries/cbor +cargo fmt --all -- --check +cd ../.. +cd libraries/crypto +cargo fmt --all -- --check +cd ../.. + +echo "Checking that CTAP2 builds properly..." +cargo check --release --target=thumbv7em-none-eabi +cargo check --release --target=thumbv7em-none-eabi --features with_ctap1 +cargo check --release --target=thumbv7em-none-eabi --features debug_ctap +cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ctap1 + +echo "Checking that examples build properly..." +cargo check --release --target=thumbv7em-none-eabi --examples + +echo "Checking that CTAP2 builds and links properly (1 set of features)..." +cargo build --release --target=thumbv7em-none-eabi --features with_ctap1 + +echo "Running unit tests on the desktop (release mode)..." +cd libraries/cbor +cargo test --release --features std +cd ../.. +cd libraries/crypto +RUSTFLAGS='-C target-feature=+aes' cargo test --release --features std,derive_debug +cd ../.. +cargo test --release --features std + +echo "Running unit tests on the desktop (debug mode)..." +cd libraries/cbor +cargo test --features std +cd ../.. +cd libraries/crypto +RUSTFLAGS='-C target-feature=+aes' cargo test --features std,derive_debug +cd ../.. +cargo test --features std + +echo "Running unit tests on the desktop (release mode + CTAP1)..." +cargo test --release --features std,with_ctap1 + +echo "Running unit tests on the desktop (debug mode + CTAP1)..." +cargo test --features std,with_ctap1 + diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 0000000..20d9cda --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +nightly-2020-01-16 diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..d3da3dd --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +use_field_init_shorthand = true +use_try_shorthand = true +edition = "2018" \ No newline at end of file diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..2b45be3 --- /dev/null +++ b/setup.sh @@ -0,0 +1,49 @@ +# Copyright 2019 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. + +# Ensure the submodules are pulled and up-to-date +git submodule update --init + +done_text="$(tput bold)DONE.$(tput sgr0)" + +# Apply patches to kernel. Do that in a sub-shell +( + cd third_party/tock/ && \ + for p in ../../patches/tock/[0-9][0-9]-*.patch + do + echo -n '[-] Applying patch "'$(basename $p)'"... ' + git apply "$p" && echo $done_text + done +) + +# Now apply patches to libtock-rs. Do that in a sub-shell +( + cd third_party/libtock-rs/ && \ + for p in ../../patches/libtock-rs/[0-9][0-9]-*.patch + do + echo -n '[-] Applying patch "'$(basename $p)'"... ' + git apply "$p" && echo $done_text + done +) + +# Ensure we have certificates, keys, etc. so that the tests can run +source tools/gen_key_materials.sh +generate_crypto_materials N + +rustup install $(head -n 1 rust-toolchain) +pip3 install --user --upgrade tockloader +rustup target add thumbv7em-none-eabi + +# Install dependency to create applications. +cargo install elf2tab diff --git a/src/ctap/command.rs b/src/ctap/command.rs new file mode 100644 index 0000000..129c671 --- /dev/null +++ b/src/ctap/command.rs @@ -0,0 +1,483 @@ +// Copyright 2019 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. + +use super::data_formats::{ + ok_or_missing, read_array, read_byte_string, read_integer, read_map, read_text_string, + read_unsigned, ClientPinSubCommand, CoseKey, Extensions, GetAssertionOptions, + MakeCredentialOptions, PublicKeyCredentialDescriptor, PublicKeyCredentialRpEntity, + PublicKeyCredentialType, PublicKeyCredentialUserEntity, +}; +use super::status_code::Ctap2StatusCode; +use alloc::string::String; +use alloc::vec::Vec; +use core::convert::TryFrom; + +// CTAP specification (version 20190130) section 6.1 +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub enum Command { + AuthenticatorMakeCredential(AuthenticatorMakeCredentialParameters), + AuthenticatorGetAssertion(AuthenticatorGetAssertionParameters), + AuthenticatorGetInfo, + AuthenticatorClientPin(AuthenticatorClientPinParameters), + AuthenticatorReset, + AuthenticatorGetNextAssertion, + // TODO(kaczmarczyck) implement FIDO 2.1 commands (see below consts) +} + +impl From for Ctap2StatusCode { + fn from(_: cbor::reader::DecoderError) -> Self { + Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR + } +} + +// TODO: Remove this `allow(dead_code)` once the constants are used. +#[allow(dead_code)] +impl Command { + const AUTHENTICATOR_MAKE_CREDENTIAL: u8 = 0x01; + const AUTHENTICATOR_GET_ASSERTION: u8 = 0x02; + const AUTHENTICATOR_GET_INFO: u8 = 0x04; + const AUTHENTICATOR_CLIENT_PIN: u8 = 0x06; + const AUTHENTICATOR_RESET: u8 = 0x07; + // TODO(kaczmarczyck) use or remove those constants + const AUTHENTICATOR_GET_NEXT_ASSERTION: u8 = 0x08; + const AUTHENTICATOR_BIO_ENROLLMENT: u8 = 0x09; + const AUTHENTICATOR_CREDENTIAL_MANAGEMENT: u8 = 0xA0; + const AUTHENTICATOR_SELECTION: u8 = 0xB0; + const AUTHENTICATOR_CONFIG: u8 = 0xC0; + const AUTHENTICATOR_VENDOR_FIRST: u8 = 0x40; + const AUTHENTICATOR_VENDOR_LAST: u8 = 0xBF; + + pub fn deserialize(bytes: &[u8]) -> Result { + if bytes.is_empty() { + // The error to return is not specified, missing parameter seems to fit best. + return Err(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER); + } + + let command_value = bytes[0]; + match command_value { + Command::AUTHENTICATOR_MAKE_CREDENTIAL => { + let decoded_cbor = cbor::read(&bytes[1..])?; + Ok(Command::AuthenticatorMakeCredential( + AuthenticatorMakeCredentialParameters::try_from(decoded_cbor)?, + )) + } + Command::AUTHENTICATOR_GET_ASSERTION => { + let decoded_cbor = cbor::read(&bytes[1..])?; + Ok(Command::AuthenticatorGetAssertion( + AuthenticatorGetAssertionParameters::try_from(decoded_cbor)?, + )) + } + Command::AUTHENTICATOR_GET_INFO => { + // Parameters are ignored. + Ok(Command::AuthenticatorGetInfo) + } + Command::AUTHENTICATOR_CLIENT_PIN => { + let decoded_cbor = cbor::read(&bytes[1..])?; + Ok(Command::AuthenticatorClientPin( + AuthenticatorClientPinParameters::try_from(decoded_cbor)?, + )) + } + Command::AUTHENTICATOR_RESET => { + // Parameters are ignored. + Ok(Command::AuthenticatorReset) + } + Command::AUTHENTICATOR_GET_NEXT_ASSERTION => { + // Parameters are ignored. + Ok(Command::AuthenticatorGetNextAssertion) + } + _ => Err(Ctap2StatusCode::CTAP1_ERR_INVALID_COMMAND), + } + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct AuthenticatorMakeCredentialParameters { + pub client_data_hash: Vec, + pub rp: PublicKeyCredentialRpEntity, + pub user: PublicKeyCredentialUserEntity, + pub pub_key_cred_params: Vec<(PublicKeyCredentialType, i64)>, + pub exclude_list: Option>, + pub extensions: Option, + // Even though options are optional, we can use the default if not present. + pub options: MakeCredentialOptions, + pub pin_uv_auth_param: Option>, + pub pin_uv_auth_protocol: Option, +} + +impl TryFrom for AuthenticatorMakeCredentialParameters { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: cbor::Value) -> Result { + let param_map = read_map(&cbor_value)?; + + let client_data_hash = read_byte_string(ok_or_missing(param_map.get(&cbor_unsigned!(1)))?)?; + + let rp = PublicKeyCredentialRpEntity::try_from(ok_or_missing( + param_map.get(&cbor_unsigned!(2)), + )?)?; + + let user = PublicKeyCredentialUserEntity::try_from(ok_or_missing( + param_map.get(&cbor_unsigned!(3)), + )?)?; + + let cred_param_vec = read_array(ok_or_missing(param_map.get(&cbor_unsigned!(4)))?)?; + let mut pub_key_cred_params = vec![]; + for cred_param_map_value in cred_param_vec { + let cred_param_map = read_map(cred_param_map_value)?; + let cred_type = PublicKeyCredentialType::try_from(ok_or_missing( + cred_param_map.get(&cbor_text!("type")), + )?)?; + let alg = read_integer(ok_or_missing(cred_param_map.get(&cbor_text!("alg")))?)?; + pub_key_cred_params.push((cred_type, alg)); + } + + let exclude_list = match param_map.get(&cbor_unsigned!(5)) { + Some(entry) => { + let exclude_list_vec = read_array(entry)?; + let mut exclude_list = vec![]; + for exclude_list_value in exclude_list_vec { + exclude_list.push(PublicKeyCredentialDescriptor::try_from(exclude_list_value)?); + } + Some(exclude_list) + } + None => None, + }; + + let extensions = param_map + .get(&cbor_unsigned!(6)) + .map(Extensions::try_from) + .transpose()?; + + let options = match param_map.get(&cbor_unsigned!(7)) { + Some(entry) => MakeCredentialOptions::try_from(entry)?, + None => MakeCredentialOptions { + rk: false, + uv: false, + }, + }; + + let pin_uv_auth_param = param_map + .get(&cbor_unsigned!(8)) + .map(read_byte_string) + .transpose()?; + + let pin_uv_auth_protocol = param_map + .get(&cbor_unsigned!(9)) + .map(read_unsigned) + .transpose()?; + + Ok(AuthenticatorMakeCredentialParameters { + client_data_hash, + rp, + user, + pub_key_cred_params, + exclude_list, + extensions, + options, + pin_uv_auth_param, + pin_uv_auth_protocol, + }) + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct AuthenticatorGetAssertionParameters { + pub rp_id: String, + pub client_data_hash: Vec, + pub allow_list: Option>, + pub extensions: Option, + // Even though options are optional, we can use the default if not present. + pub options: GetAssertionOptions, + pub pin_uv_auth_param: Option>, + pub pin_uv_auth_protocol: Option, +} + +impl TryFrom for AuthenticatorGetAssertionParameters { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: cbor::Value) -> Result { + let param_map = read_map(&cbor_value)?; + + let rp_id = read_text_string(ok_or_missing(param_map.get(&cbor_unsigned!(1)))?)?; + + let client_data_hash = read_byte_string(ok_or_missing(param_map.get(&cbor_unsigned!(2)))?)?; + + let allow_list = match param_map.get(&cbor_unsigned!(3)) { + Some(entry) => { + let allow_list_vec = read_array(entry)?; + let mut allow_list = vec![]; + for allow_list_value in allow_list_vec { + allow_list.push(PublicKeyCredentialDescriptor::try_from(allow_list_value)?); + } + Some(allow_list) + } + None => None, + }; + + let extensions = param_map + .get(&cbor_unsigned!(4)) + .map(Extensions::try_from) + .transpose()?; + + let options = match param_map.get(&cbor_unsigned!(5)) { + Some(entry) => GetAssertionOptions::try_from(entry)?, + None => GetAssertionOptions { + up: true, + uv: false, + }, + }; + + let pin_uv_auth_param = param_map + .get(&cbor_unsigned!(6)) + .map(read_byte_string) + .transpose()?; + + let pin_uv_auth_protocol = param_map + .get(&cbor_unsigned!(7)) + .map(read_unsigned) + .transpose()?; + + Ok(AuthenticatorGetAssertionParameters { + rp_id, + client_data_hash, + allow_list, + extensions, + options, + pin_uv_auth_param, + pin_uv_auth_protocol, + }) + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct AuthenticatorClientPinParameters { + pub pin_protocol: u64, + pub sub_command: ClientPinSubCommand, + pub key_agreement: Option, + pub pin_auth: Option>, + pub new_pin_enc: Option>, + pub pin_hash_enc: Option>, +} + +impl TryFrom for AuthenticatorClientPinParameters { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: cbor::Value) -> Result { + let param_map = read_map(&cbor_value)?; + + let pin_protocol = read_unsigned(ok_or_missing(param_map.get(&cbor_unsigned!(1)))?)?; + + let sub_command = + ClientPinSubCommand::try_from(ok_or_missing(param_map.get(&cbor_unsigned!(2)))?)?; + + let key_agreement = param_map + .get(&cbor_unsigned!(3)) + .map(read_map) + .transpose()? + .map(|x| CoseKey(x.clone())); + + let pin_auth = param_map + .get(&cbor_unsigned!(4)) + .map(read_byte_string) + .transpose()?; + + let new_pin_enc = param_map + .get(&cbor_unsigned!(5)) + .map(read_byte_string) + .transpose()?; + + let pin_hash_enc = param_map + .get(&cbor_unsigned!(6)) + .map(read_byte_string) + .transpose()?; + + Ok(AuthenticatorClientPinParameters { + pin_protocol, + sub_command, + key_agreement, + pin_auth, + new_pin_enc, + pin_hash_enc, + }) + } +} + +#[cfg(test)] +mod test { + use super::super::data_formats::{ + AuthenticatorTransport, PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, + }; + use super::*; + use alloc::collections::BTreeMap; + + #[test] + fn test_from_cbor_make_credential_parameters() { + let cbor_value = cbor_map! { + 1 => vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F], + 2 => cbor_map! { + "id" => "example.com", + "name" => "Example", + "icon" => "example.com/icon.png", + }, + 3 => cbor_map! { + "id" => vec![0x1D, 0x1D, 0x1D, 0x1D], + "name" => "foo", + "displayName" => "bar", + "icon" => "example.com/foo/icon.png", + }, + 4 => cbor_array![ cbor_map! { + "type" => "public-key", + "alg" => -7 + } ], + 5 => cbor_array![], + 8 => vec![0x12, 0x34], + 9 => 1, + }; + let returned_make_credential_parameters = + AuthenticatorMakeCredentialParameters::try_from(cbor_value).unwrap(); + + let client_data_hash = vec![ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + ]; + let rp = PublicKeyCredentialRpEntity { + rp_id: "example.com".to_string(), + rp_name: Some("Example".to_string()), + rp_icon: Some("example.com/icon.png".to_string()), + }; + let user = PublicKeyCredentialUserEntity { + user_id: vec![0x1D, 0x1D, 0x1D, 0x1D], + user_name: Some("foo".to_string()), + user_display_name: Some("bar".to_string()), + user_icon: Some("example.com/foo/icon.png".to_string()), + }; + let pub_key_cred_param = (PublicKeyCredentialType::PublicKey, -7); + let options = MakeCredentialOptions { + rk: false, + uv: false, + }; + let expected_make_credential_parameters = AuthenticatorMakeCredentialParameters { + client_data_hash, + rp, + user, + pub_key_cred_params: vec![pub_key_cred_param], + exclude_list: Some(vec![]), + extensions: None, + options, + pin_uv_auth_param: Some(vec![0x12, 0x34]), + pin_uv_auth_protocol: Some(1), + }; + + assert_eq!( + returned_make_credential_parameters, + expected_make_credential_parameters + ); + } + + #[test] + fn test_from_cbor_get_assertion_parameters() { + let cbor_value = cbor_map! { + 1 => "example.com", + 2 => vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F], + 3 => cbor_array![ cbor_map! { + "type" => "public-key", + "id" => vec![0x2D, 0x2D, 0x2D, 0x2D], + "transports" => cbor_array!["usb"], + } ], + 6 => vec![0x12, 0x34], + 7 => 1, + }; + let returned_get_assertion_parameters = + AuthenticatorGetAssertionParameters::try_from(cbor_value).unwrap(); + + let rp_id = "example.com".to_string(); + let client_data_hash = vec![ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x0E, 0x0F, + ]; + let pub_key_cred_descriptor = PublicKeyCredentialDescriptor { + key_type: PublicKeyCredentialType::PublicKey, + key_id: vec![0x2D, 0x2D, 0x2D, 0x2D], + transports: Some(vec![AuthenticatorTransport::Usb]), + }; + let options = GetAssertionOptions { + up: true, + uv: false, + }; + let expected_get_assertion_parameters = AuthenticatorGetAssertionParameters { + rp_id, + client_data_hash, + allow_list: Some(vec![pub_key_cred_descriptor]), + extensions: None, + options, + pin_uv_auth_param: Some(vec![0x12, 0x34]), + pin_uv_auth_protocol: Some(1), + }; + + assert_eq!( + returned_get_assertion_parameters, + expected_get_assertion_parameters + ); + } + + #[test] + fn test_from_cbor_client_pin_parameters() { + let cbor_value = cbor_map! { + 1 => 1, + 2 => ClientPinSubCommand::GetPinRetries, + 3 => cbor_map!{}, + 4 => vec! [0xBB], + 5 => vec! [0xCC], + 6 => vec! [0xDD], + }; + let returned_pin_protocol_parameters = + AuthenticatorClientPinParameters::try_from(cbor_value).unwrap(); + + let expected_pin_protocol_parameters = AuthenticatorClientPinParameters { + pin_protocol: 1, + sub_command: ClientPinSubCommand::GetPinRetries, + key_agreement: Some(CoseKey(BTreeMap::new())), + pin_auth: Some(vec![0xBB]), + new_pin_enc: Some(vec![0xCC]), + pin_hash_enc: Some(vec![0xDD]), + }; + + assert_eq!( + returned_pin_protocol_parameters, + expected_pin_protocol_parameters + ); + } + + #[test] + fn test_deserialize_get_info() { + let cbor_bytes = [Command::AUTHENTICATOR_GET_INFO]; + let command = Command::deserialize(&cbor_bytes); + assert_eq!(command, Ok(Command::AuthenticatorGetInfo)); + } + + #[test] + fn test_deserialize_reset() { + // Adding some random bytes to see if they are ignored. + let cbor_bytes = [Command::AUTHENTICATOR_RESET, 0xAB, 0xCD, 0xEF]; + let command = Command::deserialize(&cbor_bytes); + assert_eq!(command, Ok(Command::AuthenticatorReset)); + } + + #[test] + fn test_deserialize_get_next_assertion() { + let cbor_bytes = [Command::AUTHENTICATOR_GET_NEXT_ASSERTION]; + let command = Command::deserialize(&cbor_bytes); + assert_eq!(command, Ok(Command::AuthenticatorGetNextAssertion)); + } +} diff --git a/src/ctap/ctap1.rs b/src/ctap/ctap1.rs new file mode 100644 index 0000000..f3a9ce3 --- /dev/null +++ b/src/ctap/ctap1.rs @@ -0,0 +1,675 @@ +// Copyright 2019 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. + +use super::hid::ChannelID; +use super::key_material::{ATTESTATION_CERTIFICATE, ATTESTATION_PRIVATE_KEY}; +use super::status_code::Ctap2StatusCode; +use super::CtapState; +use crate::timer::ClockValue; +use alloc::vec::Vec; +use core::convert::Into; +use core::convert::TryFrom; +use crypto::rng256::Rng256; + +// The specification referenced in this file is at: +// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.pdf + +// status codes specification (version 20170411) section 3.3 +#[allow(non_camel_case_types)] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub enum Ctap1StatusCode { + SW_NO_ERROR = 0x9000, + SW_CONDITIONS_NOT_SATISFIED = 0x6985, + SW_WRONG_DATA = 0x6A80, + SW_WRONG_LENGTH = 0x6700, + SW_CLA_NOT_SUPPORTED = 0x6E00, + SW_INS_NOT_SUPPORTED = 0x6D00, + SW_VENDOR_KEY_HANDLE_TOO_LONG = 0xF000, +} + +impl TryFrom for Ctap1StatusCode { + type Error = (); + + fn try_from(value: u16) -> Result { + match value { + 0x9000 => Ok(Ctap1StatusCode::SW_NO_ERROR), + 0x6985 => Ok(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED), + 0x6A80 => Ok(Ctap1StatusCode::SW_WRONG_DATA), + 0x6700 => Ok(Ctap1StatusCode::SW_WRONG_LENGTH), + 0x6E00 => Ok(Ctap1StatusCode::SW_CLA_NOT_SUPPORTED), + 0x6D00 => Ok(Ctap1StatusCode::SW_INS_NOT_SUPPORTED), + 0xF000 => Ok(Ctap1StatusCode::SW_VENDOR_KEY_HANDLE_TOO_LONG), + _ => Err(()), + } + } +} + +impl Into for Ctap1StatusCode { + fn into(self) -> u16 { + self as u16 + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Clone, Debug))] +#[derive(PartialEq)] +pub enum Ctap1Flags { + CheckOnly = 0x07, + EnforceUpAndSign = 0x03, + DontEnforceUpAndSign = 0x08, +} + +impl TryFrom for Ctap1Flags { + type Error = Ctap1StatusCode; + + fn try_from(value: u8) -> Result { + match value { + 0x07 => Ok(Ctap1Flags::CheckOnly), + 0x03 => Ok(Ctap1Flags::EnforceUpAndSign), + 0x08 => Ok(Ctap1Flags::DontEnforceUpAndSign), + _ => Err(Ctap1StatusCode::SW_WRONG_DATA), + } + } +} + +impl Into for Ctap1Flags { + fn into(self) -> u8 { + self as u8 + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +// TODO: remove #allow when https://github.com/rust-lang/rust/issues/64362 is fixed +enum U2fCommand { + #[allow(dead_code)] + Register { + challenge: [u8; 32], + application: [u8; 32], + }, + #[allow(dead_code)] + Authenticate { + challenge: [u8; 32], + application: [u8; 32], + key_handle: Vec, + flags: Ctap1Flags, + }, + Version, + #[allow(dead_code)] + VendorSpecific { + payload: Vec, + }, +} + +impl TryFrom<&[u8]> for U2fCommand { + type Error = Ctap1StatusCode; + + fn try_from(message: &[u8]) -> Result { + if message.len() < Ctap1Command::APDU_HEADER_LEN as usize { + return Err(Ctap1StatusCode::SW_WRONG_DATA); + } + + let (apdu, payload) = message.split_at(Ctap1Command::APDU_HEADER_LEN as usize); + + // ISO7816 APDU Header format. Each cell is 1 byte. Note that the CTAP flavor always + // encodes the length on 3 bytes and doesn't use the field "Le" (Length Expected). + // We keep the 2 byte of "Le" for the packet length in mind, but always ignore its value. + // Lc is using big-endian encoding + // +-----+-----+----+----+-----+-----+-----+ + // | CLA | INS | P1 | P2 | Lc1 | Lc2 | Lc3 | + // +-----+-----+----+----+-----+-----+-----+ + if apdu[0] != Ctap1Command::CTAP1_CLA { + return Err(Ctap1StatusCode::SW_CLA_NOT_SUPPORTED); + } + + let lc = (((apdu[4] as u32) << 16) | ((apdu[5] as u32) << 8) | (apdu[6] as u32)) as usize; + + // Since there is always request data, the expected length is either omitted or + // encoded in 2 bytes. + if lc != payload.len() && lc + 2 != payload.len() { + return Err(Ctap1StatusCode::SW_WRONG_LENGTH); + } + + match apdu[1] { + // U2F raw message format specification, Section 4.1 + // +-----------------+-------------------+ + // + Challenge (32B) | Application (32B) | + // +-----------------+-------------------+ + Ctap1Command::U2F_REGISTER => { + if lc != 64 { + return Err(Ctap1StatusCode::SW_WRONG_LENGTH); + } + Ok(Self::Register { + challenge: *array_ref!(payload, 0, 32), + application: *array_ref!(payload, 32, 32), + }) + } + + // U2F raw message format specification, Section 5.1 + // +-----------------+-------------------+---------------------+------------+ + // + Challenge (32B) | Application (32B) | key handle len (1B) | key handle | + // +-----------------+-------------------+---------------------+------------+ + Ctap1Command::U2F_AUTHENTICATE => { + if lc < 65 { + return Err(Ctap1StatusCode::SW_WRONG_LENGTH); + } + let handle_length = payload[64] as usize; + if lc != 65 + handle_length { + return Err(Ctap1StatusCode::SW_WRONG_LENGTH); + } + let flag = Ctap1Flags::try_from(apdu[2])?; + Ok(Self::Authenticate { + challenge: *array_ref!(payload, 0, 32), + application: *array_ref!(payload, 32, 32), + key_handle: payload[65..lc].to_vec(), + flags: flag, + }) + } + + // U2F raw message format specification, Section 6.1 + Ctap1Command::U2F_VERSION => { + if lc != 0 { + return Err(Ctap1StatusCode::SW_WRONG_LENGTH); + } + Ok(Self::Version) + } + + // For Vendor specific command. + Ctap1Command::VENDOR_SPECIFIC_FIRST..=Ctap1Command::VENDOR_SPECIFIC_LAST => { + Ok(Self::VendorSpecific { + payload: payload.to_vec(), + }) + } + + _ => Err(Ctap1StatusCode::SW_INS_NOT_SUPPORTED), + } + } +} + +pub struct Ctap1Command {} + +impl Ctap1Command { + const APDU_HEADER_LEN: u32 = 7; // CLA + INS + P1 + P2 + LC1-3 + + const CTAP1_CLA: u8 = 0; + // This byte is used in Register, but only serves backwards compatibility. + const LEGACY_BYTE: u8 = 0x05; + // This byte is hardcoded into the specification of Authenticate. + const USER_PRESENCE_INDICATOR_BYTE: u8 = 0x01; + + // CTAP1/U2F commands + // U2F raw message format specification 1.2 (version 20170411) + const U2F_REGISTER: u8 = 0x01; + const U2F_AUTHENTICATE: u8 = 0x02; + const U2F_VERSION: u8 = 0x03; + const VENDOR_SPECIFIC_FIRST: u8 = 0x40; + const VENDOR_SPECIFIC_LAST: u8 = 0xBF; + + pub fn process_command( + message: &[u8], + ctap_state: &mut CtapState, + clock_value: ClockValue, + ) -> Result, Ctap1StatusCode> + where + R: Rng256, + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, + { + let command = U2fCommand::try_from(message)?; + match command { + U2fCommand::Register { + challenge, + application, + } => { + if !ctap_state.u2f_up_state.consume_up(clock_value) { + return Err(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED); + } + Ctap1Command::process_register(challenge, application, ctap_state) + } + + U2fCommand::Authenticate { + challenge, + application, + key_handle, + flags, + } => { + // The order is important due to side effects of checking user presence. + if flags == Ctap1Flags::EnforceUpAndSign + && !ctap_state.u2f_up_state.consume_up(clock_value) + { + return Err(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED); + } + Ctap1Command::process_authenticate( + challenge, + application, + key_handle, + flags, + ctap_state, + ) + } + + // U2F raw message format specification (version 20170411) section 6.3 + U2fCommand::Version => Ok(Vec::::from(super::U2F_VERSION_STRING)), + + // TODO: should we return an error instead such as SW_INS_NOT_SUPPORTED? + U2fCommand::VendorSpecific { .. } => Err(Ctap1StatusCode::SW_NO_ERROR), + } + } + + // U2F raw message format specification (version 20170411) section 4.3 + // In case of success we need to send back the following reply + // (excluding ISO7816 success code) + // +------+--------------------+---------------------+------------+------------+------+ + // + 0x05 | User pub key (65B) | key handle len (1B) | key handle | X.509 Cert | Sign | + // +------+--------------------+---------------------+------------+------------+------+ + // + // Where Sign is an ECDSA signature over the following structure: + // +------+-------------------+-----------------+------------+--------------------+ + // + 0x00 | application (32B) | challenge (32B) | key handle | User pub key (65B) | + // +------+-------------------+-----------------+------------+--------------------+ + fn process_register( + challenge: [u8; 32], + application: [u8; 32], + ctap_state: &mut CtapState, + ) -> Result, Ctap1StatusCode> + where + R: Rng256, + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, + { + let sk = crypto::ecdsa::SecKey::gensk(ctap_state.rng); + let pk = sk.genpk(); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + if key_handle.len() > 0xFF { + // This is just being defensive with unreachable code. + return Err(Ctap1StatusCode::SW_VENDOR_KEY_HANDLE_TOO_LONG); + } + + let mut response = + Vec::with_capacity(105 + key_handle.len() + ATTESTATION_CERTIFICATE.len()); + response.push(Ctap1Command::LEGACY_BYTE); + let user_pk = pk.to_uncompressed(); + response.extend_from_slice(&user_pk); + response.push(key_handle.len() as u8); + response.extend(key_handle.clone()); + response.extend_from_slice(&ATTESTATION_CERTIFICATE); + + // The first byte is reserved. + let mut signature_data = Vec::with_capacity(66 + key_handle.len()); + signature_data.push(0x00); + signature_data.extend(&application); + signature_data.extend(&challenge); + signature_data.extend(key_handle); + signature_data.extend_from_slice(&user_pk); + + let attestation_key = crypto::ecdsa::SecKey::from_bytes(&ATTESTATION_PRIVATE_KEY).unwrap(); + let signature = attestation_key.sign_rfc6979::(&signature_data); + + response.extend(signature.to_asn1_der()); + Ok(response) + } + + // U2F raw message format specification (version 20170411) section 5.4 + // In case of success we need to send back the following reply + // (excluding ISO7816 success code) + // +---------+--------------+-----------+ + // + UP (1B) | Counter (4B) | Signature | + // +---------+--------------+-----------+ + // UP only has 2 defined values: + // - 0x00: user presence was not verified + // - 0x01: user presence was verified + // + // Where Signature is an ECDSA signature over the following structure: + // +-------------------+---------+--------------+-----------------+ + // + application (32B) | UP (1B) | Counter (4B) | challenge (32B) | + // +-------------------+---------+--------------+-----------------+ + fn process_authenticate( + challenge: [u8; 32], + application: [u8; 32], + key_handle: Vec, + flags: Ctap1Flags, + ctap_state: &mut CtapState, + ) -> Result, Ctap1StatusCode> + where + R: Rng256, + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, + { + let credential_source = ctap_state.decrypt_credential_source(key_handle, &application); + if let Some(credential_source) = credential_source { + if flags == Ctap1Flags::CheckOnly { + return Err(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED); + } + ctap_state.increment_global_signature_counter(); + let mut signature_data = ctap_state + .generate_auth_data(&application, Ctap1Command::USER_PRESENCE_INDICATOR_BYTE); + signature_data.extend(&challenge); + let signature = credential_source + .private_key + .sign_rfc6979::(&signature_data); + + let mut response = signature_data[application.len()..application.len() + 5].to_vec(); + response.extend(signature.to_asn1_der()); + Ok(response) + } else { + Err(Ctap1StatusCode::SW_WRONG_DATA) + } + } +} + +#[cfg(test)] +mod test { + use super::super::{ENCRYPTED_CREDENTIAL_ID_SIZE, USE_SIGNATURE_COUNTER}; + use super::*; + use crypto::rng256::ThreadRng256; + use crypto::Hash256; + + const CLOCK_FREQUENCY_HZ: usize = 32768; + const START_CLOCK_VALUE: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ); + const TIMEOUT_CLOCK_VALUE: ClockValue = ClockValue::new( + (30001 * CLOCK_FREQUENCY_HZ as isize) / 1000, + CLOCK_FREQUENCY_HZ, + ); + + fn create_register_message(application: &[u8; 32]) -> Vec { + let mut message = vec![ + Ctap1Command::CTAP1_CLA, + Ctap1Command::U2F_REGISTER, + 0x00, + 0x00, + 0x00, + 0x00, + 0x40, + ]; + let challenge = [0x0C; 32]; + message.extend(&challenge); + message.extend(application); + message + } + + fn create_authenticate_message( + application: &[u8; 32], + flags: Ctap1Flags, + key_handle: &Vec, + ) -> Vec { + let mut message = vec![ + Ctap1Command::CTAP1_CLA, + Ctap1Command::U2F_AUTHENTICATE, + flags.into(), + 0x00, + 0x00, + 0x00, + 65 + ENCRYPTED_CREDENTIAL_ID_SIZE as u8, + ]; + let challenge = [0x0C; 32]; + message.extend(&challenge); + message.extend(application); + message.push(ENCRYPTED_CREDENTIAL_ID_SIZE as u8); + message.extend(key_handle); + message + } + + #[test] + fn test_process_register() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let application = [0x0A; 32]; + let message = create_register_message(&application); + ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); + ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); + let response = + Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE).unwrap(); + + assert_eq!(response[0], Ctap1Command::LEGACY_BYTE); + assert_eq!(response[66], ENCRYPTED_CREDENTIAL_ID_SIZE as u8); + assert!(ctap_state + .decrypt_credential_source( + response[67..67 + ENCRYPTED_CREDENTIAL_ID_SIZE].to_vec(), + &application + ) + .is_some()); + const CERT_START: usize = 67 + ENCRYPTED_CREDENTIAL_ID_SIZE; + assert_eq!( + &response[CERT_START..CERT_START + ATTESTATION_CERTIFICATE.len()], + &ATTESTATION_CERTIFICATE[..] + ); + } + + #[test] + fn test_process_register_bad_message() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let application = [0x0A; 32]; + let message = create_register_message(&application); + let response = Ctap1Command::process_command( + &message[..message.len() - 1], + &mut ctap_state, + START_CLOCK_VALUE, + ); + + assert_eq!(response, Err(Ctap1StatusCode::SW_WRONG_LENGTH)); + } + + #[test] + fn test_process_register_without_up() { + let application = [0x0A; 32]; + let message = create_register_message(&application); + + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); + ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); + let response = + Ctap1Command::process_command(&message, &mut ctap_state, TIMEOUT_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED)); + } + + #[test] + fn test_process_authenticate_check_only() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let message = create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle); + + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED)); + } + + #[test] + fn test_process_authenticate_check_only_wrong_rp() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let application = [0x55; 32]; + let message = create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle); + + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_WRONG_DATA)); + } + + #[test] + fn test_process_authenticate_check_only_wrong_length() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let mut message = + create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle); + + message.push(0x00); + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_WRONG_LENGTH)); + + // Two extra zeros are okay, they could encode the expected response length. + message.push(0x00); + message.push(0x00); + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_WRONG_LENGTH)); + } + + #[test] + fn test_process_authenticate_check_only_wrong_cla() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let mut message = + create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle); + message[0] = 0xEE; + + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_CLA_NOT_SUPPORTED)); + } + + #[test] + fn test_process_authenticate_check_only_wrong_ins() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let mut message = + create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle); + message[1] = 0xEE; + + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_INS_NOT_SUPPORTED)); + } + + #[test] + fn test_process_authenticate_check_only_wrong_flags() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let mut message = + create_authenticate_message(&application, Ctap1Flags::CheckOnly, &key_handle); + message[2] = 0xEE; + + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_WRONG_DATA)); + } + + #[test] + fn test_process_authenticate_enforce() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let message = + create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle); + + ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); + ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); + let response = + Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE).unwrap(); + assert_eq!(response[0], 0x01); + if USE_SIGNATURE_COUNTER { + assert_eq!(response[1..5], [0x00, 0x00, 0x00, 0x01]); + } else { + assert_eq!(response[1..5], [0x00, 0x00, 0x00, 0x00]); + } + } + + #[test] + fn test_process_authenticate_dont_enforce() { + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let sk = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + let rp_id = "example.com"; + let application = crypto::sha256::Sha256::hash(rp_id.as_bytes()); + let key_handle = ctap_state.encrypt_key_handle(sk, &application); + let message = create_authenticate_message( + &application, + Ctap1Flags::DontEnforceUpAndSign, + &key_handle, + ); + + let response = + Ctap1Command::process_command(&message, &mut ctap_state, TIMEOUT_CLOCK_VALUE).unwrap(); + assert_eq!(response[0], 0x01); + if USE_SIGNATURE_COUNTER { + assert_eq!(response[1..5], [0x00, 0x00, 0x00, 0x01]); + } else { + assert_eq!(response[1..5], [0x00, 0x00, 0x00, 0x00]); + } + } + + #[test] + fn test_process_authenticate_bad_key_handle() { + let application = [0x0A; 32]; + let key_handle = vec![0x00; ENCRYPTED_CREDENTIAL_ID_SIZE]; + let message = + create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle); + + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); + ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); + let response = Ctap1Command::process_command(&message, &mut ctap_state, START_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_WRONG_DATA)); + } + + #[test] + fn test_process_authenticate_without_up() { + let application = [0x0A; 32]; + let key_handle = vec![0x00; ENCRYPTED_CREDENTIAL_ID_SIZE]; + let message = + create_authenticate_message(&application, Ctap1Flags::EnforceUpAndSign, &key_handle); + + let mut rng = ThreadRng256 {}; + let dummy_user_presence = |_| panic!("Unexpected user presence check in CTAP1"); + let mut ctap_state = CtapState::new(&mut rng, dummy_user_presence); + + ctap_state.u2f_up_state.consume_up(START_CLOCK_VALUE); + ctap_state.u2f_up_state.grant_up(START_CLOCK_VALUE); + let response = + Ctap1Command::process_command(&message, &mut ctap_state, TIMEOUT_CLOCK_VALUE); + assert_eq!(response, Err(Ctap1StatusCode::SW_CONDITIONS_NOT_SATISFIED)); + } +} diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs new file mode 100644 index 0000000..eae2948 --- /dev/null +++ b/src/ctap/data_formats.rs @@ -0,0 +1,1020 @@ +// Copyright 2019 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. + +use super::status_code::Ctap2StatusCode; +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use core::convert::TryFrom; +use crypto::{ecdh, ecdsa}; + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct PublicKeyCredentialRpEntity { + pub rp_id: String, + pub rp_name: Option, + pub rp_icon: Option, +} + +impl TryFrom<&cbor::Value> for PublicKeyCredentialRpEntity { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let rp_map = read_map(cbor_value)?; + let rp_id = read_text_string(ok_or_missing(rp_map.get(&cbor_text!("id")))?)?; + let rp_name = rp_map + .get(&cbor_text!("name")) + .map(read_text_string) + .transpose()?; + let rp_icon = rp_map + .get(&cbor_text!("icon")) + .map(read_text_string) + .transpose()?; + Ok(Self { + rp_id, + rp_name, + rp_icon, + }) + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct PublicKeyCredentialUserEntity { + pub user_id: Vec, + pub user_name: Option, + pub user_display_name: Option, + pub user_icon: Option, +} + +impl TryFrom<&cbor::Value> for PublicKeyCredentialUserEntity { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let user_map = read_map(cbor_value)?; + let user_id = read_byte_string(ok_or_missing(user_map.get(&cbor_text!("id")))?)?; + let user_name = user_map + .get(&cbor_text!("name")) + .map(read_text_string) + .transpose()?; + let user_display_name = user_map + .get(&cbor_text!("displayName")) + .map(read_text_string) + .transpose()?; + let user_icon = user_map + .get(&cbor_text!("icon")) + .map(read_text_string) + .transpose()?; + Ok(Self { + user_id, + user_name, + user_display_name, + user_icon, + }) + } +} + +impl From for cbor::Value { + fn from(entity: PublicKeyCredentialUserEntity) -> Self { + cbor_map_options! { + "id" => entity.user_id, + "name" => entity.user_name, + "displayName" => entity.user_display_name, + "icon" => entity.user_icon, + } + } +} + +#[derive(Clone, PartialEq)] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub enum PublicKeyCredentialType { + PublicKey, +} + +impl From for cbor::Value { + fn from(cred_type: PublicKeyCredentialType) -> Self { + match cred_type { + PublicKeyCredentialType::PublicKey => "public-key", + } + .into() + } +} + +impl TryFrom<&cbor::Value> for PublicKeyCredentialType { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let cred_type_string = read_text_string(cbor_value)?; + match &cred_type_string[..] { + "public-key" => Ok(PublicKeyCredentialType::PublicKey), + _ => Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM), + } + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub enum AuthenticatorTransport { + Usb, + Nfc, + Ble, + Internal, +} + +impl From for cbor::Value { + fn from(transport: AuthenticatorTransport) -> Self { + match transport { + AuthenticatorTransport::Usb => "usb", + AuthenticatorTransport::Nfc => "nfc", + AuthenticatorTransport::Ble => "ble", + AuthenticatorTransport::Internal => "internal", + } + .into() + } +} + +impl TryFrom<&cbor::Value> for AuthenticatorTransport { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let transport_string = read_text_string(cbor_value)?; + match &transport_string[..] { + "usb" => Ok(AuthenticatorTransport::Usb), + "nfc" => Ok(AuthenticatorTransport::Nfc), + "ble" => Ok(AuthenticatorTransport::Ble), + "internal" => Ok(AuthenticatorTransport::Internal), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct PublicKeyCredentialDescriptor { + pub key_type: PublicKeyCredentialType, + pub key_id: Vec, + pub transports: Option>, +} + +impl TryFrom<&cbor::Value> for PublicKeyCredentialDescriptor { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let cred_desc_map = read_map(cbor_value)?; + let key_type = PublicKeyCredentialType::try_from(ok_or_missing( + cred_desc_map.get(&cbor_text!("type")), + )?)?; + let key_id = read_byte_string(ok_or_missing(cred_desc_map.get(&cbor_text!("id")))?)?; + let transports = match cred_desc_map.get(&cbor_text!("transports")) { + Some(exclude_entry) => { + let transport_vec = read_array(exclude_entry)?; + let mut transports = vec![]; + for transport_value in transport_vec { + transports.push(AuthenticatorTransport::try_from(transport_value)?); + } + Some(transports) + } + None => None, + }; + Ok(Self { + key_type, + key_id, + transports, + }) + } +} + +impl From for cbor::Value { + fn from(desc: PublicKeyCredentialDescriptor) -> Self { + cbor_map_options! { + "type" => desc.key_type, + "id" => desc.key_id, + "transports" => desc.transports.map(|vec| cbor_array_vec!(vec)), + } + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct Extensions(BTreeMap); + +impl TryFrom<&cbor::Value> for Extensions { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let mut extensions = BTreeMap::new(); + for (extension_key, extension_value) in read_map(cbor_value)? { + if let cbor::KeyType::TextString(extension_key_string) = extension_key { + extensions.insert(extension_key_string.to_string(), extension_value.clone()); + } else { + return Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE); + } + } + Ok(Extensions(extensions)) + } +} + +// Even though options are optional, we can use the default if not present. +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct MakeCredentialOptions { + pub rk: bool, + pub uv: bool, +} + +impl TryFrom<&cbor::Value> for MakeCredentialOptions { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let options_map = read_map(cbor_value)?; + let rk = match options_map.get(&cbor_text!("rk")) { + Some(options_entry) => read_bool(options_entry)?, + None => false, + }; + if let Some(options_entry) = options_map.get(&cbor_text!("up")) { + if !read_bool(options_entry)? { + return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); + } + } + let uv = match options_map.get(&cbor_text!("uv")) { + Some(options_entry) => read_bool(options_entry)?, + None => false, + }; + Ok(Self { rk, uv }) + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct GetAssertionOptions { + pub up: bool, + pub uv: bool, +} + +impl TryFrom<&cbor::Value> for GetAssertionOptions { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let options_map = read_map(cbor_value)?; + if let Some(options_entry) = options_map.get(&cbor_text!("rk")) { + // This is only for returning the correct status code. + read_bool(options_entry)?; + return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); + } + let up = match options_map.get(&cbor_text!("up")) { + Some(options_entry) => read_bool(options_entry)?, + None => true, + }; + let uv = match options_map.get(&cbor_text!("uv")) { + Some(options_entry) => read_bool(options_entry)?, + None => false, + }; + Ok(Self { up, uv }) + } +} + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub struct PackedAttestationStatement { + pub alg: i64, + pub sig: Vec, + pub x5c: Option>>, + pub ecdaa_key_id: Option>, +} + +impl From for cbor::Value { + fn from(att_stmt: PackedAttestationStatement) -> Self { + cbor_map_options! { + "alg" => att_stmt.alg, + "sig" => att_stmt.sig, + "x5c" => att_stmt.x5c.map(|x| cbor_array_vec!(x)), + "ecdaaKeyId" => att_stmt.ecdaa_key_id, + } + } +} + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub enum SignatureAlgorithm { + ES256 = ecdsa::PubKey::ES256_ALGORITHM as isize, +} + +#[derive(Clone)] +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub struct PublicKeyCredentialSource { + // TODO function to convert to / from Vec + pub key_type: PublicKeyCredentialType, + pub credential_id: Vec, + pub private_key: ecdsa::SecKey, // TODO(kaczmarczyck) open for other algorithms + pub rp_id: String, + pub user_handle: Vec, // not optional, but nullable + pub other_ui: Option, +} + +impl From for cbor::Value { + fn from(credential: PublicKeyCredentialSource) -> cbor::Value { + let mut private_key = [0u8; 32]; + credential.private_key.to_bytes(&mut private_key); + let other_ui = match credential.other_ui { + None => cbor_null!(), + Some(other_ui) => cbor_text!(other_ui), + }; + cbor_array! { + credential.credential_id, + private_key, + credential.rp_id, + credential.user_handle, + other_ui, + } + } +} + +impl TryFrom for PublicKeyCredentialSource { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: cbor::Value) -> Result { + use cbor::{SimpleValue, Value}; + + let fields = read_array(&cbor_value)?; + if fields.len() != 5 { + return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR); + } + let credential_id = read_byte_string(&fields[0])?; + let private_key = read_byte_string(&fields[1])?; + if private_key.len() != 32 { + return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR); + } + let private_key = ecdsa::SecKey::from_bytes(array_ref!(private_key, 0, 32)) + .ok_or(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)?; + let rp_id = read_text_string(&fields[2])?; + let user_handle = read_byte_string(&fields[3])?; + let other_ui = match &fields[4] { + Value::Simple(SimpleValue::NullValue) => None, + cbor_value => Some(read_text_string(cbor_value)?), + }; + Ok(PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id, + private_key, + rp_id, + user_handle, + other_ui, + }) + } +} + +// TODO(kaczmarczyck) we could decide to split this data type up +// It depends on the algorithm though, I think. +// So before creating a mess, this is my workaround. +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub struct CoseKey(pub BTreeMap); + +// This is the algorithm specifier that is supposed to be used in a COSE key +// map. The CTAP specification says -25 which represents ECDH-ES + HKDF-256 +// here: https://www.iana.org/assignments/cose/cose.xhtml#algorithms +// In fact, this is just used for compatibility with older specification versions. +const ECDH_ALGORITHM: i64 = -25; +const EC2_KEY_TYPE: i64 = 2; +const P_256_CURVE: i64 = 1; + +impl From for CoseKey { + fn from(pk: ecdh::PubKey) -> Self { + let mut x_bytes = [0; ecdh::NBYTES]; + let mut y_bytes = [0; ecdh::NBYTES]; + pk.to_coordinates(&mut x_bytes, &mut y_bytes); + let x_byte_cbor: cbor::Value = cbor_bytes_lit!(&x_bytes); + let y_byte_cbor: cbor::Value = cbor_bytes_lit!(&y_bytes); + // TODO(kaczmarczyck) do not write optional parameters, spec is unclear + let cose_cbor_value = cbor_map_options! { + 1 => EC2_KEY_TYPE, + 3 => ECDH_ALGORITHM, + -1 => P_256_CURVE, + -2 => x_byte_cbor, + -3 => y_byte_cbor, + }; + if let cbor::Value::Map(cose_map) = cose_cbor_value { + CoseKey(cose_map) + } else { + unreachable!(); + } + } +} + +impl TryFrom for ecdh::PubKey { + type Error = Ctap2StatusCode; + + fn try_from(cose_key: CoseKey) -> Result { + let key_type = read_integer(ok_or_missing(cose_key.0.get(&cbor_int!(1)))?)?; + if key_type != EC2_KEY_TYPE { + return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); + } + let algorithm = read_integer(ok_or_missing(cose_key.0.get(&cbor_int!(3)))?)?; + if algorithm != ECDH_ALGORITHM { + return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); + } + let curve = read_integer(ok_or_missing(cose_key.0.get(&cbor_int!(-1)))?)?; + if curve != P_256_CURVE { + return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); + } + let x_bytes = read_byte_string(ok_or_missing(cose_key.0.get(&cbor_int!(-2)))?)?; + if x_bytes.len() != ecdh::NBYTES { + return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); + } + let y_bytes = read_byte_string(ok_or_missing(cose_key.0.get(&cbor_int!(-3)))?)?; + if y_bytes.len() != ecdh::NBYTES { + return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); + } + let x_array_ref = array_ref![x_bytes.as_slice(), 0, ecdh::NBYTES]; + let y_array_ref = array_ref![y_bytes.as_slice(), 0, ecdh::NBYTES]; + ecdh::PubKey::from_coordinates(x_array_ref, y_array_ref) + .ok_or(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER) + } +} + +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))] +pub enum ClientPinSubCommand { + GetPinRetries, + GetKeyAgreement, + SetPin, + ChangePin, + GetPinUvAuthTokenUsingPin, + GetPinUvAuthTokenUsingUv, + GetUvRetries, +} + +impl From for cbor::Value { + fn from(subcommand: ClientPinSubCommand) -> Self { + match subcommand { + ClientPinSubCommand::GetPinRetries => 0x01, + ClientPinSubCommand::GetKeyAgreement => 0x02, + ClientPinSubCommand::SetPin => 0x03, + ClientPinSubCommand::ChangePin => 0x04, + ClientPinSubCommand::GetPinUvAuthTokenUsingPin => 0x05, + ClientPinSubCommand::GetPinUvAuthTokenUsingUv => 0x06, + ClientPinSubCommand::GetUvRetries => 0x07, + } + .into() + } +} + +impl TryFrom<&cbor::Value> for ClientPinSubCommand { + type Error = Ctap2StatusCode; + + fn try_from(cbor_value: &cbor::Value) -> Result { + let subcommand_int = read_unsigned(cbor_value)?; + match subcommand_int { + 0x01 => Ok(ClientPinSubCommand::GetPinRetries), + 0x02 => Ok(ClientPinSubCommand::GetKeyAgreement), + 0x03 => Ok(ClientPinSubCommand::SetPin), + 0x04 => Ok(ClientPinSubCommand::ChangePin), + 0x05 => Ok(ClientPinSubCommand::GetPinUvAuthTokenUsingPin), + 0x06 => Ok(ClientPinSubCommand::GetPinUvAuthTokenUsingUv), + 0x07 => Ok(ClientPinSubCommand::GetUvRetries), + // TODO(kaczmarczyck) what is the correct status code for this error? + _ => Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER), + } + } +} + +pub(super) fn read_unsigned(cbor_value: &cbor::Value) -> Result { + match cbor_value { + cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => Ok(*unsigned), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub(super) fn read_integer(cbor_value: &cbor::Value) -> Result { + match cbor_value { + cbor::Value::KeyValue(cbor::KeyType::Unsigned(unsigned)) => { + if *unsigned <= core::i64::MAX as u64 { + Ok(*unsigned as i64) + } else { + Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + } + } + cbor::Value::KeyValue(cbor::KeyType::Negative(signed)) => Ok(*signed), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub fn read_byte_string(cbor_value: &cbor::Value) -> Result, Ctap2StatusCode> { + match cbor_value { + cbor::Value::KeyValue(cbor::KeyType::ByteString(byte_string)) => Ok(byte_string.to_vec()), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub(super) fn read_text_string(cbor_value: &cbor::Value) -> Result { + match cbor_value { + cbor::Value::KeyValue(cbor::KeyType::TextString(text_string)) => { + Ok(text_string.to_string()) + } + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub(super) fn read_array(cbor_value: &cbor::Value) -> Result<&Vec, Ctap2StatusCode> { + match cbor_value { + cbor::Value::Array(array) => Ok(array), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub(super) fn read_map( + cbor_value: &cbor::Value, +) -> Result<&BTreeMap, Ctap2StatusCode> { + match cbor_value { + cbor::Value::Map(map) => Ok(map), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub(super) fn read_bool(cbor_value: &cbor::Value) -> Result { + match cbor_value { + cbor::Value::Simple(cbor::SimpleValue::FalseValue) => Ok(false), + cbor::Value::Simple(cbor::SimpleValue::TrueValue) => Ok(true), + _ => Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE), + } +} + +pub(super) fn ok_or_missing( + value_option: Option<&cbor::Value>, +) -> Result<&cbor::Value, Ctap2StatusCode> { + value_option.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER) +} + +#[cfg(test)] +mod test { + use self::Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE; + use super::*; + use alloc::collections::BTreeMap; + + #[test] + fn test_read_unsigned() { + assert_eq!(read_unsigned(&cbor_int!(123)), Ok(123)); + assert_eq!( + read_unsigned(&cbor_bool!(true)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_unsigned(&cbor_text!("foo")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_unsigned(&cbor_bytes_lit!(b"bar")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_unsigned(&cbor_array![]), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_unsigned(&cbor_map! {}), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_read_unsigned_limits() { + assert_eq!( + read_unsigned(&cbor_unsigned!(std::u64::MAX)), + Ok(std::u64::MAX) + ); + assert_eq!( + read_unsigned(&cbor_unsigned!((std::i64::MAX as u64) + 1)), + Ok((std::i64::MAX as u64) + 1) + ); + assert_eq!( + read_unsigned(&cbor_int!(std::i64::MAX)), + Ok(std::i64::MAX as u64) + ); + assert_eq!(read_unsigned(&cbor_int!(123)), Ok(123)); + assert_eq!(read_unsigned(&cbor_int!(1)), Ok(1)); + assert_eq!(read_unsigned(&cbor_int!(0)), Ok(0)); + assert_eq!( + read_unsigned(&cbor_int!(-1)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_unsigned(&cbor_int!(-123)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_unsigned(&cbor_int!(std::i64::MIN)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_read_integer() { + assert_eq!(read_integer(&cbor_int!(123)), Ok(123)); + assert_eq!(read_integer(&cbor_int!(-123)), Ok(-123)); + assert_eq!( + read_integer(&cbor_bool!(true)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_integer(&cbor_text!("foo")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_integer(&cbor_bytes_lit!(b"bar")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_integer(&cbor_array![]), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_integer(&cbor_map! {}), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_read_integer_limits() { + assert_eq!( + read_integer(&cbor_unsigned!(std::u64::MAX)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_integer(&cbor_unsigned!((std::i64::MAX as u64) + 1)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!(read_integer(&cbor_int!(std::i64::MAX)), Ok(std::i64::MAX)); + assert_eq!(read_integer(&cbor_int!(123)), Ok(123)); + assert_eq!(read_integer(&cbor_int!(1)), Ok(1)); + assert_eq!(read_integer(&cbor_int!(0)), Ok(0)); + assert_eq!(read_integer(&cbor_int!(-1)), Ok(-1)); + assert_eq!(read_integer(&cbor_int!(-123)), Ok(-123)); + assert_eq!(read_integer(&cbor_int!(std::i64::MIN)), Ok(std::i64::MIN)); + } + + #[test] + fn test_read_byte_string() { + assert_eq!( + read_byte_string(&cbor_int!(123)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_byte_string(&cbor_bool!(true)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_byte_string(&cbor_text!("foo")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!(read_byte_string(&cbor_bytes_lit!(b"")), Ok(Vec::new())); + assert_eq!( + read_byte_string(&cbor_bytes_lit!(b"bar")), + Ok(b"bar".to_vec()) + ); + assert_eq!( + read_byte_string(&cbor_array![]), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_byte_string(&cbor_map! {}), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_read_text_string() { + assert_eq!( + read_text_string(&cbor_int!(123)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_text_string(&cbor_bool!(true)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!(read_text_string(&cbor_text!("")), Ok(String::new())); + assert_eq!( + read_text_string(&cbor_text!("foo")), + Ok(String::from("foo")) + ); + assert_eq!( + read_text_string(&cbor_bytes_lit!(b"bar")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_text_string(&cbor_array![]), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_text_string(&cbor_map! {}), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_read_array() { + assert_eq!( + read_array(&cbor_int!(123)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_array(&cbor_bool!(true)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_array(&cbor_text!("foo")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_array(&cbor_bytes_lit!(b"bar")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!(read_array(&cbor_array![]), Ok(&Vec::new())); + assert_eq!( + read_array(&cbor_array![ + 123, + cbor_null!(), + "foo", + cbor_array![], + cbor_map! {}, + ]), + Ok(&vec![ + cbor_int!(123), + cbor_null!(), + cbor_text!("foo"), + cbor_array![], + cbor_map! {}, + ]) + ); + assert_eq!( + read_array(&cbor_map! {}), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_read_map() { + assert_eq!( + read_map(&cbor_int!(123)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_map(&cbor_bool!(true)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_map(&cbor_text!("foo")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_map(&cbor_bytes_lit!(b"bar")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_map(&cbor_array![]), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!(read_map(&cbor_map! {}), Ok(&BTreeMap::new())); + assert_eq!( + read_map(&cbor_map! { + 1 => cbor_false!(), + "foo" => b"bar", + b"bin" => -42, + }), + Ok(&[ + (cbor_unsigned!(1), cbor_false!()), + (cbor_text!("foo"), cbor_bytes_lit!(b"bar")), + (cbor_bytes_lit!(b"bin"), cbor_int!(-42)), + ] + .iter() + .cloned() + .collect::>()) + ); + } + + #[test] + fn test_read_bool() { + assert_eq!( + read_bool(&cbor_int!(123)), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!(read_bool(&cbor_bool!(true)), Ok(true)); + assert_eq!(read_bool(&cbor_bool!(false)), Ok(false)); + assert_eq!( + read_bool(&cbor_text!("foo")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_bool(&cbor_bytes_lit!(b"bar")), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_bool(&cbor_array![]), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + assert_eq!( + read_bool(&cbor_map! {}), + Err(CTAP2_ERR_CBOR_UNEXPECTED_TYPE) + ); + } + + #[test] + fn test_from_public_key_credential_rp_entity() { + let cbor_rp_entity = cbor_map! { + "id" => "example.com", + "name" => "Example", + "icon" => "example.com/icon.png", + }; + let rp_entity = PublicKeyCredentialRpEntity::try_from(&cbor_rp_entity); + let expected_rp_entity = PublicKeyCredentialRpEntity { + rp_id: "example.com".to_string(), + rp_name: Some("Example".to_string()), + rp_icon: Some("example.com/icon.png".to_string()), + }; + assert_eq!(rp_entity, Ok(expected_rp_entity)); + } + + #[test] + fn test_from_into_public_key_credential_user_entity() { + let cbor_user_entity = cbor_map! { + "id" => vec![0x1D, 0x1D, 0x1D, 0x1D], + "name" => "foo", + "displayName" => "bar", + "icon" => "example.com/foo/icon.png", + }; + let user_entity = PublicKeyCredentialUserEntity::try_from(&cbor_user_entity); + let expected_user_entity = PublicKeyCredentialUserEntity { + user_id: vec![0x1D, 0x1D, 0x1D, 0x1D], + user_name: Some("foo".to_string()), + user_display_name: Some("bar".to_string()), + user_icon: Some("example.com/foo/icon.png".to_string()), + }; + assert_eq!(user_entity, Ok(expected_user_entity)); + let created_cbor: cbor::Value = user_entity.unwrap().into(); + assert_eq!(created_cbor, cbor_user_entity); + } + + #[test] + fn test_from_into_public_key_credential_type() { + let cbor_credential_type = cbor_text!("public-key"); + let credential_type = PublicKeyCredentialType::try_from(&cbor_credential_type); + let expected_credential_type = PublicKeyCredentialType::PublicKey; + assert_eq!(credential_type, Ok(expected_credential_type)); + let created_cbor: cbor::Value = credential_type.unwrap().into(); + assert_eq!(created_cbor, cbor_credential_type); + } + + #[test] + fn test_from_into_authenticator_transport() { + let cbor_authenticator_transport = cbor_text!("usb"); + let authenticator_transport = + AuthenticatorTransport::try_from(&cbor_authenticator_transport); + let expected_authenticator_transport = AuthenticatorTransport::Usb; + assert_eq!( + authenticator_transport, + Ok(expected_authenticator_transport) + ); + let created_cbor: cbor::Value = authenticator_transport.unwrap().into(); + assert_eq!(created_cbor, cbor_authenticator_transport); + } + + #[test] + fn test_from_into_public_key_credential_descriptor() { + let cbor_credential_descriptor = cbor_map! { + "type" => "public-key", + "id" => vec![0x2D, 0x2D, 0x2D, 0x2D], + "transports" => cbor_array!["usb"], + }; + let credential_descriptor = + PublicKeyCredentialDescriptor::try_from(&cbor_credential_descriptor); + let expected_credential_descriptor = PublicKeyCredentialDescriptor { + key_type: PublicKeyCredentialType::PublicKey, + key_id: vec![0x2D, 0x2D, 0x2D, 0x2D], + transports: Some(vec![AuthenticatorTransport::Usb]), + }; + assert_eq!(credential_descriptor, Ok(expected_credential_descriptor)); + let created_cbor: cbor::Value = credential_descriptor.unwrap().into(); + assert_eq!(created_cbor, cbor_credential_descriptor); + } + + #[test] + fn test_from_extensions() { + let cbor_extensions = cbor_map! { + "the_answer" => 42, + }; + let extensions = Extensions::try_from(&cbor_extensions); + let mut expected_extensions = Extensions(BTreeMap::new()); + expected_extensions + .0 + .insert("the_answer".to_string(), cbor_int!(42)); + assert_eq!(extensions, Ok(expected_extensions)); + } + + #[test] + fn test_from_make_credential_options() { + let cbor_make_options = cbor_map! { + "rk" => true, + "uv" => false, + }; + let make_options = MakeCredentialOptions::try_from(&cbor_make_options); + let expected_make_options = MakeCredentialOptions { + rk: true, + uv: false, + }; + assert_eq!(make_options, Ok(expected_make_options)); + } + + #[test] + fn test_from_get_assertion_options() { + let cbor_get_assertion = cbor_map! { + "up" => true, + "uv" => false, + }; + let get_assertion = GetAssertionOptions::try_from(&cbor_get_assertion); + let expected_get_assertion = GetAssertionOptions { + up: true, + uv: false, + }; + assert_eq!(get_assertion, Ok(expected_get_assertion)); + } + + #[test] + fn test_into_packed_attestation_statement() { + let certificate: cbor::values::KeyType = cbor_bytes![vec![0x5C, 0x5C, 0x5C, 0x5C]]; + let cbor_packed_attestation_statement = cbor_map! { + "alg" => 1, + "sig" => vec![0x55, 0x55, 0x55, 0x55], + "x5c" => cbor_array_vec![vec![certificate]], + "ecdaaKeyId" => vec![0xEC, 0xDA, 0x1D], + }; + let packed_attestation_statement = PackedAttestationStatement { + alg: 1, + sig: vec![0x55, 0x55, 0x55, 0x55], + x5c: Some(vec![vec![0x5C, 0x5C, 0x5C, 0x5C]]), + ecdaa_key_id: Some(vec![0xEC, 0xDA, 0x1D]), + }; + let created_cbor: cbor::Value = packed_attestation_statement.into(); + assert_eq!(created_cbor, cbor_packed_attestation_statement); + } + + #[test] + fn test_from_into_cose_key() { + use crypto::rng256::ThreadRng256; + + let mut rng = ThreadRng256 {}; + let sk = crypto::ecdh::SecKey::gensk(&mut rng); + let pk = sk.genpk(); + let cose_key = CoseKey::from(pk.clone()); + let created_pk = ecdh::PubKey::try_from(cose_key); + assert_eq!(created_pk, Ok(pk)); + } + + #[test] + fn test_from_into_client_pin_sub_command() { + let cbor_sub_command = cbor_int!(0x01); + let sub_command = ClientPinSubCommand::try_from(&cbor_sub_command); + let expected_sub_command = ClientPinSubCommand::GetPinRetries; + assert_eq!(sub_command, Ok(expected_sub_command)); + let created_cbor: cbor::Value = sub_command.unwrap().into(); + assert_eq!(created_cbor, cbor_sub_command); + } + + #[test] + fn test_credential_source_cbor_round_trip() { + use crypto::rng256::{Rng256, ThreadRng256}; + + let mut rng = ThreadRng256 {}; + let credential = PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id: rng.gen_uniform_u8x32().to_vec(), + private_key: crypto::ecdsa::SecKey::gensk(&mut rng), + rp_id: "example.com".to_string(), + user_handle: b"foo".to_vec(), + other_ui: None, + }; + + assert_eq!( + PublicKeyCredentialSource::try_from(cbor::Value::from(credential.clone())), + Ok(credential.clone()) + ); + + let credential = PublicKeyCredentialSource { + other_ui: Some("other".to_string()), + ..credential + }; + + assert_eq!( + PublicKeyCredentialSource::try_from(cbor::Value::from(credential.clone())), + Ok(credential) + ); + } + + #[test] + fn test_credential_source_invalid_cbor() { + assert!(PublicKeyCredentialSource::try_from(cbor_false!()).is_err()); + assert!(PublicKeyCredentialSource::try_from(cbor_array!(false)).is_err()); + assert!(PublicKeyCredentialSource::try_from(cbor_array!(b"foo".to_vec())).is_err()); + } +} diff --git a/src/ctap/hid/mod.rs b/src/ctap/hid/mod.rs new file mode 100644 index 0000000..53e0ad6 --- /dev/null +++ b/src/ctap/hid/mod.rs @@ -0,0 +1,596 @@ +// Copyright 2019 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. + +mod receive; +mod send; + +use self::receive::MessageAssembler; +use self::send::HidPacketIterator; +#[cfg(feature = "with_ctap1")] +use super::ctap1; +use super::status_code::Ctap2StatusCode; +use super::timed_permission::TimedPermission; +use super::CtapState; +use crate::timer::{ClockValue, Duration, Timestamp}; +use alloc::vec::Vec; +#[cfg(feature = "debug_ctap")] +use core::fmt::Write; +use crypto::rng256::Rng256; +#[cfg(feature = "debug_ctap")] +use libtock::console::Console; + +// CTAP specification (version 20190130) section 8.1 +// TODO: Channel allocation, section 8.1.3? +// TODO: Transaction timeout, section 8.1.5.2 + +pub type HidPacket = [u8; 64]; +pub type ChannelID = [u8; 4]; + +pub enum ProcessedPacket<'a> { + InitPacket { + cmd: u8, + len: usize, + data: &'a [u8; 57], + }, + ContinuationPacket { + seq: u8, + data: &'a [u8; 59], + }, +} + +// An assembled CTAPHID command. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Message { + // Channel ID. + pub cid: ChannelID, + // Command. + pub cmd: u8, + // Bytes of the message. + pub payload: Vec, +} + +pub struct CtapHid { + assembler: MessageAssembler, + // The specification (version 20190130) only requires unique CIDs ; the allocation algorithm is + // vendor specific. + // We allocate them incrementally, that is all `cid` such that 1 <= cid <= allocated_cids are + // allocated. + // In packets, the ids are then encoded with the native endianness (with the + // u32::to/from_ne_bytes methods). + allocated_cids: usize, + pub wink_permission: TimedPermission, +} + +#[allow(dead_code)] +pub enum KeepaliveStatus { + Processing, + UpNeeded, +} + +#[allow(dead_code)] +// TODO(kaczmarczyck) disable the warning in the end +impl CtapHid { + // CTAP specification (version 20190130) section 8.1.3 + const CHANNEL_RESERVED: ChannelID = [0, 0, 0, 0]; + const CHANNEL_BROADCAST: ChannelID = [0xFF, 0xFF, 0xFF, 0xFF]; + const TYPE_INIT_BIT: u8 = 0x80; + const PACKET_TYPE_MASK: u8 = 0x80; + + // CTAP specification (version 20190130) section 8.1.9 + const COMMAND_PING: u8 = 0x01; + const COMMAND_MSG: u8 = 0x03; + const COMMAND_INIT: u8 = 0x06; + const COMMAND_CBOR: u8 = 0x10; + pub const COMMAND_CANCEL: u8 = 0x11; + const COMMAND_KEEPALIVE: u8 = 0x3B; + const COMMAND_ERROR: u8 = 0x3F; + // TODO: optional lock command + const COMMAND_LOCK: u8 = 0x04; + const COMMAND_WINK: u8 = 0x08; + const COMMAND_VENDOR_FIRST: u8 = 0x40; + const COMMAND_VENDOR_LAST: u8 = 0x7F; + + // CTAP specification (version 20190130) section 8.1.9.1.6 + const ERR_INVALID_CMD: u8 = 0x01; + const ERR_INVALID_PAR: u8 = 0x02; + const ERR_INVALID_LEN: u8 = 0x03; + const ERR_INVALID_SEQ: u8 = 0x04; + const ERR_MSG_TIMEOUT: u8 = 0x05; + const ERR_CHANNEL_BUSY: u8 = 0x06; + const ERR_LOCK_REQUIRED: u8 = 0x0A; + const ERR_INVALID_CHANNEL: u8 = 0x0B; + const ERR_OTHER: u8 = 0x7F; + + // CTAP specification (version 20190130) section 8.1.9.1.3 + const PROTOCOL_VERSION: u8 = 2; + + // The device version number is vendor-defined. For now we define them to be zero. + // TODO: Update with device version? + const DEVICE_VERSION_MAJOR: u8 = 0; + const DEVICE_VERSION_MINOR: u8 = 0; + const DEVICE_VERSION_BUILD: u8 = 0; + + const CAPABILITY_WINK: u8 = 0x01; + const CAPABILITY_CBOR: u8 = 0x04; + const CAPABILITY_NMSG: u8 = 0x08; + // Capabilitites currently supported by this device. + #[cfg(feature = "with_ctap1")] + const CAPABILITIES: u8 = CtapHid::CAPABILITY_WINK | CtapHid::CAPABILITY_CBOR; + #[cfg(not(feature = "with_ctap1"))] + const CAPABILITIES: u8 = + CtapHid::CAPABILITY_WINK | CtapHid::CAPABILITY_CBOR | CtapHid::CAPABILITY_NMSG; + + // TODO: Is this timeout duration specified? + const TIMEOUT_DURATION: Duration = Duration::from_ms(100); + const WINK_TIMEOUT_DURATION: Duration = Duration::from_ms(5000); + + pub fn new() -> CtapHid { + CtapHid { + assembler: MessageAssembler::new(), + allocated_cids: 0, + wink_permission: TimedPermission::waiting(), + } + } + + // Process an incoming USB HID packet, and optionally returns a list of outgoing packets to + // send as a reply. + pub fn process_hid_packet( + &mut self, + packet: &HidPacket, + clock_value: ClockValue, + ctap_state: &mut CtapState, + ) -> HidPacketIterator + where + R: Rng256, + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, + { + // TODO: Send COMMAND_KEEPALIVE every 100ms? + match self + .assembler + .parse_packet(packet, Timestamp::::from_clock_value(clock_value)) + { + Ok(Some(message)) => { + #[cfg(feature = "debug_ctap")] + writeln!(&mut Console::new(), "Received message: {:02x?}", message).unwrap(); + + let cid = message.cid; + if !self.has_valid_channel(&message) { + #[cfg(feature = "debug_ctap")] + writeln!(&mut Console::new(), "Invalid channel: {:02x?}", cid).unwrap(); + return CtapHid::error_message(cid, CtapHid::ERR_INVALID_CHANNEL); + } + // If another command arrives, stop winking to prevent accidential button touches. + self.wink_permission = TimedPermission::waiting(); + + match message.cmd { + // CTAP specification (version 20190130) section 8.1.9.1.1 + CtapHid::COMMAND_MSG => { + // If we don't have CTAP1 backward compatibilty, this command in invalid. + #[cfg(not(feature = "with_ctap1"))] + return CtapHid::error_message(cid, CtapHid::ERR_INVALID_CMD); + + #[cfg(feature = "with_ctap1")] + match ctap1::Ctap1Command::process_command( + &message.payload, + ctap_state, + clock_value, + ) { + Ok(payload) => CtapHid::ctap1_success_message(cid, &payload), + Err(ctap1_status_code) => { + CtapHid::ctap1_error_message(cid, ctap1_status_code) + } + } + } + // CTAP specification (version 20190130) section 8.1.9.1.2 + CtapHid::COMMAND_CBOR => { + // CTAP specification (version 20190130) section 8.1.5.1 + // Each transaction is atomic, so we process the command directly here and + // don't handle any other packet in the meantime. + // TODO: Send keep-alive packets in the meantime. + let response = ctap_state.process_command(&message.payload, cid); + if let Some(iterator) = CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_CBOR, + payload: response, + }) { + iterator + } else { + // Handle the case of a payload > 7609 bytes. + // Although this shouldn't happen if the FIDO2 commands are implemented + // correctly, we reply with a vendor specific code instead of silently + // ignoring the error. + // + // The error payload that we send instead is 1 <= 7609 bytes, so it is + // safe to unwrap() the result. + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_CBOR, + payload: vec![ + Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG as u8, + ], + }) + .unwrap() + } + } + // CTAP specification (version 20190130) section 8.1.9.1.3 + CtapHid::COMMAND_INIT => { + if cid == CtapHid::CHANNEL_BROADCAST { + if message.payload.len() != 8 { + return CtapHid::error_message(cid, CtapHid::ERR_INVALID_LEN); + } + + // TODO: Prevent allocating 2^32 channels. + self.allocated_cids += 1; + let allocated_cid = (self.allocated_cids as u32).to_ne_bytes(); + + let mut payload = vec![0; 17]; + payload[..8].copy_from_slice(&message.payload); + payload[8..12].copy_from_slice(&allocated_cid); + payload[12] = CtapHid::PROTOCOL_VERSION; + payload[13] = CtapHid::DEVICE_VERSION_MAJOR; + payload[14] = CtapHid::DEVICE_VERSION_MINOR; + payload[15] = CtapHid::DEVICE_VERSION_BUILD; + payload[16] = CtapHid::CAPABILITIES; + + // This unwrap is safe because the payload length is 17 <= 7609 bytes. + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_INIT, + payload, + }) + .unwrap() + } else { + // Sync the channel and discard the current transaction. + // TODO: The specification (version 20190130) wording isn't clear about + // the payload format in this case. + // + // This unwrap is safe because the payload length is 0 <= 7609 bytes. + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_INIT, + payload: vec![], + }) + .unwrap() + } + } + // CTAP specification (version 20190130) section 8.1.9.1.4 + CtapHid::COMMAND_PING => { + // Pong the same message. + // This unwrap is safe because if we could parse the incoming message, it's + // payload length must be <= 7609 bytes. + CtapHid::split_message(message).unwrap() + } + // CTAP specification (version 20190130) section 8.1.9.1.5 + CtapHid::COMMAND_CANCEL => { + // Authenticators MUST NOT reply to this message. + // CANCEL is handled during user presence checks in main. + HidPacketIterator::none() + } + // Optional commands + // CTAP specification (version 20190130) section 8.1.9.2.1 + CtapHid::COMMAND_WINK => { + if !message.payload.is_empty() { + return CtapHid::error_message(cid, CtapHid::ERR_INVALID_LEN); + } + self.wink_permission = + TimedPermission::granted(clock_value, CtapHid::WINK_TIMEOUT_DURATION); + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_WINK, + payload: vec![], + }) + .unwrap() + } + // CTAP specification (version 20190130) section 8.1.9.2.2 + // TODO: implement LOCK + _ => { + // Unknown or unsupported command. + CtapHid::error_message(cid, CtapHid::ERR_INVALID_CMD) + } + } + } + Ok(None) => { + // Waiting for more packets to assemble the message, nothing to send for now. + HidPacketIterator::none() + } + Err((cid, error)) => { + if !self.is_allocated_channel(cid) { + CtapHid::error_message(cid, CtapHid::ERR_INVALID_CHANNEL) + } else { + match error { + receive::Error::UnexpectedChannel => { + CtapHid::error_message(cid, CtapHid::ERR_CHANNEL_BUSY) + } + receive::Error::UnexpectedInit => { + // TODO: Should we send another error code in this case? + // Technically, we were expecting a sequence number and got another + // byte, although the command/seqnum bit has higher-level semantics + // than sequence numbers. + CtapHid::error_message(cid, CtapHid::ERR_INVALID_SEQ) + } + receive::Error::UnexpectedContinuation => { + // CTAP specification (version 20190130) section 8.1.5.4 + // Spurious continuation packets will be ignored. + HidPacketIterator::none() + } + receive::Error::UnexpectedSeq => { + CtapHid::error_message(cid, CtapHid::ERR_INVALID_SEQ) + } + receive::Error::Timeout => { + CtapHid::error_message(cid, CtapHid::ERR_MSG_TIMEOUT) + } + } + } + } + } + } + + fn has_valid_channel(&self, message: &Message) -> bool { + match message.cid { + // Only INIT commands use the broadcast channel. + CtapHid::CHANNEL_BROADCAST => message.cmd == CtapHid::COMMAND_INIT, + // Check that the channel is allocated. + _ => self.is_allocated_channel(message.cid), + } + } + + fn is_allocated_channel(&self, cid: ChannelID) -> bool { + cid != CtapHid::CHANNEL_RESERVED && u32::from_ne_bytes(cid) as usize <= self.allocated_cids + } + + fn error_message(cid: ChannelID, error_code: u8) -> HidPacketIterator { + // This unwrap is safe because the payload length is 1 <= 7609 bytes. + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_ERROR, + payload: vec![error_code], + }) + .unwrap() + } + + pub fn process_single_packet(packet: &HidPacket) -> (&ChannelID, ProcessedPacket) { + let (cid, rest) = array_refs![packet, 4, 60]; + if rest[0] & CtapHid::PACKET_TYPE_MASK != 0 { + let cmd = rest[0] & !CtapHid::PACKET_TYPE_MASK; + let len = (rest[1] as usize) << 8 | (rest[2] as usize); + ( + cid, + ProcessedPacket::InitPacket { + cmd, + len, + data: array_ref!(rest, 3, 57), + }, + ) + } else { + ( + cid, + ProcessedPacket::ContinuationPacket { + seq: rest[0], + data: array_ref!(rest, 1, 59), + }, + ) + } + } + + fn split_message(message: Message) -> Option { + #[cfg(feature = "debug_ctap")] + writeln!(&mut Console::new(), "Sending message: {:02x?}", message).unwrap(); + HidPacketIterator::new(message) + } + + pub fn keepalive(cid: ChannelID, status: KeepaliveStatus) -> HidPacketIterator { + let status_code = match status { + KeepaliveStatus::Processing => 1, + KeepaliveStatus::UpNeeded => 2, + }; + // This unwrap is safe because the payload length is 1 <= 7609 bytes. + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_KEEPALIVE, + payload: vec![status_code], + }) + .unwrap() + } + + #[cfg(feature = "with_ctap1")] + fn ctap1_error_message( + cid: ChannelID, + error_code: ctap1::Ctap1StatusCode, + ) -> HidPacketIterator { + // This unwrap is safe because the payload length is 2 <= 7609 bytes + let code: u16 = error_code.into(); + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_MSG, + payload: code.to_be_bytes().to_vec(), + }) + .unwrap() + } + + #[cfg(feature = "with_ctap1")] + fn ctap1_success_message(cid: ChannelID, payload: &[u8]) -> HidPacketIterator { + let mut response = payload.to_vec(); + let code: u16 = ctap1::Ctap1StatusCode::SW_NO_ERROR.into(); + response.extend_from_slice(&code.to_be_bytes()); + CtapHid::split_message(Message { + cid, + cmd: CtapHid::COMMAND_MSG, + payload: response, + }) + .unwrap() + } +} + +#[cfg(test)] +mod test { + use super::*; + use crypto::rng256::ThreadRng256; + + const CLOCK_FREQUENCY_HZ: usize = 32768; + // Except for tests for timeouts (done in ctap1.rs), transactions are time independant. + const DUMMY_CLOCK_VALUE: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ); + const DUMMY_TIMESTAMP: Timestamp = Timestamp::from_ms(0); + + fn process_messages( + ctap_hid: &mut CtapHid, + ctap_state: &mut CtapState, + request: Vec, + ) -> Option> + where + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, + { + let mut result = Vec::new(); + let mut assembler_reply = MessageAssembler::new(); + for msg_request in request { + for pkt_request in HidPacketIterator::new(msg_request).unwrap() { + for pkt_reply in + ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, ctap_state) + { + match assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP) { + Ok(Some(message)) => result.push(message), + Ok(None) => (), + Err(_) => return None, + } + } + } + } + Some(result) + } + + fn cid_from_init( + ctap_hid: &mut CtapHid, + ctap_state: &mut CtapState, + ) -> ChannelID + where + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, + { + let nonce = vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]; + let reply = process_messages( + ctap_hid, + ctap_state, + vec![Message { + cid: CtapHid::CHANNEL_BROADCAST, + cmd: CtapHid::COMMAND_INIT, + payload: nonce.clone(), + }], + ); + + let mut cid_in_payload: ChannelID = Default::default(); + if let Some(messages) = reply { + assert_eq!(messages.len(), 1); + assert!(messages[0].payload.len() >= 12); + assert_eq!(nonce, &messages[0].payload[..8]); + cid_in_payload.copy_from_slice(&messages[0].payload[8..12]); + } else { + panic!("The init process was not successful to generate a valid channel ID.") + } + cid_in_payload + } + + #[test] + fn test_split_assemble() { + for payload_len in 0..7609 { + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x00, + payload: vec![0xFF; payload_len], + }; + + let mut messages = Vec::new(); + let mut assembler = MessageAssembler::new(); + for packet in HidPacketIterator::new(message.clone()).unwrap() { + match assembler.parse_packet(&packet, DUMMY_TIMESTAMP) { + Ok(Some(msg)) => messages.push(msg), + Ok(None) => (), + Err(_) => panic!("Couldn't assemble packet: {:02x?}", &packet as &[u8]), + } + } + + assert_eq!(messages, vec![message]); + } + } + + #[test] + fn test_command_init() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + let mut ctap_hid = CtapHid::new(); + + let reply = process_messages( + &mut ctap_hid, + &mut ctap_state, + vec![Message { + cid: CtapHid::CHANNEL_BROADCAST, + cmd: CtapHid::COMMAND_INIT, + payload: vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0], + }], + ); + + assert_eq!( + reply, + Some(vec![Message { + cid: CtapHid::CHANNEL_BROADCAST, + cmd: CtapHid::COMMAND_INIT, + payload: vec![ + 0x12, // Nonce + 0x34, + 0x56, + 0x78, + 0x9A, + 0xBC, + 0xDE, + 0xF0, + 0x01, // Allocated CID + 0x00, + 0x00, + 0x00, + 0x02, // Protocol version + 0x00, // Device version + 0x00, + 0x00, + CtapHid::CAPABILITIES + ] + }]) + ); + } + + #[test] + fn test_command_ping() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + let mut ctap_hid = CtapHid::new(); + let cid = cid_from_init(&mut ctap_hid, &mut ctap_state); + + let reply = process_messages( + &mut ctap_hid, + &mut ctap_state, + vec![Message { + cid, + cmd: CtapHid::COMMAND_PING, + payload: vec![0x99, 0x99], + }], + ); + + assert_eq!( + reply, + Some(vec![Message { + cid, + cmd: CtapHid::COMMAND_PING, + payload: vec![0x99, 0x99] + }]) + ); + } +} diff --git a/src/ctap/hid/receive.rs b/src/ctap/hid/receive.rs new file mode 100644 index 0000000..ae2e707 --- /dev/null +++ b/src/ctap/hid/receive.rs @@ -0,0 +1,590 @@ +// Copyright 2019 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. + +use super::{ChannelID, CtapHid, HidPacket, Message, ProcessedPacket}; +use crate::timer::Timestamp; +use alloc::vec::Vec; +use core::mem::swap; + +// A structure to assemble CTAPHID commands from a series of incoming USB HID packets. +pub struct MessageAssembler { + // Whether this is waiting to receive an initialization packet. + idle: bool, + // Current channel ID. + cid: ChannelID, + // Timestamp of the last packet received on the current channel. + last_timestamp: Timestamp, + // Current command. + cmd: u8, + // Sequence number expected for the next packet. + seq: u8, + // Number of bytes left to fill the current message. + remaining_payload_len: usize, + // Buffer for the current payload. + payload: Vec, +} + +#[derive(PartialEq, Debug)] +pub enum Error { + // Expected a continuation packet on a specific channel, got a packet on another channel. + UnexpectedChannel, + // Expected a continuation packet, got an init packet. + UnexpectedInit, + // Expected an init packet, got a continuation packet. + UnexpectedContinuation, + // Expected a continuation packet with a specific sequence number, got another sequence number. + UnexpectedSeq, + // This packet arrived after a timeout. + Timeout, +} + +impl MessageAssembler { + pub fn new() -> MessageAssembler { + MessageAssembler { + idle: true, + cid: [0, 0, 0, 0], + last_timestamp: Timestamp::from_ms(0), + cmd: 0, + seq: 0, + remaining_payload_len: 0, + payload: Vec::new(), + } + } + + // Resets the message assembler to the idle state. + // The caller can reset the assembler for example due to a timeout. + pub fn reset(&mut self) { + self.idle = true; + self.cid = [0, 0, 0, 0]; + self.last_timestamp = Timestamp::from_ms(0); + self.cmd = 0; + self.seq = 0; + self.remaining_payload_len = 0; + self.payload.clear(); + } + + // Returns: + // - An Ok() result if the packet was parsed correctly. This contains either Some(Vec) if a + // full message was assembled after this packet, or None if more packets are needed to fill the + // message. + // - An Err() result if there was a parsing error. + // TODO: Implement timeouts. For example, have the caller pass us a timestamp of when this + // packet was received. + pub fn parse_packet( + &mut self, + packet: &HidPacket, + timestamp: Timestamp, + ) -> Result, (ChannelID, Error)> { + // TODO: Support non-full-speed devices (i.e. packet len != 64)? This isn't recommended by + // section 8.8.1 + let (cid, processed_packet) = CtapHid::process_single_packet(&packet); + + if !self.idle && timestamp - self.last_timestamp >= CtapHid::TIMEOUT_DURATION { + // The current channel timed out. + // Save the channel ID and reset the state. + let current_cid = self.cid; + self.reset(); + + // If the packet is from the timed-out channel, send back a timeout error. + // Otherwise, proceed with processing the packet. + if *cid == current_cid { + return Err((*cid, Error::Timeout)); + } + } + + if self.idle { + // Expecting an initialization packet. + match processed_packet { + ProcessedPacket::InitPacket { cmd, len, data } => { + Ok(self.accept_init_packet(*cid, cmd, len, data, timestamp)) + } + ProcessedPacket::ContinuationPacket { .. } => { + // CTAP specification (version 20190130) section 8.1.5.4 + // Spurious continuation packets will be ignored. + Err((*cid, Error::UnexpectedContinuation)) + } + } + } else { + // Expecting a continuation packet from the current channel. + + // CTAP specification (version 20190130) section 8.1.5.1 + // Reject packets from other channels. + if *cid != self.cid { + return Err((*cid, Error::UnexpectedChannel)); + } + + match processed_packet { + // Unexpected initialization packet. + ProcessedPacket::InitPacket { cmd, len, data } => { + self.reset(); + if cmd == CtapHid::COMMAND_INIT { + Ok(self.accept_init_packet(*cid, cmd, len, data, timestamp)) + } else { + Err((*cid, Error::UnexpectedInit)) + } + } + ProcessedPacket::ContinuationPacket { seq, data } => { + if seq != self.seq { + // Reject packets with the wrong sequence number. + self.reset(); + Err((*cid, Error::UnexpectedSeq)) + } else { + // Update the last timestamp. + self.last_timestamp = timestamp; + // Increment the sequence number for the next packet. + self.seq += 1; + Ok(self.append_payload(data)) + } + } + } + } + } + + fn accept_init_packet( + &mut self, + cid: ChannelID, + cmd: u8, + len: usize, + data: &[u8], + timestamp: Timestamp, + ) -> Option { + // TODO: Should invalid commands/payload lengths be rejected early, i.e. as soon as the + // initialization packet is received, or should we build a message and then catch the + // error? + // The specification (version 20190130) isn't clear on this point. + self.cid = cid; + self.last_timestamp = timestamp; + self.cmd = cmd; + self.seq = 0; + self.remaining_payload_len = len; + self.append_payload(data) + } + + fn append_payload(&mut self, data: &[u8]) -> Option { + if data.len() < self.remaining_payload_len { + self.payload.extend_from_slice(data); + self.idle = false; + self.remaining_payload_len -= data.len(); + None + } else { + self.payload + .extend_from_slice(&data[..self.remaining_payload_len]); + self.idle = true; + let mut payload = Vec::new(); + swap(&mut self.payload, &mut payload); + Some(Message { + cid: self.cid, + cmd: self.cmd, + payload, + }) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::timer::Duration; + + // Except for tests that exercise timeouts, all packets are synchronized at the same dummy + // timestamp. + const DUMMY_TIMESTAMP: Timestamp = Timestamp::from_ms(0); + + fn byte_extend(bytes: &[u8], padding: u8) -> HidPacket { + let len = bytes.len(); + assert!(len <= 64); + let mut result = [0; 64]; + result[..len].copy_from_slice(bytes); + for byte in result[len..].iter_mut() { + *byte = padding; + } + result + } + + fn zero_extend(bytes: &[u8]) -> HidPacket { + byte_extend(bytes, 0) + } + + #[test] + fn test_empty_payload() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x80]), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x00, + payload: vec![] + })) + ); + } + + #[test] + fn test_one_packet() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x80, 0x00, 0x10]), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x00, + payload: vec![0x00; 0x10] + })) + ); + } + + #[test] + fn test_nonzero_padding() { + // CTAP specification (version 20190130) section 8.1.4 + // It is written that "Unused bytes SHOULD be set to zero", so we test that non-zero + // padding is accepted as well. + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x80, 0x00, 0x10], 0xFF), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x00, + payload: vec![0xFF; 0x10] + })) + ); + } + + #[test] + fn test_two_packets() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x01, + payload: vec![0x00; 0x40] + })) + ); + } + + #[test] + fn test_three_packets() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x80]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x01]), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x01, + payload: vec![0x00; 0x80] + })) + ); + } + + #[test] + fn test_max_packets() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x1D, 0xB9]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + for seq in 0..0x7F { + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + } + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x7F]), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x01, + payload: vec![0x00; 0x1DB9] + })) + ); + } + + #[test] + fn test_multiple_messages() { + // Check that after yielding a message, the assembler is ready to process new messages. + let mut assembler = MessageAssembler::new(); + for i in 0..10 { + // Introduce some variability in the messages. + let cmd = 2 * i; + let byte = 3 * i; + + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x80 | cmd, 0x00, 0x80], byte), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x00], byte), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x01], byte), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd, + payload: vec![byte; 0x80] + })) + ); + } + } + + #[test] + fn test_channel_switch() { + // Check that the assembler can process messages from multiple channels, sequentially. + let mut assembler = MessageAssembler::new(); + for i in 0..10 { + // Introduce some variability in the messages. + let cid = 0x78 + i; + let cmd = 2 * i; + let byte = 3 * i; + + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, cid, 0x80 | cmd, 0x00, 0x80], byte), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, cid, 0x00], byte), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, cid, 0x01], byte), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, cid], + cmd, + payload: vec![byte; 0x80] + })) + ); + } + } + + #[test] + fn test_unexpected_channel() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + + // Check that many sorts of packets on another channel are ignored. + for cmd in 0..=0xFF { + for byte in 0..=0xFF { + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, 0x9A, cmd, 0x00], byte), + DUMMY_TIMESTAMP + ), + Err(([0x12, 0x34, 0x56, 0x9A], Error::UnexpectedChannel)) + ); + } + } + + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x01, + payload: vec![0x00; 0x40] + })) + ); + } + + #[test] + fn test_spurious_continuation_packets() { + // CTAP specification (version 20190130) section 8.1.5.4 + // Spurious continuation packets appearing without a prior initialization packet will be + // ignored. + let mut assembler = MessageAssembler::new(); + for i in 0..0x80 { + // Some legit packet. + let byte = 2 * i; + assert_eq!( + assembler.parse_packet( + &byte_extend(&[0x12, 0x34, 0x56, 0x78, 0x80, 0x00, 0x10], byte), + DUMMY_TIMESTAMP + ), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x00, + payload: vec![byte; 0x10] + })) + ); + + // Spurious continuation packet. + let seq = i; + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]), + DUMMY_TIMESTAMP + ), + Err(([0x12, 0x34, 0x56, 0x78], Error::UnexpectedContinuation)) + ); + } + } + + #[test] + fn test_unexpected_init() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x80]), + DUMMY_TIMESTAMP + ), + Err(([0x12, 0x34, 0x56, 0x78], Error::UnexpectedInit)) + ); + } + + #[test] + fn test_unexpected_seq() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x01]), + DUMMY_TIMESTAMP + ), + Err(([0x12, 0x34, 0x56, 0x78], Error::UnexpectedSeq)) + ); + } + + #[test] + fn test_timed_out_packet() { + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x00, 0x40]), + DUMMY_TIMESTAMP + ), + Ok(None) + ); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x00]), + DUMMY_TIMESTAMP + CtapHid::TIMEOUT_DURATION + ), + Err(([0x12, 0x34, 0x56, 0x78], Error::Timeout)) + ); + } + + #[test] + fn test_just_in_time_packets() { + let mut timestamp = DUMMY_TIMESTAMP; + // Delay between each packet is just below the threshold. + let delay = CtapHid::TIMEOUT_DURATION - Duration::from_ms(1); + + let mut assembler = MessageAssembler::new(); + assert_eq!( + assembler.parse_packet( + &zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x81, 0x1D, 0xB9]), + timestamp + ), + Ok(None) + ); + for seq in 0..0x7F { + timestamp += delay; + assert_eq!( + assembler.parse_packet(&zero_extend(&[0x12, 0x34, 0x56, 0x78, seq]), timestamp), + Ok(None) + ); + } + timestamp += delay; + assert_eq!( + assembler.parse_packet(&zero_extend(&[0x12, 0x34, 0x56, 0x78, 0x7F]), timestamp), + Ok(Some(Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x01, + payload: vec![0x00; 0x1DB9] + })) + ); + } + + // TODO: more tests +} diff --git a/src/ctap/hid/send.rs b/src/ctap/hid/send.rs new file mode 100644 index 0000000..434d633 --- /dev/null +++ b/src/ctap/hid/send.rs @@ -0,0 +1,296 @@ +// Copyright 2019 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. + +use super::{CtapHid, HidPacket, Message}; + +pub struct HidPacketIterator(Option); + +impl HidPacketIterator { + pub fn new(message: Message) -> Option { + let splitter = MessageSplitter::new(message); + if splitter.is_some() { + Some(HidPacketIterator(splitter)) + } else { + None + } + } + + pub fn none() -> HidPacketIterator { + HidPacketIterator(None) + } +} + +impl Iterator for HidPacketIterator { + type Item = HidPacket; + + fn next(&mut self) -> Option { + match &mut self.0 { + Some(splitter) => splitter.next(), + None => None, + } + } +} + +pub struct MessageSplitter { + message: Message, + packet: HidPacket, + seq: Option, + i: usize, +} + +impl MessageSplitter { + // Try to split this message into an iterator of HID packets. This fails if the message is too + // long to fit into a sequence of HID packets (which is limited to 7609 bytes). + pub fn new(message: Message) -> Option { + if message.payload.len() > 7609 { + None + } else { + // Cache the CID, as it is constant for all packets in this message. + let mut packet = [0; 64]; + packet[..4].copy_from_slice(&message.cid); + + Some(MessageSplitter { + message, + packet, + seq: None, + i: 0, + }) + } + } + + // Copy as many bytes as possible from data to dst, and return how many bytes are copied. + // Contrary to copy_from_slice, this doesn't require slices of the same length. + // All unused bytes in dst are set to zero, as if the data was padded with zeros to match. + fn consume_data(dst: &mut [u8], data: &[u8]) -> usize { + let dst_len = dst.len(); + let data_len = data.len(); + + if data_len <= dst_len { + // data fits in dst, copy all the bytes. + dst[..data_len].copy_from_slice(data); + for byte in dst[data_len..].iter_mut() { + *byte = 0; + } + data_len + } else { + // Fill all of dst. + dst.copy_from_slice(&data[..dst_len]); + dst_len + } + } +} + +impl Iterator for MessageSplitter { + type Item = HidPacket; + + fn next(&mut self) -> Option { + let payload_len = self.message.payload.len(); + match self.seq { + None => { + // First, send an initialization packet. + self.packet[4] = self.message.cmd | CtapHid::TYPE_INIT_BIT; + self.packet[5] = (payload_len >> 8) as u8; + self.packet[6] = payload_len as u8; + + self.seq = Some(0); + self.i = + MessageSplitter::consume_data(&mut self.packet[7..], &self.message.payload); + Some(self.packet) + } + Some(seq) => { + // Send the next continuation packet, if any. + if self.i < payload_len { + self.packet[4] = seq; + self.seq = Some(seq + 1); + self.i += MessageSplitter::consume_data( + &mut self.packet[5..], + &self.message.payload[self.i..], + ); + Some(self.packet) + } else { + None + } + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + fn assert_packet_output_equality(message: Message, expected_packets: Vec) { + let packets: Vec = HidPacketIterator::new(message).unwrap().collect(); + assert_eq!(packets.len(), expected_packets.len()); + for (packet, expected_packet) in packets.iter().zip(expected_packets.iter()) { + assert_eq!(packet as &[u8], expected_packet as &[u8]); + } + } + + #[test] + fn test_hid_packet_iterator_single_packet() { + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x4C, + payload: vec![0xAA, 0xBB], + }; + let expected_packets: Vec = vec![[ + 0x12, 0x34, 0x56, 0x78, 0xCC, 0x00, 0x02, 0xAA, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]]; + assert_packet_output_equality(message, expected_packets); + } + + #[test] + fn test_hid_packet_iterator_big_single_packet() { + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x4C, + payload: vec![0xAA; 64 - 7], + }; + let expected_packets: Vec = vec![[ + 0x12, 0x34, 0x56, 0x78, 0xCC, 0x00, 0x39, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + ]]; + assert_packet_output_equality(message, expected_packets); + } + + #[test] + fn test_hid_packet_iterator_two_packets() { + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x4C, + payload: vec![0xAA; 64 - 7 + 1], + }; + let expected_packets: Vec = vec![ + [ + 0x12, 0x34, 0x56, 0x78, 0xCC, 0x00, 0x3A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + ], + [ + 0x12, 0x34, 0x56, 0x78, 0x00, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ], + ]; + assert_packet_output_equality(message, expected_packets); + } + + #[test] + fn test_hid_packet_iterator_two_full_packets() { + let mut payload = vec![0xAA; 64 - 7]; + payload.extend(vec![0xBB; 64 - 5]); + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0x4C, + payload, + }; + let expected_packets: Vec = vec![ + [ + 0x12, 0x34, 0x56, 0x78, 0xCC, 0x00, 0x74, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + ], + [ + 0x12, 0x34, 0x56, 0x78, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + ], + ]; + assert_packet_output_equality(message, expected_packets); + } + + #[test] + fn test_hid_packet_iterator_max_packets() { + let mut payload = vec![0xFF; 64 - 7]; + for i in 0..128 { + payload.extend(vec![i + 1; 64 - 5]); + } + + // Sanity check for the length of the payload. + assert_eq!((64 - 7) + 128 * (64 - 5), 0x1db9); + assert_eq!(7609, 0x1db9); + assert_eq!(payload.len(), 0x1db9); + + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0xAB, + payload, + }; + + let mut expected_packets = Vec::new(); + expected_packets.push([ + 0x12, 0x34, 0x56, 0x78, 0xAB, 0x1D, 0xB9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ]); + for i in 0..128 { + let mut packet: HidPacket = [0; 64]; + packet[0] = 0x12; + packet[1] = 0x34; + packet[2] = 0x56; + packet[3] = 0x78; + packet[4] = i; + for byte in packet.iter_mut().skip(5) { + *byte = i + 1; + } + expected_packets.push(packet); + } + + assert_packet_output_equality(message, expected_packets); + } + + #[test] + fn test_hid_packet_iterator_payload_one_too_large() { + let payload = vec![0xFF; (64 - 7) + 128 * (64 - 5) + 1]; + assert_eq!(payload.len(), 0x1dba); + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0xAB, + payload, + }; + assert!(HidPacketIterator::new(message).is_none()); + } + + #[test] + fn test_hid_packet_iterator_payload_way_too_large() { + // Check that overflow of u16 doesn't bypass the size limit. + let payload = vec![0xFF; 0x10000]; + let message = Message { + cid: [0x12, 0x34, 0x56, 0x78], + cmd: 0xAB, + payload, + }; + assert!(HidPacketIterator::new(message).is_none()); + } + + // TODO(kaczmarczyck) implement and test limits (maximum bytes and packets) +} diff --git a/src/ctap/mod.rs b/src/ctap/mod.rs new file mode 100644 index 0000000..26740d5 --- /dev/null +++ b/src/ctap/mod.rs @@ -0,0 +1,1297 @@ +// Copyright 2019 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. + +pub mod command; +#[cfg(feature = "with_ctap1")] +mod ctap1; +pub mod data_formats; +pub mod hid; +mod key_material; +pub mod response; +pub mod status_code; +mod storage; +mod timed_permission; + +use self::command::{ + AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters, + AuthenticatorMakeCredentialParameters, Command, +}; +use self::data_formats::{ + ClientPinSubCommand, CoseKey, PackedAttestationStatement, PublicKeyCredentialDescriptor, + PublicKeyCredentialSource, PublicKeyCredentialType, PublicKeyCredentialUserEntity, + SignatureAlgorithm, +}; +use self::hid::ChannelID; +use self::key_material::{AAGUID, ATTESTATION_CERTIFICATE, ATTESTATION_PRIVATE_KEY}; +use self::response::{ + AuthenticatorClientPinResponse, AuthenticatorGetAssertionResponse, + AuthenticatorGetInfoResponse, AuthenticatorMakeCredentialResponse, ResponseData, +}; +use self::status_code::Ctap2StatusCode; +use self::storage::PersistentStore; +#[cfg(feature = "with_ctap1")] +use self::timed_permission::U2fUserPresenceState; +use alloc::collections::BTreeMap; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; +use byteorder::{BigEndian, ByteOrder}; +use core::convert::TryInto; +#[cfg(feature = "debug_ctap")] +use core::fmt::Write; +use crypto::cbc::{cbc_decrypt, cbc_encrypt}; +use crypto::hmac::{hmac_256, verify_hmac_256, verify_hmac_256_first_128bits}; +use crypto::rng256::Rng256; +use crypto::sha256::Sha256; +use crypto::Hash256; +#[cfg(feature = "debug_ctap")] +use libtock::console::Console; +use libtock::timer::{Duration, Timestamp}; +use subtle::ConstantTimeEq; + +// This flag enables or disables basic attestation for FIDO2. U2F is unaffected by +// this setting. The basic attestation uses the signing key from key_material.rs +// as a batch key. Turn it on if you want attestation. In this case, be aware that +// it is your responsibility to generate your own key material and keep it secret. +const USE_BATCH_ATTESTATION: bool = false; +// The signature counter is currently implemented as a global counter, if you set +// this flag to true. The spec strongly suggests to have per-credential-counters, +// but it means you can't have an infinite amount of credentials anymore. Also, +// since this is the only piece of information that needs writing often, we might +// need a flash storage friendly way to implement this feature. The implemented +// solution is a compromise to be compatible with U2F and not wasting storage. +const USE_SIGNATURE_COUNTER: bool = true; +// Those constants have to be multiples of 16, the AES block size. +const PIN_AUTH_LENGTH: usize = 16; +const PIN_TOKEN_LENGTH: usize = 32; +const PIN_PADDED_LENGTH: usize = 64; +// Our credential ID consists of +// - 16 byte initialization vector for AES-256, +// - 32 byte ECDSA private key for the credential, +// - 32 byte relying party ID hashed with SHA256, +// - 32 byte HMAC-SHA256 over everything else. +pub const ENCRYPTED_CREDENTIAL_ID_SIZE: usize = 112; +const UP_FLAG: u8 = 0x01; +const UV_FLAG: u8 = 0x04; +const AT_FLAG: u8 = 0x40; + +pub const TOUCH_TIMEOUT_MS: isize = 30000; +#[cfg(feature = "with_ctap1")] +const U2F_UP_PROMPT_TIMEOUT: Duration = Duration::from_ms(10000); +const RESET_TIMEOUT_MS: isize = 10000; + +pub const FIDO2_VERSION_STRING: &str = "FIDO_2_0"; +#[cfg(feature = "with_ctap1")] +pub const U2F_VERSION_STRING: &str = "U2F_V2"; + +fn check_pin_auth(hmac_key: &[u8], hmac_contents: &[u8], pin_auth: &[u8]) -> bool { + if pin_auth.len() != PIN_AUTH_LENGTH { + return false; + } + verify_hmac_256_first_128bits::( + hmac_key, + hmac_contents, + array_ref![pin_auth, 0, PIN_AUTH_LENGTH], + ) +} + +// This function is adapted from https://doc.rust-lang.org/nightly/src/core/str/mod.rs.html#2110 +// (as of 2020-01-20) and truncates to "max" bytes, not breaking the encoding. +// We change the return value, since we don't need the bool. +fn truncate_to_char_boundary(s: &str, mut max: usize) -> &str { + if max >= s.len() { + s + } else { + while !s.is_char_boundary(max) { + max -= 1; + } + &s[..max] + } +} + +// This struct currently holds all state, not only the persistent memory. The persistent members are +// in the persistent store field. +pub struct CtapState<'a, R: Rng256, CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>> +{ + rng: &'a mut R, + // A function to check user presence, ultimately returning true if user presence was detected, + // false otherwise. + check_user_presence: CheckUserPresence, + persistent_store: PersistentStore, + key_agreement_key: crypto::ecdh::SecKey, + pin_uv_auth_token: [u8; PIN_TOKEN_LENGTH], + consecutive_pin_mismatches: u64, + // This variable will be irreversibly set to false RESET_TIMEOUT_MS milliseconds after boot. + accepts_reset: bool, + #[cfg(feature = "with_ctap1")] + pub u2f_up_state: U2fUserPresenceState, +} + +impl<'a, R, CheckUserPresence> CtapState<'a, R, CheckUserPresence> +where + R: Rng256, + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, +{ + pub const PIN_PROTOCOL_VERSION: u64 = 1; + + pub fn new( + rng: &'a mut R, + check_user_presence: CheckUserPresence, + ) -> CtapState<'a, R, CheckUserPresence> { + let key_agreement_key = crypto::ecdh::SecKey::gensk(rng); + let pin_uv_auth_token = rng.gen_uniform_u8x32(); + let persistent_store = PersistentStore::new(rng); + CtapState { + rng, + check_user_presence, + persistent_store, + key_agreement_key, + pin_uv_auth_token, + consecutive_pin_mismatches: 0, + accepts_reset: true, + #[cfg(feature = "with_ctap1")] + u2f_up_state: U2fUserPresenceState::new( + U2F_UP_PROMPT_TIMEOUT, + Duration::from_ms(TOUCH_TIMEOUT_MS), + ), + } + } + + pub fn check_disable_reset(&mut self, timestamp: Timestamp) { + if timestamp - Timestamp::::from_ms(0) > Duration::from_ms(RESET_TIMEOUT_MS) { + self.accepts_reset = false; + } + } + + pub fn increment_global_signature_counter(&mut self) { + if USE_SIGNATURE_COUNTER { + self.persistent_store.incr_global_signature_counter(); + } + } + + // Encrypts the private key and relying party ID hash into a credential ID. Other + // information, such as a user name, are not stored, because encrypted credential IDs + // are used for credentials stored server-side. Also, we want the key handle to be + // compatible with U2F. + pub fn encrypt_key_handle( + &mut self, + private_key: crypto::ecdsa::SecKey, + application: &[u8; 32], + ) -> Vec { + let master_keys = self.persistent_store.master_keys(); + let aes_enc_key = crypto::aes256::EncryptionKey::new(master_keys.encryption); + let mut sk_bytes = [0; 32]; + private_key.to_bytes(&mut sk_bytes); + let mut iv = [0; 16]; + iv.copy_from_slice(&self.rng.gen_uniform_u8x32()[..16]); + + let mut blocks = [[0u8; 16]; 4]; + blocks[0].copy_from_slice(&sk_bytes[..16]); + blocks[1].copy_from_slice(&sk_bytes[16..]); + blocks[2].copy_from_slice(&application[..16]); + blocks[3].copy_from_slice(&application[16..]); + cbc_encrypt(&aes_enc_key, iv, &mut blocks); + + let mut encrypted_id = Vec::with_capacity(ENCRYPTED_CREDENTIAL_ID_SIZE); + encrypted_id.extend(&iv); + for b in &blocks { + encrypted_id.extend(b); + } + let id_hmac = hmac_256::(master_keys.hmac, &encrypted_id[..]); + encrypted_id.extend(&id_hmac); + encrypted_id + } + + // Decrypts a credential ID and writes the private key into a PublicKeyCredentialSource. + // None is returned if the HMAC test fails or the relying party does not match the + // decrypted relying party ID hash. + pub fn decrypt_credential_source( + &self, + credential_id: Vec, + rp_id_hash: &[u8], + ) -> Option { + if credential_id.len() != ENCRYPTED_CREDENTIAL_ID_SIZE { + return None; + } + let master_keys = self.persistent_store.master_keys(); + let payload_size = ENCRYPTED_CREDENTIAL_ID_SIZE - 32; + if !verify_hmac_256::( + master_keys.hmac, + &credential_id[..payload_size], + array_ref![credential_id, payload_size, 32], + ) { + return None; + } + let aes_enc_key = crypto::aes256::EncryptionKey::new(master_keys.encryption); + let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key); + let mut iv = [0; 16]; + iv.copy_from_slice(&credential_id[..16]); + let mut blocks = [[0u8; 16]; 4]; + for i in 0..4 { + blocks[i].copy_from_slice(&credential_id[16 * (i + 1)..16 * (i + 2)]); + } + + cbc_decrypt(&aes_dec_key, iv, &mut blocks); + let mut decrypted_sk = [0; 32]; + let mut decrypted_rp_id_hash = [0; 32]; + decrypted_sk[..16].clone_from_slice(&blocks[0]); + decrypted_sk[16..].clone_from_slice(&blocks[1]); + decrypted_rp_id_hash[..16].clone_from_slice(&blocks[2]); + decrypted_rp_id_hash[16..].clone_from_slice(&blocks[3]); + + if rp_id_hash != decrypted_rp_id_hash { + return None; + } + + let sk_option = crypto::ecdsa::SecKey::from_bytes(&decrypted_sk); + sk_option.map(|sk| PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id, + private_key: sk, + rp_id: String::from(""), + user_handle: vec![], + other_ui: None, + }) + } + + pub fn process_command(&mut self, command_cbor: &[u8], cid: ChannelID) -> Vec { + let cmd = Command::deserialize(command_cbor); + #[cfg(feature = "debug_ctap")] + writeln!(&mut Console::new(), "Received command: {:#?}", cmd).unwrap(); + match cmd { + Ok(command) => { + // Correct behavior between CTAP1 and CTAP2 isn't defined yet. Just a guess. + #[cfg(feature = "with_ctap1")] + { + self.u2f_up_state = U2fUserPresenceState::new( + U2F_UP_PROMPT_TIMEOUT, + Duration::from_ms(TOUCH_TIMEOUT_MS), + ); + } + let response = match command { + Command::AuthenticatorMakeCredential(params) => { + self.process_make_credential(params, cid) + } + Command::AuthenticatorGetAssertion(params) => { + self.process_get_assertion(params, cid) + } + Command::AuthenticatorGetInfo => self.process_get_info(), + Command::AuthenticatorClientPin(params) => self.process_client_pin(params), + Command::AuthenticatorReset => self.process_reset(cid), + // TODO(kaczmarczyck) implement GetNextAssertion and FIDO 2.1 commands + _ => unimplemented!(), + }; + #[cfg(feature = "debug_ctap")] + writeln!(&mut Console::new(), "Sending response: {:#?}", response).unwrap(); + match response { + Ok(response_data) => { + let mut response_vec = vec![0x00]; + if let Some(value) = response_data.into() { + if !cbor::write(value, &mut response_vec) { + response_vec = vec![ + Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_CANNOT_WRITE_CBOR + as u8, + ]; + } + } + response_vec + } + Err(error_code) => vec![error_code as u8], + } + } + Err(error_code) => vec![error_code as u8], + } + } + + fn process_make_credential( + &mut self, + make_credential_params: AuthenticatorMakeCredentialParameters, + cid: ChannelID, + ) -> Result { + let AuthenticatorMakeCredentialParameters { + client_data_hash, + rp, + user, + pub_key_cred_params, + exclude_list, + options, + pin_uv_auth_param, + pin_uv_auth_protocol, + .. + } = make_credential_params; + + if let Some(auth_param) = &pin_uv_auth_param { + // This case was added in FIDO 2.1. + if auth_param.is_empty() { + if self.persistent_store.pin_hash().is_none() { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); + } else { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID); + } + } + + match pin_uv_auth_protocol { + Some(protocol) => { + if protocol != CtapState::::PIN_PROTOCOL_VERSION { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + } + None => return Err(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER), + } + } + + let has_es_256 = pub_key_cred_params + .iter() + .any(|(credential_type, algorithm)| { + // Even though there is only one type now, checking seems safer in + // case of extension so you can't forget to update here. + *credential_type == PublicKeyCredentialType::PublicKey + && *algorithm == SignatureAlgorithm::ES256 as i64 + }); + if !has_es_256 { + return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); + } + + let rp_id = rp.rp_id; + if let Some(exclude_list) = exclude_list { + for cred_desc in exclude_list { + if self + .persistent_store + .find_credential(&rp_id, &cred_desc.key_id) + .is_some() + { + // Perform this check, so bad actors can't brute force exclude_list + // without user interaction. Discard the user presence check's outcome. + let _ = (self.check_user_presence)(cid); + return Err(Ctap2StatusCode::CTAP2_ERR_CREDENTIAL_EXCLUDED); + } + } + } + + // MakeCredential always requires user presence. + // User verification depends on the PIN auth inputs, which are checked here. + let flags = match pin_uv_auth_param { + Some(pin_auth) => { + if self.persistent_store.pin_hash().is_none() { + // Specification is unclear, could be CTAP2_ERR_INVALID_OPTION. + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); + } + if !check_pin_auth(&self.pin_uv_auth_token, &client_data_hash, &pin_auth) { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + UP_FLAG | UV_FLAG | AT_FLAG + } + None => { + if self.persistent_store.pin_hash().is_some() { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_REQUIRED); + } + if options.uv { + return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); + } + UP_FLAG | AT_FLAG + } + }; + + (self.check_user_presence)(cid)?; + + let sk = crypto::ecdsa::SecKey::gensk(self.rng); + let pk = sk.genpk(); + + let rp_id_hash = Sha256::hash(rp_id.as_bytes()); + let credential_id = if options.rk { + let random_id = self.rng.gen_uniform_u8x32().to_vec(); + let credential_source = PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id: random_id.clone(), + private_key: sk.clone(), + rp_id, + user_handle: user.user_id, + // This input is user provided, so we crop it to 64 byte for storage. + // The UTF8 encoding is always preserved, so the string might end up shorter. + other_ui: user + .user_display_name + .map(|s| truncate_to_char_boundary(&s, 64).to_string()), + }; + self.persistent_store.store_credential(credential_source)?; + random_id + } else { + self.encrypt_key_handle(sk.clone(), &rp_id_hash) + }; + + let mut auth_data = self.generate_auth_data(&rp_id_hash, flags); + auth_data.extend(&AAGUID); + // The length is fixed to 0x20 or 0x70 and fits one byte. + if credential_id.len() > 0xFF { + return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG); + } + auth_data.extend(vec![0x00, credential_id.len() as u8]); + auth_data.extend(&credential_id); + let cose_key = match pk.to_cose_key() { + Some(cose_key) => cose_key, + None => return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_CANNOT_WRITE_CBOR), + }; + auth_data.extend(cose_key); + + let mut signature_data = auth_data.clone(); + signature_data.extend(client_data_hash); + let (signature, x5c) = if USE_BATCH_ATTESTATION { + let attestation_key = + crypto::ecdsa::SecKey::from_bytes(&ATTESTATION_PRIVATE_KEY).unwrap(); + ( + attestation_key.sign_rfc6979::(&signature_data), + Some(vec![ATTESTATION_CERTIFICATE.to_vec()]), + ) + } else { + ( + sk.sign_rfc6979::(&signature_data), + None, + ) + }; + let attestation_statement = PackedAttestationStatement { + alg: SignatureAlgorithm::ES256 as i64, + sig: signature.to_asn1_der(), + x5c, + ecdaa_key_id: None, + }; + Ok(ResponseData::AuthenticatorMakeCredential( + AuthenticatorMakeCredentialResponse { + fmt: String::from("packed"), + auth_data, + att_stmt: attestation_statement, + }, + )) + } + + fn process_get_assertion( + &mut self, + get_assertion_params: AuthenticatorGetAssertionParameters, + cid: ChannelID, + ) -> Result { + let AuthenticatorGetAssertionParameters { + rp_id, + client_data_hash, + allow_list, + options, + pin_uv_auth_param, + pin_uv_auth_protocol, + .. + } = get_assertion_params; + + if let Some(auth_param) = &pin_uv_auth_param { + // This case was added in FIDO 2.1. + if auth_param.is_empty() { + if self.persistent_store.pin_hash().is_none() { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); + } else { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID); + } + } + + match pin_uv_auth_protocol { + Some(protocol) => { + if protocol != CtapState::::PIN_PROTOCOL_VERSION { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + } + None => return Err(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER), + } + } + + // This case was added in FIDO 2.1. + if pin_uv_auth_param == Some(vec![]) { + if self.persistent_store.pin_hash().is_none() { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); + } else { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID); + } + } + + if pin_uv_auth_param.is_some() { + match pin_uv_auth_protocol { + Some(protocol) => { + if protocol != CtapState::::PIN_PROTOCOL_VERSION { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + } + None => return Err(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER), + } + } + + // The user verification bit depends on the existance of PIN auth, whereas + // user presence is requested as an option. + let mut flags = match pin_uv_auth_param { + Some(pin_auth) => { + if self.persistent_store.pin_hash().is_none() { + // Specification is unclear, could be CTAP2_ERR_UNSUPPORTED_OPTION. + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_NOT_SET); + } + if !check_pin_auth(&self.pin_uv_auth_token, &client_data_hash, &pin_auth) { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + UV_FLAG + } + None => { + if options.uv { + // The specification (inconsistently) wants CTAP2_ERR_UNSUPPORTED_OPTION. + return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); + } + 0x00 + } + }; + if options.up { + flags |= UP_FLAG; + } + + let rp_id_hash = Sha256::hash(rp_id.as_bytes()); + let mut decrypted_credential = None; + let credentials = if let Some(allow_list) = allow_list { + let mut found_credentials = vec![]; + for allowed_credential in allow_list { + match self + .persistent_store + .find_credential(&rp_id, &allowed_credential.key_id) + { + Some(credential) => found_credentials.push(credential), + None => { + if decrypted_credential.is_none() { + decrypted_credential = self + .decrypt_credential_source(allowed_credential.key_id, &rp_id_hash); + } + } + } + } + found_credentials + } else { + // TODO(kaczmarczyck) use GetNextAssertion + self.persistent_store.filter_credential(&rp_id) + }; + + let credential = if let Some(credential) = credentials.first() { + credential + } else { + decrypted_credential + .as_ref() + .ok_or(Ctap2StatusCode::CTAP2_ERR_NO_CREDENTIALS)? + }; + + if options.up { + (self.check_user_presence)(cid)?; + } + + self.increment_global_signature_counter(); + + let auth_data = self.generate_auth_data(&rp_id_hash, flags); + let mut signature_data = auth_data.clone(); + signature_data.extend(client_data_hash); + let signature = credential + .private_key + .sign_rfc6979::(&signature_data); + + let cred_desc = PublicKeyCredentialDescriptor { + key_type: PublicKeyCredentialType::PublicKey, + key_id: credential.credential_id.clone(), + transports: None, // You can set USB as a hint here. + }; + let user = if flags & UV_FLAG != 0 { + Some(PublicKeyCredentialUserEntity { + user_id: credential.user_handle.clone(), + user_name: None, + user_display_name: credential.other_ui.clone(), + user_icon: None, + }) + } else { + None + }; + Ok(ResponseData::AuthenticatorGetAssertion( + AuthenticatorGetAssertionResponse { + credential: Some(cred_desc), + auth_data, + signature: signature.to_asn1_der(), + user, + number_of_credentials: None, + }, + )) + } + + fn process_get_info(&self) -> Result { + let mut options_map = BTreeMap::new(); + // TODO(kaczmarczyck) add FIDO 2.1 options + options_map.insert(String::from("rk"), true); + options_map.insert(String::from("up"), true); + options_map.insert( + String::from("clientPin"), + self.persistent_store.pin_hash().is_some(), + ); + Ok(ResponseData::AuthenticatorGetInfo( + AuthenticatorGetInfoResponse { + versions: vec![ + #[cfg(feature = "with_ctap1")] + String::from(U2F_VERSION_STRING), + String::from(FIDO2_VERSION_STRING), + ], + extensions: Some(vec![]), + aaguid: AAGUID, + options: Some(options_map), + max_msg_size: Some(1024), + pin_protocols: Some(vec![ + CtapState::::PIN_PROTOCOL_VERSION, + ]), + }, + )) + } + + fn check_and_store_new_pin( + &mut self, + aes_dec_key: &crypto::aes256::DecryptionKey, + new_pin_enc: Vec, + ) -> bool { + if new_pin_enc.len() != PIN_PADDED_LENGTH { + return false; + } + let iv = [0; 16]; + // Assuming PIN_PADDED_LENGTH % block_size == 0 here. + let mut blocks = [[0u8; 16]; PIN_PADDED_LENGTH / 16]; + for i in 0..PIN_PADDED_LENGTH / 16 { + blocks[i].copy_from_slice(&new_pin_enc[i * 16..(i + 1) * 16]); + } + cbc_decrypt(aes_dec_key, iv, &mut blocks); + let mut pin = vec![]; + 'pin_block_loop: for block in blocks.iter().take(PIN_PADDED_LENGTH / 16) { + for cur_char in block.iter() { + if *cur_char != 0 { + pin.push(*cur_char); + } else { + break 'pin_block_loop; + } + } + } + if pin.len() < 4 || pin.len() == PIN_PADDED_LENGTH { + return false; + } + let mut pin_hash = [0; 16]; + pin_hash.copy_from_slice(&Sha256::hash(&pin[..])[..16]); + self.persistent_store.set_pin_hash(&pin_hash); + true + } + + fn check_pin_hash_enc( + &mut self, + aes_dec_key: &crypto::aes256::DecryptionKey, + pin_hash_enc: Vec, + ) -> Result<(), Ctap2StatusCode> { + match self.persistent_store.pin_hash() { + Some(pin_hash) => { + if self.consecutive_pin_mismatches >= 3 { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED); + } + // We need to copy the pin hash, because decrementing the pin retries below may + // invalidate the reference (if the page containing the pin hash is compacted). + let pin_hash = pin_hash.to_vec(); + self.persistent_store.decr_pin_retries(); + if pin_hash_enc.len() != PIN_AUTH_LENGTH { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID); + } + + let iv = [0; 16]; + let mut blocks = [[0u8; 16]; 1]; + blocks[0].copy_from_slice(&pin_hash_enc[0..PIN_AUTH_LENGTH]); + cbc_decrypt(aes_dec_key, iv, &mut blocks); + + let pin_comparison = array_ref![pin_hash, 0, PIN_AUTH_LENGTH].ct_eq(&blocks[0]); + if !bool::from(pin_comparison) { + self.key_agreement_key = crypto::ecdh::SecKey::gensk(self.rng); + if self.persistent_store.pin_retries() == 0 { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_BLOCKED); + } + self.consecutive_pin_mismatches += 1; + if self.consecutive_pin_mismatches >= 3 { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_BLOCKED); + } + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_INVALID); + } + } + // This status code is not explicitly mentioned in the specification. + None => return Err(Ctap2StatusCode::CTAP2_ERR_PIN_REQUIRED), + } + self.persistent_store.reset_pin_retries(); + self.consecutive_pin_mismatches = 0; + Ok(()) + } + + fn process_get_pin_retries(&self) -> Result { + Ok(AuthenticatorClientPinResponse { + key_agreement: None, + pin_token: None, + retries: Some(self.persistent_store.pin_retries() as u64), + }) + } + + fn process_get_key_agreement(&self) -> Result { + let pk = self.key_agreement_key.genpk(); + Ok(AuthenticatorClientPinResponse { + key_agreement: Some(CoseKey::from(pk)), + pin_token: None, + retries: None, + }) + } + + fn process_set_pin( + &mut self, + key_agreement: CoseKey, + pin_auth: Vec, + new_pin_enc: Vec, + ) -> Result<(), Ctap2StatusCode> { + if self.persistent_store.pin_hash().is_some() { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + let pk: crypto::ecdh::PubKey = CoseKey::try_into(key_agreement)?; + let shared_secret = self.key_agreement_key.exchange_x_sha256(&pk); + + if !check_pin_auth(&shared_secret, &new_pin_enc, &pin_auth) { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + + let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret); + let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key); + if !self.check_and_store_new_pin(&aes_dec_key, new_pin_enc) { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION); + } + self.persistent_store.reset_pin_retries(); + Ok(()) + } + + fn process_change_pin( + &mut self, + key_agreement: CoseKey, + pin_auth: Vec, + new_pin_enc: Vec, + pin_hash_enc: Vec, + ) -> Result<(), Ctap2StatusCode> { + if self.persistent_store.pin_retries() == 0 { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_BLOCKED); + } + let pk: crypto::ecdh::PubKey = CoseKey::try_into(key_agreement)?; + let shared_secret = self.key_agreement_key.exchange_x_sha256(&pk); + + let mut auth_param_data = new_pin_enc.clone(); + auth_param_data.extend(&pin_hash_enc); + if !check_pin_auth(&shared_secret, &auth_param_data, &pin_auth) { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + + let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret); + let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key); + self.check_pin_hash_enc(&aes_dec_key, pin_hash_enc)?; + + if !self.check_and_store_new_pin(&aes_dec_key, new_pin_enc) { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_POLICY_VIOLATION); + } + self.pin_uv_auth_token = self.rng.gen_uniform_u8x32(); + Ok(()) + } + + fn process_get_pin_uv_auth_token_using_pin( + &mut self, + key_agreement: CoseKey, + pin_hash_enc: Vec, + ) -> Result { + if self.persistent_store.pin_retries() == 0 { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_BLOCKED); + } + let pk: crypto::ecdh::PubKey = CoseKey::try_into(key_agreement)?; + let shared_secret = self.key_agreement_key.exchange_x_sha256(&pk); + + let aes_enc_key = crypto::aes256::EncryptionKey::new(&shared_secret); + let aes_dec_key = crypto::aes256::DecryptionKey::new(&aes_enc_key); + self.check_pin_hash_enc(&aes_dec_key, pin_hash_enc)?; + + // Assuming PIN_TOKEN_LENGTH % block_size == 0 here. + let iv = [0; 16]; + let mut blocks = [[0u8; 16]; PIN_TOKEN_LENGTH / 16]; + for (i, item) in blocks.iter_mut().take(PIN_TOKEN_LENGTH / 16).enumerate() { + item.copy_from_slice(&self.pin_uv_auth_token[i * 16..(i + 1) * 16]); + } + cbc_encrypt(&aes_enc_key, iv, &mut blocks); + let mut pin_token = vec![]; + for item in blocks.iter().take(PIN_TOKEN_LENGTH / 16) { + pin_token.extend(item); + } + + Ok(AuthenticatorClientPinResponse { + key_agreement: None, + pin_token: Some(pin_token), + retries: None, + }) + } + + fn process_get_pin_uv_auth_token_using_uv( + &self, + _: CoseKey, + ) -> Result { + Ok(AuthenticatorClientPinResponse { + // User verifications is only supported through PIN currently. + key_agreement: None, + pin_token: Some(vec![]), + retries: None, + }) + } + + fn process_get_uv_retries(&self) -> Result { + // User verifications is only supported through PIN currently. + Ok(AuthenticatorClientPinResponse { + key_agreement: None, + pin_token: None, + retries: Some(0), + }) + } + + fn process_client_pin( + &mut self, + client_pin_params: AuthenticatorClientPinParameters, + ) -> Result { + let AuthenticatorClientPinParameters { + pin_protocol, + sub_command, + key_agreement, + pin_auth, + new_pin_enc, + pin_hash_enc, + } = client_pin_params; + + if pin_protocol != 1 { + return Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID); + } + + let response = match sub_command { + ClientPinSubCommand::GetPinRetries => Some(self.process_get_pin_retries()?), + ClientPinSubCommand::GetKeyAgreement => Some(self.process_get_key_agreement()?), + ClientPinSubCommand::SetPin => { + self.process_set_pin( + key_agreement.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + pin_auth.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + new_pin_enc.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + )?; + None + } + ClientPinSubCommand::ChangePin => { + self.process_change_pin( + key_agreement.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + pin_auth.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + new_pin_enc.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + pin_hash_enc.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + )?; + None + } + ClientPinSubCommand::GetPinUvAuthTokenUsingPin => { + Some(self.process_get_pin_uv_auth_token_using_pin( + key_agreement.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + pin_hash_enc.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + )?) + } + ClientPinSubCommand::GetPinUvAuthTokenUsingUv => { + Some(self.process_get_pin_uv_auth_token_using_uv( + key_agreement.ok_or(Ctap2StatusCode::CTAP2_ERR_MISSING_PARAMETER)?, + )?) + } + ClientPinSubCommand::GetUvRetries => Some(self.process_get_uv_retries()?), + }; + Ok(ResponseData::AuthenticatorClientPin(response)) + } + + fn process_reset(&mut self, cid: ChannelID) -> Result { + // Resets are only possible in the first 10 seconds after booting. + if !self.accepts_reset { + return Err(Ctap2StatusCode::CTAP2_ERR_NOT_ALLOWED); + } + (self.check_user_presence)(cid)?; + + self.persistent_store.reset(self.rng); + self.key_agreement_key = crypto::ecdh::SecKey::gensk(self.rng); + self.pin_uv_auth_token = self.rng.gen_uniform_u8x32(); + self.consecutive_pin_mismatches = 0; + #[cfg(feature = "with_ctap1")] + { + self.u2f_up_state = U2fUserPresenceState::new( + U2F_UP_PROMPT_TIMEOUT, + Duration::from_ms(TOUCH_TIMEOUT_MS), + ); + } + Ok(ResponseData::AuthenticatorReset) + } + + pub fn generate_auth_data(&self, rp_id_hash: &[u8], flag_byte: u8) -> Vec { + let mut auth_data = vec![]; + auth_data.extend(rp_id_hash); + auth_data.push(flag_byte); + // The global counter is only increased if USE_SIGNATURE_COUNTER is true. + // It uses a big-endian representation. + let mut signature_counter = [0u8; 4]; + BigEndian::write_u32( + &mut signature_counter, + self.persistent_store.global_signature_counter(), + ); + auth_data.extend(&signature_counter); + auth_data + } +} + +#[cfg(test)] +mod test { + use super::data_formats::{ + GetAssertionOptions, MakeCredentialOptions, PublicKeyCredentialRpEntity, + PublicKeyCredentialUserEntity, + }; + use super::*; + use crypto::rng256::ThreadRng256; + + // The keep-alive logic in the processing of some commands needs a channel ID to send + // keep-alive packets to. + // In tests where we define a dummy user-presence check that immediately returns, the channel + // ID is irrelevant, so we pass this (dummy but valid) value. + const DUMMY_CHANNEL_ID: ChannelID = [0x12, 0x34, 0x56, 0x78]; + + #[test] + fn test_get_info() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + let info_reponse = ctap_state.process_command(&[0x04], DUMMY_CHANNEL_ID); + + let mut expected_response = vec![0x00, 0xA6, 0x01]; + // The difference here is a longer array of supported versions. + #[cfg(not(feature = "with_ctap1"))] + expected_response.extend(&[ + 0x81, 0x68, 0x46, 0x49, 0x44, 0x4F, 0x5F, 0x32, 0x5F, 0x30, 0x02, 0x80, 0x03, 0x50, + ]); + #[cfg(feature = "with_ctap1")] + expected_response.extend(&[ + 0x82, 0x66, 0x55, 0x32, 0x46, 0x5F, 0x56, 0x32, 0x68, 0x46, 0x49, 0x44, 0x4F, 0x5F, + 0x32, 0x5F, 0x30, 0x02, 0x80, 0x03, 0x50, + ]); + expected_response.extend(&AAGUID); + expected_response.extend(&[ + 0x04, 0xA3, 0x62, 0x72, 0x6B, 0xF5, 0x62, 0x75, 0x70, 0xF5, 0x69, 0x63, 0x6C, 0x69, + 0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E, 0xF4, 0x05, 0x19, 0x04, 0x00, 0x06, 0x81, 0x01, + ]); + + assert_eq!(info_reponse, expected_response); + } + + fn create_minimal_make_credential_parameters() -> AuthenticatorMakeCredentialParameters { + let client_data_hash = vec![0xCD]; + let rp = PublicKeyCredentialRpEntity { + rp_id: String::from("example.com"), + rp_name: None, + rp_icon: None, + }; + let user = PublicKeyCredentialUserEntity { + user_id: vec![0xFA, 0xB1, 0xA2], + user_name: None, + user_display_name: None, + user_icon: None, + }; + let pub_key_cred_params = vec![( + PublicKeyCredentialType::PublicKey, + SignatureAlgorithm::ES256 as i64, + )]; + let options = MakeCredentialOptions { + rk: true, + uv: false, + }; + AuthenticatorMakeCredentialParameters { + client_data_hash, + rp, + user, + pub_key_cred_params, + exclude_list: None, + extensions: None, + options, + pin_uv_auth_param: None, + pin_uv_auth_protocol: None, + } + } + + #[test] + fn test_residential_process_make_credential() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + let make_credential_params = create_minimal_make_credential_parameters(); + let make_credential_response = + ctap_state.process_make_credential(make_credential_params, DUMMY_CHANNEL_ID); + + match make_credential_response.unwrap() { + ResponseData::AuthenticatorMakeCredential(make_credential_response) => { + let AuthenticatorMakeCredentialResponse { + fmt, + auth_data, + att_stmt, + } = make_credential_response; + // The expected response is split to only assert the non-random parts. + assert_eq!(fmt, "packed"); + let mut expected_auth_data = vec![ + 0xA3, 0x79, 0xA6, 0xF6, 0xEE, 0xAF, 0xB9, 0xA5, 0x5E, 0x37, 0x8C, 0x11, 0x80, + 0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2, + 0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00, + ]; + expected_auth_data.extend(&AAGUID); + expected_auth_data.extend(&[0x00, 0x20]); + assert_eq!( + auth_data[0..expected_auth_data.len()], + expected_auth_data[..] + ); + assert_eq!(att_stmt.alg, SignatureAlgorithm::ES256 as i64); + } + _ => panic!("Invalid response type"), + } + } + + #[test] + fn test_non_residential_process_make_credential() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + let mut make_credential_params = create_minimal_make_credential_parameters(); + make_credential_params.options.rk = false; + let make_credential_response = + ctap_state.process_make_credential(make_credential_params, DUMMY_CHANNEL_ID); + + match make_credential_response.unwrap() { + ResponseData::AuthenticatorMakeCredential(make_credential_response) => { + let AuthenticatorMakeCredentialResponse { + fmt, + auth_data, + att_stmt, + } = make_credential_response; + // The expected response is split to only assert the non-random parts. + assert_eq!(fmt, "packed"); + let mut expected_auth_data = vec![ + 0xA3, 0x79, 0xA6, 0xF6, 0xEE, 0xAF, 0xB9, 0xA5, 0x5E, 0x37, 0x8C, 0x11, 0x80, + 0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2, + 0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00, + ]; + expected_auth_data.extend(&AAGUID); + expected_auth_data.extend(&[0x00, ENCRYPTED_CREDENTIAL_ID_SIZE as u8]); + assert_eq!( + auth_data[0..expected_auth_data.len()], + expected_auth_data[..] + ); + assert_eq!(att_stmt.alg, SignatureAlgorithm::ES256 as i64); + } + _ => panic!("Invalid response type"), + } + } + + #[test] + fn test_process_make_credential_unsupported_algorithm() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + let pub_key_cred_params = vec![( + PublicKeyCredentialType::PublicKey, + SignatureAlgorithm::ES256 as i64 + 1, // any different number works + )]; + let mut make_credential_params = create_minimal_make_credential_parameters(); + make_credential_params.pub_key_cred_params = pub_key_cred_params; + let make_credential_response = + ctap_state.process_make_credential(make_credential_params, DUMMY_CHANNEL_ID); + + assert_eq!( + make_credential_response, + Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM) + ); + } + + #[test] + fn test_process_make_credential_credential_excluded() { + let mut rng = ThreadRng256 {}; + let excluded_private_key = crypto::ecdsa::SecKey::gensk(&mut rng); + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + let excluded_credential_id = vec![0x01, 0x23, 0x45, 0x67]; + let excluded_credential_source = PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id: excluded_credential_id.clone(), + private_key: excluded_private_key, + rp_id: String::from("example.com"), + user_handle: vec![], + other_ui: None, + }; + assert!(ctap_state + .persistent_store + .store_credential(excluded_credential_source) + .is_ok()); + + let excluded_credential_descriptor = PublicKeyCredentialDescriptor { + key_type: PublicKeyCredentialType::PublicKey, + key_id: excluded_credential_id, + transports: None, + }; + let exclude_list = Some(vec![excluded_credential_descriptor]); + let mut make_credential_params = create_minimal_make_credential_parameters(); + make_credential_params.exclude_list = exclude_list; + let make_credential_response = + ctap_state.process_make_credential(make_credential_params, DUMMY_CHANNEL_ID); + + assert_eq!( + make_credential_response, + Err(Ctap2StatusCode::CTAP2_ERR_CREDENTIAL_EXCLUDED) + ); + } + + #[test] + fn test_process_make_credential_cancelled() { + let mut rng = ThreadRng256 {}; + let user_presence_always_cancel = |_| Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL); + let mut ctap_state = CtapState::new(&mut rng, user_presence_always_cancel); + + let make_credential_params = create_minimal_make_credential_parameters(); + let make_credential_response = + ctap_state.process_make_credential(make_credential_params, DUMMY_CHANNEL_ID); + + assert_eq!( + make_credential_response, + Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL) + ); + } + + #[test] + fn test_residential_process_get_assertion() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + let make_credential_params = create_minimal_make_credential_parameters(); + assert!(ctap_state + .process_make_credential(make_credential_params, DUMMY_CHANNEL_ID) + .is_ok()); + + let get_assertion_params = AuthenticatorGetAssertionParameters { + rp_id: String::from("example.com"), + client_data_hash: vec![0xCD], + allow_list: None, + extensions: None, + options: GetAssertionOptions { + up: false, + uv: false, + }, + pin_uv_auth_param: None, + pin_uv_auth_protocol: None, + }; + let get_assertion_response = + ctap_state.process_get_assertion(get_assertion_params, DUMMY_CHANNEL_ID); + + match get_assertion_response.unwrap() { + ResponseData::AuthenticatorGetAssertion(get_assertion_response) => { + let AuthenticatorGetAssertionResponse { + auth_data, + user, + number_of_credentials, + .. + } = get_assertion_response; + let expected_auth_data = vec![ + 0xA3, 0x79, 0xA6, 0xF6, 0xEE, 0xAF, 0xB9, 0xA5, 0x5E, 0x37, 0x8C, 0x11, 0x80, + 0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2, + 0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x00, 0x00, 0x00, 0x00, 0x01, + ]; + assert_eq!(auth_data, expected_auth_data); + assert!(user.is_none()); + assert!(number_of_credentials.is_none()); + } + _ => panic!("Invalid response type"), + } + } + + #[test] + fn test_process_reset() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let private_key = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + let credential_id = vec![0x01, 0x23, 0x45, 0x67]; + let credential_source = PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id, + private_key, + rp_id: String::from("example.com"), + user_handle: vec![], + other_ui: None, + }; + assert!(ctap_state + .persistent_store + .store_credential(credential_source) + .is_ok()); + assert!(ctap_state.persistent_store.count_credentials() > 0); + + let reset_reponse = ctap_state.process_command(&[0x07], DUMMY_CHANNEL_ID); + let expected_response = vec![0x00]; + assert_eq!(reset_reponse, expected_response); + assert!(ctap_state.persistent_store.count_credentials() == 0); + } + + #[test] + fn test_process_reset_cancelled() { + let mut rng = ThreadRng256 {}; + let user_presence_always_cancel = |_| Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL); + let mut ctap_state = CtapState::new(&mut rng, user_presence_always_cancel); + + let reset_reponse = ctap_state.process_reset(DUMMY_CHANNEL_ID); + + assert_eq!( + reset_reponse, + Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL) + ); + } + + #[test] + fn test_encrypt_decrypt_credential() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let private_key = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + // Usually, the relying party ID or its hash is provided by the client. + // We are not testing the correctness of our SHA256 here, only if it is checked. + let rp_id_hash = [0x55; 32]; + let encrypted_id = ctap_state.encrypt_key_handle(private_key.clone(), &rp_id_hash); + let decrypted_source = ctap_state + .decrypt_credential_source(encrypted_id, &rp_id_hash) + .unwrap(); + + assert_eq!(private_key, decrypted_source.private_key); + } + + #[test] + fn test_encrypt_decrypt_bad_hmac() { + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let private_key = crypto::ecdsa::SecKey::gensk(&mut rng); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + + // Same as above. + let rp_id_hash = [0x55; 32]; + let encrypted_id = ctap_state.encrypt_key_handle(private_key, &rp_id_hash); + for i in 0..encrypted_id.len() { + let mut modified_id = encrypted_id.clone(); + modified_id[i] ^= 0x01; + assert!(ctap_state + .decrypt_credential_source(modified_id, &rp_id_hash) + .is_none()); + } + } +} diff --git a/src/ctap/response.rs b/src/ctap/response.rs new file mode 100644 index 0000000..4b8a089 --- /dev/null +++ b/src/ctap/response.rs @@ -0,0 +1,267 @@ +// Copyright 2019 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. + +use super::data_formats::{ + CoseKey, PackedAttestationStatement, PublicKeyCredentialDescriptor, + PublicKeyCredentialUserEntity, +}; +use alloc::collections::BTreeMap; +use alloc::string::String; +use alloc::vec::Vec; + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub enum ResponseData { + AuthenticatorMakeCredential(AuthenticatorMakeCredentialResponse), + AuthenticatorGetAssertion(AuthenticatorGetAssertionResponse), + AuthenticatorGetNextAssertion(AuthenticatorGetAssertionResponse), + AuthenticatorGetInfo(AuthenticatorGetInfoResponse), + AuthenticatorClientPin(Option), + AuthenticatorReset, +} + +impl From for Option { + fn from(response: ResponseData) -> Self { + match response { + ResponseData::AuthenticatorMakeCredential(data) => Some(data.into()), + ResponseData::AuthenticatorGetAssertion(data) => Some(data.into()), + ResponseData::AuthenticatorGetNextAssertion(data) => Some(data.into()), + ResponseData::AuthenticatorGetInfo(data) => Some(data.into()), + ResponseData::AuthenticatorClientPin(Some(data)) => Some(data.into()), + ResponseData::AuthenticatorClientPin(None) => None, + ResponseData::AuthenticatorReset => None, + } + } +} + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub struct AuthenticatorMakeCredentialResponse { + pub fmt: String, + pub auth_data: Vec, + pub att_stmt: PackedAttestationStatement, +} + +impl From for cbor::Value { + fn from(make_credential_response: AuthenticatorMakeCredentialResponse) -> Self { + let AuthenticatorMakeCredentialResponse { + fmt, + auth_data, + att_stmt, + } = make_credential_response; + + cbor_map_options! { + 1 => fmt, + 2 => auth_data, + 3 => att_stmt, + } + } +} + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub struct AuthenticatorGetAssertionResponse { + pub credential: Option, + pub auth_data: Vec, + pub signature: Vec, + pub user: Option, + pub number_of_credentials: Option, +} + +impl From for cbor::Value { + fn from(get_assertion_response: AuthenticatorGetAssertionResponse) -> Self { + let AuthenticatorGetAssertionResponse { + credential, + auth_data, + signature, + user, + number_of_credentials, + } = get_assertion_response; + + cbor_map_options! { + 1 => credential, + 2 => auth_data, + 3 => signature, + 4 => user, + 5 => number_of_credentials, + } + } +} + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub struct AuthenticatorGetInfoResponse { + // TODO(kaczmarczyck) add fields from 2.1 + pub versions: Vec, + pub extensions: Option>, + pub aaguid: [u8; 16], + pub options: Option>, + pub max_msg_size: Option, + pub pin_protocols: Option>, +} + +impl From for cbor::Value { + fn from(get_info_response: AuthenticatorGetInfoResponse) -> Self { + let AuthenticatorGetInfoResponse { + versions, + extensions, + aaguid, + options, + max_msg_size, + pin_protocols, + } = get_info_response; + + let options_cbor: Option = options.map(|options| { + let option_map: BTreeMap<_, _> = options + .into_iter() + .map(|(key, value)| (cbor_text!(key), cbor_bool!(value))) + .collect(); + cbor_map_btree!(option_map) + }); + + cbor_map_options! { + 1 => cbor_array_vec!(versions), + 2 => extensions.map(|vec| cbor_array_vec!(vec)), + 3 => &aaguid, + 4 => options_cbor, + 5 => max_msg_size, + 6 => pin_protocols.map(|vec| cbor_array_vec!(vec)), + } + } +} + +#[cfg_attr(test, derive(PartialEq))] +#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))] +pub struct AuthenticatorClientPinResponse { + pub key_agreement: Option, + pub pin_token: Option>, + pub retries: Option, +} + +impl From for cbor::Value { + fn from(client_pin_response: AuthenticatorClientPinResponse) -> Self { + let AuthenticatorClientPinResponse { + key_agreement, + pin_token, + retries, + } = client_pin_response; + + cbor_map_options! { + 1 => key_agreement.map(|cose_key| cbor_map_btree!(cose_key.0)), + 2 => pin_token, + 3 => retries, + } + } +} + +#[cfg(test)] +mod test { + use super::super::data_formats::PackedAttestationStatement; + use super::*; + + #[test] + fn test_make_credential_into_cbor() { + let certificate: cbor::values::KeyType = cbor_bytes![vec![0x5C, 0x5C, 0x5C, 0x5C]]; + let att_stmt = PackedAttestationStatement { + alg: 1, + sig: vec![0x55, 0x55, 0x55, 0x55], + x5c: Some(vec![vec![0x5C, 0x5C, 0x5C, 0x5C]]), + ecdaa_key_id: Some(vec![0xEC, 0xDA, 0x1D]), + }; + let cbor_packed_attestation_statement = cbor_map! { + "alg" => 1, + "sig" => vec![0x55, 0x55, 0x55, 0x55], + "x5c" => cbor_array_vec![vec![certificate]], + "ecdaaKeyId" => vec![0xEC, 0xDA, 0x1D], + }; + + let make_credential_response = AuthenticatorMakeCredentialResponse { + fmt: "packed".to_string(), + auth_data: vec![0xAD], + att_stmt, + }; + let response_cbor: Option = + ResponseData::AuthenticatorMakeCredential(make_credential_response).into(); + let expected_cbor = cbor_map_options! { + 1 => "packed", + 2 => vec![0xAD], + 3 => cbor_packed_attestation_statement, + }; + assert_eq!(response_cbor, Some(expected_cbor)); + } + + #[test] + fn test_get_assertion_into_cbor() { + let get_assertion_response = AuthenticatorGetAssertionResponse { + credential: None, + auth_data: vec![0xAD], + signature: vec![0x51], + user: None, + number_of_credentials: None, + }; + let response_cbor: Option = + ResponseData::AuthenticatorGetAssertion(get_assertion_response).into(); + let expected_cbor = cbor_map_options! { + 2 => vec![0xAD], + 3 => vec![0x51], + }; + assert_eq!(response_cbor, Some(expected_cbor)); + } + + #[test] + fn test_get_info_into_cbor() { + let get_info_response = AuthenticatorGetInfoResponse { + versions: vec!["FIDO_2_0".to_string()], + extensions: None, + aaguid: [0x00; 16], + options: None, + max_msg_size: None, + pin_protocols: None, + }; + let response_cbor: Option = + ResponseData::AuthenticatorGetInfo(get_info_response).into(); + let expected_cbor = cbor_map_options! { + 1 => cbor_array_vec![vec!["FIDO_2_0"]], + 3 => vec![0x00; 16], + }; + assert_eq!(response_cbor, Some(expected_cbor)); + } + + #[test] + fn test_used_client_pin_into_cbor() { + let client_pin_response = AuthenticatorClientPinResponse { + key_agreement: None, + pin_token: Some(vec![70]), + retries: None, + }; + let response_cbor: Option = + ResponseData::AuthenticatorClientPin(Some(client_pin_response)).into(); + let expected_cbor = cbor_map_options! { + 2 => vec![70], + }; + assert_eq!(response_cbor, Some(expected_cbor)); + } + + #[test] + fn test_empty_client_pin_into_cbor() { + let response_cbor: Option = ResponseData::AuthenticatorClientPin(None).into(); + assert_eq!(response_cbor, None); + } + + #[test] + fn test_reset_into_cbor() { + let response_cbor: Option = ResponseData::AuthenticatorReset.into(); + assert_eq!(response_cbor, None); + } +} diff --git a/src/ctap/status_code.rs b/src/ctap/status_code.rs new file mode 100644 index 0000000..1e0c2bf --- /dev/null +++ b/src/ctap/status_code.rs @@ -0,0 +1,71 @@ +// Copyright 2019 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. + +// CTAP specification (version 20190130) section 6.3 +// For now, only the CTAP2 codes are here, the CTAP1 are not included. +#[allow(non_camel_case_types)] +#[allow(dead_code)] +#[derive(Debug, PartialEq)] +pub enum Ctap2StatusCode { + CTAP2_OK = 0x00, + CTAP1_ERR_INVALID_COMMAND = 0x01, + CTAP1_ERR_INVALID_PARAMETER = 0x02, + CTAP1_ERR_INVALID_LENGTH = 0x03, + CTAP1_ERR_INVALID_SEQ = 0x04, + CTAP1_ERR_TIMEOUT = 0x05, + CTAP1_ERR_CHANNEL_BUSY = 0x06, + CTAP1_ERR_LOCK_REQUIRED = 0x0A, + CTAP1_ERR_INVALID_CHANNEL = 0x0B, + CTAP2_ERR_CBOR_UNEXPECTED_TYPE = 0x11, + CTAP2_ERR_INVALID_CBOR = 0x12, + CTAP2_ERR_MISSING_PARAMETER = 0x14, + CTAP2_ERR_LIMIT_EXCEEDED = 0x15, + CTAP2_ERR_UNSUPPORTED_EXTENSION = 0x16, + CTAP2_ERR_CREDENTIAL_EXCLUDED = 0x19, + CTAP2_ERR_PROCESSING = 0x21, + CTAP2_ERR_INVALID_CREDENTIAL = 0x22, + CTAP2_ERR_USER_ACTION_PENDING = 0x23, + CTAP2_ERR_OPERATION_PENDING = 0x24, + CTAP2_ERR_NO_OPERATIONS = 0x25, + CTAP2_ERR_UNSUPPORTED_ALGORITHM = 0x26, + CTAP2_ERR_OPERATION_DENIED = 0x27, + CTAP2_ERR_KEY_STORE_FULL = 0x28, + CTAP2_ERR_NO_OPERATION_PENDING = 0x2A, + CTAP2_ERR_UNSUPPORTED_OPTION = 0x2B, + CTAP2_ERR_INVALID_OPTION = 0x2C, + CTAP2_ERR_KEEPALIVE_CANCEL = 0x2D, + CTAP2_ERR_NO_CREDENTIALS = 0x2E, + CTAP2_ERR_USER_ACTION_TIMEOUT = 0x2F, + CTAP2_ERR_NOT_ALLOWED = 0x30, + CTAP2_ERR_PIN_INVALID = 0x31, + CTAP2_ERR_PIN_BLOCKED = 0x32, + CTAP2_ERR_PIN_AUTH_INVALID = 0x33, + CTAP2_ERR_PIN_AUTH_BLOCKED = 0x34, + CTAP2_ERR_PIN_NOT_SET = 0x35, + CTAP2_ERR_PIN_REQUIRED = 0x36, + CTAP2_ERR_PIN_POLICY_VIOLATION = 0x37, + CTAP2_ERR_PIN_TOKEN_EXPIRED = 0x38, + CTAP2_ERR_REQUEST_TOO_LARGE = 0x39, + CTAP2_ERR_ACTION_TIMEOUT = 0x3A, + CTAP2_ERR_UP_REQUIRED = 0x3B, + CTAP2_ERR_UV_BLOCKED = 0x3C, + CTAP1_ERR_OTHER = 0x7F, + CTAP2_ERR_SPEC_LAST = 0xDF, + CTAP2_ERR_EXTENSION_FIRST = 0xE0, + CTAP2_ERR_EXTENSION_LAST = 0xEF, + // CTAP2_ERR_VENDOR_FIRST = 0xF0, + CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG = 0xF0, + CTAP2_ERR_VENDOR_RESPONSE_CANNOT_WRITE_CBOR = 0xF1, + CTAP2_ERR_VENDOR_LAST = 0xFF, +} diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs new file mode 100644 index 0000000..e693a13 --- /dev/null +++ b/src/ctap/storage.rs @@ -0,0 +1,682 @@ +// Copyright 2019 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. + +use crate::crypto::rng256::Rng256; +use crate::ctap::data_formats::PublicKeyCredentialSource; +use crate::ctap::status_code::Ctap2StatusCode; +use crate::ctap::PIN_AUTH_LENGTH; +use alloc::string::String; +use alloc::vec::Vec; +use core::convert::TryInto; +use ctap2::embedded_flash::{self, StoreConfig, StoreEntry, StoreError, StoreIndex}; + +#[cfg(test)] +type Storage = embedded_flash::BufferStorage; +#[cfg(not(test))] +type Storage = embedded_flash::SyscallStorage; + +// Those constants may be modified before compilation to tune the behavior of the key. +// +// The number of pages should be at least 2 and at most what the flash can hold. There should be no +// reason to put a small number here, except that the latency of flash operations depends on the +// number of pages. This will improve in the future. Currently, using 20 pages gives 65ms per +// operation. The rule of thumb is 3.5ms per additional page. +// +// Limiting the number of residential keys permits to ensure a minimum number of counter increments. +// Let: +// - P the number of pages (NUM_PAGES) +// - K the maximum number of residential keys (MAX_SUPPORTED_RESIDENTIAL_KEYS) +// - S the maximum size of a residential key (about 500) +// - C the number of erase cycles (10000) +// - I the minimum number of counter increments +// +// We have: I = ((P - 1) * 4092 - K * S) / 12 * C +// +// With P=20 and K=150, we have I > 2M which is enough for 500 increments per day for 10 years. +const NUM_PAGES: usize = 20; +const MAX_SUPPORTED_RESIDENTIAL_KEYS: usize = 150; + +// List of tags. They should all be unique. And there should be less than NUM_TAGS. +const TAG_CREDENTIAL: usize = 0; +const GLOBAL_SIGNATURE_COUNTER: usize = 1; +const MASTER_KEYS: usize = 2; +const PIN_HASH: usize = 3; +const PIN_RETRIES: usize = 4; +const NUM_TAGS: usize = 5; + +const MAX_PIN_RETRIES: u8 = 6; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +enum Key { + // TODO(cretin): Test whether this doesn't consume too much memory. Otherwise, we can use less + // keys. Either only a simple enum value for all credentials, or group by rp_id. + Credential { + rp_id: Option, + credential_id: Option>, + user_handle: Option>, + }, + GlobalSignatureCounter, + MasterKeys, + PinHash, + PinRetries, +} + +pub struct MasterKeys<'a> { + pub encryption: &'a [u8; 32], + pub hmac: &'a [u8; 32], +} + +struct Config; + +impl StoreConfig for Config { + type Key = Key; + + fn num_tags(&self) -> usize { + NUM_TAGS + } + + fn keys(&self, entry: StoreEntry, mut add: impl FnMut(Key)) { + match entry.tag { + TAG_CREDENTIAL => { + let credential = match deserialize_credential(entry.data) { + None => { + debug_assert!(false); + return; + } + Some(credential) => credential, + }; + add(Key::Credential { + rp_id: Some(credential.rp_id.clone()), + credential_id: Some(credential.credential_id), + user_handle: None, + }); + add(Key::Credential { + rp_id: Some(credential.rp_id.clone()), + credential_id: None, + user_handle: None, + }); + add(Key::Credential { + rp_id: Some(credential.rp_id), + credential_id: None, + user_handle: Some(credential.user_handle), + }); + add(Key::Credential { + rp_id: None, + credential_id: None, + user_handle: None, + }); + } + GLOBAL_SIGNATURE_COUNTER => add(Key::GlobalSignatureCounter), + MASTER_KEYS => add(Key::MasterKeys), + PIN_HASH => add(Key::PinHash), + PIN_RETRIES => add(Key::PinRetries), + _ => debug_assert!(false), + } + } +} + +pub struct PersistentStore { + store: embedded_flash::Store, +} + +const PAGE_SIZE: usize = 0x1000; +const STORE_SIZE: usize = NUM_PAGES * PAGE_SIZE; + +#[cfg(not(test))] +#[link_section = ".app_state"] +static STORE: [u8; STORE_SIZE] = [0xff; STORE_SIZE]; + +impl PersistentStore { + /// Gives access to the persistent store. + /// + /// # Safety + /// + /// This should be at most one instance of persistent store per program lifetime. + pub fn new(rng: &mut impl Rng256) -> PersistentStore { + #[cfg(not(test))] + let storage = PersistentStore::new_prod_storage(); + #[cfg(test)] + let storage = PersistentStore::new_test_storage(); + let mut store = PersistentStore { + store: embedded_flash::Store::new(storage, Config).unwrap(), + }; + store.init(rng); + store + } + + #[cfg(not(test))] + fn new_prod_storage() -> Storage { + let store = unsafe { + // Safety: The store cannot alias because this function is called only once. + core::slice::from_raw_parts_mut(STORE.as_ptr() as *mut u8, STORE_SIZE) + }; + unsafe { + // Safety: The store is in a writeable flash region. + Storage::new(store).unwrap() + } + } + + #[cfg(test)] + fn new_test_storage() -> Storage { + let store = vec![0xff; STORE_SIZE].into_boxed_slice(); + let options = embedded_flash::BufferOptions { + word_size: 4, + page_size: PAGE_SIZE, + max_word_writes: 2, + max_page_erases: 10000, + strict_write: true, + }; + Storage::new(store, options) + } + + fn init(&mut self, rng: &mut impl Rng256) { + if self.store.find_one(&Key::MasterKeys).is_none() { + let master_encryption_key = rng.gen_uniform_u8x32(); + let master_hmac_key = rng.gen_uniform_u8x32(); + let mut master_keys = Vec::with_capacity(64); + master_keys.extend_from_slice(&master_encryption_key); + master_keys.extend_from_slice(&master_hmac_key); + self.store + .insert(StoreEntry { + tag: MASTER_KEYS, + data: &master_keys, + }) + .unwrap(); + } + if self.store.find_one(&Key::PinRetries).is_none() { + self.store + .insert(StoreEntry { + tag: PIN_RETRIES, + data: &[MAX_PIN_RETRIES], + }) + .unwrap(); + } + } + + pub fn find_credential( + &self, + rp_id: &str, + credential_id: &[u8], + ) -> Option { + let key = Key::Credential { + rp_id: Some(rp_id.into()), + credential_id: Some(credential_id.into()), + user_handle: None, + }; + let (_, entry) = self.store.find_one(&key)?; + debug_assert_eq!(entry.tag, TAG_CREDENTIAL); + let result = deserialize_credential(entry.data); + debug_assert!(result.is_some()); + result + } + + pub fn store_credential( + &mut self, + credential: PublicKeyCredentialSource, + ) -> Result<(), Ctap2StatusCode> { + let key = Key::Credential { + rp_id: Some(credential.rp_id.clone()), + credential_id: None, + user_handle: Some(credential.user_handle.clone()), + }; + let old_entry = self.store.find_one(&key); + if old_entry.is_none() && self.count_credentials() >= MAX_SUPPORTED_RESIDENTIAL_KEYS { + return Err(Ctap2StatusCode::CTAP2_ERR_KEY_STORE_FULL); + } + let credential = serialize_credential(credential)?; + let new_entry = StoreEntry { + tag: TAG_CREDENTIAL, + data: &credential, + }; + match old_entry { + None => self.store.insert(new_entry)?, + Some((index, old_entry)) => { + debug_assert_eq!(old_entry.tag, TAG_CREDENTIAL); + self.store.replace(index, new_entry)? + } + }; + Ok(()) + } + + pub fn filter_credential(&self, rp_id: &str) -> Vec { + self.store + .find_all(&Key::Credential { + rp_id: Some(rp_id.into()), + credential_id: None, + user_handle: None, + }) + .filter_map(|(_, entry)| { + debug_assert_eq!(entry.tag, TAG_CREDENTIAL); + let credential = deserialize_credential(entry.data); + debug_assert!(credential.is_some()); + credential + }) + .collect() + } + + pub fn count_credentials(&self) -> usize { + self.store + .find_all(&Key::Credential { + rp_id: None, + credential_id: None, + user_handle: None, + }) + .count() + } + + pub fn global_signature_counter(&self) -> u32 { + self.store + .find_one(&Key::GlobalSignatureCounter) + .map_or(0, |(_, entry)| { + u32::from_ne_bytes(*array_ref!(entry.data, 0, 4)) + }) + } + + pub fn incr_global_signature_counter(&mut self) { + let mut buffer = [0; core::mem::size_of::()]; + match self.store.find_one(&Key::GlobalSignatureCounter) { + None => { + buffer.copy_from_slice(&1u32.to_ne_bytes()); + self.store + .insert(StoreEntry { + tag: GLOBAL_SIGNATURE_COUNTER, + data: &buffer, + }) + .unwrap(); + } + Some((index, entry)) => { + let value = u32::from_ne_bytes(*array_ref!(entry.data, 0, 4)); + // In hopes that servers handle the wrapping gracefully. + buffer.copy_from_slice(&value.wrapping_add(1).to_ne_bytes()); + self.store + .replace( + index, + StoreEntry { + tag: GLOBAL_SIGNATURE_COUNTER, + data: &buffer, + }, + ) + .unwrap(); + } + } + } + + pub fn master_keys(&self) -> MasterKeys { + // We have as invariant that there is always exactly one MasterKeys entry in the store. + let (_, entry) = self.store.find_one(&Key::MasterKeys).unwrap(); + let data = entry.data; + // And this entry is well formed: the encryption key followed by the hmac key. + let encryption = array_ref!(data, 0, 32); + let hmac = array_ref!(data, 32, 32); + MasterKeys { encryption, hmac } + } + + pub fn pin_hash(&self) -> Option<&[u8; PIN_AUTH_LENGTH]> { + self.store + .find_one(&Key::PinHash) + .map(|(_, entry)| array_ref!(entry.data, 0, PIN_AUTH_LENGTH)) + } + + pub fn set_pin_hash(&mut self, pin_hash: &[u8; PIN_AUTH_LENGTH]) { + let entry = StoreEntry { + tag: PIN_HASH, + data: pin_hash, + }; + match self.store.find_one(&Key::PinHash) { + None => self.store.insert(entry).unwrap(), + Some((index, _)) => { + self.store.replace(index, entry).unwrap(); + } + } + } + + fn pin_retries_entry(&self) -> (StoreIndex, u8) { + let (index, entry) = self.store.find_one(&Key::PinRetries).unwrap(); + let data = entry.data; + debug_assert_eq!(data.len(), 1); + (index, data[0]) + } + + pub fn pin_retries(&self) -> u8 { + self.pin_retries_entry().1 + } + + pub fn decr_pin_retries(&mut self) { + let (index, old_value) = self.pin_retries_entry(); + let new_value = old_value.saturating_sub(1); + self.store + .replace( + index, + StoreEntry { + tag: PIN_RETRIES, + data: &[new_value], + }, + ) + .unwrap(); + } + + pub fn reset_pin_retries(&mut self) { + let (index, _) = self.pin_retries_entry(); + self.store + .replace( + index, + StoreEntry { + tag: PIN_RETRIES, + data: &[MAX_PIN_RETRIES], + }, + ) + .unwrap(); + } + + pub fn reset(&mut self, rng: &mut impl Rng256) { + loop { + let index = { + let mut iter = self.store.iter(); + match iter.next() { + None => break, + Some((index, _)) => index, + } + }; + self.store.delete(index).unwrap(); + } + self.init(rng); + } +} + +impl From for Ctap2StatusCode { + fn from(error: StoreError) -> Ctap2StatusCode { + match error { + StoreError::StoreFull => Ctap2StatusCode::CTAP2_ERR_KEY_STORE_FULL, + StoreError::InvalidTag => unreachable!(), + StoreError::InvalidPrecondition => unreachable!(), + } + } +} + +fn deserialize_credential(data: &[u8]) -> Option { + let cbor = cbor::read(data).ok()?; + cbor.try_into().ok() +} + +fn serialize_credential(credential: PublicKeyCredentialSource) -> Result, Ctap2StatusCode> { + let mut data = Vec::new(); + if cbor::write(credential.into(), &mut data) { + Ok(data) + } else { + Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CREDENTIAL) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::crypto; + use crate::crypto::rng256::{Rng256, ThreadRng256}; + use crate::ctap::data_formats::{PublicKeyCredentialSource, PublicKeyCredentialType}; + + fn create_credential_source( + rng: &mut ThreadRng256, + rp_id: &str, + user_handle: Vec, + ) -> PublicKeyCredentialSource { + let private_key = crypto::ecdsa::SecKey::gensk(rng); + PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id: rng.gen_uniform_u8x32().to_vec(), + private_key, + rp_id: String::from(rp_id), + user_handle, + other_ui: None, + } + } + + #[test] + fn format_overhead() { + // nRF52840 NVMC + const WORD_SIZE: usize = 4; + const PAGE_SIZE: usize = 0x1000; + const NUM_PAGES: usize = 100; + let store = vec![0xff; NUM_PAGES * PAGE_SIZE].into_boxed_slice(); + let options = embedded_flash::BufferOptions { + word_size: WORD_SIZE, + page_size: PAGE_SIZE, + max_word_writes: 2, + max_page_erases: 10000, + strict_write: true, + }; + let storage = Storage::new(store, options); + let store = embedded_flash::Store::new(storage, Config).unwrap(); + // We can replace 3 bytes with minimal overhead. + assert_eq!(store.replace_len(0), 2 * WORD_SIZE); + assert_eq!(store.replace_len(3), 2 * WORD_SIZE); + assert_eq!(store.replace_len(4), 3 * WORD_SIZE); + } + + #[test] + fn test_store() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + assert_eq!(persistent_store.count_credentials(), 0); + let credential_source = create_credential_source(&mut rng, "example.com", vec![]); + assert!(persistent_store.store_credential(credential_source).is_ok()); + assert!(persistent_store.count_credentials() > 0); + } + + #[test] + #[allow(clippy::assertions_on_constants)] + fn test_fill_store() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + assert_eq!(persistent_store.count_credentials(), 0); + + // To make this test work for bigger storages, implement better int -> Vec conversion. + assert!(MAX_SUPPORTED_RESIDENTIAL_KEYS < 256); + for i in 0..MAX_SUPPORTED_RESIDENTIAL_KEYS { + let credential_source = + create_credential_source(&mut rng, "example.com", vec![i as u8]); + assert!(persistent_store.store_credential(credential_source).is_ok()); + assert_eq!(persistent_store.count_credentials(), i + 1); + } + let credential_source = create_credential_source( + &mut rng, + "example.com", + vec![MAX_SUPPORTED_RESIDENTIAL_KEYS as u8], + ); + assert_eq!( + persistent_store.store_credential(credential_source), + Err(Ctap2StatusCode::CTAP2_ERR_KEY_STORE_FULL) + ); + assert_eq!( + persistent_store.count_credentials(), + MAX_SUPPORTED_RESIDENTIAL_KEYS + ); + } + + #[test] + #[allow(clippy::assertions_on_constants)] + fn test_overwrite() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + assert_eq!(persistent_store.count_credentials(), 0); + // These should have different IDs. + let credential_source0 = create_credential_source(&mut rng, "example.com", vec![0x00]); + let credential_source1 = create_credential_source(&mut rng, "example.com", vec![0x00]); + let expected_credential = credential_source1.clone(); + + assert!(persistent_store + .store_credential(credential_source0) + .is_ok()); + assert!(persistent_store + .store_credential(credential_source1) + .is_ok()); + assert_eq!(persistent_store.count_credentials(), 1); + assert_eq!( + &persistent_store.filter_credential("example.com"), + &[expected_credential] + ); + + // To make this test work for bigger storages, implement better int -> Vec conversion. + assert!(MAX_SUPPORTED_RESIDENTIAL_KEYS < 256); + for i in 0..MAX_SUPPORTED_RESIDENTIAL_KEYS { + let credential_source = + create_credential_source(&mut rng, "example.com", vec![i as u8]); + assert!(persistent_store.store_credential(credential_source).is_ok()); + assert_eq!(persistent_store.count_credentials(), i + 1); + } + let credential_source = create_credential_source( + &mut rng, + "example.com", + vec![MAX_SUPPORTED_RESIDENTIAL_KEYS as u8], + ); + assert_eq!( + persistent_store.store_credential(credential_source), + Err(Ctap2StatusCode::CTAP2_ERR_KEY_STORE_FULL) + ); + assert_eq!( + persistent_store.count_credentials(), + MAX_SUPPORTED_RESIDENTIAL_KEYS + ); + } + + #[test] + fn test_filter() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + assert_eq!(persistent_store.count_credentials(), 0); + let credential_source0 = create_credential_source(&mut rng, "example.com", vec![0x00]); + let credential_source1 = create_credential_source(&mut rng, "example.com", vec![0x01]); + let credential_source2 = + create_credential_source(&mut rng, "another.example.com", vec![0x02]); + let id0 = credential_source0.credential_id.clone(); + let id1 = credential_source1.credential_id.clone(); + assert!(persistent_store + .store_credential(credential_source0) + .is_ok()); + assert!(persistent_store + .store_credential(credential_source1) + .is_ok()); + assert!(persistent_store + .store_credential(credential_source2) + .is_ok()); + + let filtered_credentials = persistent_store.filter_credential("example.com"); + assert_eq!(filtered_credentials.len(), 2); + assert!( + (filtered_credentials[0].credential_id == id0 + && filtered_credentials[1].credential_id == id1) + || (filtered_credentials[1].credential_id == id0 + && filtered_credentials[0].credential_id == id1) + ); + } + + #[test] + fn test_find() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + assert_eq!(persistent_store.count_credentials(), 0); + let credential_source0 = create_credential_source(&mut rng, "example.com", vec![0x00]); + let credential_source1 = create_credential_source(&mut rng, "example.com", vec![0x01]); + let id0 = credential_source0.credential_id.clone(); + let key0 = credential_source0.private_key.clone(); + assert!(persistent_store + .store_credential(credential_source0) + .is_ok()); + assert!(persistent_store + .store_credential(credential_source1) + .is_ok()); + + let no_credential = persistent_store.find_credential("another.example.com", &id0); + assert_eq!(no_credential, None); + let found_credential = persistent_store.find_credential("example.com", &id0); + let expected_credential = PublicKeyCredentialSource { + key_type: PublicKeyCredentialType::PublicKey, + credential_id: id0, + private_key: key0, + rp_id: String::from("example.com"), + user_handle: vec![0x00], + other_ui: None, + }; + assert_eq!(found_credential, Some(expected_credential)); + } + + #[test] + fn test_master_keys() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + + // Master keys stay the same between resets. + let master_keys_1 = persistent_store.master_keys(); + let master_keys_2 = persistent_store.master_keys(); + assert_eq!(master_keys_2.encryption, master_keys_1.encryption); + assert_eq!(master_keys_2.hmac, master_keys_1.hmac); + + // Master keys change after reset. This test may fail if the random generator produces the + // same keys. + let master_encryption_key = master_keys_1.encryption.to_vec(); + let master_hmac_key = master_keys_1.hmac.to_vec(); + persistent_store.reset(&mut rng); + let master_keys_3 = persistent_store.master_keys(); + assert!(master_keys_3.encryption as &[u8] != &master_encryption_key[..]); + assert!(master_keys_3.hmac as &[u8] != &master_hmac_key[..]); + } + + #[test] + fn test_pin_hash() { + use crate::ctap::PIN_AUTH_LENGTH; + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + + // Pin hash is initially not set. + assert!(persistent_store.pin_hash().is_none()); + + // Setting the pin hash sets the pin hash. + let random_data = 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); + persistent_store.set_pin_hash(&pin_hash_1); + assert_eq!(persistent_store.pin_hash(), Some(pin_hash_1)); + assert_eq!(persistent_store.pin_hash(), Some(pin_hash_1)); + persistent_store.set_pin_hash(&pin_hash_2); + assert_eq!(persistent_store.pin_hash(), Some(pin_hash_2)); + assert_eq!(persistent_store.pin_hash(), Some(pin_hash_2)); + + // Resetting the storage resets the pin hash. + persistent_store.reset(&mut rng); + assert!(persistent_store.pin_hash().is_none()); + } + + #[test] + fn test_pin_retries() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + + // The pin retries is initially at the maximum. + assert_eq!(persistent_store.pin_retries(), MAX_PIN_RETRIES); + + // Decrementing the pin retries decrements the pin retries. + for pin_retries in (0..MAX_PIN_RETRIES).rev() { + persistent_store.decr_pin_retries(); + assert_eq!(persistent_store.pin_retries(), pin_retries); + } + + // Decrementing the pin retries after zero does not modify the pin retries. + persistent_store.decr_pin_retries(); + assert_eq!(persistent_store.pin_retries(), 0); + + // Resetting the pin retries resets the pin retries. + persistent_store.reset_pin_retries(); + assert_eq!(persistent_store.pin_retries(), MAX_PIN_RETRIES); + } +} diff --git a/src/ctap/timed_permission.rs b/src/ctap/timed_permission.rs new file mode 100644 index 0000000..d56ba09 --- /dev/null +++ b/src/ctap/timed_permission.rs @@ -0,0 +1,188 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2 (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 +// +// 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. + +use crate::timer::{ClockValue, Duration}; + +#[derive(Clone, Copy, Debug)] +pub enum TimedPermission { + Waiting, + Granted(ClockValue), +} + +impl TimedPermission { + pub fn waiting() -> TimedPermission { + TimedPermission::Waiting + } + + pub fn granted(now: ClockValue, grant_duration: Duration) -> TimedPermission { + TimedPermission::Granted(now.wrapping_add(grant_duration)) + } + + // Checks if the timeout is not reached, false for differing ClockValue frequencies. + pub fn is_granted(&self, now: ClockValue) -> bool { + if let TimedPermission::Granted(timeout) = self { + if let Some(remaining_duration) = timeout.wrapping_sub(now) { + return remaining_duration > Duration::from_ms(0); + } + } + false + } + + // Consumes the state and returns the current new permission state at time "now". + // Returns a new state for differing ClockValue frequencies. + pub fn check_expiration(self, now: ClockValue) -> TimedPermission { + if let TimedPermission::Granted(timeout) = self { + if let Some(remaining_duration) = timeout.wrapping_sub(now) { + if remaining_duration > Duration::from_ms(0) { + return TimedPermission::Granted(timeout); + } + } + } + TimedPermission::Waiting + } +} + +#[cfg(feature = "with_ctap1")] +#[derive(Debug)] +pub struct U2fUserPresenceState { + // If user presence was recently requested, its timeout is saved here. + needs_up: TimedPermission, + // Button touch timeouts, while user presence is requested, are saved here. + has_up: TimedPermission, + // This is the timeout duration of user presence requests. + request_duration: Duration, + // This is the timeout duration of button touches. + presence_duration: Duration, +} + +#[cfg(feature = "with_ctap1")] +impl U2fUserPresenceState { + pub fn new( + request_duration: Duration, + presence_duration: Duration, + ) -> U2fUserPresenceState { + U2fUserPresenceState { + needs_up: TimedPermission::Waiting, + has_up: TimedPermission::Waiting, + request_duration, + presence_duration, + } + } + + // Granting user presence is ignored if it needs activation, but waits. Also cleans up. + pub fn grant_up(&mut self, now: ClockValue) { + self.check_expiration(now); + if self.needs_up.is_granted(now) { + self.needs_up = TimedPermission::Waiting; + self.has_up = TimedPermission::granted(now, self.presence_duration); + } + } + + // This marks user presence as needed or uses it up if already granted. Also cleans up. + pub fn consume_up(&mut self, now: ClockValue) -> bool { + self.check_expiration(now); + if self.has_up.is_granted(now) { + self.has_up = TimedPermission::Waiting; + true + } else { + self.needs_up = TimedPermission::granted(now, self.request_duration); + false + } + } + + // Returns if user presence was requested. Also cleans up. + pub fn is_up_needed(&mut self, now: ClockValue) -> bool { + self.check_expiration(now); + self.needs_up.is_granted(now) + } + + // If you don't regularly call any other function, not cleaning up leads to overflow problems. + pub fn check_expiration(&mut self, now: ClockValue) { + self.needs_up = self.needs_up.check_expiration(now); + self.has_up = self.has_up.check_expiration(now); + } +} + +#[cfg(feature = "with_ctap1")] +#[cfg(test)] +mod test { + use super::*; + use core::isize; + + const CLOCK_FREQUENCY_HZ: usize = 32768; + const ZERO: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ); + const BIG_POSITIVE: ClockValue = ClockValue::new(isize::MAX / 1000 - 1, CLOCK_FREQUENCY_HZ); + const NEGATIVE: ClockValue = ClockValue::new(-1, CLOCK_FREQUENCY_HZ); + const SMALL_NEGATIVE: ClockValue = ClockValue::new(isize::MIN / 1000 + 1, CLOCK_FREQUENCY_HZ); + const REQUEST_DURATION: Duration = Duration::from_ms(1000); + const PRESENCE_DURATION: Duration = Duration::from_ms(1000); + + fn grant_up_when_needed(start_time: ClockValue) { + let mut u2f_state = U2fUserPresenceState::new(REQUEST_DURATION, PRESENCE_DURATION); + assert!(!u2f_state.consume_up(start_time)); + assert!(u2f_state.is_up_needed(start_time)); + u2f_state.grant_up(start_time); + assert!(u2f_state.consume_up(start_time)); + assert!(!u2f_state.consume_up(start_time)); + } + + fn need_up_timeout(start_time: ClockValue) { + let mut u2f_state = U2fUserPresenceState::new(REQUEST_DURATION, PRESENCE_DURATION); + assert!(!u2f_state.consume_up(start_time)); + assert!(u2f_state.is_up_needed(start_time)); + // The timeout excludes equality, so it should be over at this instant. + assert!(!u2f_state.is_up_needed(start_time.wrapping_add(REQUEST_DURATION))); + } + + fn grant_up_timeout(start_time: ClockValue) { + let mut u2f_state = U2fUserPresenceState::new(REQUEST_DURATION, PRESENCE_DURATION); + assert!(!u2f_state.consume_up(start_time)); + assert!(u2f_state.is_up_needed(start_time)); + u2f_state.grant_up(start_time); + // The timeout excludes equality, so it should be over at this instant. + assert!(!u2f_state.consume_up(start_time.wrapping_add(PRESENCE_DURATION))); + } + + #[test] + fn test_grant_up_timeout() { + grant_up_timeout(ZERO); + grant_up_timeout(BIG_POSITIVE); + grant_up_timeout(NEGATIVE); + grant_up_timeout(SMALL_NEGATIVE); + } + + #[test] + fn test_need_up_timeout() { + need_up_timeout(ZERO); + need_up_timeout(BIG_POSITIVE); + need_up_timeout(NEGATIVE); + need_up_timeout(SMALL_NEGATIVE); + } + + #[test] + fn test_grant_up_when_needed() { + grant_up_when_needed(ZERO); + grant_up_when_needed(BIG_POSITIVE); + grant_up_when_needed(NEGATIVE); + grant_up_when_needed(SMALL_NEGATIVE); + } + + #[test] + fn test_grant_up_without_need() { + let mut u2f_state = U2fUserPresenceState::new(REQUEST_DURATION, PRESENCE_DURATION); + u2f_state.grant_up(ZERO); + assert!(!u2f_state.is_up_needed(ZERO)); + assert!(!u2f_state.consume_up(ZERO)); + } +} diff --git a/src/embedded_flash/buffer.rs b/src/embedded_flash/buffer.rs new file mode 100644 index 0000000..b7cf3f1 --- /dev/null +++ b/src/embedded_flash/buffer.rs @@ -0,0 +1,455 @@ +// Copyright 2019 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. + +use super::{Index, Storage, StorageError, StorageResult}; + +pub struct BufferStorage { + storage: Box<[u8]>, + options: BufferOptions, + word_writes: Box<[usize]>, + page_erases: Box<[usize]>, + snapshot: Snapshot, +} + +#[derive(Copy, Clone, Debug)] +pub struct BufferOptions { + /// Size of a word in bytes. + pub word_size: usize, + + /// Size of a page in bytes. + pub page_size: usize, + + /// How many times a word can be written between page erasures + pub max_word_writes: usize, + + /// How many times a page can be erased. + pub max_page_erases: usize, + + /// Bits cannot be written from 0 to 1. + pub strict_write: bool, +} + +impl BufferStorage { + /// Creates a fake embedded flash using a buffer. + /// + /// This implementation checks that no words are written more than `max_word_writes` between + /// page erasures and than no pages are erased more than `max_page_erases`. If `strict_write` is + /// true, it also checks that no bits are written from 0 to 1. It also permits to take snapshots + /// of the storage during write and erase operations (although words would still be written or + /// erased completely). + /// + /// # Panics + /// + /// The following preconditions must hold: + /// - `options.word_size` must be a power of two. + /// - `options.page_size` must be a power of two. + /// - `options.page_size` must be word-aligned. + /// - `storage.len()` must be page-aligned. + pub fn new(storage: Box<[u8]>, options: BufferOptions) -> BufferStorage { + assert!(options.word_size.is_power_of_two()); + assert!(options.page_size.is_power_of_two()); + let num_words = storage.len() / options.word_size; + let num_pages = storage.len() / options.page_size; + let buffer = BufferStorage { + storage, + options, + word_writes: vec![0; num_words].into_boxed_slice(), + page_erases: vec![0; num_pages].into_boxed_slice(), + snapshot: Snapshot::Ready, + }; + assert!(buffer.is_word_aligned(buffer.options.page_size)); + assert!(buffer.is_page_aligned(buffer.storage.len())); + buffer + } + + /// Takes a snapshot of the storage after a given amount of word operations. + /// + /// Each time a word is written or erased, the delay is decremented if positive. Otherwise, a + /// snapshot is taken before the operation is executed. + /// + /// # Panics + /// + /// Panics if a snapshot has been armed and not examined. + pub fn arm_snapshot(&mut self, delay: usize) { + self.snapshot.arm(delay); + } + + /// Unarms and returns the snapshot or the delay remaining. + /// + /// # Panics + /// + /// Panics if a snapshot was not armed. + pub fn get_snapshot(&mut self) -> Result, usize> { + self.snapshot.get() + } + + /// Takes a snapshot of the storage. + pub fn take_snapshot(&self) -> Box<[u8]> { + self.storage.clone() + } + + /// Returns the storage. + pub fn get_storage(self) -> Box<[u8]> { + self.storage + } + + fn is_word_aligned(&self, x: usize) -> bool { + x & (self.options.word_size - 1) == 0 + } + + fn is_page_aligned(&self, x: usize) -> bool { + x & (self.options.page_size - 1) == 0 + } + + /// Writes a slice to the storage. + /// + /// The slice `value` is written to `index`. The `erase` boolean specifies whether this is an + /// erase operation or a write operation which matters for the checks and updating the shadow + /// storage. This also takes a snapshot of the storage if a snapshot was armed and the delay has + /// elapsed. + /// + /// The following preconditions should hold: + /// - `index` is word-aligned. + /// - `value.len()` is word-aligned. + /// + /// The following checks are performed: + /// - The region of length `value.len()` starting at `index` fits in a storage page. + /// - A word is not written more than `max_word_writes`. + /// - A page is not erased more than `max_page_erases`. + /// - The new word only switches 1s to 0s (only if `strict_write` is set). + fn update_storage(&mut self, index: Index, value: &[u8], erase: bool) -> StorageResult<()> { + debug_assert!(self.is_word_aligned(index.byte) && self.is_word_aligned(value.len())); + let dst = index.range(value.len(), self)?.step_by(self.word_size()); + let src = value.chunks(self.word_size()); + // Check and update page shadow. + if erase { + let page = index.page; + assert!(self.page_erases[page] < self.max_page_erases()); + self.page_erases[page] += 1; + } + for (byte, val) in dst.zip(src) { + let range = byte..byte + self.word_size(); + // The driver doesn't write identical words. + if &self.storage[range.clone()] == val { + continue; + } + // Check and update word shadow. + let word = byte / self.word_size(); + if erase { + self.word_writes[word] = 0; + } else { + assert!(self.word_writes[word] < self.max_word_writes()); + self.word_writes[word] += 1; + } + // Check strict write. + if !erase && self.options.strict_write { + for (byte, &val) in range.clone().zip(val) { + assert_eq!(self.storage[byte] & val, val); + } + } + // Take snapshot if armed and delay expired. + self.snapshot.take(&self.storage); + // Write storage + self.storage[range].copy_from_slice(val); + } + Ok(()) + } +} + +impl Storage for BufferStorage { + fn word_size(&self) -> usize { + self.options.word_size + } + + fn page_size(&self) -> usize { + self.options.page_size + } + + fn num_pages(&self) -> usize { + self.storage.len() / self.options.page_size + } + + fn max_word_writes(&self) -> usize { + self.options.max_word_writes + } + + fn max_page_erases(&self) -> usize { + self.options.max_page_erases + } + + fn read_slice(&self, index: Index, length: usize) -> StorageResult<&[u8]> { + Ok(&self.storage[index.range(length, self)?]) + } + + fn write_slice(&mut self, index: Index, value: &[u8]) -> StorageResult<()> { + if !self.is_word_aligned(index.byte) || !self.is_word_aligned(value.len()) { + return Err(StorageError::NotAligned); + } + self.update_storage(index, value, false) + } + + fn erase_page(&mut self, page: usize) -> StorageResult<()> { + let index = Index { page, byte: 0 }; + let value = vec![0xff; self.page_size()]; + self.update_storage(index, &value, true) + } +} + +// Controls when a snapshot of the storage is taken. +// +// This can be used to simulate power-offs while the device is writing to the storage or erasing a +// page in the storage. +enum Snapshot { + // Mutable word operations have normal behavior. + Ready, + // If the delay is positive, mutable word operations decrement it. If the count is zero, mutable + // word operations take a snapshot of the storage. + Armed { delay: usize }, + // Mutable word operations have normal behavior. + Taken { storage: Box<[u8]> }, +} + +impl Snapshot { + fn arm(&mut self, delay: usize) { + match self { + Snapshot::Ready => *self = Snapshot::Armed { delay }, + _ => panic!(), + } + } + + fn get(&mut self) -> Result, usize> { + let mut snapshot = Snapshot::Ready; + std::mem::swap(self, &mut snapshot); + match snapshot { + Snapshot::Armed { delay } => Err(delay), + Snapshot::Taken { storage } => Ok(storage), + _ => panic!(), + } + } + + fn take(&mut self, storage: &[u8]) { + if let Snapshot::Armed { delay } = self { + if *delay == 0 { + let storage = storage.to_vec().into_boxed_slice(); + *self = Snapshot::Taken { storage }; + } else { + *delay -= 1; + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const NUM_PAGES: usize = 2; + const OPTIONS: BufferOptions = BufferOptions { + word_size: 4, + page_size: 16, + max_word_writes: 2, + max_page_erases: 3, + strict_write: true, + }; + // Those words are decreasing bit patterns. Bits are only changed from 1 to 0 and at last one + // bit is changed. + const BLANK_WORD: &[u8] = &[0xff, 0xff, 0xff, 0xff]; + const FIRST_WORD: &[u8] = &[0xee, 0xdd, 0xbb, 0x77]; + const SECOND_WORD: &[u8] = &[0xca, 0xc9, 0xa9, 0x65]; + const THIRD_WORD: &[u8] = &[0x88, 0x88, 0x88, 0x44]; + + fn new_storage() -> Box<[u8]> { + vec![0xff; NUM_PAGES * OPTIONS.page_size].into_boxed_slice() + } + + #[test] + fn words_are_decreasing() { + fn assert_is_decreasing(prev: &[u8], next: &[u8]) { + for (&prev, &next) in prev.iter().zip(next.iter()) { + assert_eq!(prev & next, next); + assert!(prev != next); + } + } + assert_is_decreasing(BLANK_WORD, FIRST_WORD); + assert_is_decreasing(FIRST_WORD, SECOND_WORD); + assert_is_decreasing(SECOND_WORD, THIRD_WORD); + } + + #[test] + fn options_ok() { + let buffer = BufferStorage::new(new_storage(), OPTIONS); + assert_eq!(buffer.word_size(), OPTIONS.word_size); + assert_eq!(buffer.page_size(), OPTIONS.page_size); + assert_eq!(buffer.num_pages(), NUM_PAGES); + assert_eq!(buffer.max_word_writes(), OPTIONS.max_word_writes); + assert_eq!(buffer.max_page_erases(), OPTIONS.max_page_erases); + } + + #[test] + fn read_write_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 0 }; + let next_index = Index { page: 0, byte: 4 }; + assert_eq!(buffer.read_slice(index, 4).unwrap(), BLANK_WORD); + buffer.write_slice(index, FIRST_WORD).unwrap(); + assert_eq!(buffer.read_slice(index, 4).unwrap(), FIRST_WORD); + assert_eq!(buffer.read_slice(next_index, 4).unwrap(), BLANK_WORD); + } + + #[test] + fn erase_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 0 }; + let other_index = Index { page: 1, byte: 0 }; + buffer.write_slice(index, FIRST_WORD).unwrap(); + buffer.write_slice(other_index, FIRST_WORD).unwrap(); + assert_eq!(buffer.read_slice(index, 4).unwrap(), FIRST_WORD); + assert_eq!(buffer.read_slice(other_index, 4).unwrap(), FIRST_WORD); + buffer.erase_page(0).unwrap(); + assert_eq!(buffer.read_slice(index, 4).unwrap(), BLANK_WORD); + assert_eq!(buffer.read_slice(other_index, 4).unwrap(), FIRST_WORD); + } + + #[test] + fn invalid_range() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 12 }; + let half_index = Index { page: 0, byte: 14 }; + let over_index = Index { page: 0, byte: 16 }; + let bad_page = Index { page: 2, byte: 0 }; + + // Reading a word in the storage is ok. + assert!(buffer.read_slice(index, 4).is_ok()); + // Reading a half-word in the storage is ok. + assert!(buffer.read_slice(half_index, 2).is_ok()); + // Reading even a single byte outside a page is not ok. + assert!(buffer.read_slice(over_index, 1).is_err()); + // But reading an empty slice just after a page is ok. + assert!(buffer.read_slice(over_index, 0).is_ok()); + // Reading even an empty slice outside the storage is not ok. + assert!(buffer.read_slice(bad_page, 0).is_err()); + + // Writing a word in the storage is ok. + assert!(buffer.write_slice(index, FIRST_WORD).is_ok()); + // Writing an unaligned word is not ok. + assert!(buffer.write_slice(half_index, FIRST_WORD).is_err()); + // Writing a word outside a page is not ok. + assert!(buffer.write_slice(over_index, FIRST_WORD).is_err()); + // But writing an empty slice just after a page is ok. + assert!(buffer.write_slice(over_index, &[]).is_ok()); + // Writing even an empty slice outside the storage is not ok. + assert!(buffer.write_slice(bad_page, &[]).is_err()); + + // Only pages in the storage can be erased. + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(2).is_err()); + } + + #[test] + fn write_twice_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 4 }; + assert!(buffer.write_slice(index, FIRST_WORD).is_ok()); + assert!(buffer.write_slice(index, SECOND_WORD).is_ok()); + } + + #[test] + fn write_twice_and_once_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 0 }; + let next_index = Index { page: 0, byte: 4 }; + assert!(buffer.write_slice(index, FIRST_WORD).is_ok()); + assert!(buffer.write_slice(index, SECOND_WORD).is_ok()); + assert!(buffer.write_slice(next_index, THIRD_WORD).is_ok()); + } + + #[test] + #[should_panic] + fn write_three_times_panics() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 4 }; + assert!(buffer.write_slice(index, FIRST_WORD).is_ok()); + assert!(buffer.write_slice(index, SECOND_WORD).is_ok()); + let _ = buffer.write_slice(index, THIRD_WORD); + } + + #[test] + fn write_twice_then_once_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 0 }; + assert!(buffer.write_slice(index, FIRST_WORD).is_ok()); + assert!(buffer.write_slice(index, SECOND_WORD).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.write_slice(index, FIRST_WORD).is_ok()); + } + + #[test] + fn erase_three_times_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + } + + #[test] + fn erase_three_times_and_once_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(1).is_ok()); + } + + #[test] + #[should_panic] + fn erase_four_times_panics() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + assert!(buffer.erase_page(0).is_ok()); + let _ = buffer.erase_page(0).is_ok(); + } + + #[test] + #[should_panic] + fn switch_zero_to_one_panics() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 0 }; + assert!(buffer.write_slice(index, SECOND_WORD).is_ok()); + let _ = buffer.write_slice(index, FIRST_WORD); + } + + #[test] + fn get_storage_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 4 }; + buffer.write_slice(index, FIRST_WORD).unwrap(); + let storage = buffer.get_storage(); + assert_eq!(&storage[..4], BLANK_WORD); + assert_eq!(&storage[4..8], FIRST_WORD); + } + + #[test] + fn snapshot_ok() { + let mut buffer = BufferStorage::new(new_storage(), OPTIONS); + let index = Index { page: 0, byte: 0 }; + let value = [FIRST_WORD, SECOND_WORD].concat(); + buffer.arm_snapshot(1); + buffer.write_slice(index, &value).unwrap(); + let storage = buffer.get_snapshot().unwrap(); + assert_eq!(&storage[..8], &[FIRST_WORD, BLANK_WORD].concat()[..]); + let storage = buffer.take_snapshot(); + assert_eq!(&storage[..8], &value[..]); + } +} diff --git a/src/embedded_flash/mod.rs b/src/embedded_flash/mod.rs new file mode 100644 index 0000000..5e54059 --- /dev/null +++ b/src/embedded_flash/mod.rs @@ -0,0 +1,25 @@ +// Copyright 2019 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. + +#[cfg(feature = "std")] +mod buffer; +mod storage; +mod store; +mod syscall; + +#[cfg(feature = "std")] +pub use self::buffer::{BufferOptions, BufferStorage}; +pub use self::storage::{Index, Storage, StorageError, StorageResult}; +pub use self::store::{Store, StoreConfig, StoreEntry, StoreError, StoreIndex}; +pub use self::syscall::SyscallStorage; diff --git a/src/embedded_flash/storage.rs b/src/embedded_flash/storage.rs new file mode 100644 index 0000000..fe87ac4 --- /dev/null +++ b/src/embedded_flash/storage.rs @@ -0,0 +1,107 @@ +// Copyright 2019 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. + +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Index { + pub page: usize, + pub byte: usize, +} + +#[derive(Debug)] +pub enum StorageError { + BadFlash, + NotAligned, + OutOfBounds, + KernelError { code: isize }, +} + +pub type StorageResult = Result; + +/// Abstraction for embedded flash storage. +pub trait Storage { + /// Returns the size of a word in bytes. + fn word_size(&self) -> usize; + + /// Returns the size of a page in bytes. + fn page_size(&self) -> usize; + + /// Returns the number of pages in the storage. + fn num_pages(&self) -> usize; + + /// Returns how many times a word can be written between page erasures. + fn max_word_writes(&self) -> usize; + + /// Returns how many times a page can be erased in the lifetime of the flash. + fn max_page_erases(&self) -> usize; + + /// Reads a slice from the storage. + /// + /// The slice does not need to be word-aligned. + /// + /// # Errors + /// + /// The `index` must designate `length` bytes in the storage. + fn read_slice(&self, index: Index, length: usize) -> StorageResult<&[u8]>; + + /// Writes a word-aligned slice to the storage. + /// + /// The written words should not have been written too many times since last page erasure. + /// + /// # Errors + /// + /// The following preconditions must hold: + /// - `index` must be word-aligned. + /// - `value.len()` must be a multiple of the word size. + /// - `index` must designate `value.len()` bytes in the storage. + /// - `value` must be in memory until [read-only allow][tock_1274] is resolved. + /// + /// [tock_1274]: https://github.com/tock/tock/issues/1274. + fn write_slice(&mut self, index: Index, value: &[u8]) -> StorageResult<()>; + + /// Erases a page of the storage. + /// + /// # Errors + /// + /// The `page` must be in the storage. + fn erase_page(&mut self, page: usize) -> StorageResult<()>; +} + +impl Index { + /// Returns whether a slice fits in a storage page. + fn is_valid(self, length: usize, storage: &impl Storage) -> bool { + self.page < storage.num_pages() + && storage + .page_size() + .checked_sub(length) + .map(|limit| self.byte <= limit) + .unwrap_or(false) + } + + /// Returns the range of a valid slice. + /// + /// The range starts at `self` with `length` bytes. + pub fn range( + self, + length: usize, + storage: &impl Storage, + ) -> StorageResult> { + if self.is_valid(length, storage) { + let start = self.page * storage.page_size() + self.byte; + Ok(start..start + length) + } else { + Err(StorageError::OutOfBounds) + } + } +} diff --git a/src/embedded_flash/store/bitfield.rs b/src/embedded_flash/store/bitfield.rs new file mode 100644 index 0000000..60c6f86 --- /dev/null +++ b/src/embedded_flash/store/bitfield.rs @@ -0,0 +1,172 @@ +// Copyright 2019 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. + +/// Defines a consecutive sequence of bits. +#[derive(Copy, Clone)] +pub struct BitRange { + /// The first bit of the sequence. + pub start: usize, + + /// The length in bits of the sequence. + pub length: usize, +} + +impl BitRange { + /// Returns the first bit following a bit range. + pub fn end(self) -> usize { + self.start + self.length + } +} + +/// Defines a consecutive sequence of bytes. +/// +/// The bits in those bytes are ignored which essentially creates a gap in a sequence of bits. The +/// gap is necessarily at byte boundaries. This is used to ignore the user data in an entry +/// essentially providing a view of the entry information (header and footer). +#[derive(Copy, Clone)] +pub struct ByteGap { + pub start: usize, + pub length: usize, +} + +/// Empty gap. All bits count. +pub const NO_GAP: ByteGap = ByteGap { + start: 0, + length: 0, +}; + +impl ByteGap { + /// Translates a bit to skip the gap. + fn shift(self, bit: usize) -> usize { + if bit < 8 * self.start { + bit + } else { + bit + 8 * self.length + } + } +} + +/// Returns whether a bit is set in a sequence of bits. +/// +/// The sequence of bits is little-endian (both for bytes and bits) and defined by the bits that +/// are in `data` but not in `gap`. +pub fn is_zero(bit: usize, data: &[u8], gap: ByteGap) -> bool { + let bit = gap.shift(bit); + debug_assert!(bit < 8 * data.len()); + data[bit / 8] & (1 << (bit % 8)) == 0 +} + +/// Sets a bit to zero in a sequence of bits. +/// +/// The sequence of bits is little-endian (both for bytes and bits) and defined by the bits that +/// are in `data` but not in `gap`. +pub fn set_zero(bit: usize, data: &mut [u8], gap: ByteGap) { + let bit = gap.shift(bit); + debug_assert!(bit < 8 * data.len()); + data[bit / 8] &= !(1 << (bit % 8)); +} + +/// Returns a little-endian value in a sequence of bits. +/// +/// The sequence of bits is little-endian (both for bytes and bits) and defined by the bits that +/// are in `data` but not in `gap`. The range of bits where the value is stored in defined by +/// `range`. The value must fit in a `usize`. +pub fn get_range(range: BitRange, data: &[u8], gap: ByteGap) -> usize { + debug_assert!(range.length <= 8 * core::mem::size_of::()); + let mut result = 0; + for i in 0..range.length { + if !is_zero(range.start + i, data, gap) { + result |= 1 << i; + } + } + result +} + +/// Sets a little-endian value in a sequence of bits. +/// +/// The sequence of bits is little-endian (both for bytes and bits) and defined by the bits that +/// are in `data` but not in `gap`. The range of bits where the value is stored in defined by +/// `range`. The bits set to 1 in `value` must also be set to `1` in the sequence of bits. +pub fn set_range(range: BitRange, data: &mut [u8], gap: ByteGap, value: usize) { + debug_assert!(range.length == 8 * core::mem::size_of::() || value < 1 << range.length); + for i in 0..range.length { + if value & 1 << i == 0 { + set_zero(range.start + i, data, gap); + } + } +} + +/// Tests the `is_zero` and `set_zero` pair of functions. +#[test] +fn zero_ok() { + const GAP: ByteGap = ByteGap { + start: 2, + length: 1, + }; + for i in 0..24 { + assert!(!is_zero(i, &[0xffu8, 0xff, 0x00, 0xff] as &[u8], GAP)); + } + // Tests reading and setting a bit. The result should have all bits set to 1 except for the bit + // to test and the gap. + fn test(bit: usize, result: &[u8]) { + assert!(is_zero(bit, result, GAP)); + let mut data = vec![0xff; result.len()]; + // Set the gap bits to 0. + for i in 0..GAP.length { + data[GAP.start + i] = 0x00; + } + set_zero(bit, &mut data, GAP); + assert_eq!(data, result); + } + test(0, &[0xfe, 0xff, 0x00, 0xff]); + test(1, &[0xfd, 0xff, 0x00, 0xff]); + test(2, &[0xfb, 0xff, 0x00, 0xff]); + test(7, &[0x7f, 0xff, 0x00, 0xff]); + test(8, &[0xff, 0xfe, 0x00, 0xff]); + test(15, &[0xff, 0x7f, 0x00, 0xff]); + test(16, &[0xff, 0xff, 0x00, 0xfe]); + test(17, &[0xff, 0xff, 0x00, 0xfd]); + test(23, &[0xff, 0xff, 0x00, 0x7f]); +} + +/// Tests the `get_range` and `set_range` pair of functions. +#[test] +fn range_ok() { + // Tests reading and setting a range. The result should have all bits set to 1 except for the + // range to test and the gap. + fn test(start: usize, length: usize, value: usize, result: &[u8], gap: ByteGap) { + let range = BitRange { start, length }; + assert_eq!(get_range(range, result, gap), value); + let mut data = vec![0xff; result.len()]; + for i in 0..gap.length { + data[gap.start + i] = 0x00; + } + set_range(range, &mut data, gap, value); + assert_eq!(data, result); + } + test(0, 8, 42, &[42], NO_GAP); + test(3, 12, 0b11_0101, &[0b1010_1111, 0b1000_0001], NO_GAP); + test(0, 16, 0x1234, &[0x34, 0x12], NO_GAP); + test(4, 16, 0x1234, &[0x4f, 0x23, 0xf1], NO_GAP); + let mut gap = ByteGap { + start: 1, + length: 1, + }; + test(3, 12, 0b11_0101, &[0b1010_1111, 0x00, 0b1000_0001], gap); + gap.length = 2; + test(0, 16, 0x1234, &[0x34, 0x00, 0x00, 0x12], gap); + gap.start = 2; + gap.length = 1; + test(4, 16, 0x1234, &[0x4f, 0x23, 0x00, 0xf1], gap); +} diff --git a/src/embedded_flash/store/format.rs b/src/embedded_flash/store/format.rs new file mode 100644 index 0000000..cbef61f --- /dev/null +++ b/src/embedded_flash/store/format.rs @@ -0,0 +1,514 @@ +// Copyright 2019 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. + +use super::super::{Index, Storage}; +use super::{bitfield, StoreConfig, StoreEntry, StoreError}; +use alloc::vec::Vec; + +/// Whether a user entry is a replace entry. +pub enum IsReplace { + /// This is a replace entry. + Replace, + + /// This is an insert entry. + Insert, +} + +/// Helpers to parse the store format. +/// +/// See the store module-level documentation for information about the format. +pub struct Format { + pub word_size: usize, + pub page_size: usize, + pub num_pages: usize, + pub max_page_erases: usize, + pub num_tags: usize, + + /// Whether an entry is present. + /// + /// - 0 for entries (user entries or internal entries). + /// - 1 for free space until the end of the page. + present_bit: usize, + + /// Whether an entry is deleted. + /// + /// - 0 for deleted entries. + /// - 1 for alive entries. + deleted_bit: usize, + + /// Whether an entry is internal. + /// + /// - 0 for internal entries. + /// - 1 for user entries. + internal_bit: usize, + + /// Whether a user entry is a replace entry. + /// + /// - 0 for replace entries. + /// - 1 for insert entries. + replace_bit: usize, + + /// The data length of a user entry. + length_range: bitfield::BitRange, + + /// The tag of a user entry. + tag_range: bitfield::BitRange, + + /// The page index of a replace entry. + replace_page_range: bitfield::BitRange, + + /// The byte index of a replace entry. + replace_byte_range: bitfield::BitRange, + + /// The index of the page to erase. + /// + /// This is only present for internal entries. + old_page_range: bitfield::BitRange, + + /// The current erase count of the page to erase. + /// + /// This is only present for internal entries. + saved_erase_count_range: bitfield::BitRange, + + /// Whether a page is initialized. + /// + /// - 0 for initialized pages. + /// - 1 for uninitialized pages. + initialized_bit: usize, + + /// The erase count of a page. + erase_count_range: bitfield::BitRange, + + /// Whether a page is being compacted. + /// + /// - 0 for pages being compacted. + /// - 1 otherwise. + compacting_bit: usize, + + /// The page index to which a page is being compacted. + new_page_range: bitfield::BitRange, +} + +impl Format { + /// Returns a helper to parse the store format for a given storage and config. + /// + /// # Errors + /// + /// Returns `None` if any of the following conditions does not hold: + /// - The word size must be a power of two. + /// - The page size must be a power of two. + /// - There should be at least 2 pages in the storage. + /// - It should be possible to write a word at least twice. + /// - It should be possible to erase a page at least once. + /// - There should be at least 1 tag. + pub fn new(storage: &S, config: &C) -> Option { + let word_size = storage.word_size(); + let page_size = storage.page_size(); + let num_pages = storage.num_pages(); + let max_word_writes = storage.max_word_writes(); + let max_page_erases = storage.max_page_erases(); + let num_tags = config.num_tags(); + if !(word_size.is_power_of_two() + && page_size.is_power_of_two() + && num_pages > 1 + && max_word_writes >= 2 + && max_page_erases > 0 + && num_tags > 0) + { + return None; + } + // Compute how many bits we need to store the fields. + let page_bits = num_bits(num_pages); + let byte_bits = num_bits(page_size); + let tag_bits = num_bits(num_tags); + let erase_bits = num_bits(max_page_erases + 1); + // Compute the bit position of the fields. + let present_bit = 0; + let deleted_bit = present_bit + 1; + let internal_bit = deleted_bit + 1; + let replace_bit = internal_bit + 1; + let length_range = bitfield::BitRange { + start: replace_bit + 1, + length: byte_bits, + }; + let tag_range = bitfield::BitRange { + start: length_range.end(), + length: tag_bits, + }; + let replace_page_range = bitfield::BitRange { + start: tag_range.end(), + length: page_bits, + }; + let replace_byte_range = bitfield::BitRange { + start: replace_page_range.end(), + length: byte_bits, + }; + let old_page_range = bitfield::BitRange { + start: internal_bit + 1, + length: page_bits, + }; + let saved_erase_count_range = bitfield::BitRange { + start: old_page_range.end(), + length: erase_bits, + }; + let initialized_bit = 0; + let erase_count_range = bitfield::BitRange { + start: initialized_bit + 1, + length: erase_bits, + }; + let compacting_bit = erase_count_range.end(); + let new_page_range = bitfield::BitRange { + start: compacting_bit + 1, + length: page_bits, + }; + let format = Format { + word_size, + page_size, + num_pages, + max_page_erases, + num_tags, + present_bit, + deleted_bit, + internal_bit, + replace_bit, + length_range, + tag_range, + replace_page_range, + replace_byte_range, + old_page_range, + saved_erase_count_range, + initialized_bit, + erase_count_range, + compacting_bit, + new_page_range, + }; + // Make sure all the following conditions hold: + // - The page header is one word. + // - The internal entry is one word. + // - The entry header fits in one word. + if format.page_header_size() != word_size + || format.internal_entry_size() != word_size + || format.header_size() > word_size + { + return None; + } + Some(format) + } + + /// Ensures a user entry is valid. + pub fn validate_entry(&self, entry: StoreEntry) -> Result<(), StoreError> { + if entry.tag >= self.num_tags { + return Err(StoreError::InvalidTag); + } + if entry.data.len() >= self.page_size { + return Err(StoreError::StoreFull); + } + Ok(()) + } + + /// Returns the entry header length in bytes. + /// + /// This is the smallest number of bytes necessary to store all fields of the entry info up to + /// and including `length`. + pub fn header_size(&self) -> usize { + self.bits_to_bytes(self.length_range.end()) + } + + /// Returns the entry info length in bytes. + /// + /// This is the number of bytes necessary to store all fields of the entry info. This also + /// includes the internal padding to protect the `committed` bit from the `deleted` bit. + fn info_size(&self, is_replace: IsReplace) -> usize { + let suffix_bits = 2; // committed + complete + let info_bits = match is_replace { + IsReplace::Replace => self.replace_byte_range.end() + suffix_bits, + IsReplace::Insert => self.tag_range.end() + suffix_bits, + }; + let info_size = self.bits_to_bytes(info_bits); + // If the suffix bits would end up in the header, we need to add one byte for them. + if info_size == self.header_size() { + info_size + 1 + } else { + info_size + } + } + + /// Returns the length in bytes of an entry. + /// + /// This depends on the length of the user data and whether the entry replaces an old entry or + /// is an insertion. This also includes the internal padding to protect the `committed` bit from + /// the `deleted` bit. + pub fn entry_size(&self, is_replace: IsReplace, length: usize) -> usize { + let mut entry_size = length + self.info_size(is_replace); + let word_size = self.word_size; + entry_size = self.align_word(entry_size); + // The entry must be at least 2 words such that the `committed` and `deleted` bits are on + // different words. + if entry_size == word_size { + entry_size += word_size; + } + entry_size + } + + /// Returns the length in bytes of an internal entry. + pub fn internal_entry_size(&self) -> usize { + let length = self.bits_to_bytes(self.saved_erase_count_range.end()); + self.align_word(length) + } + + pub fn is_present(&self, header: &[u8]) -> bool { + bitfield::is_zero(self.present_bit, header, bitfield::NO_GAP) + } + + pub fn set_present(&self, header: &mut [u8]) { + bitfield::set_zero(self.present_bit, header, bitfield::NO_GAP) + } + + pub fn is_deleted(&self, header: &[u8]) -> bool { + bitfield::is_zero(self.deleted_bit, header, bitfield::NO_GAP) + } + + /// Returns whether an entry is present and not deleted. + pub fn is_alive(&self, header: &[u8]) -> bool { + self.is_present(header) && !self.is_deleted(header) + } + + pub fn set_deleted(&self, header: &mut [u8]) { + bitfield::set_zero(self.deleted_bit, header, bitfield::NO_GAP) + } + + pub fn is_internal(&self, header: &[u8]) -> bool { + bitfield::is_zero(self.internal_bit, header, bitfield::NO_GAP) + } + + pub fn set_internal(&self, header: &mut [u8]) { + bitfield::set_zero(self.internal_bit, header, bitfield::NO_GAP) + } + + pub fn is_replace(&self, header: &[u8]) -> IsReplace { + if bitfield::is_zero(self.replace_bit, header, bitfield::NO_GAP) { + IsReplace::Replace + } else { + IsReplace::Insert + } + } + + fn set_replace(&self, header: &mut [u8]) { + bitfield::set_zero(self.replace_bit, header, bitfield::NO_GAP) + } + + pub fn get_length(&self, header: &[u8]) -> usize { + bitfield::get_range(self.length_range, header, bitfield::NO_GAP) + } + + fn set_length(&self, header: &mut [u8], length: usize) { + bitfield::set_range(self.length_range, header, bitfield::NO_GAP, length) + } + + pub fn get_data<'a>(&self, entry: &'a [u8]) -> &'a [u8] { + &entry[self.header_size()..][..self.get_length(entry)] + } + + /// Returns the span of user data in an entry. + /// + /// The complement of this gap in the entry is exactly the entry info. The header is before the + /// gap and the footer is after the gap. + fn entry_gap(&self, entry: &[u8]) -> bitfield::ByteGap { + let start = self.header_size(); + let length = self.get_length(entry); + bitfield::ByteGap { start, length } + } + + pub fn get_tag(&self, entry: &[u8]) -> usize { + bitfield::get_range(self.tag_range, entry, self.entry_gap(entry)) + } + + fn set_tag(&self, entry: &mut [u8], tag: usize) { + bitfield::set_range(self.tag_range, entry, self.entry_gap(entry), tag) + } + + pub fn get_replace_index(&self, entry: &[u8]) -> Index { + let gap = self.entry_gap(entry); + let page = bitfield::get_range(self.replace_page_range, entry, gap); + let byte = bitfield::get_range(self.replace_byte_range, entry, gap); + Index { page, byte } + } + + fn set_replace_page(&self, entry: &mut [u8], page: usize) { + bitfield::set_range(self.replace_page_range, entry, self.entry_gap(entry), page) + } + + fn set_replace_byte(&self, entry: &mut [u8], byte: usize) { + bitfield::set_range(self.replace_byte_range, entry, self.entry_gap(entry), byte) + } + + /// Returns the bit position of the `committed` bit. + /// + /// This cannot be precomputed like other fields since it depends on the length of the entry. + fn committed_bit(&self, entry: &[u8]) -> usize { + 8 * entry.len() - 2 + } + + /// Returns the bit position of the `complete` bit. + /// + /// This cannot be precomputed like other fields since it depends on the length of the entry. + fn complete_bit(&self, entry: &[u8]) -> usize { + 8 * entry.len() - 1 + } + + pub fn is_committed(&self, entry: &[u8]) -> bool { + bitfield::is_zero(self.committed_bit(entry), entry, bitfield::NO_GAP) + } + + pub fn set_committed(&self, entry: &mut [u8]) { + bitfield::set_zero(self.committed_bit(entry), entry, bitfield::NO_GAP) + } + + pub fn is_complete(&self, entry: &[u8]) -> bool { + bitfield::is_zero(self.complete_bit(entry), entry, bitfield::NO_GAP) + } + + fn set_complete(&self, entry: &mut [u8]) { + bitfield::set_zero(self.complete_bit(entry), entry, bitfield::NO_GAP) + } + + pub fn get_old_page(&self, header: &[u8]) -> usize { + bitfield::get_range(self.old_page_range, header, bitfield::NO_GAP) + } + + pub fn set_old_page(&self, header: &mut [u8], old_page: usize) { + bitfield::set_range(self.old_page_range, header, bitfield::NO_GAP, old_page) + } + + pub fn get_saved_erase_count(&self, header: &[u8]) -> usize { + bitfield::get_range(self.saved_erase_count_range, header, bitfield::NO_GAP) + } + + pub fn set_saved_erase_count(&self, header: &mut [u8], erase_count: usize) { + bitfield::set_range( + self.saved_erase_count_range, + header, + bitfield::NO_GAP, + erase_count, + ) + } + + /// Builds an entry for replace or insert operations. + pub fn build_entry(&self, replace: Option, user_entry: StoreEntry) -> Vec { + let StoreEntry { tag, data } = user_entry; + let is_replace = match replace { + None => IsReplace::Insert, + Some(_) => IsReplace::Replace, + }; + let entry_len = self.entry_size(is_replace, data.len()); + let mut entry = Vec::with_capacity(entry_len); + // Build the header. + entry.resize(self.header_size(), 0xff); + self.set_present(&mut entry[..]); + self.set_length(&mut entry[..], data.len()); + // Add the data. + entry.extend_from_slice(data); + // Build the footer. + entry.resize(entry_len, 0xff); + self.set_tag(&mut entry[..], tag); + self.set_complete(&mut entry[..]); + match replace { + None => self.set_committed(&mut entry[..]), + Some(Index { page, byte }) => { + self.set_replace(&mut entry[..]); + self.set_replace_page(&mut entry[..], page); + self.set_replace_byte(&mut entry[..], byte); + } + } + entry + } + + /// Builds an entry for replace or insert operations. + pub fn build_erase_entry(&self, old_page: usize, saved_erase_count: usize) -> Vec { + let mut entry = vec![0xff; self.internal_entry_size()]; + self.set_present(&mut entry[..]); + self.set_internal(&mut entry[..]); + self.set_old_page(&mut entry[..], old_page); + self.set_saved_erase_count(&mut entry[..], saved_erase_count); + entry + } + + /// Returns the length in bytes of a page header entry. + /// + /// This includes the word padding. + pub fn page_header_size(&self) -> usize { + self.align_word(self.bits_to_bytes(self.erase_count_range.end())) + } + + pub fn is_initialized(&self, header: &[u8]) -> bool { + bitfield::is_zero(self.initialized_bit, header, bitfield::NO_GAP) + } + + pub fn set_initialized(&self, header: &mut [u8]) { + bitfield::set_zero(self.initialized_bit, header, bitfield::NO_GAP) + } + + pub fn get_erase_count(&self, header: &[u8]) -> usize { + bitfield::get_range(self.erase_count_range, header, bitfield::NO_GAP) + } + + pub fn set_erase_count(&self, header: &mut [u8], count: usize) { + bitfield::set_range(self.erase_count_range, header, bitfield::NO_GAP, count) + } + + pub fn is_compacting(&self, header: &[u8]) -> bool { + bitfield::is_zero(self.compacting_bit, header, bitfield::NO_GAP) + } + + pub fn set_compacting(&self, header: &mut [u8]) { + bitfield::set_zero(self.compacting_bit, header, bitfield::NO_GAP) + } + + pub fn get_new_page(&self, header: &[u8]) -> usize { + bitfield::get_range(self.new_page_range, header, bitfield::NO_GAP) + } + + pub fn set_new_page(&self, header: &mut [u8], new_page: usize) { + bitfield::set_range(self.new_page_range, header, bitfield::NO_GAP, new_page) + } + + /// Returns the smallest word boundary greater or equal to a value. + fn align_word(&self, value: usize) -> usize { + let word_size = self.word_size; + (value + word_size - 1) / word_size * word_size + } + + /// Returns the minimum number of bytes to represent a given number of bits. + fn bits_to_bytes(&self, bits: usize) -> usize { + (bits + 7) / 8 + } +} + +/// Returns the number of bits necessary to write numbers smaller than `x`. +fn num_bits(x: usize) -> usize { + x.next_power_of_two().trailing_zeros() as usize +} + +#[test] +fn num_bits_ok() { + assert_eq!(num_bits(0), 0); + assert_eq!(num_bits(1), 0); + assert_eq!(num_bits(2), 1); + assert_eq!(num_bits(3), 2); + assert_eq!(num_bits(4), 2); + assert_eq!(num_bits(5), 3); + assert_eq!(num_bits(8), 3); + assert_eq!(num_bits(9), 4); + assert_eq!(num_bits(16), 4); +} diff --git a/src/embedded_flash/store/mod.rs b/src/embedded_flash/store/mod.rs new file mode 100644 index 0000000..0431073 --- /dev/null +++ b/src/embedded_flash/store/mod.rs @@ -0,0 +1,1028 @@ +// Copyright 2019 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. + +//! Provides a multi-purpose data-structure. +//! +//! # Description +//! +//! The `Store` data-structure permits to iterate, find, insert, delete, and replace entries in a +//! multi-set. The mutable operations (insert, delete, and replace) are atomic, in the sense that if +//! power is lost during the operation, then the operation might either succeed or fail but the +//! store remains in a coherent state. The data-structure is flash-efficient, in the sense that it +//! tries to minimize the number of times a page is erased. +//! +//! An _entry_ is made of a _tag_, which is a number, and a _data_, which is a slice of bytes. The +//! tag is stored efficiently by using unassigned bits of the entry header and footer. For example, +//! it can be used to decide how to deserialize the data. It is not necessary to use tags since a +//! prefix of the data could be used to decide how to deserialize the rest. +//! +//! Entries can also be associated to a set of _keys_. The find operation permits to retrieve all +//! entries associated to a given key. The same key can be associated to multiple entries and the +//! same entry can be associated to multiple keys. +//! +//! # Storage +//! +//! The data-structure is parametric over its storage which must implement the `Storage` trait. +//! There are currently 2 implementations of this trait: +//! - `SyscallStorage` using the `embedded_flash` syscall API for production builds. +//! - `BufferStorage` using a heap-allocated buffer for testing. +//! +//! # Configuration +//! +//! The data-structure can be configured with the `StoreConfig` trait. By implementing this trait, +//! the number of possible tags and the association between keys and entries are defined. +//! +//! # Implementation +//! +//! The store is a page-aligned sequence of bits. It matches the following grammar: +//! +//! ```text +//! Store := Page* +//! Page := PageHeader (Entry | InternalEntry)* Padding(page) +//! PageHeader := // must fit in one word +//! initialized:1 +//! erase_count:erase_bits +//! compacting:1 +//! new_page:page_bits +//! Padding(word) +//! Entry := Header Data Footer +//! // Let X be the byte following `length` in `Info`. +//! Header := Info[..X] // must fit in one word +//! Footer := Info[X..] // must fit in one word +//! Info := +//! present=0 +//! deleted:1 +//! internal=1 +//! replace:1 +//! length:byte_bits +//! tag:tag_bits +//! [ // present if `replace` is 0 +//! replace_page:page_bits +//! replace_byte:byte_bits +//! ] +//! [Padding(bit)] // until `complete` is the last bit of a different word than `present` +//! committed:1 +//! complete=0 +//! InternalEntry := +//! present=0 +//! deleted:1 +//! internal=0 +//! old_page:page_bits +//! saved_erase_count:erase_bits +//! Padding(word) +//! Padding(X) := 1* until X-aligned +//! ``` +//! +//! For bit flags, a value of 0 means true and a value of 1 means false. So when erased, bits are +//! false. They can be set to true by writing 0. +//! +//! The `Entry` rule is for user entries and the `InternalEntry` rule is for internal entries of the +//! store. Currently, there is only one kind of internal entry: an entry to erase the page being +//! compacted. +//! +//! The `Header` and `Footer` rules are computed from the `Info` rule. An entry could simply be the +//! concatenation of internal metadata and the user data. However, to optimize the size in flash, we +//! splice the user data in the middle of the metadata. The reason is that we can only write twice +//! the same word and for replace entries we need to write the deleted bit and the committed bit +//! independently. Also, this is important for the complete bit to be the last written bit (since +//! slices are written to flash from low to high addresses). Here is the representation of a +//! specific replace entry for a specific configuration: +//! +//! ```text +//! page_bits=6 +//! byte_bits=9 +//! tag_bits=5 +//! +//! byte.bit name +//! 0.0 present +//! 0.1 deleted +//! 0.2 internal +//! 0.3 replace +//! 0.4 length (9 bits) +//! 1.5 tag (least significant 3 bits out of 5) +//! (the header ends at the first byte boundary after `length`) +//! 2.0 (2 bytes in this example) +//! (the footer starts immediately after the user data) +//! 4.0 tag (most significant 2 bits out of 5) +//! 4.2 replace_page (6 bits) +//! 5.0 replace_byte (9 bits) +//! 6.1 padding (make sure the 2 properties below hold) +//! 7.6 committed +//! 7.7 complete (on a different word than `present`) +//! 8.0 (word-aligned) +//! ``` +//! +//! The store should always contain at least one blank page, so that it is always possible to +//! compact. + +// TODO(cretin): We don't need inner padding for insert entries. The store format can be: +// InsertEntry | ReplaceEntry | InternalEntry (maybe rename to EraseEntry) +// InsertEntry padding is until `complete` is the last bit of a word. +// ReplaceEntry padding is until `complete` is the last bit of a different word than `present`. +// TODO(cretin): Add checksum (may play the same role as the completed bit) and recovery strategy? +// TODO(cretin): Add corruption (deterministic but undetermined reads) to fuzzing. +// TODO(cretin): Add more complex transactions? (this does not seem necessary yet) +// TODO(cretin): Add possibility to shred an entry (force compact page after delete)? + +mod bitfield; +mod format; + +use self::format::{Format, IsReplace}; +#[cfg(feature = "std")] +use super::BufferStorage; +use super::{Index, Storage}; +use alloc::collections::BTreeMap; +use alloc::vec::Vec; + +/// Configures a store. +pub trait StoreConfig { + /// How entries are keyed. + /// + /// To disable keys, this may be defined to `()` or even better a custom empty enum. + type Key: Ord; + + /// Number of entry tags. + /// + /// All tags must be smaller than this value. + /// + /// To disable tags, this function should return `1`. The only valid tag would then be `0`. + fn num_tags(&self) -> usize; + + /// Specifies the set of keys of an entry. + /// + /// If keys are not used, this function can immediately return. Otherwise, it should call + /// `associate_key` for each key that should be associated to `entry`. + fn keys(&self, entry: StoreEntry, associate_key: impl FnMut(Self::Key)); +} + +/// Errors returned by store operations. +#[derive(Debug, PartialEq, Eq)] +pub enum StoreError { + /// The operation could not proceed because the store is full. + StoreFull, + + /// The operation could not proceed because the provided tag is invalid. + InvalidTag, + + /// The operation could not proceed because the preconditions do not hold. + InvalidPrecondition, +} + +/// The position of an entry in the store. +#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Copy, Clone)] +pub struct StoreIndex { + /// The index of this entry in the storage. + index: Index, + + /// The generation at which this index is valid. + /// + /// See the documentation of the field with the same name in the `Store` struct. + generation: usize, +} + +/// A user entry. +#[cfg_attr(feature = "std", derive(Debug, PartialEq, Eq))] +#[derive(Copy, Clone)] +pub struct StoreEntry<'a> { + /// The tag of the entry. + /// + /// Must be smaller than the configured number of tags. + pub tag: usize, + + /// The data of the entry. + pub data: &'a [u8], +} + +/// Implements a configurable multi-set on top of any storage. +pub struct Store { + storage: S, + config: C, + format: Format, + + /// The index of the blank page reserved for compaction. + blank_page: usize, + + /// Counts the number of compactions since the store creation. + /// + /// A `StoreIndex` is valid only if they originate from the same generation. This is checked by + /// operations that take a `StoreIndex` as argument. + generation: usize, +} + +impl Store { + /// Creates a new store. + /// + /// Initializes the storage if it is fresh (filled with `0xff`). Rolls-back or completes an + /// operation if the store was powered off in the middle of that operation. In other words, + /// operations are atomic. + /// + /// # Errors + /// + /// Returns `None` if `storage` and/or `config` are not supported. + pub fn new(storage: S, config: C) -> Option> { + let format = Format::new(&storage, &config)?; + let blank_page = format.num_pages; + let mut store = Store { + storage, + config, + format, + blank_page, + generation: 0, + }; + // Finish any ongoing page compaction. + store.recover_compact_page(); + // Finish or roll-back any other entry-level operations. + store.recover_entry_operations(); + // Initialize uninitialized pages. + store.initialize_storage(); + Some(store) + } + + /// Iterates over all entries in the store. + pub fn iter(&self) -> impl Iterator { + Iter::new(self).filter_map(move |(index, entry)| { + if self.format.is_alive(entry) { + Some(( + StoreIndex { + index, + generation: self.generation, + }, + StoreEntry { + tag: self.format.get_tag(entry), + data: self.format.get_data(entry), + }, + )) + } else { + None + } + }) + } + + /// Iterates over all entries matching a key in the store. + pub fn find_all<'a>( + &'a self, + key: &'a C::Key, + ) -> impl Iterator + 'a { + self.iter().filter(move |&(_, entry)| { + let mut has_match = false; + self.config.keys(entry, |k| has_match |= key == &k); + has_match + }) + } + + /// Returns the first entry matching a key in the store. + /// + /// This is a convenience function for when at most one entry should match the key. + /// + /// # Panics + /// + /// In debug mode, panics if more than one entry matches the key. + pub fn find_one<'a>(&'a self, key: &'a C::Key) -> Option<(StoreIndex, StoreEntry<'a>)> { + let mut iter = self.find_all(key); + let first = iter.next()?; + let has_only_one_element = iter.next().is_none(); + debug_assert!(has_only_one_element); + Some(first) + } + + /// Deletes an entry from the store. + pub fn delete(&mut self, index: StoreIndex) -> Result<(), StoreError> { + if self.generation != index.generation { + return Err(StoreError::InvalidPrecondition); + } + self.delete_index(index.index); + Ok(()) + } + + /// Replaces an entry with another with the same tag in the store. + /// + /// This operation (like others) is atomic. If it returns successfully, then the old entry is + /// deleted and the new is inserted. If it fails, the old entry is not deleted and the new entry + /// is not inserted. If power is lost during the operation, during next startup, the operation + /// is either rolled-back (like in case of failure) or completed (like in case of success). + /// + /// # Errors + /// + /// Returns: + /// - `StoreFull` if the new entry does not fit in the store. + /// - `InvalidTag` if the tag of the new entry is not smaller than the configured number of + /// tags. + pub fn replace(&mut self, old: StoreIndex, new: StoreEntry) -> Result<(), StoreError> { + if self.generation != old.generation { + return Err(StoreError::InvalidPrecondition); + } + self.format.validate_entry(new)?; + let mut old_index = old.index; + // Find a slot. + let entry_len = self.replace_len(new.data.len()); + let index = self.find_slot_for_write(entry_len, Some(&mut old_index))?; + // Build a new entry replacing the old one. + let entry = self.format.build_entry(Some(old_index), new); + debug_assert_eq!(entry.len(), entry_len); + // Write the new entry. + self.write_entry(index, &entry); + // Commit the new entry, which both deletes the old entry and commits the new one. + self.commit_index(index); + Ok(()) + } + + /// Inserts an entry in the store. + /// + /// # Errors + /// + /// Returns: + /// - `StoreFull` if the new entry does not fit in the store. + /// - `InvalidTag` if the tag of the new entry is not smaller than the configured number of + /// tags. + pub fn insert(&mut self, entry: StoreEntry) -> Result<(), StoreError> { + self.format.validate_entry(entry)?; + // Build entry. + let entry = self.format.build_entry(None, entry); + // Find a slot. + let index = self.find_slot_for_write(entry.len(), None)?; + // Write entry. + self.write_entry(index, &entry); + Ok(()) + } + + /// Returns the byte cost of a replace operation. + /// + /// Computes the length in bytes that would be used in the storage if a replace operation is + /// executed provided the data of the new entry has `length` bytes. + pub fn replace_len(&self, length: usize) -> usize { + self.format.entry_size(IsReplace::Replace, length) + } + + /// Returns the byte cost of an insert operation. + /// + /// Computes the length in bytes that would be used in the storage if an insert operation is + /// executed provided the data of the inserted entry has `length` bytes. + pub fn insert_len(&self, length: usize) -> usize { + self.format.entry_size(IsReplace::Insert, length) + } + + /// Returns the erase count of all pages. + /// + /// The value at index `page` of the result is the number of times page `page` was erased. This + /// number is an underestimate in case power was lost when this page was erased. + pub fn compaction_info(&self) -> Vec { + let mut info = Vec::with_capacity(self.format.num_pages); + for page in 0..self.format.num_pages { + let (page_header, _) = self.read_page_header(page); + let erase_count = self.format.get_erase_count(page_header); + info.push(erase_count); + } + info + } + + /// Completes any ongoing page compaction. + fn recover_compact_page(&mut self) { + for page in 0..self.format.num_pages { + let (page_header, _) = self.read_page_header(page); + if self.format.is_compacting(page_header) { + let new_page = self.format.get_new_page(page_header); + self.compact_page(page, new_page); + } + } + } + + /// Rolls-back or completes any ongoing operation. + fn recover_entry_operations(&mut self) { + for page in 0..self.format.num_pages { + let (page_header, mut index) = self.read_page_header(page); + if !self.format.is_initialized(page_header) { + // Skip uninitialized pages. + continue; + } + while index.byte < self.format.page_size { + let entry_index = index; + let entry = self.read_entry(index); + index.byte += entry.len(); + if !self.format.is_alive(entry) { + // Skip deleted entries (or the page padding). + } else if self.format.is_internal(entry) { + // Finish page compaction. + self.erase_page(entry_index); + } else if !self.format.is_complete(entry) { + // Roll-back incomplete operations. + self.delete_index(entry_index); + } else if !self.format.is_committed(entry) { + // Finish complete but uncommitted operations. + self.commit_index(entry_index) + } + } + } + } + + /// Initializes uninitialized pages. + fn initialize_storage(&mut self) { + for page in 0..self.format.num_pages { + let (header, index) = self.read_page_header(page); + if self.format.is_initialized(header) { + // Update blank page. + let first_entry = self.read_entry(index); + if !self.format.is_present(first_entry) { + self.blank_page = page; + } + } else { + // We set the erase count to zero the very first time we initialize a page. + self.initialize_page(page, 0); + } + } + debug_assert!(self.blank_page != self.format.num_pages); + } + + /// Marks an entry as deleted. + /// + /// The provided index must point to the beginning of an entry. + fn delete_index(&mut self, index: Index) { + self.update_word(index, |format, word| format.set_deleted(word)); + } + + /// Finds a page with enough free space. + /// + /// Returns an index to the free space of a page which can hold an entry of `length` bytes. If + /// necessary, pages may be compacted to free space. In that case, if provided, the `old_index` + /// is updated according to compaction. + fn find_slot_for_write( + &mut self, + length: usize, + mut old_index: Option<&mut Index>, + ) -> Result { + loop { + if let Some(index) = self.choose_slot_for_write(length) { + return Ok(index); + } + match self.choose_page_for_compact() { + None => return Err(StoreError::StoreFull), + Some(page) => { + let blank_page = self.blank_page; + // Compact the chosen page and update the old index to point to the entry in the + // new page if it happened to be in the old page. This is essentially a way to + // avoid index invalidation due to compaction. + let map = self.compact_page(page, blank_page); + if let Some(old_index) = &mut old_index { + map_index(page, blank_page, &map, old_index); + } + } + } + } + } + + /// Returns whether a page has enough free space. + /// + /// Returns an index to the free space of a page with smallest free space that may hold `length` + /// bytes. + fn choose_slot_for_write(&self, length: usize) -> Option { + Iter::new(self) + .filter(|(index, entry)| { + index.page != self.blank_page + && !self.format.is_present(entry) + && length <= entry.len() + }) + .min_by_key(|(_, entry)| entry.len()) + .map(|(index, _)| index) + } + + /// Returns the page that should be compacted. + fn choose_page_for_compact(&self) -> Option { + // TODO(cretin): This could be optimized by using some cost function depending on: + // - the erase count + // - the length of the free space + // - the length of the alive entries + // We want to minimize this cost. We could also take into account the length of the entry we + // want to write to bound the number of compaction before failing with StoreFull. + // + // We should also make sure that all pages (including if they have no deleted entries and no + // free space) are eventually compacted (ideally to a heavily used page) to benefit from the + // low erase count of those pages. + (0..self.format.num_pages) + .map(|page| (page, self.page_info(page))) + .filter(|&(page, ref info)| { + page != self.blank_page + && info.erase_count < self.format.max_page_erases + && info.deleted_length > self.format.internal_entry_size() + }) + .min_by(|(_, lhs_info), (_, rhs_info)| lhs_info.compare_for_compaction(rhs_info)) + .map(|(page, _)| page) + } + + fn page_info(&self, page: usize) -> PageInfo { + let (page_header, mut index) = self.read_page_header(page); + let mut info = PageInfo { + erase_count: self.format.get_erase_count(page_header), + deleted_length: 0, + free_length: 0, + }; + while index.byte < self.format.page_size { + let entry = self.read_entry(index); + index.byte += entry.len(); + if !self.format.is_present(entry) { + debug_assert_eq!(info.free_length, 0); + info.free_length = entry.len(); + } else if self.format.is_deleted(entry) { + info.deleted_length += entry.len(); + } + } + debug_assert_eq!(index.page, page); + info + } + + fn read_slice(&self, index: Index, length: usize) -> &[u8] { + self.storage.read_slice(index, length).unwrap() + } + + /// Reads an entry (with header and footer) at a given index. + /// + /// If no entry is present, returns the free space up to the end of the page. + fn read_entry(&self, index: Index) -> &[u8] { + let first_byte = self.read_slice(index, 1); + let max_length = self.format.page_size - index.byte; + let mut length = if !self.format.is_present(first_byte) { + max_length + } else if self.format.is_internal(first_byte) { + self.format.internal_entry_size() + } else { + let header = self.read_slice(index, self.format.header_size()); + let replace = self.format.is_replace(header); + let length = self.format.get_length(header); + self.format.entry_size(replace, length) + }; + // Truncate the length to fit the page. This can only happen in case of corruption or + // partial writes. + length = core::cmp::min(length, max_length); + self.read_slice(index, length) + } + + /// Reads a page header. + /// + /// Also returns the index after the page header. + fn read_page_header(&self, page: usize) -> (&[u8], Index) { + let mut index = Index { page, byte: 0 }; + let page_header = self.read_slice(index, self.format.page_header_size()); + index.byte += page_header.len(); + (page_header, index) + } + + /// Updates a word at a given index. + /// + /// The `update` function is called with the word at `index`. The input value is the current + /// value of the word. The output value is the value that will be written. It should only change + /// bits from 1 to 0. + fn update_word(&mut self, index: Index, update: impl FnOnce(&Format, &mut [u8])) { + let word_size = self.format.word_size; + let mut word = self.read_slice(index, word_size).to_vec(); + update(&self.format, &mut word); + self.storage.write_slice(index, &word).unwrap(); + } + + fn write_entry(&mut self, index: Index, entry: &[u8]) { + self.storage.write_slice(index, entry).unwrap(); + } + + /// Initializes a page by writing the page header. + /// + /// If the page is not erased, it is first erased. + fn initialize_page(&mut self, page: usize, erase_count: usize) { + let index = Index { page, byte: 0 }; + let page = self.read_slice(index, self.format.page_size); + if !page.iter().all(|&byte| byte == 0xff) { + self.storage.erase_page(index.page).unwrap(); + } + self.update_word(index, |format, header| { + format.set_initialized(header); + format.set_erase_count(header, erase_count); + }); + self.blank_page = index.page; + } + + /// Commits a replace entry. + /// + /// Deletes the old entry and commits the new entry. + fn commit_index(&mut self, mut index: Index) { + let entry = self.read_entry(index); + index.byte += entry.len(); + let word_size = self.format.word_size; + debug_assert!(entry.len() >= 2 * word_size); + match self.format.is_replace(entry) { + IsReplace::Replace => { + let delete_index = self.format.get_replace_index(entry); + self.delete_index(delete_index); + } + IsReplace::Insert => debug_assert!(false), + }; + index.byte -= word_size; + self.update_word(index, |format, word| format.set_committed(word)); + } + + /// Compacts a page to an other. + /// + /// Returns the mapping from the alive entries in the old page to their index in the new page. + fn compact_page(&mut self, old_page: usize, new_page: usize) -> BTreeMap { + // Write the old page as being compacted to the new page. + let mut erase_count = 0; + self.update_word( + Index { + page: old_page, + byte: 0, + }, + |format, header| { + erase_count = format.get_erase_count(header); + format.set_compacting(header); + format.set_new_page(header, new_page); + }, + ); + // Copy alive entries from the old page to the new page. + let page_header_size = self.format.page_header_size(); + let mut old_index = Index { + page: old_page, + byte: page_header_size, + }; + let mut new_index = Index { + page: new_page, + byte: page_header_size, + }; + let mut map = BTreeMap::new(); + while old_index.byte < self.format.page_size { + let old_entry = self.read_entry(old_index); + let old_entry_index = old_index.byte; + old_index.byte += old_entry.len(); + if !self.format.is_alive(old_entry) { + continue; + } + let previous_mapping = map.insert(old_entry_index, new_index.byte); + debug_assert!(previous_mapping.is_none()); + // We need to copy the old entry because it is in the storage and we are going to write + // to the storage. Rust cannot tell that both entries don't overlap. + let old_entry = old_entry.to_vec(); + self.write_entry(new_index, &old_entry); + new_index.byte += old_entry.len(); + } + // Save the old page index and erase count to the new page. + let erase_index = new_index; + let erase_entry = self.format.build_erase_entry(old_page, erase_count); + self.storage.write_slice(new_index, &erase_entry).unwrap(); + // Erase the page. + self.erase_page(erase_index); + // Increase generation. + self.generation += 1; + map + } + + /// Commits an internal entry. + /// + /// The only kind of internal entry is to erase a page, which first erases the page, then + /// initializes it with the saved erase count, and finally deletes the internal entry. + fn erase_page(&mut self, erase_index: Index) { + let erase_entry = self.read_entry(erase_index); + debug_assert!(self.format.is_present(erase_entry)); + debug_assert!(!self.format.is_deleted(erase_entry)); + debug_assert!(self.format.is_internal(erase_entry)); + let old_page = self.format.get_old_page(erase_entry); + let erase_count = self.format.get_saved_erase_count(erase_entry) + 1; + // Erase the page. + self.storage.erase_page(old_page).unwrap(); + // Initialize the page. + self.initialize_page(old_page, erase_count); + // Delete the internal entry. + self.delete_index(erase_index); + } +} + +// Those functions are not meant for production. +#[cfg(feature = "std")] +impl Store { + /// Takes a snapshot of the storage after a given amount of word operations. + pub fn arm_snapshot(&mut self, delay: usize) { + self.storage.arm_snapshot(delay); + } + + /// Unarms and returns the snapshot or the delay remaining. + pub fn get_snapshot(&mut self) -> Result, usize> { + self.storage.get_snapshot() + } + + /// Takes a snapshot of the storage. + pub fn take_snapshot(&self) -> Box<[u8]> { + self.storage.take_snapshot() + } + + /// Returns the storage. + pub fn get_storage(self) -> Box<[u8]> { + self.storage.get_storage() + } + + /// Erases and initializes a page with a given erase count. + pub fn set_erase_count(&mut self, page: usize, erase_count: usize) { + self.initialize_page(page, erase_count); + } +} + +/// Maps an index from an old page to a new page if needed. +fn map_index(old_page: usize, new_page: usize, map: &BTreeMap, index: &mut Index) { + if index.page == old_page { + index.page = new_page; + index.byte = *map.get(&index.byte).unwrap(); + } +} + +/// Page information for compaction. +struct PageInfo { + /// How many times the page was erased. + erase_count: usize, + + /// Cumulative length of deleted entries (including header and footer). + deleted_length: usize, + + /// Length of the free space. + free_length: usize, +} + +impl PageInfo { + /// Returns whether a page should be compacted before another. + fn compare_for_compaction(&self, rhs: &PageInfo) -> core::cmp::Ordering { + self.erase_count + .cmp(&rhs.erase_count) + .then(rhs.deleted_length.cmp(&self.deleted_length)) + .then(self.free_length.cmp(&rhs.free_length)) + } +} + +/// Iterates over all entries (including free space) of a store. +struct Iter<'a, S: Storage, C: StoreConfig> { + store: &'a Store, + index: Index, +} + +impl<'a, S: Storage, C: StoreConfig> Iter<'a, S, C> { + fn new(store: &'a Store) -> Iter<'a, S, C> { + let index = Index { + page: 0, + byte: store.format.page_header_size(), + }; + Iter { store, index } + } +} + +impl<'a, S: Storage, C: StoreConfig> Iterator for Iter<'a, S, C> { + type Item = (Index, &'a [u8]); + + fn next(&mut self) -> Option<(Index, &'a [u8])> { + if self.index.byte == self.store.format.page_size { + self.index.page += 1; + self.index.byte = self.store.format.page_header_size(); + } + if self.index.page == self.store.format.num_pages { + return None; + } + let index = self.index; + let entry = self.store.read_entry(self.index); + self.index.byte += entry.len(); + Some((index, entry)) + } +} + +#[cfg(test)] +mod tests { + use super::super::{BufferOptions, BufferStorage}; + use super::*; + + struct Config; + + const WORD_SIZE: usize = 4; + const PAGE_SIZE: usize = 8 * WORD_SIZE; + const NUM_PAGES: usize = 3; + + impl StoreConfig for Config { + type Key = u8; + + fn num_tags(&self) -> usize { + 1 + } + + fn keys(&self, entry: StoreEntry, mut add: impl FnMut(u8)) { + assert_eq!(entry.tag, 0); + if !entry.data.is_empty() { + add(entry.data[0]); + } + } + } + + fn new_buffer(storage: Box<[u8]>) -> BufferStorage { + let options = BufferOptions { + word_size: WORD_SIZE, + page_size: PAGE_SIZE, + max_word_writes: 2, + max_page_erases: 2, + strict_write: true, + }; + BufferStorage::new(storage, options) + } + + fn new_store() -> Store { + let storage = vec![0xff; NUM_PAGES * PAGE_SIZE].into_boxed_slice(); + Store::new(new_buffer(storage), Config).unwrap() + } + + #[test] + fn insert_ok() { + let mut store = new_store(); + assert_eq!(store.iter().count(), 0); + let tag = 0; + let key = 1; + let data = &[key, 2]; + let entry = StoreEntry { tag, data }; + store.insert(entry).unwrap(); + assert_eq!(store.iter().count(), 1); + assert_eq!(store.find_one(&key).unwrap().1, entry); + } + + #[test] + fn delete_ok() { + let mut store = new_store(); + let tag = 0; + let key = 1; + let entry = StoreEntry { + tag, + data: &[key, 2], + }; + store.insert(entry).unwrap(); + assert_eq!(store.find_all(&key).count(), 1); + let (index, _) = store.find_one(&key).unwrap(); + store.delete(index).unwrap(); + assert_eq!(store.find_all(&key).count(), 0); + assert_eq!(store.iter().count(), 0); + } + + #[test] + fn insert_until_full() { + let mut store = new_store(); + let tag = 0; + let mut key = 0; + while store + .insert(StoreEntry { + tag, + data: &[key, 0], + }) + .is_ok() + { + key += 1; + } + assert!(key > 0); + } + + #[test] + fn compact_ok() { + let mut store = new_store(); + let tag = 0; + let mut key = 0; + while store + .insert(StoreEntry { + tag, + data: &[key, 0], + }) + .is_ok() + { + key += 1; + } + let (index, _) = store.find_one(&0).unwrap(); + store.delete(index).unwrap(); + store + .insert(StoreEntry { + tag: 0, + data: &[key, 0], + }) + .unwrap(); + for k in 1..=key { + assert_eq!(store.find_all(&k).count(), 1); + } + } + + #[test] + fn reboot_ok() { + let mut store = new_store(); + let tag = 0; + let key = 1; + let data = &[key, 2]; + let entry = StoreEntry { tag, data }; + store.insert(entry).unwrap(); + + // Reboot the store. + let store = store.get_storage(); + let store = Store::new(new_buffer(store), Config).unwrap(); + + assert_eq!(store.iter().count(), 1); + assert_eq!(store.find_one(&key).unwrap().1, entry); + } + + #[test] + fn replace_atomic() { + let tag = 0; + let key = 1; + let old_entry = StoreEntry { + tag, + data: &[key, 2, 3, 4, 5, 6], + }; + let new_entry = StoreEntry { + tag, + data: &[key, 7, 8, 9], + }; + let mut delay = 0; + loop { + let mut store = new_store(); + store.insert(old_entry).unwrap(); + store.arm_snapshot(delay); + let (index, _) = store.find_one(&key).unwrap(); + store.replace(index, new_entry).unwrap(); + let (complete, store) = match store.get_snapshot() { + Err(_) => (true, store.get_storage()), + Ok(store) => (false, store), + }; + let store = Store::new(new_buffer(store), Config).unwrap(); + assert_eq!(store.iter().count(), 1); + assert_eq!(store.find_all(&key).count(), 1); + let (_, cur_entry) = store.find_one(&key).unwrap(); + assert!((cur_entry == old_entry && !complete) || cur_entry == new_entry); + if complete { + break; + } + delay += 1; + } + } + + #[test] + fn compact_atomic() { + let tag = 0; + let mut delay = 0; + loop { + let mut store = new_store(); + let mut key = 0; + while store + .insert(StoreEntry { + tag, + data: &[key, 0], + }) + .is_ok() + { + key += 1; + } + let (index, _) = store.find_one(&0).unwrap(); + store.delete(index).unwrap(); + let (index, _) = store.find_one(&1).unwrap(); + store.arm_snapshot(delay); + store + .replace(index, StoreEntry { tag, data: &[1, 1] }) + .unwrap(); + let (complete, store) = match store.get_snapshot() { + Err(_) => (true, store.get_storage()), + Ok(store) => (false, store), + }; + let store = Store::new(new_buffer(store), Config).unwrap(); + assert_eq!(store.iter().count(), key as usize - 1); + for k in 2..key { + assert_eq!(store.find_all(&k).count(), 1); + assert_eq!( + store.find_one(&k).unwrap().1, + StoreEntry { tag, data: &[k, 0] } + ); + } + assert_eq!(store.find_all(&1).count(), 1); + let (_, entry) = store.find_one(&1).unwrap(); + assert_eq!(entry.tag, tag); + assert!((entry.data == [1, 0] && !complete) || entry.data == [1, 1]); + if complete { + break; + } + delay += 1; + } + } + + #[test] + fn invalid_tag() { + let mut store = new_store(); + let entry = StoreEntry { tag: 1, data: &[] }; + assert_eq!(store.insert(entry), Err(StoreError::InvalidTag)); + } + + #[test] + fn invalid_length() { + let mut store = new_store(); + let entry = StoreEntry { + tag: 0, + data: &[0; PAGE_SIZE], + }; + assert_eq!(store.insert(entry), Err(StoreError::StoreFull)); + } +} diff --git a/src/embedded_flash/syscall.rs b/src/embedded_flash/syscall.rs new file mode 100644 index 0000000..7fca17a --- /dev/null +++ b/src/embedded_flash/syscall.rs @@ -0,0 +1,195 @@ +// Copyright 2019 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. + +use super::{Index, Storage, StorageError, StorageResult}; +use libtock::syscalls; + +const DRIVER_NUMBER: usize = 0x50003; + +mod command_nr { + pub const GET_INFO: usize = 1; + pub mod get_info_nr { + pub const WORD_SIZE: usize = 0; + pub const PAGE_SIZE: usize = 1; + pub const MAX_WORD_WRITES: usize = 2; + pub const MAX_PAGE_ERASES: usize = 3; + } + pub const WRITE_SLICE: usize = 2; + pub const ERASE_PAGE: usize = 3; +} + +mod allow_nr { + pub const WRITE_SLICE: usize = 0; +} + +fn get_info(nr: usize) -> StorageResult { + let code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_INFO, nr, 0) }; + if code < 0 { + Err(StorageError::KernelError { code }) + } else { + Ok(code as usize) + } +} + +pub struct SyscallStorage { + word_size: usize, + page_size: usize, + max_word_writes: usize, + max_page_erases: usize, + storage: &'static mut [u8], +} + +impl SyscallStorage { + /// Provides access to the embedded flash if available. + /// + /// # Safety + /// + /// The `storage` must be in a writeable flash region. + /// + /// # Errors + /// + /// Returns `BadFlash` if any of the following conditions do not hold: + /// - The word size is not a power of two. + /// - The page size is not a power of two. + /// - The page size is not a multiple of the word size. + /// + /// Returns `NotAligned` if any of the following conditions do not hold: + /// - `storage` is page-aligned. + /// - `storage.len()` is a multiple of the page size. + /// + /// # Examples + /// + /// ```rust + /// # extern crate ctap2; + /// # use ctap2::embedded_flash::SyscallStorage; + /// # use ctap2::embedded_flash::StorageResult; + /// # const NUM_PAGES: usize = 1; + /// # const PAGE_SIZE: usize = 1; + /// #[link_section = ".app_state"] + /// static mut STORAGE: [u8; NUM_PAGES * PAGE_SIZE] = [0xff; NUM_PAGES * PAGE_SIZE]; + /// # fn foo() -> StorageResult { + /// // This is safe because this is the only use of `STORAGE` in the whole program and this is + /// // called only once. + /// unsafe { SyscallStorage::new(&mut STORAGE) } + /// # } + /// ``` + pub unsafe fn new(storage: &'static mut [u8]) -> StorageResult { + let word_size = get_info(command_nr::get_info_nr::WORD_SIZE)?; + let page_size = get_info(command_nr::get_info_nr::PAGE_SIZE)?; + let max_word_writes = get_info(command_nr::get_info_nr::MAX_WORD_WRITES)?; + let max_page_erases = get_info(command_nr::get_info_nr::MAX_PAGE_ERASES)?; + if !word_size.is_power_of_two() || !page_size.is_power_of_two() { + return Err(StorageError::BadFlash); + } + let syscall = SyscallStorage { + word_size, + page_size, + max_word_writes, + max_page_erases, + storage, + }; + if !syscall.is_word_aligned(page_size) { + return Err(StorageError::BadFlash); + } + if syscall.is_page_aligned(syscall.storage.as_ptr() as usize) + && syscall.is_page_aligned(syscall.storage.len()) + { + Ok(syscall) + } else { + Err(StorageError::NotAligned) + } + } + + fn is_word_aligned(&self, x: usize) -> bool { + x & (self.word_size - 1) == 0 + } + + fn is_page_aligned(&self, x: usize) -> bool { + x & (self.page_size - 1) == 0 + } +} + +impl Storage for SyscallStorage { + fn word_size(&self) -> usize { + self.word_size + } + + fn page_size(&self) -> usize { + self.page_size + } + + fn num_pages(&self) -> usize { + self.storage.len() / self.page_size + } + + fn max_word_writes(&self) -> usize { + self.max_word_writes + } + + fn max_page_erases(&self) -> usize { + self.max_page_erases + } + + fn read_slice(&self, index: Index, length: usize) -> StorageResult<&[u8]> { + Ok(&self.storage[index.range(length, self)?]) + } + + fn write_slice(&mut self, index: Index, value: &[u8]) -> StorageResult<()> { + if !self.is_word_aligned(index.byte) || !self.is_word_aligned(value.len()) { + return Err(StorageError::NotAligned); + } + let range = index.range(value.len(), self)?; + let code = unsafe { + syscalls::allow_ptr( + DRIVER_NUMBER, + allow_nr::WRITE_SLICE, + // We rely on the driver not writing to the slice. This should use read-only allow + // when available. See https://github.com/tock/tock/issues/1274. + value.as_ptr() as *mut u8, + value.len(), + ) + }; + if code < 0 { + return Err(StorageError::KernelError { code }); + } + let code = unsafe { + syscalls::command( + DRIVER_NUMBER, + command_nr::WRITE_SLICE, + self.storage[range].as_ptr() as usize, + 0, + ) + }; + if code < 0 { + return Err(StorageError::KernelError { code }); + } + Ok(()) + } + + fn erase_page(&mut self, page: usize) -> StorageResult<()> { + let range = Index { page, byte: 0 }.range(self.page_size(), self)?; + let code = unsafe { + syscalls::command( + DRIVER_NUMBER, + command_nr::ERASE_PAGE, + self.storage[range].as_ptr() as usize, + 0, + ) + }; + if code < 0 { + return Err(StorageError::KernelError { code }); + } + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..b12f77b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2019 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. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +extern crate alloc; +extern crate libtock; + +pub mod embedded_flash; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..753f165 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,388 @@ +// Copyright 2019 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. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[macro_use] +extern crate alloc; +#[macro_use] +extern crate arrayref; +extern crate byteorder; +#[cfg(feature = "std")] +extern crate core; +extern crate ctap2; +extern crate libtock; +extern crate subtle; +#[macro_use] +extern crate cbor; +extern crate crypto; + +mod ctap; +mod usb_ctap_hid; + +use core::cell::Cell; +#[cfg(feature = "debug_ctap")] +use core::fmt::Write; +use crypto::rng256::TockRng256; +use ctap::hid::{ChannelID, CtapHid, KeepaliveStatus, ProcessedPacket}; +use ctap::status_code::Ctap2StatusCode; +use ctap::CtapState; +use libtock::buttons; +use libtock::buttons::ButtonState; +#[cfg(feature = "debug_ctap")] +use libtock::console::Console; +use libtock::led; +use libtock::result::TockValue; +use libtock::syscalls; +use libtock::timer; +#[cfg(feature = "debug_ctap")] +use libtock::timer::Timer; +use libtock::timer::{Duration, StopAlarmError, Timestamp}; + +const KEEPALIVE_DELAY_MS: isize = 100; +const KEEPALIVE_DELAY: Duration = Duration::from_ms(KEEPALIVE_DELAY_MS); +const SEND_TIMEOUT: Duration = Duration::from_ms(1000); + +fn main() { + // Setup the timer with a dummy callback (we only care about reading the current time, but the + // API forces us to set an alarm callback too). + let mut with_callback = timer::with_callback(|_, _| {}); + let timer = with_callback.init().unwrap(); + + // Setup USB driver. + if !usb_ctap_hid::setup() { + panic!("Cannot setup USB driver"); + } + + let mut rng = TockRng256 {}; + let mut ctap_state = CtapState::new(&mut rng, check_user_presence); + let mut ctap_hid = CtapHid::new(); + + let mut led_counter = 0; + let mut last_led_increment = timer.get_current_clock(); + + // Main loop. If CTAP1 is used, we register button presses for U2F while receiving and waiting. + // The way TockOS and apps currently interact, callbacks need a yield syscall to execute, + // making consistent blinking patterns and sending keepalives harder. + loop { + // Create the button callback, used for CTAP1. + #[cfg(feature = "with_ctap1")] + let button_touched = Cell::new(false); + #[cfg(feature = "with_ctap1")] + let mut buttons_callback = buttons::with_callback(|_button_num, state| { + match state { + ButtonState::Pressed => button_touched.set(true), + ButtonState::Released => (), + }; + }); + #[cfg(feature = "with_ctap1")] + let mut buttons = buttons_callback.init().unwrap(); + #[cfg(feature = "with_ctap1")] + // At the moment, all buttons are accepted. You can customize your setup here. + for mut button in &mut buttons { + button.enable().unwrap(); + } + + let mut pkt_request = [0; 64]; + let has_packet = match usb_ctap_hid::recv_with_timeout(&mut pkt_request, KEEPALIVE_DELAY) { + Some(usb_ctap_hid::SendOrRecvStatus::Received) => { + #[cfg(feature = "debug_ctap")] + print_packet_notice("Received packet", &timer); + true + } + Some(_) => panic!("Error receiving packet"), + None => false, + }; + + let now = timer.get_current_clock(); + #[cfg(feature = "with_ctap1")] + { + if button_touched.get() { + ctap_state.u2f_up_state.grant_up(now); + } + // Cleanup button callbacks. We miss button presses while processing though. + // Heavy computation mostly follows a registered touch luckily. Unregistering + // callbacks is important to not clash with those from check_user_presence. + for mut button in &mut buttons { + button.disable().unwrap(); + } + drop(buttons); + drop(buttons_callback); + } + + // These calls are making sure that even for long inactivity, wrapping clock values + // never randomly wink or grant user presence for U2F. + ctap_state.check_disable_reset(Timestamp::::from_clock_value(now)); + ctap_hid.wink_permission = ctap_hid.wink_permission.check_expiration(now); + + if has_packet { + let reply = ctap_hid.process_hid_packet(&pkt_request, now, &mut ctap_state); + // This block handles sending packets. + for mut pkt_reply in reply { + let status = usb_ctap_hid::send_or_recv_with_timeout(&mut pkt_reply, SEND_TIMEOUT); + match status { + None => { + #[cfg(feature = "debug_ctap")] + print_packet_notice("Sending packet timed out", &timer); + // TODO: reset the ctap_hid state. + // Since sending the packet timed out, we cancel this reply. + break; + } + Some(usb_ctap_hid::SendOrRecvStatus::Error) => panic!("Error sending packet"), + Some(usb_ctap_hid::SendOrRecvStatus::Sent) => { + #[cfg(feature = "debug_ctap")] + print_packet_notice("Sent packet", &timer); + } + Some(usb_ctap_hid::SendOrRecvStatus::Received) => { + #[cfg(feature = "debug_ctap")] + print_packet_notice("Received an UNEXPECTED packet", &timer); + // TODO: handle this unexpected packet. + } + } + } + } + + let now = timer.get_current_clock(); + if let Some(wait_duration) = now.wrapping_sub(last_led_increment) { + if wait_duration > KEEPALIVE_DELAY { + // Loops quickly when waiting for U2F user presence, so the next LED blink + // state is only set if enough time has elapsed. + led_counter += 1; + last_led_increment = now; + } + } else { + // This branch means the clock frequency changed. This should never happen. + led_counter += 1; + last_led_increment = now; + } + + if ctap_hid.wink_permission.is_granted(now) { + wink_leds(led_counter); + } else { + #[cfg(not(feature = "with_ctap1"))] + switch_off_leds(); + #[cfg(feature = "with_ctap1")] + { + if ctap_state.u2f_up_state.is_up_needed(now) { + // Flash the LEDs with an almost regular pattern. The inaccuracy comes from + // delay caused by processing and sending of packets. + blink_leds(led_counter); + } else { + switch_off_leds(); + } + } + } + } +} + +#[cfg(feature = "debug_ctap")] +fn print_packet_notice(notice_text: &str, timer: &Timer) { + let now_us = + (Timestamp::::from_clock_value(timer.get_current_clock()).ms() * 1000.0) as u64; + writeln!( + Console::new(), + "{} at {}.{:06} s", + notice_text, + now_us / 1_000_000, + now_us % 1_000_000 + ) + .unwrap(); +} + +// Returns whether the keepalive was sent, or false if cancelled. +fn send_keepalive_up_needed( + cid: ChannelID, + timeout: Duration, +) -> Result<(), Ctap2StatusCode> { + let keepalive_msg = CtapHid::keepalive(cid, KeepaliveStatus::UpNeeded); + for mut pkt in keepalive_msg { + let status = usb_ctap_hid::send_or_recv_with_timeout(&mut pkt, timeout); + match status { + None => { + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Sending a KEEPALIVE packet timed out").unwrap(); + // TODO: abort user presence test? + } + Some(usb_ctap_hid::SendOrRecvStatus::Error) => panic!("Error sending KEEPALIVE packet"), + Some(usb_ctap_hid::SendOrRecvStatus::Sent) => { + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Sent KEEPALIVE packet").unwrap(); + } + Some(usb_ctap_hid::SendOrRecvStatus::Received) => { + // We only parse one packet, because we only care about CANCEL. + let (received_cid, processed_packet) = CtapHid::process_single_packet(&pkt); + if received_cid != &cid { + #[cfg(feature = "debug_ctap")] + writeln!( + Console::new(), + "Received a packet on channel ID {:?} while sending a KEEPALIVE packet", + received_cid, + ) + .unwrap(); + return Ok(()); + } + match processed_packet { + ProcessedPacket::InitPacket { cmd, .. } => { + if cmd == CtapHid::COMMAND_CANCEL { + // We ignore the payload, we can't answer with an error code anyway. + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "User presence check cancelled").unwrap(); + return Err(Ctap2StatusCode::CTAP2_ERR_KEEPALIVE_CANCEL); + } else { + #[cfg(feature = "debug_ctap")] + writeln!( + Console::new(), + "Discarded packet with command {} received while sending a KEEPALIVE packet", + cmd, + ) + .unwrap(); + } + } + ProcessedPacket::ContinuationPacket { .. } => { + #[cfg(feature = "debug_ctap")] + writeln!( + Console::new(), + "Discarded continuation packet received while sending a KEEPALIVE packet", + ) + .unwrap(); + } + } + } + } + } + Ok(()) +} + +fn blink_leds(pattern_seed: isize) { + for l in 0..led::count() { + if (pattern_seed ^ l).count_ones() & 1 != 0 { + led::get(l).unwrap().on(); + } else { + led::get(l).unwrap().off(); + } + } +} + +fn wink_leds(pattern_seed: isize) { + // This generates a "snake" pattern circling through the LEDs. + // Fox example with 4 LEDs the sequence of lit LEDs will be the following. + // 0 1 2 3 + // * * + // * * * + // * * + // * * * + // * * + // * * * + // * * + // * * * + // * * + let count = led::count(); + let a = (pattern_seed / 2) % count; + let b = ((pattern_seed + 1) / 2) % count; + let c = ((pattern_seed + 3) / 2) % count; + + for l in 0..count { + // On nRF52840-DK, logically swap LEDs 3 and 4 so that the order of LEDs form a circle. + let k = match l { + 2 => 3, + 3 => 2, + _ => l, + }; + if k == a || k == b || k == c { + led::get(l).unwrap().on(); + } else { + led::get(l).unwrap().off(); + } + } +} + +fn switch_off_leds() { + for l in 0..led::count() { + led::get(l).unwrap().off(); + } +} + +fn check_user_presence(cid: ChannelID) -> Result<(), Ctap2StatusCode> { + // The timeout is N times the keepalive delay. + const TIMEOUT_ITERATIONS: isize = ctap::TOUCH_TIMEOUT_MS / KEEPALIVE_DELAY_MS; + + // First, send a keep-alive packet to notify that the keep-alive status has changed. + send_keepalive_up_needed(cid, KEEPALIVE_DELAY)?; + + // Listen to the button presses. + let button_touched = Cell::new(false); + let mut buttons_callback = buttons::with_callback(|_button_num, state| { + match state { + ButtonState::Pressed => button_touched.set(true), + ButtonState::Released => (), + }; + }); + let mut buttons = buttons_callback.init().unwrap(); + // At the moment, all buttons are accepted. You can customize your setup here. + for mut button in &mut buttons { + button.enable().unwrap(); + } + + let mut keepalive_response = Ok(()); + for i in 0..TIMEOUT_ITERATIONS { + blink_leds(i); + + // Setup a keep-alive callback. + let keepalive_expired = Cell::new(false); + let mut keepalive_callback = timer::with_callback(|_, _| { + keepalive_expired.set(true); + }); + let mut keepalive = keepalive_callback.init().unwrap(); + let keepalive_alarm = keepalive.set_alarm(KEEPALIVE_DELAY).unwrap(); + + // Wait for a button touch or an alarm. + syscalls::yieldk_for(|| button_touched.get() || keepalive_expired.get()); + + // Cleanup alarm callback. + match keepalive.stop_alarm(keepalive_alarm) { + Ok(()) => (), + Err(TockValue::Expected(StopAlarmError::AlreadyDisabled)) => { + assert!(keepalive_expired.get()) + } + Err(e) => panic!("Unexpected error when stopping alarm: {:?}", e), + } + + // TODO: this may take arbitrary time. The keepalive_delay should be adjusted accordingly, + // so that LEDs blink with a consistent pattern. + if keepalive_expired.get() { + // Do not return immediately, because we must clean up still. + keepalive_response = send_keepalive_up_needed(cid, KEEPALIVE_DELAY); + } + + if button_touched.get() || keepalive_response.is_err() { + break; + } + } + + switch_off_leds(); + + // Cleanup button callbacks. + for mut button in &mut buttons { + button.disable().unwrap(); + } + + // Returns whether the user was present. + if keepalive_response.is_err() { + keepalive_response + } else if button_touched.get() { + Ok(()) + } else { + Err(Ctap2StatusCode::CTAP2_ERR_USER_ACTION_TIMEOUT) + } +} diff --git a/src/usb_ctap_hid.rs b/src/usb_ctap_hid.rs new file mode 100644 index 0000000..421e70b --- /dev/null +++ b/src/usb_ctap_hid.rs @@ -0,0 +1,344 @@ +// Copyright 2019 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. + +use core::cell::Cell; +#[cfg(feature = "debug_ctap")] +use core::fmt::Write; +#[cfg(feature = "debug_ctap")] +use libtock::console::Console; +use libtock::result::TockValue; +use libtock::result::{EALREADY, EBUSY, SUCCESS}; +use libtock::syscalls; +use libtock::timer; +use libtock::timer::{Duration, StopAlarmError}; + +const DRIVER_NUMBER: usize = 0x20009; + +mod command_nr { + pub const CHECK: usize = 0; + pub const CONNECT: usize = 1; + pub const TRANSMIT: usize = 2; + pub const RECEIVE: usize = 3; + pub const TRANSMIT_OR_RECEIVE: usize = 4; + pub const CANCEL: usize = 5; +} + +mod subscribe_nr { + pub const TRANSMIT: usize = 1; + pub const RECEIVE: usize = 2; + pub const TRANSMIT_OR_RECEIVE: usize = 3; + pub mod callback_status { + pub const TRANSMITTED: usize = 1; + pub const RECEIVED: usize = 2; + } +} + +mod allow_nr { + pub const TRANSMIT: usize = 1; + pub const RECEIVE: usize = 2; + pub const TRANSMIT_OR_RECEIVE: usize = 3; +} + +pub fn setup() -> bool { + let result = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::CHECK, 0, 0) }; + if result != 0 { + return false; + } + + let result = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::CONNECT, 0, 0) }; + if result != 0 { + return false; + } + + true +} + +#[allow(dead_code)] +pub fn recv(buf: &mut [u8; 64]) -> bool { + let result = syscalls::allow(DRIVER_NUMBER, allow_nr::RECEIVE, buf); + if result.is_err() { + return false; + } + + let done = Cell::new(false); + let mut alarm = |_, _, _| done.set(true); + let subscription = syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::RECEIVE, &mut alarm); + if subscription.is_err() { + return false; + } + + let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::RECEIVE, 0, 0) }; + if result_code != 0 { + return false; + } + + syscalls::yieldk_for(|| done.get()); + true +} + +#[allow(dead_code)] +pub fn send(buf: &mut [u8; 64]) -> bool { + let result = syscalls::allow(DRIVER_NUMBER, allow_nr::TRANSMIT, buf); + if result.is_err() { + return false; + } + + let done = Cell::new(false); + let mut alarm = |_, _, _| done.set(true); + let subscription = syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::TRANSMIT, &mut alarm); + if subscription.is_err() { + return false; + } + + let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::TRANSMIT, 0, 0) }; + if result_code != 0 { + return false; + } + + syscalls::yieldk_for(|| done.get()); + true +} + +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum SendOrRecvStatus { + Error, + Sent, + Received, +} + +// Either sends or receive a packet. +// Because USB transactions are initiated by the host, we don't decide whether an IN transaction +// (send for us), an OUT transaction (receive for us), or no transaction at all will happen next. +// +// - If an IN transaction happens first, the initial content of buf is sent to the host and the +// Sent status is returned. +// - If an OUT transaction happens first, the content of buf is replaced by the packet received +// from the host and Received status is returned. In that case, the original content of buf is not +// sent to the host, and it's up to the caller to retry sending or to handle the packet received +// from the host. +#[allow(dead_code)] +pub fn send_or_recv(buf: &mut [u8; 64]) -> SendOrRecvStatus { + let result = syscalls::allow(DRIVER_NUMBER, allow_nr::TRANSMIT_OR_RECEIVE, buf); + if result.is_err() { + return SendOrRecvStatus::Error; + } + + let status = Cell::new(None); + let mut alarm = |direction, _, _| { + status.set(Some(match direction { + subscribe_nr::callback_status::TRANSMITTED => SendOrRecvStatus::Sent, + subscribe_nr::callback_status::RECEIVED => SendOrRecvStatus::Received, + // Unknown direction sent by the kernel. + _ => SendOrRecvStatus::Error, + })); + }; + + let subscription = + syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::TRANSMIT_OR_RECEIVE, &mut alarm); + if subscription.is_err() { + return SendOrRecvStatus::Error; + } + + let result_code = + unsafe { syscalls::command(DRIVER_NUMBER, command_nr::TRANSMIT_OR_RECEIVE, 0, 0) }; + if result_code != 0 { + return SendOrRecvStatus::Error; + } + + syscalls::yieldk_for(|| status.get().is_some()); + status.get().unwrap() +} + +// Same as recv, but with a timeout. +// If the timeout elapses, return None. +pub fn recv_with_timeout( + buf: &mut [u8; 64], + timeout_delay: Duration, +) -> Option { + let result = syscalls::allow(DRIVER_NUMBER, allow_nr::RECEIVE, buf); + if result.is_err() { + return Some(SendOrRecvStatus::Error); + } + + let status = Cell::new(None); + let mut alarm = |direction, _, _| { + status.set(Some(match direction { + subscribe_nr::callback_status::RECEIVED => SendOrRecvStatus::Received, + // Unknown direction or "transmitted" sent by the kernel. + _ => SendOrRecvStatus::Error, + })); + }; + + let subscription = syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::RECEIVE, &mut alarm); + if subscription.is_err() { + return Some(SendOrRecvStatus::Error); + } + + // Setup a time-out callback. + let timeout_expired = Cell::new(false); + let mut timeout_callback = timer::with_callback(|_, _| { + timeout_expired.set(true); + }); + let mut timeout = match timeout_callback.init() { + Ok(x) => x, + Err(_) => return Some(SendOrRecvStatus::Error), + }; + let timeout_alarm = match timeout.set_alarm(timeout_delay) { + Ok(x) => x, + Err(_) => return Some(SendOrRecvStatus::Error), + }; + + // Trigger USB reception. + let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::RECEIVE, 0, 0) }; + if result_code != 0 { + return Some(SendOrRecvStatus::Error); + } + + syscalls::yieldk_for(|| status.get().is_some() || timeout_expired.get()); + + // Cleanup alarm callback. + match timeout.stop_alarm(timeout_alarm) { + Ok(()) => (), + Err(TockValue::Expected(StopAlarmError::AlreadyDisabled)) => { + if !timeout_expired.get() { + #[cfg(feature = "debug_ctap")] + writeln!( + Console::new(), + "The receive timeout already expired, but the callback wasn't executed." + ) + .unwrap(); + } + } + Err(e) => panic!("Unexpected error when stopping alarm: {:?}", e), + } + + // Cancel USB transaction if necessary. + if status.get().is_none() { + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Cancelling USB receive due to timeout").unwrap(); + let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::CANCEL, 0, 0) }; + match result_code { + // - SUCCESS means that we successfully cancelled the transaction. + // - EALREADY means that the transaction was already completed. + SUCCESS | EALREADY => (), + // - EBUSY means that the transaction is in progress. + EBUSY => { + // The app should wait for it, but it may never happen if the remote app crashes. + // We just return to avoid a deadlock. + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Couldn't cancel the USB receive").unwrap(); + } + _ => panic!( + "Unexpected error when cancelling USB receive: {:?}", + result_code + ), + } + } + + status.get() +} + +// Same as send_or_recv, but with a timeout. +// If the timeout elapses, return None. +pub fn send_or_recv_with_timeout( + buf: &mut [u8; 64], + timeout_delay: Duration, +) -> Option { + let result = syscalls::allow(DRIVER_NUMBER, allow_nr::TRANSMIT_OR_RECEIVE, buf); + if result.is_err() { + return Some(SendOrRecvStatus::Error); + } + + let status = Cell::new(None); + let mut alarm = |direction, _, _| { + status.set(Some(match direction { + subscribe_nr::callback_status::TRANSMITTED => SendOrRecvStatus::Sent, + subscribe_nr::callback_status::RECEIVED => SendOrRecvStatus::Received, + // Unknown direction sent by the kernel. + _ => SendOrRecvStatus::Error, + })); + }; + + let subscription = + syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::TRANSMIT_OR_RECEIVE, &mut alarm); + if subscription.is_err() { + return Some(SendOrRecvStatus::Error); + } + + // Setup a time-out callback. + let timeout_expired = Cell::new(false); + let mut timeout_callback = timer::with_callback(|_, _| { + timeout_expired.set(true); + }); + let mut timeout = match timeout_callback.init() { + Ok(x) => x, + Err(_) => return Some(SendOrRecvStatus::Error), + }; + let timeout_alarm = match timeout.set_alarm(timeout_delay) { + Ok(x) => x, + Err(_) => return Some(SendOrRecvStatus::Error), + }; + + // Trigger USB transmission. + let result_code = + unsafe { syscalls::command(DRIVER_NUMBER, command_nr::TRANSMIT_OR_RECEIVE, 0, 0) }; + if result_code != 0 { + return Some(SendOrRecvStatus::Error); + } + + syscalls::yieldk_for(|| status.get().is_some() || timeout_expired.get()); + + // Cleanup alarm callback. + match timeout.stop_alarm(timeout_alarm) { + Ok(()) => (), + Err(TockValue::Expected(StopAlarmError::AlreadyDisabled)) => { + if !timeout_expired.get() { + #[cfg(feature = "debug_ctap")] + writeln!( + Console::new(), + "The send/receive timeout already expired, but the callback wasn't executed." + ) + .unwrap(); + } + } + Err(e) => panic!("Unexpected error when stopping alarm: {:?}", e), + } + + // Cancel USB transaction if necessary. + if status.get().is_none() { + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Cancelling USB transaction due to timeout").unwrap(); + let result_code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::CANCEL, 0, 0) }; + match result_code { + // - SUCCESS means that we successfully cancelled the transaction. + // - EALREADY means that the transaction was already completed. + SUCCESS | EALREADY => (), + // - EBUSY means that the transaction is in progress. + EBUSY => { + // The app should wait for it, but it may never happen if the remote app crashes. + // We just return to avoid a deadlock. + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Couldn't cancel the transaction").unwrap(); + } + _ => panic!( + "Unexpected error when cancelling USB transaction: {:?}", + result_code + ), + } + #[cfg(feature = "debug_ctap")] + writeln!(Console::new(), "Cancelled USB transaction!").unwrap(); + } + + status.get() +} diff --git a/third_party/libtock-rs b/third_party/libtock-rs new file mode 160000 index 0000000..ab2c945 --- /dev/null +++ b/third_party/libtock-rs @@ -0,0 +1 @@ +Subproject commit ab2c945184b98ecae3e70ac678e9f5231deef73b diff --git a/third_party/tock b/third_party/tock new file mode 160000 index 0000000..862452b --- /dev/null +++ b/third_party/tock @@ -0,0 +1 @@ +Subproject commit 862452b77ae0fc160231a2250de385dc7c358ef7 diff --git a/tools/gen_key_materials.sh b/tools/gen_key_materials.sh new file mode 100644 index 0000000..260d8eb --- /dev/null +++ b/tools/gen_key_materials.sh @@ -0,0 +1,169 @@ +#!/bin/bash +# Copyright 2019 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. + +generate_crypto_materials () { + # Root CA key pair and certificate + local ca_priv_key=crypto_data/opensk_ca.key + local ca_cert_name=crypto_data/opensk_ca + + # Attestation key pair and certificate that will be embedded into the + # firmware. The certificate will be signed by the Root CA. + local opensk_key=crypto_data/opensk.key + local opensk_cert_name=crypto_data/opensk_cert + + # Rust file that we will generate will all cryptographic data. + local rust_file=src/ctap/key_material.rs + + # Allow invoker to override the command with a full path. + local openssl=${OPENSSL:-$(which openssl)} + + # We need openssl command to continue + if [ ! -x "${openssl}" ] + then + echo "Missing openssl command. Try to specify its full path using OPENSSL environment variable." + exit 1 + fi + + mkdir -p crypto_data + if [ ! -f "${ca_priv_key}" ] + then + "${openssl}" ecparam -genkey -name prime256v1 -out "${ca_priv_key}" + fi + + if [ ! -f "${ca_cert_name}.pem" ] + then + "${openssl}" req \ + -new \ + -key "${ca_priv_key}" \ + -out "${ca_cert_name}.csr" \ + -subj "/CN=Google OpenSK CA" + "${openssl}" x509 \ + -trustout \ + -req \ + -days 7305 \ + -in "${ca_cert_name}.csr" \ + -signkey "${ca_priv_key}" \ + -outform pem \ + -out "${ca_cert_name}.pem" \ + -sha256 + fi + + if [ ! -f "${opensk_key}" ] + then + "${openssl}" ecparam -genkey -name prime256v1 -out "${opensk_key}" + fi + + if [ ! -f "${opensk_cert_name}.pem" ] + then + "${openssl}" req \ + -new \ + -key "${opensk_key}" \ + -out "${opensk_cert_name}.csr" \ + -subj "/CN=Google OpenSK Hacker Edition" + "${openssl}" x509 \ + -req \ + -days 3652 \ + -in "${opensk_cert_name}.csr" \ + -CA "${ca_cert_name}.pem" \ + -CAkey "${ca_priv_key}" \ + -CAcreateserial \ + -outform pem \ + -out "${opensk_cert_name}.pem" \ + -sha256 + fi + + local cert_mtime=$(stat --printf="%Y" "${opensk_cert_name}.pem") + local rust_file_mtime=0 + # Only take into consideration the mtime of the file if it exists and if we're not forcing + # the rust file to be re-generated. + if [ -f "${rust_file}" -a "x$1" != "xY" ] + then + rust_file_mtime=$(stat --printf="%Y" "${rust_file}") + fi + if [ $cert_mtime -gt $rust_file_mtime ] + then + local cert_size=$("${openssl}" x509 \ + -in "${opensk_cert_name}.pem" \ + -outform der 2>/dev/null \ + | wc -c) + local cert_serial_hex=$("${openssl}" x509 \ + -in "${opensk_cert_name}.pem" \ + -noout \ + -serial \ + | cut -d'=' -f2) + # Pad with zeroes in case the serial is too short. We don't care if the + # serial is longer than 32 characters as we will only process the first 32 + # characters in the loop later. + cert_serial_hex="${cert_serial_hex}00000000000000000000000000000000" + + # Create header + echo "// This file had been generated by OpenSK deploy.sh script" > "${rust_file}" + echo "" >> "${rust_file}" + + echo "pub const AAGUID: [u8; 16] = [" >> "${rust_file}" + for i in `seq 0 2 30` + do + echo -n "0x${cert_serial_hex:$i:2}, " >> "${rust_file}" + done + echo "" >> "${rust_file}" + echo "];" >> "${rust_file}" + echo "" >> "${rust_file}" + + echo "pub const ATTESTATION_CERTIFICATE: [u8; ${cert_size}] = [" >> "${rust_file}" + "${openssl}" x509 \ + -in "${opensk_cert_name}.pem" \ + -outform der 2>/dev/null \ + | xxd -i >> "${rust_file}" + echo "];" >> "${rust_file}" + echo "" >> "${rust_file}" + + # Private key is tricky to extract as we want the raw value and not the DER encoding + # Example output of openssl ec -in file.key -noout -text: + # read EC key + # Private-Key: (256 bit) + # priv: + # 47:b3:58:b8:f0:09:1d:72:b1:03:34:62:9a:c7:b2: + # b2:e1:06:28:15:69:d4:82:b5:4e:21:6d:98:bf:65: + # 98:34 + # pub: + # 04:32:84:a1:3c:90:db:3f:db:d7:fb:ff:e9:00:c8: + # 8a:a1:79:2e:95:2e:7c:86:ec:19:03:97:6e:7c:d6: + # 67:eb:28:56:f1:d8:dd:cb:ae:ce:b9:cb:e4:6d:9d: + # 1d:76:96:fc:48:9b:2d:d5:80:86:04:3d:f9:fe:6c: + # f3:9a:45:bc:b1 + # ASN1 OID: prime256v1 + # NIST CURVE: P-256 + # + # The awk script starts printing lines after seeing a line starting with + # "priv:" and stops printing as soon as it reaches a line that doesn't start + # with a space. + # The sed script then converts the output into a proper hex-encode byte + # array by replacing the initial spaces on each line with "0x", replacing + # the semicolons at the end of each line by commas and replacing all + # remainging semicolons by ". 0x". + echo "pub const ATTESTATION_PRIVATE_KEY: [u8; 32] = [" >> "${rust_file}" + "${openssl}" ec \ + -in "${opensk_key}" \ + -noout \ + -text 2>/dev/null \ + | awk '/^priv:/{p=1;next}/^[^ ]/{p=0}p' \ + | sed -e 's/^ */0x/;s/:$/,/;s/:/, 0x/g' >> "${rust_file}" + echo "];" >> "${rust_file}" + echo "" >> "${rust_file}" + + # If the tool is installed, prettify the file. It will catch syntax errors earlier. + which rustfmt > /dev/null 2>&1 && rustfmt "${rust_file}" + fi +}