parsec-interface-0.29.1/.cargo/audit.toml000064400000000000000000000020201046102023000162760ustar 00000000000000[advisories] ignore = [] informational_warnings = ["unmaintained"] # warn for categories of informational advisories severity_threshold = "low" # CVSS severity ("none", "low", "medium", "high", "critical") # Advisory Database Configuration [database] path = "/tmp/advisory-db" # Path where advisory git repo will be cloned url = "https://github.com/RustSec/advisory-db.git" # URL to git repo fetch = true # Perform a `git fetch` before auditing stale = false # Allow stale advisory DB (i.e. no commits for 90 days) # Output Configuration [output] deny = ["unmaintained"] # exit on error if unmaintained dependencies are found format = "terminal" # "terminal" (human readable report) or "json" quiet = false # Only print information on error show_tree = true # Show inverse dependency trees along with advisories # Target Configuration [target] os = "linux" # Ignore advisories for operating systems other than this one [yanked] enabled = true # Warn for yanked crates in Cargo.lock update_index = true # Auto-update the crates.io index parsec-interface-0.29.1/.cargo_vcs_info.json0000644000000001360000000000100143400ustar { "git": { "sha1": "ce9ab8b003ced37d07aa473fb52ccb1245368234" }, "path_in_vcs": "" }parsec-interface-0.29.1/.github/workflows/ci.yml000064400000000000000000000010451046102023000176430ustar 00000000000000name: Continuous Integration on: [push, pull_request, workflow_dispatch] jobs: build: name: Build and check formatting runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Execute all tests run: ./tests/ci.sh links: name: Check links runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Link Checker uses: peter-evans/link-checker@v1 with: args: -v -r *.md - name: Fail if there were link errors run: exit ${{ steps.lc.outputs.exit_code }} parsec-interface-0.29.1/.github/workflows/nightly.yml000064400000000000000000000027371046102023000207370ustar 00000000000000name: Nightly Checks on: schedule: # Every night at midnight - cron: '0 0 * * *' workflow_dispatch: inputs: rev: description: "Revision hash to run against" required: false default: "" jobs: dependencies: name: Check for unused dependencies runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: ref: "${{ github.event.inputs.rev }}" - name: Install latest Rust uses: actions-rs/toolchain@v1 with: toolchain: nightly - name: Fetch submodules run: git submodule update --init - name: Install cargo udeps run: cargo install cargo-udeps --locked - name: Execute cargo udeps run: cargo +nightly udeps build: name: Build and check formatting with updated dependencies runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: ref: "${{ github.event.inputs.rev }}" - name: Execute all tests run: | rm Cargo.lock ./tests/ci.sh audit: name: Check for crates with security vulnerabilities runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: ref: "${{ github.event.inputs.rev }}" - name: Install latest Rust uses: actions-rs/toolchain@v1 with: toolchain: nightly - name: Install cargo audit run: cargo install cargo-audit - name: Execute cargo audit run: cargo audit parsec-interface-0.29.1/.gitignore000064400000000000000000000000241046102023000151140ustar 00000000000000/target tags *patch parsec-interface-0.29.1/.gitmodules000064400000000000000000000001711046102023000153040ustar 00000000000000[submodule "parsec-operations"] path = parsec-operations url = https://github.com/parallaxsecond/parsec-operations.git parsec-interface-0.29.1/.travis.yml.disabled000064400000000000000000000001601046102023000170040ustar 00000000000000# Executing our tests on Arm64 with Travis CI arch: arm64 dist: bionic language: rust script: - ./tests/ci.sh parsec-interface-0.29.1/CHANGELOG.md000064400000000000000000000660751046102023000147570ustar 00000000000000# Changelog ## [0.29.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.29.1) (2023-10-16) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.29.0...0.29.1) **Merged pull requests:** - Bump psa-crypto to 0.12.0 [\#146](https://github.com/parallaxsecond/parsec-interface-rs/pull/146) ([tgonzalezorlandoarm](https://github.com/tgonzalezorlandoarm)) ## [0.29.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.29.0) (2023-10-06) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.28.0...0.29.0) **Merged pull requests:** - Bump psa-crypto to 0.11.0 [\#144](https://github.com/parallaxsecond/parsec-interface-rs/pull/144) ([tgonzalezorlandoarm](https://github.com/tgonzalezorlandoarm)) - Bump num-derive to 0.4.0 [\#143](https://github.com/parallaxsecond/parsec-interface-rs/pull/143) ([tgonzalezorlandoarm](https://github.com/tgonzalezorlandoarm)) - Cargo.toml: Bump prost and prost-build to 0.9.0 [\#142](https://github.com/parallaxsecond/parsec-interface-rs/pull/142) ([tgonzalezorlandoarm](https://github.com/tgonzalezorlandoarm)) - Tg/msrv 1.66.0 [\#141](https://github.com/parallaxsecond/parsec-interface-rs/pull/141) ([tgonzalezorlandoarm](https://github.com/tgonzalezorlandoarm)) - Fix nightly issues [\#140](https://github.com/parallaxsecond/parsec-interface-rs/pull/140) ([gowthamsk-arm](https://github.com/gowthamsk-arm)) - Bump secrecy crate [\#139](https://github.com/parallaxsecond/parsec-interface-rs/pull/139) ([gowthamsk-arm](https://github.com/gowthamsk-arm)) ## [0.28.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.28.0) (2023-03-13) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.27.0...0.28.0) **Merged pull requests:** - Fix CI issues [\#136](https://github.com/parallaxsecond/parsec-interface-rs/pull/136) ([gowthamsk-arm](https://github.com/gowthamsk-arm)) - Do not derive Arbitrary for types not implementing it [\#135](https://github.com/parallaxsecond/parsec-interface-rs/pull/135) ([ema](https://github.com/ema)) - Update to remove const\_err [\#134](https://github.com/parallaxsecond/parsec-interface-rs/pull/134) ([marcsvll](https://github.com/marcsvll)) ## [0.27.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.27.0) (2022-09-09) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.26.0...0.27.0) **Implemented enhancements:** - Strongify wire header serialization [\#115](https://github.com/parallaxsecond/parsec-interface-rs/issues/115) - Validate hash length for psa\_sign\_hash [\#107](https://github.com/parallaxsecond/parsec-interface-rs/issues/107) - Find a way to represent deprecated primitives [\#33](https://github.com/parallaxsecond/parsec-interface-rs/issues/33) **Merged pull requests:** - Release prep 0.27.0 [\#132](https://github.com/parallaxsecond/parsec-interface-rs/pull/132) ([mohamedasaker-arm](https://github.com/mohamedasaker-arm)) - Use psa-crypto with updated zeroize [\#131](https://github.com/parallaxsecond/parsec-interface-rs/pull/131) ([gowthamsk-arm](https://github.com/gowthamsk-arm)) - Fix clippy warnings and ignore those under generated ops [\#130](https://github.com/parallaxsecond/parsec-interface-rs/pull/130) ([mohamedasaker-arm](https://github.com/mohamedasaker-arm)) - Feature/33 represent check deprecated primitives [\#129](https://github.com/parallaxsecond/parsec-interface-rs/pull/129) ([mohamedasaker-arm](https://github.com/mohamedasaker-arm)) - Configure bincode used in wire header serialization/deserialization [\#128](https://github.com/parallaxsecond/parsec-interface-rs/pull/128) ([mohamedasaker-arm](https://github.com/mohamedasaker-arm)) ## [0.26.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.26.0) (2022-02-15) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.25.0...0.26.0) **Implemented enhancements:** - Add key attestation operations [\#124](https://github.com/parallaxsecond/parsec-interface-rs/pull/124) ([ionut-arm](https://github.com/ionut-arm)) **Merged pull requests:** - Prepare for 0.26.0 release [\#126](https://github.com/parallaxsecond/parsec-interface-rs/pull/126) ([ionut-arm](https://github.com/ionut-arm)) - Merge can-do-crypto branch into main [\#125](https://github.com/parallaxsecond/parsec-interface-rs/pull/125) ([anta5010](https://github.com/anta5010)) - Merge origin/main into can-do-crypto [\#123](https://github.com/parallaxsecond/parsec-interface-rs/pull/123) ([anta5010](https://github.com/anta5010)) - Add PsaCipherEncrypt and PsaCipherDecrypt operations [\#122](https://github.com/parallaxsecond/parsec-interface-rs/pull/122) ([akazimierskigl](https://github.com/akazimierskigl)) - Upgrade prost to 0.8.0 [\#121](https://github.com/parallaxsecond/parsec-interface-rs/pull/121) ([hug-dev](https://github.com/hug-dev)) - Added the changes required for the CanDoCrypto operation. [\#120](https://github.com/parallaxsecond/parsec-interface-rs/pull/120) ([Kakemone](https://github.com/Kakemone)) - Update CHANGELOG [\#119](https://github.com/parallaxsecond/parsec-interface-rs/pull/119) ([hug-dev](https://github.com/hug-dev)) ## [0.25.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.25.0) (2021-08-03) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.24.0...0.25.0) **Implemented enhancements:** - Investigate pre-generating Rust protobuf code [\#98](https://github.com/parallaxsecond/parsec-interface-rs/issues/98) - Implement Deref on RequestBody and ResponseBody [\#61](https://github.com/parallaxsecond/parsec-interface-rs/issues/61) **Fixed bugs:** - Check that reserved fields are zero [\#109](https://github.com/parallaxsecond/parsec-interface-rs/pull/109) ([hug-dev](https://github.com/hug-dev)) **Security fixes:** - Bump prost crate versions [\#112](https://github.com/parallaxsecond/parsec-interface-rs/pull/112) ([ionut-arm](https://github.com/ionut-arm)) **Merged pull requests:** - Prepare for next release [\#118](https://github.com/parallaxsecond/parsec-interface-rs/pull/118) ([hug-dev](https://github.com/hug-dev)) - Commit the generated Rust protobuf files in tree [\#117](https://github.com/parallaxsecond/parsec-interface-rs/pull/117) ([hug-dev](https://github.com/hug-dev)) - Implement Deref\(Mut\) on bodies [\#116](https://github.com/parallaxsecond/parsec-interface-rs/pull/116) ([hug-dev](https://github.com/hug-dev)) - Add a cargo audit config [\#114](https://github.com/parallaxsecond/parsec-interface-rs/pull/114) ([hug-dev](https://github.com/hug-dev)) - Revert "Bump prost crate versions" [\#113](https://github.com/parallaxsecond/parsec-interface-rs/pull/113) ([ionut-arm](https://github.com/ionut-arm)) - Update psa-crypto [\#110](https://github.com/parallaxsecond/parsec-interface-rs/pull/110) ([hug-dev](https://github.com/hug-dev)) - Add more precision to error messages [\#108](https://github.com/parallaxsecond/parsec-interface-rs/pull/108) ([hug-dev](https://github.com/hug-dev)) - Fix latest clippy lints [\#106](https://github.com/parallaxsecond/parsec-interface-rs/pull/106) ([hug-dev](https://github.com/hug-dev)) - Add PsaSignMessage and PsaVerifyMessage operations [\#105](https://github.com/parallaxsecond/parsec-interface-rs/pull/105) ([akazimierskigl](https://github.com/akazimierskigl)) - Add updated changelog [\#104](https://github.com/parallaxsecond/parsec-interface-rs/pull/104) ([hug-dev](https://github.com/hug-dev)) ## [0.24.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.24.0) (2021-03-18) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.23.0...0.24.0) **Implemented enhancements:** - Rename ProviderID [\#36](https://github.com/parallaxsecond/parsec-interface-rs/issues/36) - Investigate possible use of zerocopy [\#10](https://github.com/parallaxsecond/parsec-interface-rs/issues/10) **Merged pull requests:** - Add version 0.24.0 [\#103](https://github.com/parallaxsecond/parsec-interface-rs/pull/103) ([hug-dev](https://github.com/hug-dev)) - Update psa-crypto dependence [\#102](https://github.com/parallaxsecond/parsec-interface-rs/pull/102) ([hug-dev](https://github.com/hug-dev)) - Implement Display on ProviderID and AuthType [\#101](https://github.com/parallaxsecond/parsec-interface-rs/pull/101) ([hug-dev](https://github.com/hug-dev)) - Add log message to help debugging [\#100](https://github.com/parallaxsecond/parsec-interface-rs/pull/100) ([hug-dev](https://github.com/hug-dev)) - Use newest PSA Crypto crate version [\#99](https://github.com/parallaxsecond/parsec-interface-rs/pull/99) ([ionut-arm](https://github.com/ionut-arm)) - Add Changelog file [\#97](https://github.com/parallaxsecond/parsec-interface-rs/pull/97) ([ionut-arm](https://github.com/ionut-arm)) ## [0.23.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.23.0) (2021-01-19) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.22.0...0.23.0) **Security fixes:** - Add a new ResponseStatus for admin operations [\#93](https://github.com/parallaxsecond/parsec-interface-rs/issues/93) **Closed issues:** - Add ListClients and DeleteClient structures [\#94](https://github.com/parallaxsecond/parsec-interface-rs/issues/94) **Merged pull requests:** - Bump PSA Crypto version [\#96](https://github.com/parallaxsecond/parsec-interface-rs/pull/96) ([ionut-arm](https://github.com/ionut-arm)) - Add ListClients and DeleteClient operations [\#95](https://github.com/parallaxsecond/parsec-interface-rs/pull/95) ([hug-dev](https://github.com/hug-dev)) - Fix lints and remove Travis build [\#92](https://github.com/parallaxsecond/parsec-interface-rs/pull/92) ([ionut-arm](https://github.com/ionut-arm)) ## [0.22.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.22.0) (2020-12-18) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.21.0...0.22.0) **Merged pull requests:** - Consume psa-crypto at version 0.6.1 and bump interface to 0.22.0 [\#91](https://github.com/parallaxsecond/parsec-interface-rs/pull/91) ([paulhowardarm](https://github.com/paulhowardarm)) - Add CryptoAuthLib to Provider enumeration. [\#90](https://github.com/parallaxsecond/parsec-interface-rs/pull/90) ([RobertDrazkowskiGL](https://github.com/RobertDrazkowskiGL)) - Update psa-crypto version [\#89](https://github.com/parallaxsecond/parsec-interface-rs/pull/89) ([hug-dev](https://github.com/hug-dev)) ## [0.21.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.21.0) (2020-10-20) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.20.2...0.21.0) **Implemented enhancements:** - Write opcode numbers in hexadecimal format [\#82](https://github.com/parallaxsecond/parsec-interface-rs/issues/82) - Create conversion method from TryFromIntError for ResponseStatus [\#53](https://github.com/parallaxsecond/parsec-interface-rs/issues/53) - Add Trusted Services crypto provider ID [\#87](https://github.com/parallaxsecond/parsec-interface-rs/pull/87) ([ionut-arm](https://github.com/ionut-arm)) - Add a JWT SVID authentication type [\#84](https://github.com/parallaxsecond/parsec-interface-rs/pull/84) ([hug-dev](https://github.com/hug-dev)) **Fixed bugs:** - Fix nightly CI [\#78](https://github.com/parallaxsecond/parsec-interface-rs/pull/78) ([hug-dev](https://github.com/hug-dev)) **Closed issues:** - Add support for another authenticator [\#70](https://github.com/parallaxsecond/parsec-interface-rs/issues/70) **Merged pull requests:** - Add methods to check opcode nature [\#88](https://github.com/parallaxsecond/parsec-interface-rs/pull/88) ([hug-dev](https://github.com/hug-dev)) - Use hexadecimal format for opcode values [\#86](https://github.com/parallaxsecond/parsec-interface-rs/pull/86) ([hug-dev](https://github.com/hug-dev)) - Add a uuid::Error conversion [\#85](https://github.com/parallaxsecond/parsec-interface-rs/pull/85) ([hug-dev](https://github.com/hug-dev)) - Add ListKeys operation [\#83](https://github.com/parallaxsecond/parsec-interface-rs/pull/83) ([joechrisellis](https://github.com/joechrisellis)) ## [0.20.2](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.20.2) (2020-09-04) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.20.1...0.20.2) **Implemented enhancements:** - Re-export `uuid` crate [\#51](https://github.com/parallaxsecond/parsec-interface-rs/issues/51) - Upgrade dependencies [\#77](https://github.com/parallaxsecond/parsec-interface-rs/pull/77) ([hug-dev](https://github.com/hug-dev)) **Security fixes:** - Audit response status code for information disclosure [\#59](https://github.com/parallaxsecond/parsec-interface-rs/issues/59) ## [0.20.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.20.1) (2020-08-20) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.20.0...0.20.1) ## [0.20.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.20.0) (2020-08-14) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.19.0...0.20.0) **Fixed bugs:** - Fix clippy warnings [\#67](https://github.com/parallaxsecond/parsec-interface-rs/pull/67) ([ionut-arm](https://github.com/ionut-arm)) **Merged pull requests:** - Added raw key agreement interface [\#75](https://github.com/parallaxsecond/parsec-interface-rs/pull/75) ([sbailey-arm](https://github.com/sbailey-arm)) - Added hash compute and compare interfaces [\#74](https://github.com/parallaxsecond/parsec-interface-rs/pull/74) ([sbailey-arm](https://github.com/sbailey-arm)) - Added aead encrypt and decrypt [\#73](https://github.com/parallaxsecond/parsec-interface-rs/pull/73) ([sbailey-arm](https://github.com/sbailey-arm)) - Add support for ListAuthenticators operation [\#72](https://github.com/parallaxsecond/parsec-interface-rs/pull/72) ([joechrisellis](https://github.com/joechrisellis)) - Add new AuthType variants [\#71](https://github.com/parallaxsecond/parsec-interface-rs/pull/71) ([joechrisellis](https://github.com/joechrisellis)) - Add support for `psa_generate_random` [\#68](https://github.com/parallaxsecond/parsec-interface-rs/pull/68) ([joechrisellis](https://github.com/joechrisellis)) ## [0.19.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.19.0) (2020-07-15) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.18.0...0.19.0) **Implemented enhancements:** - Bump version of psa-crypto to 0.3.0 [\#66](https://github.com/parallaxsecond/parsec-interface-rs/pull/66) ([hug-dev](https://github.com/hug-dev)) - Added export key [\#65](https://github.com/parallaxsecond/parsec-interface-rs/pull/65) ([sbailey-arm](https://github.com/sbailey-arm)) **Merged pull requests:** - Added the from impls for going from an operations and result to NativeOperation and NativeResult for asym encrypt and decrypt [\#64](https://github.com/parallaxsecond/parsec-interface-rs/pull/64) ([sbailey-arm](https://github.com/sbailey-arm)) ## [0.18.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.18.0) (2020-07-07) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.17.1...0.18.0) **Merged pull requests:** - Added asymmetric encrypt and decrypt [\#63](https://github.com/parallaxsecond/parsec-interface-rs/pull/63) ([sbailey-arm](https://github.com/sbailey-arm)) ## [0.17.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.17.1) (2020-07-01) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.17.0...0.17.1) **Fixed bugs:** - Fix compilation on testing feature [\#62](https://github.com/parallaxsecond/parsec-interface-rs/pull/62) ([hug-dev](https://github.com/hug-dev)) ## [0.17.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.17.0) (2020-06-26) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.16.0...0.17.0) **Implemented enhancements:** - Implement DataBuffer and replace byte vectors [\#60](https://github.com/parallaxsecond/parsec-interface-rs/pull/60) ([ionut-arm](https://github.com/ionut-arm)) ## [0.16.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.16.0) (2020-06-18) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.15.0...0.16.0) **Implemented enhancements:** - Import the newer version of psa-crypto [\#58](https://github.com/parallaxsecond/parsec-interface-rs/pull/58) ([hug-dev](https://github.com/hug-dev)) ## [0.15.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.15.0) (2020-06-03) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.14.1...0.15.0) **Implemented enhancements:** - Use crates.io for psa-crypto [\#57](https://github.com/parallaxsecond/parsec-interface-rs/pull/57) ([hug-dev](https://github.com/hug-dev)) - Derive PartialEq, Hash and Eq on ProviderInfo [\#54](https://github.com/parallaxsecond/parsec-interface-rs/pull/54) ([ionut-arm](https://github.com/ionut-arm)) **Merged pull requests:** - Replace algorithms and attributes with psa-crypto [\#55](https://github.com/parallaxsecond/parsec-interface-rs/pull/55) ([ionut-arm](https://github.com/ionut-arm)) ## [0.14.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.14.1) (2020-05-11) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.14.0...0.14.1) **Implemented enhancements:** - Add validation to sign and verify operations [\#52](https://github.com/parallaxsecond/parsec-interface-rs/pull/52) ([ionut-arm](https://github.com/ionut-arm)) **Fixed bugs:** - Modify Opcode enumeration size [\#49](https://github.com/parallaxsecond/parsec-interface-rs/issues/49) - Modify Opcode size [\#50](https://github.com/parallaxsecond/parsec-interface-rs/pull/50) ([hug-dev](https://github.com/hug-dev)) ## [0.14.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.14.0) (2020-04-23) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.13.0...0.14.0) **Implemented enhancements:** - Breaking change to wire protocol 1.0 to support additional fields and transports [\#48](https://github.com/parallaxsecond/parsec-interface-rs/pull/48) ([paulhowardarm](https://github.com/paulhowardarm)) - Update copyrights on all files [\#46](https://github.com/parallaxsecond/parsec-interface-rs/pull/46) ([hug-dev](https://github.com/hug-dev)) **Fixed bugs:** - Make wire protocol version a property of request and response headers [\#41](https://github.com/parallaxsecond/parsec-interface-rs/issues/41) - Make sure there is a clear separation between PSA and Core structures [\#30](https://github.com/parallaxsecond/parsec-interface-rs/issues/30) ## [0.13.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.13.0) (2020-04-15) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.12.0...0.13.0) **Implemented enhancements:** - Add body type getter in Convert trait [\#40](https://github.com/parallaxsecond/parsec-interface-rs/issues/40) - Add provider ID to list\_opcodes [\#44](https://github.com/parallaxsecond/parsec-interface-rs/pull/44) ([ionut-arm](https://github.com/ionut-arm)) - Add body\_type fn to Convert [\#42](https://github.com/parallaxsecond/parsec-interface-rs/pull/42) ([ionut-arm](https://github.com/ionut-arm)) **Merged pull requests:** - Bump version number [\#45](https://github.com/parallaxsecond/parsec-interface-rs/pull/45) ([ionut-arm](https://github.com/ionut-arm)) ## [0.12.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.12.0) (2020-04-07) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.11.0...0.12.0) **Implemented enhancements:** - Add faillible methods [\#39](https://github.com/parallaxsecond/parsec-interface-rs/pull/39) ([hug-dev](https://github.com/hug-dev)) - Add a new method for permisison and compatibility [\#38](https://github.com/parallaxsecond/parsec-interface-rs/pull/38) ([hug-dev](https://github.com/hug-dev)) ## [0.11.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.11.0) (2020-04-03) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.10.0...0.11.0) **Implemented enhancements:** - Add permits method to check for policy [\#37](https://github.com/parallaxsecond/parsec-interface-rs/pull/37) ([hug-dev](https://github.com/hug-dev)) ## [0.10.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.10.0) (2020-03-18) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.8.3...0.10.0) **Implemented enhancements:** - Update to PSA Crypto API 1.0.0 [\#4](https://github.com/parallaxsecond/parsec-interface-rs/issues/4) - Update to PSA Crypto API 1.0.0 [\#28](https://github.com/parallaxsecond/parsec-interface-rs/pull/28) ([hug-dev](https://github.com/hug-dev)) **Closed issues:** - Update documentation after upgrading to PSA Crypto 1.0.0 [\#29](https://github.com/parallaxsecond/parsec-interface-rs/issues/29) **Merged pull requests:** - Add missing\_doc as an error [\#31](https://github.com/parallaxsecond/parsec-interface-rs/pull/31) ([hug-dev](https://github.com/hug-dev)) ## [0.8.3](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.8.3) (2020-02-28) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.8.2...0.8.3) **Implemented enhancements:** - Add code documentation [\#26](https://github.com/parallaxsecond/parsec-interface-rs/pull/26) ([hug-dev](https://github.com/hug-dev)) ## [0.8.2](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.8.2) (2020-02-25) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.8.1...0.8.2) ## [0.8.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.8.1) (2020-02-24) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.8.0...0.8.1) **Fixed bugs:** - Fix supported wire protocol version [\#24](https://github.com/parallaxsecond/parsec-interface-rs/pull/24) ([hug-dev](https://github.com/hug-dev)) ## [0.8.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.8.0) (2020-02-21) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.7.1...0.8.0) ## [0.7.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.7.1) (2020-02-06) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.7.0...0.7.1) **Implemented enhancements:** - Add a submodule for the operations [\#21](https://github.com/parallaxsecond/parsec-interface-rs/pull/21) ([hug-dev](https://github.com/hug-dev)) **Fixed bugs:** - Deploy on crates.io [\#14](https://github.com/parallaxsecond/parsec-interface-rs/issues/14) ## [0.7.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.7.0) (2020-02-05) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.6.1...0.7.0) **Implemented enhancements:** - Add Travis CI tests for Aarch64 [\#12](https://github.com/parallaxsecond/parsec-interface-rs/issues/12) **Fixed bugs:** - Build fails with confusing message if wget is not available [\#17](https://github.com/parallaxsecond/parsec-interface-rs/issues/17) - Replace direct `Command` by crates in the build script [\#7](https://github.com/parallaxsecond/parsec-interface-rs/issues/7) ## [0.6.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.6.1) (2020-02-04) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.6.0...0.6.1) **Implemented enhancements:** - Various lint fixes [\#18](https://github.com/parallaxsecond/parsec-interface-rs/pull/18) ([hug-dev](https://github.com/hug-dev)) **Fixed bugs:** - Replace cross tests for native tests [\#19](https://github.com/parallaxsecond/parsec-interface-rs/pull/19) ([hug-dev](https://github.com/hug-dev)) ## [0.6.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.6.0) (2020-01-30) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.5.1...0.6.0) **Fixed bugs:** - Add body length limit to reading requests and responses [\#16](https://github.com/parallaxsecond/parsec-interface-rs/pull/16) ([ionut-arm](https://github.com/ionut-arm)) ## [0.5.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.5.1) (2020-01-28) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.5.0...0.5.1) **Implemented enhancements:** - Derive Arbitrary for fuzz testing [\#15](https://github.com/parallaxsecond/parsec-interface-rs/pull/15) ([ionut-arm](https://github.com/ionut-arm)) ## [0.5.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.5.0) (2020-01-27) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.4.1...0.5.0) **Implemented enhancements:** - Remove most panicking behaviour [\#13](https://github.com/parallaxsecond/parsec-interface-rs/pull/13) ([hug-dev](https://github.com/hug-dev)) ## [0.4.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.4.1) (2020-01-09) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.4.0...0.4.1) **Implemented enhancements:** - Deny compilation for some rustc lints [\#11](https://github.com/parallaxsecond/parsec-interface-rs/pull/11) ([hug-dev](https://github.com/hug-dev)) ## [0.4.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.4.0) (2019-12-05) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.3.0...0.4.0) **Implemented enhancements:** - Add TPM Provider [\#9](https://github.com/parallaxsecond/parsec-interface-rs/pull/9) ([hug-dev](https://github.com/hug-dev)) ## [0.3.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.3.0) (2019-11-18) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.2.1...0.3.0) **Implemented enhancements:** - Add PKCS 11 ProviderID enumeration variant [\#8](https://github.com/parallaxsecond/parsec-interface-rs/pull/8) ([hug-dev](https://github.com/hug-dev)) ## [0.2.1](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.2.1) (2019-11-01) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.2.0...0.2.1) **Implemented enhancements:** - Add cross-compilation and testing to Arm64 on CI [\#6](https://github.com/parallaxsecond/parsec-interface-rs/pull/6) ([hug-dev](https://github.com/hug-dev)) ## [0.2.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.2.0) (2019-10-23) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/0.1.0...0.2.0) **Merged pull requests:** - Remove references to key lifetime [\#5](https://github.com/parallaxsecond/parsec-interface-rs/pull/5) ([hug-dev](https://github.com/hug-dev)) - Remove ci folder and modify CI workflow [\#3](https://github.com/parallaxsecond/parsec-interface-rs/pull/3) ([hug-dev](https://github.com/hug-dev)) ## [0.1.0](https://github.com/parallaxsecond/parsec-interface-rs/tree/0.1.0) (2019-10-09) [Full Changelog](https://github.com/parallaxsecond/parsec-interface-rs/compare/c89c06232024d57d96826b41ea4d409a021fd530...0.1.0) **Merged pull requests:** - Add a specific tag when getting operations [\#2](https://github.com/parallaxsecond/parsec-interface-rs/pull/2) ([hug-dev](https://github.com/hug-dev)) - Split Rust interface into its own repository [\#1](https://github.com/parallaxsecond/parsec-interface-rs/pull/1) ([hug-dev](https://github.com/hug-dev)) \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* parsec-interface-0.29.1/Cargo.toml0000644000000033010000000000100123330ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.66.0" name = "parsec-interface" version = "0.29.1" authors = ["Parsec Project Contributors"] description = "Parsec interface library to communicate using the wire protocol" readme = "README.md" keywords = [ "parsec", "interface", "serialization", ] categories = ["encoding"] license = "Apache-2.0" repository = "https://github.com/parallaxsecond/parsec-interface-rs" [dependencies.arbitrary] version = "0.4.6" features = ["derive"] optional = true [dependencies.bincode] version = "1.3.1" [dependencies.derivative] version = "2.1.1" [dependencies.log] version = "0.4.11" [dependencies.num] version = "0.4.0" [dependencies.num-derive] version = "0.4.0" [dependencies.num-traits] version = "0.2.12" [dependencies.prost] version = "0.9.0" [dependencies.psa-crypto] version = "0.12.0" default-features = false [dependencies.secrecy] version = "0.8.0" features = ["serde"] [dependencies.serde] version = "1.0.115" features = ["derive"] [dependencies.uuid] version = "0.8.1" [dependencies.zeroize] version = "1.1.0" features = ["zeroize_derive"] [build-dependencies.prost-build] version = "0.9.0" optional = true [features] fuzz = ["arbitrary"] regenerate-protobuf = ["prost-build"] testing = [] parsec-interface-0.29.1/Cargo.toml.orig000064400000000000000000000020121046102023000160120ustar 00000000000000[package] name = "parsec-interface" version = "0.29.1" authors = ["Parsec Project Contributors"] description = "Parsec interface library to communicate using the wire protocol" license = "Apache-2.0" repository = "https://github.com/parallaxsecond/parsec-interface-rs" readme = "README.md" keywords = ["parsec", "interface", "serialization"] categories = ["encoding"] edition = "2018" rust-version = "1.66.0" [build-dependencies] prost-build = { version = "0.9.0", optional = true } [dependencies] serde = { version = "1.0.115", features = ["derive"] } bincode = "1.3.1" num-traits = "0.2.12" num-derive = "0.4.0" num = "0.4.0" prost = "0.9.0" arbitrary = { version = "0.4.6", features = ["derive"], optional = true } uuid = "0.8.1" log = "0.4.11" psa-crypto = { version = "0.12.0", default-features = false } zeroize = { version = "1.1.0", features = ["zeroize_derive"] } secrecy = { version = "0.8.0", features = ["serde"] } derivative = "2.1.1" [features] testing = [] fuzz = ["arbitrary"] regenerate-protobuf = ["prost-build"] parsec-interface-0.29.1/LICENSE000064400000000000000000000261361046102023000141450ustar 00000000000000 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. parsec-interface-0.29.1/MAINTAINERS.toml000064400000000000000000000024171046102023000156030ustar 00000000000000# parsec-interface-rs maintainers file # # This file lists the maintainers of the parallaxsecond/parsec-interface-rs # project. # # Its structure is inspired from the maintainers files in the Docker Github # repositories. Please see the MAINTAINERS file in docker/opensource for more # information. [maintainers] # Core maintainers of the project. [maintainers.core] people = [ "adamparco", "heavypackets", "hug-dev", "ionut-arm", "justincormack", "paulhowardarm", ] [people] # A reference list of all people associated with the project. [people.adamparco] Name = "Adam Parco" Email = "adam.parco@docker.com" GitHub = "adamparco" [people.heavypackets] Name = "Sabree Blackmon" Email = "sabree.blackmon@docker.com" GitHub = "heavypackets" [people.hug-dev] Name = "Hugues de Valon" Email = "hugues.devalon@arm.com" GitHub = "hug-dev" [people.ionut-arm] Name = "Ionut Mihalcea" Email = "ionut.mihalcea@docker.com" GitHub = "ionut-arm" [people.justincormack] Name = "Justin Cormack" Email = "justin.cormack@docker.com" GitHub = "justincormack" [people.paulhowardarm] Name = "Paul Howard" Email = "paul.howard@arm.com" GitHub = "paulhowardarm" parsec-interface-0.29.1/README.md000064400000000000000000000025631046102023000144150ustar 00000000000000# Parsec Rust Interface

Crates.io Code documentation

This repository contains an interface library to be used both by the Parsec service and a Rust Client library. The library contains methods to communicate using the [wire protocol](https://parallaxsecond.github.io/parsec-book/parsec_client/wire_protocol.html). ## Build The Parsec operations repository is included as a submodule. Make sure to update it first before trying to compile otherwise it will not work ("`No such file or directory`"). ```bash $ git submodule update --init ``` By default, the crate will use the pre-generated Rust Protobuf files in `src/operations_protobuf/generated_ops`. To re-generate them from the `parsec-operations` submodule, compile this crate with the feature `regenerate-protobuf`. ## License The software is provided under Apache-2.0. Contributions to this project are accepted under the same license. ## Contributing Please check the [**Contribution Guidelines**](https://parallaxsecond.github.io/parsec-book/contributing/index.html) to know more about the contribution process. *Copyright 2021 Contributors to the Parsec project.* parsec-interface-0.29.1/build.rs000064400000000000000000000036751046102023000146100ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 // This one is hard to avoid. #![allow(clippy::multiple_crate_versions)] use std::io::Result; // Replace the committed protobuf files with the generated one. #[cfg(feature = "regenerate-protobuf")] fn generate_proto_sources() -> Result<()> { use std::fs::read_dir; use std::io::{Error, ErrorKind}; use std::path::Path; use std::process::Command; let path = String::from("parsec-operations/protobuf"); let dir_entries = read_dir(Path::new(&path))?; let files: Result> = dir_entries .map(|protos_file| { protos_file? .path() .into_os_string() .into_string() .map_err(|_| { Error::new( ErrorKind::InvalidData, "conversion from OsString to String failed", ) }) }) // Fail the entire operation if there was an error. .collect(); let proto_files: Vec = files? .into_iter() .filter(|string| string.ends_with(".proto")) .collect(); let files_slices: Vec<&str> = proto_files.iter().map(|file| &file[..]).collect(); prost_build::compile_protos(&files_slices, &[&path])?; // Copy all files generated in src/operations_protobuf/generated_ops let status = Command::new("bash") .arg("-c") .arg(format!( "cp {}/*.rs src/operations_protobuf/generated_ops", std::env::var("OUT_DIR").expect("OUT_DIR env var is empty") )) .status()?; if !status.success() { Err(Error::new( ErrorKind::InvalidData, "failed copying generated protobuf files", )) } else { Ok(()) } } fn main() -> Result<()> { #[cfg(feature = "regenerate-protobuf")] generate_proto_sources()?; Ok(()) } parsec-interface-0.29.1/parsec-operations/.github/workflows/ci.yml000064400000000000000000000015721046102023000233060ustar 00000000000000name: Continuous Integration on: [push, pull_request] jobs: format: name: Check formatting runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Install clang-format run: | sudo apt update # This is needed because of a bug, see microsoft/azure-pipelines-image-generation#672 sudo apt-get remove -y clang-6.0 libclang-common-6.0-dev libclang1-6.0 libllvm6.0 sudo apt-get autoremove sudo apt install clang-format - name: Check formatting using clang-format run: ./ci/check_format.sh build: name: Build tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Install protoc run: | sudo apt update sudo apt install protobuf-compiler - name: Check that the protobuf files compile using protoc run: ./ci/check_build.sh parsec-interface-0.29.1/parsec-operations/.gitignore000064400000000000000000000000101046102023000205450ustar 00000000000000*.patch parsec-interface-0.29.1/parsec-operations/LICENSE000064400000000000000000000261361046102023000176030ustar 00000000000000 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. parsec-interface-0.29.1/parsec-operations/MAINTAINERS.toml000064400000000000000000000026121046102023000212360ustar 00000000000000# parsec-operations maintainers file # # This file lists the maintainers of the parallaxsecond/parsec-operations # project. # # Its structure is inspired from the maintainers files in the Docker Github # repositories. Please see the MAINTAINERS file in docker/opensource for more # information. [maintainers] # Core maintainers of the project. [maintainers.core] people = [ "adamparco", "anta5010", "heavypackets", "hug-dev", "ionut-arm", "justincormack", "paulhowardarm", ] [people] # A reference list of all people associated with the project. [people.adamparco] Name = "Adam Parco" Email = "adam.parco@docker.com" GitHub = "adamparco" [people.anta5010] Name = "Anton Antonov" Email = "anton.antonov@arm.com" GitHub = "anta5010" [people.heavypackets] Name = "Sabree Blackmon" Email = "sabree.blackmon@docker.com" GitHub = "heavypackets" [people.hug-dev] Name = "Hugues de Valon" Email = "hugues.devalon@arm.com" GitHub = "hug-dev" [people.ionut-arm] Name = "Ionut Mihalcea" Email = "ionut.mihalcea@docker.com" GitHub = "ionut-arm" [people.justincormack] Name = "Justin Cormack" Email = "justin.cormack@docker.com" GitHub = "justincormack" [people.paulhowardarm] Name = "Paul Howard" Email = "paul.howard@arm.com" GitHub = "paulhowardarm" parsec-interface-0.29.1/parsec-operations/README.md000064400000000000000000000022451046102023000200500ustar 00000000000000 # Parsec Language Neutral Operations ![](https://github.com/parallaxsecond/parsec-operations/workflows/Continuous%20Integration/badge.svg) This repository provides a centralised access for all Parsec operations. Client libraries can download and compile the operations of this repository to the programming language that they use. Please check the [operations document](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/index.html) for more information on operations. # License The software is provided under Apache-2.0. Contributions to this project are accepted under the same license. # User Guide In order to make a Parsec client library, you will need to add in the build script of your library the needed operations to clone this git repository and then compile the operations into functions to convert between your language native memory structures and the operations format. # Contributing Please check the [**Contribution Guidelines**](https://parallaxsecond.github.io/parsec-book/contributing.html) to know more about the contribution process. parsec-interface-0.29.1/parsec-operations/ci/check_build.sh000075500000000000000000000005731046102023000217610ustar 00000000000000#!/usr/bin/env bash # Copyright 2020 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 set -e OUT_DIR="/tmp/parsec-operations-ci" mkdir -p $OUT_DIR # Check that protoc can build the protobuf files. mkdir -p $OUT_DIR/protobuf PROTOBUF_FILES=protobuf/*.proto for f in $PROTOBUF_FILES do protoc --proto_path=protobuf --cpp_out=$OUT_DIR/protobuf $f done parsec-interface-0.29.1/parsec-operations/ci/check_format.sh000075500000000000000000000006731046102023000221530ustar 00000000000000#!/usr/bin/env bash # Copyright 2020 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 set -e # Check the git diff between the clang-formatted file and the actual file to # make sure they match. OUT_DIR="/tmp/parsec-operations-ci" mkdir -p $OUT_DIR # protobuf tests mkdir -p $OUT_DIR/protobuf PROTOBUF_FILES=protobuf/*.proto for f in $PROTOBUF_FILES do clang-format $f > $OUT_DIR/$f git diff $f $OUT_DIR/$f done parsec-interface-0.29.1/parsec-operations/protobuf/delete_client.proto000064400000000000000000000003141046102023000243110ustar 00000000000000/* * Copyright 2021 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package delete_client; message Operation { string client = 1; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/list_authenticators.proto000064400000000000000000000006061046102023000256050ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package list_authenticators; message AuthenticatorInfo { string description = 1; uint32 version_maj = 2; uint32 version_min = 3; uint32 version_rev = 4; uint32 id = 5; } message Operation {} message Result { repeated AuthenticatorInfo authenticators = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/list_clients.proto000064400000000000000000000003251046102023000242070ustar 00000000000000/* * Copyright 2021 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package list_clients; message Operation {} message Result { repeated string clients = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/list_keys.proto000064400000000000000000000005511046102023000235220ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package list_keys; import "psa_key_attributes.proto"; message KeyInfo { uint32 provider_id = 1; string name = 2; psa_key_attributes.KeyAttributes attributes = 3; } message Operation {} message Result { repeated KeyInfo keys = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/list_opcodes.proto000064400000000000000000000004051046102023000242010ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package list_opcodes; message Operation { uint32 provider_id = 1; } // Cast down to 8 bits message Result { repeated uint32 opcodes = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/list_providers.proto000064400000000000000000000006321046102023000245640ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package list_providers; message ProviderInfo { string uuid = 1; string description = 2; string vendor = 3; uint32 version_maj = 4; uint32 version_min = 5; uint32 version_rev = 6; uint32 id = 7; } message Operation {} message Result { repeated ProviderInfo providers = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/ping.proto000064400000000000000000000004561046102023000224550ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package ping; message Operation {} message Result { uint32 wire_protocol_version_maj = 1; // Cast down to 8 bits uint32 wire_protocol_version_min = 2; // Cast down to 8 bits } parsec-interface-0.29.1/parsec-operations/protobuf/psa_aead_decrypt.proto000064400000000000000000000005671046102023000250120ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_aead_decrypt; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.Aead alg = 2; bytes nonce = 3; bytes additional_data = 4; bytes ciphertext = 5; } message Result { bytes plaintext = 1; }parsec-interface-0.29.1/parsec-operations/protobuf/psa_aead_encrypt.proto000064400000000000000000000005671046102023000250240ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_aead_encrypt; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.Aead alg = 2; bytes nonce = 3; bytes additional_data = 4; bytes plaintext = 5; } message Result { bytes ciphertext = 1; }parsec-interface-0.29.1/parsec-operations/protobuf/psa_algorithm.proto000064400000000000000000000067421046102023000243550ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_algorithm; message Algorithm { message None {} enum Hash { HASH_NONE = 0; // This default variant should not be used. MD2 = 1 [ deprecated = true ]; MD4 = 2 [ deprecated = true ]; MD5 = 3 [ deprecated = true ]; RIPEMD160 = 4; SHA_1 = 5 [ deprecated = true ]; SHA_224 = 6; SHA_256 = 7; SHA_384 = 8; SHA_512 = 9; SHA_512_224 = 10; SHA_512_256 = 11; SHA3_224 = 12; SHA3_256 = 13; SHA3_384 = 14; SHA3_512 = 15; } message Mac { message FullLength { message Hmac { Hash hash_alg = 1; } message CbcMac {} message Cmac {} oneof variant { Hmac hmac = 1; CbcMac cbc_mac = 2; Cmac cmac = 3; } } message Truncated { FullLength mac_alg = 1; uint32 mac_length = 2; } oneof variant { FullLength full_length = 1; Truncated truncated = 2; } } enum Cipher { CIPHER_NONE = 0; // This default variant should not be used. STREAM_CIPHER = 1; CTR = 2; CFB = 3; OFB = 4; XTS = 5; ECB_NO_PADDING = 6; CBC_NO_PADDING = 7; CBC_PKCS7 = 8; } message Aead { enum AeadWithDefaultLengthTag { AEAD_WITH_DEFAULT_LENGTH_TAG_NONE = 0; // This default variant should not be used. CCM = 1; GCM = 2; CHACHA20_POLY1305 = 3; } message AeadWithShortenedTag { AeadWithDefaultLengthTag aead_alg = 1; uint32 tag_length = 2; } oneof variant { AeadWithDefaultLengthTag aead_with_default_length_tag = 1; AeadWithShortenedTag aead_with_shortened_tag = 2; } } message AsymmetricSignature { message SignHash { message Any {} oneof variant { Any any = 1; Hash specific = 2; } } message RsaPkcs1v15Sign { SignHash hash_alg = 1; } message RsaPkcs1v15SignRaw {} message RsaPss { SignHash hash_alg = 1; } message Ecdsa { SignHash hash_alg = 1; } message EcdsaAny {} message DeterministicEcdsa { SignHash hash_alg = 1; } oneof variant { RsaPkcs1v15Sign rsa_pkcs1v15_sign = 1; RsaPkcs1v15SignRaw rsa_pkcs1v15_sign_raw = 2; RsaPss rsa_pss = 3; Ecdsa ecdsa = 4; EcdsaAny ecdsa_any = 5; DeterministicEcdsa deterministic_ecdsa = 6; } } message AsymmetricEncryption { message RsaPkcs1v15Crypt {} message RsaOaep { Hash hash_alg = 1; } oneof variant { RsaPkcs1v15Crypt rsa_pkcs1v15_crypt = 1; RsaOaep rsa_oaep = 2; } } message KeyAgreement { enum Raw { RAW_NONE = 0; // This default variant should not be used. FFDH = 1; ECDH = 2; } message WithKeyDerivation { Raw ka_alg = 1; KeyDerivation kdf_alg = 2; } oneof variant { Raw raw = 1; WithKeyDerivation with_key_derivation = 2; } } message KeyDerivation { message Hkdf { Hash hash_alg = 1; } message Tls12Prf { Hash hash_alg = 1; } message Tls12PskToMs { Hash hash_alg = 1; } oneof variant { Hkdf hkdf = 1; Tls12Prf tls12_prf = 2; Tls12PskToMs tls12_psk_to_ms = 3; } } oneof variant { None none = 1; Hash hash = 2; Mac mac = 3; Cipher cipher = 4; Aead aead = 5; AsymmetricSignature asymmetric_signature = 6; AsymmetricEncryption asymmetric_encryption = 7; KeyAgreement key_agreement = 8; KeyDerivation key_derivation = 9; } } parsec-interface-0.29.1/parsec-operations/protobuf/psa_asymmetric_decrypt.proto000064400000000000000000000005571046102023000262740ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_asymmetric_decrypt; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.AsymmetricEncryption alg = 2; bytes ciphertext = 3; bytes salt = 4; } message Result { bytes plaintext = 1; }parsec-interface-0.29.1/parsec-operations/protobuf/psa_asymmetric_encrypt.proto000064400000000000000000000005571046102023000263060ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_asymmetric_encrypt; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.AsymmetricEncryption alg = 2; bytes plaintext = 3; bytes salt = 4; } message Result { bytes ciphertext = 1; }parsec-interface-0.29.1/parsec-operations/protobuf/psa_cipher_decrypt.proto000064400000000000000000000005131046102023000253610ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_cipher_decrypt; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.Cipher alg = 2; bytes ciphertext = 3; } message Result { bytes plaintext = 1; }parsec-interface-0.29.1/parsec-operations/protobuf/psa_cipher_encrypt.proto000064400000000000000000000005131046102023000253730ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_cipher_encrypt; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.Cipher alg = 2; bytes plaintext = 3; } message Result { bytes ciphertext = 1; }parsec-interface-0.29.1/parsec-operations/protobuf/psa_destroy_key.proto000064400000000000000000000003201046102023000247120ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_destroy_key; message Operation { string key_name = 1; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/psa_export_key.proto000064400000000000000000000003401046102023000245440ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_export_key; message Operation { string key_name = 1; } message Result { bytes data = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_export_public_key.proto000064400000000000000000000003471046102023000261110ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_export_public_key; message Operation { string key_name = 1; } message Result { bytes data = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_generate_key.proto000064400000000000000000000004521046102023000250210ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_generate_key; import "psa_key_attributes.proto"; message Operation { string key_name = 1; psa_key_attributes.KeyAttributes attributes = 2; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/psa_generate_random.proto000064400000000000000000000003511046102023000255070ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_generate_random; message Operation { uint64 size = 1; } message Result { bytes random_bytes = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_hash_compare.proto000064400000000000000000000004501046102023000250060ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_hash_compare; import "psa_algorithm.proto"; message Operation { psa_algorithm.Algorithm.Hash alg = 1; bytes input = 2; bytes hash = 3; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/psa_hash_compute.proto000064400000000000000000000004471046102023000250420ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_hash_compute; import "psa_algorithm.proto"; message Operation { psa_algorithm.Algorithm.Hash alg = 1; bytes input = 2; } message Result { bytes hash = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_import_key.proto000064400000000000000000000004721046102023000245430ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_import_key; import "psa_key_attributes.proto"; message Operation { string key_name = 1; psa_key_attributes.KeyAttributes attributes = 2; bytes data = 3; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/psa_key_attributes.proto000064400000000000000000000040031046102023000254110ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_key_attributes; import "psa_algorithm.proto"; message KeyAttributes { KeyType key_type = 1; uint32 key_bits = 2; KeyPolicy key_policy = 3; } message KeyType { message RawData {} message Hmac {} message Derive {} message Aes {} message Des {} message Camellia {} message Arc4 {} message Chacha20 {} message RsaPublicKey {} message RsaKeyPair {} message EccKeyPair { EccFamily curve_family = 1; } message EccPublicKey { EccFamily curve_family = 1; } message DhKeyPair { DhFamily group_family = 1; } message DhPublicKey { DhFamily group_family = 1; } enum EccFamily { ECC_FAMILY_NONE = 0; // This default variant should not be used. SECP_K1 = 1; SECP_R1 = 2; SECP_R2 = 3 [ deprecated = true ]; SECT_K1 = 4; // DEPRECATED for sect163k1 curve SECT_R1 = 5; // DEPRECATED for sect163r1 curve SECT_R2 = 6 [ deprecated = true ]; BRAINPOOL_P_R1 = 7; // DEPRECATED for brainpoolP160r1 curve FRP = 8; MONTGOMERY = 9; } enum DhFamily { RFC7919 = 0; } oneof variant { RawData raw_data = 1; // Symmetric keys Hmac hmac = 2; Derive derive = 3; Aes aes = 4; Des des = 5 [ deprecated = true ]; Camellia camellia = 6; Arc4 arc4 = 7 [ deprecated = true ]; Chacha20 chacha20 = 8; // RSA keys RsaPublicKey rsa_public_key = 9; RsaKeyPair rsa_key_pair = 10; // Elliptic Curve keys EccKeyPair ecc_key_pair = 11; EccPublicKey ecc_public_key = 12; // Finite Field Diffie Hellman keys DhKeyPair dh_key_pair = 13; DhPublicKey dh_public_key = 14; } } message KeyPolicy { UsageFlags key_usage_flags = 1; psa_algorithm.Algorithm key_algorithm = 2; } message UsageFlags { bool export = 1; bool copy = 2; bool cache = 3; bool encrypt = 4; bool decrypt = 5; bool sign_message = 6; bool verify_message = 7; bool sign_hash = 8; bool verify_hash = 9; bool derive = 10; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_mac_compute.proto000064400000000000000000000004731046102023000246560ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_mac_compute; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.Mac alg = 2; bytes input = 3; } message Result { bytes mac = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_mac_verify.proto000064400000000000000000000004731046102023000245060ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_mac_verify; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.Mac alg = 2; bytes input = 3; bytes mac = 4; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/psa_raw_key_agreement.proto000064400000000000000000000005431046102023000260500ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_raw_key_agreement; import "psa_algorithm.proto"; message Operation { psa_algorithm.Algorithm.KeyAgreement.Raw alg = 1; string private_key_name = 2; bytes peer_key = 3; } message Result { bytes shared_secret = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_sign_hash.proto000064400000000000000000000005161046102023000243230ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_sign_hash; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.AsymmetricSignature alg = 2; bytes hash = 3; } message Result { bytes signature = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_sign_message.proto000064400000000000000000000005241046102023000250230ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_sign_message; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.AsymmetricSignature alg = 2; bytes message = 3; } message Result { bytes signature = 1; } parsec-interface-0.29.1/parsec-operations/protobuf/psa_verify_hash.proto000064400000000000000000000005211046102023000246630ustar 00000000000000/* * Copyright 2019 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_verify_hash; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.AsymmetricSignature alg = 2; bytes hash = 3; bytes signature = 4; } message Result {} parsec-interface-0.29.1/parsec-operations/protobuf/psa_verify_message.proto000064400000000000000000000005271046102023000253720ustar 00000000000000/* * Copyright 2020 Contributors to the Parsec project. * SPDX-License-Identifier: Apache-2.0 */ syntax = "proto3"; package psa_verify_message; import "psa_algorithm.proto"; message Operation { string key_name = 1; psa_algorithm.Algorithm.AsymmetricSignature alg = 2; bytes message = 3; bytes signature = 4; } message Result {} parsec-interface-0.29.1/rustfmt.toml000064400000000000000000000001411046102023000155250ustar 00000000000000# The utils module has to be declared before to make its macros visible. reorder_modules = false parsec-interface-0.29.1/src/lib.rs000064400000000000000000000171021046102023000150340ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 #![deny( nonstandard_style, dead_code, improper_ctypes, non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals, path_statements, patterns_in_fns_without_body, private_in_public, unconditional_recursion, unused, unused_allocation, unused_comparisons, unused_parens, while_true, missing_debug_implementations, missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces, unused_qualifications, unused_results, missing_copy_implementations )] // This one is hard to avoid. #![allow(clippy::multiple_crate_versions)] // This crate declares deprecated values for legacy reasons. #![allow(deprecated)] //! # Parsec Rust Interface //! //! The Parsec Rust Interface provides methods to communicate easily with the Parsec service using //! the [wire protocol](https://github.com/docker/parsec/blob/master/docs/wire_protocol.md) and the //! [operation //! contracts](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/index.html). //! //! ## For the Parsec service //! //! This library is used by the Parsec service to: //! * read from a stream a `Request` sent to the service with the `read_from_stream` method //! * use the `body_to_operation` method of the `Convert` trait on a converter to parse the request //! body into a `NativeOperation` //! //!``` //!# use std::io::Read; //!# //!# pub struct MockRead { //!# pub buffer: Vec, //!# } //!# //!# impl Read for MockRead { //!# fn read(&mut self, buf: &mut [u8]) -> std::io::Result { //!# for val in buf.iter_mut() { //!# *val = self.buffer.remove(0); //!# } //!# //!# Ok(buf.len()) //!# } //!# } //!# //!# let mut stream = MockRead { //!# buffer: vec![ //!# 0x10, 0xA7, 0xC0, 0x5E, 0x1e, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, //!# 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, //!# 0x0, 0x0, 0x0, 0x0, 0x0, 0x72, 0x6F, 0x6F, 0x74 //!# ] //!# }; //!use parsec_interface::operations::{Convert, NativeOperation}; //!use parsec_interface::requests::Request; //!use parsec_interface::operations_protobuf::ProtobufConverter; //! //!let converter = ProtobufConverter {}; //!// stream is a Read object //!let request = Request::read_from_stream(&mut stream, 2048).unwrap(); //!let operation: NativeOperation = converter //! .body_to_operation(request.body, request.header.opcode) //! .unwrap(); //!``` //! //! The service can now execute the operation to yield a `NativeResult` and: //! * use the `result_to_body` method to serialize the `NativeResult` //! * create a `Response` containing the result as its body and write it back to the stream with //! the `write_to_stream` method. //! //!``` //!# use std::io::Write; //!# //!# pub struct MockWrite { //!# pub buffer: Vec, //!# } //!# //!# impl Write for MockWrite { //!# fn write(&mut self, buf: &[u8]) -> std::io::Result { //!# for val in buf.iter() { //!# self.buffer.push(*val); //!# } //!# Ok(buf.len()) //!# } //!# //!# fn flush(&mut self) -> std::io::Result<()> { //!# Ok(()) //!# } //!# } //!# let mut stream = MockWrite { buffer: Vec::new() }; //!use parsec_interface::operations::{Convert, NativeResult, psa_generate_key::Result}; //!use parsec_interface::requests::{ProviderId, Opcode, BodyType, Response, ResponseStatus}; //!use parsec_interface::requests::response::ResponseHeader; //!use parsec_interface::operations_protobuf::ProtobufConverter; //! //!let converter = ProtobufConverter {}; //!let result = NativeResult::PsaGenerateKey(Result {}); //!let result_body = converter.result_to_body(result).unwrap(); //!let response = Response { //! header: ResponseHeader { //! provider: ProviderId::MbedCrypto, //! session: 0, //! content_type: BodyType::Protobuf, //! opcode: Opcode::PsaGenerateKey, //! status: ResponseStatus::Success, //! }, //! body: result_body, //!}; //!// stream is a Write object //!response.write_to_stream(&mut stream).unwrap(); //!``` //! //! ## For the Parsec Rust clients //! //! This library is used by the Parsec Rust clients to: //! * use the `operation_to_body` method to serialize the `NativeOperation` to be sent as body of a //! `Request` //! * write it to the stream with the `write_to_stream` method. //! //!``` //!# use std::io::Write; //!# //!# pub struct MockWrite { //!# pub buffer: Vec, //!# } //!# //!# impl Write for MockWrite { //!# fn write(&mut self, buf: &[u8]) -> std::io::Result { //!# for val in buf.iter() { //!# self.buffer.push(*val); //!# } //!# Ok(buf.len()) //!# } //!# fn flush(&mut self) -> std::io::Result<()> { //!# Ok(()) //!# } //!# } //!# //!# let mut stream = MockWrite { buffer: Vec::new() }; //!use parsec_interface::operations::{Convert, NativeOperation}; //!use parsec_interface::requests::{Request, ProviderId, BodyType, AuthType, Opcode}; //!use parsec_interface::requests::request::{RequestHeader, RequestAuth}; //!use parsec_interface::operations_protobuf::ProtobufConverter; //!use parsec_interface::operations::ping::Operation; //! //!let converter = ProtobufConverter {}; //!let operation = NativeOperation::Ping(Operation {}); //!let request = Request { //! header: RequestHeader { //! provider: ProviderId::Core, //! session: 0, //! content_type: BodyType::Protobuf, //! accept_type: BodyType::Protobuf, //! auth_type: AuthType::Direct, //! opcode: Opcode::Ping, //! }, //! body: converter.operation_to_body(operation).unwrap(), //! auth: RequestAuth::new(Vec::from("root")), //!}; //!// stream is a Write object //!request.write_to_stream(&mut stream).unwrap(); //!``` //! //! After the operation has been executed by the Parsec service: //! * read from a stream the `Response` from the service with the `read_from_stream` method //! * use the `body_to_result` method to parse the result body into a `NativeResult` //! //!``` //!# use std::io::Read; //!# //!# pub struct MockRead { //!# pub buffer: Vec, //!# } //!# //!# impl Read for MockRead { //!# fn read(&mut self, buf: &mut [u8]) -> std::io::Result { //!# for val in buf.iter_mut() { //!# *val = self.buffer.remove(0); //!# } //!# //!# Ok(buf.len()) //!# } //!# } //!# //!# let mut stream = MockRead { //!# buffer: vec![ //!# 0x10, 0xA7, 0xC0, 0x5E, 0x1e, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, //!# 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, //!# 0x0, 0x0, 0x0, 0x0 //!# ] //!# }; //!use parsec_interface::operations::{Convert, NativeResult}; //!use parsec_interface::requests::Response; //!use parsec_interface::operations_protobuf::ProtobufConverter; //! //!let converter = ProtobufConverter {}; //!// stream is a Read object //!let response = Response::read_from_stream(&mut stream, 2048).unwrap(); //!let result: NativeResult = converter //! .body_to_result(response.body, response.header.opcode) //! .unwrap(); //!``` //! //! See the [Parsec Test client](https://github.com/parallaxsecond/parsec-client-test) as an example //! of a Rust client. pub mod operations; pub mod operations_protobuf; pub mod requests; /// Module providing access to secret-wrapping functionality. pub use secrecy; parsec-interface-0.29.1/src/operations/attest_key.rs000064400000000000000000000024201046102023000206220ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # AttestKey operation //! //! Produce an attestation token as proof that the given //! key was produced and is stored in the hardware backend. use derivative::Derivative; use zeroize::Zeroizing; /// Native operation for key attestation #[derive(Derivative)] #[derivative(Debug)] #[non_exhaustive] pub enum Operation { /// Attestation via TPM 2.0 ActivateCredential operation ActivateCredential { /// Name of key to be attested attested_key_name: String, /// Blob of data representing the encrypted credential #[derivative(Debug = "ignore")] credential_blob: Zeroizing>, /// Blob of data representing the encrypted secret #[derivative(Debug = "ignore")] secret: Zeroizing>, /// Name of key to be used for attesting attesting_key_name: Option, }, } /// Native result of key attestation #[derive(Derivative)] #[derivative(Debug)] #[non_exhaustive] pub enum Result { /// Result of attestation via TPM 2.0 ActivateCredential operation ActivateCredential { /// Decrypted credential #[derivative(Debug = "ignore")] credential: Zeroizing>, }, } parsec-interface-0.29.1/src/operations/can_do_crypto.rs000064400000000000000000000020761046102023000213000ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # CanDoCrypto operation //! //! Checks if the provider supports the input attributes for the operations of a given type use super::psa_key_attributes::Attributes; /// Public enum which stores the options for the types of check #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] pub enum CheckType { /// Using a specific algorithm with an existing key. Use, /// Generating a key and optionally using it for a specific algorithm. Generate, /// Importing a key and optionally using it for a specific algorithm. Import, /// Deriving a key and optionally using it for a specific algorithm (to be checked) Derive, } /// Native object for client deleting operation. #[derive(Clone, Debug, Copy)] pub struct Operation { /// The type of check required pub check_type: CheckType, /// The attributes that are to be checked pub attributes: Attributes, } /// Native object for client deleting result. #[derive(Copy, Clone, Debug)] pub struct Result; parsec-interface-0.29.1/src/operations/delete_client.rs000064400000000000000000000006501046102023000212510ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # DeleteClient operation //! //! Delete all data a client own in Parsec. /// Native object for client deleting operation. #[derive(Clone, Debug)] pub struct Operation { /// A client application name. pub client: String, } /// Native object for client deleting result. #[derive(Copy, Clone, Debug)] pub struct Result; parsec-interface-0.29.1/src/operations/list_authenticators.rs000064400000000000000000000023121046102023000225360ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # ListAuthenticators operation //! //! List the authenticators available in the service. use crate::requests::AuthType; use std::cmp::Eq; /// Structure holding the basic information that defines the authenticators in the service for /// client discovery. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct AuthenticatorInfo { /// Short description of the authenticator. pub description: String, /// Authenticator implementation version major. pub version_maj: u32, /// Authenticator implementation version minor. pub version_min: u32, /// Authenticator implementation version revision number. pub version_rev: u32, /// Authenticator ID to use on the wire protocol to communicate with this authenticator. pub id: AuthType, } /// Native object for authenticator listing operation. #[derive(Copy, Clone, Debug)] pub struct Operation; /// Native object for authenticator listing result. #[derive(Debug)] pub struct Result { /// A list of `AuthenticatorInfo` structures, one for each authenticator available in /// the service. pub authenticators: Vec, } parsec-interface-0.29.1/src/operations/list_clients.rs000064400000000000000000000006561046102023000211530ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # ListClients operation //! //! Lists all clients owning data in Parsec. /// Native object for client listing operation. #[derive(Copy, Clone, Debug)] pub struct Operation; /// Native object for client listing result. #[derive(Debug)] pub struct Result { /// A list of client application names. pub clients: Vec, } parsec-interface-0.29.1/src/operations/list_keys.rs000064400000000000000000000015101046102023000204530ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # ListKeys operation //! //! Lists all keys belonging to the application. use super::psa_key_attributes::Attributes; use crate::requests::ProviderId; /// Structure holding the basic information for a key in the application for client discovery. #[derive(Debug, Clone, PartialEq, Eq)] pub struct KeyInfo { /// The ID of the associated provider. pub provider_id: ProviderId, /// The name of the key. pub name: String, /// The key attributes. pub attributes: Attributes, } /// Native object for key listing operation. #[derive(Copy, Clone, Debug)] pub struct Operation; /// Native object for key listing result. #[derive(Debug)] pub struct Result { /// A list of `KeyInfo` structures. pub keys: Vec, } parsec-interface-0.29.1/src/operations/list_opcodes.rs000064400000000000000000000012361046102023000211410ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # ListOpcodes operation //! //! List the opcodes supported by the provider. use crate::requests::{Opcode, ProviderId}; use std::collections::HashSet; /// Native object for opcode listing operation. #[derive(Copy, Clone, Debug)] pub struct Operation { /// Provider for which the supported opcodes are requsted. pub provider_id: ProviderId, } /// Native object for opcode listing result. #[derive(Debug)] pub struct Result { /// `opcodes` holds a list of opcodes supported by the provider identified in /// the request. pub opcodes: HashSet, } parsec-interface-0.29.1/src/operations/list_providers.rs000064400000000000000000000024451046102023000215250ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # ListProviders operation //! //! List the providers available in the service, with some information. use crate::requests::ProviderId; use std::cmp::Eq; pub use uuid::Uuid; /// Structure holding the basic information that defines the providers in /// the service for client discovery. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ProviderInfo { /// Unique, permanent, identifier of the provider. pub uuid: Uuid, /// Short description of the provider. pub description: String, /// Provider vendor. pub vendor: String, /// Provider implementation version major. pub version_maj: u32, /// Provider implementation version minor. pub version_min: u32, /// Provider implementation version revision number. pub version_rev: u32, /// Provider ID to use on the wire protocol to communicate with this provider. pub id: ProviderId, } /// Native object for provider listing operation. #[derive(Copy, Clone, Debug)] pub struct Operation; /// Native object for provider listing result. #[derive(Debug)] pub struct Result { /// A list of `ProviderInfo` structures, one for each provider available in /// the service. pub providers: Vec, } parsec-interface-0.29.1/src/operations/mod.rs000064400000000000000000000522571046102023000172420ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # Rust representation of operations //! //! Rust native representation of the language neutral operations described in the //! [Operations](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/index.html) //! page in the book. //! Some of the doc comments have directly been taken from the PSA Crypto API document version //! 1.0.0. Please check that //! [document](https://developer.arm.com/architectures/security-architectures/platform-security-architecture/documentation) //! and the book for more details. pub mod ping; pub mod psa_generate_key; pub mod psa_import_key; pub mod psa_export_public_key; pub mod psa_export_key; pub mod psa_destroy_key; pub mod psa_sign_hash; pub mod psa_verify_hash; pub mod psa_hash_compute; pub mod psa_hash_compare; pub mod psa_asymmetric_encrypt; pub mod psa_asymmetric_decrypt; pub mod psa_aead_encrypt; pub mod psa_aead_decrypt; pub mod psa_cipher_encrypt; pub mod psa_cipher_decrypt; pub mod psa_sign_message; pub mod psa_verify_message; pub mod list_opcodes; pub mod list_providers; pub mod list_authenticators; pub mod list_keys; pub mod delete_client; pub mod list_clients; pub mod psa_generate_random; pub mod psa_raw_key_agreement; pub mod can_do_crypto; pub mod attest_key; pub mod prepare_key_attestation; pub mod utils_deprecated_primitives; pub use psa_crypto::types::algorithm as psa_algorithm; pub use psa_crypto::types::key as psa_key_attributes; use crate::requests::{request::RequestBody, response::ResponseBody, BodyType, Opcode, Result}; /// Container type for operation conversion values, holding a native operation object /// to be passed in/out of a converter. #[derive(Debug)] pub enum NativeOperation { /// ListProviders operation ListProviders(list_providers::Operation), /// ListOpcodes operation ListOpcodes(list_opcodes::Operation), /// ListAuthenticators operation ListAuthenticators(list_authenticators::Operation), /// ListKeys operation ListKeys(list_keys::Operation), /// ListClients operation ListClients(list_clients::Operation), /// DeleteClient operation DeleteClient(delete_client::Operation), /// Ping operation Ping(ping::Operation), /// PsaGenerateKey operation PsaGenerateKey(psa_generate_key::Operation), /// PsaImportKey operation PsaImportKey(psa_import_key::Operation), /// PsaExportPublicKey operation PsaExportPublicKey(psa_export_public_key::Operation), /// PsaExportKey operation PsaExportKey(psa_export_key::Operation), /// PsaDestroyKey operation PsaDestroyKey(psa_destroy_key::Operation), /// PsaSignHash operation PsaSignHash(psa_sign_hash::Operation), /// PsaVerifyHash operation PsaVerifyHash(psa_verify_hash::Operation), /// PsaHashCompute operation PsaHashCompute(psa_hash_compute::Operation), /// PsaHashCompare operation PsaHashCompare(psa_hash_compare::Operation), /// PsaAsymmetricEncrypt operation PsaAsymmetricEncrypt(psa_asymmetric_encrypt::Operation), /// PsaAsymmetricDecrypt operation PsaAsymmetricDecrypt(psa_asymmetric_decrypt::Operation), /// PsaAeadEncrypt operation PsaAeadEncrypt(psa_aead_encrypt::Operation), /// PsaAeadDecrypt operation PsaAeadDecrypt(psa_aead_decrypt::Operation), /// PsaCipherEncrypt operation PsaCipherEncrypt(psa_cipher_encrypt::Operation), /// PsaCipherDecrypt operation PsaCipherDecrypt(psa_cipher_decrypt::Operation), /// PsaGenerateRandom operation PsaGenerateRandom(psa_generate_random::Operation), /// PsaRawKeyAgreement operation PsaRawKeyAgreement(psa_raw_key_agreement::Operation), /// PsaSignMessage operation PsaSignMessage(psa_sign_message::Operation), /// PsaVerifyMessage operation PsaVerifyMessage(psa_verify_message::Operation), /// CanDoCrypto operation CanDoCrypto(can_do_crypto::Operation), /// AttestKey operation AttestKey(attest_key::Operation), /// PrepareKeyAttestation operation PrepareKeyAttestation(prepare_key_attestation::Operation), } impl NativeOperation { /// Return the opcode of the operation associated. pub fn opcode(&self) -> Opcode { match self { NativeOperation::Ping(_) => Opcode::Ping, NativeOperation::PsaGenerateKey(_) => Opcode::PsaGenerateKey, NativeOperation::PsaDestroyKey(_) => Opcode::PsaDestroyKey, NativeOperation::PsaSignHash(_) => Opcode::PsaSignHash, NativeOperation::PsaVerifyHash(_) => Opcode::PsaVerifyHash, NativeOperation::PsaHashCompute(_) => Opcode::PsaHashCompute, NativeOperation::PsaHashCompare(_) => Opcode::PsaHashCompare, NativeOperation::PsaImportKey(_) => Opcode::PsaImportKey, NativeOperation::PsaExportPublicKey(_) => Opcode::PsaExportPublicKey, NativeOperation::PsaExportKey(_) => Opcode::PsaExportKey, NativeOperation::ListOpcodes(_) => Opcode::ListOpcodes, NativeOperation::ListProviders(_) => Opcode::ListProviders, NativeOperation::ListAuthenticators(_) => Opcode::ListAuthenticators, NativeOperation::ListKeys(_) => Opcode::ListKeys, NativeOperation::ListClients(_) => Opcode::ListClients, NativeOperation::DeleteClient(_) => Opcode::DeleteClient, NativeOperation::PsaAsymmetricEncrypt(_) => Opcode::PsaAsymmetricEncrypt, NativeOperation::PsaAsymmetricDecrypt(_) => Opcode::PsaAsymmetricDecrypt, NativeOperation::PsaAeadEncrypt(_) => Opcode::PsaAeadEncrypt, NativeOperation::PsaAeadDecrypt(_) => Opcode::PsaAeadDecrypt, NativeOperation::PsaCipherEncrypt(_) => Opcode::PsaCipherEncrypt, NativeOperation::PsaCipherDecrypt(_) => Opcode::PsaCipherDecrypt, NativeOperation::PsaGenerateRandom(_) => Opcode::PsaGenerateRandom, NativeOperation::PsaRawKeyAgreement(_) => Opcode::PsaRawKeyAgreement, NativeOperation::PsaSignMessage(_) => Opcode::PsaSignMessage, NativeOperation::PsaVerifyMessage(_) => Opcode::PsaVerifyMessage, NativeOperation::CanDoCrypto(_) => Opcode::CanDoCrypto, NativeOperation::AttestKey(_) => Opcode::AttestKey, NativeOperation::PrepareKeyAttestation(_) => Opcode::PrepareKeyAttestation, } } } /// Container type for result conversion values, holding a native result object to be /// passed in/out of the converter. #[derive(Debug)] pub enum NativeResult { /// ListProviders result ListProviders(list_providers::Result), /// ListOpcodes result ListOpcodes(list_opcodes::Result), /// ListAuthenticators result ListAuthenticators(list_authenticators::Result), /// ListKeys result ListKeys(list_keys::Result), /// ListClients result ListClients(list_clients::Result), /// DeleteClient result DeleteClient(delete_client::Result), /// Ping result Ping(ping::Result), /// PsaGenerateKey result PsaGenerateKey(psa_generate_key::Result), /// PsaImportKey result PsaImportKey(psa_import_key::Result), /// PsaExportPublicKey result PsaExportPublicKey(psa_export_public_key::Result), /// PsaExportKey result PsaExportKey(psa_export_key::Result), /// PsaDestroyKey result PsaDestroyKey(psa_destroy_key::Result), /// PsaSignHash result PsaSignHash(psa_sign_hash::Result), /// PsaHashCompute result PsaHashCompute(psa_hash_compute::Result), /// PsaHashCompare result PsaHashCompare(psa_hash_compare::Result), /// PsaVerifyHash result PsaVerifyHash(psa_verify_hash::Result), /// PsaAsymmetricEncrypt result PsaAsymmetricEncrypt(psa_asymmetric_encrypt::Result), /// PsaAsymmetricDecrypt result PsaAsymmetricDecrypt(psa_asymmetric_decrypt::Result), /// PsaAeadEncrypt result PsaAeadEncrypt(psa_aead_encrypt::Result), /// PsaAeadDecrypt result PsaAeadDecrypt(psa_aead_decrypt::Result), /// PsaCipherEncrypt result PsaCipherEncrypt(psa_cipher_encrypt::Result), /// PsaCipherDecrypt result PsaCipherDecrypt(psa_cipher_decrypt::Result), /// PsaGenerateRandom result PsaGenerateRandom(psa_generate_random::Result), /// PsaRawKeyAgreement result PsaRawKeyAgreement(psa_raw_key_agreement::Result), /// PsaSignMessage result PsaSignMessage(psa_sign_message::Result), /// PsaVerifyMessage result PsaVerifyMessage(psa_verify_message::Result), /// CanDoCrypto result CanDoCrypto(can_do_crypto::Result), /// AttestKey result AttestKey(attest_key::Result), /// AttestKey result PrepareKeyAttestation(prepare_key_attestation::Result), } impl NativeResult { /// Return the opcode of the operation associated. pub fn opcode(&self) -> Opcode { match self { NativeResult::Ping(_) => Opcode::Ping, NativeResult::PsaGenerateKey(_) => Opcode::PsaGenerateKey, NativeResult::PsaDestroyKey(_) => Opcode::PsaDestroyKey, NativeResult::PsaSignHash(_) => Opcode::PsaSignHash, NativeResult::PsaVerifyHash(_) => Opcode::PsaVerifyHash, NativeResult::PsaImportKey(_) => Opcode::PsaImportKey, NativeResult::PsaHashCompute(_) => Opcode::PsaHashCompute, NativeResult::PsaHashCompare(_) => Opcode::PsaHashCompare, NativeResult::PsaExportPublicKey(_) => Opcode::PsaExportPublicKey, NativeResult::PsaExportKey(_) => Opcode::PsaExportKey, NativeResult::ListOpcodes(_) => Opcode::ListOpcodes, NativeResult::ListProviders(_) => Opcode::ListProviders, NativeResult::ListAuthenticators(_) => Opcode::ListAuthenticators, NativeResult::ListKeys(_) => Opcode::ListKeys, NativeResult::ListClients(_) => Opcode::ListClients, NativeResult::DeleteClient(_) => Opcode::DeleteClient, NativeResult::PsaAsymmetricEncrypt(_) => Opcode::PsaAsymmetricEncrypt, NativeResult::PsaAsymmetricDecrypt(_) => Opcode::PsaAsymmetricDecrypt, NativeResult::PsaAeadEncrypt(_) => Opcode::PsaAeadEncrypt, NativeResult::PsaAeadDecrypt(_) => Opcode::PsaAeadDecrypt, NativeResult::PsaCipherEncrypt(_) => Opcode::PsaCipherEncrypt, NativeResult::PsaCipherDecrypt(_) => Opcode::PsaCipherDecrypt, NativeResult::PsaGenerateRandom(_) => Opcode::PsaGenerateRandom, NativeResult::PsaRawKeyAgreement(_) => Opcode::PsaRawKeyAgreement, NativeResult::PsaSignMessage(_) => Opcode::PsaSignMessage, NativeResult::PsaVerifyMessage(_) => Opcode::PsaVerifyMessage, NativeResult::CanDoCrypto(_) => Opcode::CanDoCrypto, NativeResult::AttestKey(_) => Opcode::AttestKey, NativeResult::PrepareKeyAttestation(_) => Opcode::PrepareKeyAttestation, } } } /// Definition of the operations converters must implement to allow usage of a specific /// `BodyType`. pub trait Convert { /// Get the `BodyType` associated with this converter. fn body_type(&self) -> BodyType; /// Create a native operation object from a request body. /// /// # Errors /// - if deserialization fails, `ResponseStatus::DeserializingBodyFailed` is returned fn body_to_operation(&self, body: RequestBody, opcode: Opcode) -> Result; /// Create a request body from a native operation object. /// /// # Errors /// - if serialization fails, `ResponseStatus::SerializingBodyFailed` is returned fn operation_to_body(&self, operation: NativeOperation) -> Result; /// Create a native result object from a response body. /// /// # Errors /// - if deserialization fails, `ResponseStatus::DeserializingBodyFailed` is returned fn body_to_result(&self, body: ResponseBody, opcode: Opcode) -> Result; /// Create a response body from a native result object. /// /// # Errors /// - if serialization fails, `ResponseStatus::SerializingBodyFailed` is returned fn result_to_body(&self, result: NativeResult) -> Result; } impl From for NativeOperation { fn from(op: list_providers::Operation) -> Self { NativeOperation::ListProviders(op) } } impl From for NativeOperation { fn from(op: list_opcodes::Operation) -> Self { NativeOperation::ListOpcodes(op) } } impl From for NativeOperation { fn from(op: list_authenticators::Operation) -> Self { NativeOperation::ListAuthenticators(op) } } impl From for NativeOperation { fn from(op: list_keys::Operation) -> Self { NativeOperation::ListKeys(op) } } impl From for NativeOperation { fn from(op: list_clients::Operation) -> Self { NativeOperation::ListClients(op) } } impl From for NativeOperation { fn from(op: delete_client::Operation) -> Self { NativeOperation::DeleteClient(op) } } impl From for NativeOperation { fn from(op: ping::Operation) -> Self { NativeOperation::Ping(op) } } impl From for NativeOperation { fn from(op: psa_generate_key::Operation) -> Self { NativeOperation::PsaGenerateKey(op) } } impl From for NativeOperation { fn from(op: psa_import_key::Operation) -> Self { NativeOperation::PsaImportKey(op) } } impl From for NativeOperation { fn from(op: psa_export_public_key::Operation) -> Self { NativeOperation::PsaExportPublicKey(op) } } impl From for NativeOperation { fn from(op: psa_export_key::Operation) -> Self { NativeOperation::PsaExportKey(op) } } impl From for NativeOperation { fn from(op: psa_destroy_key::Operation) -> Self { NativeOperation::PsaDestroyKey(op) } } impl From for NativeOperation { fn from(op: psa_sign_hash::Operation) -> Self { NativeOperation::PsaSignHash(op) } } impl From for NativeOperation { fn from(op: psa_verify_hash::Operation) -> Self { NativeOperation::PsaVerifyHash(op) } } impl From for NativeOperation { fn from(op: psa_asymmetric_encrypt::Operation) -> Self { NativeOperation::PsaAsymmetricEncrypt(op) } } impl From for NativeOperation { fn from(op: psa_asymmetric_decrypt::Operation) -> Self { NativeOperation::PsaAsymmetricDecrypt(op) } } impl From for NativeOperation { fn from(op: psa_aead_encrypt::Operation) -> Self { NativeOperation::PsaAeadEncrypt(op) } } impl From for NativeOperation { fn from(op: psa_aead_decrypt::Operation) -> Self { NativeOperation::PsaAeadDecrypt(op) } } impl From for NativeOperation { fn from(op: psa_cipher_encrypt::Operation) -> Self { NativeOperation::PsaCipherEncrypt(op) } } impl From for NativeOperation { fn from(op: psa_cipher_decrypt::Operation) -> Self { NativeOperation::PsaCipherDecrypt(op) } } impl From for NativeOperation { fn from(op: psa_generate_random::Operation) -> Self { NativeOperation::PsaGenerateRandom(op) } } impl From for NativeOperation { fn from(op: psa_hash_compute::Operation) -> Self { NativeOperation::PsaHashCompute(op) } } impl From for NativeOperation { fn from(op: psa_hash_compare::Operation) -> Self { NativeOperation::PsaHashCompare(op) } } impl From for NativeOperation { fn from(op: psa_raw_key_agreement::Operation) -> Self { NativeOperation::PsaRawKeyAgreement(op) } } impl From for NativeOperation { fn from(op: psa_sign_message::Operation) -> Self { NativeOperation::PsaSignMessage(op) } } impl From for NativeOperation { fn from(op: psa_verify_message::Operation) -> Self { NativeOperation::PsaVerifyMessage(op) } } impl From for NativeOperation { fn from(op: can_do_crypto::Operation) -> Self { NativeOperation::CanDoCrypto(op) } } impl From for NativeOperation { fn from(op: attest_key::Operation) -> Self { NativeOperation::AttestKey(op) } } impl From for NativeOperation { fn from(op: prepare_key_attestation::Operation) -> Self { NativeOperation::PrepareKeyAttestation(op) } } impl From for NativeResult { fn from(op: list_providers::Result) -> Self { NativeResult::ListProviders(op) } } impl From for NativeResult { fn from(op: list_opcodes::Result) -> Self { NativeResult::ListOpcodes(op) } } impl From for NativeResult { fn from(op: list_authenticators::Result) -> Self { NativeResult::ListAuthenticators(op) } } impl From for NativeResult { fn from(op: list_keys::Result) -> Self { NativeResult::ListKeys(op) } } impl From for NativeResult { fn from(op: list_clients::Result) -> Self { NativeResult::ListClients(op) } } impl From for NativeResult { fn from(op: delete_client::Result) -> Self { NativeResult::DeleteClient(op) } } impl From for NativeResult { fn from(op: ping::Result) -> Self { NativeResult::Ping(op) } } impl From for NativeResult { fn from(op: psa_generate_key::Result) -> Self { NativeResult::PsaGenerateKey(op) } } impl From for NativeResult { fn from(op: psa_import_key::Result) -> Self { NativeResult::PsaImportKey(op) } } impl From for NativeResult { fn from(op: psa_export_public_key::Result) -> Self { NativeResult::PsaExportPublicKey(op) } } impl From for NativeResult { fn from(op: psa_export_key::Result) -> Self { NativeResult::PsaExportKey(op) } } impl From for NativeResult { fn from(op: psa_destroy_key::Result) -> Self { NativeResult::PsaDestroyKey(op) } } impl From for NativeResult { fn from(op: psa_sign_hash::Result) -> Self { NativeResult::PsaSignHash(op) } } impl From for NativeResult { fn from(op: psa_verify_hash::Result) -> Self { NativeResult::PsaVerifyHash(op) } } impl From for NativeResult { fn from(op: psa_hash_compute::Result) -> Self { NativeResult::PsaHashCompute(op) } } impl From for NativeResult { fn from(op: psa_hash_compare::Result) -> Self { NativeResult::PsaHashCompare(op) } } impl From for NativeResult { fn from(op: psa_asymmetric_encrypt::Result) -> Self { NativeResult::PsaAsymmetricEncrypt(op) } } impl From for NativeResult { fn from(op: psa_asymmetric_decrypt::Result) -> Self { NativeResult::PsaAsymmetricDecrypt(op) } } impl From for NativeResult { fn from(op: psa_aead_encrypt::Result) -> Self { NativeResult::PsaAeadEncrypt(op) } } impl From for NativeResult { fn from(op: psa_aead_decrypt::Result) -> Self { NativeResult::PsaAeadDecrypt(op) } } impl From for NativeResult { fn from(op: psa_cipher_encrypt::Result) -> Self { NativeResult::PsaCipherEncrypt(op) } } impl From for NativeResult { fn from(op: psa_cipher_decrypt::Result) -> Self { NativeResult::PsaCipherDecrypt(op) } } impl From for NativeResult { fn from(op: psa_generate_random::Result) -> Self { NativeResult::PsaGenerateRandom(op) } } impl From for NativeResult { fn from(op: psa_raw_key_agreement::Result) -> Self { NativeResult::PsaRawKeyAgreement(op) } } impl From for NativeResult { fn from(op: psa_sign_message::Result) -> Self { NativeResult::PsaSignMessage(op) } } impl From for NativeResult { fn from(op: psa_verify_message::Result) -> Self { NativeResult::PsaVerifyMessage(op) } } impl From for NativeResult { fn from(op: can_do_crypto::Result) -> Self { NativeResult::CanDoCrypto(op) } } impl From for NativeResult { fn from(op: attest_key::Result) -> Self { NativeResult::AttestKey(op) } } impl From for NativeResult { fn from(op: prepare_key_attestation::Result) -> Self { NativeResult::PrepareKeyAttestation(op) } } parsec-interface-0.29.1/src/operations/ping.rs000064400000000000000000000014141046102023000174050ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # Ping operation //! //! The Ping operation is used to check if the service is alive and determine the highest wire //! protocol version a client can use. /// Native object for Ping operation. #[derive(Copy, Clone, Debug)] pub struct Operation; /// Native object for Ping result. /// /// The latest wire protocol version supported by the service. The version is represented as `x.y` /// where `x` is the version major and `y` the version minor. #[derive(Copy, Clone, Debug)] pub struct Result { /// Supported latest wire protocol version major pub wire_protocol_version_maj: u8, /// Supported latest wire protocol version minor pub wire_protocol_version_min: u8, } parsec-interface-0.29.1/src/operations/prepare_key_attestation.rs000064400000000000000000000023451046102023000234010ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PrepareKeyAttestation operation //! //! Produce any parameters required for the AttestKey operation use derivative::Derivative; use zeroize::Zeroizing; /// Native operation for retrieving key attestation parameters #[derive(Debug)] #[non_exhaustive] pub enum Operation { /// Get parameters for TPM 2.0 ActivateCredential operation ActivateCredential { /// Name of key to be attested attested_key_name: String, /// Name of key to be used for attesting attesting_key_name: Option, }, } /// Native result of retrieving key attestation parameters #[derive(Derivative)] #[derivative(Debug)] #[non_exhaustive] pub enum Result { /// Parameters for TPM 2.0 ActivateCredential operation ActivateCredential { /// TPM name of key to be attested #[derivative(Debug = "ignore")] name: Zeroizing>, /// TPM public key parameters of object to be attested #[derivative(Debug = "ignore")] public: Zeroizing>, /// Public part of attesting key #[derivative(Debug = "ignore")] attesting_key_pub: Zeroizing>, }, } parsec-interface-0.29.1/src/operations/psa_aead_decrypt.rs000064400000000000000000000126101046102023000217370ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaAeadDecrypt operation //! //! Process an authenticated decryption operation. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::Aead; use crate::requests::ResponseStatus; use derivative::Derivative; /// Native object for AEAD decryption operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// Defines which key should be used for the decryption operation. pub key_name: String, /// An AEAD encryption algorithm that is compatible with the key type. pub alg: Aead, /// Nonce or IV to use. #[derivative(Debug = "ignore")] pub nonce: zeroize::Zeroizing>, /// Additional data that has been authenticated but not encrypted. #[derivative(Debug = "ignore")] pub additional_data: zeroize::Zeroizing>, /// Data that has been authenticated and encrypted. For algorithms where the encrypted data and /// the authentication tag are defined as separate inputs, the buffer must contain the encrypted /// data followed by the authentication tag. #[derivative(Debug = "ignore")] pub ciphertext: zeroize::Zeroizing>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows decrypting messages /// * the key policy allows the encryption algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * the message to decrypt is valid (not length 0) /// * the nonce is valid (not length 0) pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_decrypt_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if self.ciphertext.is_empty() || self.nonce.is_empty() { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } /// Native object for AEAD decrypt result. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// The `plaintext` field contains the authenticated and decrypted data. #[derivative(Debug = "ignore")] pub plaintext: zeroize::Zeroizing>, } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::AeadWithDefaultLengthTag; use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags}; use psa_crypto::types::algorithm::Aead; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_decrypt(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::Aes, bits: 0, policy: Policy { usage_flags, permitted_algorithms: Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm) .into(), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), ciphertext: vec![0xff, 32].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_decrypt() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), ciphertext: vec![0xff, 32].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into() }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Gcm.into(), ciphertext: vec![0xff, 32].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into() }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_plaintext() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), ciphertext: vec![].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into() }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } #[test] fn invalid_nonce() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), ciphertext: vec![0xff, 32].into(), nonce: vec![].into(), additional_data: vec![0xff, 16].into() }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_aead_encrypt.rs000064400000000000000000000125531046102023000217570ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaAeadEncrypt operation //! //! Process an authenticated encryption operation. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::Aead; use crate::requests::ResponseStatus; use derivative::Derivative; /// Native object for AEAD encryption operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// Defines which key should be used for the encryption operation. pub key_name: String, /// An AEAD encryption algorithm that is compatible with the key type. pub alg: Aead, /// Nonce or IV to use. #[derivative(Debug = "ignore")] pub nonce: zeroize::Zeroizing>, /// Additional data that will be authenticated but not encrypted. #[derivative(Debug = "ignore")] pub additional_data: zeroize::Zeroizing>, /// Data that will be authenticated and encrypted. #[derivative(Debug = "ignore")] pub plaintext: zeroize::Zeroizing>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows encrypting messages /// * the key policy allows the encryption algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * the message to encrypt is valid (not length 0) /// * the nonce is valid (not length 0) pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_encrypt_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if self.plaintext.is_empty() || self.nonce.is_empty() { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } /// Native object for AEAD encrypt result. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// The `ciphertext` field contains the encrypted and authenticated data.For algorithms where /// the encrypted data and the authentication tag are defined as separate outputs, the authentication /// tag is appended to the encrypted data. #[derivative(Debug = "ignore")] pub ciphertext: zeroize::Zeroizing>, } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::AeadWithDefaultLengthTag; use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags}; use psa_crypto::types::algorithm::Aead; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_encrypt(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::Aes, bits: 0, policy: Policy { usage_flags, permitted_algorithms: Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm) .into(), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), plaintext: vec![0xff, 32].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_encrypt() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), plaintext: vec![0xff, 32].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into() }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Gcm.into(), plaintext: vec![0xff, 32].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into() }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_plaintext() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), plaintext: vec![].into(), nonce: vec![0xaa, 12].into(), additional_data: vec![0xff, 16].into() }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } #[test] fn invalid_nonce() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AeadWithDefaultLengthTag::Ccm.into(), plaintext: vec![0xff, 32].into(), nonce: vec![].into(), additional_data: vec![0xff, 16].into() }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_asymmetric_decrypt.rs000064400000000000000000000122101046102023000232160ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaAsymmetricDecrypt operation //! //! Decrypt a short message with a public key. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::AsymmetricEncryption; use crate::requests::ResponseStatus; use derivative::Derivative; /// Native object for asymmetric decryption operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// Defines which key should be used for the signing operation. pub key_name: String, /// An asymmetric encryption algorithm to be used for decryption, that is compatible with the type of key. pub alg: AsymmetricEncryption, /// The short encrypted message to be decrypted. #[derivative(Debug = "ignore")] pub ciphertext: zeroize::Zeroizing>, /// Salt to use during decryption, if supported by the algorithm. #[derivative(Debug = "ignore")] pub salt: Option>>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows decrypting messages /// * the key policy allows the decryption algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * if the algorithm is RsaPkcs1v15Crypt, it has no salt (it is not compatible with salt) /// * the message to decrypt is valid (not length 0) pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_decrypt_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if (self.alg == AsymmetricEncryption::RsaPkcs1v15Crypt && self.salt.is_some()) || self.ciphertext.is_empty() { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } /// Native object for asymmetric decrypt result. // Debug derived as NativeResult enum requires it, even though nothing inside this Result is debuggable // as `plaintext` is sensitive. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// Decrypted message #[derivative(Debug = "ignore")] pub plaintext: zeroize::Zeroizing>, } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{AsymmetricEncryption, Hash}; use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags}; use zeroize::Zeroizing; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_decrypt(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 256, policy: Policy { usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, ciphertext: Zeroizing::new(vec![0xff, 32]), salt: None, }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_decrypt() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, ciphertext: Zeroizing::new(vec![0xff, 32]), salt: None, }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaOaep { hash_alg: Hash::Sha256, }, ciphertext: Zeroizing::new(vec![0xff, 32]), salt: None, }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_ciphertext() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, ciphertext: Zeroizing::new(vec![]), salt: None, }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } #[test] fn salt_with_rsapkcs1v15crypt() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, ciphertext: Zeroizing::new(vec![0xff, 32]), salt: Some(zeroize::Zeroizing::new(vec![0xff, 32])), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_asymmetric_encrypt.rs000064400000000000000000000116651046102023000232450ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaAsymmetricEncrypt operation //! //! Encrypt a short message with a public key. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::AsymmetricEncryption; use crate::requests::ResponseStatus; use derivative::Derivative; /// Native object for asymmetric encryption operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// Defines which key should be used for the encryption operation. pub key_name: String, /// An asymmetric encryption algorithm that is compatible with the key type pub alg: AsymmetricEncryption, /// The short message to be encrypted. #[derivative(Debug = "ignore")] pub plaintext: zeroize::Zeroizing>, /// Salt to use during encryption, if supported by the algorithm. #[derivative(Debug = "ignore")] pub salt: Option>>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows encrypting messages /// * the key policy allows the encryption algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * if the algorithm is RsaPkcs1v15Crypt, it has no salt (it is not compatible with salt) /// * the message to encrypt is valid (not length 0) pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_encrypt_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if (self.alg == AsymmetricEncryption::RsaPkcs1v15Crypt && self.salt.is_some()) || self.plaintext.is_empty() { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } /// Native object for asymmetric encrypt result. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// The `ciphertext` field contains the encrypted short message. #[derivative(Debug = "ignore")] pub ciphertext: zeroize::Zeroizing>, } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{AsymmetricEncryption, Hash}; use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags}; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_encrypt(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::RsaKeyPair, bits: 256, policy: Policy { usage_flags, permitted_algorithms: AsymmetricEncryption::RsaPkcs1v15Crypt.into(), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, plaintext: vec![0xff, 32].into(), salt: None, }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_encrypt() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, plaintext: vec![0xff, 32].into(), salt: None, }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaOaep { hash_alg: Hash::Sha256, }, plaintext: vec![0xff, 32].into(), salt: None, }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_plaintext() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, plaintext: vec![].into(), salt: None, }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } #[test] fn salt_with_rsapkcs1v15crypt() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, plaintext: vec![0xff, 32].into(), salt: Some(zeroize::Zeroizing::new(vec![0xff, 32])), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_cipher_decrypt.rs000064400000000000000000000076761046102023000223370ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaCipherDecrypt operation //! //! Decrypt a short message with a symmetric cipher use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::Cipher; use crate::requests::ResponseStatus; use derivative::Derivative; /// Native object for cipher decryption operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// Defines which key should be used for the decryption operation. pub key_name: String, /// An cipher encryption algorithm to be used for decryption, that is compatible with the type of key. pub alg: Cipher, /// The short encrypted message to be decrypted. #[derivative(Debug = "ignore")] pub ciphertext: zeroize::Zeroizing>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows decrypting messages /// * the key policy allows the decryption algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * the message to decrypt is valid (not length 0) pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_decrypt_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if self.ciphertext.is_empty() { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } /// Native object for cipher decrypt result. // Debug derived as NativeResult enum requires it, even though nothing inside this Result is debuggable // as `plaintext` is sensitive. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// Decrypted message #[derivative(Debug = "ignore")] pub plaintext: zeroize::Zeroizing>, } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::Cipher; use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags}; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_decrypt(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::Arc4, bits: 256, policy: Policy { usage_flags, permitted_algorithms: Cipher::StreamCipher.into(), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: Cipher::StreamCipher, ciphertext: vec![0xff, 32].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_decrypt() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: Cipher::StreamCipher, ciphertext: vec![0xff, 32].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: Cipher::Cfb, ciphertext: vec![0xff, 32].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_ciphertext() { assert_eq!( (Operation { key_name: String::from("some key"), alg: Cipher::StreamCipher, ciphertext: vec![].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_cipher_encrypt.rs000064400000000000000000000074621046102023000223420ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaCipherEncrypt operation //! //! Encrypt a short message with a symmetric cipher use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::Cipher; use crate::requests::ResponseStatus; use derivative::Derivative; /// Native object for cipher encryption operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// Defines which key should be used for the encryption operation. pub key_name: String, /// An cipher encryption algorithm that is compatible with the key type pub alg: Cipher, /// The short message to be encrypted. #[derivative(Debug = "ignore")] pub plaintext: zeroize::Zeroizing>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows encrypting messages /// * the key policy allows the encryption algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * the message to encrypt is valid (not length 0) pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_encrypt_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if self.plaintext.is_empty() { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } /// Native object for cipher encrypt result. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// The `ciphertext` field contains the encrypted short message. #[derivative(Debug = "ignore")] pub ciphertext: zeroize::Zeroizing>, } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::Cipher; use crate::operations::psa_key_attributes::{Lifetime, Policy, Type, UsageFlags}; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_encrypt(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::Arc4, bits: 256, policy: Policy { usage_flags, permitted_algorithms: Cipher::StreamCipher.into(), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: Cipher::StreamCipher, plaintext: vec![0xff, 32].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_encrypt() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: Cipher::StreamCipher, plaintext: vec![0xff, 32].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: Cipher::Cfb, plaintext: vec![0xff, 32].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_plaintext() { assert_eq!( (Operation { key_name: String::from("some key"), alg: Cipher::StreamCipher, plaintext: vec![].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_destroy_key.rs000064400000000000000000000010021046102023000216450ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaDestroyKey operation //! //! Destroy a key. /// Native object for cryptographic key destruction. #[derive(Debug, Clone)] pub struct Operation { /// `key_name` identifies the key to be destroyed. pub key_name: String, } /// Native object for result of cryptographic key destruction. /// /// True result of operation is returned in the response `status`. #[derive(Copy, Clone, Debug)] pub struct Result; parsec-interface-0.29.1/src/operations/psa_export_key.rs000064400000000000000000000014271046102023000215100ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaExportKey operation //! //! Export a key in binary format. See the book for the format description. use derivative::Derivative; /// Native object for key exporting operation. #[derive(Debug)] pub struct Operation { /// `key_name` identifies the key that will be exported. pub key_name: String, } /// Native object for result of key export operation. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// `data` holds the bytes defining the key, formatted as specified /// by the provider for which the request was made. #[derivative(Debug = "ignore")] // Don't output at debug - potentially contains private key pub data: secrecy::Secret>, } parsec-interface-0.29.1/src/operations/psa_export_public_key.rs000064400000000000000000000013551046102023000230460ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaExportPublicKey operation //! //! Export a key in binary format. See the book for the format description. /// Native object for public key exporting operation. #[derive(Debug)] pub struct Operation { /// `key_name` identifies the key for which the public /// part will be exported. The specified key must be an asymmetric keypair. pub key_name: String, } /// Native object for result of public key export operation. #[derive(Debug)] pub struct Result { /// `data` holds the bytes defining the public key, formatted as specified /// by the provider for which the request was made. pub data: zeroize::Zeroizing>, } parsec-interface-0.29.1/src/operations/psa_generate_key.rs000064400000000000000000000013731046102023000217610ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaGenerateKey operation //! //! Generate a key or a key pair. use super::psa_key_attributes::Attributes; /// Native object for creating a cryptographic key. #[derive(Clone, Debug)] pub struct Operation { /// `key_name` specifies a name by which the service will identify the key. Key /// name must be unique per application. pub key_name: String, /// `attributes` specifies the parameters to be associated with the key. pub attributes: Attributes, } /// Native object for the result of creating a cryptographic key. /// /// The true result is returned in the `status` field of the response. #[derive(Copy, Clone, Debug)] pub struct Result; parsec-interface-0.29.1/src/operations/psa_generate_random.rs000064400000000000000000000011171046102023000224450ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaGenerateRandom operation //! //! Generate random bytes. use derivative::Derivative; /// Native object for creating a cryptographic key. #[derive(Copy, Clone, Debug)] pub struct Operation { /// `size` specifies how many random bytes to fetch. pub size: usize, } /// Native object for random bytes result. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// Random bytes. #[derivative(Debug = "ignore")] pub random_bytes: zeroize::Zeroizing>, } parsec-interface-0.29.1/src/operations/psa_hash_compare.rs000064400000000000000000000014101046102023000217400ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaHashCompare operation //! //! Compute the hash value of a message and compare it with a reference value. use crate::operations::psa_algorithm::Hash; use derivative::Derivative; /// Native object for hash compare operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// The hash algorithm to compute. pub alg: Hash, /// The input to hash. #[derivative(Debug = "ignore")] pub input: zeroize::Zeroizing>, /// The reference hash value. #[derivative(Debug = "ignore")] pub hash: zeroize::Zeroizing>, } /// Native object for hash compare result. #[derive(Debug, Default, Copy, Clone)] pub struct Result; parsec-interface-0.29.1/src/operations/psa_hash_compute.rs000064400000000000000000000014021046102023000217670ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaHashCompute operation //! //! Compute the hash value of a message. use crate::operations::psa_algorithm::Hash; use derivative::Derivative; /// Native object for hash compute operations. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// The hash algorithm to compute. pub alg: Hash, /// The input to hash. #[derivative(Debug = "ignore")] pub input: zeroize::Zeroizing>, } /// Native object for hash compute result. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// The `hash` field contains the hash of the message. #[derivative(Debug = "ignore")] pub hash: zeroize::Zeroizing>, } parsec-interface-0.29.1/src/operations/psa_import_key.rs000064400000000000000000000022261046102023000214770ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaImportKey operation //! //! Import a key in binary format. use super::psa_key_attributes::Attributes; use derivative::Derivative; /// Native object for cryptographic key importing operation. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// `key_name` specifies a name by which the service will identify the key. Key /// name must be unique per application. pub key_name: String, /// `attributes` specifies the attributes for the new key. pub attributes: Attributes, /// `data` contains the bytes for the key, /// formatted in accordance with the requirements of the provider for the key type /// specified in `attributes`. // Debug is not derived for this because it could expose secrets if printed or logged // somewhere #[derivative(Debug = "ignore")] pub data: crate::secrecy::Secret>, } /// Native object for the result of a cryptographic key import operation. /// /// The true result is sent in the `status` field of the response header. #[derive(Copy, Clone, Debug)] pub struct Result; parsec-interface-0.29.1/src/operations/psa_raw_key_agreement.rs000064400000000000000000000073651046102023000230160ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaRawKeyAgreement operation //! //! Perform a raw key agreement. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::{KeyAgreement, RawKeyAgreement}; use derivative::Derivative; /// Native object for raw key agreement operation. #[derive(Derivative)] #[derivative(Debug)] pub struct Operation { /// `alg` specifies the raw key agreement algorithm to use. It must allow the `derive` usage flag. pub alg: RawKeyAgreement, /// `private_key_name` specifies a name of the private key to use in the key agreement operation. pub private_key_name: String, /// `peer_key` contains the bytes of a peers public key, to be used in the key agreement operation. /// This must be in the format that `PsaImportKey` accepts. #[derivative(Debug = "ignore")] pub peer_key: zeroize::Zeroizing>, } /// Native object for result for raw key agreement operation. #[derive(Derivative)] #[derivative(Debug)] pub struct Result { /// `data` holds the bytes defining the key, formatted as specified /// by the provider for which the request was made. #[derivative(Debug = "ignore")] pub shared_secret: crate::secrecy::Secret>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows derivation /// * the key policy allows the key agreement algorithm requested in the operation /// * the key type is compatible with the requested algorithm pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_derive_from()?; key_attributes.permits_alg(KeyAgreement::Raw(self.alg).into())?; key_attributes.compatible_with_alg(KeyAgreement::Raw(self.alg).into())?; Ok(()) } } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{KeyAgreement, RawKeyAgreement}; use crate::operations::psa_key_attributes::{EccFamily, Lifetime, Policy, Type, UsageFlags}; use crate::requests::ResponseStatus; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_derive(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, }, bits: 256, policy: Policy { usage_flags, permitted_algorithms: KeyAgreement::Raw(RawKeyAgreement::Ecdh).into(), }, } } #[test] fn validate_success() { (Operation { private_key_name: String::from("some key"), alg: RawKeyAgreement::Ecdh, peer_key: vec![0xff, 32].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_derive() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { private_key_name: String::from("some key"), alg: RawKeyAgreement::Ecdh, peer_key: vec![0xff, 32].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { private_key_name: String::from("some key"), alg: RawKeyAgreement::Ffdh, peer_key: vec![0xff, 32].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } } parsec-interface-0.29.1/src/operations/psa_sign_hash.rs000064400000000000000000000115431046102023000212620ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaSignHash operation //! //! Sign an already-calculated hash with a private key. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::AsymmetricSignature; use crate::requests::ResponseStatus; /// Native object for asymmetric sign operations. #[derive(Debug)] pub struct Operation { /// Defines which key should be used for the signing operation. pub key_name: String, /// An asymmetric signature algorithm that separates the hash and sign operations, that is /// compatible with the type of key. pub alg: AsymmetricSignature, /// The input whose signature is to be verified. This is usually the hash of a message. pub hash: zeroize::Zeroizing>, } /// Native object for asymmetric sign result. #[derive(Debug)] pub struct Result { /// The `signature` field contains the resulting bytes from the signing operation. The format of /// the signature is as specified by the provider doing the signing. pub signature: zeroize::Zeroizing>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows signing hashes /// * the key policy allows the signing algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * the length of the given digest is consistent with the specified signing algorithm pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_sign_hash()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if !self.alg.is_hash_len_permitted(self.hash.len()) { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{EccFamily, Lifetime, Policy, Type, UsageFlags}; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_sign_hash(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, }, bits: 256, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, hash: vec![0xff; 32].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_sign() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, hash: vec![0xff; 32].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha224.into(), }, hash: vec![0xff; 28].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_scheme() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::RsaPss { hash_alg: Hash::Sha224.into(), }, hash: vec![0xff; 28].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_hash() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, hash: vec![0xff; 16].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_sign_message.rs000064400000000000000000000102131046102023000217540ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaSignMessage operation //! //! Sign a message with a private key. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::AsymmetricSignature; /// Native object for asymmetric sign operations. #[derive(Debug)] pub struct Operation { /// Defines which key should be used for the signing operation. pub key_name: String, /// An asymmetric signature algorithm that separates the hash and sign operations, that is /// compatible with the type of key. pub alg: AsymmetricSignature, /// The message to sign. pub message: zeroize::Zeroizing>, } /// Native object for asymmetric sign result. #[derive(Debug)] pub struct Result { /// The `signature` field contains the resulting bytes from the signing operation. The format of /// the signature is as specified by the provider doing the signing. pub signature: zeroize::Zeroizing>, } impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows signing messages /// * the key policy allows the signing algorithm requested in the operation /// * the key type is compatible with the requested algorithm pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_sign_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; Ok(()) } } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{EccFamily, Lifetime, Policy, Type, UsageFlags}; use crate::requests::ResponseStatus; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_sign_hash(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, }, bits: 256, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, message: vec![0xff; 32].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_sign() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, message: vec![0xff; 32].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha224.into(), }, message: vec![0xff; 28].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_scheme() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::RsaPss { hash_alg: Hash::Sha224.into(), }, message: vec![0xff; 28].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } } parsec-interface-0.29.1/src/operations/psa_verify_hash.rs000064400000000000000000000122341046102023000216240ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaVerifyHash operation //! //! Verify the signature of a hash or short message using a public key. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::AsymmetricSignature; use crate::requests::ResponseStatus; /// Native object for asymmetric verification of signatures. #[derive(Debug)] pub struct Operation { /// `key_name` specifies the key to be used for verification. pub key_name: String, /// An asymmetric signature algorithm that separates the hash and sign operations, that is /// compatible with the type of key. pub alg: AsymmetricSignature, /// The `hash` contains a short message or hash value as described for the /// asymmetric signing operation. pub hash: zeroize::Zeroizing>, /// Buffer containing the signature to verify. pub signature: zeroize::Zeroizing>, } /// Native object for asymmetric verification of signatures. /// /// The true result of the operation is sent as a `status` code in the response. #[derive(Copy, Clone, Debug)] pub struct Result; impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows verifying signatures on hashes /// * the key policy allows the verification algorithm requested in the operation /// * the key type is compatible with the requested algorithm /// * the length of the given digest is consistent with the specified verification algorithm pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_verify_hash()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; if !self.alg.is_hash_len_permitted(self.hash.len()) { return Err(ResponseStatus::PsaErrorInvalidArgument); } Ok(()) } } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{EccFamily, Lifetime, Policy, Type, UsageFlags}; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_verify_hash(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, }, bits: 256, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, hash: vec![0xff; 32].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_sign() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, hash: vec![0xff; 32].into(), signature: vec![0xa5; 65].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha224.into(), }, hash: vec![0xff; 28].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_scheme() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::RsaPss { hash_alg: Hash::Sha224.into(), }, hash: vec![0xff; 28].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn invalid_hash() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, hash: vec![0xff; 16].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorInvalidArgument ); } } parsec-interface-0.29.1/src/operations/psa_verify_message.rs000064400000000000000000000107011046102023000223220ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # PsaVerifyMessage operation //! //! Verify the signature of a message using a public key. use super::psa_key_attributes::Attributes; use crate::operations::psa_algorithm::AsymmetricSignature; /// Native object for asymmetric verification of signatures. #[derive(Debug)] pub struct Operation { /// `key_name` specifies the key to be used for verification. pub key_name: String, /// An asymmetric signature algorithm that separates the hash and sign operations, that is /// compatible with the type of key. pub alg: AsymmetricSignature, /// The `message` whose signature is to be verified for the /// asymmetric signing operation. pub message: zeroize::Zeroizing>, /// Buffer containing the signature to verify. pub signature: zeroize::Zeroizing>, } /// Native object for asymmetric verification of signatures. /// /// The true result of the operation is sent as a `status` code in the response. #[derive(Copy, Clone, Debug)] pub struct Result; impl Operation { /// Validate the contents of the operation against the attributes of the key it targets /// /// This method checks that: /// * the key policy allows verifying signatures on messages /// * the key policy allows the verification algorithm requested in the operation /// * the key type is compatible with the requested algorithm pub fn validate(&self, key_attributes: Attributes) -> crate::requests::Result<()> { key_attributes.can_verify_message()?; key_attributes.permits_alg(self.alg.into())?; key_attributes.compatible_with_alg(self.alg.into())?; Ok(()) } } #[cfg(test)] mod tests { use super::*; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{EccFamily, Lifetime, Policy, Type, UsageFlags}; use crate::requests::ResponseStatus; fn get_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags.set_verify_hash(); Attributes { lifetime: Lifetime::Persistent, key_type: Type::EccKeyPair { curve_family: EccFamily::SecpR1, }, bits: 256, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature(AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }), }, } } #[test] fn validate_success() { (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, message: vec![0xff; 32].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap(); } #[test] fn cannot_sign() { let mut attrs = get_attrs(); attrs.policy.usage_flags = UsageFlags::default(); assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha256.into(), }, message: vec![0xff; 32].into(), signature: vec![0xa5; 65].into(), }) .validate(attrs) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_algorithm() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::Ecdsa { hash_alg: Hash::Sha224.into(), }, message: vec![0xff; 28].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } #[test] fn wrong_scheme() { assert_eq!( (Operation { key_name: String::from("some key"), alg: AsymmetricSignature::RsaPss { hash_alg: Hash::Sha224.into(), }, message: vec![0xff; 28].into(), signature: vec![0xa5; 65].into(), }) .validate(get_attrs()) .unwrap_err(), ResponseStatus::PsaErrorNotPermitted ); } } parsec-interface-0.29.1/src/operations/utils_deprecated_primitives.rs000064400000000000000000000571231046102023000242530ustar 00000000000000// Copyright 2022 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! //! # Utilities for checking deprecated primitives //! # by PSA Crypto API 1.0.0 use crate::requests::{ResponseStatus, Result}; use psa_crypto::types::algorithm::*; use psa_crypto::types::key; use psa_crypto::types::key::Type; fn get_deprecated_hashes() -> Vec { vec![Hash::Md2, Hash::Md4, Hash::Md5, Hash::Sha1] } /// Check if hash is deprecated by PSA Crypto API pub fn is_hash_deprecated(hash: Hash) -> bool { get_deprecated_hashes().contains(&hash) } /// Check if signhash is deprecated by PSA Crypto API pub fn is_signhash_deprecated(signhash: SignHash) -> bool { match signhash { SignHash::Specific(hash) => is_hash_deprecated(hash), SignHash::Any => false, } } /// Check if any part of the mac is deprecated by PSA Crypto API pub fn is_mac_deprecated(mac: Mac) -> bool { pub fn is_full_length_mac_deprecated(full_length_mac: FullLengthMac) -> bool { match full_length_mac { FullLengthMac::Hmac { hash_alg } => is_hash_deprecated(hash_alg), _ => false, } } match mac { Mac::FullLength(full_length_mac) => is_full_length_mac_deprecated(full_length_mac), Mac::Truncated { mac_alg, .. } => is_full_length_mac_deprecated(mac_alg), } } /// Check if any part of the cipher is deprecated by PSA Crypto API pub fn is_cipher_deprecated(_cipher: Cipher) -> bool { false } /// Check if any part of the aead is deprecated by PSA Crypto API pub fn is_aead_deprecated(_aead: Aead) -> bool { false } /// Check if any part of the asymmetric signature is deprecated by PSA Crypto API pub fn is_asymmetric_signature_deprecated(asymm_sig: AsymmetricSignature) -> bool { match asymm_sig { AsymmetricSignature::RsaPkcs1v15Sign { hash_alg } | AsymmetricSignature::RsaPss { hash_alg } | AsymmetricSignature::Ecdsa { hash_alg } | AsymmetricSignature::DeterministicEcdsa { hash_alg } => is_signhash_deprecated(hash_alg), _ => false, } } /// Check if any part of the asymmetric encryption is deprecated by PSA Crypto API pub fn is_asymmetric_encryption_deprecated(asymm_enc: AsymmetricEncryption) -> bool { match asymm_enc { AsymmetricEncryption::RsaOaep { hash_alg } => is_hash_deprecated(hash_alg), _ => false, } } /// Check if any part of the key agreement is deprecated by PSA Crypto API pub fn is_key_agreement_deprecated(key_agreement: KeyAgreement) -> bool { match key_agreement { KeyAgreement::WithKeyDerivation { kdf_alg, .. } => is_key_derivation_deprecated(kdf_alg), _ => false, } } /// Check if any part of the key derivation is deprecated by PSA Crypto API pub fn is_key_derivation_deprecated(keyderv: KeyDerivation) -> bool { match keyderv { KeyDerivation::Hkdf { hash_alg } | KeyDerivation::Tls12Prf { hash_alg } | KeyDerivation::Tls12PskToMs { hash_alg } => is_hash_deprecated(hash_alg), } } /// Check if any part of the algorithm is deprecated by PSA Crypto API pub fn is_algorithm_deprecated(alg: Algorithm) -> bool { match alg { Algorithm::None => false, Algorithm::Hash(hash) => is_hash_deprecated(hash), Algorithm::Mac(mac) => is_mac_deprecated(mac), Algorithm::Cipher(cipher) => is_cipher_deprecated(cipher), Algorithm::Aead(aead) => is_aead_deprecated(aead), Algorithm::AsymmetricSignature(asymm_sig) => is_asymmetric_signature_deprecated(asymm_sig), Algorithm::AsymmetricEncryption(asymm_enc) => { is_asymmetric_encryption_deprecated(asymm_enc) } Algorithm::KeyAgreement(key_agreement) => is_key_agreement_deprecated(key_agreement), Algorithm::KeyDerivation(keyderv) => is_key_derivation_deprecated(keyderv), } } /// Return a list of deprecated keys (type, size) if size is None, then the key type is deprecated fn get_deprecated_keys() -> Vec<(Type, Option)> { vec![ (Type::Des, None), (Type::Arc4, None), ( Type::EccPublicKey { curve_family: key::EccFamily::BrainpoolPR1, }, Some(160), ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectR2, }, None, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectR1, }, Some(163), ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectK1, }, Some(163), ), ( Type::EccPublicKey { curve_family: key::EccFamily::SecpR2, }, None, ), ] } /// Check if the key or the key type is deprecated by PSA Crypto API pub fn is_key_deprecated(key_type: Type, key_size: usize) -> bool { for (ktype, ksize) in get_deprecated_keys() { if ktype == key_type && (ksize.is_none() || ksize == Some(key_size)) { return true; } } false } /// Checks if any part of the key template is deprecated by PSA Crypto API pub trait CheckDeprecated { /// Return Error with status ResponseStatus::DeprecatedPrimitive /// if any part of the key template is deprecated by PSA Crypto API fn check_deprecated(&self) -> Result<()>; } impl CheckDeprecated for crate::operations::psa_import_key::Operation { /// Checks if any part of the key template is deprecated by PSA Crypto API fn check_deprecated(&self) -> Result<()> { if is_algorithm_deprecated(self.attributes.policy.permitted_algorithms) || is_key_deprecated(self.attributes.key_type, self.attributes.bits) { return Err(ResponseStatus::DeprecatedPrimitive); } Ok(()) } } impl CheckDeprecated for crate::operations::psa_generate_key::Operation { /// Check if any part of the key template is deprecated by PSA Crypto API fn check_deprecated(&self) -> Result<()> { if is_algorithm_deprecated(self.attributes.policy.permitted_algorithms) || is_key_deprecated(self.attributes.key_type, self.attributes.bits) { return Err(ResponseStatus::DeprecatedPrimitive); } Ok(()) } } #[cfg(test)] mod tests { use super::*; fn get_selection_non_deprecated_hashes() -> Vec { vec![Hash::Sha256, Hash::Sha3_512, Hash::Sha384, Hash::Ripemd160] } fn get_deprecated_macs() -> Vec { let mut deprecated_macs: Vec = vec![]; for hash in get_deprecated_hashes() { deprecated_macs.push(Mac::FullLength(FullLengthMac::Hmac { hash_alg: hash })); // mac_length is chosen arbitary deprecated_macs.push(Mac::Truncated { mac_alg: FullLengthMac::Hmac { hash_alg: hash }, mac_length: 1234, }); } deprecated_macs } fn get_selection_non_deprecated_macs() -> Vec { let mut selection_non_deprecated_macs: Vec = vec![ Mac::FullLength(FullLengthMac::CbcMac), Mac::FullLength(FullLengthMac::Cmac), Mac::Truncated { mac_alg: FullLengthMac::CbcMac, // mac_length is chosen arbitary mac_length: 1234, }, Mac::Truncated { mac_alg: FullLengthMac::Cmac, // mac_length is chosen arbitary mac_length: 1234, }, ]; for hash in get_selection_non_deprecated_hashes() { selection_non_deprecated_macs .push(Mac::FullLength(FullLengthMac::Hmac { hash_alg: hash })); selection_non_deprecated_macs.push(Mac::Truncated { mac_alg: FullLengthMac::Hmac { hash_alg: hash }, // mac_length is chosen arbitary mac_length: 1234, }); } selection_non_deprecated_macs } fn get_deprecated_ciphers() -> Vec { vec![] } fn get_selection_non_deprecated_ciphers() -> Vec { vec![Cipher::Ctr, Cipher::CbcNoPadding, Cipher::StreamCipher] } fn get_deprecated_aeads() -> Vec { vec![] } fn get_selection_non_deprecated_aeads() -> Vec { vec![ Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Ccm), Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTag::Gcm), // tag_length is chosen arbitary Aead::AeadWithShortenedTag { aead_alg: AeadWithDefaultLengthTag::Chacha20Poly1305, tag_length: 121, }, Aead::AeadWithShortenedTag { aead_alg: AeadWithDefaultLengthTag::Ccm, tag_length: 212, }, ] } fn get_deprecated_asymmetric_signatures() -> Vec { let mut deprecated_asymmetric_signatures = vec![]; for hash in get_deprecated_hashes() { deprecated_asymmetric_signatures.push(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: hash.into(), }); deprecated_asymmetric_signatures.push(AsymmetricSignature::RsaPss { hash_alg: hash.into(), }); deprecated_asymmetric_signatures.push(AsymmetricSignature::Ecdsa { hash_alg: hash.into(), }); deprecated_asymmetric_signatures.push(AsymmetricSignature::DeterministicEcdsa { hash_alg: hash.into(), }); } deprecated_asymmetric_signatures } fn get_selection_non_deprecated_asymmetric_signatures() -> Vec { let mut selection_non_deprecated_asymmetric_signatures = vec![ AsymmetricSignature::RsaPkcs1v15SignRaw, AsymmetricSignature::EcdsaAny, ]; for hash in get_selection_non_deprecated_hashes() { selection_non_deprecated_asymmetric_signatures.push( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: hash.into(), }, ); selection_non_deprecated_asymmetric_signatures.push(AsymmetricSignature::RsaPss { hash_alg: hash.into(), }); selection_non_deprecated_asymmetric_signatures.push(AsymmetricSignature::Ecdsa { hash_alg: hash.into(), }); selection_non_deprecated_asymmetric_signatures.push( AsymmetricSignature::DeterministicEcdsa { hash_alg: hash.into(), }, ); } selection_non_deprecated_asymmetric_signatures } fn get_deprecated_asymmetric_encryptions() -> Vec { let mut deprecated_asymmetric_encryptions = vec![]; for hash in get_deprecated_hashes() { deprecated_asymmetric_encryptions .push(AsymmetricEncryption::RsaOaep { hash_alg: hash }); } deprecated_asymmetric_encryptions } fn get_selection_non_deprecated_asymmetric_encryptions() -> Vec { let mut selection_non_deprecated_asymmetric_encryptions = vec![AsymmetricEncryption::RsaPkcs1v15Crypt]; for hash in get_selection_non_deprecated_hashes() { selection_non_deprecated_asymmetric_encryptions .push(AsymmetricEncryption::RsaOaep { hash_alg: hash }); } selection_non_deprecated_asymmetric_encryptions } fn get_deprecated_key_derivations() -> Vec { let mut deprecated_key_derivations = vec![]; for hash in get_deprecated_hashes() { deprecated_key_derivations.push(KeyDerivation::Hkdf { hash_alg: hash }); deprecated_key_derivations.push(KeyDerivation::Tls12Prf { hash_alg: hash }); deprecated_key_derivations.push(KeyDerivation::Tls12PskToMs { hash_alg: hash }); } deprecated_key_derivations } fn get_selection_non_deprecated_key_derivations() -> Vec { let mut selection_non_deprecated_key_derivations = vec![]; for hash in get_selection_non_deprecated_hashes() { selection_non_deprecated_key_derivations.push(KeyDerivation::Hkdf { hash_alg: hash }); selection_non_deprecated_key_derivations .push(KeyDerivation::Tls12Prf { hash_alg: hash }); selection_non_deprecated_key_derivations .push(KeyDerivation::Tls12PskToMs { hash_alg: hash }); } selection_non_deprecated_key_derivations } fn get_deprecated_key_agreements() -> Vec { let mut deprecated_key_agreements = vec![]; for keyderv in get_deprecated_key_derivations() { deprecated_key_agreements.push(KeyAgreement::WithKeyDerivation { ka_alg: RawKeyAgreement::Ffdh, kdf_alg: keyderv, }); deprecated_key_agreements.push(KeyAgreement::WithKeyDerivation { ka_alg: RawKeyAgreement::Ecdh, kdf_alg: keyderv, }); } deprecated_key_agreements } fn get_selection_non_deprecated_key_agreements() -> Vec { let mut selection_non_deprecated_key_agreements = vec![]; for keyderv in get_selection_non_deprecated_key_derivations() { selection_non_deprecated_key_agreements.push(KeyAgreement::WithKeyDerivation { ka_alg: RawKeyAgreement::Ffdh, kdf_alg: keyderv, }); selection_non_deprecated_key_agreements.push(KeyAgreement::WithKeyDerivation { ka_alg: RawKeyAgreement::Ecdh, kdf_alg: keyderv, }); } selection_non_deprecated_key_agreements.push(KeyAgreement::Raw(RawKeyAgreement::Ffdh)); selection_non_deprecated_key_agreements.push(KeyAgreement::Raw(RawKeyAgreement::Ecdh)); selection_non_deprecated_key_agreements } fn get_deprecated_algorithms() -> Vec { let mut deprecated_algorithms: Vec = vec![]; // Hashes for hash in get_deprecated_hashes() { deprecated_algorithms.push(Algorithm::Hash(hash)); } // Macs for mac in get_deprecated_macs() { deprecated_algorithms.push(Algorithm::Mac(mac)); } // Cipher for cipher in get_deprecated_ciphers() { deprecated_algorithms.push(Algorithm::Cipher(cipher)); } // Aead for aead in get_deprecated_aeads() { deprecated_algorithms.push(Algorithm::Aead(aead)); } // AsymmetricSignatures for asymm_sig in get_deprecated_asymmetric_signatures() { deprecated_algorithms.push(Algorithm::AsymmetricSignature(asymm_sig)); } // AsymmetricEncryptions for asymm_enc in get_deprecated_asymmetric_encryptions() { deprecated_algorithms.push(Algorithm::AsymmetricEncryption(asymm_enc)); } // KeyDerivations for key_derv in get_deprecated_key_derivations() { deprecated_algorithms.push(Algorithm::KeyDerivation(key_derv)); } // KeyAgreements for key_agreement in get_deprecated_key_agreements() { deprecated_algorithms.push(Algorithm::KeyAgreement(key_agreement)); } deprecated_algorithms } fn get_selection_non_deprecated_algorithms() -> Vec { let mut selection_non_deprecated_algorithms: Vec = vec![]; // Hashes for hash in get_selection_non_deprecated_hashes() { selection_non_deprecated_algorithms.push(Algorithm::Hash(hash)); } // Macs for mac in get_selection_non_deprecated_macs() { selection_non_deprecated_algorithms.push(Algorithm::Mac(mac)); } // Cipher for cipher in get_selection_non_deprecated_ciphers() { selection_non_deprecated_algorithms.push(Algorithm::Cipher(cipher)); } // Aead for aead in get_selection_non_deprecated_aeads() { selection_non_deprecated_algorithms.push(Algorithm::Aead(aead)); } // AsymmetricSignatures for asymm_sig in get_selection_non_deprecated_asymmetric_signatures() { selection_non_deprecated_algorithms.push(Algorithm::AsymmetricSignature(asymm_sig)); } // AsymmetricEncryptions for asymm_enc in get_selection_non_deprecated_asymmetric_encryptions() { selection_non_deprecated_algorithms.push(Algorithm::AsymmetricEncryption(asymm_enc)); } // KeyDerivations for key_derv in get_selection_non_deprecated_key_derivations() { selection_non_deprecated_algorithms.push(Algorithm::KeyDerivation(key_derv)); } // KeyAgreements for key_agreement in get_selection_non_deprecated_key_agreements() { selection_non_deprecated_algorithms.push(Algorithm::KeyAgreement(key_agreement)); } selection_non_deprecated_algorithms } #[test] fn deprecated_algorithms() { for algo in get_deprecated_algorithms() { assert!(is_algorithm_deprecated(algo), "algorithm: {algo:?}"); } } #[test] fn non_deprecated_algorithms() { for algo in get_selection_non_deprecated_algorithms() { assert!(!is_algorithm_deprecated(algo), "algorithm: {algo:?}"); } } #[test] fn deprecated_keys() { let test_keys = vec![ ( Type::EccPublicKey { curve_family: key::EccFamily::SecpR2, }, 160, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectK1, }, 163, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectR1, }, 163, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectR2, }, 163, ), ( Type::EccPublicKey { curve_family: key::EccFamily::BrainpoolPR1, }, 160, ), (Type::Des, 56), (Type::Des, 56 * 2), (Type::Des, 56 * 3), (Type::Arc4, 40), (Type::Arc4, 2048), ]; for (ktype, ksize) in test_keys { assert!( is_key_deprecated(ktype, ksize), "key: ({ktype:?} : {ksize:?})" ); } } #[test] fn non_deprecated_keys() { let test_keys = vec![ ( Type::EccPublicKey { curve_family: key::EccFamily::SecpK1, }, 192, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SecpR1, }, 256, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectK1, }, 239, ), ( Type::EccPublicKey { curve_family: key::EccFamily::SectR1, }, 409, ), ( Type::EccPublicKey { curve_family: key::EccFamily::BrainpoolPR1, }, 192, ), ( Type::EccPublicKey { curve_family: key::EccFamily::BrainpoolPR1, }, 256, ), (Type::Aes, 256), (Type::RsaPublicKey, 2048), (Type::Hmac, 128), (Type::Chacha20, 256), ]; for (ktype, ksize) in test_keys { assert!( !is_key_deprecated(ktype, ksize), "key: ({ktype:?} : {ksize:?})" ); } } #[test] fn op_check_deprecated_for_deprecated() { use psa_crypto::types::key::{Attributes, Lifetime, Policy, UsageFlags}; let mut generate_key_op = crate::operations::psa_generate_key::Operation { key_name: "dummy".to_string(), attributes: Attributes { lifetime: Lifetime::Persistent, key_type: Type::RawData, bits: 0, policy: Policy { usage_flags: UsageFlags::default(), permitted_algorithms: Algorithm::None, }, }, }; let mut import_key_op = crate::operations::psa_import_key::Operation { key_name: "dummy".to_string(), attributes: Attributes { lifetime: Lifetime::Persistent, key_type: Type::RawData, bits: 0, policy: Policy { usage_flags: UsageFlags::default(), permitted_algorithms: Algorithm::None, }, }, data: secrecy::Secret::new(vec![]), }; let (test_key_type, test_key_size) = get_deprecated_keys()[0]; let test_algorithm = Algorithm::Hash(Hash::Md2); generate_key_op.attributes.key_type = test_key_type; generate_key_op.attributes.bits = test_key_size.unwrap_or(0); generate_key_op.attributes.policy.permitted_algorithms = test_algorithm; assert_eq!( generate_key_op.check_deprecated(), Err(ResponseStatus::DeprecatedPrimitive) ); import_key_op.attributes.key_type = test_key_type; import_key_op.attributes.bits = test_key_size.unwrap_or(0); import_key_op.attributes.policy.permitted_algorithms = test_algorithm; assert_eq!( import_key_op.check_deprecated(), Err(ResponseStatus::DeprecatedPrimitive) ); } #[test] fn op_check_deprecated_for_non_deprecated() { use psa_crypto::types::key::{Attributes, Lifetime, Policy, UsageFlags}; let mut generate_key_op = crate::operations::psa_generate_key::Operation { key_name: "dummy".to_string(), attributes: Attributes { lifetime: Lifetime::Persistent, key_type: Type::RawData, bits: 0, policy: Policy { usage_flags: UsageFlags::default(), permitted_algorithms: Algorithm::None, }, }, }; let mut import_key_op = crate::operations::psa_import_key::Operation { key_name: "dummy".to_string(), attributes: Attributes { lifetime: Lifetime::Persistent, key_type: Type::RawData, bits: 0, policy: Policy { usage_flags: UsageFlags::default(), permitted_algorithms: Algorithm::None, }, }, data: secrecy::Secret::new(vec![]), }; let test_key_type = Type::Aes; let test_key_size: usize = 256; let test_algorithm = Algorithm::Cipher(Cipher::CbcNoPadding); generate_key_op.attributes.key_type = test_key_type; generate_key_op.attributes.bits = test_key_size; generate_key_op.attributes.policy.permitted_algorithms = test_algorithm; assert_eq!(generate_key_op.check_deprecated(), Ok(())); import_key_op.attributes.key_type = test_key_type; import_key_op.attributes.bits = test_key_size; import_key_op.attributes.policy.permitted_algorithms = test_algorithm; assert_eq!(import_key_op.check_deprecated(), Ok(())); } } parsec-interface-0.29.1/src/operations_protobuf/convert_attest_key.rs000064400000000000000000000267141046102023000243160ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::attest_key::{ attestation_mechanism_params, attestation_output, AttestationMechanismParams, AttestationOutput, Operation as OperationProto, Result as ResultProto, }; use crate::operations::attest_key::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::TryFrom; impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { match op { Operation::ActivateCredential { attested_key_name, attesting_key_name, credential_blob, secret, } => Ok(OperationProto { attested_key_name, attesting_key_name: attesting_key_name.unwrap_or_default(), parameters: Some(AttestationMechanismParams { mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential( attestation_mechanism_params::ActivateCredential { credential_blob: credential_blob.to_vec(), secret: secret.to_vec(), }, )), }), }), } } } impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { match proto_op.parameters { Some(AttestationMechanismParams { mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential( attestation_mechanism_params::ActivateCredential { credential_blob, secret, }, )), }) => Ok(Operation::ActivateCredential { attested_key_name: proto_op.attested_key_name, attesting_key_name: if proto_op.attesting_key_name.is_empty() { None } else { Some(proto_op.attesting_key_name) }, credential_blob: credential_blob.into(), secret: secret.into(), }), _ => { error!("The encoding of the operation does not follow the expected pattern"); Err(ResponseStatus::InvalidEncoding) } } } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { match op { Result::ActivateCredential { credential } => Ok(ResultProto { output: Some(AttestationOutput { mechanism: Some(attestation_output::Mechanism::ActivateCredential( attestation_output::ActivateCredential { credential: credential.to_vec(), }, )), }), }), } } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { match proto_op { ResultProto { output: Some(AttestationOutput { mechanism: Some(attestation_output::Mechanism::ActivateCredential( attestation_output::ActivateCredential { credential }, )), }), } => Ok(Result::ActivateCredential { credential: credential.into(), }), _ => { error!("The encoding of the result does not follow the expected pattern"); Err(ResponseStatus::InvalidEncoding) } } } } #[cfg(test)] mod test { use super::super::generated_ops::attest_key::{ attestation_mechanism_params, attestation_output, AttestationMechanismParams, AttestationOutput, Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::{ attest_key::Operation, attest_key::Result, NativeOperation, NativeResult, }; use crate::requests::Opcode; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn attest_key_op_from_proto() { let op_attested_key_name = String::from("attested key name"); let op_attesting_key_name = String::from("attesting key name"); let op_credential_blob = vec![0xaa; 32]; let op_secret = vec![0x11; 16]; let proto = OperationProto { attested_key_name: op_attested_key_name.clone(), attesting_key_name: op_attesting_key_name.clone(), parameters: Some(AttestationMechanismParams { mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential( attestation_mechanism_params::ActivateCredential { credential_blob: op_credential_blob.clone(), secret: op_secret.clone(), }, )), }), }; let op: Operation = proto.try_into().expect("Failed conversion"); let Operation::ActivateCredential { attested_key_name, attesting_key_name, credential_blob, secret, } = op; assert_eq!(attested_key_name, op_attested_key_name); assert_eq!( attesting_key_name.unwrap_or_default(), op_attesting_key_name ); assert_eq!(credential_blob.to_vec(), op_credential_blob); assert_eq!(secret.to_vec(), op_secret); } #[test] fn attest_key_proto_no_attesting() { let op_attested_key_name = String::from("attested key name"); let op_credential_blob = vec![0xaa; 32]; let op_secret = vec![0x11; 16]; let proto = OperationProto { attested_key_name: op_attested_key_name, attesting_key_name: String::new(), parameters: Some(AttestationMechanismParams { mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential( attestation_mechanism_params::ActivateCredential { credential_blob: op_credential_blob, secret: op_secret, }, )), }), }; let op: Operation = proto.try_into().expect("Failed conversion"); let Operation::ActivateCredential { attesting_key_name, .. } = op; assert!(attesting_key_name.is_none()); } #[test] fn attest_key_proto_from_op() { let op_attested_key_name = String::from("attested key name"); let op_attesting_key_name = String::from("attesting key name"); let op_credential_blob = vec![0xaa; 32]; let op_secret = vec![0x11; 16]; let op = Operation::ActivateCredential { attested_key_name: op_attested_key_name.clone(), attesting_key_name: Some(op_attesting_key_name.clone()), credential_blob: op_credential_blob.clone().into(), secret: op_secret.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed conversion"); if let OperationProto { attested_key_name, attesting_key_name, parameters: Some(AttestationMechanismParams { mechanism: Some(attestation_mechanism_params::Mechanism::ActivateCredential( attestation_mechanism_params::ActivateCredential { credential_blob, secret, }, )), }), } = proto { assert_eq!(attested_key_name, op_attested_key_name); assert_eq!(attesting_key_name, op_attesting_key_name); assert_eq!(credential_blob, op_credential_blob); assert_eq!(secret, op_secret); } } #[test] fn attest_key_op_no_attesting() { let op_attested_key_name = String::from("attested key name"); let op_credential_blob = vec![0xaa; 32]; let op_secret = vec![0x11; 16]; let op = Operation::ActivateCredential { attested_key_name: op_attested_key_name, attesting_key_name: None, credential_blob: op_credential_blob.into(), secret: op_secret.into(), }; let proto: OperationProto = op.try_into().expect("Failed conversion"); assert_eq!(proto.attesting_key_name, String::new()); } #[test] fn attest_key_op_e2e() { let op_attested_key_name = String::from("attested key name"); let op_attesting_key_name = String::from("attesting key name"); let op_credential_blob = vec![0xaa; 32]; let op_secret = vec![0x11; 16]; let op = Operation::ActivateCredential { attested_key_name: op_attested_key_name, attesting_key_name: Some(op_attesting_key_name), credential_blob: op_credential_blob.into(), secret: op_secret.into(), }; let body = CONVERTER .operation_to_body(NativeOperation::AttestKey(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::AttestKey) .expect("Failed to convert to operation"); } #[test] fn attest_key_resp_from_proto() { let resp_credential = vec![0xbb; 32]; let proto = ResultProto { output: Some(AttestationOutput { mechanism: Some(attestation_output::Mechanism::ActivateCredential( attestation_output::ActivateCredential { credential: resp_credential.clone(), }, )), }), }; let resp: Result = proto.try_into().expect("Failed conversion"); let Result::ActivateCredential { credential } = resp; assert_eq!(credential.to_vec(), resp_credential); } #[test] fn attest_key_resp_to_proto() { let resp_credential = vec![0xbb; 32]; let resp = Result::ActivateCredential { credential: resp_credential.clone().into(), }; let proto: ResultProto = resp.try_into().expect("Failed conversion"); if let ResultProto { output: Some(AttestationOutput { mechanism: Some(attestation_output::Mechanism::ActivateCredential( attestation_output::ActivateCredential { credential }, )), }), } = proto { assert_eq!(credential.to_vec(), resp_credential); } } #[test] fn attest_key_resp_e2e() { let resp_credential = vec![0xbb; 32]; let resp = Result::ActivateCredential { credential: resp_credential.into(), }; let body = CONVERTER .result_to_body(NativeResult::AttestKey(resp)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_result(body, Opcode::AttestKey) .expect("Failed to convert to operation"); } } parsec-interface-0.29.1/src/operations_protobuf/convert_can_do_crypto.rs000064400000000000000000000143411046102023000247560ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::can_do_crypto::{ CheckType as CheckTypeProto, Operation as OperationProto, Result as ResultProto, }; use crate::operations::can_do_crypto::{CheckType, Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let key_attributes = proto_op.attributes.ok_or_else(|| { error!("The attributes field of CanDoCrypto::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })?; Ok(Operation { check_type: i32_to_check_type(proto_op.check_type)?, attributes: key_attributes.try_into()?, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { check_type: check_type_to_i32(op.check_type), attributes: Some(op.attributes.try_into()?), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_result: Result) -> std::result::Result { Ok(ResultProto {}) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_response: ResultProto) -> std::result::Result { Ok(Result {}) } } // CheckType: from protobuf to native impl TryFrom for CheckType { type Error = ResponseStatus; fn try_from(check_type_proto_val: CheckTypeProto) -> std::result::Result { match check_type_proto_val { CheckTypeProto::ChecktypeNone => Err(ResponseStatus::InvalidEncoding), CheckTypeProto::Use => Ok(CheckType::Use), CheckTypeProto::Generate => Ok(CheckType::Generate), CheckTypeProto::Import => Ok(CheckType::Import), CheckTypeProto::Derive => Ok(CheckType::Derive), } } } // CheckType: from native to protobuf impl TryFrom for CheckTypeProto { type Error = ResponseStatus; fn try_from(check_type_val: CheckType) -> std::result::Result { match check_type_val { CheckType::Use => Ok(CheckTypeProto::Use), CheckType::Generate => Ok(CheckTypeProto::Generate), CheckType::Import => Ok(CheckTypeProto::Import), CheckType::Derive => Ok(CheckTypeProto::Derive), } } } // CheckType from protobuf to native pub fn i32_to_check_type(check_type_val: i32) -> std::result::Result { let check_type_proto: CheckTypeProto = check_type_val.try_into()?; check_type_proto.try_into() } // CheckType from native to protobuf pub fn check_type_to_i32(check_type: CheckType) -> i32 { match check_type { CheckType::Use => CheckTypeProto::Use.into(), CheckType::Generate => CheckTypeProto::Generate.into(), CheckType::Import => CheckTypeProto::Import.into(), CheckType::Derive => CheckTypeProto::Derive.into(), } } #[cfg(test)] mod test { use super::super::generated_ops::can_do_crypto::Operation as OperationProto; use crate::operations::can_do_crypto::{CheckType, Operation}; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{self, Attributes, Lifetime, Policy, UsageFlags}; use crate::operations_protobuf::convert_can_do_crypto::check_type_to_i32; use std::convert::TryInto; #[test] fn proto_to_resp() { let mut usage_flags: UsageFlags = Default::default(); let _ = usage_flags .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_attrs = Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }; let proto = OperationProto { check_type: check_type_to_i32(CheckType::Use), attributes: Some(key_attrs.try_into().expect("Failed conversion")), }; let resp: Operation = proto.try_into().expect("Failed conversion"); assert_eq!(resp.check_type, CheckType::Use); assert_eq!(resp.attributes, key_attrs); } #[test] fn resp_to_proto() { let mut usage_flags: UsageFlags = Default::default(); let _ = usage_flags .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_attrs = Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }; let resp: Operation = Operation { check_type: CheckType::Use, attributes: key_attrs, }; let proto: OperationProto = resp.try_into().expect("Failed conversion"); assert_eq!(proto.check_type, check_type_to_i32(CheckType::Use)); assert_eq!( proto.attributes.expect("Failed conversion"), key_attrs.try_into().expect("Failed conversion") ); } } parsec-interface-0.29.1/src/operations_protobuf/convert_delete_client.rs000064400000000000000000000025701046102023000247340ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::delete_client::{Operation as OperationProto, Result as ResultProto}; use crate::operations::delete_client::{Operation, Result}; impl From for Operation { fn from(proto_op: OperationProto) -> Self { Operation { client: proto_op.client, } } } impl From for OperationProto { fn from(op: Operation) -> Self { OperationProto { client: op.client } } } impl From for Result { fn from(_proto_op: ResultProto) -> Self { Result {} } } impl From for ResultProto { fn from(_op: Result) -> Self { ResultProto {} } } #[cfg(test)] mod test { use super::super::generated_ops::delete_client::Operation as OperationProto; use crate::operations::delete_client::Operation; #[test] fn proto_to_resp() { let proto = OperationProto { client: String::from("toto"), }; let resp: Operation = proto.into(); assert_eq!(resp.client, String::from("toto")); } #[test] fn resp_to_proto() { let resp: Operation = Operation { client: String::from("toto"), }; let proto: OperationProto = resp.into(); assert_eq!(proto.client, String::from("toto")); } } parsec-interface-0.29.1/src/operations_protobuf/convert_list_authenticators.rs000064400000000000000000000207351046102023000262270ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::list_authenticators::{ AuthenticatorInfo as AuthenticatorInfoProto, Operation as OperationProto, Result as ResultProto, }; use crate::operations::list_authenticators::{AuthenticatorInfo, Operation, Result}; use crate::requests::{AuthType, ResponseStatus}; use num::FromPrimitive; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(_proto_op: OperationProto) -> std::result::Result { Ok(Operation {}) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(_op: Operation) -> std::result::Result { Ok(Default::default()) } } impl TryFrom for AuthenticatorInfo { type Error = ResponseStatus; fn try_from(proto_info: AuthenticatorInfoProto) -> std::result::Result { let id: AuthType = match FromPrimitive::from_u32(proto_info.id) { Some(id) => id, None => return Err(ResponseStatus::AuthenticatorDoesNotExist), }; Ok(AuthenticatorInfo { description: proto_info.description, version_maj: proto_info.version_maj, version_min: proto_info.version_min, version_rev: proto_info.version_rev, id, }) } } impl TryFrom for AuthenticatorInfoProto { type Error = ResponseStatus; fn try_from(info: AuthenticatorInfo) -> std::result::Result { Ok(AuthenticatorInfoProto { description: info.description, version_maj: info.version_maj, version_min: info.version_min, version_rev: info.version_rev, id: info.id as u32, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { let mut authenticators: Vec = Vec::new(); for authenticator in proto_op.authenticators { authenticators.push(authenticator.try_into()?); } Ok(Result { authenticators }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { let mut authenticators: Vec = Vec::new(); for authenticator in op.authenticators { authenticators.push(authenticator.try_into()?); } Ok(ResultProto { authenticators }) } } #[cfg(test)] mod test { // Operation <-> Proto conversions are not tested since they're too simple use super::super::generated_ops::list_authenticators::{ AuthenticatorInfo as AuthenticatorInfoProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::list_authenticators::{AuthenticatorInfo, Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, AuthType, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn proto_to_resp() { let mut proto: ResultProto = Default::default(); let authenticator_info = AuthenticatorInfoProto { description: String::from("authenticator description"), version_maj: 0, version_min: 1, version_rev: 0, id: AuthType::Direct as u32, }; proto.authenticators.push(authenticator_info); let resp: Result = proto.try_into().unwrap(); assert_eq!(resp.authenticators.len(), 1); assert_eq!( resp.authenticators[0].description, "authenticator description" ); assert_eq!(resp.authenticators[0].version_maj, 0); assert_eq!(resp.authenticators[0].version_min, 1); assert_eq!(resp.authenticators[0].version_rev, 0); assert_eq!(resp.authenticators[0].id, AuthType::Direct); } #[test] fn resp_to_proto() { let mut resp: Result = Result { authenticators: Vec::new(), }; let authenticator_info = AuthenticatorInfo { description: String::from("authenticator description"), version_maj: 0, version_min: 1, version_rev: 0, id: AuthType::Direct, }; resp.authenticators.push(authenticator_info); let proto: ResultProto = resp.try_into().unwrap(); assert_eq!(proto.authenticators.len(), 1); assert_eq!( proto.authenticators[0].description, "authenticator description" ); assert_eq!(proto.authenticators[0].version_maj, 0); assert_eq!(proto.authenticators[0].version_min, 1); assert_eq!(proto.authenticators[0].version_rev, 0); assert_eq!(proto.authenticators[0].id, AuthType::Direct as u32); } #[test] fn list_authenticators_req_to_native() { let req_body = RequestBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListAuthenticators) .is_ok()); } #[test] fn op_list_authenticators_from_native() { let list_authenticators = Operation {}; let body = CONVERTER .operation_to_body(NativeOperation::ListAuthenticators(list_authenticators)) .expect("Failed to convert request"); assert!(body.is_empty()); } #[test] fn op_list_authenticators_e2e() { let list_authenticators = Operation {}; let req_body = CONVERTER .operation_to_body(NativeOperation::ListAuthenticators(list_authenticators)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListAuthenticators) .is_ok()); } #[test] fn req_from_native_mangled_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListAuthenticators) .is_err()); } #[test] fn list_authenticators_body_to_native() { let resp_body = ResponseBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListAuthenticators) .is_ok()); } #[test] fn result_list_authenticators_from_native() { let mut list_authenticators = Result { authenticators: Vec::new(), }; let authenticator_info = AuthenticatorInfo { description: String::from("authenticator description"), version_maj: 0, version_min: 1, version_rev: 0, id: AuthType::Direct, }; list_authenticators.authenticators.push(authenticator_info); let body = CONVERTER .result_to_body(NativeResult::ListAuthenticators(list_authenticators)) .expect("Failed to convert response"); assert!(!body.is_empty()); } #[test] fn list_authenticators_result_e2e() { let mut list_authenticators = Result { authenticators: Vec::new(), }; let authenticator_info = AuthenticatorInfo { description: String::from("authenticator description"), version_maj: 0, version_min: 1, version_rev: 0, id: AuthType::Direct, }; list_authenticators.authenticators.push(authenticator_info); let body = CONVERTER .result_to_body(NativeResult::ListAuthenticators(list_authenticators)) .expect("Failed to convert response"); assert!(!body.is_empty()); let result = CONVERTER .body_to_result(body, Opcode::ListAuthenticators) .expect("Failed to convert back to result"); match result { NativeResult::ListAuthenticators(result) => { assert_eq!(result.authenticators.len(), 1); } _ => panic!("Expected list_authenticators"), } } #[test] fn resp_from_native_mangled_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListAuthenticators) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_list_clients.rs000064400000000000000000000027611046102023000246320ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::list_clients::{Operation as OperationProto, Result as ResultProto}; use crate::operations::list_clients::{Operation, Result}; impl From for Operation { fn from(_proto_op: OperationProto) -> Self { Operation {} } } impl From for OperationProto { fn from(_op: Operation) -> Self { Default::default() } } impl From for Result { fn from(proto_op: ResultProto) -> Self { Result { clients: proto_op.clients, } } } impl From for ResultProto { fn from(op: Result) -> Self { ResultProto { clients: op.clients, } } } #[cfg(test)] mod test { use super::super::generated_ops::list_clients::Result as ResultProto; use crate::operations::list_clients::Result; #[test] fn proto_to_resp() { let mut proto: ResultProto = Default::default(); proto.clients.push(String::from("toto")); let resp: Result = proto.into(); assert_eq!(resp.clients.len(), 1); assert_eq!(resp.clients[0], String::from("toto")); } #[test] fn resp_to_proto() { let resp: Result = Result { clients: vec![String::from("toto")], }; let proto: ResultProto = resp.into(); assert_eq!(proto.clients.len(), 1); assert_eq!(proto.clients[0], String::from("toto")); } } parsec-interface-0.29.1/src/operations_protobuf/convert_list_keys.rs000064400000000000000000000257571046102023000241560ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::list_keys::{ KeyInfo as KeyInfoProto, Operation as OperationProto, Result as ResultProto, }; use crate::operations::list_keys::{KeyInfo, Operation, Result}; use crate::requests::{ProviderId, ResponseStatus}; use log::error; use num::FromPrimitive; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(_proto_op: OperationProto) -> std::result::Result { Ok(Operation {}) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(_op: Operation) -> std::result::Result { Ok(Default::default()) } } impl TryFrom for KeyInfo { type Error = ResponseStatus; fn try_from(proto_info: KeyInfoProto) -> std::result::Result { let id: ProviderId = match FromPrimitive::from_u32(proto_info.provider_id) { Some(id) => id, None => return Err(ResponseStatus::ProviderDoesNotExist), }; let attributes = proto_info .attributes .ok_or_else(|| { error!("The attributes field of KeyInfo protobuf message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?; Ok(KeyInfo { provider_id: id, name: proto_info.name, attributes, }) } } impl TryFrom for KeyInfoProto { type Error = ResponseStatus; fn try_from(info: KeyInfo) -> std::result::Result { Ok(KeyInfoProto { provider_id: info.provider_id as u32, name: info.name, attributes: Some(info.attributes.try_into()?), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { let mut keys: Vec = Vec::new(); for key in proto_op.keys { keys.push(key.try_into()?); } Ok(Result { keys }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { let mut keys: Vec = Vec::new(); for key in op.keys { keys.push(key.try_into()?); } Ok(ResultProto { keys }) } } #[cfg(test)] mod test { // Operation <-> Proto conversions are not tested since they're too simple use super::super::generated_ops::list_keys::{KeyInfo as KeyInfoProto, Result as ResultProto}; use super::super::generated_ops::psa_key_attributes::KeyAttributes as KeyAttributesProto; use super::super::{Convert, ProtobufConverter}; use crate::operations::list_keys::{KeyInfo, Operation, Result}; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{self, Attributes, Lifetime, Policy, UsageFlags}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode, ProviderId}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn proto_to_resp() { let mut proto: ResultProto = Default::default(); let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_attrs = Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }; let key_attrs_proto: KeyAttributesProto = key_attrs.try_into().unwrap(); let key_info = KeyInfoProto { provider_id: ProviderId::MbedCrypto as u32, name: String::from("Some Key Name"), attributes: Some(key_attrs_proto), }; proto.keys.push(key_info); let resp: Result = proto.try_into().unwrap(); assert_eq!(resp.keys.len(), 1); assert_eq!(resp.keys[0].name, "Some Key Name"); assert_eq!(resp.keys[0].provider_id, ProviderId::MbedCrypto); assert_eq!(resp.keys[0].attributes, key_attrs); } #[test] fn resp_to_proto() { let mut resp: Result = Result { keys: Vec::new() }; let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_attributes = Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }; let key_info = KeyInfo { provider_id: ProviderId::MbedCrypto, name: String::from("Foo"), attributes: key_attributes, }; resp.keys.push(key_info); let proto: ResultProto = resp.try_into().unwrap(); let key_attributes_proto: KeyAttributesProto = key_attributes.try_into().unwrap(); assert_eq!(proto.keys.len(), 1); assert_eq!(proto.keys[0].provider_id, ProviderId::MbedCrypto as u32); assert_eq!(proto.keys[0].name, "Foo"); assert_eq!(proto.keys[0].attributes, Some(key_attributes_proto)); } #[test] fn list_keys_req_to_native() { let req_body = RequestBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListKeys) .is_ok()); } #[test] fn op_list_keys_from_native() { let list_keys = Operation {}; let body = CONVERTER .operation_to_body(NativeOperation::ListKeys(list_keys)) .expect("Failed to convert request"); assert!(body.is_empty()); } #[test] fn op_list_keys_e2e() { let list_keys = Operation {}; let req_body = CONVERTER .operation_to_body(NativeOperation::ListKeys(list_keys)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListKeys) .is_ok()); } #[test] fn req_from_native_mangled_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListKeys) .is_err()); } #[test] fn list_keys_body_to_native() { let resp_body = ResponseBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListKeys) .is_ok()); } #[test] fn result_list_keys_from_native() { let mut list_keys = Result { keys: Vec::new() }; let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_info = KeyInfo { provider_id: ProviderId::MbedCrypto, name: String::from("Bar"), attributes: Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }, }; list_keys.keys.push(key_info); let body = CONVERTER .result_to_body(NativeResult::ListKeys(list_keys)) .expect("Failed to convert response"); assert!(!body.is_empty()); } #[test] fn list_keys_result_e2e() { let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let mut list_keys = Result { keys: Vec::new() }; let key_info = KeyInfo { provider_id: ProviderId::MbedCrypto, name: String::from("Baz"), attributes: Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }, }; list_keys.keys.push(key_info); let body = CONVERTER .result_to_body(NativeResult::ListKeys(list_keys)) .expect("Failed to convert response"); assert!(!body.is_empty()); let result = CONVERTER .body_to_result(body, Opcode::ListKeys) .expect("Failed to convert back to result"); match result { NativeResult::ListKeys(result) => { assert_eq!(result.keys.len(), 1); } _ => panic!("Expected list_keys"), } } #[test] fn resp_from_native_mangled_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListKeys) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_list_opcodes.rs000064400000000000000000000137011046102023000246210ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::list_opcodes::{Operation as OperationProto, Result as ResultProto}; use crate::operations::list_opcodes::{Operation, Result}; use crate::requests::{Opcode, ResponseStatus}; use log::error; use num::FromPrimitive; use std::collections::HashSet; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { match FromPrimitive::from_u32(proto_op.provider_id) { None => { error!("Invalid provider ID: {}", proto_op.provider_id); Err(ResponseStatus::ProviderDoesNotExist) } Some(provider_id) => Ok(Operation { provider_id }), } } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { provider_id: op.provider_id as u32, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { let mut opcodes: HashSet = HashSet::new(); for opcode in proto_op.opcodes { let opcode = match FromPrimitive::from_u32(opcode) { Some(code) => code, None => return Err(ResponseStatus::OpcodeDoesNotExist), }; let _ = opcodes.insert(opcode); } Ok(Result { opcodes }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { let mut opcodes: Vec = Vec::new(); for opcode in op.opcodes { opcodes.push(opcode as u32); } Ok(ResultProto { opcodes }) } } #[cfg(test)] mod test { // Operation <-> Proto conversions are not tested since they're too simple use super::super::generated_ops::list_opcodes::Result as ResultProto; use super::super::{Convert, ProtobufConverter}; use crate::operations::{ list_opcodes::Operation, list_opcodes::Result, NativeOperation, NativeResult, }; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode, ProviderId}; use std::collections::HashSet; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn proto_to_resp() { let mut proto: ResultProto = Default::default(); proto.opcodes.push(1); let resp: Result = proto.try_into().unwrap(); assert_eq!(resp.opcodes.len(), 1); assert!(resp.opcodes.contains(&Opcode::Ping)); } #[test] fn resp_to_proto() { let mut resp: Result = Result { opcodes: HashSet::new(), }; let _ = resp.opcodes.insert(Opcode::Ping); let proto: ResultProto = resp.try_into().unwrap(); assert_eq!(proto.opcodes.len(), 1); assert_eq!(proto.opcodes[0], 1); } #[test] fn list_opcodes_req_to_native() { let req_body = RequestBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListOpcodes) .is_ok()); } #[test] fn op_list_opcodes_from_native() { let list_opcodes = Operation { provider_id: ProviderId::Core, }; let body = CONVERTER .operation_to_body(NativeOperation::ListOpcodes(list_opcodes)) .expect("Failed to convert request"); assert!(body.is_empty()); } #[test] fn op_list_opcodes_e2e() { let list_opcodes = Operation { provider_id: ProviderId::Pkcs11, }; let req_body = CONVERTER .operation_to_body(NativeOperation::ListOpcodes(list_opcodes)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListOpcodes) .is_ok()); } #[test] fn req_from_native_mangled_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListOpcodes) .is_err()); } #[test] fn list_opcodes_body_to_native() { let resp_body = ResponseBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListOpcodes) .is_ok()); } #[test] fn result_list_opcodes_from_native() { let mut list_opcodes = Result { opcodes: HashSet::new(), }; let _ = list_opcodes.opcodes.insert(Opcode::Ping); let body = CONVERTER .result_to_body(NativeResult::ListOpcodes(list_opcodes)) .expect("Failed to convert response"); assert!(!body.is_empty()); } #[test] fn list_opcodes_result_e2e() { let mut list_opcodes = Result { opcodes: HashSet::new(), }; let _ = list_opcodes.opcodes.insert(Opcode::Ping); let body = CONVERTER .result_to_body(NativeResult::ListOpcodes(list_opcodes)) .expect("Failed to convert response"); assert!(!body.is_empty()); let result = CONVERTER .body_to_result(body, Opcode::ListOpcodes) .expect("Failed to convert back to result"); match result { NativeResult::ListOpcodes(result) => { assert_eq!(result.opcodes.len(), 1); } _ => panic!("Expected list_opcodes"), } } #[test] fn resp_from_native_mangled_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListOpcodes) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_list_providers.rs000064400000000000000000000223531046102023000252050ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::list_providers::{ Operation as OperationProto, ProviderInfo as ProviderInfoProto, Result as ResultProto, }; use crate::operations::list_providers::{Operation, ProviderInfo, Result}; use crate::requests::{ProviderId, ResponseStatus}; use num::FromPrimitive; use std::convert::{TryFrom, TryInto}; use uuid::Uuid; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(_proto_op: OperationProto) -> std::result::Result { Ok(Operation {}) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(_op: Operation) -> std::result::Result { Ok(Default::default()) } } impl TryFrom for ProviderInfo { type Error = ResponseStatus; fn try_from(proto_info: ProviderInfoProto) -> std::result::Result { // UUIDs are strings of 36 ASCII characters (bytes) containing 32 lowercase hexadecimal // digits and 4 hyphens. let provider_uuid = match Uuid::parse_str(&proto_info.uuid) { Ok(provider_uuid) => provider_uuid, Err(_) => return Err(ResponseStatus::WrongProviderUuid), }; let id: ProviderId = match FromPrimitive::from_u32(proto_info.id) { Some(id) => id, None => return Err(ResponseStatus::ProviderDoesNotExist), }; Ok(ProviderInfo { uuid: provider_uuid, description: proto_info.description, vendor: proto_info.vendor, version_maj: proto_info.version_maj, version_min: proto_info.version_min, version_rev: proto_info.version_rev, id, }) } } impl TryFrom for ProviderInfoProto { type Error = ResponseStatus; fn try_from(info: ProviderInfo) -> std::result::Result { Ok(ProviderInfoProto { uuid: info.uuid.to_string(), description: info.description, vendor: info.vendor, version_maj: info.version_maj, version_min: info.version_min, version_rev: info.version_rev, id: info.id as u32, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { let mut providers: Vec = Vec::new(); for provider in proto_op.providers { providers.push(provider.try_into()?); } Ok(Result { providers }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { let mut providers: Vec = Vec::new(); for provider in op.providers { providers.push(provider.try_into()?); } Ok(ResultProto { providers }) } } #[cfg(test)] mod test { // Operation <-> Proto conversions are not tested since they're too simple use super::super::generated_ops::list_providers::{ ProviderInfo as ProviderInfoProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::list_providers::{Operation, ProviderInfo, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode, ProviderId}; use std::convert::TryInto; use uuid::Uuid; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn proto_to_resp() { let mut proto: ResultProto = Default::default(); let provider_info = ProviderInfoProto { uuid: String::from("9840cd61-9367-4010-bc24-f5b98a6174d1"), description: String::from("provider description"), vendor: String::from("Arm"), version_maj: 0, version_min: 1, version_rev: 0, id: 1, }; proto.providers.push(provider_info); let resp: Result = proto.try_into().unwrap(); assert_eq!(resp.providers.len(), 1); assert_eq!( resp.providers[0].uuid, Uuid::parse_str("9840CD6193674010BC24F5B98A6174D1").unwrap() ); assert_eq!(resp.providers[0].description, "provider description"); assert_eq!(resp.providers[0].vendor, "Arm"); assert_eq!(resp.providers[0].version_maj, 0); assert_eq!(resp.providers[0].version_min, 1); assert_eq!(resp.providers[0].version_rev, 0); assert_eq!(resp.providers[0].id, ProviderId::MbedCrypto); } #[test] fn resp_to_proto() { let mut resp: Result = Result { providers: Vec::new(), }; let provider_info = ProviderInfo { uuid: Uuid::parse_str("9840CD6193674010BC24F5B98A6174D1").unwrap(), description: String::from("provider description"), vendor: String::from("Arm"), version_maj: 0, version_min: 1, version_rev: 0, id: ProviderId::MbedCrypto, }; resp.providers.push(provider_info); let proto: ResultProto = resp.try_into().unwrap(); assert_eq!(proto.providers.len(), 1); assert_eq!( proto.providers[0].uuid, "9840cd61-9367-4010-bc24-f5b98a6174d1" ); assert_eq!(proto.providers[0].description, "provider description"); assert_eq!(proto.providers[0].vendor, "Arm"); assert_eq!(proto.providers[0].version_maj, 0); assert_eq!(proto.providers[0].version_min, 1); assert_eq!(proto.providers[0].version_rev, 0); assert_eq!(proto.providers[0].id, 1); } #[test] fn list_providers_req_to_native() { let req_body = RequestBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListProviders) .is_ok()); } #[test] fn op_list_providers_from_native() { let list_providers = Operation {}; let body = CONVERTER .operation_to_body(NativeOperation::ListProviders(list_providers)) .expect("Failed to convert request"); assert!(body.is_empty()); } #[test] fn op_list_providers_e2e() { let list_providers = Operation {}; let req_body = CONVERTER .operation_to_body(NativeOperation::ListProviders(list_providers)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListProviders) .is_ok()); } #[test] fn req_from_native_mangled_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::ListProviders) .is_err()); } #[test] fn list_providers_body_to_native() { let resp_body = ResponseBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListProviders) .is_ok()); } #[test] fn result_list_providers_from_native() { let mut list_providers = Result { providers: Vec::new(), }; let provider_info = ProviderInfo { uuid: Uuid::parse_str("9840cd61-9367-4010-bc24-f5b98a6174d1").unwrap(), description: String::from("provider description"), vendor: String::from("Arm"), version_maj: 0, version_min: 1, version_rev: 0, id: ProviderId::MbedCrypto, }; list_providers.providers.push(provider_info); let body = CONVERTER .result_to_body(NativeResult::ListProviders(list_providers)) .expect("Failed to convert response"); assert!(!body.is_empty()); } #[test] fn list_providers_result_e2e() { let mut list_providers = Result { providers: Vec::new(), }; let provider_info = ProviderInfo { uuid: Uuid::parse_str("9840cd61-9367-4010-bc24-f5b98a6174d1").unwrap(), description: String::from("provider description"), vendor: String::from("Arm"), version_maj: 0, version_min: 1, version_rev: 0, id: ProviderId::MbedCrypto, }; list_providers.providers.push(provider_info); let body = CONVERTER .result_to_body(NativeResult::ListProviders(list_providers)) .expect("Failed to convert response"); assert!(!body.is_empty()); let result = CONVERTER .body_to_result(body, Opcode::ListProviders) .expect("Failed to convert back to result"); match result { NativeResult::ListProviders(result) => { assert_eq!(result.providers.len(), 1); } _ => panic!("Expected list_providers"), } } #[test] fn resp_from_native_mangled_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::ListProviders) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_ping.rs000064400000000000000000000121131046102023000230630ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::ping::{Operation as OperationProto, Result as ResultProto}; use crate::operations::ping::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(_proto_op: OperationProto) -> std::result::Result { Ok(Operation {}) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(_proto_op: Operation) -> std::result::Result { Ok(Default::default()) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { let proto_response = ResultProto { wire_protocol_version_maj: u32::from(result.wire_protocol_version_maj), wire_protocol_version_min: u32::from(result.wire_protocol_version_min), }; Ok(proto_response) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(response: ResultProto) -> std::result::Result { Ok(Result { wire_protocol_version_maj: u8::try_from(response.wire_protocol_version_maj)?, wire_protocol_version_min: u8::try_from(response.wire_protocol_version_min)?, }) } } #[cfg(test)] mod test { // Operation <-> Proto conversions are not tested since they're too simple use super::super::generated_ops::ping::Result as ResultProto; use super::super::{Convert, ProtobufConverter}; use crate::operations::ping::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn proto_to_resp() { let proto = ResultProto { wire_protocol_version_maj: 1, wire_protocol_version_min: 1, }; let resp: Result = proto.try_into().unwrap(); assert!(resp.wire_protocol_version_maj == 1); assert!(resp.wire_protocol_version_min == 1); } #[test] fn resp_to_proto() { let resp: Result = Result { wire_protocol_version_maj: 1, wire_protocol_version_min: 1, }; let proto: ResultProto = resp.try_into().unwrap(); assert!(proto.wire_protocol_version_maj == 1); assert!(proto.wire_protocol_version_min == 1); } #[test] fn ping_req_to_native() { let req_body = RequestBody::from_bytes(Vec::new()); assert!(CONVERTER.body_to_operation(req_body, Opcode::Ping).is_ok()); } #[test] fn op_ping_from_native() { let ping = Operation {}; let body = CONVERTER .operation_to_body(NativeOperation::Ping(ping)) .expect("Failed to convert request"); assert!(body.is_empty()); } #[test] fn op_ping_e2e() { let ping = Operation {}; let req_body = CONVERTER .operation_to_body(NativeOperation::Ping(ping)) .expect("Failed to convert request"); assert!(CONVERTER.body_to_operation(req_body, Opcode::Ping).is_ok()); } #[test] fn req_from_native_mangled_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER.body_to_operation(req_body, Opcode::Ping).is_err()); } #[test] fn ping_body_to_native() { let resp_body = ResponseBody::from_bytes(Vec::new()); assert!(CONVERTER.body_to_result(resp_body, Opcode::Ping).is_ok()); } #[test] fn result_ping_from_native() { let ping = Result { wire_protocol_version_maj: 1, wire_protocol_version_min: 0, }; let body = CONVERTER .result_to_body(NativeResult::Ping(ping)) .expect("Failed to convert response"); assert!(!body.is_empty()); } #[test] fn ping_result_e2e() { let ping = Result { wire_protocol_version_maj: 1, wire_protocol_version_min: 0, }; let body = CONVERTER .result_to_body(NativeResult::Ping(ping)) .expect("Failed to convert response"); assert!(!body.is_empty()); let result = CONVERTER .body_to_result(body, Opcode::Ping) .expect("Failed to convert back to result"); match result { NativeResult::Ping(result) => { assert_eq!(result.wire_protocol_version_maj, 1); assert_eq!(result.wire_protocol_version_min, 0); } _ => panic!("Expected ping"), } } #[test] fn resp_from_native_mangled_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER.body_to_result(resp_body, Opcode::Ping).is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_prepare_key_attestation.rs000064400000000000000000000314531046102023000270630ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::prepare_key_attestation::{ prepare_key_attestation_output, prepare_key_attestation_params, Operation as OperationProto, PrepareKeyAttestationOutput, PrepareKeyAttestationParams, Result as ResultProto, }; use crate::operations::prepare_key_attestation::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::TryFrom; impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { match op { Operation::ActivateCredential { attested_key_name, attesting_key_name, } => Ok(OperationProto { parameters: Some(PrepareKeyAttestationParams { mechanism: Some( prepare_key_attestation_params::Mechanism::ActivateCredential( prepare_key_attestation_params::ActivateCredential { attested_key_name, attesting_key_name: attesting_key_name.unwrap_or_default(), }, ), ), }), }), } } } impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(op: OperationProto) -> std::result::Result { match op { OperationProto { parameters: Some(PrepareKeyAttestationParams { mechanism: Some(prepare_key_attestation_params::Mechanism::ActivateCredential( prepare_key_attestation_params::ActivateCredential { attested_key_name, attesting_key_name, }, )), }), } => Ok(Operation::ActivateCredential { attested_key_name, attesting_key_name: if attesting_key_name.is_empty() { None } else { Some(attesting_key_name) }, }), _ => { error!("The encoding of the operation does not follow the expected pattern"); Err(ResponseStatus::InvalidEncoding) } } } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { match op { Result::ActivateCredential { name, public, attesting_key_pub, } => Ok(ResultProto { output: Some(PrepareKeyAttestationOutput { mechanism: Some( prepare_key_attestation_output::Mechanism::ActivateCredential( prepare_key_attestation_output::ActivateCredential { name: name.to_vec(), public: public.to_vec(), attesting_key_pub: attesting_key_pub.to_vec(), }, ), ), }), }), } } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(op: ResultProto) -> std::result::Result { match op { ResultProto { output: Some(PrepareKeyAttestationOutput { mechanism: Some(prepare_key_attestation_output::Mechanism::ActivateCredential( prepare_key_attestation_output::ActivateCredential { name, public, attesting_key_pub, }, )), }), } => Ok(Result::ActivateCredential { name: name.into(), public: public.into(), attesting_key_pub: attesting_key_pub.into(), }), _ => { error!("The encoding of the operation does not follow the expected pattern"); Err(ResponseStatus::InvalidEncoding) } } } } #[cfg(test)] mod test { use super::super::generated_ops::prepare_key_attestation::{ prepare_key_attestation_output, prepare_key_attestation_params, Operation as OperationProto, PrepareKeyAttestationOutput, PrepareKeyAttestationParams, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::{ prepare_key_attestation::Operation, prepare_key_attestation::Result, NativeOperation, NativeResult, }; use crate::requests::Opcode; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn prepare_key_attestation_op_from_proto() { let op_attested_key_name = String::from("attested key name"); let op_attesting_key_name = String::from("attesting key name"); let proto = OperationProto { parameters: Some(PrepareKeyAttestationParams { mechanism: Some( prepare_key_attestation_params::Mechanism::ActivateCredential( prepare_key_attestation_params::ActivateCredential { attested_key_name: op_attested_key_name.clone(), attesting_key_name: op_attesting_key_name.clone(), }, ), ), }), }; let op: Operation = proto.try_into().expect("Conversion failed"); let Operation::ActivateCredential { attested_key_name, attesting_key_name, } = op; assert_eq!(attested_key_name, op_attested_key_name); assert_eq!( attesting_key_name.expect("Attesting key name was empty"), op_attesting_key_name ); } #[test] fn prepare_key_attestation_proto_no_attesting() { let op_attested_key_name = String::from("attested key name"); let proto = OperationProto { parameters: Some(PrepareKeyAttestationParams { mechanism: Some( prepare_key_attestation_params::Mechanism::ActivateCredential( prepare_key_attestation_params::ActivateCredential { attested_key_name: op_attested_key_name, attesting_key_name: String::new(), }, ), ), }), }; let op: Operation = proto.try_into().expect("Conversion failed"); let Operation::ActivateCredential { attesting_key_name, .. } = op; assert!(attesting_key_name.is_none()); } #[test] fn prepare_key_attestation_op_to_proto() { let op_attested_key_name = String::from("attested key name"); let op_attesting_key_name = String::from("attesting key name"); let op: Operation = Operation::ActivateCredential { attested_key_name: op_attested_key_name.clone(), attesting_key_name: Some(op_attesting_key_name.clone()), }; let proto: OperationProto = op.try_into().expect("Conversion failed"); if let OperationProto { parameters: Some(PrepareKeyAttestationParams { mechanism: Some(prepare_key_attestation_params::Mechanism::ActivateCredential( prepare_key_attestation_params::ActivateCredential { attested_key_name, attesting_key_name, }, )), }), } = proto { assert_eq!(attested_key_name, op_attested_key_name); assert_eq!(attesting_key_name, op_attesting_key_name); } } #[test] fn prepare_key_attestation_op_no_attesting() { let op_attested_key_name = String::from("attested key name"); let op: Operation = Operation::ActivateCredential { attested_key_name: op_attested_key_name, attesting_key_name: None, }; let proto: OperationProto = op.try_into().expect("Conversion failed"); if let OperationProto { parameters: Some(PrepareKeyAttestationParams { mechanism: Some(prepare_key_attestation_params::Mechanism::ActivateCredential( prepare_key_attestation_params::ActivateCredential { attesting_key_name, .. }, )), }), } = proto { assert_eq!(attesting_key_name, String::new()); } } #[test] fn prepare_key_attestation_op_e2e() { let op_attested_key_name = String::from("attested key name"); let op_attesting_key_name = String::from("attesting key name"); let op: Operation = Operation::ActivateCredential { attested_key_name: op_attested_key_name, attesting_key_name: Some(op_attesting_key_name), }; let body = CONVERTER .operation_to_body(NativeOperation::PrepareKeyAttestation(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PrepareKeyAttestation) .expect("Failed to convert to operation"); } #[test] fn prepare_key_attestation_resp_to_proto() { let resp_name = vec![0xff; 32]; let resp_public = vec![0xcc; 32]; let resp_attesting_key_pub = vec![0x22; 32]; let result = Result::ActivateCredential { name: resp_name.clone().into(), public: resp_public.clone().into(), attesting_key_pub: resp_attesting_key_pub.clone().into(), }; let proto: ResultProto = result.try_into().expect("Conversion failed"); if let ResultProto { output: Some(PrepareKeyAttestationOutput { mechanism: Some(prepare_key_attestation_output::Mechanism::ActivateCredential( prepare_key_attestation_output::ActivateCredential { name, public, attesting_key_pub, }, )), }), } = proto { assert_eq!(name, resp_name); assert_eq!(public, resp_public); assert_eq!(attesting_key_pub, resp_attesting_key_pub); } } #[test] fn prepare_key_attestation_resp_from_proto() { let resp_name = vec![0xff; 32]; let resp_public = vec![0xcc; 32]; let resp_attesting_key_pub = vec![0x22; 32]; let proto = ResultProto { output: Some(PrepareKeyAttestationOutput { mechanism: Some( prepare_key_attestation_output::Mechanism::ActivateCredential( prepare_key_attestation_output::ActivateCredential { name: resp_name.clone(), public: resp_public.clone(), attesting_key_pub: resp_attesting_key_pub.clone(), }, ), ), }), }; let result: Result = proto.try_into().expect("Conversion failed"); let Result::ActivateCredential { name, public, attesting_key_pub, } = result; assert_eq!(name.to_vec(), resp_name); assert_eq!(public.to_vec(), resp_public); assert_eq!(attesting_key_pub.to_vec(), resp_attesting_key_pub); } #[test] fn prepare_key_attestation_resp_e2e() { let resp_name = vec![0xff; 32]; let resp_public = vec![0xcc; 32]; let resp_attesting_key_pub = vec![0x22; 32]; let result = Result::ActivateCredential { name: resp_name.into(), public: resp_public.into(), attesting_key_pub: resp_attesting_key_pub.into(), }; let body = CONVERTER .result_to_body(NativeResult::PrepareKeyAttestation(result)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_result(body, Opcode::PrepareKeyAttestation) .expect("Failed to convert to operation"); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_aead_decrypt.rs000064400000000000000000000154711046102023000254270ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_aead_decrypt::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_aead_decrypt::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of PsaAeadDecrypt::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, additional_data: proto_op.additional_data.into(), ciphertext: proto_op.ciphertext.into(), nonce: proto_op.nonce.into(), }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); Ok(OperationProto { key_name: op.key_name, alg, additional_data: op.additional_data.to_vec(), ciphertext: op.ciphertext.to_vec(), nonce: op.nonce.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { plaintext: proto_result.plaintext.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { plaintext: result.plaintext.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_aead_decrypt::{ Operation as OperationProto, Result as ResultProto, }; use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_aead_decrypt::{Operation, Result}; use crate::operations::psa_algorithm::AeadWithDefaultLengthTag; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; #[test] fn aead_proto_to_op() { let mut proto: OperationProto = Default::default(); let ciphertext = vec![0x11, 0x22, 0x33]; let additional_data = vec![0x66, 0x77, 0x88]; let key_name = "test name".to_string(); let nonce: Vec = vec![0x55; 12]; proto.ciphertext = ciphertext.clone(); proto.alg = Some(algorithm_proto::algorithm::Aead { variant: Some( algorithm_proto::algorithm::aead::Variant::AeadWithDefaultLengthTag( algorithm_proto::algorithm::aead::AeadWithDefaultLengthTag::Ccm.into(), ), ), }); proto.key_name = key_name.clone(); proto.nonce = nonce.clone(); proto.additional_data = additional_data.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(*op.ciphertext, ciphertext); assert_eq!(op.key_name, key_name); assert_eq!(*op.additional_data, additional_data); assert_eq!(*op.nonce, nonce); assert_eq!(op.alg, AeadWithDefaultLengthTag::Ccm.into()); } #[test] fn aead_op_to_proto() { let ciphertext = vec![0x11, 0x22, 0x33]; let additional_data = vec![0x55, 0x66, 0x77]; let nonce: Vec = vec![0x55; 12]; let key_name = "test name".to_string(); let op = Operation { ciphertext: ciphertext.clone().into(), alg: AeadWithDefaultLengthTag::Ccm.into(), key_name: key_name.clone(), nonce: nonce.clone().into(), additional_data: additional_data.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.ciphertext, ciphertext); assert_eq!(proto.key_name, key_name); assert_eq!(proto.nonce, nonce); assert_eq!(proto.additional_data, additional_data); } #[test] fn aead_proto_to_resp() { let mut proto: ResultProto = Default::default(); let plaintext = vec![0x11, 0x22, 0x33]; proto.plaintext = plaintext.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(*result.plaintext, plaintext); } #[test] fn aead_resp_to_proto() { let plaintext = vec![0x11, 0x22, 0x33]; let result = Result { plaintext: plaintext.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.plaintext, plaintext); } #[test] fn psa_decrypt_message_op_e2e() { let ciphertext = vec![0x11, 0x22, 0x33]; let additional_data = vec![0x55, 0x66, 0x77]; let nonce: Vec = vec![0x55; 12]; let key_name = "test name".to_string(); let op = Operation { ciphertext: ciphertext.into(), alg: AeadWithDefaultLengthTag::Ccm.into(), key_name, nonce: nonce.into(), additional_data: additional_data.into(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaAeadDecrypt(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaAeadDecrypt) .expect("Failed to convert to operation"); } #[test] fn resp_aead_decrypt_e2e() { let result = Result { plaintext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaAeadDecrypt(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaAeadDecrypt) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaAeadDecrypt) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaAeadDecrypt) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_aead_encrypt.rs000064400000000000000000000154701046102023000254400ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_aead_encrypt::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_aead_encrypt::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of PsaAeadEncrypt::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, additional_data: proto_op.additional_data.into(), plaintext: proto_op.plaintext.into(), nonce: proto_op.nonce.into(), }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); Ok(OperationProto { key_name: op.key_name, alg, additional_data: op.additional_data.to_vec(), plaintext: op.plaintext.to_vec(), nonce: op.nonce.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { ciphertext: proto_result.ciphertext.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { ciphertext: result.ciphertext.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_aead_encrypt::{ Operation as OperationProto, Result as ResultProto, }; use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_aead_encrypt::{Operation, Result}; use crate::operations::psa_algorithm::AeadWithDefaultLengthTag; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; #[test] fn aead_proto_to_op() { let mut proto: OperationProto = Default::default(); let plaintext = vec![0x11, 0x22, 0x33]; let additional_data = vec![0x66, 0x77, 0x88]; let key_name = "test name".to_string(); let nonce: Vec = vec![0x55; 12]; proto.plaintext = plaintext.clone(); proto.alg = Some(algorithm_proto::algorithm::Aead { variant: Some( algorithm_proto::algorithm::aead::Variant::AeadWithDefaultLengthTag( algorithm_proto::algorithm::aead::AeadWithDefaultLengthTag::Ccm.into(), ), ), }); proto.key_name = key_name.clone(); proto.nonce = nonce.clone(); proto.additional_data = additional_data.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(*op.plaintext, plaintext); assert_eq!(op.key_name, key_name); assert_eq!(*op.additional_data, additional_data); assert_eq!(*op.nonce, nonce); assert_eq!(op.alg, AeadWithDefaultLengthTag::Ccm.into()); } #[test] fn aead_op_to_proto() { let plaintext = vec![0x11, 0x22, 0x33]; let additional_data = vec![0x55, 0x66, 0x77]; let nonce: Vec = vec![0x55; 12]; let key_name = "test name".to_string(); let op = Operation { plaintext: plaintext.clone().into(), alg: AeadWithDefaultLengthTag::Ccm.into(), key_name: key_name.clone(), nonce: nonce.clone().into(), additional_data: additional_data.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.plaintext, plaintext); assert_eq!(proto.key_name, key_name); assert_eq!(proto.nonce, nonce); assert_eq!(proto.additional_data, additional_data); } #[test] fn aead_proto_to_resp() { let mut proto: ResultProto = Default::default(); let ciphertext = vec![0x11, 0x22, 0x33]; proto.ciphertext = ciphertext.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(*result.ciphertext, ciphertext); } #[test] fn aead_resp_to_proto() { let ciphertext = vec![0x11, 0x22, 0x33]; let result = Result { ciphertext: ciphertext.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.ciphertext, ciphertext); } #[test] fn psa_encrypt_message_op_e2e() { let plaintext = vec![0x11, 0x22, 0x33]; let additional_data = vec![0x55, 0x66, 0x77]; let nonce: Vec = vec![0x55; 12]; let key_name = "test name".to_string(); let op = Operation { plaintext: plaintext.into(), alg: AeadWithDefaultLengthTag::Ccm.into(), key_name, nonce: nonce.into(), additional_data: additional_data.into(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaAeadEncrypt(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaAeadEncrypt) .expect("Failed to convert to operation"); } #[test] fn resp_aead_encrypt_e2e() { let result = Result { ciphertext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaAeadEncrypt(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaAeadEncrypt) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaAeadEncrypt) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaAeadEncrypt) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_algorithm.rs000064400000000000000000000763131046102023000247730ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 // Protobuf imports use super::generated_ops::psa_algorithm::algorithm; use super::generated_ops::psa_algorithm::algorithm::aead; use super::generated_ops::psa_algorithm::algorithm::aead::AeadWithDefaultLengthTag as AeadWithDefaultLengthTagProto; use super::generated_ops::psa_algorithm::algorithm::asymmetric_encryption; use super::generated_ops::psa_algorithm::algorithm::asymmetric_signature; use super::generated_ops::psa_algorithm::algorithm::asymmetric_signature::sign_hash; use super::generated_ops::psa_algorithm::algorithm::asymmetric_signature::SignHash as SignHashProto; use super::generated_ops::psa_algorithm::algorithm::key_agreement; use super::generated_ops::psa_algorithm::algorithm::key_agreement::Raw as RawKeyAgreementProto; use super::generated_ops::psa_algorithm::algorithm::key_derivation; use super::generated_ops::psa_algorithm::algorithm::Aead as AeadProto; use super::generated_ops::psa_algorithm::algorithm::AsymmetricEncryption as AsymmetricEncryptionProto; use super::generated_ops::psa_algorithm::algorithm::AsymmetricSignature as AsymmetricSignatureProto; use super::generated_ops::psa_algorithm::algorithm::Cipher as CipherProto; use super::generated_ops::psa_algorithm::algorithm::Hash as HashProto; use super::generated_ops::psa_algorithm::algorithm::KeyAgreement as KeyAgreementProto; use super::generated_ops::psa_algorithm::algorithm::KeyDerivation as KeyDerivationProto; use super::generated_ops::psa_algorithm::algorithm::Mac as MacProto; use super::generated_ops::psa_algorithm::algorithm::None as NoneProto; use super::generated_ops::psa_algorithm::algorithm::{mac, mac::FullLength as FullLengthMacProto}; use super::generated_ops::psa_algorithm::Algorithm as AlgorithmProto; // Native imports use crate::operations::psa_algorithm::{ Aead, AeadWithDefaultLengthTag, Algorithm, AsymmetricEncryption, AsymmetricSignature, Cipher, FullLengthMac, Hash, KeyAgreement, KeyDerivation, Mac, RawKeyAgreement, SignHash, }; use crate::requests::{ResponseStatus, Result}; use log::error; use std::convert::{TryFrom, TryInto}; // Hash algorithms: from protobuf to native impl TryFrom for Hash { type Error = ResponseStatus; fn try_from(hash_val: HashProto) -> Result { match hash_val { HashProto::None => { error!("The None value of Hash enumeration is not allowed (mandatory field)."); Err(ResponseStatus::InvalidEncoding) } #[allow(deprecated)] HashProto::Md2 => Ok(Hash::Md2), #[allow(deprecated)] HashProto::Md4 => Ok(Hash::Md4), #[allow(deprecated)] HashProto::Md5 => Ok(Hash::Md5), HashProto::Ripemd160 => Ok(Hash::Ripemd160), #[allow(deprecated)] HashProto::Sha1 => Ok(Hash::Sha1), HashProto::Sha224 => Ok(Hash::Sha224), HashProto::Sha256 => Ok(Hash::Sha256), HashProto::Sha384 => Ok(Hash::Sha384), HashProto::Sha512 => Ok(Hash::Sha512), HashProto::Sha512224 => Ok(Hash::Sha512_224), HashProto::Sha512256 => Ok(Hash::Sha512_256), HashProto::Sha3224 => Ok(Hash::Sha3_224), HashProto::Sha3256 => Ok(Hash::Sha3_256), HashProto::Sha3384 => Ok(Hash::Sha3_384), HashProto::Sha3512 => Ok(Hash::Sha3_512), } } } // Hash algorithms: from protobuf to native pub fn i32_to_hash(hash_val: i32) -> Result { let hash_proto_alg: HashProto = hash_val.try_into()?; hash_proto_alg.try_into() } // Hash algorithms: from native to protobuf pub fn hash_to_i32(hash: Hash) -> i32 { match hash { #[allow(deprecated)] Hash::Md2 => HashProto::Md2.into(), #[allow(deprecated)] Hash::Md4 => HashProto::Md4.into(), #[allow(deprecated)] Hash::Md5 => HashProto::Md5.into(), Hash::Ripemd160 => HashProto::Ripemd160.into(), #[allow(deprecated)] Hash::Sha1 => HashProto::Sha1.into(), Hash::Sha224 => HashProto::Sha224.into(), Hash::Sha256 => HashProto::Sha256.into(), Hash::Sha384 => HashProto::Sha384.into(), Hash::Sha512 => HashProto::Sha512.into(), Hash::Sha512_224 => HashProto::Sha512224.into(), Hash::Sha512_256 => HashProto::Sha512256.into(), Hash::Sha3_224 => HashProto::Sha3224.into(), Hash::Sha3_256 => HashProto::Sha3256.into(), Hash::Sha3_384 => HashProto::Sha3384.into(), Hash::Sha3_512 => HashProto::Sha3512.into(), } } impl TryFrom for SignHash { type Error = ResponseStatus; fn try_from(sign_hash_val: SignHashProto) -> Result { match sign_hash_val.variant.ok_or_else(|| { error!("The SignHash variant used is not supported."); ResponseStatus::InvalidEncoding })? { sign_hash::Variant::Any(_) => Ok(SignHash::Any), sign_hash::Variant::Specific(hash_val) => Ok(SignHash::Specific( HashProto::try_from(hash_val)?.try_into()?, )), } } } impl From for SignHashProto { fn from(sign_hash: SignHash) -> Self { match sign_hash { SignHash::Any => SignHashProto { variant: Some(sign_hash::Variant::Any(sign_hash::Any {})), }, SignHash::Specific(hash) => SignHashProto { variant: Some(sign_hash::Variant::Specific(hash_to_i32(hash))), }, } } } // FullLengthMac algorithms: from protobuf to native impl TryFrom for FullLengthMac { type Error = ResponseStatus; fn try_from(alg: FullLengthMacProto) -> Result { match alg.variant.ok_or_else(|| { error!("The FullLengthMac variant used is not supported."); ResponseStatus::InvalidEncoding })? { mac::full_length::Variant::Hmac(hmac) => Ok(FullLengthMac::Hmac { hash_alg: HashProto::try_from(hmac.hash_alg)?.try_into()?, }), mac::full_length::Variant::CbcMac(_) => Ok(FullLengthMac::CbcMac), mac::full_length::Variant::Cmac(_) => Ok(FullLengthMac::Cmac), } } } // FullLengthMac algorithms: from native to protobuf impl TryFrom for FullLengthMacProto { type Error = ResponseStatus; fn try_from(alg: FullLengthMac) -> Result { match alg { FullLengthMac::Hmac { hash_alg } => Ok(FullLengthMacProto { variant: Some(mac::full_length::Variant::Hmac(mac::full_length::Hmac { hash_alg: hash_to_i32(hash_alg), })), }), FullLengthMac::CbcMac => Ok(FullLengthMacProto { variant: Some(mac::full_length::Variant::CbcMac( mac::full_length::CbcMac {}, )), }), FullLengthMac::Cmac => Ok(FullLengthMacProto { variant: Some(mac::full_length::Variant::Cmac(mac::full_length::Cmac {})), }), } } } // Mac algorithms: from protobuf to native impl TryFrom for Mac { type Error = ResponseStatus; fn try_from(alg: MacProto) -> Result { match alg.variant.ok_or_else(|| { error!("The Mac variant used is not supported."); ResponseStatus::InvalidEncoding })? { mac::Variant::FullLength(full_length) => Ok(Mac::FullLength(full_length.try_into()?)), mac::Variant::Truncated(truncated) => Ok(Mac::Truncated { mac_alg: truncated.mac_alg.ok_or_else(|| { error!("The mac_alg field of mac::Truncated message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })?.try_into()?, mac_length: truncated.mac_length.try_into().map_err(|e| { error!("mac_length field of mac::Truncated message can not be represented by an usize ({}).", e); ResponseStatus::InvalidEncoding })?, }), } } } // Mac algorithms: from native to protobuf impl TryFrom for MacProto { type Error = ResponseStatus; fn try_from(alg: Mac) -> Result { match alg { Mac::FullLength(full_length_mac) => Ok(MacProto { variant: Some(mac::Variant::FullLength(full_length_mac.try_into()?)), }), Mac::Truncated { mac_alg, mac_length, } => Ok(MacProto { variant: Some(mac::Variant::Truncated(mac::Truncated { mac_alg: Some(mac_alg.try_into()?), mac_length: mac_length.try_into().map_err(|e| { error!( "mac_length field of Mac can not be represented by an u32 ({}).", e ); ResponseStatus::InvalidEncoding })?, })), }), } } } // Cipher algorithms: from protobuf to native impl TryFrom for Cipher { type Error = ResponseStatus; fn try_from(cipher_val: CipherProto) -> Result { match cipher_val { CipherProto::None => { error!("The None value of Cipher enumeration is not allowed (mandatory field)."); Err(ResponseStatus::InvalidEncoding) } CipherProto::StreamCipher => Ok(Cipher::StreamCipher), CipherProto::Ctr => Ok(Cipher::Ctr), CipherProto::Cfb => Ok(Cipher::Cfb), CipherProto::Ofb => Ok(Cipher::Ofb), CipherProto::Xts => Ok(Cipher::Xts), CipherProto::EcbNoPadding => Ok(Cipher::EcbNoPadding), CipherProto::CbcNoPadding => Ok(Cipher::CbcNoPadding), CipherProto::CbcPkcs7 => Ok(Cipher::CbcPkcs7), } } } // Cipher algorithms: from protobuf to native pub fn i32_to_cipher(cipher_val: i32) -> Result { let cipher_proto_alg: CipherProto = cipher_val.try_into()?; cipher_proto_alg.try_into() } // Cipher algorithms: from native to protobuf pub fn cipher_to_i32(cipher: Cipher) -> i32 { match cipher { Cipher::StreamCipher => CipherProto::StreamCipher.into(), Cipher::Ctr => CipherProto::Ctr.into(), Cipher::Cfb => CipherProto::Cfb.into(), Cipher::Ofb => CipherProto::Ofb.into(), Cipher::Xts => CipherProto::Xts.into(), Cipher::EcbNoPadding => CipherProto::EcbNoPadding.into(), Cipher::CbcNoPadding => CipherProto::CbcNoPadding.into(), Cipher::CbcPkcs7 => CipherProto::CbcPkcs7.into(), } } // AeadWithDefaultLengthTag algorithms: from protobuf to native impl TryFrom for AeadWithDefaultLengthTag { type Error = ResponseStatus; fn try_from(aead_val: AeadWithDefaultLengthTagProto) -> Result { match aead_val { AeadWithDefaultLengthTagProto::None => { error!("The None value of AeadWithDefaultLengthTag enumeration is not allowed (mandatory field)."); Err(ResponseStatus::InvalidEncoding) } AeadWithDefaultLengthTagProto::Ccm => Ok(AeadWithDefaultLengthTag::Ccm), AeadWithDefaultLengthTagProto::Gcm => Ok(AeadWithDefaultLengthTag::Gcm), AeadWithDefaultLengthTagProto::Chacha20Poly1305 => { Ok(AeadWithDefaultLengthTag::Chacha20Poly1305) } } } } // AeadWithDefaultLengthTag algorithms: from native to protobuf fn aead_with_default_length_tag_to_i32(cipher: AeadWithDefaultLengthTag) -> i32 { match cipher { AeadWithDefaultLengthTag::Ccm => AeadWithDefaultLengthTagProto::Ccm.into(), AeadWithDefaultLengthTag::Gcm => AeadWithDefaultLengthTagProto::Gcm.into(), AeadWithDefaultLengthTag::Chacha20Poly1305 => { AeadWithDefaultLengthTagProto::Chacha20Poly1305.into() } } } // Aead algorithms: from protobuf to native impl TryFrom for Aead { type Error = ResponseStatus; fn try_from(alg: AeadProto) -> Result { match alg.variant.ok_or_else(|| { error!("The Aead variant used is not supported."); ResponseStatus::InvalidEncoding })? { aead::Variant::AeadWithDefaultLengthTag(aead_with_default_length_tag) => { Ok(Aead::AeadWithDefaultLengthTag(AeadWithDefaultLengthTagProto::try_from(aead_with_default_length_tag)?.try_into()?)) }, aead::Variant::AeadWithShortenedTag(aead_with_shortened_tag) => Ok(Aead::AeadWithShortenedTag { aead_alg: AeadWithDefaultLengthTagProto::try_from(aead_with_shortened_tag.aead_alg)?.try_into()?, tag_length: aead_with_shortened_tag.tag_length.try_into().map_err(|e| { error!("tag_length field of aead::AeadWithShortenedTag can not be represented by an usize ({}).", e); ResponseStatus::InvalidEncoding })?, }), } } } // Aead algorithms: from native to protobuf impl TryFrom for AeadProto { type Error = ResponseStatus; fn try_from(alg: Aead) -> Result { match alg { Aead::AeadWithDefaultLengthTag(aead_with_default_length_tag) => Ok(AeadProto { variant: Some(aead::Variant::AeadWithDefaultLengthTag(aead_with_default_length_tag_to_i32(aead_with_default_length_tag))), }), Aead::AeadWithShortenedTag { aead_alg, tag_length } => Ok(AeadProto { variant: Some(aead::Variant::AeadWithShortenedTag(aead::AeadWithShortenedTag { aead_alg: aead_with_default_length_tag_to_i32(aead_alg), tag_length: tag_length.try_into().map_err(|e| { error!("tag_length field of Aead::AeadWithShortenedTag can not be represented by an u32 ({}).", e); ResponseStatus::InvalidEncoding })?, })), }), } } } // AsymmetricSignature algorithms: from protobuf to native impl TryFrom for AsymmetricSignature { type Error = ResponseStatus; fn try_from(alg: AsymmetricSignatureProto) -> Result { match alg.variant.ok_or_else(|| { error!("The AsymmetricSignature variant used is not supported."); ResponseStatus::InvalidEncoding })? { asymmetric_signature::Variant::RsaPkcs1v15Sign(rsa_pkcs1v15_sign) => { Ok(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: rsa_pkcs1v15_sign .hash_alg .ok_or_else(|| { error!("The hash_alg field of RsaPkcs1v15Sign message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, }) } asymmetric_signature::Variant::RsaPkcs1v15SignRaw(_) => { Ok(AsymmetricSignature::RsaPkcs1v15SignRaw) } asymmetric_signature::Variant::RsaPss(rsa_pss) => Ok(AsymmetricSignature::RsaPss { hash_alg: rsa_pss .hash_alg .ok_or_else(|| { error!("The hash_alg field of RsaPss message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, }), asymmetric_signature::Variant::Ecdsa(ecdsa) => Ok(AsymmetricSignature::Ecdsa { hash_alg: ecdsa .hash_alg .ok_or_else(|| { error!("The hash_alg field of Ecdsa message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, }), asymmetric_signature::Variant::EcdsaAny(_) => Ok(AsymmetricSignature::EcdsaAny), asymmetric_signature::Variant::DeterministicEcdsa(deterministic_ecdsa) => { Ok(AsymmetricSignature::DeterministicEcdsa { hash_alg: deterministic_ecdsa .hash_alg .ok_or_else(|| { error!("The hash_alg field of DeterministicEcdsa message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, }) } } } } // AsymmetricSignature algorithms: from native to protobuf impl TryFrom for AsymmetricSignatureProto { type Error = ResponseStatus; fn try_from(alg: AsymmetricSignature) -> Result { match alg { AsymmetricSignature::RsaPkcs1v15Sign { hash_alg } => Ok(AsymmetricSignatureProto { variant: Some(asymmetric_signature::Variant::RsaPkcs1v15Sign( asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(hash_alg.into()), }, )), }), AsymmetricSignature::RsaPkcs1v15SignRaw => Ok(AsymmetricSignatureProto { variant: Some(asymmetric_signature::Variant::RsaPkcs1v15SignRaw( asymmetric_signature::RsaPkcs1v15SignRaw {}, )), }), AsymmetricSignature::RsaPss { hash_alg } => Ok(AsymmetricSignatureProto { variant: Some(asymmetric_signature::Variant::RsaPss( asymmetric_signature::RsaPss { hash_alg: Some(hash_alg.into()), }, )), }), AsymmetricSignature::Ecdsa { hash_alg } => Ok(AsymmetricSignatureProto { variant: Some(asymmetric_signature::Variant::Ecdsa( asymmetric_signature::Ecdsa { hash_alg: Some(hash_alg.into()), }, )), }), AsymmetricSignature::EcdsaAny => Ok(AsymmetricSignatureProto { variant: Some(asymmetric_signature::Variant::EcdsaAny( asymmetric_signature::EcdsaAny {}, )), }), AsymmetricSignature::DeterministicEcdsa { hash_alg } => Ok(AsymmetricSignatureProto { variant: Some(asymmetric_signature::Variant::DeterministicEcdsa( asymmetric_signature::DeterministicEcdsa { hash_alg: Some(hash_alg.into()), }, )), }), } } } // AsymmetricEncryption algorithms: from protobuf to native impl TryFrom for AsymmetricEncryption { type Error = ResponseStatus; fn try_from(alg: AsymmetricEncryptionProto) -> Result { match alg.variant.ok_or_else(|| { error!("The AsymmetricSignature variant used is not supported."); ResponseStatus::InvalidEncoding })? { asymmetric_encryption::Variant::RsaPkcs1v15Crypt(_) => { Ok(AsymmetricEncryption::RsaPkcs1v15Crypt) } asymmetric_encryption::Variant::RsaOaep(rsa_oaep) => { Ok(AsymmetricEncryption::RsaOaep { hash_alg: HashProto::try_from(rsa_oaep.hash_alg)?.try_into()?, }) } } } } // AsymmetricEncryption algorithms: from native to protobuf impl TryFrom for AsymmetricEncryptionProto { type Error = ResponseStatus; fn try_from(alg: AsymmetricEncryption) -> Result { match alg { AsymmetricEncryption::RsaPkcs1v15Crypt => Ok(AsymmetricEncryptionProto { variant: Some(asymmetric_encryption::Variant::RsaPkcs1v15Crypt( asymmetric_encryption::RsaPkcs1v15Crypt {}, )), }), AsymmetricEncryption::RsaOaep { hash_alg } => Ok(AsymmetricEncryptionProto { variant: Some(asymmetric_encryption::Variant::RsaOaep( asymmetric_encryption::RsaOaep { hash_alg: hash_to_i32(hash_alg), }, )), }), } } } // RawKeyAgreement algorithms: from protobuf to native impl TryFrom for RawKeyAgreement { type Error = ResponseStatus; fn try_from(raw_key_agreement_val: RawKeyAgreementProto) -> Result { match raw_key_agreement_val { RawKeyAgreementProto::None => { error!("The None value of RawKeyAgreement enumeration is not allowed (mandatory field)."); Err(ResponseStatus::InvalidEncoding) } RawKeyAgreementProto::Ffdh => Ok(RawKeyAgreement::Ffdh), RawKeyAgreementProto::Ecdh => Ok(RawKeyAgreement::Ecdh), } } } // RawKeyAgreement algorithms: from native to protobuf pub fn raw_key_agreement_to_i32(raw_key_agreement: RawKeyAgreement) -> i32 { match raw_key_agreement { RawKeyAgreement::Ffdh => RawKeyAgreementProto::Ffdh.into(), RawKeyAgreement::Ecdh => RawKeyAgreementProto::Ecdh.into(), } } // RawKeyAgreement algorithms: from protobuf to native pub fn i32_to_raw_key_agreement(raw_key_agreement_val: i32) -> Result { let raw_key_agreement_alg: RawKeyAgreementProto = raw_key_agreement_val.try_into()?; raw_key_agreement_alg.try_into() } // KeyAgreement algorithms: from protobuf to native impl TryFrom for KeyAgreement { type Error = ResponseStatus; fn try_from(alg: KeyAgreementProto) -> Result { match alg.variant.ok_or_else(|| { error!("The KeyAgreement variant used is not supported."); ResponseStatus::InvalidEncoding })? { key_agreement::Variant::Raw(raw) => Ok(KeyAgreement::Raw(RawKeyAgreementProto::try_from(raw)?.try_into()?)), key_agreement::Variant::WithKeyDerivation(with_key_derivation) => Ok(KeyAgreement::WithKeyDerivation { ka_alg: RawKeyAgreementProto::try_from(with_key_derivation.ka_alg)?.try_into()?, kdf_alg: with_key_derivation.kdf_alg.ok_or_else(|| { error!("The kdf_alg field of key_agreement::WithKeyDerivation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })?.try_into()?, }), } } } // KeyAgreement algorithms: from native to protobuf impl TryFrom for KeyAgreementProto { type Error = ResponseStatus; fn try_from(alg: KeyAgreement) -> Result { match alg { KeyAgreement::Raw(raw_key_agreement) => Ok(KeyAgreementProto { variant: Some(key_agreement::Variant::Raw(raw_key_agreement_to_i32( raw_key_agreement, ))), }), KeyAgreement::WithKeyDerivation { ka_alg, kdf_alg } => Ok(KeyAgreementProto { variant: Some(key_agreement::Variant::WithKeyDerivation( key_agreement::WithKeyDerivation { ka_alg: raw_key_agreement_to_i32(ka_alg), kdf_alg: Some(kdf_alg.try_into()?), }, )), }), } } } // KeyDerivation algorithms: from protobuf to native impl TryFrom for KeyDerivation { type Error = ResponseStatus; fn try_from(alg: KeyDerivationProto) -> Result { match alg.variant.ok_or_else(|| { error!("The KeyDerivation variant used is not supported."); ResponseStatus::InvalidEncoding })? { key_derivation::Variant::Hkdf(hkdf) => Ok(KeyDerivation::Hkdf { hash_alg: HashProto::try_from(hkdf.hash_alg)?.try_into()?, }), key_derivation::Variant::Tls12Prf(tls12_prf) => Ok(KeyDerivation::Tls12Prf { hash_alg: HashProto::try_from(tls12_prf.hash_alg)?.try_into()?, }), key_derivation::Variant::Tls12PskToMs(tls12_psk_to_ms) => { Ok(KeyDerivation::Tls12PskToMs { hash_alg: HashProto::try_from(tls12_psk_to_ms.hash_alg)?.try_into()?, }) } } } } // KeyDerivation algorithms: from native to protobuf impl TryFrom for KeyDerivationProto { type Error = ResponseStatus; fn try_from(alg: KeyDerivation) -> Result { match alg { KeyDerivation::Hkdf { hash_alg } => Ok(KeyDerivationProto { variant: Some(key_derivation::Variant::Hkdf(key_derivation::Hkdf { hash_alg: hash_to_i32(hash_alg), })), }), KeyDerivation::Tls12Prf { hash_alg } => Ok(KeyDerivationProto { variant: Some(key_derivation::Variant::Tls12Prf( key_derivation::Tls12Prf { hash_alg: hash_to_i32(hash_alg), }, )), }), KeyDerivation::Tls12PskToMs { hash_alg } => Ok(KeyDerivationProto { variant: Some(key_derivation::Variant::Tls12PskToMs( key_derivation::Tls12PskToMs { hash_alg: hash_to_i32(hash_alg), }, )), }), } } } // Algorithm: from protobug to native impl TryFrom for Algorithm { type Error = ResponseStatus; fn try_from(alg: AlgorithmProto) -> Result { match alg.variant.ok_or_else(|| { error!("The Algorithm variant used is not supported."); ResponseStatus::InvalidEncoding })? { algorithm::Variant::None(_) => Ok(Algorithm::None), algorithm::Variant::Hash(hash) => { Ok(Algorithm::Hash(HashProto::try_from(hash)?.try_into()?)) } algorithm::Variant::Mac(mac) => Ok(Algorithm::Mac(mac.try_into()?)), algorithm::Variant::Cipher(cipher) => Ok(Algorithm::Cipher( CipherProto::try_from(cipher)?.try_into()?, )), algorithm::Variant::Aead(aead) => Ok(Algorithm::Aead(aead.try_into()?)), algorithm::Variant::AsymmetricSignature(asymmetric_signature) => Ok( Algorithm::AsymmetricSignature(asymmetric_signature.try_into()?), ), algorithm::Variant::AsymmetricEncryption(asymmetric_encryption) => Ok( Algorithm::AsymmetricEncryption(asymmetric_encryption.try_into()?), ), algorithm::Variant::KeyAgreement(key_agreement) => { Ok(Algorithm::KeyAgreement(key_agreement.try_into()?)) } algorithm::Variant::KeyDerivation(key_derivation) => { Ok(Algorithm::KeyDerivation(key_derivation.try_into()?)) } } } } // Algorithm: from native to protobuf impl TryFrom for AlgorithmProto { type Error = ResponseStatus; fn try_from(alg: Algorithm) -> Result { match alg { Algorithm::None => Ok(AlgorithmProto { variant: Some(algorithm::Variant::None(NoneProto {})), }), Algorithm::Hash(hash) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::Hash(hash_to_i32(hash))), }), Algorithm::Mac(mac) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::Mac(mac.try_into()?)), }), Algorithm::Cipher(cipher) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::Cipher(cipher_to_i32(cipher))), }), Algorithm::Aead(aead) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::Aead(aead.try_into()?)), }), Algorithm::AsymmetricSignature(asymmetric_signature) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::AsymmetricSignature( asymmetric_signature.try_into()?, )), }), Algorithm::AsymmetricEncryption(asymmetric_encryption) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::AsymmetricEncryption( asymmetric_encryption.try_into()?, )), }), Algorithm::KeyAgreement(key_agreement) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::KeyAgreement(key_agreement.try_into()?)), }), Algorithm::KeyDerivation(key_derivation) => Ok(AlgorithmProto { variant: Some(algorithm::Variant::KeyDerivation( key_derivation.try_into()?, )), }), } } } #[cfg(test)] mod test { #![allow(deprecated)] use super::super::generated_ops::psa_algorithm::{ self as algorithm_proto, algorithm::asymmetric_signature::{sign_hash, SignHash as SignHashProto}, Algorithm as AlgorithmProto, }; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use std::convert::TryInto; #[test] fn sign_algo_from_proto() { let proto_sign = algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature( algorithm_proto::algorithm::AsymmetricSignature { variant: Some( algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign( algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(SignHashProto { variant: Some(sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), }, ), ), }, )), }; let sign: Algorithm = proto_sign.try_into().unwrap(); let sign_expected = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }); assert_eq!(sign, sign_expected); } #[test] fn sign_algo_to_proto() { let sign = Algorithm::AsymmetricSignature(AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }); let proto_sign: AlgorithmProto = sign.try_into().unwrap(); let proto_sign_expected = algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature( algorithm_proto::algorithm::AsymmetricSignature { variant: Some( algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign( algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(SignHashProto { variant: Some(sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), }, ), ), }, )), }; assert_eq!(proto_sign, proto_sign_expected); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_asymmetric_decrypt.rs000064400000000000000000000146051046102023000267100ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_asymmetric_decrypt::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_asymmetric_decrypt::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; use zeroize::Zeroizing; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let salt = match proto_op.salt.len() { 0 => None, _ => Some(Zeroizing::new(proto_op.salt)), }; Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of PsaAsymmetricDecrypt::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, ciphertext: proto_op.ciphertext.into(), salt, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); let salt = match op.salt { Some(salt) => salt.to_vec(), None => vec![], }; Ok(OperationProto { key_name: op.key_name, alg, ciphertext: op.ciphertext.to_vec(), salt, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { plaintext: proto_result.plaintext.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { plaintext: result.plaintext.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_asymmetric_decrypt::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::AsymmetricEncryption; use crate::operations::psa_asymmetric_decrypt::{Operation, Result}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use zeroize::Zeroizing; #[test] fn asym_proto_to_op() { let mut proto: OperationProto = Default::default(); let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let salt: Vec = vec![]; proto.ciphertext = message.clone(); proto.alg = Some(algorithm_proto::algorithm::AsymmetricEncryption { variant: Some( algorithm_proto::algorithm::asymmetric_encryption::Variant::RsaPkcs1v15Crypt( algorithm_proto::algorithm::asymmetric_encryption::RsaPkcs1v15Crypt {}, ), ), }); proto.key_name = key_name.clone(); proto.salt = salt; let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.ciphertext.to_vec(), message); assert_eq!(op.key_name, key_name); assert_eq!(op.salt, None); } #[test] fn asym_op_to_proto() { let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let op = Operation { ciphertext: Zeroizing::new(message.clone()), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, key_name: key_name.clone(), salt: None, }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.ciphertext, message); assert_eq!(proto.key_name, key_name); assert_eq!(proto.salt, vec![]); } #[test] fn asym_proto_to_resp() { let mut proto: ResultProto = Default::default(); let plaintext: Vec = vec![0x11, 0x22, 0x33]; proto.plaintext = plaintext.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(*result.plaintext, plaintext); } #[test] fn asym_resp_to_proto() { let plaintext = vec![0x11, 0x22, 0x33]; let result = Result { plaintext: plaintext.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.plaintext, plaintext); } #[test] fn psa_decrypt_message_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, alg: AsymmetricEncryption::RsaPkcs1v15Crypt, ciphertext: Zeroizing::new(vec![0x11, 0x22, 0x33]), salt: None, }; let body = CONVERTER .operation_to_body(NativeOperation::PsaAsymmetricDecrypt(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaAsymmetricDecrypt) .expect("Failed to convert to operation"); } #[test] fn resp_asym_decrypt_e2e() { let result = Result { plaintext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaAsymmetricDecrypt(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaAsymmetricDecrypt) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaAsymmetricDecrypt) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaAsymmetricDecrypt) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_asymmetric_encrypt.rs000064400000000000000000000145141046102023000267210ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_asymmetric_encrypt::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_asymmetric_encrypt::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; use zeroize::Zeroizing; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let salt = match proto_op.salt.len() { 0 => None, _ => Some(Zeroizing::new(proto_op.salt)), }; Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of PsaAsymmetricEncrypt::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, plaintext: proto_op.plaintext.into(), salt, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); let salt = match op.salt { Some(salt) => salt.to_vec(), None => vec![], }; Ok(OperationProto { key_name: op.key_name, alg, plaintext: op.plaintext.to_vec(), salt, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { ciphertext: proto_result.ciphertext.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { ciphertext: result.ciphertext.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_asymmetric_encrypt::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::AsymmetricEncryption; use crate::operations::psa_asymmetric_encrypt::{Operation, Result}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; #[test] fn asym_proto_to_op() { let mut proto: OperationProto = Default::default(); let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let salt: Vec = vec![]; proto.plaintext = message.clone(); proto.alg = Some(algorithm_proto::algorithm::AsymmetricEncryption { variant: Some( algorithm_proto::algorithm::asymmetric_encryption::Variant::RsaPkcs1v15Crypt( algorithm_proto::algorithm::asymmetric_encryption::RsaPkcs1v15Crypt {}, ), ), }); proto.key_name = key_name.clone(); proto.salt = salt; let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(*op.plaintext, message); assert_eq!(op.key_name, key_name); assert_eq!(op.salt, None); } #[test] fn asym_op_to_proto() { let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let op = Operation { plaintext: message.clone().into(), alg: AsymmetricEncryption::RsaPkcs1v15Crypt, key_name: key_name.clone(), salt: None, }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.plaintext, message); assert_eq!(proto.key_name, key_name); assert_eq!(proto.salt, vec![]); } #[test] fn asym_proto_to_resp() { let mut proto: ResultProto = Default::default(); let ciphertext = vec![0x11, 0x22, 0x33]; proto.ciphertext = ciphertext.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(*result.ciphertext, ciphertext); } #[test] fn asym_resp_to_proto() { let ciphertext = vec![0x11, 0x22, 0x33]; let result = Result { ciphertext: ciphertext.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.ciphertext, ciphertext); } #[test] fn psa_encrypt_message_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, alg: AsymmetricEncryption::RsaPkcs1v15Crypt, plaintext: vec![0x11, 0x22, 0x33].into(), salt: None, }; let body = CONVERTER .operation_to_body(NativeOperation::PsaAsymmetricEncrypt(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaAsymmetricEncrypt) .expect("Failed to convert to operation"); } #[test] fn resp_asym_encrypt_e2e() { let result = Result { ciphertext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaAsymmetricEncrypt(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaAsymmetricEncrypt) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaAsymmetricEncrypt) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaAsymmetricEncrypt) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_cipher_decrypt.rs000064400000000000000000000126101046102023000257770ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::convert_psa_algorithm; use super::generated_ops::psa_cipher_decrypt::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_cipher_decrypt::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, alg: convert_psa_algorithm::i32_to_cipher(proto_op.alg)?, ciphertext: proto_op.ciphertext.into(), }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { key_name: op.key_name, alg: convert_psa_algorithm::cipher_to_i32(op.alg), ciphertext: op.ciphertext.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { plaintext: proto_result.plaintext.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { plaintext: result.plaintext.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_cipher_decrypt::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use super::convert_psa_algorithm; use crate::operations::psa_algorithm::Cipher; use crate::operations::psa_cipher_decrypt::{Operation, Result}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use zeroize::Zeroizing; #[test] fn cipher_proto_to_op() { let mut proto: OperationProto = Default::default(); let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let proto_alg = psa_crypto::types::algorithm::Cipher::StreamCipher; proto.ciphertext = message.clone(); proto.alg = convert_psa_algorithm::cipher_to_i32(proto_alg); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.ciphertext.to_vec(), message); assert_eq!(op.key_name, key_name); } #[test] fn cipher_op_to_proto() { let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let op = Operation { ciphertext: Zeroizing::new(message.clone()), alg: Cipher::StreamCipher, key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.ciphertext, message); assert_eq!(proto.key_name, key_name); } #[test] fn cipher_proto_to_resp() { let mut proto: ResultProto = Default::default(); let plaintext: Vec = vec![0x11, 0x22, 0x33]; proto.plaintext = plaintext.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(*result.plaintext, plaintext); } #[test] fn cipher_resp_to_proto() { let plaintext = vec![0x11, 0x22, 0x33]; let result = Result { plaintext: plaintext.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.plaintext, plaintext); } #[test] fn psa_decrypt_message_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, alg: Cipher::StreamCipher, ciphertext: Zeroizing::new(vec![0x11, 0x22, 0x33]), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaCipherDecrypt(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaCipherDecrypt) .expect("Failed to convert to operation"); } #[test] fn resp_cipher_decrypt_e2e() { let result = Result { plaintext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaCipherDecrypt(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaCipherDecrypt) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaCipherDecrypt) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaCipherDecrypt) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_cipher_encrypt.rs000064400000000000000000000125171046102023000260170ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::convert_psa_algorithm; use super::generated_ops::psa_cipher_encrypt::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_cipher_encrypt::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, alg: convert_psa_algorithm::i32_to_cipher(proto_op.alg)?, plaintext: proto_op.plaintext.into(), }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { key_name: op.key_name, alg: convert_psa_algorithm::cipher_to_i32(op.alg), plaintext: op.plaintext.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { ciphertext: proto_result.ciphertext.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { ciphertext: result.ciphertext.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_cipher_encrypt::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use super::convert_psa_algorithm; use crate::operations::psa_algorithm::Cipher; use crate::operations::psa_cipher_encrypt::{Operation, Result}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; #[test] fn cipher_proto_to_op() { let mut proto: OperationProto = Default::default(); let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let proto_alg = psa_crypto::types::algorithm::Cipher::StreamCipher; proto.plaintext = message.clone(); proto.alg = convert_psa_algorithm::cipher_to_i32(proto_alg); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(*op.plaintext, message); assert_eq!(op.key_name, key_name); } #[test] fn cipher_op_to_proto() { let message = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let op = Operation { plaintext: message.clone().into(), alg: Cipher::StreamCipher, key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.plaintext, message); assert_eq!(proto.key_name, key_name); } #[test] fn cipher_proto_to_resp() { let mut proto: ResultProto = Default::default(); let ciphertext = vec![0x11, 0x22, 0x33]; proto.ciphertext = ciphertext.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(*result.ciphertext, ciphertext); } #[test] fn cipher_resp_to_proto() { let ciphertext = vec![0x11, 0x22, 0x33]; let result = Result { ciphertext: ciphertext.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.ciphertext, ciphertext); } #[test] fn psa_encrypt_message_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, alg: Cipher::StreamCipher, plaintext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaCipherEncrypt(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaCipherEncrypt) .expect("Failed to convert to operation"); } #[test] fn resp_cipher_encrypt_e2e() { let result = Result { ciphertext: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaCipherEncrypt(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaCipherEncrypt) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaCipherEncrypt) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaCipherEncrypt) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_destroy_key.rs000064400000000000000000000070561046102023000253440ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_destroy_key::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_destroy_key::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { key_name: op.key_name, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_proto_result: ResultProto) -> std::result::Result { Ok(Result {}) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_result: Result) -> std::result::Result { Ok(ResultProto {}) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_destroy_key::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::{psa_destroy_key::Operation, psa_destroy_key::Result, NativeOperation}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn psa_destroy_key_proto_to_op() { let mut proto: OperationProto = Default::default(); let key_name = "test name".to_string(); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.key_name, key_name); } #[test] fn psa_destroy_key_op_to_proto() { let key_name = "test name".to_string(); let op = Operation { key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.key_name, key_name); } #[test] fn psa_destroy_key_proto_to_resp() { let proto: ResultProto = Default::default(); let _result: Result = proto.try_into().expect("Failed to convert"); } #[test] fn psa_destroy_key_resp_to_proto() { let result = Result {}; let _proto: ResultProto = result.try_into().expect("Failed to convert"); } #[test] fn op_psa_destroy_key_e2e() { let op = Operation { key_name: "test name".to_string(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaDestroyKey(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaDestroyKey) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaDestroyKey) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaDestroyKey) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_export_key.rs000064400000000000000000000106001046102023000251610ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_export_key::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_export_key::{Operation, Result}; use crate::requests::ResponseStatus; use secrecy::ExposeSecret; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { key_name: op.key_name, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { Ok(Result { data: secrecy::Secret::new(proto_op.data), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { Ok(ResultProto { data: op.data.expose_secret().to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_export_key::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::{ psa_export_key::Operation, psa_export_key::Result, NativeOperation, NativeResult, }; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use secrecy::{ExposeSecret, Secret}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn export_pk_proto_to_op() { let mut proto: OperationProto = Default::default(); let key_name = "test name".to_string(); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.key_name, key_name); } #[test] fn asym_op_to_proto() { let key_name = "test name".to_string(); let op = Operation { key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.key_name, key_name); } #[test] fn asym_proto_to_resp() { let mut proto: ResultProto = Default::default(); let key_data: Vec = vec![0x11, 0x22, 0x33]; proto.data = key_data.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(result.data.expose_secret(), &key_data); } #[test] fn asym_resp_to_proto() { let key_data: Vec = vec![0x11, 0x22, 0x33]; let result = Result { data: Secret::new(key_data.clone()), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.data, key_data); } #[test] fn op_export_pk_e2e() { let op = Operation { key_name: "test name".to_string(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaExportKey(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaExportKey) .is_ok()); } #[test] fn resp_export_pk_e2e() { let result = Result { data: secrecy::Secret::new(vec![0x11, 0x22, 0x33]), }; let body = CONVERTER .result_to_body(NativeResult::PsaExportKey(result)) .expect("Failed to convert request"); assert!(CONVERTER.body_to_result(body, Opcode::PsaExportKey).is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaExportKey) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaExportKey) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_export_public_key.rs000064400000000000000000000105351046102023000265260ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_export_public_key::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_export_public_key::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { key_name: op.key_name, }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { Ok(Result { data: proto_op.data.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { Ok(ResultProto { data: op.data.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_export_public_key::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::{ psa_export_public_key::Operation, psa_export_public_key::Result, NativeOperation, NativeResult, }; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn export_pk_proto_to_op() { let mut proto: OperationProto = Default::default(); let key_name = "test name".to_string(); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.key_name, key_name); } #[test] fn asym_op_to_proto() { let key_name = "test name".to_string(); let op = Operation { key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.key_name, key_name); } #[test] fn asym_proto_to_resp() { let mut proto: ResultProto = Default::default(); let key_data = vec![0x11, 0x22, 0x33]; proto.data = key_data.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(result.data, key_data.into()); } #[test] fn asym_resp_to_proto() { let key_data = vec![0x11, 0x22, 0x33]; let result = Result { data: key_data.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.data, key_data); } #[test] fn op_export_pk_e2e() { let op = Operation { key_name: "test name".to_string(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaExportPublicKey(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaExportPublicKey) .is_ok()); } #[test] fn resp_export_pk_e2e() { let result = Result { data: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaExportPublicKey(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaExportPublicKey) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaExportPublicKey) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaExportPublicKey) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_generate_key.rs000064400000000000000000000147221046102023000254430ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_generate_key::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_generate_key::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { key_name: proto_op.key_name, attributes: proto_op .attributes .ok_or_else(|| { error!("The attributes field of PsaGenerateKey::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let proto = OperationProto { key_name: op.key_name, attributes: Some(op.attributes.try_into()?), }; Ok(proto) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_result: Result) -> std::result::Result { Ok(Default::default()) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_response: ResultProto) -> std::result::Result { Ok(Result {}) } } #[cfg(test)] mod test { #![allow(deprecated)] use super::super::generated_ops::psa_algorithm::{ self as algorithm_proto, Algorithm as AlgorithmProto, }; use super::super::generated_ops::psa_generate_key::{ Operation as OperationProto, Result as ResultProto, }; use super::super::generated_ops::psa_key_attributes::{ self as key_attributes_proto, KeyAttributes as KeyAttributesProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_generate_key::{Operation, Result}; use crate::operations::psa_key_attributes::{self, Attributes, Lifetime, Policy, UsageFlags}; use crate::operations::NativeOperation; use crate::requests::Opcode; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn create_key_op_from_proto() { let name = "test name".to_string(); let proto = OperationProto { key_name: name.clone(), attributes: Some(get_key_attrs_proto()), }; let op: Operation = proto.try_into().expect("Failed conversion"); assert_eq!(op.key_name, name); } #[test] fn create_key_op_to_proto() { let name = "test name".to_string(); let op = Operation { key_name: name.clone(), attributes: get_key_attrs(), }; let proto: OperationProto = op.try_into().expect("Failed conversion"); assert_eq!(proto.key_name, name); } #[test] fn create_key_res_from_proto() { let proto = ResultProto {}; let _res: Result = proto.try_into().expect("Failed conversion"); } #[test] fn create_key_res_to_proto() { let res = Result {}; let _proto: ResultProto = res.try_into().expect("Failed conversion"); } #[test] fn create_key_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, attributes: get_key_attrs(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaGenerateKey(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaGenerateKey) .expect("Failed to convert to operation"); } fn get_key_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, } } fn get_key_attrs_proto() -> KeyAttributesProto { KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair(key_attributes_proto::key_type::RsaKeyPair {})), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(AlgorithmProto { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature(algorithm_proto::algorithm::AsymmetricSignature { variant: Some(algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign(algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), })), })) }), }), } } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_generate_random.rs000064400000000000000000000127341046102023000261340ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_generate_random::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_generate_random::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { size: proto_op.size as usize, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let proto = OperationProto { size: op.size.try_into()?, }; Ok(proto) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { random_bytes: proto_result.random_bytes.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { random_bytes: result.random_bytes.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_generate_random::Result as ResultProto; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_generate_random::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn proto_to_resp() { let proto = ResultProto { random_bytes: vec![0xDE, 0xAD, 0xBE, 0xEF], }; let resp: Result = proto.try_into().unwrap(); assert!(resp.random_bytes[0] == 0xDE); assert!(resp.random_bytes[1] == 0xAD); assert!(resp.random_bytes[2] == 0xBE); assert!(resp.random_bytes[3] == 0xEF); } #[test] fn resp_to_proto() { let resp: Result = Result { random_bytes: vec![0xDE, 0xAD, 0xBE, 0xEF].into(), }; let proto: ResultProto = resp.try_into().unwrap(); assert!(proto.random_bytes[0] == 0xDE); assert!(proto.random_bytes[1] == 0xAD); assert!(proto.random_bytes[2] == 0xBE); assert!(proto.random_bytes[3] == 0xEF); } #[test] fn generate_random_req_to_native() { let req_body = RequestBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaGenerateRandom) .is_ok()); } #[test] fn op_generate_random_from_native() { let generate_random = Operation { size: 4 }; let body = CONVERTER .operation_to_body(NativeOperation::PsaGenerateRandom(generate_random)) .expect("Failed to convert request"); assert!(!body.is_empty()); } #[test] fn op_generate_random_e2e() { let generate_random = Operation { size: 4 }; let req_body = CONVERTER .operation_to_body(NativeOperation::PsaGenerateRandom(generate_random)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaGenerateRandom) .is_ok()); } #[test] fn req_from_native_mangled_body() { let req_body = RequestBody::from_bytes(vec![0xDE, 0xAD, 0xBE, 0xEF]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaGenerateRandom) .is_err()); } #[test] fn generate_random_body_to_native() { let resp_body = ResponseBody::from_bytes(Vec::new()); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaGenerateRandom) .is_ok()); } #[test] fn result_generate_random_from_native() { let generate_random = Result { random_bytes: vec![0xDE, 0xAD, 0xBE, 0xEF].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaGenerateRandom(generate_random)) .expect("Failed to convert response"); assert!(!body.is_empty()); } #[test] fn generate_random_result_e2e() { let generate_random = Result { random_bytes: vec![0xDE, 0xAD, 0xBE, 0xEF].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaGenerateRandom(generate_random)) .expect("Failed to convert response"); assert!(!body.is_empty()); let result = CONVERTER .body_to_result(body, Opcode::PsaGenerateRandom) .expect("Failed to convert back to result"); match result { NativeResult::PsaGenerateRandom(result) => { assert_eq!(result.random_bytes[0], 0xDE); assert_eq!(result.random_bytes[1], 0xAD); assert_eq!(result.random_bytes[2], 0xBE); assert_eq!(result.random_bytes[3], 0xEF); } _ => panic!("Expected generate random"), } } #[test] fn resp_from_native_mangled_body() { let resp_body = ResponseBody::from_bytes(vec![0xDE, 0xAD, 0xBE, 0xEF]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaGenerateRandom) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_hash_compare.rs000064400000000000000000000106571046102023000254350ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::convert_psa_algorithm; use super::generated_ops::psa_hash_compare::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_hash_compare::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let hash = proto_op.hash.into(); let input = proto_op.input.into(); Ok(Operation { alg: convert_psa_algorithm::i32_to_hash(proto_op.alg)?, input, hash, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { hash: op.hash.to_vec(), input: op.input.to_vec(), alg: convert_psa_algorithm::hash_to_i32(op.alg), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_proto_result: ResultProto) -> std::result::Result { Ok(Default::default()) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_result: Result) -> std::result::Result { Ok(ResultProto {}) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_hash_compare::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::Hash; use crate::operations::psa_hash_compare::{Operation, Result}; use crate::operations::NativeOperation; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; use zeroize::Zeroizing; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn hash_compare_proto_to_op() { let mut proto: OperationProto = Default::default(); let input = vec![0x11, 0x22, 0x33]; let hash = vec![0x44, 0x55, 0x66]; proto.input = input.clone(); proto.hash = hash.clone(); proto.alg = algorithm_proto::algorithm::Hash::Sha256.into(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.input, input.into()); assert_eq!(op.hash, hash.into()); assert_eq!(op.alg, Hash::Sha256); } #[test] fn hash_compare_op_to_proto() { let input = vec![0x11, 0x22, 0x33]; let hash = vec![0x44, 0x55, 0x66]; let alg = Hash::Sha256; let op = Operation { alg, input: input.clone().into(), hash: hash.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.input, input); assert_eq!(proto.hash, hash); } #[test] fn hash_compare_proto_to_resp() { let proto = ResultProto {}; let _res: Result = proto.try_into().expect("Failed conversion"); } #[test] fn hash_compare_resp_to_proto() { let res = Result {}; let _proto: ResultProto = res.try_into().expect("Failed conversion"); } #[test] fn op_hash_compare_e2e() { let op = Operation { input: Zeroizing::new(vec![0x11, 0x22, 0x33]), hash: Zeroizing::new(vec![0x44, 0x55, 0x66]), alg: Hash::Sha256, }; let body = CONVERTER .operation_to_body(NativeOperation::PsaHashCompare(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaHashCompare) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaHashCompare) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaHashCompute) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_hash_compute.rs000064400000000000000000000114361046102023000254570ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::convert_psa_algorithm; use super::generated_ops::psa_hash_compute::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_hash_compute::{Operation, Result}; use crate::requests::ResponseStatus; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let input = proto_op.input.into(); Ok(Operation { alg: convert_psa_algorithm::i32_to_hash(proto_op.alg)?, input, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { input: op.input.to_vec(), alg: convert_psa_algorithm::hash_to_i32(op.alg), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { hash: proto_result.hash.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { hash: result.hash.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_hash_compute::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::Hash; use crate::operations::psa_hash_compute::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn hash_compute_proto_to_op() { let mut proto: OperationProto = Default::default(); let input = vec![0x11, 0x22, 0x33]; proto.input = input.clone(); proto.alg = algorithm_proto::algorithm::Hash::Sha256.into(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.input, input.into()); assert_eq!(op.alg, Hash::Sha256); } #[test] fn hash_compute_op_to_proto() { let input = vec![0x11, 0x22, 0x33]; let alg = Hash::Sha256; let op = Operation { alg, input: input.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.input, input); } #[test] fn hash_compute_proto_to_resp() { let mut proto: ResultProto = Default::default(); let hash = vec![0x11, 0x22, 0x33]; proto.hash = hash.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(result.hash, hash.into()); } #[test] fn hash_compute_resp_to_proto() { let hash = vec![0x11, 0x22, 0x33]; let result = Result { hash: hash.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.hash, hash); } #[test] fn op_hash_compute_sign_e2e() { let op = Operation { input: vec![0x11, 0x22, 0x33].into(), alg: Hash::Sha256, }; let body = CONVERTER .operation_to_body(NativeOperation::PsaHashCompute(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaHashCompute) .is_ok()); } #[test] fn resp_hash_compute_sign_e2e() { let result = Result { hash: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaHashCompute(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaHashCompute) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaHashCompute) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaHashCompute) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_import_key.rs000064400000000000000000000157301046102023000251630ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_import_key::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_import_key::{Operation, Result}; use crate::requests::ResponseStatus; use crate::secrecy::ExposeSecret; use crate::secrecy::Secret; use log::error; use std::convert::{TryFrom, TryInto}; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let data = Secret::new(proto_op.data); Ok(Operation { key_name: proto_op.key_name, attributes: proto_op .attributes .ok_or_else(|| { error!("The attributes field of PsaImportKey::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, data, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { key_name: op.key_name, attributes: Some(op.attributes.try_into()?), data: op.data.expose_secret().to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_proto_op: ResultProto) -> std::result::Result { Ok(Result {}) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_op: Result) -> std::result::Result { Ok(ResultProto {}) } } #[cfg(test)] mod test { #![allow(deprecated)] use super::super::generated_ops::psa_algorithm::{ self as algorithm_proto, Algorithm as AlgorithmProto, }; use super::super::generated_ops::psa_import_key::{ Operation as OperationProto, Result as ResultProto, }; use super::super::generated_ops::psa_key_attributes::{ self as key_attributes_proto, KeyAttributes as KeyAttributesProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{self, Attributes, Lifetime, Policy, UsageFlags}; use crate::operations::{psa_import_key::Operation, psa_import_key::Result, NativeOperation}; use crate::requests::Opcode; use crate::secrecy::{ExposeSecret, Secret}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn psa_import_key_op_from_proto() { let name = "test name".to_string(); let key_data = vec![0x11, 0x22, 0x33]; let proto = OperationProto { key_name: name.clone(), attributes: Some(get_key_attrs_proto()), data: key_data.clone(), }; let op: Operation = proto.try_into().expect("Failed conversion"); assert_eq!(op.key_name, name); assert_eq!(op.data.expose_secret(), &key_data); } #[test] fn psa_import_key_op_to_proto() { let name = "test name".to_string(); let key_data = vec![0x11, 0x22, 0x33]; let op = Operation { key_name: name.clone(), attributes: get_key_attrs(), data: Secret::new(key_data.clone()), }; let proto: OperationProto = op.try_into().expect("Failed conversion"); assert_eq!(proto.key_name, name); assert_eq!(proto.data, key_data); } #[test] fn psa_import_key_res_from_proto() { let proto = ResultProto {}; let _res: Result = proto.try_into().expect("Failed conversion"); } #[test] fn psa_import_key_res_to_proto() { let res = Result {}; let _proto: ResultProto = res.try_into().expect("Failed conversion"); } #[test] fn psa_import_key_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, attributes: get_key_attrs(), data: Secret::new(vec![0x11, 0x22, 0x33]), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaImportKey(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaImportKey) .expect("Failed to convert to operation"); } fn get_key_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, } } fn get_key_attrs_proto() -> KeyAttributesProto { KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair(key_attributes_proto::key_type::RsaKeyPair {})), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(AlgorithmProto { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature(algorithm_proto::algorithm::AsymmetricSignature { variant: Some(algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign(algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), })), })) }), }), } } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_key_attributes.rs000064400000000000000000000622061046102023000260370ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 // Protobuf imports use super::generated_ops::psa_key_attributes::key_type; use super::generated_ops::psa_key_attributes::{ key_type::DhFamily as DhFamilyProto, key_type::EccFamily as EccFamilyProto, KeyAttributes as KeyAttributesProto, KeyPolicy as KeyPolicyProto, KeyType as KeyTypeProto, UsageFlags as UsageFlagsProto, }; // Native imports use crate::operations::psa_algorithm::Algorithm; use crate::operations::psa_key_attributes::{ Attributes, DhFamily, EccFamily, Lifetime, Policy, Type, UsageFlags, }; use crate::requests::{ResponseStatus, Result}; use log::error; use std::convert::{TryFrom, TryInto}; // UsageFlags: from protobuf to native impl TryFrom for UsageFlags { type Error = ResponseStatus; fn try_from(usage_flags_proto: UsageFlagsProto) -> Result { let mut usage_flags = UsageFlags::default(); if usage_flags_proto.export { let _ = usage_flags.set_export(); } if usage_flags_proto.copy { let _ = usage_flags.set_copy(); } if usage_flags_proto.cache { let _ = usage_flags.set_cache(); } if usage_flags_proto.encrypt { let _ = usage_flags.set_encrypt(); } if usage_flags_proto.decrypt { let _ = usage_flags.set_decrypt(); } if usage_flags_proto.sign_message { let _ = usage_flags.set_sign_message(); } if usage_flags_proto.verify_message { let _ = usage_flags.set_verify_message(); } if usage_flags_proto.sign_hash { let _ = usage_flags.set_sign_hash(); } if usage_flags_proto.verify_hash { let _ = usage_flags.set_verify_hash(); } if usage_flags_proto.derive { let _ = usage_flags.set_derive(); } Ok(usage_flags) } } // UsageFlags: from native to protobuf impl TryFrom for UsageFlagsProto { type Error = ResponseStatus; fn try_from(usage_flags: UsageFlags) -> Result { Ok(UsageFlagsProto { export: usage_flags.export(), copy: usage_flags.copy(), cache: usage_flags.cache(), encrypt: usage_flags.encrypt(), decrypt: usage_flags.decrypt(), sign_message: usage_flags.sign_message(), verify_message: usage_flags.verify_message(), sign_hash: usage_flags.sign_hash(), verify_hash: usage_flags.verify_hash(), derive: usage_flags.derive(), }) } } // Policy: from protobuf to native impl TryFrom for Policy { type Error = ResponseStatus; fn try_from(key_policy_proto: KeyPolicyProto) -> Result { let permitted_algorithms: Algorithm = key_policy_proto .key_algorithm .ok_or_else(|| { error!("The permitted_algorithms field of Policy message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?; Ok(Policy { usage_flags: key_policy_proto .key_usage_flags .ok_or_else(|| { error!("The usage_flags field of Policy message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, permitted_algorithms, }) } } // Policy: from native to protobuf impl TryFrom for KeyPolicyProto { type Error = ResponseStatus; fn try_from(key_policy: Policy) -> Result { Ok(KeyPolicyProto { key_usage_flags: Some(key_policy.usage_flags.try_into()?), key_algorithm: Some(key_policy.permitted_algorithms.try_into()?), }) } } // EccFamily: from protobuf to native impl TryFrom for EccFamily { type Error = ResponseStatus; fn try_from(ecc_family_val: EccFamilyProto) -> Result { match ecc_family_val { EccFamilyProto::None => { error!("The None value of EccFamily enumeration is not allowed (mandatory field)."); Err(ResponseStatus::InvalidEncoding) } EccFamilyProto::SecpK1 => Ok(EccFamily::SecpK1), EccFamilyProto::SecpR1 => Ok(EccFamily::SecpR1), #[allow(deprecated)] EccFamilyProto::SecpR2 => Ok(EccFamily::SecpR2), EccFamilyProto::SectK1 => Ok(EccFamily::SectK1), EccFamilyProto::SectR1 => Ok(EccFamily::SectR1), #[allow(deprecated)] EccFamilyProto::SectR2 => Ok(EccFamily::SectR2), EccFamilyProto::BrainpoolPR1 => Ok(EccFamily::BrainpoolPR1), EccFamilyProto::Frp => Ok(EccFamily::Frp), EccFamilyProto::Montgomery => Ok(EccFamily::Montgomery), } } } // EccFamily: from native to protobuf fn ecc_family_to_i32(ecc_family: EccFamily) -> i32 { match ecc_family { EccFamily::SecpK1 => EccFamilyProto::SecpK1.into(), EccFamily::SecpR1 => EccFamilyProto::SecpR1.into(), #[allow(deprecated)] EccFamily::SecpR2 => EccFamilyProto::SecpR2.into(), EccFamily::SectK1 => EccFamilyProto::SectK1.into(), EccFamily::SectR1 => EccFamilyProto::SectR1.into(), #[allow(deprecated)] EccFamily::SectR2 => EccFamilyProto::SectR2.into(), EccFamily::BrainpoolPR1 => EccFamilyProto::BrainpoolPR1.into(), EccFamily::Frp => EccFamilyProto::Frp.into(), EccFamily::Montgomery => EccFamilyProto::Montgomery.into(), } } // DhFamily: from protobuf to native impl TryFrom for DhFamily { type Error = ResponseStatus; fn try_from(dh_family_val: DhFamilyProto) -> Result { match dh_family_val { DhFamilyProto::Rfc7919 => Ok(DhFamily::Rfc7919), } } } // DhFamily: from native to protobuf fn dh_family_to_i32(dh_family: DhFamily) -> i32 { match dh_family { DhFamily::Rfc7919 => DhFamilyProto::Rfc7919.into(), } } impl TryFrom for Type { type Error = ResponseStatus; fn try_from(key_type_proto: KeyTypeProto) -> Result { match key_type_proto.variant.ok_or_else(|| { error!("variant field of Type message is empty."); ResponseStatus::InvalidEncoding })? { key_type::Variant::RawData(_) => Ok(Type::RawData), key_type::Variant::Hmac(_) => Ok(Type::Hmac), key_type::Variant::Derive(_) => Ok(Type::Derive), key_type::Variant::Aes(_) => Ok(Type::Aes), key_type::Variant::Des(_) => Ok(Type::Des), key_type::Variant::Camellia(_) => Ok(Type::Camellia), key_type::Variant::Arc4(_) => Ok(Type::Arc4), key_type::Variant::Chacha20(_) => Ok(Type::Chacha20), key_type::Variant::RsaPublicKey(_) => Ok(Type::RsaPublicKey), key_type::Variant::RsaKeyPair(_) => Ok(Type::RsaKeyPair), key_type::Variant::EccKeyPair(ecc_key_pair) => Ok(Type::EccKeyPair { curve_family: EccFamilyProto::try_from(ecc_key_pair.curve_family)?.try_into()?, }), key_type::Variant::EccPublicKey(ecc_public_key) => Ok(Type::EccPublicKey { curve_family: EccFamilyProto::try_from(ecc_public_key.curve_family)?.try_into()?, }), key_type::Variant::DhKeyPair(dh_key_pair) => Ok(Type::DhKeyPair { group_family: DhFamilyProto::try_from(dh_key_pair.group_family)?.try_into()?, }), key_type::Variant::DhPublicKey(dh_public_key) => Ok(Type::DhPublicKey { group_family: DhFamilyProto::try_from(dh_public_key.group_family)?.try_into()?, }), } } } impl TryFrom for KeyTypeProto { type Error = ResponseStatus; fn try_from(key_type: Type) -> Result { match key_type { Type::RawData => Ok(KeyTypeProto { variant: Some(key_type::Variant::RawData(key_type::RawData {})), }), Type::Hmac => Ok(KeyTypeProto { variant: Some(key_type::Variant::Hmac(key_type::Hmac {})), }), Type::Derive => Ok(KeyTypeProto { variant: Some(key_type::Variant::Derive(key_type::Derive {})), }), Type::Aes => Ok(KeyTypeProto { variant: Some(key_type::Variant::Aes(key_type::Aes {})), }), Type::Des => Ok(KeyTypeProto { variant: Some(key_type::Variant::Des(key_type::Des {})), }), Type::Camellia => Ok(KeyTypeProto { variant: Some(key_type::Variant::Camellia(key_type::Camellia {})), }), Type::Arc4 => Ok(KeyTypeProto { variant: Some(key_type::Variant::Arc4(key_type::Arc4 {})), }), Type::Chacha20 => Ok(KeyTypeProto { variant: Some(key_type::Variant::Chacha20(key_type::Chacha20 {})), }), Type::RsaPublicKey => Ok(KeyTypeProto { variant: Some(key_type::Variant::RsaPublicKey(key_type::RsaPublicKey {})), }), Type::RsaKeyPair => Ok(KeyTypeProto { variant: Some(key_type::Variant::RsaKeyPair(key_type::RsaKeyPair {})), }), Type::EccKeyPair { curve_family } => Ok(KeyTypeProto { variant: Some(key_type::Variant::EccKeyPair(key_type::EccKeyPair { curve_family: ecc_family_to_i32(curve_family), })), }), Type::EccPublicKey { curve_family } => Ok(KeyTypeProto { variant: Some(key_type::Variant::EccPublicKey(key_type::EccPublicKey { curve_family: ecc_family_to_i32(curve_family), })), }), Type::DhKeyPair { group_family } => Ok(KeyTypeProto { variant: Some(key_type::Variant::DhKeyPair(key_type::DhKeyPair { group_family: dh_family_to_i32(group_family), })), }), Type::DhPublicKey { group_family } => Ok(KeyTypeProto { variant: Some(key_type::Variant::DhPublicKey(key_type::DhPublicKey { group_family: dh_family_to_i32(group_family), })), }), } } } // Attributes: from protobuf to native impl TryFrom for Attributes { type Error = ResponseStatus; fn try_from(key_attributes_proto: KeyAttributesProto) -> Result { Ok(Attributes { lifetime: Lifetime::Persistent, key_type: key_attributes_proto .key_type .ok_or_else(|| { error!( "The key_type field of Attributes message is not set (mandatory field)." ); ResponseStatus::InvalidEncoding })? .try_into()?, bits: key_attributes_proto.key_bits.try_into().map_err(|e| { error!("failed to convert key bits from proto. Error: {}", e); ResponseStatus::InvalidEncoding })?, policy: key_attributes_proto .key_policy .ok_or_else(|| { error!("The policy field of Attributes message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, }) } } // Attributes: from native to protobuf impl TryFrom for KeyAttributesProto { type Error = ResponseStatus; fn try_from(key_attributes: Attributes) -> Result { Ok(KeyAttributesProto { key_type: Some(key_attributes.key_type.try_into()?), key_bits: key_attributes.bits.try_into().map_err(|e| { error!("failed to convert key bits to proto. Error: {}", e); ResponseStatus::InvalidEncoding })?, key_policy: Some(key_attributes.policy.try_into()?), }) } } #[cfg(test)] mod test { #![allow(deprecated)] use super::super::generated_ops::psa_algorithm::{self as algorithm_proto}; use super::super::generated_ops::psa_key_attributes::{ self as key_attributes_proto, KeyAttributes as KeyAttributesProto, }; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{self, Attributes, Lifetime, Policy, UsageFlags}; use crate::requests::ResponseStatus; use std::convert::{TryFrom, TryInto}; #[test] fn key_attrs_to_proto() { let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_attrs = Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }; let key_attrs_proto: KeyAttributesProto = key_attrs.try_into().unwrap(); let key_attrs_proto_expected = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair(key_attributes_proto::key_type::RsaKeyPair {})), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature(algorithm_proto::algorithm::AsymmetricSignature { variant: Some(algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign(algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), })), })) }), }), }; assert_eq!(key_attrs_proto, key_attrs_proto_expected); } #[test] fn key_attrs_from_proto() { let key_attrs_proto = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair(key_attributes_proto::key_type::RsaKeyPair {})), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature(algorithm_proto::algorithm::AsymmetricSignature { variant: Some(algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign(algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), })), })) }), }), }; let key_attrs: Attributes = key_attrs_proto.try_into().unwrap(); let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); let key_attrs_expected = Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, }; assert_eq!(key_attrs, key_attrs_expected); } #[test] fn proto_key_type_variant_not_recognised() { let key_attrs_proto = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: None }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::None( algorithm_proto::algorithm::None {}, )), }), }), }; assert_eq!( Attributes::try_from(key_attrs_proto).unwrap_err(), ResponseStatus::InvalidEncoding ); } #[test] fn proto_key_type_not_set() { let key_attrs_proto = KeyAttributesProto { key_type: None, key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::None( algorithm_proto::algorithm::None {}, )), }), }), }; assert_eq!( Attributes::try_from(key_attrs_proto).unwrap_err(), ResponseStatus::InvalidEncoding ); } #[test] fn proto_usage_flags_not_set() { let key_attrs_proto = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair( key_attributes_proto::key_type::RsaKeyPair {}, )), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: None, key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::None( algorithm_proto::algorithm::None {}, )), }), }), }; assert_eq!( Attributes::try_from(key_attrs_proto).unwrap_err(), ResponseStatus::InvalidEncoding ); } #[test] fn proto_key_alg_not_recognised() { let key_attrs_proto = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair( key_attributes_proto::key_type::RsaKeyPair {}, )), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: None }), }), }; assert_eq!( Attributes::try_from(key_attrs_proto).unwrap_err(), ResponseStatus::InvalidEncoding ); } #[test] fn proto_key_alg_not_recognised2() { let key_attrs_proto = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair( key_attributes_proto::key_type::RsaKeyPair {}, )), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature( algorithm_proto::algorithm::AsymmetricSignature { variant: None }, )), }), }), }; assert_eq!( Attributes::try_from(key_attrs_proto).unwrap_err(), ResponseStatus::InvalidEncoding ); } #[test] fn proto_key_alg_not_recognised3() { let key_attrs_proto = KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair(key_attributes_proto::key_type::RsaKeyPair {})), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(algorithm_proto::Algorithm { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature(algorithm_proto::algorithm::AsymmetricSignature { variant: Some(algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign(algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( 78, )), }), })), })) }), }), }; assert_eq!( Attributes::try_from(key_attrs_proto).unwrap_err(), ResponseStatus::InvalidEncoding ); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_raw_key_agreement.rs000064400000000000000000000157131046102023000264720ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::convert_psa_algorithm; use super::generated_ops::psa_raw_key_agreement::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_raw_key_agreement::{Operation, Result}; use crate::requests::ResponseStatus; use crate::secrecy::{ExposeSecret, Secret}; use std::convert::TryFrom; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { Ok(Operation { alg: convert_psa_algorithm::i32_to_raw_key_agreement(proto_op.alg)?, private_key_name: proto_op.private_key_name, peer_key: proto_op.peer_key.into(), }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { Ok(OperationProto { alg: convert_psa_algorithm::raw_key_agreement_to_i32(op.alg), private_key_name: op.private_key_name, peer_key: op.peer_key.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_op: ResultProto) -> std::result::Result { Ok(Result { shared_secret: Secret::new(proto_op.shared_secret), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(op: Result) -> std::result::Result { Ok(ResultProto { shared_secret: op.shared_secret.expose_secret().to_vec(), }) } } #[cfg(test)] mod test { #![allow(deprecated)] use super::super::generated_ops::psa_algorithm::{ self as algorithm_proto, Algorithm as AlgorithmProto, }; use super::super::generated_ops::psa_import_key::{ Operation as OperationProto, Result as ResultProto, }; use super::super::generated_ops::psa_key_attributes::{ self as key_attributes_proto, KeyAttributes as KeyAttributesProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::{Algorithm, AsymmetricSignature, Hash}; use crate::operations::psa_key_attributes::{self, Attributes, Lifetime, Policy, UsageFlags}; use crate::operations::{psa_import_key::Operation, psa_import_key::Result, NativeOperation}; use crate::requests::Opcode; use crate::secrecy::{ExposeSecret, Secret}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn psa_raw_key_agreement_op_from_proto() { let name = "test name".to_string(); let key_data = vec![0x11, 0x22, 0x33]; let proto = OperationProto { key_name: name.clone(), attributes: Some(get_key_attrs_proto()), data: key_data.clone(), }; let op: Operation = proto.try_into().expect("Failed conversion"); assert_eq!(op.key_name, name); assert_eq!(op.data.expose_secret(), &key_data); } #[test] fn psa_raw_key_agreement_op_to_proto() { let name = "test name".to_string(); let key_data = vec![0x11, 0x22, 0x33]; let op = Operation { key_name: name.clone(), attributes: get_key_attrs(), data: Secret::new(key_data.clone()), }; let proto: OperationProto = op.try_into().expect("Failed conversion"); assert_eq!(proto.key_name, name); assert_eq!(proto.data, key_data); } #[test] fn psa_raw_key_agreement_res_from_proto() { let proto = ResultProto {}; let _res: Result = proto.try_into().expect("Failed conversion"); } #[test] fn psa_raw_key_agreement_res_to_proto() { let res = Result {}; let _proto: ResultProto = res.try_into().expect("Failed conversion"); } #[test] fn psa_raw_key_agreement_op_e2e() { let name = "test name".to_string(); let op = Operation { key_name: name, attributes: get_key_attrs(), data: Secret::new(vec![0x11, 0x22, 0x33]), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaImportKey(op)) .expect("Failed to convert to body"); let _ = CONVERTER .body_to_operation(body, Opcode::PsaImportKey) .expect("Failed to convert to operation"); } fn get_key_attrs() -> Attributes { let mut usage_flags = UsageFlags::default(); let _ = usage_flags .set_decrypt() .set_export() .set_copy() .set_cache() .set_encrypt() .set_decrypt() .set_sign_message() .set_verify_message() .set_sign_hash() .set_verify_hash() .set_derive(); Attributes { lifetime: Lifetime::Persistent, key_type: psa_key_attributes::Type::RsaKeyPair, bits: 1024, policy: Policy { usage_flags, permitted_algorithms: Algorithm::AsymmetricSignature( AsymmetricSignature::RsaPkcs1v15Sign { hash_alg: Hash::Sha1.into(), }, ), }, } } fn get_key_attrs_proto() -> KeyAttributesProto { KeyAttributesProto { key_type: Some(key_attributes_proto::KeyType { variant: Some(key_attributes_proto::key_type::Variant::RsaKeyPair(key_attributes_proto::key_type::RsaKeyPair {})), }), key_bits: 1024, key_policy: Some(key_attributes_proto::KeyPolicy { key_usage_flags: Some(key_attributes_proto::UsageFlags { export: true, copy: true, cache: true, encrypt: true, decrypt: true, sign_message: true, verify_message: true, sign_hash: true, verify_hash: true, derive: true, }), key_algorithm: Some(AlgorithmProto { variant: Some(algorithm_proto::algorithm::Variant::AsymmetricSignature(algorithm_proto::algorithm::AsymmetricSignature { variant: Some(algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign(algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), })), })) }), }), } } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_sign_hash.rs000064400000000000000000000137771046102023000247550ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_sign_hash::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_sign_hash::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; use zeroize::Zeroizing; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let hash = Zeroizing::new(proto_op.hash); Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of psa_sign_hash::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, hash, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); Ok(OperationProto { key_name: op.key_name, alg, hash: op.hash.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { signature: proto_result.signature.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { signature: result.signature.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_sign_hash::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::AsymmetricSignature; use crate::operations::psa_sign_hash::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn asym_proto_to_op() { let mut proto: OperationProto = Default::default(); let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); proto.hash = hash.clone(); proto.alg = Some(algorithm_proto::algorithm::AsymmetricSignature { variant: Some( algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign( algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), }, ), ), }); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.hash, hash.into()); assert_eq!(op.key_name, key_name); } #[test] fn asym_op_to_proto() { let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let op = Operation { hash: hash.clone().into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.hash, hash); assert_eq!(proto.key_name, key_name); } #[test] fn asym_proto_to_resp() { let mut proto: ResultProto = Default::default(); let signature = vec![0x11, 0x22, 0x33]; proto.signature = signature.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(result.signature, signature.into()); } #[test] fn asym_resp_to_proto() { let signature = vec![0x11, 0x22, 0x33]; let result = Result { signature: signature.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.signature, signature); } #[test] fn op_asym_sign_e2e() { let op = Operation { hash: vec![0x11, 0x22, 0x33].into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: "test name".to_string(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaSignHash(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaSignHash) .is_ok()); } #[test] fn resp_asym_sign_e2e() { let result = Result { signature: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaSignHash(result)) .expect("Failed to convert request"); assert!(CONVERTER.body_to_result(body, Opcode::PsaSignHash).is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaSignHash) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaSignHash) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_sign_message.rs000064400000000000000000000141301046102023000254360ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_sign_message::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_sign_message::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; use zeroize::Zeroizing; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let message = Zeroizing::new(proto_op.message); Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of psa_sign_message::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, message, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); Ok(OperationProto { key_name: op.key_name, alg, message: op.message.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(proto_result: ResultProto) -> std::result::Result { Ok(Result { signature: proto_result.signature.into(), }) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(result: Result) -> std::result::Result { Ok(ResultProto { signature: result.signature.to_vec(), }) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_sign_message::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::AsymmetricSignature; use crate::operations::psa_sign_message::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn asym_proto_to_op() { let mut proto: OperationProto = Default::default(); let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); proto.message = hash.clone(); proto.alg = Some(algorithm_proto::algorithm::AsymmetricSignature { variant: Some( algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign( algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), }, ), ), }); proto.key_name = key_name.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.message, hash.into()); assert_eq!(op.key_name, key_name); } #[test] fn asym_op_to_proto() { let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let op = Operation { message: hash.clone().into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: key_name.clone(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.message, hash); assert_eq!(proto.key_name, key_name); } #[test] fn asym_proto_to_resp() { let mut proto: ResultProto = Default::default(); let signature = vec![0x11, 0x22, 0x33]; proto.signature = signature.clone(); let result: Result = proto.try_into().expect("Failed to convert"); assert_eq!(result.signature, signature.into()); } #[test] fn asym_resp_to_proto() { let signature = vec![0x11, 0x22, 0x33]; let result = Result { signature: signature.clone().into(), }; let proto: ResultProto = result.try_into().expect("Failed to convert"); assert_eq!(proto.signature, signature); } #[test] fn op_asym_sign_e2e() { let op = Operation { message: vec![0x11, 0x22, 0x33].into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: "test name".to_string(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaSignMessage(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaSignMessage) .is_ok()); } #[test] fn resp_asym_sign_e2e() { let result = Result { signature: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .result_to_body(NativeResult::PsaSignMessage(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaSignMessage) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaSignMessage) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaSignMessage) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_verify_hash.rs000064400000000000000000000140361046102023000253060ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_verify_hash::{Operation as OperationProto, Result as ResultProto}; use crate::operations::psa_verify_hash::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; use zeroize::Zeroizing; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let hash = Zeroizing::new(proto_op.hash); let signature = Zeroizing::new(proto_op.signature); Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of psa_verify_hash::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, hash, signature, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); Ok(OperationProto { key_name: op.key_name, alg, hash: op.hash.to_vec(), signature: op.signature.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_proto_result: ResultProto) -> std::result::Result { Ok(Result {}) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_result: Result) -> std::result::Result { Ok(ResultProto {}) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_verify_hash::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::AsymmetricSignature; use crate::operations::psa_verify_hash::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn asym_proto_to_op() { let mut proto: OperationProto = Default::default(); let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let signature = vec![0x11, 0x22, 0x33]; proto.hash = hash.clone(); proto.alg = Some(algorithm_proto::algorithm::AsymmetricSignature { variant: Some( algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign( algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), }, ), ), }); proto.key_name = key_name.clone(); proto.signature = signature.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.hash, hash.into()); assert_eq!(op.key_name, key_name); assert_eq!(op.signature, signature.into()); } #[test] fn asym_op_to_proto() { let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let signature = vec![0x11, 0x22, 0x33]; let op = Operation { hash: hash.clone().into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: key_name.clone(), signature: signature.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.hash, hash); assert_eq!(proto.key_name, key_name); assert_eq!(proto.signature, signature); } #[test] fn asym_proto_to_resp() { let proto: ResultProto = Default::default(); let _result: Result = proto.try_into().expect("Failed to convert"); } #[test] fn asym_resp_to_proto() { let result = Result {}; let _proto: ResultProto = result.try_into().expect("Failed to convert"); } #[test] fn op_asym_sign_e2e() { let op = Operation { hash: vec![0x11, 0x22, 0x33].into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: "test name".to_string(), signature: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaVerifyHash(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaVerifyHash) .is_ok()); } #[test] fn resp_asym_sign_e2e() { let result = Result {}; let body = CONVERTER .result_to_body(NativeResult::PsaVerifyHash(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaVerifyHash) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaVerifyHash) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaVerifyHash) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/convert_psa_verify_message.rs000064400000000000000000000141441046102023000260070ustar 00000000000000// Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::generated_ops::psa_verify_message::{ Operation as OperationProto, Result as ResultProto, }; use crate::operations::psa_verify_message::{Operation, Result}; use crate::requests::ResponseStatus; use log::error; use std::convert::{TryFrom, TryInto}; use zeroize::Zeroizing; impl TryFrom for Operation { type Error = ResponseStatus; fn try_from(proto_op: OperationProto) -> std::result::Result { let message = Zeroizing::new(proto_op.message); let signature = Zeroizing::new(proto_op.signature); Ok(Operation { key_name: proto_op.key_name, alg: proto_op .alg .ok_or_else(|| { error!("The alg field of psa_verify_message::Operation message is not set (mandatory field)."); ResponseStatus::InvalidEncoding })? .try_into()?, message, signature, }) } } impl TryFrom for OperationProto { type Error = ResponseStatus; fn try_from(op: Operation) -> std::result::Result { let alg = Some(op.alg.try_into()?); Ok(OperationProto { key_name: op.key_name, alg, message: op.message.to_vec(), signature: op.signature.to_vec(), }) } } impl TryFrom for Result { type Error = ResponseStatus; fn try_from(_proto_result: ResultProto) -> std::result::Result { Ok(Result {}) } } impl TryFrom for ResultProto { type Error = ResponseStatus; fn try_from(_result: Result) -> std::result::Result { Ok(ResultProto {}) } } #[cfg(test)] mod test { use super::super::generated_ops::psa_algorithm as algorithm_proto; use super::super::generated_ops::psa_verify_message::{ Operation as OperationProto, Result as ResultProto, }; use super::super::{Convert, ProtobufConverter}; use crate::operations::psa_algorithm::AsymmetricSignature; use crate::operations::psa_verify_message::{Operation, Result}; use crate::operations::{NativeOperation, NativeResult}; use crate::requests::{request::RequestBody, response::ResponseBody, Opcode}; use std::convert::TryInto; static CONVERTER: ProtobufConverter = ProtobufConverter {}; #[test] fn asym_proto_to_op() { let mut proto: OperationProto = Default::default(); let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let signature = vec![0x11, 0x22, 0x33]; proto.message = hash.clone(); proto.alg = Some(algorithm_proto::algorithm::AsymmetricSignature { variant: Some( algorithm_proto::algorithm::asymmetric_signature::Variant::RsaPkcs1v15Sign( algorithm_proto::algorithm::asymmetric_signature::RsaPkcs1v15Sign { hash_alg: Some(algorithm_proto::algorithm::asymmetric_signature::SignHash { variant: Some(algorithm_proto::algorithm::asymmetric_signature::sign_hash::Variant::Specific( algorithm_proto::algorithm::Hash::Sha1.into(), )), }), }, ), ), }); proto.key_name = key_name.clone(); proto.signature = signature.clone(); let op: Operation = proto.try_into().expect("Failed to convert"); assert_eq!(op.message, hash.into()); assert_eq!(op.key_name, key_name); assert_eq!(op.signature, signature.into()); } #[test] fn asym_op_to_proto() { let hash = vec![0x11, 0x22, 0x33]; let key_name = "test name".to_string(); let signature = vec![0x11, 0x22, 0x33]; let op = Operation { message: hash.clone().into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: key_name.clone(), signature: signature.clone().into(), }; let proto: OperationProto = op.try_into().expect("Failed to convert"); assert_eq!(proto.message, hash); assert_eq!(proto.key_name, key_name); assert_eq!(proto.signature, signature); } #[test] fn asym_proto_to_resp() { let proto: ResultProto = Default::default(); let _result: Result = proto.try_into().expect("Failed to convert"); } #[test] fn asym_resp_to_proto() { let result = Result {}; let _proto: ResultProto = result.try_into().expect("Failed to convert"); } #[test] fn op_asym_sign_e2e() { let op = Operation { message: vec![0x11, 0x22, 0x33].into(), alg: AsymmetricSignature::RsaPkcs1v15SignRaw, key_name: "test name".to_string(), signature: vec![0x11, 0x22, 0x33].into(), }; let body = CONVERTER .operation_to_body(NativeOperation::PsaVerifyMessage(op)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_operation(body, Opcode::PsaVerifyMessage) .is_ok()); } #[test] fn resp_asym_sign_e2e() { let result = Result {}; let body = CONVERTER .result_to_body(NativeResult::PsaVerifyMessage(result)) .expect("Failed to convert request"); assert!(CONVERTER .body_to_result(body, Opcode::PsaVerifyMessage) .is_ok()); } #[test] fn result_from_mangled_resp_body() { let resp_body = ResponseBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_result(resp_body, Opcode::PsaVerifyMessage) .is_err()); } #[test] fn op_from_mangled_req_body() { let req_body = RequestBody::from_bytes(vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]); assert!(CONVERTER .body_to_operation(req_body, Opcode::PsaVerifyMessage) .is_err()); } } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/attest_key.rs000064400000000000000000000036671046102023000253770ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct AttestationMechanismParams { #[prost(oneof="attestation_mechanism_params::Mechanism", tags="1")] pub mechanism: ::core::option::Option, } /// Nested message and enum types in `AttestationMechanismParams`. pub mod attestation_mechanism_params { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActivateCredential { #[prost(bytes="vec", tag="1")] pub credential_blob: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="2")] pub secret: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Mechanism { #[prost(message, tag="1")] ActivateCredential(ActivateCredential), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub attested_key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub parameters: ::core::option::Option, #[prost(string, tag="3")] pub attesting_key_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AttestationOutput { #[prost(oneof="attestation_output::Mechanism", tags="1")] pub mechanism: ::core::option::Option, } /// Nested message and enum types in `AttestationOutput`. pub mod attestation_output { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActivateCredential { #[prost(bytes="vec", tag="1")] pub credential: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Mechanism { #[prost(message, tag="1")] ActivateCredential(ActivateCredential), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(message, optional, tag="1")] pub output: ::core::option::Option, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/can_do_crypto.rs000064400000000000000000000010451046102023000260320ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(enumeration="CheckType", tag="1")] pub check_type: i32, #[prost(message, optional, tag="2")] pub attributes: ::std::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum CheckType { ChecktypeNone = 0, Use = 1, Generate = 2, Import = 3, Derive = 4, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/delete_client.rs000064400000000000000000000003311046102023000260040ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub client: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/list_authenticators.rs000064400000000000000000000011621046102023000272770ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct AuthenticatorInfo { #[prost(string, tag="1")] pub description: ::prost::alloc::string::String, #[prost(uint32, tag="2")] pub version_maj: u32, #[prost(uint32, tag="3")] pub version_min: u32, #[prost(uint32, tag="4")] pub version_rev: u32, #[prost(uint32, tag="5")] pub id: u32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(message, repeated, tag="1")] pub authenticators: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/list_clients.rs000064400000000000000000000003761046102023000257110ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(string, repeated, tag="1")] pub clients: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/list_keys.rs000064400000000000000000000010551046102023000252160ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyInfo { #[prost(uint32, tag="1")] pub provider_id: u32, #[prost(string, tag="2")] pub name: ::prost::alloc::string::String, #[prost(message, optional, tag="3")] pub attributes: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(message, repeated, tag="1")] pub keys: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/list_opcodes.rs000064400000000000000000000004331046102023000256760ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(uint32, tag="1")] pub provider_id: u32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(uint32, repeated, tag="1")] pub opcodes: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/list_providers.rs000064400000000000000000000013751046102023000262650ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct ProviderInfo { #[prost(string, tag="1")] pub uuid: ::prost::alloc::string::String, #[prost(string, tag="2")] pub description: ::prost::alloc::string::String, #[prost(string, tag="3")] pub vendor: ::prost::alloc::string::String, #[prost(uint32, tag="4")] pub version_maj: u32, #[prost(uint32, tag="5")] pub version_min: u32, #[prost(uint32, tag="6")] pub version_rev: u32, #[prost(uint32, tag="7")] pub id: u32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(message, repeated, tag="1")] pub providers: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/mod.rs000064400000000000000000000272371046102023000240010ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 #![allow(clippy::derive_partial_eq_without_eq)] pub mod psa_sign_hash; pub mod psa_verify_hash; pub mod psa_sign_message; pub mod psa_verify_message; pub mod psa_asymmetric_encrypt; pub mod psa_asymmetric_decrypt; pub mod psa_aead_encrypt; pub mod psa_aead_decrypt; pub mod psa_cipher_encrypt; pub mod psa_cipher_decrypt; pub mod psa_generate_key; pub mod psa_destroy_key; pub mod psa_export_public_key; pub mod psa_export_key; pub mod psa_import_key; pub mod list_opcodes; pub mod list_providers; pub mod list_authenticators; pub mod list_keys; pub mod list_clients; pub mod delete_client; pub mod ping; pub mod psa_key_attributes; pub mod psa_algorithm; pub mod psa_generate_random; pub mod psa_hash_compute; pub mod psa_hash_compare; pub mod psa_raw_key_agreement; pub mod can_do_crypto; pub mod attest_key; pub mod prepare_key_attestation; use zeroize::Zeroize; use crate::requests::{ResponseStatus, Result}; use log::error; use psa_algorithm::algorithm::{aead::AeadWithDefaultLengthTag, key_agreement::Raw, Cipher, Hash}; use psa_key_attributes::key_type::{DhFamily, EccFamily}; use can_do_crypto::CheckType; use std::convert::TryFrom; impl TryFrom for Cipher { type Error = ResponseStatus; fn try_from(cipher_val: i32) -> Result { Cipher::from_i32(cipher_val).ok_or_else(|| { error!( "Value {} not supported as a cipher algorithm encoding.", cipher_val ); ResponseStatus::InvalidEncoding }) } } impl TryFrom for Hash { type Error = ResponseStatus; fn try_from(hash_val: i32) -> Result { Hash::from_i32(hash_val).ok_or_else(|| { error!( "Value {} not supported as a hash algorithm encoding.", hash_val ); ResponseStatus::InvalidEncoding }) } } impl TryFrom for AeadWithDefaultLengthTag { type Error = ResponseStatus; fn try_from(aead_val: i32) -> Result { AeadWithDefaultLengthTag::from_i32(aead_val).ok_or_else(|| { error!( "Value {} not supported as an AEAD with default tag length algorithm encoding.", aead_val ); ResponseStatus::InvalidEncoding }) } } impl TryFrom for Raw { type Error = ResponseStatus; fn try_from(key_agreement_val: i32) -> Result { Raw::from_i32(key_agreement_val).ok_or_else(|| { error!( "Value {} not supported as a raw key agreement algorithm encoding.", key_agreement_val ); ResponseStatus::InvalidEncoding }) } } impl TryFrom for EccFamily { type Error = ResponseStatus; fn try_from(ecc_family_val: i32) -> Result { EccFamily::from_i32(ecc_family_val).ok_or_else(|| { error!( "Value {} not supported as an ECC family encoding.", ecc_family_val ); ResponseStatus::InvalidEncoding }) } } impl TryFrom for DhFamily { type Error = ResponseStatus; fn try_from(dh_family_val: i32) -> Result { DhFamily::from_i32(dh_family_val).ok_or_else(|| { error!( "Value {} not supported as a DH family encoding.", dh_family_val ); ResponseStatus::InvalidEncoding }) } } impl TryFrom for CheckType { type Error = ResponseStatus; fn try_from(check_type_val: i32) -> Result { CheckType::from_i32(check_type_val).ok_or_else(|| { error!( "Value {} not supported as a check type.", check_type_val ); ResponseStatus::InvalidEncoding }) } } pub(super) trait ClearProtoMessage { fn clear_message(&mut self) {} } // Implement a no-op zeroize for types that don't contain sensitive data macro_rules! empty_clear_message { ($type:ty) => { impl ClearProtoMessage for $type { fn clear_message(&mut self) {} } }; } empty_clear_message!(list_opcodes::Operation); empty_clear_message!(list_opcodes::Result); empty_clear_message!(list_providers::Operation); empty_clear_message!(list_providers::Result); empty_clear_message!(list_authenticators::Operation); empty_clear_message!(list_authenticators::Result); empty_clear_message!(list_keys::Operation); empty_clear_message!(list_keys::Result); empty_clear_message!(list_clients::Operation); empty_clear_message!(list_clients::Result); empty_clear_message!(delete_client::Operation); empty_clear_message!(delete_client::Result); empty_clear_message!(ping::Operation); empty_clear_message!(ping::Result); empty_clear_message!(psa_destroy_key::Operation); empty_clear_message!(psa_destroy_key::Result); empty_clear_message!(psa_generate_key::Operation); empty_clear_message!(psa_generate_key::Result); empty_clear_message!(psa_export_public_key::Operation); empty_clear_message!(psa_export_key::Operation); empty_clear_message!(psa_import_key::Result); empty_clear_message!(psa_verify_hash::Result); empty_clear_message!(psa_verify_message::Result); empty_clear_message!(psa_generate_random::Operation); empty_clear_message!(psa_hash_compare::Result); empty_clear_message!(can_do_crypto::Operation); empty_clear_message!(can_do_crypto::Result); empty_clear_message!(prepare_key_attestation::Operation); impl ClearProtoMessage for psa_sign_hash::Operation { fn clear_message(&mut self) { self.hash.zeroize(); } } impl ClearProtoMessage for psa_sign_hash::Result { fn clear_message(&mut self) { self.signature.zeroize(); } } impl ClearProtoMessage for psa_verify_hash::Operation { fn clear_message(&mut self) { self.hash.zeroize(); self.signature.zeroize(); } } impl ClearProtoMessage for psa_sign_message::Operation { fn clear_message(&mut self) { self.message.zeroize(); } } impl ClearProtoMessage for psa_sign_message::Result { fn clear_message(&mut self) { self.signature.zeroize(); } } impl ClearProtoMessage for psa_verify_message::Operation { fn clear_message(&mut self) { self.message.zeroize(); self.signature.zeroize(); } } impl ClearProtoMessage for psa_import_key::Operation { fn clear_message(&mut self) { self.data.zeroize(); } } impl ClearProtoMessage for psa_export_public_key::Result { fn clear_message(&mut self) { self.data.zeroize(); } } impl ClearProtoMessage for psa_export_key::Result { fn clear_message(&mut self) { self.data.zeroize(); } } impl ClearProtoMessage for psa_asymmetric_encrypt::Operation { fn clear_message(&mut self) { self.plaintext.zeroize(); self.salt.zeroize(); } } impl ClearProtoMessage for psa_asymmetric_decrypt::Operation { fn clear_message(&mut self) { self.salt.zeroize(); self.ciphertext.zeroize(); } } impl ClearProtoMessage for psa_asymmetric_encrypt::Result { fn clear_message(&mut self) { self.ciphertext.zeroize(); } } impl ClearProtoMessage for psa_asymmetric_decrypt::Result { fn clear_message(&mut self) { self.plaintext.zeroize(); } } impl ClearProtoMessage for psa_aead_encrypt::Operation { fn clear_message(&mut self) { self.plaintext.zeroize(); self.additional_data.zeroize(); self.nonce.zeroize(); } } impl ClearProtoMessage for psa_aead_decrypt::Operation { fn clear_message(&mut self) { self.additional_data.zeroize(); self.nonce.zeroize(); self.ciphertext.zeroize(); } } impl ClearProtoMessage for psa_aead_encrypt::Result { fn clear_message(&mut self) { self.ciphertext.zeroize(); } } impl ClearProtoMessage for psa_aead_decrypt::Result { fn clear_message(&mut self) { self.plaintext.zeroize() } } impl ClearProtoMessage for psa_cipher_encrypt::Operation { fn clear_message(&mut self) { self.plaintext.zeroize(); } } impl ClearProtoMessage for psa_cipher_decrypt::Operation { fn clear_message(&mut self) { self.ciphertext.zeroize(); } } impl ClearProtoMessage for psa_cipher_encrypt::Result { fn clear_message(&mut self) { self.ciphertext.zeroize(); } } impl ClearProtoMessage for psa_cipher_decrypt::Result { fn clear_message(&mut self) { self.plaintext.zeroize(); } } impl ClearProtoMessage for psa_generate_random::Result { fn clear_message(&mut self) { self.random_bytes.zeroize(); } } impl ClearProtoMessage for psa_hash_compute::Operation { fn clear_message(&mut self) { self.input.zeroize(); } } impl ClearProtoMessage for psa_hash_compute::Result { fn clear_message(&mut self) { self.hash.zeroize(); } } impl ClearProtoMessage for psa_hash_compare::Operation { fn clear_message(&mut self) { self.input.zeroize(); self.hash.zeroize(); } } impl ClearProtoMessage for psa_raw_key_agreement::Operation { fn clear_message(&mut self) { self.peer_key.zeroize(); } } impl ClearProtoMessage for psa_raw_key_agreement::Result { fn clear_message(&mut self) { self.shared_secret.zeroize(); } } impl ClearProtoMessage for attest_key::Operation { fn clear_message(&mut self) { if let attest_key::Operation { parameters: Some(attest_key::AttestationMechanismParams { mechanism: Some(attest_key::attestation_mechanism_params::Mechanism::ActivateCredential( attest_key::attestation_mechanism_params::ActivateCredential { credential_blob, secret, }, )), }), .. } = self { credential_blob.zeroize(); secret.zeroize(); } } } impl ClearProtoMessage for attest_key::Result { fn clear_message(&mut self) { if let attest_key::Result { output: Some(attest_key::AttestationOutput { mechanism: Some(attest_key::attestation_output::Mechanism::ActivateCredential( attest_key::attestation_output::ActivateCredential { credential }, )), }), } = self { credential.zeroize(); } } } impl ClearProtoMessage for prepare_key_attestation::Result { fn clear_message(&mut self) { if let prepare_key_attestation::Result { output: Some(prepare_key_attestation::PrepareKeyAttestationOutput { mechanism: Some(prepare_key_attestation::prepare_key_attestation_output::Mechanism::ActivateCredential( prepare_key_attestation::prepare_key_attestation_output::ActivateCredential { name, public, attesting_key_pub } )) }) } = self { name.zeroize(); public.zeroize(); attesting_key_pub.zeroize(); } } } #[test] fn i32_conversions() { assert_eq!( Cipher::try_from(56).unwrap_err(), ResponseStatus::InvalidEncoding ); assert_eq!( Cipher::try_from(-5).unwrap_err(), ResponseStatus::InvalidEncoding ); assert_eq!( Hash::try_from(89).unwrap_err(), ResponseStatus::InvalidEncoding ); assert_eq!( Hash::try_from(-4).unwrap_err(), ResponseStatus::InvalidEncoding ); assert_eq!( EccFamily::try_from(78).unwrap_err(), ResponseStatus::InvalidEncoding ); } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/ping.rs000064400000000000000000000005171046102023000241470ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { /// Cast down to 8 bits #[prost(uint32, tag="1")] pub wire_protocol_version_maj: u32, /// Cast down to 8 bits #[prost(uint32, tag="2")] pub wire_protocol_version_min: u32, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/prepare_key_attestation.rs000064400000000000000000000040161046102023000301350ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct PrepareKeyAttestationParams { #[prost(oneof="prepare_key_attestation_params::Mechanism", tags="1")] pub mechanism: ::core::option::Option, } /// Nested message and enum types in `PrepareKeyAttestationParams`. pub mod prepare_key_attestation_params { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActivateCredential { #[prost(string, tag="1")] pub attested_key_name: ::prost::alloc::string::String, #[prost(string, tag="2")] pub attesting_key_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Mechanism { #[prost(message, tag="1")] ActivateCredential(ActivateCredential), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(message, optional, tag="1")] pub parameters: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct PrepareKeyAttestationOutput { #[prost(oneof="prepare_key_attestation_output::Mechanism", tags="1")] pub mechanism: ::core::option::Option, } /// Nested message and enum types in `PrepareKeyAttestationOutput`. pub mod prepare_key_attestation_output { #[derive(Clone, PartialEq, ::prost::Message)] pub struct ActivateCredential { #[prost(bytes="vec", tag="1")] pub name: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="2")] pub public: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="3")] pub attesting_key_pub: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Mechanism { #[prost(message, tag="1")] ActivateCredential(ActivateCredential), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(message, optional, tag="1")] pub output: ::core::option::Option, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_aead_decrypt.rs000064400000000000000000000012431046102023000264760ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub nonce: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub additional_data: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="5")] pub ciphertext: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub plaintext: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_aead_encrypt.rs000064400000000000000000000012431046102023000265100ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub nonce: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub additional_data: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="5")] pub plaintext: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub ciphertext: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_algorithm.rs000064400000000000000000000247671046102023000260600ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Algorithm { #[prost(oneof="algorithm::Variant", tags="1, 2, 3, 4, 5, 6, 7, 8, 9")] pub variant: ::core::option::Option, } /// Nested message and enum types in `Algorithm`. pub mod algorithm { #[derive(Clone, PartialEq, ::prost::Message)] pub struct None { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Mac { #[prost(oneof="mac::Variant", tags="1, 2")] pub variant: ::core::option::Option, } /// Nested message and enum types in `Mac`. pub mod mac { #[derive(Clone, PartialEq, ::prost::Message)] pub struct FullLength { #[prost(oneof="full_length::Variant", tags="1, 2, 3")] pub variant: ::core::option::Option, } /// Nested message and enum types in `FullLength`. pub mod full_length { #[derive(Clone, PartialEq, ::prost::Message)] pub struct Hmac { #[prost(enumeration="super::super::Hash", tag="1")] pub hash_alg: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct CbcMac { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Cmac { } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] Hmac(Hmac), #[prost(message, tag="2")] CbcMac(CbcMac), #[prost(message, tag="3")] Cmac(Cmac), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Truncated { #[prost(message, optional, tag="1")] pub mac_alg: ::core::option::Option, #[prost(uint32, tag="2")] pub mac_length: u32, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] FullLength(FullLength), #[prost(message, tag="2")] Truncated(Truncated), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Aead { #[prost(oneof="aead::Variant", tags="1, 2")] pub variant: ::core::option::Option, } /// Nested message and enum types in `Aead`. pub mod aead { #[derive(Clone, PartialEq, ::prost::Message)] pub struct AeadWithShortenedTag { #[prost(enumeration="AeadWithDefaultLengthTag", tag="1")] pub aead_alg: i32, #[prost(uint32, tag="2")] pub tag_length: u32, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum AeadWithDefaultLengthTag { /// This default variant should not be used. None = 0, Ccm = 1, Gcm = 2, Chacha20Poly1305 = 3, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(enumeration="AeadWithDefaultLengthTag", tag="1")] AeadWithDefaultLengthTag(i32), #[prost(message, tag="2")] AeadWithShortenedTag(AeadWithShortenedTag), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AsymmetricSignature { #[prost(oneof="asymmetric_signature::Variant", tags="1, 2, 3, 4, 5, 6")] pub variant: ::core::option::Option, } /// Nested message and enum types in `AsymmetricSignature`. pub mod asymmetric_signature { #[derive(Clone, PartialEq, ::prost::Message)] pub struct SignHash { #[prost(oneof="sign_hash::Variant", tags="1, 2")] pub variant: ::core::option::Option, } /// Nested message and enum types in `SignHash`. pub mod sign_hash { #[derive(Clone, PartialEq, ::prost::Message)] pub struct Any { } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] Any(Any), #[prost(enumeration="super::super::Hash", tag="2")] Specific(i32), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaPkcs1v15Sign { #[prost(message, optional, tag="1")] pub hash_alg: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaPkcs1v15SignRaw { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaPss { #[prost(message, optional, tag="1")] pub hash_alg: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Ecdsa { #[prost(message, optional, tag="1")] pub hash_alg: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct EcdsaAny { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeterministicEcdsa { #[prost(message, optional, tag="1")] pub hash_alg: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] RsaPkcs1v15Sign(RsaPkcs1v15Sign), #[prost(message, tag="2")] RsaPkcs1v15SignRaw(RsaPkcs1v15SignRaw), #[prost(message, tag="3")] RsaPss(RsaPss), #[prost(message, tag="4")] Ecdsa(Ecdsa), #[prost(message, tag="5")] EcdsaAny(EcdsaAny), #[prost(message, tag="6")] DeterministicEcdsa(DeterministicEcdsa), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AsymmetricEncryption { #[prost(oneof="asymmetric_encryption::Variant", tags="1, 2")] pub variant: ::core::option::Option, } /// Nested message and enum types in `AsymmetricEncryption`. pub mod asymmetric_encryption { #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaPkcs1v15Crypt { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaOaep { #[prost(enumeration="super::Hash", tag="1")] pub hash_alg: i32, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] RsaPkcs1v15Crypt(RsaPkcs1v15Crypt), #[prost(message, tag="2")] RsaOaep(RsaOaep), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyAgreement { #[prost(oneof="key_agreement::Variant", tags="1, 2")] pub variant: ::core::option::Option, } /// Nested message and enum types in `KeyAgreement`. pub mod key_agreement { #[derive(Clone, PartialEq, ::prost::Message)] pub struct WithKeyDerivation { #[prost(enumeration="Raw", tag="1")] pub ka_alg: i32, #[prost(message, optional, tag="2")] pub kdf_alg: ::core::option::Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Raw { /// This default variant should not be used. None = 0, Ffdh = 1, Ecdh = 2, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(enumeration="Raw", tag="1")] Raw(i32), #[prost(message, tag="2")] WithKeyDerivation(WithKeyDerivation), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyDerivation { #[prost(oneof="key_derivation::Variant", tags="1, 2, 3")] pub variant: ::core::option::Option, } /// Nested message and enum types in `KeyDerivation`. pub mod key_derivation { #[derive(Clone, PartialEq, ::prost::Message)] pub struct Hkdf { #[prost(enumeration="super::Hash", tag="1")] pub hash_alg: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Tls12Prf { #[prost(enumeration="super::Hash", tag="1")] pub hash_alg: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Tls12PskToMs { #[prost(enumeration="super::Hash", tag="1")] pub hash_alg: i32, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] Hkdf(Hkdf), #[prost(message, tag="2")] Tls12Prf(Tls12Prf), #[prost(message, tag="3")] Tls12PskToMs(Tls12PskToMs), } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Hash { /// This default variant should not be used. None = 0, Md2 = 1, Md4 = 2, Md5 = 3, Ripemd160 = 4, Sha1 = 5, Sha224 = 6, Sha256 = 7, Sha384 = 8, Sha512 = 9, Sha512224 = 10, Sha512256 = 11, Sha3224 = 12, Sha3256 = 13, Sha3384 = 14, Sha3512 = 15, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum Cipher { /// This default variant should not be used. None = 0, StreamCipher = 1, Ctr = 2, Cfb = 3, Ofb = 4, Xts = 5, EcbNoPadding = 6, CbcNoPadding = 7, CbcPkcs7 = 8, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] None(None), #[prost(enumeration="Hash", tag="2")] Hash(i32), #[prost(message, tag="3")] Mac(Mac), #[prost(enumeration="Cipher", tag="4")] Cipher(i32), #[prost(message, tag="5")] Aead(Aead), #[prost(message, tag="6")] AsymmetricSignature(AsymmetricSignature), #[prost(message, tag="7")] AsymmetricEncryption(AsymmetricEncryption), #[prost(message, tag="8")] KeyAgreement(KeyAgreement), #[prost(message, tag="9")] KeyDerivation(KeyDerivation), } } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_asymmetric_decrypt.rs000064400000000000000000000011301046102023000277540ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub ciphertext: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub salt: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub plaintext: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_asymmetric_encrypt.rs000064400000000000000000000011301046102023000277660ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub plaintext: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub salt: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub ciphertext: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_cipher_decrypt.rs000064400000000000000000000007431046102023000270620ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(enumeration="super::psa_algorithm::algorithm::Cipher", tag="2")] pub alg: i32, #[prost(bytes="vec", tag="3")] pub ciphertext: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub plaintext: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_cipher_encrypt.rs000064400000000000000000000007431046102023000270740ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(enumeration="super::psa_algorithm::algorithm::Cipher", tag="2")] pub alg: i32, #[prost(bytes="vec", tag="3")] pub plaintext: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub ciphertext: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_destroy_key.rs000064400000000000000000000003331046102023000264120ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_export_key.rs000064400000000000000000000004521046102023000262440ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub data: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_export_public_key.rs000064400000000000000000000004521046102023000276020ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub data: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_generate_key.rs000064400000000000000000000005321046102023000265140ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub attributes: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_generate_random.rs000064400000000000000000000004231046102023000272030ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(uint64, tag="1")] pub size: u64, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub random_bytes: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_hash_compare.rs000064400000000000000000000006071046102023000265060ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(enumeration="super::psa_algorithm::algorithm::Hash", tag="1")] pub alg: i32, #[prost(bytes="vec", tag="2")] pub input: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="3")] pub hash: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_hash_compute.rs000064400000000000000000000006071046102023000265340ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(enumeration="super::psa_algorithm::algorithm::Hash", tag="1")] pub alg: i32, #[prost(bytes="vec", tag="2")] pub input: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub hash: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_import_key.rs000064400000000000000000000006511046102023000262360ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub attributes: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub data: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_key_attributes.rs000064400000000000000000000112051046102023000271070ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyAttributes { #[prost(message, optional, tag="1")] pub key_type: ::core::option::Option, #[prost(uint32, tag="2")] pub key_bits: u32, #[prost(message, optional, tag="3")] pub key_policy: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyType { #[prost(oneof="key_type::Variant", tags="1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14")] pub variant: ::core::option::Option, } /// Nested message and enum types in `KeyType`. pub mod key_type { #[derive(Clone, PartialEq, ::prost::Message)] pub struct RawData { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Hmac { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Derive { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Aes { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Des { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Camellia { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Arc4 { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Chacha20 { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaPublicKey { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RsaKeyPair { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct EccKeyPair { #[prost(enumeration="EccFamily", tag="1")] pub curve_family: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct EccPublicKey { #[prost(enumeration="EccFamily", tag="1")] pub curve_family: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DhKeyPair { #[prost(enumeration="DhFamily", tag="1")] pub group_family: i32, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DhPublicKey { #[prost(enumeration="DhFamily", tag="1")] pub group_family: i32, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum EccFamily { /// This default variant should not be used. None = 0, SecpK1 = 1, SecpR1 = 2, SecpR2 = 3, /// DEPRECATED for sect163k1 curve SectK1 = 4, /// DEPRECATED for sect163r1 curve SectR1 = 5, SectR2 = 6, /// DEPRECATED for brainpoolP160r1 curve BrainpoolPR1 = 7, Frp = 8, Montgomery = 9, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum DhFamily { Rfc7919 = 0, } #[derive(Clone, PartialEq, ::prost::Oneof)] pub enum Variant { #[prost(message, tag="1")] RawData(RawData), /// Symmetric keys #[prost(message, tag="2")] Hmac(Hmac), #[prost(message, tag="3")] Derive(Derive), #[prost(message, tag="4")] Aes(Aes), #[prost(message, tag="5")] Des(Des), #[prost(message, tag="6")] Camellia(Camellia), #[prost(message, tag="7")] Arc4(Arc4), #[prost(message, tag="8")] Chacha20(Chacha20), /// RSA keys #[prost(message, tag="9")] RsaPublicKey(RsaPublicKey), #[prost(message, tag="10")] RsaKeyPair(RsaKeyPair), /// Elliptic Curve keys #[prost(message, tag="11")] EccKeyPair(EccKeyPair), #[prost(message, tag="12")] EccPublicKey(EccPublicKey), /// Finite Field Diffie Hellman keys #[prost(message, tag="13")] DhKeyPair(DhKeyPair), #[prost(message, tag="14")] DhPublicKey(DhPublicKey), } } #[derive(Clone, PartialEq, ::prost::Message)] pub struct KeyPolicy { #[prost(message, optional, tag="1")] pub key_usage_flags: ::core::option::Option, #[prost(message, optional, tag="2")] pub key_algorithm: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct UsageFlags { #[prost(bool, tag="1")] pub export: bool, #[prost(bool, tag="2")] pub copy: bool, #[prost(bool, tag="3")] pub cache: bool, #[prost(bool, tag="4")] pub encrypt: bool, #[prost(bool, tag="5")] pub decrypt: bool, #[prost(bool, tag="6")] pub sign_message: bool, #[prost(bool, tag="7")] pub verify_message: bool, #[prost(bool, tag="8")] pub sign_hash: bool, #[prost(bool, tag="9")] pub verify_hash: bool, #[prost(bool, tag="10")] pub derive: bool, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_mac_compute.rs000064400000000000000000000007551046102023000263550ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub input: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub mac: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_mac_verify.rs000064400000000000000000000007551046102023000262050ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub input: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub mac: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_raw_key_agreement.rs000064400000000000000000000007711046102023000275470ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(enumeration="super::psa_algorithm::algorithm::key_agreement::Raw", tag="1")] pub alg: i32, #[prost(string, tag="2")] pub private_key_name: ::prost::alloc::string::String, #[prost(bytes="vec", tag="3")] pub peer_key: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub shared_secret: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_sign_hash.rs000064400000000000000000000010021046102023000260060ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub hash: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub signature: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_sign_message.rs000064400000000000000000000010051046102023000265120ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub message: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { #[prost(bytes="vec", tag="1")] pub signature: ::prost::alloc::vec::Vec, } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_verify_hash.rs000064400000000000000000000010021046102023000263520ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub hash: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub signature: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/generated_ops/psa_verify_message.rs000064400000000000000000000010051046102023000270560ustar 00000000000000#[derive(Clone, PartialEq, ::prost::Message)] pub struct Operation { #[prost(string, tag="1")] pub key_name: ::prost::alloc::string::String, #[prost(message, optional, tag="2")] pub alg: ::core::option::Option, #[prost(bytes="vec", tag="3")] pub message: ::prost::alloc::vec::Vec, #[prost(bytes="vec", tag="4")] pub signature: ::prost::alloc::vec::Vec, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Result { } parsec-interface-0.29.1/src/operations_protobuf/mod.rs000064400000000000000000000624451046102023000211620ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # Protobuf converter //! //! This module exposes the `ProtobufConverter` struct that implements the `Convert` trait. mod convert_psa_algorithm; mod convert_ping; mod convert_psa_generate_key; mod convert_psa_key_attributes; mod convert_psa_import_key; mod convert_psa_export_public_key; mod convert_psa_export_key; mod convert_psa_destroy_key; mod convert_psa_sign_hash; mod convert_psa_verify_hash; mod convert_psa_sign_message; mod convert_psa_verify_message; mod convert_psa_hash_compute; mod convert_psa_hash_compare; mod convert_list_providers; mod convert_list_opcodes; mod convert_list_authenticators; mod convert_list_keys; mod convert_list_clients; mod convert_delete_client; mod convert_psa_asymmetric_encrypt; mod convert_psa_asymmetric_decrypt; mod convert_psa_aead_encrypt; mod convert_psa_aead_decrypt; mod convert_psa_cipher_encrypt; mod convert_psa_cipher_decrypt; mod convert_psa_generate_random; mod convert_psa_raw_key_agreement; mod convert_can_do_crypto; mod convert_attest_key; mod convert_prepare_key_attestation; #[rustfmt::skip] #[allow(unused_qualifications, missing_copy_implementations, clippy::pedantic, clippy::module_inception, clippy::upper_case_acronyms, clippy::enum_variant_names)] mod generated_ops; use crate::operations::{Convert, NativeOperation, NativeResult}; use crate::requests::{ request::RequestBody, response::ResponseBody, BodyType, Opcode, ResponseStatus, Result, }; use generated_ops::attest_key as attest_key_proto; use generated_ops::can_do_crypto as can_do_crypto_proto; use generated_ops::delete_client as delete_client_proto; use generated_ops::list_authenticators as list_authenticators_proto; use generated_ops::list_clients as list_clients_proto; use generated_ops::list_keys as list_keys_proto; use generated_ops::list_opcodes as list_opcodes_proto; use generated_ops::list_providers as list_providers_proto; use generated_ops::ping as ping_proto; use generated_ops::prepare_key_attestation as prepare_key_attestation_proto; use generated_ops::psa_aead_decrypt as psa_aead_decrypt_proto; use generated_ops::psa_aead_encrypt as psa_aead_encrypt_proto; use generated_ops::psa_asymmetric_decrypt as psa_asymmetric_decrypt_proto; use generated_ops::psa_asymmetric_encrypt as psa_asymmetric_encrypt_proto; use generated_ops::psa_cipher_decrypt as psa_cipher_decrypt_proto; use generated_ops::psa_cipher_encrypt as psa_cipher_encrypt_proto; use generated_ops::psa_destroy_key as psa_destroy_key_proto; use generated_ops::psa_export_key as psa_export_key_proto; use generated_ops::psa_export_public_key as psa_export_public_key_proto; use generated_ops::psa_generate_key as psa_generate_key_proto; use generated_ops::psa_generate_random as psa_generate_random_proto; use generated_ops::psa_hash_compare as psa_hash_compare_proto; use generated_ops::psa_hash_compute as psa_hash_compute_proto; use generated_ops::psa_import_key as psa_import_key_proto; use generated_ops::psa_raw_key_agreement as psa_raw_key_agreement_proto; use generated_ops::psa_sign_hash as psa_sign_hash_proto; use generated_ops::psa_sign_message as psa_sign_message_proto; use generated_ops::psa_verify_hash as psa_verify_hash_proto; use generated_ops::psa_verify_message as psa_verify_message_proto; use generated_ops::ClearProtoMessage; use prost::Message; use std::convert::TryInto; macro_rules! wire_to_native { ($body:expr, $proto_type:ty) => {{ let mut proto: $proto_type = Default::default(); if proto.merge($body).is_err() { return Err(ResponseStatus::DeserializingBodyFailed); } proto.try_into()? }}; } macro_rules! native_to_wire { ($native_msg:expr, $proto_type:ty) => {{ let mut proto: $proto_type = $native_msg.try_into()?; let mut bytes = Vec::new(); if proto.encode(&mut bytes).is_err() { proto.clear_message(); return Err(ResponseStatus::SerializingBodyFailed); } proto.clear_message(); bytes }}; } /// Implementation for a converter between protobuf-encoded bodies and native /// objects. #[derive(Copy, Clone, Debug)] pub struct ProtobufConverter; impl Convert for ProtobufConverter { fn body_type(&self) -> BodyType { BodyType::Protobuf } fn body_to_operation(&self, body: RequestBody, opcode: Opcode) -> Result { match opcode { Opcode::ListProviders => Ok(NativeOperation::ListProviders(wire_to_native!( body.bytes(), list_providers_proto::Operation ))), Opcode::ListOpcodes => Ok(NativeOperation::ListOpcodes(wire_to_native!( body.bytes(), list_opcodes_proto::Operation ))), Opcode::ListAuthenticators => Ok(NativeOperation::ListAuthenticators(wire_to_native!( body.bytes(), list_authenticators_proto::Operation ))), Opcode::ListKeys => Ok(NativeOperation::ListKeys(wire_to_native!( body.bytes(), list_keys_proto::Operation ))), Opcode::ListClients => Ok(NativeOperation::ListClients(wire_to_native!( body.bytes(), list_clients_proto::Operation ))), Opcode::DeleteClient => Ok(NativeOperation::DeleteClient(wire_to_native!( body.bytes(), delete_client_proto::Operation ))), Opcode::Ping => Ok(NativeOperation::Ping(wire_to_native!( body.bytes(), ping_proto::Operation ))), Opcode::PsaGenerateKey => Ok(NativeOperation::PsaGenerateKey(wire_to_native!( body.bytes(), psa_generate_key_proto::Operation ))), Opcode::PsaImportKey => Ok(NativeOperation::PsaImportKey(wire_to_native!( body.bytes(), psa_import_key_proto::Operation ))), Opcode::PsaExportPublicKey => Ok(NativeOperation::PsaExportPublicKey(wire_to_native!( body.bytes(), psa_export_public_key_proto::Operation ))), Opcode::PsaExportKey => Ok(NativeOperation::PsaExportKey(wire_to_native!( body.bytes(), psa_export_key_proto::Operation ))), Opcode::PsaDestroyKey => Ok(NativeOperation::PsaDestroyKey(wire_to_native!( body.bytes(), psa_destroy_key_proto::Operation ))), Opcode::PsaSignHash => Ok(NativeOperation::PsaSignHash(wire_to_native!( body.bytes(), psa_sign_hash_proto::Operation ))), Opcode::PsaVerifyHash => Ok(NativeOperation::PsaVerifyHash(wire_to_native!( body.bytes(), psa_verify_hash_proto::Operation ))), Opcode::PsaSignMessage => Ok(NativeOperation::PsaSignMessage(wire_to_native!( body.bytes(), psa_sign_message_proto::Operation ))), Opcode::PsaVerifyMessage => Ok(NativeOperation::PsaVerifyMessage(wire_to_native!( body.bytes(), psa_verify_message_proto::Operation ))), Opcode::PsaAsymmetricEncrypt => Ok(NativeOperation::PsaAsymmetricEncrypt( wire_to_native!(body.bytes(), psa_asymmetric_encrypt_proto::Operation), )), Opcode::PsaAsymmetricDecrypt => Ok(NativeOperation::PsaAsymmetricDecrypt( wire_to_native!(body.bytes(), psa_asymmetric_decrypt_proto::Operation), )), Opcode::PsaAeadEncrypt => Ok(NativeOperation::PsaAeadEncrypt(wire_to_native!( body.bytes(), psa_aead_encrypt_proto::Operation ))), Opcode::PsaAeadDecrypt => Ok(NativeOperation::PsaAeadDecrypt(wire_to_native!( body.bytes(), psa_aead_decrypt_proto::Operation ))), Opcode::PsaCipherEncrypt => Ok(NativeOperation::PsaCipherEncrypt(wire_to_native!( body.bytes(), psa_cipher_encrypt_proto::Operation ))), Opcode::PsaCipherDecrypt => Ok(NativeOperation::PsaCipherDecrypt(wire_to_native!( body.bytes(), psa_cipher_decrypt_proto::Operation ))), Opcode::PsaGenerateRandom => Ok(NativeOperation::PsaGenerateRandom(wire_to_native!( body.bytes(), psa_generate_random_proto::Operation ))), Opcode::PsaHashCompare => Ok(NativeOperation::PsaHashCompare(wire_to_native!( body.bytes(), psa_hash_compare_proto::Operation ))), Opcode::PsaHashCompute => Ok(NativeOperation::PsaHashCompute(wire_to_native!( body.bytes(), psa_hash_compute_proto::Operation ))), Opcode::PsaRawKeyAgreement => Ok(NativeOperation::PsaRawKeyAgreement(wire_to_native!( body.bytes(), psa_raw_key_agreement_proto::Operation ))), Opcode::CanDoCrypto => Ok(NativeOperation::CanDoCrypto(wire_to_native!( body.bytes(), can_do_crypto_proto::Operation ))), Opcode::AttestKey => Ok(NativeOperation::AttestKey(wire_to_native!( body.bytes(), attest_key_proto::Operation ))), Opcode::PrepareKeyAttestation => Ok(NativeOperation::PrepareKeyAttestation( wire_to_native!(body.bytes(), prepare_key_attestation_proto::Operation), )), } } fn operation_to_body(&self, operation: NativeOperation) -> Result { match operation { NativeOperation::ListProviders(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, list_providers_proto::Operation), )), NativeOperation::ListOpcodes(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, list_opcodes_proto::Operation), )), NativeOperation::ListAuthenticators(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, list_authenticators_proto::Operation), )), NativeOperation::ListKeys(operation) => Ok(RequestBody::from_bytes(native_to_wire!( operation, list_keys_proto::Operation ))), NativeOperation::ListClients(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, list_clients_proto::Operation), )), NativeOperation::DeleteClient(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, delete_client_proto::Operation), )), NativeOperation::Ping(operation) => Ok(RequestBody::from_bytes(native_to_wire!( operation, ping_proto::Operation ))), NativeOperation::PsaGenerateKey(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_generate_key_proto::Operation), )), NativeOperation::PsaImportKey(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_import_key_proto::Operation), )), NativeOperation::PsaExportPublicKey(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_export_public_key_proto::Operation), )), NativeOperation::PsaExportKey(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_export_key_proto::Operation), )), NativeOperation::PsaDestroyKey(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_destroy_key_proto::Operation), )), NativeOperation::PsaSignHash(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_sign_hash_proto::Operation), )), NativeOperation::PsaVerifyHash(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_verify_hash_proto::Operation), )), NativeOperation::PsaSignMessage(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_sign_message_proto::Operation), )), NativeOperation::PsaVerifyMessage(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_verify_message_proto::Operation), )), NativeOperation::PsaAsymmetricEncrypt(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_asymmetric_encrypt_proto::Operation), )), NativeOperation::PsaAsymmetricDecrypt(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_asymmetric_decrypt_proto::Operation), )), NativeOperation::PsaAeadEncrypt(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_aead_encrypt_proto::Operation), )), NativeOperation::PsaAeadDecrypt(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_aead_decrypt_proto::Operation), )), NativeOperation::PsaCipherEncrypt(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_cipher_encrypt_proto::Operation), )), NativeOperation::PsaCipherDecrypt(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_cipher_decrypt_proto::Operation), )), NativeOperation::PsaGenerateRandom(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_generate_random_proto::Operation), )), NativeOperation::PsaHashCompare(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_hash_compare_proto::Operation), )), NativeOperation::PsaHashCompute(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_hash_compute_proto::Operation), )), NativeOperation::PsaRawKeyAgreement(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, psa_raw_key_agreement_proto::Operation), )), NativeOperation::CanDoCrypto(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, can_do_crypto_proto::Operation), )), NativeOperation::AttestKey(operation) => Ok(RequestBody::from_bytes(native_to_wire!( operation, attest_key_proto::Operation ))), NativeOperation::PrepareKeyAttestation(operation) => Ok(RequestBody::from_bytes( native_to_wire!(operation, prepare_key_attestation_proto::Operation), )), } } fn body_to_result(&self, body: ResponseBody, opcode: Opcode) -> Result { match opcode { Opcode::ListProviders => Ok(NativeResult::ListProviders(wire_to_native!( body.bytes(), list_providers_proto::Result ))), Opcode::ListOpcodes => Ok(NativeResult::ListOpcodes(wire_to_native!( body.bytes(), list_opcodes_proto::Result ))), Opcode::ListAuthenticators => Ok(NativeResult::ListAuthenticators(wire_to_native!( body.bytes(), list_authenticators_proto::Result ))), Opcode::ListKeys => Ok(NativeResult::ListKeys(wire_to_native!( body.bytes(), list_keys_proto::Result ))), Opcode::ListClients => Ok(NativeResult::ListClients(wire_to_native!( body.bytes(), list_clients_proto::Result ))), Opcode::DeleteClient => Ok(NativeResult::DeleteClient(wire_to_native!( body.bytes(), delete_client_proto::Result ))), Opcode::Ping => Ok(NativeResult::Ping(wire_to_native!( body.bytes(), ping_proto::Result ))), Opcode::PsaGenerateKey => Ok(NativeResult::PsaGenerateKey(wire_to_native!( body.bytes(), psa_generate_key_proto::Result ))), Opcode::PsaImportKey => Ok(NativeResult::PsaImportKey(wire_to_native!( body.bytes(), psa_import_key_proto::Result ))), Opcode::PsaExportPublicKey => Ok(NativeResult::PsaExportPublicKey(wire_to_native!( body.bytes(), psa_export_public_key_proto::Result ))), Opcode::PsaExportKey => Ok(NativeResult::PsaExportKey(wire_to_native!( body.bytes(), psa_export_key_proto::Result ))), Opcode::PsaDestroyKey => Ok(NativeResult::PsaDestroyKey(wire_to_native!( body.bytes(), psa_destroy_key_proto::Result ))), Opcode::PsaSignHash => Ok(NativeResult::PsaSignHash(wire_to_native!( body.bytes(), psa_sign_hash_proto::Result ))), Opcode::PsaVerifyHash => Ok(NativeResult::PsaVerifyHash(wire_to_native!( body.bytes(), psa_verify_hash_proto::Result ))), Opcode::PsaSignMessage => Ok(NativeResult::PsaSignMessage(wire_to_native!( body.bytes(), psa_sign_message_proto::Result ))), Opcode::PsaVerifyMessage => Ok(NativeResult::PsaVerifyMessage(wire_to_native!( body.bytes(), psa_verify_message_proto::Result ))), Opcode::PsaAsymmetricEncrypt => Ok(NativeResult::PsaAsymmetricEncrypt( wire_to_native!(body.bytes(), psa_asymmetric_encrypt_proto::Result), )), Opcode::PsaAsymmetricDecrypt => Ok(NativeResult::PsaAsymmetricDecrypt( wire_to_native!(body.bytes(), psa_asymmetric_decrypt_proto::Result), )), Opcode::PsaAeadEncrypt => Ok(NativeResult::PsaAeadEncrypt(wire_to_native!( body.bytes(), psa_aead_encrypt_proto::Result ))), Opcode::PsaAeadDecrypt => Ok(NativeResult::PsaAeadDecrypt(wire_to_native!( body.bytes(), psa_aead_decrypt_proto::Result ))), Opcode::PsaCipherEncrypt => Ok(NativeResult::PsaCipherEncrypt(wire_to_native!( body.bytes(), psa_cipher_encrypt_proto::Result ))), Opcode::PsaCipherDecrypt => Ok(NativeResult::PsaCipherDecrypt(wire_to_native!( body.bytes(), psa_cipher_decrypt_proto::Result ))), Opcode::PsaGenerateRandom => Ok(NativeResult::PsaGenerateRandom(wire_to_native!( body.bytes(), psa_generate_random_proto::Result ))), Opcode::PsaHashCompare => Ok(NativeResult::PsaHashCompare(wire_to_native!( body.bytes(), psa_hash_compare_proto::Result ))), Opcode::PsaHashCompute => Ok(NativeResult::PsaHashCompute(wire_to_native!( body.bytes(), psa_hash_compute_proto::Result ))), Opcode::PsaRawKeyAgreement => Ok(NativeResult::PsaRawKeyAgreement(wire_to_native!( body.bytes(), psa_raw_key_agreement_proto::Result ))), Opcode::CanDoCrypto => Ok(NativeResult::CanDoCrypto(wire_to_native!( body.bytes(), can_do_crypto_proto::Result ))), Opcode::AttestKey => Ok(NativeResult::AttestKey(wire_to_native!( body.bytes(), attest_key_proto::Result ))), Opcode::PrepareKeyAttestation => Ok(NativeResult::PrepareKeyAttestation( wire_to_native!(body.bytes(), prepare_key_attestation_proto::Result), )), } } fn result_to_body(&self, result: NativeResult) -> Result { match result { NativeResult::ListProviders(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, list_providers_proto::Result ))), NativeResult::ListOpcodes(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, list_opcodes_proto::Result ))), NativeResult::ListAuthenticators(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, list_authenticators_proto::Result), )), NativeResult::ListKeys(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, list_keys_proto::Result ))), NativeResult::ListClients(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, list_clients_proto::Result ))), NativeResult::DeleteClient(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, delete_client_proto::Result ))), NativeResult::Ping(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, ping_proto::Result ))), NativeResult::PsaGenerateKey(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_generate_key_proto::Result ))), NativeResult::PsaImportKey(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_import_key_proto::Result ))), NativeResult::PsaExportPublicKey(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_export_public_key_proto::Result), )), NativeResult::PsaExportKey(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_export_key_proto::Result ))), NativeResult::PsaDestroyKey(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_destroy_key_proto::Result ))), NativeResult::PsaSignHash(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_sign_hash_proto::Result ))), NativeResult::PsaVerifyHash(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_verify_hash_proto::Result ))), NativeResult::PsaSignMessage(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_sign_message_proto::Result ))), NativeResult::PsaVerifyMessage(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_verify_message_proto::Result), )), NativeResult::PsaAsymmetricEncrypt(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_asymmetric_encrypt_proto::Result), )), NativeResult::PsaAsymmetricDecrypt(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_asymmetric_decrypt_proto::Result), )), NativeResult::PsaAeadEncrypt(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_aead_encrypt_proto::Result ))), NativeResult::PsaAeadDecrypt(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_aead_decrypt_proto::Result ))), NativeResult::PsaCipherEncrypt(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_cipher_encrypt_proto::Result), )), NativeResult::PsaCipherDecrypt(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_cipher_decrypt_proto::Result), )), NativeResult::PsaGenerateRandom(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_generate_random_proto::Result), )), NativeResult::PsaHashCompare(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_hash_compare_proto::Result ))), NativeResult::PsaHashCompute(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, psa_hash_compute_proto::Result ))), NativeResult::PsaRawKeyAgreement(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, psa_raw_key_agreement_proto::Result), )), NativeResult::CanDoCrypto(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, can_do_crypto_proto::Result ))), NativeResult::AttestKey(result) => Ok(ResponseBody::from_bytes(native_to_wire!( result, attest_key_proto::Result ))), NativeResult::PrepareKeyAttestation(result) => Ok(ResponseBody::from_bytes( native_to_wire!(result, prepare_key_attestation_proto::Result), )), } } } parsec-interface-0.29.1/src/requests/common/mod.rs000064400000000000000000000004721046102023000202120ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! This module implements the raw wire protocol header frame for requests and responses in //! all defined versions of the protocol (currently just 1.0). pub mod wire_header_1_0; const MAGIC_NUMBER: u32 = 0x5EC0_A710; parsec-interface-0.29.1/src/requests/common/wire_header_1_0.rs000064400000000000000000000130771046102023000223550ustar 00000000000000// Copyright 2020 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! This module defines and implements the raw wire protocol header frame for //! version 1.0 of the protocol. use crate::requests::common::MAGIC_NUMBER; use crate::requests::{ResponseStatus, Result}; #[cfg(feature = "fuzz")] use arbitrary::Arbitrary; use bincode::Options; use log::error; use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use std::io::{Read, Write}; const WIRE_PROTOCOL_VERSION_MAJ: u8 = 1; const WIRE_PROTOCOL_VERSION_MIN: u8 = 0; const REQUEST_HDR_SIZE: u16 = 30; /// Raw representation of a common request/response header, as defined for the wire format. /// /// Serialisation and deserialisation are handled by `serde`, also in tune with the /// wire format (i.e. little-endian, native encoding). #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct WireHeader { /// Implementation-defined flags. Not used in Parsec currently. Must be present, but must be zero. pub flags: u16, /// Provider ID value pub provider: u8, /// Session handle pub session: u64, /// Content type: defines how the request body should be processed. pub content_type: u8, /// Accept type: defines how the service should provide its response. pub accept_type: u8, /// Authentication type. pub auth_type: u8, /// Number of bytes of content. pub body_len: u32, /// Number of bytes of authentication. pub auth_len: u16, /// Opcode of the operation to perform. pub opcode: u32, /// Response status of the request. pub status: u16, /// Reserved byte. Currently unused. Must be present. Must be zero. pub reserved1: u8, /// Reserved byte. Currently unused. Must be present. Must be zero. pub reserved2: u8, } impl WireHeader { /// Create a new raw wire header. /// /// For use in testing only. #[cfg(feature = "testing")] #[allow(clippy::new_without_default)] pub fn new() -> WireHeader { WireHeader { flags: 0, provider: 0, session: 0, content_type: 0, accept_type: 0, auth_type: 0, body_len: 0, auth_len: 0, opcode: 0, status: 0, reserved1: 0, reserved2: 0, } } /// Serialise the request header and write the corresponding bytes to the given /// stream. /// /// # Errors /// - if marshalling the header fails, `ResponseStatus::InvalidEncoding` is returned. /// - if writing the header bytes fails, `ResponseStatus::ConnectionError` is returned. pub fn write_to_stream(&self, stream: &mut W) -> Result<()> { let serializer = bincode::DefaultOptions::new() .with_little_endian() .with_fixint_encoding(); stream.write_all(&serializer.serialize(&MAGIC_NUMBER)?)?; stream.write_all(&serializer.serialize(&REQUEST_HDR_SIZE)?)?; stream.write_all(&serializer.serialize(&WIRE_PROTOCOL_VERSION_MAJ)?)?; stream.write_all(&serializer.serialize(&WIRE_PROTOCOL_VERSION_MIN)?)?; stream.write_all(&serializer.serialize(&self)?)?; Ok(()) } /// Deserialise a request header from the given stream. /// /// # Errors /// - if either the magic number, the header size or the reserved fields /// are invalid values, `ResponseStatus::InvalidHeader` is returned. /// - if reading the fields after magic number and header size fails, /// `ResponseStatus::ConnectionError` is returned /// - the read may fail due to a timeout if not enough bytes are /// sent across /// - if the parsed bytes cannot be unmarshalled into the contained fields, /// `ResponseStatus::InvalidEncoding` is returned. /// - if the wire protocol version used is different than 1.0 pub fn read_from_stream(mut stream: &mut R) -> Result { let magic_number = get_from_stream!(stream, u32); if magic_number != MAGIC_NUMBER { error!( "Expected magic number {}, got {}", MAGIC_NUMBER, magic_number ); return Err(ResponseStatus::InvalidHeader); } let hdr_size = get_from_stream!(stream, u16); let mut bytes = vec![0_u8; usize::try_from(hdr_size)?]; stream.read_exact(&mut bytes)?; if hdr_size != REQUEST_HDR_SIZE { error!( "Expected request header size {}, got {}", REQUEST_HDR_SIZE, hdr_size ); return Err(ResponseStatus::InvalidHeader); } let version_maj = bytes.remove(0); // first byte after hdr length is version maj let version_min = bytes.remove(0); // second byte after hdr length is version min if version_maj != WIRE_PROTOCOL_VERSION_MAJ || version_min != WIRE_PROTOCOL_VERSION_MIN { error!( "Expected wire protocol version {}.{}, got {}.{} instead", WIRE_PROTOCOL_VERSION_MAJ, WIRE_PROTOCOL_VERSION_MIN, version_maj, version_min ); return Err(ResponseStatus::WireProtocolVersionNotSupported); } let deserializer = bincode::DefaultOptions::new() .with_little_endian() .with_fixint_encoding(); let wire_header: WireHeader = deserializer.deserialize(&bytes)?; if wire_header.reserved1 != 0x00 || wire_header.reserved2 != 0x00 { Err(ResponseStatus::InvalidHeader) } else { Ok(wire_header) } } } parsec-interface-0.29.1/src/requests/mod.rs000064400000000000000000000212271046102023000167230ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # Request and response definitions //! //! A `Request` is what is sent to the service to execute one operation. A `Response` is what the //! service returns. use num_derive::FromPrimitive; mod response_status; pub mod utils; pub mod common; pub mod request; pub mod response; #[cfg(feature = "fuzz")] use arbitrary::Arbitrary; pub use request::Request; pub use response::Response; pub use response_status::{ResponseStatus, Result}; use std::convert::TryFrom; use std::fmt; /// Listing of provider types and their associated codes. /// /// Passed in headers as `provider`. #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(FromPrimitive, PartialEq, Eq, Hash, Copy, Clone, Debug)] #[repr(u8)] pub enum ProviderId { /// Provider to use for core Parsec operations. Core = 0, /// Provider using Mbed Crypto software library. MbedCrypto = 1, /// Provider using a PKCS 11 compatible library. Pkcs11 = 2, /// Provider using a TSS 2.0 Enhanced System API library. Tpm = 3, /// Provider using the crypto Trusted Service running in TrustZone TrustedService = 4, /// Provider using the MicrochipTech cryptodevice ATECCx08 via CryptoAuthentication Library CryptoAuthLib = 5, } impl fmt::Display for ProviderId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ProviderId::Core => write!(f, "Core provider"), ProviderId::MbedCrypto => write!(f, "Mbed Crypto provider"), ProviderId::Pkcs11 => write!(f, "PKCS #11 provider"), ProviderId::Tpm => write!(f, "TPM provider"), ProviderId::TrustedService => write!(f, "Trusted Service provider"), ProviderId::CryptoAuthLib => write!(f, "CryptoAuthentication Library provider"), } } } impl TryFrom for ProviderId { type Error = ResponseStatus; fn try_from(provider_id: u8) -> ::std::result::Result { match num::FromPrimitive::from_u8(provider_id) { Some(provider_id) => Ok(provider_id), None => Err(ResponseStatus::ProviderDoesNotExist), } } } /// Listing of body encoding types and their associated codes. /// /// Passed in headers as `content_type` and `accept_type`. #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(FromPrimitive, Copy, Clone, Debug, PartialEq, Eq)] #[repr(u8)] pub enum BodyType { /// Protobuf format for operations. Protobuf = 0, } /// Listing of available operations and their associated opcode. /// /// Passed in headers as `opcode`. Check the /// [Operations](https://parallaxsecond.github.io/parsec-book/parsec_client/operations/index.html) /// page of the book for more information. #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(FromPrimitive, Copy, Clone, PartialEq, Debug, Hash, Eq)] #[repr(u32)] pub enum Opcode { /// Ping operation Ping = 0x0001, /// PsaGenerateKey operation PsaGenerateKey = 0x0002, /// PsaDestroyKey operation PsaDestroyKey = 0x0003, /// PsaSignHash operation PsaSignHash = 0x0004, /// PsaVerifyHash operation PsaVerifyHash = 0x0005, /// PsaImportKey operation PsaImportKey = 0x0006, /// PsaExportPublicKey operation PsaExportPublicKey = 0x0007, /// ListProviders operation ListProviders = 0x0008, /// ListOpcodes operation ListOpcodes = 0x0009, /// PsaAsymmetricEncrypt operation PsaAsymmetricEncrypt = 0x000A, /// PsaAsymmetricDecrypt operation PsaAsymmetricDecrypt = 0x000B, /// PsaExportKey operation PsaExportKey = 0x000C, /// PsaGenerateRandom operation PsaGenerateRandom = 0x000D, /// ListAuthenticators operation ListAuthenticators = 0x000E, /// PsaHashCompute operation PsaHashCompute = 0x000F, /// PsaHashCompare operation PsaHashCompare = 0x0010, /// PsaAeadEncrypt PsaAeadEncrypt = 0x0011, /// PsaAeadDecrypt PsaAeadDecrypt = 0x0012, /// PsaRawKeyAgreement operation PsaRawKeyAgreement = 0x0013, /// PsaCipherEncrypt PsaCipherEncrypt = 0x0014, /// PsaCipherDecrypt PsaCipherDecrypt = 0x0015, /// PsaSignMessage operation PsaSignMessage = 0x0018, /// PsaVerifyMessage operation PsaVerifyMessage = 0x0019, /// ListKeys operation ListKeys = 0x001A, /// ListClients operation (admin operation) ListClients = 0x001B, /// DeleteClient operation (admin operation) DeleteClient = 0x001C, /// AttestKey operation AttestKey = 0x001E, /// PrepareKeyAttestation operation PrepareKeyAttestation = 0x001F, /// CanDoCrypto operation CanDoCrypto = 0x0020, } impl Opcode { /// Check if an opcode is one of a Core operation pub fn is_core(&self) -> bool { // match to ensure exhaustivity when a new opcode is added match self { Opcode::Ping | Opcode::ListProviders | Opcode::ListOpcodes | Opcode::ListAuthenticators | Opcode::ListKeys | Opcode::ListClients | Opcode::DeleteClient => true, Opcode::PsaGenerateKey | Opcode::PsaDestroyKey | Opcode::PsaSignHash | Opcode::PsaVerifyHash | Opcode::PsaSignMessage | Opcode::PsaVerifyMessage | Opcode::PsaImportKey | Opcode::PsaExportPublicKey | Opcode::PsaAsymmetricEncrypt | Opcode::PsaAsymmetricDecrypt | Opcode::PsaExportKey | Opcode::PsaGenerateRandom | Opcode::PsaHashCompute | Opcode::PsaHashCompare | Opcode::PsaAeadEncrypt | Opcode::PsaAeadDecrypt | Opcode::PsaCipherEncrypt | Opcode::PsaCipherDecrypt | Opcode::PsaRawKeyAgreement | Opcode::CanDoCrypto | Opcode::AttestKey | Opcode::PrepareKeyAttestation => false, } } /// Check if an opcode is an admin operation pub fn is_admin(&self) -> bool { // match to ensure exhaustivity when a new opcode is added match self { Opcode::ListClients | Opcode::DeleteClient => true, Opcode::Ping | Opcode::ListProviders | Opcode::ListOpcodes | Opcode::ListAuthenticators | Opcode::ListKeys | Opcode::PsaGenerateKey | Opcode::PsaDestroyKey | Opcode::PsaSignHash | Opcode::PsaVerifyHash | Opcode::PsaSignMessage | Opcode::PsaVerifyMessage | Opcode::PsaImportKey | Opcode::PsaExportPublicKey | Opcode::PsaAsymmetricEncrypt | Opcode::PsaAsymmetricDecrypt | Opcode::PsaExportKey | Opcode::PsaGenerateRandom | Opcode::PsaHashCompute | Opcode::PsaHashCompare | Opcode::PsaAeadEncrypt | Opcode::PsaAeadDecrypt | Opcode::PsaCipherEncrypt | Opcode::PsaCipherDecrypt | Opcode::PsaRawKeyAgreement | Opcode::CanDoCrypto | Opcode::AttestKey | Opcode::PrepareKeyAttestation => false, } } /// Check if an opcode is one of a PSA Crypto operation pub fn is_crypto(&self) -> bool { !self.is_core() } } /// Listing of available authentication methods. /// /// Passed in headers as `auth_type`. #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(FromPrimitive, PartialEq, Eq, Hash, Copy, Clone, Debug)] #[repr(u8)] pub enum AuthType { /// No authentication NoAuth = 0, /// Direct authentication Direct = 1, /// JSON Web Tokens (JWT) authentication (not currently supported) Jwt = 2, /// Unix peer credentials authentication UnixPeerCredentials = 3, /// Authentication verifying a JWT SPIFFE Verifiable Identity Document JwtSvid = 4, } impl fmt::Display for AuthType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { AuthType::NoAuth => write!(f, "No authentication"), AuthType::Direct => write!(f, "Direct authentication"), AuthType::Jwt => write!(f, "JSON Web Tokens authentication"), AuthType::UnixPeerCredentials => write!(f, "Unix Peer Credentials authentication"), AuthType::JwtSvid => { write!(f, "JWT SPIFFE Verifiable Identity Document authentication") } } } } #[test] fn check_opcode_nature() { assert!(Opcode::ListKeys.is_core()); assert!(!Opcode::ListKeys.is_crypto()); assert!(Opcode::PsaGenerateKey.is_crypto()); assert!(Opcode::ListClients.is_admin()); assert!(!Opcode::PsaGenerateKey.is_admin()); } parsec-interface-0.29.1/src/requests/request/mod.rs000064400000000000000000000471541046102023000204220ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! # Request definition //! //! A `Request` is to the service to execute one operation. use super::common::wire_header_1_0::WireHeader as Raw; use super::response::ResponseHeader; use crate::requests::{ResponseStatus, Result}; use crate::secrecy::ExposeSecret; use derivative::Derivative; use log::error; use std::convert::{TryFrom, TryInto}; use std::io::{Read, Write}; mod request_auth; mod request_body; mod request_header; pub use request_auth::RequestAuth; pub use request_body::RequestBody; pub use request_header::RequestHeader; #[cfg(feature = "testing")] pub use super::common::wire_header_1_0::WireHeader as RawHeader; /// Representation of the request wire format. #[derive(Derivative)] #[derivative(Debug)] pub struct Request { /// Request header pub header: RequestHeader, /// Request body consists of `RequestBody` object holding a collection of bytes. /// Interpretation of said bytes is deferred to the a converter which can handle the /// `content_type` defined in the header. pub body: RequestBody, /// Auth field is stored as a `RequestAuth` object. A parser that can handle the `auth_type` /// specified in the header is needed to authenticate the request. #[derivative(Debug = "ignore")] pub auth: RequestAuth, } impl Request { /// Create a request with "default" header and empty body. /// Available for testing purposes only. #[cfg(feature = "testing")] pub fn new() -> Request { Request { header: RequestHeader::new(), body: RequestBody::new(), auth: RequestAuth::new(Vec::new()), } } /// Serialise request and write it to given stream. /// /// Request header is first converted to its raw format before serialization. /// /// # Errors /// - if an IO operation fails while writing any of the subfields of the request, /// `ResponseStatus::ConnectionError` is returned. /// - if encoding any of the fields in the header fails, `ResponseStatus::InvalidEncoding` /// is returned. pub fn write_to_stream(self, stream: &mut impl Write) -> Result<()> { let mut raw_header: Raw = self.header.into(); raw_header.body_len = u32::try_from(self.body.len())?; raw_header.auth_len = u16::try_from(self.auth.buffer.expose_secret().len())?; raw_header.write_to_stream(stream)?; self.body.write_to_stream(stream)?; self.auth.write_to_stream(stream)?; Ok(()) } /// Deserialise request from given stream. /// /// Request header is parsed from its raw form, ensuring that all fields are valid. /// The `body_len_limit` parameter allows the interface client to reject requests that are /// longer than a predefined limit. The length limit is in bytes. /// /// # Errors /// - if reading any of the subfields (header, body or auth) fails, the corresponding /// `ResponseStatus` will be returned. /// - if the request body size specified in the header is larger than the limit passed as /// a parameter, `BodySizeExceedsLimit` will be returned. pub fn read_from_stream(stream: &mut impl Read, body_len_limit: usize) -> Result { let raw_header = Raw::read_from_stream(stream)?; let body_len = usize::try_from(raw_header.body_len)?; if body_len > body_len_limit { error!( "Request body length ({}) bigger than the limit given ({}).", body_len, body_len_limit ); return Err(ResponseStatus::BodySizeExceedsLimit); } let body = RequestBody::read_from_stream(stream, body_len)?; let auth = RequestAuth::read_from_stream(stream, usize::try_from(raw_header.auth_len)?)?; Ok(Request { header: raw_header.try_into()?, body, auth, }) } } #[cfg(feature = "testing")] impl Default for Request { fn default() -> Request { Request::new() } } /// Conversion from `RequestHeader` to `ResponseHeader` is useful for /// when reversing data flow, from handling a request to handling a response. impl From for ResponseHeader { fn from(req_hdr: RequestHeader) -> ResponseHeader { ResponseHeader { provider: req_hdr.provider, session: req_hdr.session, content_type: req_hdr.accept_type, opcode: req_hdr.opcode, status: ResponseStatus::Success, } } } #[cfg(test)] mod tests { use super::super::utils::tests as test_utils; use super::super::{AuthType, BodyType, Opcode, ProviderId, ResponseStatus}; use super::*; #[test] fn request_1_to_stream() { let mut mock = test_utils::MockReadWrite { buffer: Vec::new() }; let request = get_request_1(); request .write_to_stream(&mut mock) .expect("Failed to write request"); assert_eq!(mock.buffer, get_request_1_bytes()); } #[test] fn request_2_to_stream() { let mut mock = test_utils::MockReadWrite { buffer: Vec::new() }; let request = get_request_2(); request .write_to_stream(&mut mock) .expect("Failed to write request"); assert_eq!(mock.buffer, get_request_2_bytes()); } #[test] fn stream_to_request_1() { let mut mock = test_utils::MockReadWrite { buffer: get_request_1_bytes(), }; let request = Request::read_from_stream(&mut mock, 1000).expect("Failed to read request"); let exp_req = get_request_1(); assert_eq!(request.header, exp_req.header); assert_eq!(request.body, exp_req.body); assert_eq!( request.auth.buffer.expose_secret(), exp_req.auth.buffer.expose_secret() ); } #[test] fn stream_to_request_2() { let mut mock = test_utils::MockReadWrite { buffer: get_request_2_bytes(), }; let request = Request::read_from_stream(&mut mock, 1000).expect("Failed to read request"); let exp_req = get_request_2(); assert_eq!(request.header, exp_req.header); assert_eq!(request.body, exp_req.body); assert_eq!( request.auth.buffer.expose_secret(), exp_req.auth.buffer.expose_secret() ); } #[test] fn stream_to_fail_request_1() { let mut mock = test_utils::MockReadWrite { buffer: get_request_bytes_reserved_fields_both_not_zero(), }; assert_eq!( Request::read_from_stream(&mut mock, 1000).unwrap_err(), ResponseStatus::InvalidHeader ); } #[test] fn stream_to_fail_request_2() { let mut mock = test_utils::MockReadWrite { buffer: get_request_bytes_reserved_fields_first_not_zero(), }; assert_eq!( Request::read_from_stream(&mut mock, 1000).unwrap_err(), ResponseStatus::InvalidHeader ); } #[test] fn stream_to_fail_request_3() { let mut mock = test_utils::MockReadWrite { buffer: get_request_bytes_reserved_fields_second_not_zero(), }; assert_eq!( Request::read_from_stream(&mut mock, 1000).unwrap_err(), ResponseStatus::InvalidHeader ); } #[test] fn stream_to_fail_request_wrong_endians() { let mut mock = test_utils::MockReadWrite { buffer: get_request_bytes_big_endian_fixint_encoding(), }; let response_status = Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!(response_status, ResponseStatus::InvalidHeader); let mut mock = test_utils::MockReadWrite { buffer: get_request_bytes_big_endian_varint_encoding(), }; let response_status = Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!(response_status, ResponseStatus::InvalidHeader); } #[test] fn stream_to_fail_request_wrong_int_encoding() { let mut mock = test_utils::MockReadWrite { buffer: get_request_bytes_little_endian_varint_encoding(), }; let response_status = Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!(response_status, ResponseStatus::InvalidHeader); } #[test] #[should_panic(expected = "Failed to read request")] fn failed_read() { let mut fail_mock = test_utils::MockFailReadWrite; let _ = Request::read_from_stream(&mut fail_mock, 1000).expect("Failed to read request"); } #[test] #[should_panic(expected = "Request body too large")] fn body_too_large() { let mut mock = test_utils::MockReadWrite { buffer: get_request_1_bytes(), }; let _ = Request::read_from_stream(&mut mock, 0).expect("Request body too large"); } #[test] #[should_panic(expected = "Failed to write request")] fn failed_write() { let request: Request = get_request_1(); let mut fail_mock = test_utils::MockFailReadWrite; request .write_to_stream(&mut fail_mock) .expect("Failed to write request"); } #[test] fn req_hdr_to_resp_hdr() { let req_hdr = get_request_1().header; let resp_hdr: ResponseHeader = req_hdr.into(); let mut resp_hdr_exp = ResponseHeader::new(); resp_hdr_exp.provider = ProviderId::Core; resp_hdr_exp.session = 0x11_22_33_44_55_66_77_88; resp_hdr_exp.content_type = BodyType::Protobuf; resp_hdr_exp.opcode = Opcode::Ping; resp_hdr_exp.status = ResponseStatus::Success; assert_eq!(resp_hdr, resp_hdr_exp); } #[test] fn wrong_version() { let mut mock = test_utils::MockReadWrite { buffer: get_request_1_bytes(), }; // Put an invalid version major field. mock.buffer[6] = 0xFF; // Put an invalid version minor field. mock.buffer[7] = 0xFF; let response_status = Request::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!( response_status, ResponseStatus::WireProtocolVersionNotSupported ); } fn get_request_1() -> Request { let body = RequestBody::from_bytes(vec![0x70, 0x80, 0x90]); let auth = RequestAuth::new(vec![0xa0, 0xb0, 0xc0]); let header = RequestHeader { provider: ProviderId::Core, session: 0x11_22_33_44_55_66_77_88, content_type: BodyType::Protobuf, accept_type: BodyType::Protobuf, auth_type: AuthType::Direct, opcode: Opcode::Ping, }; Request { header, body, auth } } fn get_request_2() -> Request { let body = RequestBody::from_bytes(vec![0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5]); let auth = RequestAuth::new(vec![0xA0, 0xA1, 0xA2, 0xA3, 0xA4]); let header = RequestHeader { provider: ProviderId::Core, session: 0x88_99_AA_BB_CC_DD_EE_FF, content_type: BodyType::Protobuf, accept_type: BodyType::Protobuf, auth_type: AuthType::Direct, opcode: Opcode::Ping, }; Request { header, body, auth } } fn get_request_1_bytes() -> Vec { vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x03, 0x00, 0x00, 0x00, // WireHeader::body_len 0x03, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody 0xA0, 0xB0, 0xC0, // RequestAuth ] } fn get_request_2_bytes() -> Vec { vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x06, 0x00, 0x00, 0x00, // WireHeader::body_len 0x05, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, // RequestBody 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, // RequestAuth ] } fn get_request_bytes_reserved_fields_both_not_zero() -> Vec { // reserved fields set to 0xDEAD vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x06, 0x00, 0x00, 0x00, // WireHeader::body_len 0x05, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0xDE, // WireHeader::reserved1 0xAD, // WireHeader::reserved2 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, // RequestBody 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, // RequestAuth ] } fn get_request_bytes_reserved_fields_first_not_zero() -> Vec { vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x06, 0x00, 0x00, 0x00, // WireHeader::body_len 0x05, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0xDE, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, // RequestBody 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, // RequestAuth ] } fn get_request_bytes_reserved_fields_second_not_zero() -> Vec { vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x06, 0x00, 0x00, 0x00, // WireHeader::body_len 0x05, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0xAD, // WireHeader::reserved2 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, // RequestBody 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, // RequestAuth ] } fn get_request_bytes_big_endian_fixint_encoding() -> Vec { vec![ 0x5E, 0xC0, 0xA7, 0x10, // MAGIC_NUMBER 0x00, 0x1E, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x00, 0x00, 0x00, 0x03, // WireHeader::body_len 0x00, 0x03, // WireHeader::auth_len 0x00, 0x00, 0x00, 0x01, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody 0xa0, 0xb0, 0xc0, // RequestAuth ] } fn get_request_bytes_little_endian_varint_encoding() -> Vec { vec![ 0xFC, // Encoding byte indicates that the following 4 bytes make a u32 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x5E, 0xC0, 0xA7, 0x10, // MAGIC_NUMBER 0x1E, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFD, // Encoding byte indicates that the following 8 bytes make a u64 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x03, // WireHeader::body_len 0x03, // WireHeader::auth_len 0x01, // WireHeader::opcode 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody 0xA0, 0xB0, 0xC0, // RequestAuth ] } fn get_request_bytes_big_endian_varint_encoding() -> Vec { vec![ 0xFC, // Encoding byte indicates that the following 4 bytes make a u32 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFD, // Encoding byte indicates that the following 8 bytes make a u64 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x01, // WireHeader::auth_type 0x03, // WireHeader::body_len 0x03, // WireHeader::auth_len 0x01, // WireHeader::opcode 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody 0xA0, 0xB0, 0xC0, // RequestAuth ] } } parsec-interface-0.29.1/src/requests/request/request_auth.rs000064400000000000000000000023231046102023000223410ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::requests::Result; use crate::secrecy::{ExposeSecret, Secret}; use std::io::{Read, Write}; /// Wrapper around the authentication value of a request. /// /// Hides the contents and keeps them immutable. #[allow(missing_debug_implementations)] pub struct RequestAuth { /// Buffer holding the authentication token as a byte vector pub buffer: Secret>, } impl RequestAuth { /// Create a new authentication field for a request. pub fn new(bytes: Vec) -> Self { RequestAuth { buffer: Secret::new(bytes), } } /// Read a request authentication field from the stream, given the length /// of the byte stream contained. pub(super) fn read_from_stream(mut stream: &mut impl Read, len: usize) -> Result { let buffer = get_from_stream!(stream; len); Ok(RequestAuth { buffer: Secret::new(buffer), }) } /// Write request authentication field to stream. pub(super) fn write_to_stream(&self, stream: &mut impl Write) -> Result<()> { stream.write_all(self.buffer.expose_secret())?; Ok(()) } } parsec-interface-0.29.1/src/requests/request/request_body.rs000064400000000000000000000041271046102023000223410ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::requests::Result; #[cfg(feature = "fuzz")] use arbitrary::Arbitrary; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; use zeroize::Zeroize; /// Wrapper around the body of a request. /// /// Hides the contents and keeps them immutable. #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(Debug, PartialEq, Eq, Zeroize)] #[zeroize(drop)] pub struct RequestBody { buffer: Vec, } impl Deref for RequestBody { type Target = [u8]; fn deref(&self) -> &Self::Target { &self.buffer } } impl DerefMut for RequestBody { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } impl RequestBody { /// Create a new, emtpy request body field. /// Available for testing only. #[cfg(feature = "testing")] pub(super) fn new() -> RequestBody { RequestBody { buffer: Vec::new() } } /// Read the request body from a stream, given the length of the content. pub(super) fn read_from_stream(mut stream: &mut impl Read, len: usize) -> Result { let buffer = get_from_stream!(stream; len); Ok(RequestBody { buffer }) } /// Write the request body to a stream. pub(super) fn write_to_stream(&self, stream: &mut impl Write) -> Result<()> { stream.write_all(&self.buffer)?; Ok(()) } /// Create a `RequestBody` from a vector of bytes. pub(crate) fn from_bytes(buffer: Vec) -> RequestBody { RequestBody { buffer } } /// Get the body as a slice of bytes. pub fn bytes(&self) -> &[u8] { &self.buffer } /// Get size of body. pub fn len(&self) -> usize { self.buffer.len() } /// Check if body is empty. pub fn is_empty(&self) -> bool { self.buffer.is_empty() } /// Create a `RequestBody` from the provided bytes. /// /// Must only be used for testing purposes. #[cfg(feature = "testing")] pub fn _from_bytes(buffer: Vec) -> RequestBody { RequestBody { buffer } } } parsec-interface-0.29.1/src/requests/request/request_header.rs000064400000000000000000000071051046102023000226330ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::requests::common::wire_header_1_0::WireHeader as Raw; use crate::requests::ResponseStatus; use crate::requests::{AuthType, BodyType, Opcode, ProviderId}; #[cfg(feature = "fuzz")] use arbitrary::Arbitrary; use num::FromPrimitive; use std::convert::TryFrom; /// A native representation of the request header. /// /// Fields that are not relevant for application development (e.g. magic number) are /// not copied across from the raw header. #[cfg_attr(feature = "fuzz", derive(Arbitrary))] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct RequestHeader { /// Provider ID value pub provider: ProviderId, /// Session handle pub session: u64, /// Content type: defines how the request body should be processed. pub content_type: BodyType, /// Accept type: defines how the service should provide its response. pub accept_type: BodyType, /// Authentication type. pub auth_type: AuthType, /// Opcode of the operation to perform. pub opcode: Opcode, } impl RequestHeader { /// Create a new request header with default field values. /// Available for testing only. #[cfg(feature = "testing")] pub(crate) fn new() -> RequestHeader { RequestHeader { provider: ProviderId::Core, session: 0, content_type: BodyType::Protobuf, accept_type: BodyType::Protobuf, auth_type: AuthType::Direct, opcode: Opcode::Ping, } } } /// Conversion from the raw to native request header. /// /// This conversion must be done before a `Request` value can be populated. impl TryFrom for RequestHeader { type Error = ResponseStatus; fn try_from(header: Raw) -> ::std::result::Result { let content_type: BodyType = match FromPrimitive::from_u8(header.content_type) { Some(content_type) => content_type, None => return Err(ResponseStatus::ContentTypeNotSupported), }; let accept_type: BodyType = match FromPrimitive::from_u8(header.accept_type) { Some(accept_type) => accept_type, None => return Err(ResponseStatus::AcceptTypeNotSupported), }; let auth_type: AuthType = match FromPrimitive::from_u8(header.auth_type) { Some(auth_type) => auth_type, None => return Err(ResponseStatus::AuthenticatorDoesNotExist), }; let opcode: Opcode = match FromPrimitive::from_u32(header.opcode) { Some(opcode) => opcode, None => return Err(ResponseStatus::OpcodeDoesNotExist), }; Ok(RequestHeader { provider: ProviderId::try_from(header.provider)?, session: header.session, content_type, accept_type, auth_type, opcode, }) } } /// Conversion from native to raw request header. /// /// This is required in order to bring the contents of the header in a state /// which can be serialized. impl From for Raw { fn from(header: RequestHeader) -> Self { Raw { flags: 0, provider: header.provider as u8, session: header.session, content_type: header.content_type as u8, accept_type: header.accept_type as u8, auth_type: header.auth_type as u8, body_len: 0, auth_len: 0, opcode: header.opcode as u32, status: 0, // status field unused reserved1: 0, reserved2: 0, } } } parsec-interface-0.29.1/src/requests/response/mod.rs000064400000000000000000000327471046102023000205720ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! Response definition use super::common::wire_header_1_0::WireHeader as Raw; use super::request::RequestHeader; use super::ResponseStatus; use super::Result; use log::error; use std::convert::{TryFrom, TryInto}; use std::io::{Read, Write}; mod response_body; mod response_header; pub use response_body::ResponseBody; pub use response_header::ResponseHeader; #[cfg(feature = "testing")] pub use super::common::wire_header_1_0::WireHeader as RawHeader; /// Native representation of the response wire format. #[derive(PartialEq, Eq, Debug)] pub struct Response { /// Header of the response, containing the response status. pub header: ResponseHeader, /// Response body consists of an opaque vector of bytes. Interpretation of said bytes /// is deferred to the a converter which can handle the `content_type` defined in the /// header. pub body: ResponseBody, } impl Response { /// Create a response with empty header and empty body. fn new() -> Response { Response { header: ResponseHeader::new(), body: ResponseBody::new(), } } /// Convert request into an error response with a given `ResponseStatus`. /// /// The relevant fields in the header are preserved and an empty body is provided /// by default. pub fn from_request_header(header: RequestHeader, status: ResponseStatus) -> Response { let mut response = Response::new(); response.header = header.into(); response.header.status = status; response } /// Create an empty response with a specific status. pub fn from_status(status: ResponseStatus) -> Response { let mut response = Response::new(); response.header.status = status; response } /// Serialise response and write it to given stream. /// /// Header is converted to a raw format before serializing. /// /// # Errors /// - if writing any of the subfields (header or body) fails, then /// `ResponseStatus::ConnectionError` is returned. /// - if encoding any of the fields in the header fails, then /// `ResponseStatus::InvalidEncoding` is returned. pub fn write_to_stream(self, stream: &mut impl Write) -> Result<()> { let mut raw_header: Raw = self.header.into(); raw_header.body_len = u32::try_from(self.body.len())?; raw_header.write_to_stream(stream)?; self.body.write_to_stream(stream)?; Ok(()) } /// Deserialise response from given stream. /// /// The `body_len_limit` parameter allows the interface client to reject requests that are /// longer than a predefined limit. The length limit is in bytes. /// /// # Errors /// - if reading any of the subfields (header or body) fails, the /// corresponding `ResponseStatus` will be returned. /// - if the request body size specified in the header is larger than the limit passed as /// a parameter, `BodySizeExceedsLimit` will be returned. pub fn read_from_stream(stream: &mut impl Read, body_len_limit: usize) -> Result { let raw_header = Raw::read_from_stream(stream)?; let body_len = usize::try_from(raw_header.body_len)?; if body_len > body_len_limit { error!( "Request body length ({}) bigger than the limit given ({}).", body_len, body_len_limit ); return Err(ResponseStatus::BodySizeExceedsLimit); } let body = ResponseBody::read_from_stream(stream, body_len)?; Ok(Response { header: raw_header.try_into()?, body, }) } } #[cfg(test)] mod tests { use super::super::utils::tests as test_utils; use super::super::{BodyType, Opcode, ProviderId, ResponseStatus}; use super::*; #[test] fn response_1_to_stream() { let mut mock = test_utils::MockReadWrite { buffer: Vec::new() }; let response = get_response_1(); response .write_to_stream(&mut mock) .expect("Failed to write response"); assert_eq!(mock.buffer, get_response_1_bytes()); } #[test] fn response_2_to_stream() { let mut mock = test_utils::MockReadWrite { buffer: Vec::new() }; let response = get_response_2(); response .write_to_stream(&mut mock) .expect("Failed to write response"); assert_eq!(mock.buffer, get_response_2_bytes()); } #[test] fn stream_to_response_1() { let mut mock = test_utils::MockReadWrite { buffer: get_response_1_bytes(), }; let response = Response::read_from_stream(&mut mock, 1000).expect("Failed to read response"); assert_eq!(response, get_response_1()); } #[test] fn stream_to_response_2() { let mut mock = test_utils::MockReadWrite { buffer: get_response_2_bytes(), }; let response = Response::read_from_stream(&mut mock, 1000).expect("Failed to read response"); assert_eq!(response, get_response_2()); } #[test] fn stream_to_fail_response_wrong_endians() { let mut mock = test_utils::MockReadWrite { buffer: get_response_bytes_big_endian_fixint_encoding(), }; let response_status = Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!(response_status, ResponseStatus::InvalidHeader); let mut mock = test_utils::MockReadWrite { buffer: get_response_bytes_big_endian_varint_encoding(), }; let response_status = Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!(response_status, ResponseStatus::InvalidHeader); } #[test] fn stream_to_fail_response_wrong_int_encoding() { let mut mock = test_utils::MockReadWrite { buffer: get_response_bytes_little_endian_varint_encoding(), }; let response_status = Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!(response_status, ResponseStatus::InvalidHeader); } #[test] #[should_panic(expected = "Failed to read response")] fn failed_read() { let mut fail_mock = test_utils::MockFailReadWrite; let _ = Response::read_from_stream(&mut fail_mock, 1000).expect("Failed to read response"); } #[test] #[should_panic(expected = "Response body too large")] fn body_too_large() { let mut mock = test_utils::MockReadWrite { buffer: get_response_1_bytes(), }; let _ = Response::read_from_stream(&mut mock, 0).expect("Response body too large"); } #[test] #[should_panic(expected = "Failed to write response")] fn failed_write() { let response: Response = get_response_1(); let mut fail_mock = test_utils::MockFailReadWrite; response .write_to_stream(&mut fail_mock) .expect("Failed to write response"); } #[test] fn wrong_version() { let mut mock = test_utils::MockReadWrite { buffer: get_response_1_bytes(), }; // Put an invalid version major field. mock.buffer[6] = 0xFF; // Put an invalid version minor field. mock.buffer[7] = 0xFF; let response_status = Response::read_from_stream(&mut mock, 1000).expect_err("Should have failed."); assert_eq!( response_status, ResponseStatus::WireProtocolVersionNotSupported ); } fn get_response_1() -> Response { let body = ResponseBody::from_bytes(vec![0x70, 0x80, 0x90]); let header = ResponseHeader { provider: ProviderId::Core, session: 0x11_22_33_44_55_66_77_88, content_type: BodyType::Protobuf, opcode: Opcode::Ping, status: ResponseStatus::Success, }; Response { header, body } } fn get_response_2() -> Response { let body = ResponseBody::from_bytes(vec![0xB0, 0xB1, 0xB2, 0xB3]); let header = ResponseHeader { provider: ProviderId::Core, session: 0x88_99_AA_BB_CC_DD_EE_FF, content_type: BodyType::Protobuf, opcode: Opcode::Ping, status: ResponseStatus::Success, }; Response { header, body } } fn get_response_1_bytes() -> Vec { vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x00, // WireHeader::auth_type 0x03, 0x00, 0x00, 0x00, // WireHeader::body_len 0x00, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // ResponseBody ] } fn get_response_2_bytes() -> Vec { vec![ 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, 0x00, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x00, // WireHeader::auth_type 0x04, 0x00, 0x00, 0x00, // WireHeader::body_len 0x00, 0x00, // WireHeader::auth_len 0x01, 0x00, 0x00, 0x00, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0xB0, 0xB1, 0xB2, 0xB3, // ResponseBody ] } fn get_response_bytes_big_endian_fixint_encoding() -> Vec { vec![ 0x5E, 0xC0, 0xA7, 0x10, // MAGIC_NUMBER 0x00, 0x1E, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x00, // WireHeader::auth_type 0x00, 0x00, 0x00, 0x03, // WireHeader::body_len 0x00, 0x00, // WireHeader::auth_len 0x00, 0x00, 0x00, 0x01, // WireHeader::opcode 0x00, 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody ] } fn get_response_bytes_little_endian_varint_encoding() -> Vec { vec![ 0xFC, // Encoding byte indicates that the following 4 bytes make a u32 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x5E, 0xC0, 0xA7, 0x10, // MAGIC_NUMBER 0x1E, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFD, // Encoding byte indicates that the following 8 bytes make a u64 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x00, // WireHeader::auth_type 0x03, // WireHeader::body_len 0x00, // WireHeader::auth_len 0x01, // WireHeader::opcode 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody ] } fn get_response_bytes_big_endian_varint_encoding() -> Vec { vec![ 0xFC, // Encoding byte indicates that the following 4 bytes make a u32 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x10, 0xA7, 0xC0, 0x5E, // MAGIC_NUMBER 0x1E, // REQUEST_HDR_SIZE 0x01, // WIRE_PROTOCOL_VERSION_MAJ 0x00, // WIRE_PROTOCOL_VERSION_MIN 0x00, // WireHeader::flags 0x00, // WireHeader::provider 0xFD, // Encoding byte indicates that the following 8 bytes make a u64 int //https://docs.rs/bincode/1.3.3/bincode/config/struct.VarintEncoding.html 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, // WireHeader::session 0x00, // WireHeader::content_type 0x00, // WireHeader::accept_type 0x00, // WireHeader::auth_type 0x03, // WireHeader::body_len 0x00, // WireHeader::auth_len 0x01, // WireHeader::opcode 0x00, // WireHeader::status 0x00, // WireHeader::reserved1 0x00, // WireHeader::reserved2 0x70, 0x80, 0x90, // RequestBody ] } } parsec-interface-0.29.1/src/requests/response/response_body.rs000064400000000000000000000034051046102023000226530ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use super::Result; use serde::{Deserialize, Serialize}; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; use zeroize::Zeroize; /// Wrapper around the body of a response. /// /// Hides the contents and keeps them immutable. #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Zeroize)] #[zeroize(drop)] pub struct ResponseBody { buffer: Vec, } impl Deref for ResponseBody { type Target = [u8]; fn deref(&self) -> &Self::Target { &self.buffer } } impl DerefMut for ResponseBody { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } impl ResponseBody { /// Create a new empty response body. pub(crate) fn new() -> ResponseBody { ResponseBody { buffer: Vec::new() } } /// Read a response body from a stream, given the number of bytes it contains. pub(super) fn read_from_stream(mut stream: &mut impl Read, len: usize) -> Result { let buffer = get_from_stream!(stream; len); Ok(ResponseBody { buffer }) } /// Write a response body to a stream. pub(super) fn write_to_stream(&self, stream: &mut impl Write) -> Result<()> { stream.write_all(&self.buffer)?; Ok(()) } /// Create a `ResponseBody` from a vector of bytes. pub(crate) fn from_bytes(buffer: Vec) -> ResponseBody { ResponseBody { buffer } } /// Get the body as a slice of bytes. pub fn bytes(&self) -> &[u8] { &self.buffer } /// Get the size of the body. pub fn len(&self) -> usize { self.buffer.len() } /// Check if body is empty. pub fn is_empty(&self) -> bool { self.buffer.is_empty() } } parsec-interface-0.29.1/src/requests/response/response_header.rs000064400000000000000000000061641046102023000231530ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::requests::common::wire_header_1_0::WireHeader as Raw; use crate::requests::{BodyType, Opcode, ProviderId, ResponseStatus, Result}; use num::FromPrimitive; use std::convert::TryFrom; /// A native representation of the response header. /// /// Fields that are not relevant for application development (e.g. magic number) are /// not copied across from the raw header. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct ResponseHeader { /// Provider ID value pub provider: ProviderId, /// Session handle pub session: u64, /// Content type: defines how the request body should be processed. pub content_type: BodyType, /// Opcode of the operation to perform. pub opcode: Opcode, /// Response status of the request. pub status: ResponseStatus, } impl ResponseHeader { /// Create a new response header with default field values. pub(crate) fn new() -> ResponseHeader { ResponseHeader { provider: ProviderId::Core, session: 0, content_type: BodyType::Protobuf, opcode: Opcode::Ping, status: ResponseStatus::Success, } } } /// Conversion from the raw to native response header. /// /// This conversion must be done before a `Response` value can be populated. impl TryFrom for ResponseHeader { type Error = ResponseStatus; fn try_from(header: Raw) -> Result { let provider: ProviderId = match FromPrimitive::from_u8(header.provider) { Some(provider_id) => provider_id, None => return Err(ResponseStatus::ProviderDoesNotExist), }; let content_type: BodyType = match FromPrimitive::from_u8(header.content_type) { Some(content_type) => content_type, None => return Err(ResponseStatus::ContentTypeNotSupported), }; let opcode: Opcode = match FromPrimitive::from_u32(header.opcode) { Some(opcode) => opcode, None => return Err(ResponseStatus::OpcodeDoesNotExist), }; let status: ResponseStatus = match FromPrimitive::from_u16(header.status) { Some(status) => status, None => return Err(ResponseStatus::InvalidEncoding), }; Ok(ResponseHeader { provider, session: header.session, content_type, opcode, status, }) } } /// Conversion from native to raw response header. /// /// This is required in order to bring the contents of the header in a state /// which can be serialized. impl From for Raw { fn from(header: ResponseHeader) -> Self { Raw { flags: 0, provider: header.provider as u8, session: header.session, content_type: header.content_type as u8, accept_type: 0, auth_type: 0, auth_len: 0, body_len: 0, opcode: header.opcode as u32, status: header.status as u16, reserved1: 0, reserved2: 0, } } } parsec-interface-0.29.1/src/requests/response_status.rs000064400000000000000000000362151046102023000214100ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use log::{error, warn}; use num_derive::FromPrimitive; use std::convert::TryFrom; use std::error::Error as ErrorTrait; use std::fmt; /// C-like enum mapping response status options to their code. /// /// See the [status /// code](https://parallaxsecond.github.io/parsec-book/parsec_client/status_codes.html) page for a /// broader description of these codes. #[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive)] #[repr(u16)] pub enum ResponseStatus { /// Successful operation Success = 0, /// Requested provider ID does not match that of the backend WrongProviderId = 1, /// Requested content type is not supported by the backend ContentTypeNotSupported = 2, /// Requested accept type is not supported by the backend AcceptTypeNotSupported = 3, /// Requested version is not supported by the backend WireProtocolVersionNotSupported = 4, /// No provider registered for the requested provider ID ProviderNotRegistered = 5, /// No provider defined for requested provider ID ProviderDoesNotExist = 6, /// Failed to deserialize the body of the message DeserializingBodyFailed = 7, /// Failed to serialize the body of the message SerializingBodyFailed = 8, /// Requested operation is not defined OpcodeDoesNotExist = 9, /// Response size exceeds allowed limits ResponseTooLarge = 10, /// Authentication failed AuthenticationError = 11, /// Authenticator not supported AuthenticatorDoesNotExist = 12, /// Authenticator not supported AuthenticatorNotRegistered = 13, /// Internal error in the Key Info Manager KeyInfoManagerError = 14, /// Generic input/output error ConnectionError = 15, /// Invalid value for this data type InvalidEncoding = 16, /// Constant fields in header are invalid InvalidHeader = 17, /// The UUID vector needs to only contain 16 bytes WrongProviderUuid = 18, /// Request did not provide a required authentication NotAuthenticated = 19, /// Request length specified in the header is above defined limit BodySizeExceedsLimit = 20, /// The operation requires admin privilege AdminOperation = 21, /// The key template contains a deprecated type or algorithm DeprecatedPrimitive = 22, /// An error occurred that does not correspond to any defined failure cause PsaErrorGenericError = 1132, /// The requested operation or a parameter is not supported by this implementation PsaErrorNotSupported = 1134, /// The requested action is denied by a policy PsaErrorNotPermitted = 1133, /// An output buffer is too small PsaErrorBufferTooSmall = 1138, /// Asking for an item that already exists PsaErrorAlreadyExists = 1139, /// Asking for an item that doesn't exist PsaErrorDoesNotExist = 1140, /// The requested action cannot be performed in the current state PsaErrorBadState = 1137, /// The parameters passed to the function are invalid PsaErrorInvalidArgument = 1135, /// There is not enough runtime memory PsaErrorInsufficientMemory = 1141, /// There is not enough persistent storage PsaErrorInsufficientStorage = 1142, /// There was a communication failure inside the implementation PsaErrorCommunicationFailure = 1145, /// There was a storage failure that may have led to data loss PsaErrorStorageFailure = 1146, /// Stored data has been corrupted PsaErrorDataCorrupt = 1152, /// Data read from storage is not valid for the implementation PsaErrorDataInvalid = 1153, /// A hardware failure was detected PsaErrorHardwareFailure = 1147, /// A tampering attempt was detected PsaErrorCorruptionDetected = 1151, /// There is not enough entropy to generate random data needed for the requested action PsaErrorInsufficientEntropy = 1148, /// The signature, MAC or hash is incorrect PsaErrorInvalidSignature = 1149, /// The decrypted padding is incorrect PsaErrorInvalidPadding = 1150, /// Insufficient data when attempting to read from a resource PsaErrorInsufficientData = 1143, /// The key handle is not valid PsaErrorInvalidHandle = 1136, } impl TryFrom for ResponseStatus { type Error = ResponseStatus; fn try_from(value: u16) -> Result { num::FromPrimitive::from_u16(value).ok_or_else(|| { error!( "Value {} does not correspond to a valid ResponseStatus.", value ); ResponseStatus::InvalidEncoding }) } } impl fmt::Display for ResponseStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ResponseStatus::Success => write!(f, "successful operation"), ResponseStatus::WrongProviderId => write!( f, "requested provider ID does not match that of the backend" ), ResponseStatus::ContentTypeNotSupported => { write!(f, "requested content type is not supported by the backend") } ResponseStatus::AcceptTypeNotSupported => { write!(f, "requested accept type is not supported by the backend") } ResponseStatus::WireProtocolVersionNotSupported => { write!(f, "requested version is not supported by the backend") } ResponseStatus::ProviderNotRegistered => { write!(f, "no provider registered for the requested provider ID") } ResponseStatus::ProviderDoesNotExist => { write!(f, "no provider defined for requested provider ID") } ResponseStatus::DeserializingBodyFailed => { write!(f, "failed to deserialize the body of the message") } ResponseStatus::SerializingBodyFailed => { write!(f, "failed to serialize the body of the message") } ResponseStatus::OpcodeDoesNotExist => write!(f, "requested operation is not defined"), ResponseStatus::ResponseTooLarge => write!(f, "response size exceeds allowed limits"), ResponseStatus::AuthenticationError => { write!(f, "authentication failed") } ResponseStatus::AuthenticatorDoesNotExist => { write!(f, "authenticator not supported") } ResponseStatus::AuthenticatorNotRegistered => { write!(f, "authenticator not supported") } ResponseStatus::KeyInfoManagerError => { write!(f, "internal error in the Key Info Manager") } ResponseStatus::ConnectionError => { write!(f, "generic input/output error") } ResponseStatus::InvalidEncoding => { write!(f, "invalid value for this data type") } ResponseStatus::InvalidHeader => { write!(f, "constant fields in header are invalid") } ResponseStatus::WrongProviderUuid => { write!(f, "the UUID vector needs to only contain 16 bytes") } ResponseStatus::NotAuthenticated => { write!(f, "request did not provide a required authentication") } ResponseStatus::BodySizeExceedsLimit => { write!( f, "request length specified in the header is above defined limit" ) } ResponseStatus::AdminOperation => { write!(f, "the operation requires admin privilege") } ResponseStatus::DeprecatedPrimitive => { write!( f, "the key template contains a deprecated type or algorithm" ) } ResponseStatus::PsaErrorGenericError => { write!( f, "an error occurred that does not correspond to any defined failure cause" ) } ResponseStatus::PsaErrorNotPermitted => { write!(f, "the requested action is denied by a policy") } ResponseStatus::PsaErrorNotSupported => { write!(f, "the requested operation or a parameter is not supported by this implementation") } ResponseStatus::PsaErrorInvalidArgument => { write!(f, "the parameters passed to the function are invalid") } ResponseStatus::PsaErrorInvalidHandle => { write!(f, "the key handle is not valid") } ResponseStatus::PsaErrorBadState => { write!( f, "the requested action cannot be performed in the current state" ) } ResponseStatus::PsaErrorBufferTooSmall => { write!(f, "an output buffer is too small") } ResponseStatus::PsaErrorAlreadyExists => { write!(f, "asking for an item that already exists") } ResponseStatus::PsaErrorDoesNotExist => { write!(f, "asking for an item that doesn't exist") } ResponseStatus::PsaErrorInsufficientMemory => { write!(f, "there is not enough runtime memory") } ResponseStatus::PsaErrorInsufficientStorage => { write!(f, "there is not enough persistent storage") } ResponseStatus::PsaErrorInsufficientData => { write!( f, "insufficient data when attempting to read from a resource" ) } ResponseStatus::PsaErrorCommunicationFailure => { write!( f, "there was a communication failure inside the implementation" ) } ResponseStatus::PsaErrorStorageFailure => { write!( f, "there was a storage failure that may have led to data loss" ) } ResponseStatus::PsaErrorDataCorrupt => { write!(f, "stored data has been corrupted") } ResponseStatus::PsaErrorDataInvalid => { write!( f, "data read from storage is not valid for the implementation" ) } ResponseStatus::PsaErrorHardwareFailure => { write!(f, "a hardware failure was detected") } ResponseStatus::PsaErrorCorruptionDetected => { write!(f, "a tampering attempt was detected") } ResponseStatus::PsaErrorInsufficientEntropy => { write!(f, "there is not enough entropy to generate random data needed for the requested action") } ResponseStatus::PsaErrorInvalidSignature => { write!(f, "the signature, MAC or hash is incorrect") } ResponseStatus::PsaErrorInvalidPadding => { write!(f, "the decrypted padding is incorrect") } } } } impl ErrorTrait for ResponseStatus {} /// Conversion from a std::io::Error to a ResponseStatus /// /// It allows to easily return a ResponseStatus in case of error when using functions from the /// standard library. impl From for ResponseStatus { fn from(err: std::io::Error) -> Self { warn!( "Conversion from {:?} to ResponseStatus::ConnectionError.", err ); if err.kind() == std::io::ErrorKind::WouldBlock { warn!("The WouldBlock error might mean that the connection timed out. Try in increase the timeout length."); } ResponseStatus::ConnectionError } } impl From for ResponseStatus { fn from(err: bincode::Error) -> Self { warn!( "Conversion from {} to ResponseStatus::InvalidEncoding.", err ); ResponseStatus::InvalidEncoding } } impl From for ResponseStatus { fn from(err: uuid::Error) -> Self { warn!( "Conversion from {} to ResponseStatus::InvalidEncoding.", err ); ResponseStatus::InvalidEncoding } } impl From for ResponseStatus { fn from(err: std::num::TryFromIntError) -> Self { warn!( "Conversion from {} to ResponseStatus::InvalidEncoding.", err ); ResponseStatus::InvalidEncoding } } impl From for ResponseStatus { fn from(err: std::array::TryFromSliceError) -> Self { warn!( "Conversion from {} to ResponseStatus::InvalidEncoding.", err ); ResponseStatus::InvalidEncoding } } impl From for ResponseStatus { fn from(err: std::ffi::NulError) -> Self { warn!( "Conversion from {} to ResponseStatus::InvalidEncoding.", err ); ResponseStatus::InvalidEncoding } } impl From for ResponseStatus { fn from(_err: std::convert::Infallible) -> Self { unreachable!(); } } use psa_crypto::types::status::Error; impl From for ResponseStatus { fn from(err: Error) -> ResponseStatus { match err { Error::GenericError => ResponseStatus::PsaErrorGenericError, Error::NotSupported => ResponseStatus::PsaErrorNotSupported, Error::NotPermitted => ResponseStatus::PsaErrorNotPermitted, Error::BufferTooSmall => ResponseStatus::PsaErrorBufferTooSmall, Error::AlreadyExists => ResponseStatus::PsaErrorAlreadyExists, Error::DoesNotExist => ResponseStatus::PsaErrorDoesNotExist, Error::BadState => ResponseStatus::PsaErrorBadState, Error::InvalidArgument => ResponseStatus::PsaErrorInvalidArgument, Error::InsufficientMemory => ResponseStatus::PsaErrorInsufficientMemory, Error::InsufficientStorage => ResponseStatus::PsaErrorInsufficientStorage, Error::CommunicationFailure => ResponseStatus::PsaErrorCommunicationFailure, Error::StorageFailure => ResponseStatus::PsaErrorStorageFailure, Error::DataCorrupt => ResponseStatus::PsaErrorDataCorrupt, Error::DataInvalid => ResponseStatus::PsaErrorDataInvalid, Error::HardwareFailure => ResponseStatus::PsaErrorHardwareFailure, Error::CorruptionDetected => ResponseStatus::PsaErrorCorruptionDetected, Error::InsufficientEntropy => ResponseStatus::PsaErrorInsufficientEntropy, Error::InvalidSignature => ResponseStatus::PsaErrorInvalidSignature, Error::InvalidPadding => ResponseStatus::PsaErrorInvalidPadding, Error::InsufficientData => ResponseStatus::PsaErrorInsufficientData, Error::InvalidHandle => ResponseStatus::PsaErrorInvalidHandle, } } } /// A Result type with the Err variant set as a ResponseStatus pub type Result = std::result::Result; parsec-interface-0.29.1/src/requests/utils.rs000064400000000000000000000036771046102023000173150ustar 00000000000000// Copyright 2019 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 //! Module containing helper macros and functions used in tests. #![macro_use] macro_rules! get_from_stream { ($stream:expr, $type:ty) => { match &mut $stream { stream => { let mut read_bytes = [0_u8; std::mem::size_of::<$type>()]; stream.read_exact(&mut read_bytes)?; <$type>::from_le_bytes(read_bytes) } } }; ($stream:expr; $size:expr) => { match (&mut $stream, $size) { (stream, size) => { let mut read_bytes = vec![0; size]; stream.read_exact(&mut read_bytes)?; read_bytes } } }; } #[cfg(test)] pub mod tests { use std::io::{Error, ErrorKind, Read, Result, Write}; #[derive(Debug)] pub struct MockReadWrite { pub buffer: Vec, } impl Read for MockReadWrite { fn read(&mut self, buf: &mut [u8]) -> Result { for val in buf.iter_mut() { *val = self.buffer.remove(0); } Ok(buf.len()) } } impl Write for MockReadWrite { fn write(&mut self, buf: &[u8]) -> Result { for val in buf.iter() { self.buffer.push(*val); } Ok(buf.len()) } fn flush(&mut self) -> Result<()> { Ok(()) } } #[derive(Copy, Clone, Debug)] pub struct MockFailReadWrite; impl Read for MockFailReadWrite { fn read(&mut self, _: &mut [u8]) -> Result { Err(Error::from(ErrorKind::Other)) } } impl Write for MockFailReadWrite { fn write(&mut self, _: &[u8]) -> Result { Err(Error::from(ErrorKind::Other)) } fn flush(&mut self) -> Result<()> { Err(Error::from(ErrorKind::Other)) } } } parsec-interface-0.29.1/tests/ci.sh000075500000000000000000000020411046102023000152210ustar 00000000000000#!/usr/bin/env bash # Copyright 2020 Contributors to the Parsec project. # SPDX-License-Identifier: Apache-2.0 # Continuous Integration test script, executed by GitHub Actions on x86 and # Travis CI on Arm64. # To update the `parsec-operations` submodule, rebase onto the latest release and commit before running `ci.sh` set -euf -o pipefail # The Parsec operations repository is included as a submodule. It is # necessary to update it first. git submodule update --init ############## # Build test # ############## RUST_BACKTRACE=1 cargo build RUST_BACKTRACE=1 cargo build --features testing RUST_BACKTRACE=1 cargo build --features regenerate-protobuf ################# # Static checks # ################# # On native target clippy or fmt might not be available. if cargo fmt -h then cargo fmt --all -- --check fi if cargo clippy -h then cargo clippy --all-targets -- -D clippy::all -D clippy::cargo fi ############################ # Unit tests and doc tests # ############################ RUST_BACKTRACE=1 cargo test --all-features cargo clean