From ce3bdfee3ad0d500dba480ecb0b0339fed68bcbc Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Wed, 20 Aug 2025 16:04:26 +0200 Subject: [PATCH 01/20] docs: added logging instructions for ios emulator to flutter plugin, added description to flutter plugin --- cSpell.json | 2 + cal_flutter_plugin/README.md | 45 +++++++++++++---------- cal_flutter_plugin/pubspec.yaml | 4 +- cal_flutter_plugin/rust/src/api/simple.rs | 5 ++- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/cSpell.json b/cSpell.json index b629d652..8a519f65 100644 --- a/cSpell.json +++ b/cSpell.json @@ -40,6 +40,7 @@ "rustup", "securestore", "serde", + "simctl", "sodiumoxide", "sqlite", "Sqlite", @@ -47,6 +48,7 @@ "Taskfile", "thiserror", "typia", + "xcrun", "yubi", "yubikey", "zeroize", diff --git a/cal_flutter_plugin/README.md b/cal_flutter_plugin/README.md index c719b1d8..e0b04f02 100644 --- a/cal_flutter_plugin/README.md +++ b/cal_flutter_plugin/README.md @@ -1,19 +1,10 @@ -# cal_flutter_plugin +# `cal_flutter_plugin` -A new Flutter FFI plugin project. - -## Getting Started - -This project is a starting point for a Flutter -[FFI plugin](https://flutter.dev/to/ffi-package), -a specialized package that includes native code directly invoked with Dart FFI. +Flutter FFI plugin for the crypto layer project. ## Project structure -This template uses the following structure: - -* `src`: Contains the native source code, and a CmakeFile.txt file for building - that source code into a dynamic library. +This project has the following structure: * `lib`: Contains the Dart code that defines the API of the plugin, and which calls into the native code using `dart:ffi`. @@ -21,6 +12,29 @@ This template uses the following structure: * platform folders (`android`, `ios`, `windows`, etc.): Contains the build files for building and bundling the native code library with the platform application. + +## Binding to native code + +To use the native code, bindings in Dart are needed. +To avoid writing these by hand, they are generated from the header file +(`src/cal_flutter_plugin.h`) by `package:ffigen`. +Regenerate the bindings by running `dart run ffigen --config ffigen.yaml`. + + +## Reading logs + +Crypto-layer uses structured logging. See the [tracing documentation](https://docs.rs/tracing/latest/tracing/#spans). + +### IOS Emulator + +On apple platforms spans are logged as activities. + +To read logs and activities from the command line, you may use `xcrun` with `grep`: +```sh +xcrun simctl spawn booted log stream -level debug | grep -E "cal\_flutter\_plugin|eu\.nmshd\.crypto\-layer" +``` + + ## Building and bundling native code The `pubspec.yaml` specifies FFI plugins as follows: @@ -68,13 +82,6 @@ The native build systems that are invoked by FFI (and method channel) plugins ar * See the documentation in linux/CMakeLists.txt. * See the documentation in windows/CMakeLists.txt. -## Binding to native code - -To use the native code, bindings in Dart are needed. -To avoid writing these by hand, they are generated from the header file -(`src/cal_flutter_plugin.h`) by `package:ffigen`. -Regenerate the bindings by running `dart run ffigen --config ffigen.yaml`. - ## Invoking native code Very short-running native functions can be directly invoked from any isolate. diff --git a/cal_flutter_plugin/pubspec.yaml b/cal_flutter_plugin/pubspec.yaml index 23fa74bf..8871f231 100644 --- a/cal_flutter_plugin/pubspec.yaml +++ b/cal_flutter_plugin/pubspec.yaml @@ -1,7 +1,7 @@ name: cal_flutter_plugin -description: "A new Flutter FFI plugin project." +description: "Flutter FFI plugin for the crypto layer project." version: 0.0.1 -homepage: +repository: https://github.com/nmshd/rust-crypto environment: sdk: ^3.8.0 diff --git a/cal_flutter_plugin/rust/src/api/simple.rs b/cal_flutter_plugin/rust/src/api/simple.rs index cd4728e7..47109704 100644 --- a/cal_flutter_plugin/rust/src/api/simple.rs +++ b/cal_flutter_plugin/rust/src/api/simple.rs @@ -16,8 +16,9 @@ use tracing_subscriber::Registry; pub(super) fn set_up_logging() { #[cfg(target_os = "android")] - let subscriber = Registry::default() - .with(tracing_android::layer("RUST").expect("could not create android logger")); + let subscriber = Registry::default().with( + tracing_android::layer("eu.nmshd.crypto-layer").expect("could not create android logger"), + ); #[cfg(any(target_os = "macos", target_os = "ios"))] let subscriber = Registry::default().with( From 27850f5d6ddb937614755b3184b0452b31bdcba0 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Wed, 20 Aug 2025 16:13:41 +0200 Subject: [PATCH 02/20] docs: removed old warning --- examples/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/README.md b/examples/README.md index 7806915e..57e8260b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,11 +8,8 @@ cd rust-crypto ## Sign Data Example -> [!WARNING] -> There might be some issues compiling the software provider with gnu windows toolchain. +Example showing how to create a software provider, create a key pair, sign and verify data. ``` cargo run -F software --example sign_data ``` - -Example showing how to create a software provider, create a key pair, sign and verify data. \ No newline at end of file From f702e4b143a48b47ee659c9a8d28d6f1421c635f Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Wed, 20 Aug 2025 16:43:11 +0200 Subject: [PATCH 03/20] docs: reworked flutter example app readme --- cSpell.json | 4 +++ examples/README.md | 4 +-- flutter_app/README.md | 62 +++++++++++++++++++------------------------ 3 files changed, 33 insertions(+), 37 deletions(-) diff --git a/cSpell.json b/cSpell.json index 8a519f65..b5e965e8 100644 --- a/cSpell.json +++ b/cSpell.json @@ -1,5 +1,7 @@ { "words": [ + "androideabi", + "armv", "arrayref", "asym", "blake", @@ -10,6 +12,7 @@ "ciphertext", "codegen", "dalek", + "DEVICEID", "Diffie", "ecdh", "Ecdsa", @@ -38,6 +41,7 @@ "rstest", "rusqlite", "rustup", + "sdkmanager", "securestore", "serde", "simctl", diff --git a/examples/README.md b/examples/README.md index 57e8260b..2af000e4 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,7 +1,7 @@ # Examples To execute the examples you need to clone this git repository and cd into its root: -``` +```sh git clone https://github.com/nmshd/rust-crypto.git cd rust-crypto ``` @@ -10,6 +10,6 @@ cd rust-crypto Example showing how to create a software provider, create a key pair, sign and verify data. -``` +```sh cargo run -F software --example sign_data ``` diff --git a/flutter_app/README.md b/flutter_app/README.md index 523b99a7..58c21c47 100644 --- a/flutter_app/README.md +++ b/flutter_app/README.md @@ -1,50 +1,42 @@ -# Example Flutter App integration +# Example Flutter App -This repository additionally contains a Flutter native plugin and an example Flutter app to test the Crypto Abstraction Layer, currently only supporting Android. +Example flutter app using [crypto-layer](../README.md) via the [`cal_flutter_plugin`](../cal_flutter_plugin/README.md). -To run this App, the following tools are reqiuired: -- Rust compiler -- Rust aarch64-linux-android and armv7-linux-androideabi toolchains -- cargo-ndk -- Android Debug Bridge (adb) -- Flutter -- Android SDK -- Android NDK +## Prerequisites -## Dependencies +To run this App, the following tools are required: -``` -# rustup -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +- [Rust compiler](https://www.rust-lang.org/tools/install) +- [Flutter](https://docs.flutter.dev/get-started/install) -# toolchains -rustup target add \ - aarch64-linux-android \ - armv7-linux-androideabi \ - x86_64-linux-android \ - i686-linux-android -# cargo-ndk -cargo install cargo-ndk -``` +### Android Specifics -Addidtionally install Flutter and either install Android Studio or Download the Android SDK -Now you can install the NDK with: +- [cargo-ndk](https://github.com/bbqsrc/cargo-ndk?tab=readme-ov-file#installing) + - Do not forget to install cargo-ndk dependencies (the toolchains) first! +- Android SDK +- Android Debug Bridge (adb) +- Android NDK -``` -sdkmanager ndk-bundle -``` ## Running the App -Get the id of the connected Android device with `flutter devices`, then run the App in debug mode: +> [!TIP] +> Android Emulators don't contain a Secure Element. + +1. Start an emulator (`flutter emulators --launch ____`) or connect a device. +2. Compile and run the app: + ```sh + flutter run + ``` -``` -cd flutter_app -flutter run -d $DEVICEID -``` +You might also want to use a specific device: +1. List connected devices: + `flutter devices` +2. Compile and run the app: + `flutter run -d ______` -This should compile the Rust code and the plugin and start the App on the device. +## Logs -As Android Emulators don't contain a Secure Element, the App was only tested on real devices. +See the [`cal_flutter_plugin` documentation](../cal_flutter_plugin/README.md#reading-logs). From d7260de8165ab8e6adb2a1f63a755aa3b5f035f5 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Wed, 20 Aug 2025 16:52:47 +0200 Subject: [PATCH 04/20] docs: reworked eror handling section to reflect current best practices, fixed some typos --- CONTRIBUTION.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/CONTRIBUTION.md b/CONTRIBUTION.md index 0abc2579..4ead3d90 100644 --- a/CONTRIBUTION.md +++ b/CONTRIBUTION.md @@ -10,15 +10,16 @@ Your coding style should follow the [official rust style guide](https://doc.rust ## Error Handling -* Errors should, when available be wrapped with `CalError` before returning. - * Make use of `CalErrorKind` categories. - * The source error should be wrapped into an `anyhow::Error` and be set as source. - * Errors should be logged with `tracing::error!()` right where they are first seen. - * Structured logging should always be preffered: `tracing::error!(error=the_error_Im_logging, "My error message")` ✔️ - * Do not log `CalError` as debug print: `tracing::error!("{:?}", the_error_Im_logging)` ❌ - * Consider using `#[tracing::instrument(level = "trace")]` for complex functions. - * Consider using `#[tracing::instrument]` for important functions, like `delete()`. - * **Never log secrets!**. Skip secrets: `#[instrument(skip(secret1, secret2))]` or `#[instrument(skip_all)]` +* Errors: + * Prefer structured errors (nested enums). + * Prefer one structured error per logical unit (function / module). + * Errors should not be generic (anyhow, eyre), but rather specific, structured and parsable. +* Logging: + * Prefer structured logging: `tracing::error!(error=the_error_Im_logging, "My error message")` ✔️ + * Do not log errors as debug print: `tracing::error!("{:?}", the_error_Im_logging)` ❌ + * Consider using `#[tracing::instrument(level = "trace")]` for complex functions. + * Consider using `#[tracing::instrument]` for important functions, like `delete()`. + * **Never log secrets!**. Skip secrets: `#[instrument(skip(secret1, secret2))]` or `#[instrument(skip_all)]` ## Commits @@ -28,7 +29,7 @@ Commits must follow [Conventional Commits](https://www.conventionalcommits.org/e ## Branch Names -Branch names must adhere to the following schme: `the-operation/the-thing-being-worked-on` +Branch names must adhere to the following scheme: `the-operation/the-thing-being-worked-on` ``` feature/structured-error-logging @@ -40,7 +41,7 @@ fix/program-crash-on-second-provider-creation ## Pull Requests -A PR should have a good description of what has been added, changed and removed. Examples might be usefull. +A PR should have a good description of what has been added, changed and removed. Examples might be useful. Before merging a PR go over the [checklist](.github/PULL_REQUEST_TEMPLATE/default.md). @@ -54,5 +55,5 @@ The examples should cover the core use cases of the library. ### README -The README of the subprojects should describe how to build and test the subprojects. +The README of the subprojekts should describe how to build and test the subprojekts. From bb00ab1406b02082cb5408eb15a5aa260a82f8ca Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Wed, 20 Aug 2025 17:14:38 +0200 Subject: [PATCH 05/20] docs: removed old warning, fixed outdated diagram, strikeout of abandoned feature --- README.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8c87e131..08fa6996 100644 --- a/README.md +++ b/README.md @@ -6,36 +6,34 @@ -> [!WARNING] +> [!CAUTION] > Work in Progress -> [!WARNING] -> Might not compile on `x86_64-pc-windows-gnu`. - Crypto Layer is a comprehensive and flexible cryptographic library designed to provide a unified interface for various cryptographic operations and algorithms. It offers a wide range of functionalities, including encryption, decryption, signing, signature verification, and hashing, while supporting both symmetric and asymmetric cryptography. ## Features +> [!NOTE] +> Support for specific algorithms and features is dependent on the target platform. + - **Encryption Algorithms**: Supports a variety of encryption algorithms, including: - Asymmetric Encryption: RSA, ECC (Elliptic Curve Cryptography) with various curve types (P-256, P-384, P-521, secp256k1, Brainpool curves, Curve25519, Curve448, FRP256v1) - Symmetric Block Ciphers: AES (GCM, CBC) - Stream Ciphers: ChaCha20, XChaCha20 - - **Hashing Algorithms**: Supports a wide range of hashing algorithms, including: - SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256) - SHA-3 (SHA3-224, SHA3-256, SHA3-384, SHA3-512) - - **Key Management**: Provides a unified interface for creating, loading, and managing cryptographic keys, supporting various key usages and algorithms. - **Cross-Platform Support**: Designed to work seamlessly across multiple platforms, including Android, Apple, Linux and Windows, with platform-specific implementations for key handling and security module integration. -- **Security Module Integration**: Integrates with Hardware Security Modules (HSMs) and Trusted Platform Modules (TPMs) for secure key storage and cryptographic operations, ensuring enhanced security and compliance with industry standards. +- **Security Module Integration**: Integrates with ~~Hardware Security Modules (HSMs) and~~ Trusted Platform Modules (TPMs) for secure key storage and cryptographic operations, ensuring enhanced security and compliance with industry standards. - **Extensibility**: The modular design of the Crypto Layer allows for easy extension and integration of additional cryptographic algorithms and security modules in the future. @@ -57,7 +55,6 @@ classDiagram Provider "1" --> "0..*" KeyHandle : manages Provider "1" --> "0..*" KeyPairHandle : manages Provider "1" --> "0..*" DHExchange : creates ephemeral - KeyPairHandle "1" --> "1" DHExchange : creates DHExchange "1" --> "1" KeyHandle : results in class Provider { @@ -130,7 +127,7 @@ Examples for the rust crate can be found in the [example folder](./examples/). ### [Usage Flutter Plugin](./flutter_plugin/README.md) -### [Example Flutter App integration](./flutter_app/README.md) +### [Example Flutter App](./flutter_app/README.md) ### [Usage NodeJS Plugin](https://github.com/nmshd/crypto-layer-node) From b9b86772a9f64c9e13ee2e3d127d3722b1defa94 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Wed, 20 Aug 2025 18:37:53 +0200 Subject: [PATCH 06/20] docs: added to readme how to build the docs, added auto docs, updated top level docs --- Cargo.toml | 4 ++++ README.md | 13 +++++++++++++ cSpell.json | 3 +++ src/README.md | 26 ++++++++++++++++++++++++++ src/lib.rs | 16 ++-------------- 5 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 src/README.md diff --git a/Cargo.toml b/Cargo.toml index 7a8318ed..d8a7aa66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,3 +105,7 @@ test-case = "3.3.1" tempfile = "3.15.0" lazy_static = "1.5.0" rstest = "0.25.0" + +[package.metadata.docs.rs] +features = [] +rustdoc-args = ["--cfg", "docsrs"] diff --git a/README.md b/README.md index 08fa6996..4c73be2a 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,19 @@ Examples for the rust crate can be found in the [example folder](./examples/). ### [Usage NodeJS Plugin](https://github.com/nmshd/crypto-layer-node) +## Documentation + +### Build Documentation + +To build the documentation run: +```sh +RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --open +``` +Or in Powershell: +```sh +$env:RUSTDOCFLAGS="--cfg docsrs" +cargo +nightly doc --open +``` ## Contributing diff --git a/cSpell.json b/cSpell.json index b5e965e8..c70789ac 100644 --- a/cSpell.json +++ b/cSpell.json @@ -14,6 +14,7 @@ "dalek", "DEVICEID", "Diffie", + "docsrs", "ecdh", "Ecdsa", "esapi", @@ -40,6 +41,8 @@ "robusta", "rstest", "rusqlite", + "rustdoc", + "RUSTDOCFLAGS", "rustup", "sdkmanager", "securestore", diff --git a/src/README.md b/src/README.md new file mode 100644 index 00000000..54e30bfe --- /dev/null +++ b/src/README.md @@ -0,0 +1,26 @@ +`crypto-layer` is meant as a library interfacing with secure elements of different operating systems. + +# Providers + +Every operating system provides a different native API for accessing secure elements. +Providers are implementations of the `crypto-layer` API. + +Though there are some caveats: + +- The `crypto-layer` API is vast and not every provider supports all algorithms or operations! +- Some of the `crypto-layer` API is not applicable to every provider. + +There are following providers: + +- `ANDROID_PROVIDER` and `ANDROID_PROVIDER_SECURE_ELEMENT` (Android) + - These two providers differ in the security they minimally provide. + `ANDROID_PROVIDER_SECURE_ELEMENT` always uses a [Strongbox](https://source.android.com/docs/compatibility/15/android-15-cdd#9112_strongbox), + while `ANDROID_PROVIDER` may use secure elements that are not certified. +- `APPLE_SECURE_ENCLAVE` (IOS and MacOS) + - Is only usable, when the application using `crypto-layer` is code signed! + - Supports asymmetric cryptography including asymmetric hybrid encryption schemes. +- `SoftwareProvider` (Fallback) + - Supports every operating system, but also does not make use of any secure element. + +Currently there is no good way to check, what provider supports what operation explicitly. +A provider returns an error with `CalErrorKind::NotImplemented`, if an operation is not supported or implemented. diff --git a/src/lib.rs b/src/lib.rs index cfa94271..b3962ffb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,17 +1,5 @@ -//! `cryptolayer` is meant as a library interfacing with secure elements of different operating systems. -//! -//! # Providers -//! -//! | Provider Name | Sign and Verify | Encrypt and Decrypt | DH Exchange | Import Key | Import Key Pair | Import Public Key | Export Key | Export Private Key | Export Public Key | -//! | ------------------------------- | --------------------- | ------------------------- | ----------- | ---------- | --------------- | ----------------- | ---------- | ------------------ | ----------------- | -//! | STUB_PROVIDER | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | -//! | ANDROID_PROVIDER | ✅ | ✅ | ✅ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ✅ | -//! | ANDROID_PROVIDER_SECURE_ELEMENT | ✅ | ✅ | ✅ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ✅ | -//! | APPLE_SECURE_ENCLAVE | ✅ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ⬜ | ✅ | -//! | SoftwareProvider | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ⬜ | ✅ | ✅ | -//! -//! - +#![doc = include_str!("./README.md")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![warn( rust_2024_incompatible_pat, rust_2024_prelude_collisions, From 32f0953874fea81cdbaae9ef7001a21ca85ff7ac Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 10:44:36 +0200 Subject: [PATCH 07/20] ci: added building of documentation to taskfile --- README.md | 5 +++++ Taskfile.yml | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4c73be2a..739e3a8b 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,11 @@ $env:RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --open ``` +Or if you have [task](https://taskfile.dev/) installed, run: +```sh +task build-documentation +``` + ## Contributing Contributions to the Crypto Layer are welcome! diff --git a/Taskfile.yml b/Taskfile.yml index 70d4c9bc..03040b52 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -18,11 +18,11 @@ tasks: - npm run prepare prerequisites-dt: - aliases: [predt] - desc: Installs dart dependencies. - dir: ./cal_flutter_plugin/ - cmds: - - dart pub get + aliases: [predt] + desc: Installs dart dependencies. + dir: ./cal_flutter_plugin/ + cmds: + - dart pub get generate: desc: Generates ts types and dart bindings. @@ -44,7 +44,7 @@ tasks: dir: ./cal_flutter_plugin/ cmds: - flutter_rust_bridge_codegen generate --rust-preamble "use std::future::Future; use std::pin::Pin; use crypto_layer::common::config::DynFuture;" - # - flutter pub run build_runner build + # - flutter pub run build_runner build test: desc: Execute non interactive tests. @@ -87,3 +87,11 @@ tasks: dir: ./flutter_app/ cmds: - flutter test integration_test/cal_test.dart + + build-documentation: + desc: Build the documentation of crypto-layer and open it in the browser + aliases: [bdoc] + env: + RUSTDOCFLAGS: --cfg docsrs + cmds: + - cargo +nightly doc --open From 6035133306d0abe1eda4fe3a19881a56ed05816e Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 11:41:13 +0200 Subject: [PATCH 08/20] docs: added top level docs to factory, reworked docs of error --- Taskfile.yml | 4 ++-- src/common/error.rs | 15 +++++++-------- src/common/factory.rs | 15 +++++++++++++++ src/common/mod.rs | 8 ++++---- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 03040b52..d583d4c9 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -89,9 +89,9 @@ tasks: - flutter test integration_test/cal_test.dart build-documentation: - desc: Build the documentation of crypto-layer and open it in the browser + desc: Build the documentation of crypto-layer aliases: [bdoc] env: RUSTDOCFLAGS: --cfg docsrs cmds: - - cargo +nightly doc --open + - cargo +nightly doc diff --git a/src/common/error.rs b/src/common/error.rs index e5af0fed..da124af9 100644 --- a/src/common/error.rs +++ b/src/common/error.rs @@ -8,13 +8,12 @@ use crate::storage::{StorageManagerError, StorageManagerInitializationError}; // Feel free to add more items to error. -/// Error wrapping native errors. +/// Crypto-layer error representation. /// -/// The native libraries used large lists of errors that might occur. -/// This struct exists to dumb down said errors. -/// The provider implementation should map errors from native libraries to this enum. -/// Most if not all errors should have a source for backtraces. -/// If other fields are useful for understanding the error, they should also exist. +/// Every provider is built for a different native backend or purpose in mind. +/// Moreover crypto-layer must be ffi compatible. +/// For these reasons this error is not an enum, but rather a struct containing a non nested enum +/// and a source, that does not need to be parsed by ffi. #[derive(thiserror::Error, Debug)] #[error("{error_kind}: {source}")] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] @@ -26,8 +25,8 @@ pub struct CalError { source: anyhow::Error, } -/// Enumeration differentiating between the causes and the severity of the error. -/// flutter_rust_bridge:non_opaque +/// Enumeration of classifications of error sources. +// flutter_rust_bridge:non_opaque #[derive(thiserror::Error, Debug, Clone)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] #[repr(C)] diff --git a/src/common/factory.rs b/src/common/factory.rs index 214a49b6..7d28fbcf 100644 --- a/src/common/factory.rs +++ b/src/common/factory.rs @@ -1,3 +1,18 @@ +//! +//! There are essentially two ways of getting your first provider: +//! 1. Create a [`ProviderConfig`] that represents your needs +//! and then use [`create_provider`] to get assigned a provider automatically. +//! 2. Use [`get_all_providers`] and [`get_provider_capabilities`] +//! to find a suitable provider and use [`create_provider_from_name`] to create said provider. +//! +//! As keys are bound to their respective provider, it is advisable +//! to store the used providers and recreate them with [`create_provider_from_name`]. +//! +//! [`create_provider`]: crate::common::factory::create_provider +//! [`get_all_providers`]: crate::common::factory::get_all_providers +//! [`get_provider_capabilities`]: crate::common::factory::get_provider_capabilities +//! [`create_provider_from_name`]: crate::common::factory::create_provider_from_name + use std::sync::LazyLock; use tracing::{trace, warn}; diff --git a/src/common/mod.rs b/src/common/mod.rs index fbbfebd1..6e4d750b 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -9,18 +9,18 @@ use traits::key_handle::{ }; use traits::module_provider::{ProviderImpl, ProviderImplEnum}; -/// Structs and enumerations used for configuring providers, key and key pairs. +/// Configuration for providers, key and key pairs. pub mod config; -/// Structs and enumerations representing cryptographic algorithms or standards. +/// Cryptographic algorithms or standards. pub mod crypto; -/// Struct for error handling. +/// Error representations. pub mod error; /// Functions used for creating providers. pub mod factory; pub(crate) mod traits; // Do not delete this struct, it is a workaround for a bug in the code generation -/// ¯\_(ツ)_/¯ +#[doc(hidden)] pub struct T {} macro_rules! delegate_enum { From c9cb6130625ea7e92f6cc7bd0200e9eba249aee2 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 14:37:53 +0200 Subject: [PATCH 09/20] docs: fixed some descriptions not being shown and flutter rust bridge necessary comments being doc comments --- cSpell.json | 5 +++++ src/common/config.rs | 15 +++++++-------- src/common/crypto/algorithms/encryption.rs | 4 ++-- src/common/crypto/algorithms/hashes.rs | 2 +- .../crypto/algorithms/key_derivation.rs | 19 +++++++++++-------- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/cSpell.json b/cSpell.json index c70789ac..79cf4da8 100644 --- a/cSpell.json +++ b/cSpell.json @@ -11,6 +11,7 @@ "chacha", "ciphertext", "codegen", + "Cryptoki", "dalek", "DEVICEID", "Diffie", @@ -31,7 +32,9 @@ "libloading", "libsodium", "nmshd", + "Ocsp", "pkcs", + "Pkix", "pwsh", "qufiwefefwoyn", "redb", @@ -45,6 +48,8 @@ "RUSTDOCFLAGS", "rustup", "sdkmanager", + "secp", + "Secp", "securestore", "serde", "simctl", diff --git a/src/common/config.rs b/src/common/config.rs index 711cedb1..08bdf40d 100644 --- a/src/common/config.rs +++ b/src/common/config.rs @@ -53,7 +53,7 @@ pub type AllKeysFn = Arc DynFuture> + Send + Sync>; /// /// * [SecurityLevel::Hardware]: Provider is hardware backed (tpm, other security chips, StrongBox KeyStore). /// * [SecurityLevel::Software]: Provider uses the systems software keystore. -/// * [SecurityLevel::Network]: Provider uses a network key store (Hashicorp). +/// * [SecurityLevel::Network]: Provider uses a network key store (HashiCorp). /// * [SecurityLevel::Unsafe]: Provider uses software fallback. #[derive( Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, EnumString, EnumIter, IntoStaticStr, @@ -81,7 +81,7 @@ pub enum SecurityLevel { #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque pub enum Spec { KeySpec(KeySpec), KeyPairSpec(KeyPairSpec), @@ -90,7 +90,7 @@ pub enum Spec { /// Struct used to configure keys. #[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, Zeroize, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque pub struct KeySpec { /// Cipher used for symmetric encryption. pub cipher: Cipher, @@ -105,7 +105,7 @@ pub struct KeySpec { /// Struct used to configure key pairs. #[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque pub struct KeyPairSpec { /// Asymmetric algorithm to be used. pub asym_spec: AsymmetricKeySpec, @@ -120,7 +120,7 @@ pub struct KeyPairSpec { } /// Capabilities of a Provider -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[derive(Clone, Debug)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct ProviderConfig { @@ -140,7 +140,6 @@ pub struct ProviderConfig { /// and either /// * [AdditionalConfig::StorageConfigHMAC] /// * [AdditionalConfig::StorageConfigDSA] -/// * [AdditionalConfig::StorageConfigPass] /// /// need to be supplied. /// @@ -156,7 +155,7 @@ pub struct ProviderConfig { /// ], /// }; /// ``` -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[derive(Clone)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct ProviderImplConfig { @@ -164,7 +163,7 @@ pub struct ProviderImplConfig { } /// Configuration needed for using or initializing providers. -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[derive(Clone, EnumDiscriminants)] #[strum_discriminants(derive(EnumString, IntoStaticStr))] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] diff --git a/src/common/crypto/algorithms/encryption.rs b/src/common/crypto/algorithms/encryption.rs index 101b4bb2..2f67eb81 100644 --- a/src/common/crypto/algorithms/encryption.rs +++ b/src/common/crypto/algorithms/encryption.rs @@ -16,7 +16,7 @@ use strum::{EnumString, IntoStaticStr}; /// /// This enum uses `#[repr(C)]` to ensure that it has the same memory layout as a C enum, /// facilitating interfacing with C code or when ABI compatibility is required. -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[repr(C)] #[derive( Clone, @@ -72,7 +72,7 @@ pub enum AsymmetricKeySpec { /// /// Marked with `#[repr(C)]` to ensure it has the same memory layout as a C enum, /// facilitating ABI compatibility and interfacing with C code. -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[repr(C)] #[derive( Clone, diff --git a/src/common/crypto/algorithms/hashes.rs b/src/common/crypto/algorithms/hashes.rs index 94d12b76..8be357d6 100644 --- a/src/common/crypto/algorithms/hashes.rs +++ b/src/common/crypto/algorithms/hashes.rs @@ -12,7 +12,7 @@ use zeroize::Zeroize; /// Algorithms like SHA-1, MD2, MD4, and MD5 are considered insecure for most cryptographic /// purposes due to practical collision attacks and should be avoided for new applications. /// Prefer using more secure algorithms like SHA-2 or SHA-3 for cryptographic purposes. -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[repr(C)] #[derive( Clone, diff --git a/src/common/crypto/algorithms/key_derivation.rs b/src/common/crypto/algorithms/key_derivation.rs index f836d912..cdeaa3c2 100644 --- a/src/common/crypto/algorithms/key_derivation.rs +++ b/src/common/crypto/algorithms/key_derivation.rs @@ -25,7 +25,7 @@ use serde::{Deserialize, Serialize}; /// parallelism: 1, /// }); /// ``` -/// flutter_rust_bridge:non_opaque +// flutter_rust_bridge:non_opaque #[derive(Clone, Copy, Debug, Serialize, Deserialize)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub enum KDF { @@ -36,7 +36,10 @@ pub enum KDF { Argon2i(Argon2Options), } -/// flutter_rust_bridge:non_opaque +/// Configuration for KDF with Argon2 +/// +/// When in doubt use the default. +// flutter_rust_bridge:non_opaque #[derive(Clone, Copy, Debug, Serialize, Deserialize)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct Argon2Options { @@ -48,10 +51,10 @@ pub struct Argon2Options { pub parallelism: u32, } -// Defaults for servers. -// Taken from Password Storage Cheat Sheet (12.03.2025) -// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html impl Default for Argon2Options { + /// Defaults for servers. + /// Taken from Password Storage Cheat Sheet (12.03.2025) + /// fn default() -> Self { Argon2Options { memory: 19456, @@ -61,10 +64,10 @@ impl Default for Argon2Options { } } -// Defaults for servers. -// Taken from Password Storage Cheat Sheet (12.03.2025) -// https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html impl Default for KDF { + /// Defaults for servers. + /// Taken from Password Storage Cheat Sheet (12.03.2025) + /// fn default() -> Self { KDF::Argon2id(Argon2Options::default()) } From d12be4ffbe2814ce0315345c889292a3e5ed23c9 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 15:42:52 +0200 Subject: [PATCH 10/20] docs: added docs for ProviderConfig and updated docs for create_provider, also fixed top level docs not mentioning caveat of android provider --- cSpell.json | 1 + .../common/crypto/algorithms/encryption.dart | 1 - src/README.md | 2 +- src/common/config.rs | 88 +++++++++++++++++++ src/common/factory.rs | 21 ++--- src/provider/android/provider.rs | 4 +- 6 files changed, 101 insertions(+), 16 deletions(-) diff --git a/cSpell.json b/cSpell.json index 79cf4da8..377629b1 100644 --- a/cSpell.json +++ b/cSpell.json @@ -22,6 +22,7 @@ "github", "hcvault", "hmac", + "initializable", "Itertools", "jalgorithm", "javax", diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart index c68c6092..e92eeaf5 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart @@ -3,7 +3,6 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import -import '../../../../../frb_generated.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `clone`, `clone`, `eq`, `eq`, `fmt`, `fmt`, `from_str`, `from_str`, `from`, `from`, `from`, `from`, `hash`, `hash`, `try_from`, `try_from`, `zeroize` diff --git a/src/README.md b/src/README.md index 54e30bfe..95715332 100644 --- a/src/README.md +++ b/src/README.md @@ -15,7 +15,7 @@ There are following providers: - `ANDROID_PROVIDER` and `ANDROID_PROVIDER_SECURE_ELEMENT` (Android) - These two providers differ in the security they minimally provide. `ANDROID_PROVIDER_SECURE_ELEMENT` always uses a [Strongbox](https://source.android.com/docs/compatibility/15/android-15-cdd#9112_strongbox), - while `ANDROID_PROVIDER` may use secure elements that are not certified. + while `ANDROID_PROVIDER` may use secure elements that are not certified **or non at all!** - `APPLE_SECURE_ENCLAVE` (IOS and MacOS) - Is only usable, when the application using `crypto-layer` is code signed! - Supports asymmetric cryptography including asymmetric hybrid encryption schemes. diff --git a/src/common/config.rs b/src/common/config.rs index 08bdf40d..c0771ac6 100644 --- a/src/common/config.rs +++ b/src/common/config.rs @@ -120,14 +120,102 @@ pub struct KeyPairSpec { } /// Capabilities of a Provider +/// +/// This configuration struct has multiple uses: +/// * Act as capabilities of a provider. +/// * Act as requirement for [`create_provider`](crate::prelude::create_provider). +/// +/// Depending on the use some properties have different meanings: +/// * Currently a provider may only have one security level. +/// * The requester may ask for a provider that has at a minimum one security level or at a maximum another security level. +/// * A provider has certain algorithm he at least in some form supports. +/// * A requester may ask for minimum requirements regarding these algorithms. +/// +/// ### Example +/// +/// A provider might return capabilities like: +/// ``` +/// # use crypto_layer::prelude::*; +/// # use std::collections::HashSet; +/// +/// let apple_provider_capabilities = ProviderConfig { +/// max_security_level: SecurityLevel::Hardware, +/// min_security_level: SecurityLevel::Hardware, +/// supported_ciphers: HashSet::from([Cipher::AesGcm128, Cipher::AesGcm256]), +/// supported_asym_spec: HashSet::from([AsymmetricKeySpec::P256]), +/// supported_hashes: HashSet::from([ +/// CryptoHash::Sha2_224, +/// CryptoHash::Sha2_256, +/// CryptoHash::Sha2_384, +/// CryptoHash::Sha2_512, +/// ]), +/// }; +/// +/// ``` +/// Such provider then is ought to use a secure element (apart from the `ANDROID_PROVIDER`) +/// and at least support these algorithms **in one form or another** . +/// +/// Please be aware, that `supported_ciphers` does not imply support for symmetric cryptography! +/// +/// A requestor might ask for a provider with capabilities like: +/// ``` +/// # use crypto_layer::prelude::*; +/// # use std::collections::HashSet; +/// +/// let requested_capabilities = ProviderConfig { +/// max_security_level: SecurityLevel::Hardware, +/// min_security_level: SecurityLevel::Software, +/// supported_ciphers: HashSet::from([Cipher::AesGcm256]), +/// supported_asym_spec: HashSet::from([AsymmetricKeySpec::P256]), +/// supported_hashes: HashSet::from([ +/// CryptoHash::Sha2_256, +/// CryptoHash::Sha2_512, +/// ]), +/// }; +/// ``` +/// +/// As the requested capabilities are a subset of the provided capabilities above, +/// this requestor might be assigned the apple secure enclave provider on apple platforms. +/// // flutter_rust_bridge:non_opaque #[derive(Clone, Debug)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct ProviderConfig { + /// Highest security supported or maximum security requested. + /// + /// As an example, the software fallback provider has a maximum security level of [`SecurityLevel::Software`]. pub max_security_level: SecurityLevel, + + /// Minimum security level supported or security level required. + /// + /// As an example: + /// If one wishes to use provider that is based on a secure element, one would require [`SecurityLevel::Hardware`]. pub min_security_level: SecurityLevel, + + /// Cipher algorithms supported in one fashion or another or cipher algorithms required. + /// + /// A provider might support cipher algorithms returned as capabilities in following ways: + /// * Supports symmetric encryption with said cipher. + /// * Supports asymmetric hybrid encryption with said cipher. (What standard is used for the hybrid encryption is not set.) pub supported_ciphers: HashSet, + + /// Hashing algorithm supported for either the use with signing (symmetric or asymmetric) operations or encryption operations (symmetric or asymmetric), + /// or hashing algorithm required for the same purpose. + /// + /// A provider that supports a hash algorithm **may or may not** support following operations in combination with said hashing algorithm: + /// * [`KeyHandle::hmac()`](crate::prelude::KeyHandle::hmac) + /// * [`KeyHandle::verify_hmac()`](crate::prelude::KeyHandle::verify_hmac) + /// * [`KeyHandle::encrypt()`](crate::prelude::KeyHandle::encrypt()) + /// * [`KeyHandle::decrypt_data()`](crate::prelude::KeyHandle::decrypt_data()) + /// * [`KeyPairHandle::sign_data`](crate::prelude::KeyPairHandle::sign_data) + /// * [`KeyPairHandle::verify_signature`](crate::prelude::KeyPairHandle::verify_signature) + /// * [`KeyPairHandle::encrypt_data()`](crate::prelude::KeyPairHandle::encrypt_data) + /// * [`KeyPairHandle::decrypt_data()`](crate::prelude::KeyPairHandle::decrypt_data) pub supported_hashes: HashSet, + + /// Asymmetric cryptographic algorithms supported or required. + /// + /// A provider supporting an asymmetric cryptographic algorithm **may or may not** support said algorithm for signing or encryption operations. pub supported_asym_spec: HashSet, } diff --git a/src/common/factory.rs b/src/common/factory.rs index 7d28fbcf..f3a8f6c8 100644 --- a/src/common/factory.rs +++ b/src/common/factory.rs @@ -63,21 +63,18 @@ fn provider_supports_capabilities( .is_subset(&provider_capabilities.supported_hashes) } -/// Returns a provider which supports the given requirements. +/// Returns a provider which supports the given requirements and is initializable. /// -/// This function returns the first provider, which supports the given requirements and has a [`ProviderImplConfig`]. +/// This function returns the first provider, which supports the given requirements (see [`ProviderConfig`]) +/// and can be initialized on the target platform with the given [`ProviderImplConfig`]. /// -/// * `conf` - A provider config that the provider must at least contain. -/// * `impl_conf_vec` - A `Vec` of [`ProviderImplConfig`]. Only providers, which have [`ProviderImplConfig`] are returned. -/// -/// # Example +/// ### Example /// ``` -/// use std::collections::HashSet; -/// -/// use crypto_layer::prelude::*; +/// # use std::collections::HashSet; +/// # use crypto_layer::prelude::*; /// -/// let specific_provider_config = ProviderImplConfig{additional_config: vec![]}; -/// let provider_config = ProviderConfig { +/// let platform_specific_provider_config = ProviderImplConfig{additional_config: vec![]}; +/// let required_capabilities = ProviderConfig { /// min_security_level: SecurityLevel::Software, /// max_security_level: SecurityLevel::Hardware, /// supported_asym_spec: HashSet::new(), @@ -85,7 +82,7 @@ fn provider_supports_capabilities( /// supported_hashes: HashSet::new(), /// }; /// -/// let provider_option: Option = create_provider(&provider_config, specific_provider_config); +/// let provider_option: Option = create_provider(&required_capabilities, platform_specific_provider_config); /// ``` pub fn create_provider(conf: &ProviderConfig, impl_conf: ProviderImplConfig) -> Option { for provider in ALL_PROVIDERS.iter() { diff --git a/src/provider/android/provider.rs b/src/provider/android/provider.rs index 229b09b7..058261b7 100644 --- a/src/provider/android/provider.rs +++ b/src/provider/android/provider.rs @@ -49,13 +49,13 @@ impl ProviderFactory for AndroidProviderFactory { } fn get_capabilities(&self, _impl_config: ProviderImplConfig) -> Option { - // check if android context is initialised + // check if android context is initialized if !wrapper::context::is_initialized() { info!("Android Context is not initialized, no android provider"); return None; } - // only check for Stronbox if secure element is enabled + // only check for Strongbox if secure element is enabled if self.secure_element && !wrapper::context::has_strong_box().ok()? { return None; } From 5b36094fe65175823a2acc5edd7427907034da9e Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 18:59:44 +0200 Subject: [PATCH 11/20] docs: updated factory docs --- src/common/factory.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/factory.rs b/src/common/factory.rs index f3a8f6c8..8924939d 100644 --- a/src/common/factory.rs +++ b/src/common/factory.rs @@ -105,8 +105,10 @@ pub fn create_provider(conf: &ProviderConfig, impl_conf: ProviderImplConfig) -> /// Returns the provider matching the given name. /// -/// * `name` - Name of the provider. See `get_name()`. -/// * `impl_config` - Specif configuration for said provider. +/// Returns `None` if the provider requested is not available on the target platform or it is not initializable. +/// +/// A providers name is a hardcoded string unique to a provider (see [`Provider::provider_name()`](crate::prelude::Provider::provider_name) +/// and [`get_all_providers()`](crate::prelude::get_all_providers)). #[tracing::instrument] pub fn create_provider_from_name(name: &str, impl_conf: ProviderImplConfig) -> Option { trace!("create_provider_from_name: {}", name); @@ -130,6 +132,8 @@ pub fn create_provider_from_name(name: &str, impl_conf: ProviderImplConfig) -> O } /// Returns the names of all available providers. +/// +/// A provider is available if it is initializable on the target platform. pub fn get_all_providers() -> Vec { ALL_PROVIDERS .iter() @@ -137,7 +141,7 @@ pub fn get_all_providers() -> Vec { .collect() } -/// Returns the names and capabilities of all providers that can be initialized with the given [ProviderImplConfig]. +/// Returns the names and capabilities of all providers that can be initialized with the given [ProviderImplConfig] on the target platform. pub fn get_provider_capabilities(impl_config: ProviderImplConfig) -> Vec<(String, ProviderConfig)> { ALL_PROVIDERS .iter() From 2f81b8e8e7eed7ec3b7d13190d327b6c14717f64 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 20:34:29 +0200 Subject: [PATCH 12/20] docs: updated ProviderImplConfig docs --- src/common/config.rs | 53 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/common/config.rs b/src/common/config.rs index c0771ac6..26a1bf93 100644 --- a/src/common/config.rs +++ b/src/common/config.rs @@ -88,33 +88,48 @@ pub enum Spec { } /// Struct used to configure keys. +/// +/// It is important to note, that the configuration of a key can only happen at the point of its creation. +/// A key cannot be reconfigured. #[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, Zeroize, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] // flutter_rust_bridge:non_opaque pub struct KeySpec { /// Cipher used for symmetric encryption. pub cipher: Cipher, + /// Hash function used with HMAC. pub signing_hash: CryptoHash, - /// If set to `true`, the key is going to be deleted when the handle is dropped. + + /// If set to `true`, metadata of the key is not stored and the key is going to be deleted when the handle is dropped. pub ephemeral: bool, + /// If set to `true`, the key cannot be exported. + /// + /// Some providers do not allow exporting keys at all, even if set to `false`. pub non_exportable: bool, } /// Struct used to configure key pairs. +/// +/// It is important to note, that the configuration of a key can only happen at the point of its creation. +/// A key cannot be reconfigured. #[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] // flutter_rust_bridge:non_opaque pub struct KeyPairSpec { /// Asymmetric algorithm to be used. pub asym_spec: AsymmetricKeySpec, + /// Cipher used for hybrid encryption. If set to None, no hybrid encryption will be used. pub cipher: Option, + /// Hash function used for signing and encrypting. pub signing_hash: CryptoHash, + /// If set to true, the key pair will be discarded after the handle is dropped. pub ephemeral: bool, + /// If set to true, the key can't be exported (also software keys) pub non_exportable: bool, } @@ -219,22 +234,28 @@ pub struct ProviderConfig { pub supported_asym_spec: HashSet, } -/// Configuration needed for using or initializing providers. +/// Key metadata store configuration +/// +/// Due to an accident, this configuration became a vector. /// -/// Either -/// * [AdditionalConfig::KVStoreConfig] -/// * [AdditionalConfig::FileStoreConfig] +/// If neither [`AdditionalConfig::KVStoreConfig`] nor [`AdditionalConfig::FileStoreConfig`] are supplied +/// to [`create_provider()`] or to [`create_provider_from_name()`], +/// a provider will be created that is only capable of creating ephemeral keys! /// -/// and either -/// * [AdditionalConfig::StorageConfigHMAC] -/// * [AdditionalConfig::StorageConfigDSA] +/// To protect key metadata against unauthorized change, it is recommended to make use of +/// [`AdditionalConfig::StorageConfigHMAC`] or [`AdditionalConfig::StorageConfigDSA`]. +/// (This may only apply if you use multiple providers and one is of [`SecurityLevel::Hardware`] or above.) +/// +/// If the fallback software provider is used with [AdditionalConfig::StorageConfigSymmetricEncryption] +/// or [AdditionalConfig::StorageConfigAsymmetricEncryption], the stored secret keys are secured by +/// the provided key, which in turn makes such construct a hybrid provider (as the keys at rest have hardware security protection). /// -/// need to be supplied. /// /// ## Example /// /// ```rust -/// use crypto_layer::prelude::*; +/// # use crypto_layer::prelude::*; +/// /// let implementation_config = ProviderImplConfig { /// additional_config: vec![ /// AdditionalConfig::FileStoreConfig { @@ -243,6 +264,10 @@ pub struct ProviderConfig { /// ], /// }; /// ``` +/// +/// [`create_provider()`]: crate::prelude::create_provider +/// [`create_provider_from_name()`]: crate::prelude::create_provider_from_name +/// // flutter_rust_bridge:non_opaque #[derive(Clone)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] @@ -250,7 +275,7 @@ pub struct ProviderImplConfig { pub additional_config: Vec, } -/// Configuration needed for using or initializing providers. +/// Key metadata store configuration enumeration. // flutter_rust_bridge:non_opaque #[derive(Clone, EnumDiscriminants)] #[strum_discriminants(derive(EnumString, IntoStaticStr))] @@ -274,6 +299,7 @@ pub enum AdditionalConfig { delete_fn: DeleteFn, all_keys_fn: AllKeysFn, }, + /// Configuration for the usage of the metadata file database. /// /// Mutually exclusive with [AdditionalConfig::KVStoreConfig]. @@ -281,20 +307,24 @@ pub enum AdditionalConfig { /// Path to a directory where the database holding key metadata will be saved. db_dir: String, }, + /// Enables integrity verification of key metadata. /// /// Mutually exclusive with [AdditionalConfig::StorageConfigDSA]. StorageConfigHMAC(KeyHandle), + /// Enables integrity verification of key metadata. /// /// Mutually exclusive with [AdditionalConfig::StorageConfigHMAC]. StorageConfigDSA(KeyPairHandle), + /// Enables encryption of sensitive key metadata. /// /// In case of the software provider, this enables encryption of secret keys. /// /// Mutually exclusive with [AdditionalConfig::StorageConfigAsymmetricEncryption]. StorageConfigSymmetricEncryption(KeyHandle), + /// Enables encryption of sensitive key metadata. /// /// In case of the software provider, this enables encryption of secret keys. @@ -311,6 +341,7 @@ impl std::fmt::Debug for ProviderImplConfig { impl ProviderImplConfig { /// Creates a new `ProviderImplConfig` instance. + #[doc(hidden)] pub fn new( get_fn: GetFn, store_fn: StoreFn, From 6f964153f7cef98252d9293a2c4e2ea0f7d89963 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 21:00:42 +0200 Subject: [PATCH 13/20] docs: added missing documentation for key handle --- src/common/traits/key_handle.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/traits/key_handle.rs b/src/common/traits/key_handle.rs index a004d195..5ad9dcb7 100644 --- a/src/common/traits/key_handle.rs +++ b/src/common/traits/key_handle.rs @@ -74,8 +74,10 @@ pub(crate) trait KeyHandleImpl: Send + Sync { /// A `Result` containing the decrypted data as a `Vec` on success, or a `CalError` on failure. fn decrypt_data(&self, encrypted_data: &[u8], iv: &[u8]) -> Result, CalError>; + /// Calculates HMAC of the given data. fn hmac(&self, data: &[u8]) -> Result, CalError>; + /// Verifies data with the given signature. fn verify_hmac(&self, data: &[u8], hmac: &[u8]) -> Result; /// Derives an ephemeral key from this key as base with the same spec as the base key. From bd94d833965f7e302f8dc2d7d95945f47210ceae Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 21:16:05 +0200 Subject: [PATCH 14/20] refactor: removed delegate_enum macro in favor of direct implementation of the wrapping logic due to docs be stripped otherwise Copied docs of the traits to the respective redirection logic. --- src/common/mod.rs | 442 ++++++++++++++++++++++++++-------------------- 1 file changed, 249 insertions(+), 193 deletions(-) diff --git a/src/common/mod.rs b/src/common/mod.rs index 6e4d750b..3028b4bf 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -2,7 +2,6 @@ use crate::common::traits::key_handle::DHKeyExchangeImpl; use crate::prelude::{CryptoHash, KDF}; use config::{KeyPairSpec, KeySpec, ProviderConfig, Spec}; use error::CalError; -use tracing::error; use traits::key_handle::DHKeyExchangeImplEnum; use traits::key_handle::{ KeyHandleImpl, KeyHandleImplEnum, KeyPairHandleImpl, KeyPairHandleImplEnum, @@ -23,78 +22,6 @@ pub(crate) mod traits; #[doc(hidden)] pub struct T {} -macro_rules! delegate_enum { - ($(pub fn $method:ident(self $(,$arg:ident: $type:ty)* $(,)?) $(-> $ret:ty)?;)+) => { - $( - pub fn $method(self $(,$arg: $type)*) $(-> $ret)? { - match self.implementation.$method($($arg),*) { - Ok(v) => Ok(v), - Err(e) => { - error!("Error in {}: {}", stringify!($method), e); - Err(e) - } - } - } - )+ - }; - ($(pub fn $method:ident(&self $(,$arg:ident: $type:ty)* $(,)?) $(-> $ret:ty)?;)+) => { - $( - pub fn $method(&self $(,$arg: $type)*) $(-> $ret)? { - match self.implementation.$method($($arg),*) { - Ok(v) => Ok(v), - Err(e) => { - error!("Error in {}: {}", stringify!($method), e); - Err(e) - } - } - } - )+ - }; - ($(pub fn $method:ident(&mut self $(,$arg:ident: $type:ty)* $(,)?) $(-> $ret:ty)?;)+) => { - $( - pub fn $method(&mut self $(,$arg: $type)*) $(-> $ret)? { - match self.implementation.$method($($arg),*) { - Ok(v) => Ok(v), - Err(e) => { - error!("Error in {}: {}", stringify!($method), e); - Err(e) - } - } - } - )+ - }; - ($(pub fn $method:ident(self $(,$arg:ident: $type:ty)* $(,)?) $(-> $ret:ty)?;)+) => { - $( - pub fn $method(self $(,$arg: $type)*) $(-> $ret)? { - match self.implementation.$method($($arg),*) { - Ok(v) => Ok(v), - Err(e) => { - error!("Error in {}: {}", stringify!($method), e); - Err(e) - } - } - } - )+ - }; -} - -macro_rules! delegate_enum_bare { - ($(pub fn $method:ident(&self $(,$arg:ident: $type:ty)* $(,)?) $(-> $ret:ty)?;)+) => { - $( - #[must_use] pub fn $method(&self $(,$arg: $type)*) $(-> $ret)? { - self.implementation.$method($($arg),*) - } - )+ - }; - ($(pub fn $method:ident(&mut self $(,$arg:ident: $type:ty)* $(,)?) $(-> $ret:ty)?;)+) => { - $( - pub fn $method(&mut self $(,$arg: $type)*) $(-> $ret)? { - self.implementation.$method($($arg),*) - } - )+ - }; -} - /// Abstraction of cryptographic providers. /// /// [Provider] abstracts hardware, software and network based keystores. @@ -105,52 +32,74 @@ pub struct Provider { } impl Provider { - delegate_enum! { - pub fn create_key(&mut self, spec: KeySpec) -> Result; + /// Creates a new symmetric key. + pub fn create_key(&mut self, spec: KeySpec) -> Result { + self.implementation + .create_key(spec) + .inspect_err(|error| tracing::error!(error = %error, "Failed to create key")) } - delegate_enum! { - pub fn load_key(&mut self, id: String) -> Result; + /// Loads an existing symmetric key identified by `key_id`. + pub fn load_key(&mut self, id: String) -> Result { + self.implementation + .load_key(id) + .inspect_err(|error| tracing::error!(error = %error, "Failed to load key")) } - delegate_enum! { - pub fn import_key( - &mut self, - spec: KeySpec, - data: &[u8], - ) -> Result; + /// Imports a symmetric key from raw data. + pub fn import_key(&mut self, spec: KeySpec, data: &[u8]) -> Result { + self.implementation + .import_key(spec, data) + .inspect_err(|error| tracing::error!(error = %error, "Failed to import key")) } - delegate_enum! { - pub fn create_key_pair(&mut self, spec: KeyPairSpec) -> Result; + /// Creates a new asymmetric key pair. + pub fn create_key_pair(&mut self, spec: KeyPairSpec) -> Result { + self.implementation + .create_key_pair(spec) + .inspect_err(|error| tracing::error!(error = %error, "Failed to create key pair")) } - delegate_enum! { - pub fn load_key_pair(&mut self, id: String) -> Result; + /// Loads an existing asymmetric keypair identified by `key_id`. + pub fn load_key_pair(&mut self, id: String) -> Result { + self.implementation + .load_key_pair(id) + .inspect_err(|error| tracing::error!(error = %error, "Failed to load key pair")) } - delegate_enum! { - pub fn import_key_pair( - &mut self, - spec: KeyPairSpec, - public_key: &[u8], - private_key: &[u8], - ) -> Result; + /// Imports an asymmetric key pair from raw data. + pub fn import_key_pair( + &mut self, + spec: KeyPairSpec, + public_key: &[u8], + private_key: &[u8], + ) -> Result { + self.implementation + .import_key_pair(spec, public_key, private_key) + .inspect_err(|error| tracing::error!(error = %error, "Failed to import key pair")) } - delegate_enum! { - pub fn import_public_key( - &mut self, - spec: KeyPairSpec, - public_key: &[u8], - ) -> Result; + /// Imports a public key only. + pub fn import_public_key( + &mut self, + spec: KeyPairSpec, + public_key: &[u8], + ) -> Result { + self.implementation + .import_public_key(spec, public_key) + .inspect_err(|error| tracing::error!(error = %error, "Failed to import public key")) } - delegate_enum! { - pub fn start_ephemeral_dh_exchange( - &mut self, - spec: KeyPairSpec, - ) -> Result; + /// Generates a key pair suited for a Diffie-Hellman Key Exchange. + pub fn start_ephemeral_dh_exchange( + &mut self, + spec: KeyPairSpec, + ) -> Result { + self.implementation + .start_ephemeral_dh_exchange(spec) + .inspect_err( + |error| tracing::error!(error = %error, "Failed to start ephemeral DH exchange"), + ) } #[deprecated(note = "Non ephemeral dh exchanges are possibly insecure.")] @@ -165,26 +114,38 @@ impl Provider { .dh_exchange_from_keys(public_key, private_key, spec) } - delegate_enum! { - pub fn get_all_keys(&self) -> Result, CalError>; + /// Returns all keys stored in this provider. + pub fn get_all_keys(&self) -> Result, CalError> { + self.implementation + .get_all_keys() + .inspect_err(|error| tracing::error!(error = %error, "Failed to get all keys")) } - delegate_enum_bare! { - pub fn provider_name(&self) -> String; + /// Returns the name of this provider. + #[must_use] + pub fn provider_name(&self) -> String { + self.implementation.provider_name() } - delegate_enum_bare! { - pub fn get_capabilities(&self) -> Option; + /// Returns the capabilities of this provider. + #[must_use] + pub fn get_capabilities(&self) -> Option { + self.implementation.get_capabilities() } - delegate_enum! { - pub fn derive_key_from_password( - &self, - password: &str, - salt: &[u8], - algorithm: KeySpec, - kdf: KDF, - ) -> Result; + /// Derives a high-entropy key from a low-entropy password and a unique salt. + pub fn derive_key_from_password( + &self, + password: &str, + salt: &[u8], + algorithm: KeySpec, + kdf: KDF, + ) -> Result { + self.implementation + .derive_key_from_password(password, salt, algorithm, kdf) + .inspect_err( + |error| tracing::error!(error = %error, "Failed to derive key from password"), + ) } #[deprecated( @@ -201,12 +162,17 @@ impl Provider { .derive_key_from_base(base_key, key_id, context, spec) } - delegate_enum_bare! { - pub fn get_random(&self, len: usize) -> Vec; + /// Generates random bytes. + #[must_use] + pub fn get_random(&self, len: usize) -> Vec { + self.implementation.get_random(len) } - delegate_enum! { - pub fn hash(&self, input: &[u8], hash: CryptoHash) -> Result, CalError> ; + /// Hashes the input using the specified hash algorithm. + pub fn hash(&self, input: &[u8], hash: CryptoHash) -> Result, CalError> { + self.implementation + .hash(input, hash) + .inspect_err(|error| tracing::error!(error = %error, "Failed to hash input")) } } @@ -219,32 +185,49 @@ pub struct KeyPairHandle { /// Abstraction of asymmetric key pair handles. impl KeyPairHandle { - delegate_enum! { - pub fn encrypt_data(&self, data: &[u8]) -> Result, CalError>; + /// Encrypts the given data using the cryptographic key. + pub fn encrypt_data(&self, data: &[u8]) -> Result, CalError> { + self.implementation.encrypt_data(data).inspect_err( + |error| tracing::error!(error = %error, "Failed to encrypt data with key pair"), + ) } - delegate_enum! { - pub fn decrypt_data(&self, data: &[u8]) -> Result, CalError>; + /// Decrypts the given encrypted data using the cryptographic key. + pub fn decrypt_data(&self, data: &[u8]) -> Result, CalError> { + self.implementation.decrypt_data(data).inspect_err( + |error| tracing::error!(error = %error, "Failed to decrypt data with key pair"), + ) } - delegate_enum! { - pub fn sign_data(&self, data: &[u8]) -> Result, CalError>; + /// Signs the given data using the cryptographic key. + pub fn sign_data(&self, data: &[u8]) -> Result, CalError> { + self.implementation + .sign_data(data) + .inspect_err(|error| tracing::error!(error = %error, "Failed to sign data")) } - delegate_enum! { - pub fn verify_signature( - &self, - data: &[u8], - signature: &[u8], - ) -> Result; + /// Verifies the signature of the given data using the cryptographic key. + pub fn verify_signature(&self, data: &[u8], signature: &[u8]) -> Result { + self.implementation + .verify_signature(data, signature) + .inspect_err(|error| tracing::error!(error = %error, "Failed to verify signature")) } - delegate_enum! { - pub fn get_public_key(&self) -> Result, CalError>; + /// Returns the raw public key as binary. + pub fn get_public_key(&self) -> Result, CalError> { + self.implementation + .get_public_key() + .inspect_err(|error| tracing::error!(error = %error, "Failed to get public key")) } - delegate_enum! { - pub fn extract_key(&self) -> Result, CalError>; + /// Returns the raw private key as binary. + /// + /// Most hardware based providers will return [CalError] + /// with [CalErrorKind::NotImplemented](super::CalErrorKind::NotImplemented). + pub fn extract_key(&self) -> Result, CalError> { + self.implementation + .extract_key() + .inspect_err(|error| tracing::error!(error = %error, "Failed to extract private key")) } #[deprecated(note = "Non ephemeral dh exchanges are possibly insecure.")] @@ -253,16 +236,24 @@ impl KeyPairHandle { self.implementation.start_dh_exchange() } - delegate_enum! { - pub fn id(&self) -> Result; + /// Returns the id of the key pair, which can be used with `load_key_pair`. + pub fn id(&self) -> Result { + self.implementation + .id() + .inspect_err(|error| tracing::error!(error = %error, "Failed to get key pair ID")) } - delegate_enum! { - pub fn delete(self) -> Result<(), CalError>; + /// Delete this key pair. + pub fn delete(self) -> Result<(), CalError> { + self.implementation + .delete() + .inspect_err(|error| tracing::error!(error = %error, "Failed to delete key pair")) } - delegate_enum_bare! { - pub fn spec(&self) -> KeyPairSpec; + /// Returns the [KeyPairSpec] the key was generated with. + #[must_use] + pub fn spec(&self) -> KeyPairSpec { + self.implementation.spec() } } @@ -274,8 +265,14 @@ pub struct KeyHandle { } impl KeyHandle { - delegate_enum! { - pub fn extract_key(&self) -> Result, CalError>; + /// Returns the raw key as binary. + /// + /// Most hardware based providers will return [CalError] + /// with [CalErrorKind::NotImplemented](super::CalErrorKind::NotImplemented). + pub fn extract_key(&self) -> Result, CalError> { + self.implementation + .extract_key() + .inspect_err(|error| tracing::error!(error = %error, "Failed to extract key")) } #[deprecated( @@ -285,43 +282,76 @@ impl KeyHandle { self.implementation.encrypt_data(data, iv) } - delegate_enum! { - pub fn encrypt(&self, data: &[u8]) -> Result<(Vec, Vec), CalError>; + /// Encrypt data. + /// + /// The iv is randomly generated. + /// + /// The resulting output is a pair of cipher text and generated iv: `(cipher_text, iv)` + pub fn encrypt(&self, data: &[u8]) -> Result<(Vec, Vec), CalError> { + self.implementation + .encrypt(data) + .inspect_err(|error| tracing::error!(error = %error, "Failed to encrypt data")) } - delegate_enum! { - pub fn encrypt_with_iv(&self, data: &[u8], iv: &[u8]) -> Result, CalError>; + /// Encrypt data with the given iv. + /// + /// Some providers panic, if the iv is not the correct length. + pub fn encrypt_with_iv(&self, data: &[u8], iv: &[u8]) -> Result, CalError> { + self.implementation + .encrypt_with_iv(data, iv) + .inspect_err(|error| tracing::error!(error = %error, "Failed to encrypt data with IV")) } - delegate_enum! { - pub fn decrypt_data( - &self, - encrypted_data: &[u8], - iv: &[u8], - ) -> Result, CalError>; + /// Decrypts the given encrypted data using the cryptographic key. + pub fn decrypt_data(&self, encrypted_data: &[u8], iv: &[u8]) -> Result, CalError> { + self.implementation + .decrypt_data(encrypted_data, iv) + .inspect_err(|error| tracing::error!(error = %error, "Failed to decrypt data")) } - delegate_enum! { - pub fn hmac(&self, data: &[u8]) -> Result, CalError>; + /// Calculates HMAC of the given data. + pub fn hmac(&self, data: &[u8]) -> Result, CalError> { + self.implementation + .hmac(data) + .inspect_err(|error| tracing::error!(error = %error, "Failed to calculate HMAC")) } - delegate_enum! { - pub fn verify_hmac(&self, data: &[u8], hmac: &[u8]) -> Result; + + /// Verifies data with the given signature. + pub fn verify_hmac(&self, data: &[u8], hmac: &[u8]) -> Result { + self.implementation + .verify_hmac(data, hmac) + .inspect_err(|error| tracing::error!(error = %error, "Failed to verify HMAC")) } - delegate_enum! { - pub fn derive_key(&self, nonce: &[u8]) -> Result; + /// Derives an ephemeral key from this key as base with the same spec as the base key. + /// + /// A derived key is exportable if the base key (self) is exportable. + /// + /// This operation is deterministic, meaning the same nonce and key are always going to result in the same [KeyHandle]. + pub fn derive_key(&self, nonce: &[u8]) -> Result { + self.implementation + .derive_key(nonce) + .inspect_err(|error| tracing::error!(error = %error, "Failed to derive key")) } - delegate_enum! { - pub fn id(&self) -> Result; + /// Returns the id of the key, which can be used with `load_key`. + pub fn id(&self) -> Result { + self.implementation + .id() + .inspect_err(|error| tracing::error!(error = %error, "Failed to get key ID")) } - delegate_enum! { - pub fn delete(self) -> Result<(), CalError>; + /// Delete this key. + pub fn delete(self) -> Result<(), CalError> { + self.implementation + .delete() + .inspect_err(|error| tracing::error!(error = %error, "Failed to delete key")) } - delegate_enum_bare! { - pub fn spec(&self) -> KeySpec; + /// Returns the [KeySpec] the key was generated with. + #[must_use] + pub fn spec(&self) -> KeySpec { + self.implementation.spec() } } @@ -334,40 +364,66 @@ pub struct DHExchange { } impl DHExchange { - delegate_enum! { - pub fn id(&self) -> Result; + /// Returns the id of the key pair, which can be used with `load_key_pair`. + pub fn id(&self) -> Result { + self.implementation + .id() + .inspect_err(|error| tracing::error!(error = %error, "Failed to get DH exchange ID")) } - delegate_enum! { - pub fn get_public_key(&self) -> Result, CalError>; + /// Get the public key of the internal key pair to use for the other party. + pub fn get_public_key(&self) -> Result, CalError> { + self.implementation.get_public_key().inspect_err( + |error| tracing::error!(error = %error, "Failed to get DH exchange public key"), + ) } - delegate_enum! { - pub fn derive_client_session_keys( - &mut self, - server_pk: &[u8], - ) -> Result<(Vec, Vec), CalError>; + /// Derive client session keys (rx, tx) - client is the templator in your code. + pub fn derive_client_session_keys( + &mut self, + server_pk: &[u8], + ) -> Result<(Vec, Vec), CalError> { + self.implementation + .derive_client_session_keys(server_pk) + .inspect_err( + |error| tracing::error!(error = %error, "Failed to derive client session keys"), + ) } - delegate_enum! { - pub fn derive_server_session_keys( - &mut self, - client_pk: &[u8], - ) -> Result<(Vec, Vec), CalError>; + /// Derive server session keys (rx, tx) - server is the requestor in your code. + pub fn derive_server_session_keys( + &mut self, + client_pk: &[u8], + ) -> Result<(Vec, Vec), CalError> { + self.implementation + .derive_server_session_keys(client_pk) + .inspect_err( + |error| tracing::error!(error = %error, "Failed to derive server session keys"), + ) } - delegate_enum! { - pub fn derive_client_key_handles( - &mut self, - server_pk: &[u8], - ) -> Result<(KeyHandle, KeyHandle), CalError>; + /// Derives client session keys and returns them as key handles. + pub fn derive_client_key_handles( + &mut self, + server_pk: &[u8], + ) -> Result<(KeyHandle, KeyHandle), CalError> { + self.implementation + .derive_client_key_handles(server_pk) + .inspect_err( + |error| tracing::error!(error = %error, "Failed to derive client key handles"), + ) } - delegate_enum! { - pub fn derive_server_key_handles( - &mut self, - client_pk: &[u8], - ) -> Result<(KeyHandle, KeyHandle), CalError>; + /// Derives server session keys and returns them as key handles. + pub fn derive_server_key_handles( + &mut self, + client_pk: &[u8], + ) -> Result<(KeyHandle, KeyHandle), CalError> { + self.implementation + .derive_server_key_handles(client_pk) + .inspect_err( + |error| tracing::error!(error = %error, "Failed to derive server key handles"), + ) } } From 5c321896fed05945b56c3e1fc04d4024b025d3c1 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 21:22:01 +0200 Subject: [PATCH 15/20] docs: updated ts-types for the reworked docs --- ts-types/generated/AdditionalConfig.ts | 3 +- ts-types/generated/Argon2Options.ts | 4 +- ts-types/generated/AsymmetricKeySpec.ts | 1 - ts-types/generated/CalError.ts | 11 ++- ts-types/generated/CalErrorKind.ts | 3 +- ts-types/generated/Cipher.ts | 1 - ts-types/generated/CryptoHash.ts | 1 - ts-types/generated/KDF.ts | 1 - ts-types/generated/KeyPairSpec.ts | 4 +- ts-types/generated/KeySpec.ts | 8 +- ts-types/generated/ProviderConfig.ts | 94 +++++++++++++++++++++++- ts-types/generated/ProviderImplConfig.ts | 28 ++++--- ts-types/generated/SecurityLevel.ts | 2 +- ts-types/generated/Spec.ts | 3 - ts-types/package-lock.json | 29 +++++--- ts-types/package.json | 2 +- 16 files changed, 149 insertions(+), 46 deletions(-) diff --git a/ts-types/generated/AdditionalConfig.ts b/ts-types/generated/AdditionalConfig.ts index c53eb633..cdb86e3b 100644 --- a/ts-types/generated/AdditionalConfig.ts +++ b/ts-types/generated/AdditionalConfig.ts @@ -3,8 +3,7 @@ import type { KeyHandle } from "./KeyHandle"; import type { KeyPairHandle } from "./KeyPairHandle"; /** - * Configuration needed for using or initializing providers. - * flutter_rust_bridge:non_opaque + * Key metadata store configuration enumeration. */ export type AdditionalConfig = | { diff --git a/ts-types/generated/Argon2Options.ts b/ts-types/generated/Argon2Options.ts index a940d049..a0a12bc6 100644 --- a/ts-types/generated/Argon2Options.ts +++ b/ts-types/generated/Argon2Options.ts @@ -1,7 +1,9 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. /** - * flutter_rust_bridge:non_opaque + * Configuration for KDF with Argon2 + * + * When in doubt use the default. */ export type Argon2Options = { /** diff --git a/ts-types/generated/AsymmetricKeySpec.ts b/ts-types/generated/AsymmetricKeySpec.ts index ddfd4569..07308091 100644 --- a/ts-types/generated/AsymmetricKeySpec.ts +++ b/ts-types/generated/AsymmetricKeySpec.ts @@ -12,7 +12,6 @@ * * This enum uses `#[repr(C)]` to ensure that it has the same memory layout as a C enum, * facilitating interfacing with C code or when ABI compatibility is required. - * flutter_rust_bridge:non_opaque */ export type AsymmetricKeySpec = | "RSA1024" diff --git a/ts-types/generated/CalError.ts b/ts-types/generated/CalError.ts index ea15f861..6a498a3c 100644 --- a/ts-types/generated/CalError.ts +++ b/ts-types/generated/CalError.ts @@ -2,12 +2,11 @@ import type { CalErrorKind } from "./CalErrorKind"; /** - * Error wrapping native errors. + * Crypto-layer error representation. * - * The native libraries used large lists of errors that might occur. - * This struct exists to dumb down said errors. - * The provider implementation should map errors from native libraries to this enum. - * Most if not all errors should have a source for backtraces. - * If other fields are useful for understanding the error, they should also exist. + * Every provider is built for a different native backend or purpose in mind. + * Moreover crypto-layer must be ffi compatible. + * For these reasons this error is not an enum, but rather a struct containing a non nested enum + * and a source, that does not need to be parsed by ffi. */ export type CalError = { error_kind: CalErrorKind }; diff --git a/ts-types/generated/CalErrorKind.ts b/ts-types/generated/CalErrorKind.ts index 01b701d8..30334c93 100644 --- a/ts-types/generated/CalErrorKind.ts +++ b/ts-types/generated/CalErrorKind.ts @@ -2,8 +2,7 @@ import type { KeyType } from "./KeyType"; /** - * Enumeration differentiating between the causes and the severity of the error. - * flutter_rust_bridge:non_opaque + * Enumeration of classifications of error sources. */ export type CalErrorKind = | "NotImplemented" diff --git a/ts-types/generated/Cipher.ts b/ts-types/generated/Cipher.ts index 1786f40b..6a48aa78 100644 --- a/ts-types/generated/Cipher.ts +++ b/ts-types/generated/Cipher.ts @@ -13,7 +13,6 @@ * * Marked with `#[repr(C)]` to ensure it has the same memory layout as a C enum, * facilitating ABI compatibility and interfacing with C code. - * flutter_rust_bridge:non_opaque */ export type Cipher = | "AesGcm128" diff --git a/ts-types/generated/CryptoHash.ts b/ts-types/generated/CryptoHash.ts index 408c9228..9ad5ce4c 100644 --- a/ts-types/generated/CryptoHash.ts +++ b/ts-types/generated/CryptoHash.ts @@ -10,7 +10,6 @@ * Algorithms like SHA-1, MD2, MD4, and MD5 are considered insecure for most cryptographic * purposes due to practical collision attacks and should be avoided for new applications. * Prefer using more secure algorithms like SHA-2 or SHA-3 for cryptographic purposes. - * flutter_rust_bridge:non_opaque */ export type CryptoHash = | "Sha2_224" diff --git a/ts-types/generated/KDF.ts b/ts-types/generated/KDF.ts index 8ed070c0..d3182662 100644 --- a/ts-types/generated/KDF.ts +++ b/ts-types/generated/KDF.ts @@ -27,7 +27,6 @@ import type { Argon2Options } from "./Argon2Options"; * parallelism: 1, * }); * ``` - * flutter_rust_bridge:non_opaque */ export type KDF = | { "Argon2d": Argon2Options } diff --git a/ts-types/generated/KeyPairSpec.ts b/ts-types/generated/KeyPairSpec.ts index a59843ee..1c270864 100644 --- a/ts-types/generated/KeyPairSpec.ts +++ b/ts-types/generated/KeyPairSpec.ts @@ -5,7 +5,9 @@ import type { CryptoHash } from "./CryptoHash"; /** * Struct used to configure key pairs. - * flutter_rust_bridge:non_opaque + * + * It is important to note, that the configuration of a key can only happen at the point of its creation. + * A key cannot be reconfigured. */ export type KeyPairSpec = { /** diff --git a/ts-types/generated/KeySpec.ts b/ts-types/generated/KeySpec.ts index 9ac8f86c..36d254c6 100644 --- a/ts-types/generated/KeySpec.ts +++ b/ts-types/generated/KeySpec.ts @@ -4,7 +4,9 @@ import type { CryptoHash } from "./CryptoHash"; /** * Struct used to configure keys. - * flutter_rust_bridge:non_opaque + * + * It is important to note, that the configuration of a key can only happen at the point of its creation. + * A key cannot be reconfigured. */ export type KeySpec = { /** @@ -16,11 +18,13 @@ export type KeySpec = { */ signing_hash: CryptoHash; /** - * If set to `true`, the key is going to be deleted when the handle is dropped. + * If set to `true`, metadata of the key is not stored and the key is going to be deleted when the handle is dropped. */ ephemeral: boolean; /** * If set to `true`, the key cannot be exported. + * + * Some providers do not allow exporting keys at all, even if set to `false`. */ non_exportable: boolean; }; diff --git a/ts-types/generated/ProviderConfig.ts b/ts-types/generated/ProviderConfig.ts index 7f72b25d..a11fd70e 100644 --- a/ts-types/generated/ProviderConfig.ts +++ b/ts-types/generated/ProviderConfig.ts @@ -6,12 +6,104 @@ import type { SecurityLevel } from "./SecurityLevel"; /** * Capabilities of a Provider - * flutter_rust_bridge:non_opaque + * + * This configuration struct has multiple uses: + * * Act as capabilities of a provider. + * * Act as requirement for [`create_provider`](crate::prelude::create_provider). + * + * Depending on the use some properties have different meanings: + * * Currently a provider may only have one security level. + * * The requester may ask for a provider that has at a minimum one security level or at a maximum another security level. + * * A provider has certain algorithm he at least in some form supports. + * * A requester may ask for minimum requirements regarding these algorithms. + * + * ### Example + * + * A provider might return capabilities like: + * ``` + * # use crypto_layer::prelude::*; + * # use std::collections::HashSet; + * + * let apple_provider_capabilities = ProviderConfig { + * max_security_level: SecurityLevel::Hardware, + * min_security_level: SecurityLevel::Hardware, + * supported_ciphers: HashSet::from([Cipher::AesGcm128, Cipher::AesGcm256]), + * supported_asym_spec: HashSet::from([AsymmetricKeySpec::P256]), + * supported_hashes: HashSet::from([ + * CryptoHash::Sha2_224, + * CryptoHash::Sha2_256, + * CryptoHash::Sha2_384, + * CryptoHash::Sha2_512, + * ]), + * }; + * + * ``` + * Such provider then is ought to use a secure element (apart from the `ANDROID_PROVIDER`) + * and at least support these algorithms **in one form or another** . + * + * Please be aware, that `supported_ciphers` does not imply support for symmetric cryptography! + * + * A requestor might ask for a provider with capabilities like: + * ``` + * # use crypto_layer::prelude::*; + * # use std::collections::HashSet; + * + * let requested_capabilities = ProviderConfig { + * max_security_level: SecurityLevel::Hardware, + * min_security_level: SecurityLevel::Software, + * supported_ciphers: HashSet::from([Cipher::AesGcm256]), + * supported_asym_spec: HashSet::from([AsymmetricKeySpec::P256]), + * supported_hashes: HashSet::from([ + * CryptoHash::Sha2_256, + * CryptoHash::Sha2_512, + * ]), + * }; + * ``` + * + * As the requested capabilities are a subset of the provided capabilities above, + * this requestor might be assigned the apple secure enclave provider on apple platforms. */ export type ProviderConfig = { + /** + * Highest security supported or maximum security requested. + * + * As an example, the software fallback provider has a maximum security level of [`SecurityLevel::Software`]. + */ max_security_level: SecurityLevel; + /** + * Minimum security level supported or security level required. + * + * As an example: + * If one wishes to use provider that is based on a secure element, one would require [`SecurityLevel::Hardware`]. + */ min_security_level: SecurityLevel; + /** + * Cipher algorithms supported in one fashion or another or cipher algorithms required. + * + * A provider might support cipher algorithms returned as capabilities in following ways: + * * Supports symmetric encryption with said cipher. + * * Supports asymmetric hybrid encryption with said cipher. (What standard is used for the hybrid encryption is not set.) + */ supported_ciphers: Array; + /** + * Hashing algorithm supported for either the use with signing (symmetric or asymmetric) operations or encryption operations (symmetric or asymmetric), + * or hashing algorithm required for the same purpose. + * + * A provider that supports a hash algorithm **may or may not** support following operations in combination with said hashing algorithm: + * * [`KeyHandle::hmac()`](crate::prelude::KeyHandle::hmac) + * * [`KeyHandle::verify_hmac()`](crate::prelude::KeyHandle::verify_hmac) + * * [`KeyHandle::encrypt()`](crate::prelude::KeyHandle::encrypt()) + * * [`KeyHandle::decrypt_data()`](crate::prelude::KeyHandle::decrypt_data()) + * * [`KeyPairHandle::sign_data`](crate::prelude::KeyPairHandle::sign_data) + * * [`KeyPairHandle::verify_signature`](crate::prelude::KeyPairHandle::verify_signature) + * * [`KeyPairHandle::encrypt_data()`](crate::prelude::KeyPairHandle::encrypt_data) + * * [`KeyPairHandle::decrypt_data()`](crate::prelude::KeyPairHandle::decrypt_data) + */ supported_hashes: Array; + /** + * Asymmetric cryptographic algorithms supported or required. + * + * A provider supporting an asymmetric cryptographic algorithm **may or may not** support said algorithm for signing or encryption operations. + */ supported_asym_spec: Array; }; diff --git a/ts-types/generated/ProviderImplConfig.ts b/ts-types/generated/ProviderImplConfig.ts index af516a45..604d22bb 100644 --- a/ts-types/generated/ProviderImplConfig.ts +++ b/ts-types/generated/ProviderImplConfig.ts @@ -2,23 +2,27 @@ import type { AdditionalConfig } from "./AdditionalConfig"; /** - * Configuration needed for using or initializing providers. + * Key metadata store configuration * - * Either - * * [AdditionalConfig::KVStoreConfig] - * * [AdditionalConfig::FileStoreConfig] + * Due to an accident, this configuration became a vector. * - * and either - * * [AdditionalConfig::StorageConfigHMAC] - * * [AdditionalConfig::StorageConfigDSA] - * * [AdditionalConfig::StorageConfigPass] + * If neither [`AdditionalConfig::KVStoreConfig`] nor [`AdditionalConfig::FileStoreConfig`] are supplied + * to [`create_provider()`] or to [`create_provider_from_name()`], + * a provider will be created that is only capable of creating ephemeral keys! * - * need to be supplied. + * To protect key metadata against unauthorized change, it is recommended to make use of + * [`AdditionalConfig::StorageConfigHMAC`] or [`AdditionalConfig::StorageConfigDSA`]. + * (This may only apply if you use multiple providers and one is of [`SecurityLevel::Hardware`] or above.) + * + * If the fallback software provider is used with [AdditionalConfig::StorageConfigSymmetricEncryption] + * or [AdditionalConfig::StorageConfigAsymmetricEncryption], the stored secret keys are secured by + * the provided key, which in turn makes such construct a hybrid provider (as the keys at rest have hardware security protection). * * ## Example * * ```rust - * use crypto_layer::prelude::*; + * # use crypto_layer::prelude::*; + * * let implementation_config = ProviderImplConfig { * additional_config: vec![ * AdditionalConfig::FileStoreConfig { @@ -27,6 +31,8 @@ import type { AdditionalConfig } from "./AdditionalConfig"; * ], * }; * ``` - * flutter_rust_bridge:non_opaque + * + * [`create_provider()`]: crate::prelude::create_provider + * [`create_provider_from_name()`]: crate::prelude::create_provider_from_name */ export type ProviderImplConfig = { additional_config: Array }; diff --git a/ts-types/generated/SecurityLevel.ts b/ts-types/generated/SecurityLevel.ts index 66ff75c7..5f46afd6 100644 --- a/ts-types/generated/SecurityLevel.ts +++ b/ts-types/generated/SecurityLevel.ts @@ -5,7 +5,7 @@ * * * [SecurityLevel::Hardware]: Provider is hardware backed (tpm, other security chips, StrongBox KeyStore). * * [SecurityLevel::Software]: Provider uses the systems software keystore. - * * [SecurityLevel::Network]: Provider uses a network key store (Hashicorp). + * * [SecurityLevel::Network]: Provider uses a network key store (HashiCorp). * * [SecurityLevel::Unsafe]: Provider uses software fallback. */ export type SecurityLevel = "Hardware" | "Software" | "Network" | "Unsafe"; diff --git a/ts-types/generated/Spec.ts b/ts-types/generated/Spec.ts index 9fa10814..7cd3ce62 100644 --- a/ts-types/generated/Spec.ts +++ b/ts-types/generated/Spec.ts @@ -2,7 +2,4 @@ import type { KeyPairSpec } from "./KeyPairSpec"; import type { KeySpec } from "./KeySpec"; -/** - * flutter_rust_bridge:non_opaque - */ export type Spec = { "KeySpec": KeySpec } | { "KeyPairSpec": KeyPairSpec }; diff --git a/ts-types/package-lock.json b/ts-types/package-lock.json index 99e38a43..c2acde2b 100644 --- a/ts-types/package-lock.json +++ b/ts-types/package-lock.json @@ -1,12 +1,12 @@ { "name": "@nmshd/rs-crypto-types", - "version": "0.12.1", + "version": "0.12.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@nmshd/rs-crypto-types", - "version": "0.12.1", + "version": "0.12.2", "license": "MIT", "dependencies": { "typia": "^8.0.3" @@ -183,9 +183,9 @@ } }, "node_modules/@inquirer/external-editor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.0.tgz", - "integrity": "sha512-5v3YXc5ZMfL6OJqXPrX9csb4l7NlQA2doO1yynUjpUChT9hg4JcuBVP0RbsEJ/3SL/sxWEyFjT2W69ZhtoBWqg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz", + "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==", "license": "MIT", "dependencies": { "chardet": "^2.1.0", @@ -196,6 +196,11 @@ }, "peerDependencies": { "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/@samchon/openapi": { @@ -205,9 +210,10 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.17.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.1.tgz", - "integrity": "sha512-y3tBaz+rjspDTylNjAX37jEC3TETEFGNJL6uQDxwF9/8GLLIjW1rvVHlynyuUKMnMr1Roq8jOv3vkopBjC4/VA==", + "version": "22.17.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.17.2.tgz", + "integrity": "sha512-gL6z5N9Jm9mhY+U2KXZpteb+09zyffliRkZyZOHODGATyC5B1Jt/7TzuuiLkFsSUMLbS1OLmlj/E+/3KF4Q/4w==", + "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -788,9 +794,9 @@ "license": "MIT" }, "node_modules/quansync": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.10.tgz", - "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", "funding": [ { "type": "individual", @@ -1086,6 +1092,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "devOptional": true, "license": "MIT" }, "node_modules/util-deprecate": { diff --git a/ts-types/package.json b/ts-types/package.json index e595f8d2..0cc694e0 100644 --- a/ts-types/package.json +++ b/ts-types/package.json @@ -1,6 +1,6 @@ { "name": "@nmshd/rs-crypto-types", - "version": "0.12.1", + "version": "0.12.2", "description": "Crypto Layer TS type definitions.", "homepage": "https://enmeshed.eu", "repository": "github:nmshd/rust-crypto", From b7000577dab454794f8d4823e3630f7fbef5ca2a Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 21:24:41 +0200 Subject: [PATCH 16/20] docs: fixed usage of ts-types --- ts-types/README.md | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/ts-types/README.md b/ts-types/README.md index c0300ad8..e551282f 100644 --- a/ts-types/README.md +++ b/ts-types/README.md @@ -2,7 +2,20 @@ [![NPM Version](https://img.shields.io/npm/v/%40nmshd%2Frs-crypto-types)](https://www.npmjs.com/package/@nmshd/rs-crypto-types) -This is an npm package with the ts type defintions of the CAL project. +This is an npm package with the ts type definitions of the CAL project. + +## Usage + +Add the npm package as dependency: +```sh +npm add --save @nmshd/rs-crypto-types +``` + +Import the types + +```ts +import { type EccCurve } from "crypto-layer-ts-types"; +``` ## Build Package @@ -11,10 +24,15 @@ This is an npm package with the ts type defintions of the CAL project. ### Generate the Types -``` +```pwsh .\Generate-Types.ps1 ``` +Or if you have [task](https://taskfile.dev/) installed, run: +```sh +task gents testts +``` + ### Build the Package ``` @@ -22,16 +40,3 @@ npm i npm run build ``` -## Usage - -Add the npm package as dependecy - -``` -npm add --save ./PathToLib/rust-crypto/ts-types/ -``` - -Import the types - -```ts -import { type EccCurve } from "crypto-layer-ts-types"; -``` From a3c1b7d8bfe4cbe8306d4fd8788378196728f80d Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 21:33:30 +0200 Subject: [PATCH 17/20] docs: moved ts-types dev docs into separate file and added section on how to release a new version --- ts-types/DEVELOPMENT.md | 34 ++++++++++++++++++++++++++++++++++ ts-types/README.md | 23 ++--------------------- 2 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 ts-types/DEVELOPMENT.md diff --git a/ts-types/DEVELOPMENT.md b/ts-types/DEVELOPMENT.md new file mode 100644 index 00000000..9e9224b2 --- /dev/null +++ b/ts-types/DEVELOPMENT.md @@ -0,0 +1,34 @@ +# Crypto-Layer TS Type Definitions Development Documentation + +## Build Package + +1. You need to have rust installed. +2. You need to have npm or similar installed. + +### Generate the Types + +```pwsh +.\Generate-Types.ps1 +``` + +Or if you have [task](https://taskfile.dev/) installed, run: +```sh +task gents testts +``` + +### Build the Package + +``` +npm i +npm run build +``` + +## Creating a New Release + +* Update the version in [`package.json`](./package.json). +* Update `package-lock.json` by calling + ```sh + npm update + ``` +* Merge your changes onto `main` branch. +* Call the `Release` (`release.yml`) GitHub action. The action should publish the new version of the package. diff --git a/ts-types/README.md b/ts-types/README.md index e551282f..00658e73 100644 --- a/ts-types/README.md +++ b/ts-types/README.md @@ -17,26 +17,7 @@ Import the types import { type EccCurve } from "crypto-layer-ts-types"; ``` -## Build Package +## Development Documentation -1. You need to have rust installed. -2. You need to have npm or similar installed. - -### Generate the Types - -```pwsh -.\Generate-Types.ps1 -``` - -Or if you have [task](https://taskfile.dev/) installed, run: -```sh -task gents testts -``` - -### Build the Package - -``` -npm i -npm run build -``` +See [`DEVELOPMENT.md`](./DEVELOPMENT.md). From f81495842869104929cf0a67802ed1cbbe8808a8 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 21:42:24 +0200 Subject: [PATCH 18/20] docs: added taskfile section --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index 739e3a8b..a0858645 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,32 @@ task build-documentation Contributions to the Crypto Layer are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the project's GitHub repository. +## Development + +### Taskfile + +Many of the necessary workflows are automated with [task](https://taskfile.dev/). +See the [Taskfile](./Taskfile.yml). + +Useful commands are: +```sh +# Test crypto layer with the software provider: +task testrs + +# Install TS and dart dependencies: +task pre + +# Generate ts types. +task gents tests + +# Generate dart bindings +task gendt testdt + +# Generate docs +task bdoc +``` + + ## License From c21991789753e3d17541afb29914c3e9bb2ee00b Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 22:07:37 +0200 Subject: [PATCH 19/20] reverted: flutter_rust_bridge to docstrings https://cjycode.com/flutter_rust_bridge/guides/custom/attributes/comments --- src/common/config.rs | 12 ++++++------ src/common/crypto/algorithms/encryption.rs | 4 ++-- src/common/crypto/algorithms/hashes.rs | 2 +- src/common/crypto/algorithms/key_derivation.rs | 4 ++-- src/common/error.rs | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/common/config.rs b/src/common/config.rs index 26a1bf93..b5926096 100644 --- a/src/common/config.rs +++ b/src/common/config.rs @@ -81,7 +81,7 @@ pub enum SecurityLevel { #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque pub enum Spec { KeySpec(KeySpec), KeyPairSpec(KeyPairSpec), @@ -93,7 +93,7 @@ pub enum Spec { /// A key cannot be reconfigured. #[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, Zeroize, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque pub struct KeySpec { /// Cipher used for symmetric encryption. pub cipher: Cipher, @@ -116,7 +116,7 @@ pub struct KeySpec { /// A key cannot be reconfigured. #[derive(Clone, Copy, Debug, Serialize, Deserialize, Default, PartialEq)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque pub struct KeyPairSpec { /// Asymmetric algorithm to be used. pub asym_spec: AsymmetricKeySpec, @@ -192,7 +192,7 @@ pub struct KeyPairSpec { /// As the requested capabilities are a subset of the provided capabilities above, /// this requestor might be assigned the apple secure enclave provider on apple platforms. /// -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[derive(Clone, Debug)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct ProviderConfig { @@ -268,7 +268,7 @@ pub struct ProviderConfig { /// [`create_provider()`]: crate::prelude::create_provider /// [`create_provider_from_name()`]: crate::prelude::create_provider_from_name /// -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[derive(Clone)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct ProviderImplConfig { @@ -276,7 +276,7 @@ pub struct ProviderImplConfig { } /// Key metadata store configuration enumeration. -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[derive(Clone, EnumDiscriminants)] #[strum_discriminants(derive(EnumString, IntoStaticStr))] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] diff --git a/src/common/crypto/algorithms/encryption.rs b/src/common/crypto/algorithms/encryption.rs index 2f67eb81..101b4bb2 100644 --- a/src/common/crypto/algorithms/encryption.rs +++ b/src/common/crypto/algorithms/encryption.rs @@ -16,7 +16,7 @@ use strum::{EnumString, IntoStaticStr}; /// /// This enum uses `#[repr(C)]` to ensure that it has the same memory layout as a C enum, /// facilitating interfacing with C code or when ABI compatibility is required. -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[repr(C)] #[derive( Clone, @@ -72,7 +72,7 @@ pub enum AsymmetricKeySpec { /// /// Marked with `#[repr(C)]` to ensure it has the same memory layout as a C enum, /// facilitating ABI compatibility and interfacing with C code. -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[repr(C)] #[derive( Clone, diff --git a/src/common/crypto/algorithms/hashes.rs b/src/common/crypto/algorithms/hashes.rs index 8be357d6..94d12b76 100644 --- a/src/common/crypto/algorithms/hashes.rs +++ b/src/common/crypto/algorithms/hashes.rs @@ -12,7 +12,7 @@ use zeroize::Zeroize; /// Algorithms like SHA-1, MD2, MD4, and MD5 are considered insecure for most cryptographic /// purposes due to practical collision attacks and should be avoided for new applications. /// Prefer using more secure algorithms like SHA-2 or SHA-3 for cryptographic purposes. -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[repr(C)] #[derive( Clone, diff --git a/src/common/crypto/algorithms/key_derivation.rs b/src/common/crypto/algorithms/key_derivation.rs index cdeaa3c2..825a0e96 100644 --- a/src/common/crypto/algorithms/key_derivation.rs +++ b/src/common/crypto/algorithms/key_derivation.rs @@ -25,7 +25,7 @@ use serde::{Deserialize, Serialize}; /// parallelism: 1, /// }); /// ``` -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[derive(Clone, Copy, Debug, Serialize, Deserialize)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub enum KDF { @@ -39,7 +39,7 @@ pub enum KDF { /// Configuration for KDF with Argon2 /// /// When in doubt use the default. -// flutter_rust_bridge:non_opaque +/// flutter_rust_bridge:non_opaque #[derive(Clone, Copy, Debug, Serialize, Deserialize)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] pub struct Argon2Options { diff --git a/src/common/error.rs b/src/common/error.rs index da124af9..1973a917 100644 --- a/src/common/error.rs +++ b/src/common/error.rs @@ -26,7 +26,7 @@ pub struct CalError { } /// Enumeration of classifications of error sources. -// flutter_rust_bridge:non_opaque +//// flutter_rust_bridge:non_opaque #[derive(thiserror::Error, Debug, Clone)] #[cfg_attr(feature = "ts-interface", derive(ts_rs::TS), ts(export))] #[repr(C)] From 60d9fca634f045e1e944a4cefc5801a9d8cf8a94 Mon Sep 17 00:00:00 2001 From: Adam McKellar Date: Thu, 21 Aug 2025 22:10:40 +0200 Subject: [PATCH 20/20] chore: generated dart bindings --- .../lib/src/rust/frb_generated.dart | 329 +++++----- .../lib/src/rust/frb_generated.io.dart | 94 ++- .../lib/src/rust/frb_generated.web.dart | 86 ++- .../rust/third_party/crypto_layer/common.dart | 56 +- .../crypto_layer/common/config.dart | 131 +++- .../common/crypto/algorithms/encryption.dart | 1 + .../crypto/algorithms/key_derivation.dart | 9 + .../crypto_layer/common/error.dart | 65 +- .../crypto_layer/common/error.freezed.dart | 583 ------------------ .../crypto_layer/common/factory.dart | 31 +- cal_flutter_plugin/rust/src/frb_generated.rs | 387 +++--------- 11 files changed, 592 insertions(+), 1180 deletions(-) delete mode 100644 cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.freezed.dart diff --git a/cal_flutter_plugin/lib/src/rust/frb_generated.dart b/cal_flutter_plugin/lib/src/rust/frb_generated.dart index 43645322..f5ffea50 100644 --- a/cal_flutter_plugin/lib/src/rust/frb_generated.dart +++ b/cal_flutter_plugin/lib/src/rust/frb_generated.dart @@ -412,6 +412,14 @@ abstract class RustLibApi extends BaseApi { CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_CalErrorPtr; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_CalErrorKind; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_CalErrorKind; + + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_CalErrorKindPtr; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DhExchange; @@ -507,7 +515,8 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); }, codec: SseCodec( - decodeSuccessData: sse_decode_cal_error_kind, + decodeSuccessData: + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind, decodeErrorData: null, ), constMeta: kCryptoLayerCommonErrorCalErrorErrorKindConstMeta, @@ -2944,6 +2953,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { get rust_arc_decrement_strong_count_CalError => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalError; + RustArcIncrementStrongCountFnType + get rust_arc_increment_strong_count_CalErrorKind => wire + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind; + + RustArcDecrementStrongCountFnType + get rust_arc_decrement_strong_count_CalErrorKind => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind; + RustArcIncrementStrongCountFnType get rust_arc_increment_strong_count_DhExchange => wire .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange; @@ -3035,6 +3052,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return CalErrorImpl.frbInternalDcoDecode(raw as List); } + @protected + CalErrorKind + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return CalErrorKindImpl.frbInternalDcoDecode(raw as List); + } + @protected DhExchange dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -3225,6 +3251,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return CalErrorImpl.frbInternalDcoDecode(raw as List); } + @protected + CalErrorKind + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + dynamic raw, + ) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return CalErrorKindImpl.frbInternalDcoDecode(raw as List); + } + @protected DhExchange dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -3425,50 +3460,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return dco_decode_provider_impl_config(raw); } - @protected - CalErrorKind dco_decode_cal_error_kind(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - switch (raw[0]) { - case 0: - return CalErrorKind_NotImplemented(); - case 1: - return CalErrorKind_BadParameter( - description: dco_decode_String(raw[1]), - internal: dco_decode_bool(raw[2]), - ); - case 2: - return CalErrorKind_MissingKey( - keyId: dco_decode_String(raw[1]), - keyType: dco_decode_key_type(raw[2]), - ); - case 3: - return CalErrorKind_MissingValue( - description: dco_decode_String(raw[1]), - internal: dco_decode_bool(raw[2]), - ); - case 4: - return CalErrorKind_FailedOperation( - description: dco_decode_String(raw[1]), - internal: dco_decode_bool(raw[2]), - ); - case 5: - return CalErrorKind_InitializationError( - description: dco_decode_String(raw[1]), - internal: dco_decode_bool(raw[2]), - ); - case 6: - return CalErrorKind_NonExportable(); - case 7: - return CalErrorKind_UnsupportedAlgorithm(dco_decode_String(raw[1])); - case 8: - return CalErrorKind_EphemeralKeyError(); - case 9: - return CalErrorKind_Other(); - default: - throw Exception("unreachable"); - } - } - @protected Cipher dco_decode_cipher(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3537,12 +3528,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - @protected - KeyType dco_decode_key_type(dynamic raw) { - // Codec=Dco (DartCObject based), see doc to use other codecs - return KeyType.values[raw as int]; - } - @protected List dco_decode_list_String(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -3845,6 +3830,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + CalErrorKind + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return CalErrorKindImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + @protected DhExchange sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -4044,6 +4041,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + CalErrorKind + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + SseDeserializer deserializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + return CalErrorKindImpl.frbInternalSseDecode( + sse_decode_usize(deserializer), + sse_decode_i_32(deserializer), + ); + } + @protected DhExchange sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -4274,60 +4283,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_provider_impl_config(deserializer)); } - @protected - CalErrorKind sse_decode_cal_error_kind(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - - var tag_ = sse_decode_i_32(deserializer); - switch (tag_) { - case 0: - return CalErrorKind_NotImplemented(); - case 1: - var var_description = sse_decode_String(deserializer); - var var_internal = sse_decode_bool(deserializer); - return CalErrorKind_BadParameter( - description: var_description, - internal: var_internal, - ); - case 2: - var var_keyId = sse_decode_String(deserializer); - var var_keyType = sse_decode_key_type(deserializer); - return CalErrorKind_MissingKey(keyId: var_keyId, keyType: var_keyType); - case 3: - var var_description = sse_decode_String(deserializer); - var var_internal = sse_decode_bool(deserializer); - return CalErrorKind_MissingValue( - description: var_description, - internal: var_internal, - ); - case 4: - var var_description = sse_decode_String(deserializer); - var var_internal = sse_decode_bool(deserializer); - return CalErrorKind_FailedOperation( - description: var_description, - internal: var_internal, - ); - case 5: - var var_description = sse_decode_String(deserializer); - var var_internal = sse_decode_bool(deserializer); - return CalErrorKind_InitializationError( - description: var_description, - internal: var_internal, - ); - case 6: - return CalErrorKind_NonExportable(); - case 7: - var var_field0 = sse_decode_String(deserializer); - return CalErrorKind_UnsupportedAlgorithm(var_field0); - case 8: - return CalErrorKind_EphemeralKeyError(); - case 9: - return CalErrorKind_Other(); - default: - throw UnimplementedError(''); - } - } - @protected Cipher sse_decode_cipher(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4406,13 +4361,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } - @protected - KeyType sse_decode_key_type(SseDeserializer deserializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - var inner = sse_decode_i_32(deserializer); - return KeyType.values[inner]; - } - @protected List sse_decode_list_String(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -4790,6 +4738,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + CalErrorKind self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as CalErrorKindImpl).frbInternalSseEncode(move: true), + serializer, + ); + } + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -5073,6 +5034,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); } + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + CalErrorKind self, + SseSerializer serializer, + ) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_usize( + (self as CalErrorKindImpl).frbInternalSseEncode(move: null), + serializer, + ); + } + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -5312,56 +5286,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_provider_impl_config(self, serializer); } - @protected - void sse_encode_cal_error_kind(CalErrorKind self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - switch (self) { - case CalErrorKind_NotImplemented(): - sse_encode_i_32(0, serializer); - case CalErrorKind_BadParameter( - description: final description, - internal: final internal, - ): - sse_encode_i_32(1, serializer); - sse_encode_String(description, serializer); - sse_encode_bool(internal, serializer); - case CalErrorKind_MissingKey(keyId: final keyId, keyType: final keyType): - sse_encode_i_32(2, serializer); - sse_encode_String(keyId, serializer); - sse_encode_key_type(keyType, serializer); - case CalErrorKind_MissingValue( - description: final description, - internal: final internal, - ): - sse_encode_i_32(3, serializer); - sse_encode_String(description, serializer); - sse_encode_bool(internal, serializer); - case CalErrorKind_FailedOperation( - description: final description, - internal: final internal, - ): - sse_encode_i_32(4, serializer); - sse_encode_String(description, serializer); - sse_encode_bool(internal, serializer); - case CalErrorKind_InitializationError( - description: final description, - internal: final internal, - ): - sse_encode_i_32(5, serializer); - sse_encode_String(description, serializer); - sse_encode_bool(internal, serializer); - case CalErrorKind_NonExportable(): - sse_encode_i_32(6, serializer); - case CalErrorKind_UnsupportedAlgorithm(field0: final field0): - sse_encode_i_32(7, serializer); - sse_encode_String(field0, serializer); - case CalErrorKind_EphemeralKeyError(): - sse_encode_i_32(8, serializer); - case CalErrorKind_Other(): - sse_encode_i_32(9, serializer); - } - } - @protected void sse_encode_cipher(Cipher self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5421,12 +5345,6 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_bool(self.nonExportable, serializer); } - @protected - void sse_encode_key_type(KeyType self, SseSerializer serializer) { - // Codec=Sse (Serialization based), see doc to use other codecs - sse_encode_i_32(self.index, serializer); - } - @protected void sse_encode_list_String(List self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -5854,6 +5772,26 @@ class CalErrorImpl extends RustOpaque implements CalError { RustLib.instance.api.cryptoLayerCommonErrorCalErrorErrorKind(that: this); } +@sealed +class CalErrorKindImpl extends RustOpaque implements CalErrorKind { + // Not to be used by end users + CalErrorKindImpl.frbInternalDcoDecode(List wire) + : super.frbInternalDcoDecode(wire, _kStaticData); + + // Not to be used by end users + CalErrorKindImpl.frbInternalSseDecode(BigInt ptr, int externalSizeOnNative) + : super.frbInternalSseDecode(ptr, externalSizeOnNative, _kStaticData); + + static final _kStaticData = RustArcStaticData( + rustArcIncrementStrongCount: + RustLib.instance.api.rust_arc_increment_strong_count_CalErrorKind, + rustArcDecrementStrongCount: + RustLib.instance.api.rust_arc_decrement_strong_count_CalErrorKind, + rustArcDecrementStrongCountPtr: + RustLib.instance.api.rust_arc_decrement_strong_count_CalErrorKindPtr, + ); +} + @sealed class DhExchangeImpl extends RustOpaque implements DhExchange { // Not to be used by end users @@ -5873,6 +5811,7 @@ class DhExchangeImpl extends RustOpaque implements DhExchange { RustLib.instance.api.rust_arc_decrement_strong_count_DhExchangePtr, ); + /// Derives client session keys and returns them as key handles. Future<(KeyHandle, KeyHandle)> deriveClientKeyHandles({ required List serverPk, }) => RustLib.instance.api.cryptoLayerCommonDhExchangeDeriveClientKeyHandles( @@ -5880,6 +5819,7 @@ class DhExchangeImpl extends RustOpaque implements DhExchange { serverPk: serverPk, ); + /// Derive client session keys (rx, tx) - client is the templator in your code. Future<(Uint8List, Uint8List)> deriveClientSessionKeys({ required List serverPk, }) => RustLib.instance.api.cryptoLayerCommonDhExchangeDeriveClientSessionKeys( @@ -5887,6 +5827,7 @@ class DhExchangeImpl extends RustOpaque implements DhExchange { serverPk: serverPk, ); + /// Derives server session keys and returns them as key handles. Future<(KeyHandle, KeyHandle)> deriveServerKeyHandles({ required List clientPk, }) => RustLib.instance.api.cryptoLayerCommonDhExchangeDeriveServerKeyHandles( @@ -5894,6 +5835,7 @@ class DhExchangeImpl extends RustOpaque implements DhExchange { clientPk: clientPk, ); + /// Derive server session keys (rx, tx) - server is the requestor in your code. Future<(Uint8List, Uint8List)> deriveServerSessionKeys({ required List clientPk, }) => RustLib.instance.api.cryptoLayerCommonDhExchangeDeriveServerSessionKeys( @@ -5901,9 +5843,11 @@ class DhExchangeImpl extends RustOpaque implements DhExchange { clientPk: clientPk, ); + /// Get the public key of the internal key pair to use for the other party. Future getPublicKey() => RustLib.instance.api.cryptoLayerCommonDhExchangeGetPublicKey(that: this); + /// Returns the id of the key pair, which can be used with `load_key_pair`. Future id() => RustLib.instance.api.cryptoLayerCommonDhExchangeId(that: this); } @@ -5927,6 +5871,7 @@ class KeyHandleImpl extends RustOpaque implements KeyHandle { RustLib.instance.api.rust_arc_decrement_strong_count_KeyHandlePtr, ); + /// Decrypts the given encrypted data using the cryptographic key. Future decryptData({ required List encryptedData, required List iv, @@ -5936,14 +5881,25 @@ class KeyHandleImpl extends RustOpaque implements KeyHandle { iv: iv, ); + /// Delete this key. Future delete() => RustLib.instance.api.cryptoLayerCommonKeyHandleDelete(that: this); + /// Derives an ephemeral key from this key as base with the same spec as the base key. + /// + /// A derived key is exportable if the base key (self) is exportable. + /// + /// This operation is deterministic, meaning the same nonce and key are always going to result in the same [KeyHandle]. Future deriveKey({required List nonce}) => RustLib .instance .api .cryptoLayerCommonKeyHandleDeriveKey(that: this, nonce: nonce); + /// Encrypt data. + /// + /// The iv is randomly generated. + /// + /// The resulting output is a pair of cipher text and generated iv: `(cipher_text, iv)` Future<(Uint8List, Uint8List)> encrypt({required List data}) => RustLib .instance .api @@ -5958,6 +5914,9 @@ class KeyHandleImpl extends RustOpaque implements KeyHandle { iv: iv, ); + /// Encrypt data with the given iv. + /// + /// Some providers panic, if the iv is not the correct length. Future encryptWithIv({ required List data, required List iv, @@ -5967,18 +5926,26 @@ class KeyHandleImpl extends RustOpaque implements KeyHandle { iv: iv, ); + /// Returns the raw key as binary. + /// + /// Most hardware based providers will return [CalError] + /// with [CalErrorKind::NotImplemented](super::CalErrorKind::NotImplemented). Future extractKey() => RustLib.instance.api.cryptoLayerCommonKeyHandleExtractKey(that: this); + /// Calculates HMAC of the given data. Future hmac({required List data}) => RustLib.instance.api .cryptoLayerCommonKeyHandleHmac(that: this, data: data); + /// Returns the id of the key, which can be used with `load_key`. Future id() => RustLib.instance.api.cryptoLayerCommonKeyHandleId(that: this); + /// Returns the [KeySpec] the key was generated with. Future spec() => RustLib.instance.api.cryptoLayerCommonKeyHandleSpec(that: this); + /// Verifies data with the given signature. Future verifyHmac({required List data, required List hmac}) => RustLib.instance.api.cryptoLayerCommonKeyHandleVerifyHmac( that: this, @@ -6006,38 +5973,49 @@ class KeyPairHandleImpl extends RustOpaque implements KeyPairHandle { RustLib.instance.api.rust_arc_decrement_strong_count_KeyPairHandlePtr, ); + /// Decrypts the given encrypted data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future decryptData({required List data}) => RustLib .instance .api .cryptoLayerCommonKeyPairHandleDecryptData(that: this, data: data); + /// Delete this key pair. /// Abstraction of asymmetric key pair handles. Future delete() => RustLib.instance.api.cryptoLayerCommonKeyPairHandleDelete(that: this); + /// Encrypts the given data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future encryptData({required List data}) => RustLib .instance .api .cryptoLayerCommonKeyPairHandleEncryptData(that: this, data: data); + /// Returns the raw private key as binary. + /// + /// Most hardware based providers will return [CalError] + /// with [CalErrorKind::NotImplemented](super::CalErrorKind::NotImplemented). /// Abstraction of asymmetric key pair handles. Future extractKey() => RustLib.instance.api.cryptoLayerCommonKeyPairHandleExtractKey(that: this); + /// Returns the raw public key as binary. /// Abstraction of asymmetric key pair handles. Future getPublicKey() => RustLib.instance.api .cryptoLayerCommonKeyPairHandleGetPublicKey(that: this); + /// Returns the id of the key pair, which can be used with `load_key_pair`. /// Abstraction of asymmetric key pair handles. Future id() => RustLib.instance.api.cryptoLayerCommonKeyPairHandleId(that: this); + /// Signs the given data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future signData({required List data}) => RustLib.instance.api .cryptoLayerCommonKeyPairHandleSignData(that: this, data: data); + /// Returns the [KeyPairSpec] the key was generated with. /// Abstraction of asymmetric key pair handles. Future spec() => RustLib.instance.api.cryptoLayerCommonKeyPairHandleSpec(that: this); @@ -6046,6 +6024,7 @@ class KeyPairHandleImpl extends RustOpaque implements KeyPairHandle { Future startDhExchange() => RustLib.instance.api .cryptoLayerCommonKeyPairHandleStartDhExchange(that: this); + /// Verifies the signature of the given data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future verifySignature({ required List data, @@ -6076,9 +6055,11 @@ class ProviderImpl extends RustOpaque implements Provider { RustLib.instance.api.rust_arc_decrement_strong_count_ProviderPtr, ); + /// Creates a new symmetric key. Future createKey({required KeySpec spec}) => RustLib.instance.api .cryptoLayerCommonProviderCreateKey(that: this, spec: spec); + /// Creates a new asymmetric key pair. Future createKeyPair({required KeyPairSpec spec}) => RustLib .instance .api @@ -6097,6 +6078,7 @@ class ProviderImpl extends RustOpaque implements Provider { spec: spec, ); + /// Derives a high-entropy key from a low-entropy password and a unique salt. Future deriveKeyFromPassword({ required String password, required List salt, @@ -6121,15 +6103,19 @@ class ProviderImpl extends RustOpaque implements Provider { spec: spec, ); + /// Returns all keys stored in this provider. Future> getAllKeys() => RustLib.instance.api.cryptoLayerCommonProviderGetAllKeys(that: this); + /// Returns the capabilities of this provider. Future getCapabilities() => RustLib.instance.api.cryptoLayerCommonProviderGetCapabilities(that: this); + /// Generates random bytes. Future getRandom({required BigInt len}) => RustLib.instance.api .cryptoLayerCommonProviderGetRandom(that: this, len: len); + /// Hashes the input using the specified hash algorithm. Future hash({ required List input, required CryptoHash hash, @@ -6139,6 +6125,7 @@ class ProviderImpl extends RustOpaque implements Provider { hash: hash, ); + /// Imports a symmetric key from raw data. Future importKey({ required KeySpec spec, required List data, @@ -6148,6 +6135,7 @@ class ProviderImpl extends RustOpaque implements Provider { data: data, ); + /// Imports an asymmetric key pair from raw data. Future importKeyPair({ required KeyPairSpec spec, required List publicKey, @@ -6159,6 +6147,7 @@ class ProviderImpl extends RustOpaque implements Provider { privateKey: privateKey, ); + /// Imports a public key only. Future importPublicKey({ required KeyPairSpec spec, required List publicKey, @@ -6168,17 +6157,21 @@ class ProviderImpl extends RustOpaque implements Provider { publicKey: publicKey, ); + /// Loads an existing symmetric key identified by `key_id`. Future loadKey({required String id}) => RustLib.instance.api.cryptoLayerCommonProviderLoadKey(that: this, id: id); + /// Loads an existing asymmetric keypair identified by `key_id`. Future loadKeyPair({required String id}) => RustLib .instance .api .cryptoLayerCommonProviderLoadKeyPair(that: this, id: id); + /// Returns the name of this provider. Future providerName() => RustLib.instance.api.cryptoLayerCommonProviderProviderName(that: this); + /// Generates a key pair suited for a Diffie-Hellman Key Exchange. Future startEphemeralDhExchange({required KeyPairSpec spec}) => RustLib.instance.api.cryptoLayerCommonProviderStartEphemeralDhExchange( that: this, diff --git a/cal_flutter_plugin/lib/src/rust/frb_generated.io.dart b/cal_flutter_plugin/lib/src/rust/frb_generated.io.dart index 3b3297fa..3b9ca9d0 100644 --- a/cal_flutter_plugin/lib/src/rust/frb_generated.io.dart +++ b/cal_flutter_plugin/lib/src/rust/frb_generated.io.dart @@ -47,6 +47,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { get rust_arc_decrement_strong_count_CalErrorPtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorPtr; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_CalErrorKindPtr => wire + ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKindPtr; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DhExchangePtr => wire ._rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchangePtr; @@ -96,6 +100,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + CalErrorKind + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + dynamic raw, + ); + @protected DhExchange dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -215,6 +225,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + CalErrorKind + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + dynamic raw, + ); + @protected DhExchange dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -293,9 +309,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ProviderImplConfig dco_decode_box_autoadd_provider_impl_config(dynamic raw); - @protected - CalErrorKind dco_decode_cal_error_kind(dynamic raw); - @protected Cipher dco_decode_cipher(dynamic raw); @@ -317,9 +330,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected KeySpec dco_decode_key_spec(dynamic raw); - @protected - KeyType dco_decode_key_type(dynamic raw); - @protected List dco_decode_list_String(dynamic raw); @@ -448,6 +458,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + CalErrorKind + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + SseDeserializer deserializer, + ); + @protected DhExchange sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -547,6 +563,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + CalErrorKind + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + SseDeserializer deserializer, + ); + @protected DhExchange sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -634,9 +656,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); - @protected - CalErrorKind sse_decode_cal_error_kind(SseDeserializer deserializer); - @protected Cipher sse_decode_cipher(SseDeserializer deserializer); @@ -658,9 +677,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected KeySpec sse_decode_key_spec(SseDeserializer deserializer); - @protected - KeyType sse_decode_key_type(SseDeserializer deserializer); - @protected List sse_decode_list_String(SseDeserializer deserializer); @@ -809,6 +825,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + CalErrorKind self, + SseSerializer serializer, + ); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -950,6 +973,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + CalErrorKind self, + SseSerializer serializer, + ); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -1054,9 +1084,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); - @protected - void sse_encode_cal_error_kind(CalErrorKind self, SseSerializer serializer); - @protected void sse_encode_cipher(Cipher self, SseSerializer serializer); @@ -1078,9 +1105,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_key_spec(KeySpec self, SseSerializer serializer); - @protected - void sse_encode_key_type(KeyType self, SseSerializer serializer); - @protected void sse_encode_list_String(List self, SseSerializer serializer); @@ -1400,6 +1424,40 @@ class RustLibWire implements BaseWire { _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorPtr .asFunction)>(); + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ffi.Pointer ptr, + ) { + return _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr, + ); + } + + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKindPtr = + _lookup)>>( + 'frbgen_cal_flutter_plugin_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind', + ); + late final _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind = + _rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKindPtr + .asFunction)>(); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ffi.Pointer ptr, + ) { + return _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr, + ); + } + + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKindPtr = + _lookup)>>( + 'frbgen_cal_flutter_plugin_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind', + ); + late final _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind = + _rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKindPtr + .asFunction)>(); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( ffi.Pointer ptr, diff --git a/cal_flutter_plugin/lib/src/rust/frb_generated.web.dart b/cal_flutter_plugin/lib/src/rust/frb_generated.web.dart index d98dd9bc..39846148 100644 --- a/cal_flutter_plugin/lib/src/rust/frb_generated.web.dart +++ b/cal_flutter_plugin/lib/src/rust/frb_generated.web.dart @@ -49,6 +49,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { get rust_arc_decrement_strong_count_CalErrorPtr => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalError; + CrossPlatformFinalizerArg + get rust_arc_decrement_strong_count_CalErrorKindPtr => wire + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind; + CrossPlatformFinalizerArg get rust_arc_decrement_strong_count_DhExchangePtr => wire .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange; @@ -98,6 +102,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + CalErrorKind + dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + dynamic raw, + ); + @protected DhExchange dco_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -217,6 +227,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dynamic raw, ); + @protected + CalErrorKind + dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + dynamic raw, + ); + @protected DhExchange dco_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -295,9 +311,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected ProviderImplConfig dco_decode_box_autoadd_provider_impl_config(dynamic raw); - @protected - CalErrorKind dco_decode_cal_error_kind(dynamic raw); - @protected Cipher dco_decode_cipher(dynamic raw); @@ -319,9 +332,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected KeySpec dco_decode_key_spec(dynamic raw); - @protected - KeyType dco_decode_key_type(dynamic raw); - @protected List dco_decode_list_String(dynamic raw); @@ -450,6 +460,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + CalErrorKind + sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + SseDeserializer deserializer, + ); + @protected DhExchange sse_decode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -549,6 +565,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); + @protected + CalErrorKind + sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + SseDeserializer deserializer, + ); + @protected DhExchange sse_decode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -636,9 +658,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseDeserializer deserializer, ); - @protected - CalErrorKind sse_decode_cal_error_kind(SseDeserializer deserializer); - @protected Cipher sse_decode_cipher(SseDeserializer deserializer); @@ -660,9 +679,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected KeySpec sse_decode_key_spec(SseDeserializer deserializer); - @protected - KeyType sse_decode_key_type(SseDeserializer deserializer); - @protected List sse_decode_list_String(SseDeserializer deserializer); @@ -811,6 +827,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + CalErrorKind self, + SseSerializer serializer, + ); + @protected void sse_encode_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -952,6 +975,13 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); + @protected + void + sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + CalErrorKind self, + SseSerializer serializer, + ); + @protected void sse_encode_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( @@ -1056,9 +1086,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { SseSerializer serializer, ); - @protected - void sse_encode_cal_error_kind(CalErrorKind self, SseSerializer serializer); - @protected void sse_encode_cipher(Cipher self, SseSerializer serializer); @@ -1080,9 +1107,6 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_key_spec(KeySpec self, SseSerializer serializer); - @protected - void sse_encode_key_type(KeyType self, SseSerializer serializer); - @protected void sse_encode_list_String(List self, SseSerializer serializer); @@ -1303,6 +1327,22 @@ class RustLibWire implements BaseWire { ptr, ); + void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + int ptr, + ) => wasmModule + .rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr, + ); + + void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + int ptr, + ) => wasmModule + .rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr, + ); + void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( int ptr, @@ -1424,6 +1464,16 @@ extension type RustLibWasmModule._(JSObject _) implements JSObject { int ptr, ); + external void + rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + int ptr, + ); + + external void + rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + int ptr, + ); + external void rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( int ptr, diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common.dart index 70e5bc32..db352fef 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common.dart @@ -15,38 +15,56 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // Rust type: RustOpaqueMoi> abstract class DhExchange implements RustOpaqueInterface { + /// Derives client session keys and returns them as key handles. Future<(KeyHandle, KeyHandle)> deriveClientKeyHandles({ required List serverPk, }); + /// Derive client session keys (rx, tx) - client is the templator in your code. Future<(Uint8List, Uint8List)> deriveClientSessionKeys({ required List serverPk, }); + /// Derives server session keys and returns them as key handles. Future<(KeyHandle, KeyHandle)> deriveServerKeyHandles({ required List clientPk, }); + /// Derive server session keys (rx, tx) - server is the requestor in your code. Future<(Uint8List, Uint8List)> deriveServerSessionKeys({ required List clientPk, }); + /// Get the public key of the internal key pair to use for the other party. Future getPublicKey(); + /// Returns the id of the key pair, which can be used with `load_key_pair`. Future id(); } // Rust type: RustOpaqueMoi> abstract class KeyHandle implements RustOpaqueInterface { + /// Decrypts the given encrypted data using the cryptographic key. Future decryptData({ required List encryptedData, required List iv, }); + /// Delete this key. Future delete(); + /// Derives an ephemeral key from this key as base with the same spec as the base key. + /// + /// A derived key is exportable if the base key (self) is exportable. + /// + /// This operation is deterministic, meaning the same nonce and key are always going to result in the same [KeyHandle]. Future deriveKey({required List nonce}); + /// Encrypt data. + /// + /// The iv is randomly generated. + /// + /// The resulting output is a pair of cipher text and generated iv: `(cipher_text, iv)` Future<(Uint8List, Uint8List)> encrypt({required List data}); Future<(Uint8List, Uint8List)> encryptData({ @@ -54,51 +72,74 @@ abstract class KeyHandle implements RustOpaqueInterface { required List iv, }); + /// Encrypt data with the given iv. + /// + /// Some providers panic, if the iv is not the correct length. Future encryptWithIv({ required List data, required List iv, }); + /// Returns the raw key as binary. + /// + /// Most hardware based providers will return [CalError] + /// with [CalErrorKind::NotImplemented](super::CalErrorKind::NotImplemented). Future extractKey(); + /// Calculates HMAC of the given data. Future hmac({required List data}); + /// Returns the id of the key, which can be used with `load_key`. Future id(); + /// Returns the [KeySpec] the key was generated with. Future spec(); + /// Verifies data with the given signature. Future verifyHmac({required List data, required List hmac}); } // Rust type: RustOpaqueMoi> abstract class KeyPairHandle implements RustOpaqueInterface { + /// Decrypts the given encrypted data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future decryptData({required List data}); + /// Delete this key pair. /// Abstraction of asymmetric key pair handles. Future delete(); + /// Encrypts the given data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future encryptData({required List data}); + /// Returns the raw private key as binary. + /// + /// Most hardware based providers will return [CalError] + /// with [CalErrorKind::NotImplemented](super::CalErrorKind::NotImplemented). /// Abstraction of asymmetric key pair handles. Future extractKey(); + /// Returns the raw public key as binary. /// Abstraction of asymmetric key pair handles. Future getPublicKey(); + /// Returns the id of the key pair, which can be used with `load_key_pair`. /// Abstraction of asymmetric key pair handles. Future id(); + /// Signs the given data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future signData({required List data}); + /// Returns the [KeyPairSpec] the key was generated with. /// Abstraction of asymmetric key pair handles. Future spec(); /// Abstraction of asymmetric key pair handles. Future startDhExchange(); + /// Verifies the signature of the given data using the cryptographic key. /// Abstraction of asymmetric key pair handles. Future verifySignature({ required List data, @@ -108,8 +149,10 @@ abstract class KeyPairHandle implements RustOpaqueInterface { // Rust type: RustOpaqueMoi> abstract class Provider implements RustOpaqueInterface { + /// Creates a new symmetric key. Future createKey({required KeySpec spec}); + /// Creates a new asymmetric key pair. Future createKeyPair({required KeyPairSpec spec}); Future deriveKeyFromBase({ @@ -119,6 +162,7 @@ abstract class Provider implements RustOpaqueInterface { required KeySpec spec, }); + /// Derives a high-entropy key from a low-entropy password and a unique salt. Future deriveKeyFromPassword({ required String password, required List salt, @@ -132,37 +176,47 @@ abstract class Provider implements RustOpaqueInterface { required KeyPairSpec spec, }); + /// Returns all keys stored in this provider. Future> getAllKeys(); + /// Returns the capabilities of this provider. Future getCapabilities(); + /// Generates random bytes. Future getRandom({required BigInt len}); + /// Hashes the input using the specified hash algorithm. Future hash({required List input, required CryptoHash hash}); + /// Imports a symmetric key from raw data. Future importKey({required KeySpec spec, required List data}); + /// Imports an asymmetric key pair from raw data. Future importKeyPair({ required KeyPairSpec spec, required List publicKey, required List privateKey, }); + /// Imports a public key only. Future importPublicKey({ required KeyPairSpec spec, required List publicKey, }); + /// Loads an existing symmetric key identified by `key_id`. Future loadKey({required String id}); + /// Loads an existing asymmetric keypair identified by `key_id`. Future loadKeyPair({required String id}); + /// Returns the name of this provider. Future providerName(); + /// Generates a key pair suited for a Diffie-Hellman Key Exchange. Future startEphemeralDhExchange({required KeyPairSpec spec}); } -/// ¯\_(ツ)_/¯ class T { const T(); diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/config.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/config.dart index a0620c94..8dede624 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/config.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/config.dart @@ -13,7 +13,7 @@ import 'package:freezed_annotation/freezed_annotation.dart' hide protected; part 'config.freezed.dart'; // These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `AdditionalConfigDiscriminants`, `SecurityLevelIter` -// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `cmp`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from_str`, `from_str`, `from`, `from`, `from`, `from`, `from`, `from`, `iter`, `len`, `next_back`, `next`, `nth`, `partial_cmp`, `size_hint`, `try_from`, `try_from`, `zeroize` +// These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `clone`, `cmp`, `discriminant`, `eq`, `eq`, `eq`, `eq`, `eq`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from_str`, `from_str`, `from`, `from`, `from`, `from`, `from`, `from`, `iter`, `len`, `next_back`, `next`, `nth`, `partial_cmp`, `size_hint`, `try_from`, `try_from`, `zeroize` @freezed sealed class AdditionalConfig with _$AdditionalConfig { @@ -69,6 +69,9 @@ sealed class AdditionalConfig with _$AdditionalConfig { } /// Struct used to configure key pairs. +/// +/// It is important to note, that the configuration of a key can only happen at the point of its creation. +/// A key cannot be reconfigured. /// flutter_rust_bridge:non_opaque class KeyPairSpec { /// Asymmetric algorithm to be used. @@ -118,6 +121,9 @@ class KeyPairSpec { } /// Struct used to configure keys. +/// +/// It is important to note, that the configuration of a key can only happen at the point of its creation. +/// A key cannot be reconfigured. /// flutter_rust_bridge:non_opaque class KeySpec { /// Cipher used for symmetric encryption. @@ -126,10 +132,12 @@ class KeySpec { /// Hash function used with HMAC. final CryptoHash signingHash; - /// If set to `true`, the key is going to be deleted when the handle is dropped. + /// If set to `true`, metadata of the key is not stored and the key is going to be deleted when the handle is dropped. final bool ephemeral; /// If set to `true`, the key cannot be exported. + /// + /// Some providers do not allow exporting keys at all, even if set to `false`. final bool nonExportable; const KeySpec({ @@ -161,12 +169,100 @@ class KeySpec { } /// Capabilities of a Provider +/// +/// This configuration struct has multiple uses: +/// * Act as capabilities of a provider. +/// * Act as requirement for [`create_provider`](crate::prelude::create_provider). +/// +/// Depending on the use some properties have different meanings: +/// * Currently a provider may only have one security level. +/// * The requester may ask for a provider that has at a minimum one security level or at a maximum another security level. +/// * A provider has certain algorithm he at least in some form supports. +/// * A requester may ask for minimum requirements regarding these algorithms. +/// +/// ### Example +/// +/// A provider might return capabilities like: +/// ``` +/// # use crypto_layer::prelude::*; +/// # use std::collections::HashSet; +/// +/// let apple_provider_capabilities = ProviderConfig { +/// max_security_level: SecurityLevel::Hardware, +/// min_security_level: SecurityLevel::Hardware, +/// supported_ciphers: HashSet::from([Cipher::AesGcm128, Cipher::AesGcm256]), +/// supported_asym_spec: HashSet::from([AsymmetricKeySpec::P256]), +/// supported_hashes: HashSet::from([ +/// CryptoHash::Sha2_224, +/// CryptoHash::Sha2_256, +/// CryptoHash::Sha2_384, +/// CryptoHash::Sha2_512, +/// ]), +/// }; +/// +/// ``` +/// Such provider then is ought to use a secure element (apart from the `ANDROID_PROVIDER`) +/// and at least support these algorithms **in one form or another** . +/// +/// Please be aware, that `supported_ciphers` does not imply support for symmetric cryptography! +/// +/// A requestor might ask for a provider with capabilities like: +/// ``` +/// # use crypto_layer::prelude::*; +/// # use std::collections::HashSet; +/// +/// let requested_capabilities = ProviderConfig { +/// max_security_level: SecurityLevel::Hardware, +/// min_security_level: SecurityLevel::Software, +/// supported_ciphers: HashSet::from([Cipher::AesGcm256]), +/// supported_asym_spec: HashSet::from([AsymmetricKeySpec::P256]), +/// supported_hashes: HashSet::from([ +/// CryptoHash::Sha2_256, +/// CryptoHash::Sha2_512, +/// ]), +/// }; +/// ``` +/// +/// As the requested capabilities are a subset of the provided capabilities above, +/// this requestor might be assigned the apple secure enclave provider on apple platforms. +/// /// flutter_rust_bridge:non_opaque class ProviderConfig { + /// Highest security supported or maximum security requested. + /// + /// As an example, the software fallback provider has a maximum security level of [`SecurityLevel::Software`]. final SecurityLevel maxSecurityLevel; + + /// Minimum security level supported or security level required. + /// + /// As an example: + /// If one wishes to use provider that is based on a secure element, one would require [`SecurityLevel::Hardware`]. final SecurityLevel minSecurityLevel; + + /// Cipher algorithms supported in one fashion or another or cipher algorithms required. + /// + /// A provider might support cipher algorithms returned as capabilities in following ways: + /// * Supports symmetric encryption with said cipher. + /// * Supports asymmetric hybrid encryption with said cipher. (What standard is used for the hybrid encryption is not set.) final Set supportedCiphers; + + /// Hashing algorithm supported for either the use with signing (symmetric or asymmetric) operations or encryption operations (symmetric or asymmetric), + /// or hashing algorithm required for the same purpose. + /// + /// A provider that supports a hash algorithm **may or may not** support following operations in combination with said hashing algorithm: + /// * [`KeyHandle::hmac()`](crate::prelude::KeyHandle::hmac) + /// * [`KeyHandle::verify_hmac()`](crate::prelude::KeyHandle::verify_hmac) + /// * [`KeyHandle::encrypt()`](crate::prelude::KeyHandle::encrypt()) + /// * [`KeyHandle::decrypt_data()`](crate::prelude::KeyHandle::decrypt_data()) + /// * [`KeyPairHandle::sign_data`](crate::prelude::KeyPairHandle::sign_data) + /// * [`KeyPairHandle::verify_signature`](crate::prelude::KeyPairHandle::verify_signature) + /// * [`KeyPairHandle::encrypt_data()`](crate::prelude::KeyPairHandle::encrypt_data) + /// * [`KeyPairHandle::decrypt_data()`](crate::prelude::KeyPairHandle::decrypt_data) final Set supportedHashes; + + /// Asymmetric cryptographic algorithms supported or required. + /// + /// A provider supporting an asymmetric cryptographic algorithm **may or may not** support said algorithm for signing or encryption operations. final Set supportedAsymSpec; const ProviderConfig({ @@ -197,23 +293,28 @@ class ProviderConfig { supportedAsymSpec == other.supportedAsymSpec; } -/// Configuration needed for using or initializing providers. +/// Key metadata store configuration +/// +/// Due to an accident, this configuration became a vector. /// -/// Either -/// * [AdditionalConfig::KVStoreConfig] -/// * [AdditionalConfig::FileStoreConfig] +/// If neither [`AdditionalConfig::KVStoreConfig`] nor [`AdditionalConfig::FileStoreConfig`] are supplied +/// to [`create_provider()`] or to [`create_provider_from_name()`], +/// a provider will be created that is only capable of creating ephemeral keys! /// -/// and either -/// * [AdditionalConfig::StorageConfigHMAC] -/// * [AdditionalConfig::StorageConfigDSA] -/// * [AdditionalConfig::StorageConfigPass] +/// To protect key metadata against unauthorized change, it is recommended to make use of +/// [`AdditionalConfig::StorageConfigHMAC`] or [`AdditionalConfig::StorageConfigDSA`]. +/// (This may only apply if you use multiple providers and one is of [`SecurityLevel::Hardware`] or above.) +/// +/// If the fallback software provider is used with [AdditionalConfig::StorageConfigSymmetricEncryption] +/// or [AdditionalConfig::StorageConfigAsymmetricEncryption], the stored secret keys are secured by +/// the provided key, which in turn makes such construct a hybrid provider (as the keys at rest have hardware security protection). /// -/// need to be supplied. /// /// ## Example /// /// ```rust -/// use crypto_layer::prelude::*; +/// # use crypto_layer::prelude::*; +/// /// let implementation_config = ProviderImplConfig { /// additional_config: vec![ /// AdditionalConfig::FileStoreConfig { @@ -222,6 +323,10 @@ class ProviderConfig { /// ], /// }; /// ``` +/// +/// [`create_provider()`]: crate::prelude::create_provider +/// [`create_provider_from_name()`]: crate::prelude::create_provider_from_name +/// /// flutter_rust_bridge:non_opaque class ProviderImplConfig { final List additionalConfig; @@ -259,7 +364,7 @@ class ProviderImplConfig { /// /// * [SecurityLevel::Hardware]: Provider is hardware backed (tpm, other security chips, StrongBox KeyStore). /// * [SecurityLevel::Software]: Provider uses the systems software keystore. -/// * [SecurityLevel::Network]: Provider uses a network key store (Hashicorp). +/// * [SecurityLevel::Network]: Provider uses a network key store (HashiCorp). /// * [SecurityLevel::Unsafe]: Provider uses software fallback. enum SecurityLevel { /// Highest security level. diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart index e92eeaf5..c68c6092 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/encryption.dart @@ -3,6 +3,7 @@ // ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import +import '../../../../../frb_generated.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `assert_receiver_is_total_eq`, `assert_receiver_is_total_eq`, `clone`, `clone`, `eq`, `eq`, `fmt`, `fmt`, `from_str`, `from_str`, `from`, `from`, `from`, `from`, `hash`, `hash`, `try_from`, `try_from`, `zeroize` diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/key_derivation.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/key_derivation.dart index ec476376..43b9be10 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/key_derivation.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/crypto/algorithms/key_derivation.dart @@ -10,6 +10,9 @@ part 'key_derivation.freezed.dart'; // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt` +/// Configuration for KDF with Argon2 +/// +/// When in doubt use the default. /// flutter_rust_bridge:non_opaque class Argon2Options { /// Memory cost in kibibytes @@ -27,6 +30,9 @@ class Argon2Options { required this.parallelism, }); + /// Defaults for servers. + /// Taken from Password Storage Cheat Sheet (12.03.2025) + /// static Future default_() => RustLib.instance.api .cryptoLayerCommonCryptoAlgorithmsKeyDerivationArgon2OptionsDefault(); @@ -55,6 +61,9 @@ sealed class KDF with _$KDF { const factory KDF.argon2Id(Argon2Options field0) = KDF_Argon2id; const factory KDF.argon2I(Argon2Options field0) = KDF_Argon2i; + /// Defaults for servers. + /// Taken from Password Storage Cheat Sheet (12.03.2025) + /// static Future default_() => RustLib.instance.api .cryptoLayerCommonCryptoAlgorithmsKeyDerivationKdfDefault(); } diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.dart index 546d79c2..cad75498 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.dart @@ -6,9 +6,8 @@ import '../../../frb_generated.dart'; import '../common.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -import 'package:freezed_annotation/freezed_annotation.dart' hide protected; -part 'error.freezed.dart'; +// These types are ignored because they are neither used by any `pub` functions nor (for structs and enums) marked `#[frb(unignore)]`: `KeyType` // These function are ignored because they are on traits that is not defined in current crate (put an empty `#[frb]` on it to unignore): `clone`, `clone`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `fmt`, `from`, `from`, `from`, `source` // Rust type: RustOpaqueMoi> @@ -18,65 +17,9 @@ abstract class CalError implements RustOpaqueInterface { Future errorKind(); } +// Rust type: RustOpaqueMoi> +abstract class CalErrorKind implements RustOpaqueInterface {} + abstract class ToCalError { Future errInternal(); } - -@freezed -sealed class CalErrorKind with _$CalErrorKind { - const CalErrorKind._(); - - /// This error is returned on calling functions that are not implemented. - const factory CalErrorKind.notImplemented() = CalErrorKind_NotImplemented; - - /// One or more of the parameters supplied are invalid for said function. - const factory CalErrorKind.badParameter({ - required String description, - - /// `true` if caused within this library. `false` if caused by another library. - required bool internal, - }) = CalErrorKind_BadParameter; - const factory CalErrorKind.missingKey({ - required String keyId, - required KeyType keyType, - }) = CalErrorKind_MissingKey; - - /// The value requested could not be found. - const factory CalErrorKind.missingValue({ - required String description, - - /// `true` if caused within this library. `false` if caused by another library. - required bool internal, - }) = CalErrorKind_MissingValue; - - /// A cryptographic operation failed. - const factory CalErrorKind.failedOperation({ - required String description, - - /// `true` if caused within this library. `false` if caused by another library. - required bool internal, - }) = CalErrorKind_FailedOperation; - - /// Failed to initialize a provider. - const factory CalErrorKind.initializationError({ - required String description, - - /// `true` if caused within this library. `false` if caused by another library. - required bool internal, - }) = CalErrorKind_InitializationError; - const factory CalErrorKind.nonExportable() = CalErrorKind_NonExportable; - - /// Algorithm requested is not supported by the provider. - const factory CalErrorKind.unsupportedAlgorithm(String field0) = - CalErrorKind_UnsupportedAlgorithm; - - /// Tried to create a non-ephemeral key with an ephemeral provider. - const factory CalErrorKind.ephemeralKeyError() = - CalErrorKind_EphemeralKeyError; - - /// Errors that do not fall into the above classes. - const factory CalErrorKind.other() = CalErrorKind_Other; -} - -/// Key type for error pertaining to said key. -enum KeyType { public, private, publicAndPrivate, symmetric } diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.freezed.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.freezed.dart deleted file mode 100644 index 7ab267a4..00000000 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/error.freezed.dart +++ /dev/null @@ -1,583 +0,0 @@ -// dart format width=80 -// coverage:ignore-file -// GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: type=lint -// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark - -part of 'error.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$CalErrorKind { - - - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind); -} - - -@override -int get hashCode => runtimeType.hashCode; - -@override -String toString() { - return 'CalErrorKind()'; -} - - -} - -/// @nodoc -class $CalErrorKindCopyWith<$Res> { -$CalErrorKindCopyWith(CalErrorKind _, $Res Function(CalErrorKind) __); -} - - -/// @nodoc - - -class CalErrorKind_NotImplemented extends CalErrorKind { - const CalErrorKind_NotImplemented(): super._(); - - - - - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_NotImplemented); -} - - -@override -int get hashCode => runtimeType.hashCode; - -@override -String toString() { - return 'CalErrorKind.notImplemented()'; -} - - -} - - - - -/// @nodoc - - -class CalErrorKind_BadParameter extends CalErrorKind { - const CalErrorKind_BadParameter({required this.description, required this.internal}): super._(); - - - final String description; -/// `true` if caused within this library. `false` if caused by another library. - final bool internal; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalErrorKind_BadParameterCopyWith get copyWith => _$CalErrorKind_BadParameterCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_BadParameter&&(identical(other.description, description) || other.description == description)&&(identical(other.internal, internal) || other.internal == internal)); -} - - -@override -int get hashCode => Object.hash(runtimeType,description,internal); - -@override -String toString() { - return 'CalErrorKind.badParameter(description: $description, internal: $internal)'; -} - - -} - -/// @nodoc -abstract mixin class $CalErrorKind_BadParameterCopyWith<$Res> implements $CalErrorKindCopyWith<$Res> { - factory $CalErrorKind_BadParameterCopyWith(CalErrorKind_BadParameter value, $Res Function(CalErrorKind_BadParameter) _then) = _$CalErrorKind_BadParameterCopyWithImpl; -@useResult -$Res call({ - String description, bool internal -}); - - - - -} -/// @nodoc -class _$CalErrorKind_BadParameterCopyWithImpl<$Res> - implements $CalErrorKind_BadParameterCopyWith<$Res> { - _$CalErrorKind_BadParameterCopyWithImpl(this._self, this._then); - - final CalErrorKind_BadParameter _self; - final $Res Function(CalErrorKind_BadParameter) _then; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') $Res call({Object? description = null,Object? internal = null,}) { - return _then(CalErrorKind_BadParameter( -description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable -as String,internal: null == internal ? _self.internal : internal // ignore: cast_nullable_to_non_nullable -as bool, - )); -} - - -} - -/// @nodoc - - -class CalErrorKind_MissingKey extends CalErrorKind { - const CalErrorKind_MissingKey({required this.keyId, required this.keyType}): super._(); - - - final String keyId; - final KeyType keyType; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalErrorKind_MissingKeyCopyWith get copyWith => _$CalErrorKind_MissingKeyCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_MissingKey&&(identical(other.keyId, keyId) || other.keyId == keyId)&&(identical(other.keyType, keyType) || other.keyType == keyType)); -} - - -@override -int get hashCode => Object.hash(runtimeType,keyId,keyType); - -@override -String toString() { - return 'CalErrorKind.missingKey(keyId: $keyId, keyType: $keyType)'; -} - - -} - -/// @nodoc -abstract mixin class $CalErrorKind_MissingKeyCopyWith<$Res> implements $CalErrorKindCopyWith<$Res> { - factory $CalErrorKind_MissingKeyCopyWith(CalErrorKind_MissingKey value, $Res Function(CalErrorKind_MissingKey) _then) = _$CalErrorKind_MissingKeyCopyWithImpl; -@useResult -$Res call({ - String keyId, KeyType keyType -}); - - - - -} -/// @nodoc -class _$CalErrorKind_MissingKeyCopyWithImpl<$Res> - implements $CalErrorKind_MissingKeyCopyWith<$Res> { - _$CalErrorKind_MissingKeyCopyWithImpl(this._self, this._then); - - final CalErrorKind_MissingKey _self; - final $Res Function(CalErrorKind_MissingKey) _then; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') $Res call({Object? keyId = null,Object? keyType = null,}) { - return _then(CalErrorKind_MissingKey( -keyId: null == keyId ? _self.keyId : keyId // ignore: cast_nullable_to_non_nullable -as String,keyType: null == keyType ? _self.keyType : keyType // ignore: cast_nullable_to_non_nullable -as KeyType, - )); -} - - -} - -/// @nodoc - - -class CalErrorKind_MissingValue extends CalErrorKind { - const CalErrorKind_MissingValue({required this.description, required this.internal}): super._(); - - - final String description; -/// `true` if caused within this library. `false` if caused by another library. - final bool internal; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalErrorKind_MissingValueCopyWith get copyWith => _$CalErrorKind_MissingValueCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_MissingValue&&(identical(other.description, description) || other.description == description)&&(identical(other.internal, internal) || other.internal == internal)); -} - - -@override -int get hashCode => Object.hash(runtimeType,description,internal); - -@override -String toString() { - return 'CalErrorKind.missingValue(description: $description, internal: $internal)'; -} - - -} - -/// @nodoc -abstract mixin class $CalErrorKind_MissingValueCopyWith<$Res> implements $CalErrorKindCopyWith<$Res> { - factory $CalErrorKind_MissingValueCopyWith(CalErrorKind_MissingValue value, $Res Function(CalErrorKind_MissingValue) _then) = _$CalErrorKind_MissingValueCopyWithImpl; -@useResult -$Res call({ - String description, bool internal -}); - - - - -} -/// @nodoc -class _$CalErrorKind_MissingValueCopyWithImpl<$Res> - implements $CalErrorKind_MissingValueCopyWith<$Res> { - _$CalErrorKind_MissingValueCopyWithImpl(this._self, this._then); - - final CalErrorKind_MissingValue _self; - final $Res Function(CalErrorKind_MissingValue) _then; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') $Res call({Object? description = null,Object? internal = null,}) { - return _then(CalErrorKind_MissingValue( -description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable -as String,internal: null == internal ? _self.internal : internal // ignore: cast_nullable_to_non_nullable -as bool, - )); -} - - -} - -/// @nodoc - - -class CalErrorKind_FailedOperation extends CalErrorKind { - const CalErrorKind_FailedOperation({required this.description, required this.internal}): super._(); - - - final String description; -/// `true` if caused within this library. `false` if caused by another library. - final bool internal; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalErrorKind_FailedOperationCopyWith get copyWith => _$CalErrorKind_FailedOperationCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_FailedOperation&&(identical(other.description, description) || other.description == description)&&(identical(other.internal, internal) || other.internal == internal)); -} - - -@override -int get hashCode => Object.hash(runtimeType,description,internal); - -@override -String toString() { - return 'CalErrorKind.failedOperation(description: $description, internal: $internal)'; -} - - -} - -/// @nodoc -abstract mixin class $CalErrorKind_FailedOperationCopyWith<$Res> implements $CalErrorKindCopyWith<$Res> { - factory $CalErrorKind_FailedOperationCopyWith(CalErrorKind_FailedOperation value, $Res Function(CalErrorKind_FailedOperation) _then) = _$CalErrorKind_FailedOperationCopyWithImpl; -@useResult -$Res call({ - String description, bool internal -}); - - - - -} -/// @nodoc -class _$CalErrorKind_FailedOperationCopyWithImpl<$Res> - implements $CalErrorKind_FailedOperationCopyWith<$Res> { - _$CalErrorKind_FailedOperationCopyWithImpl(this._self, this._then); - - final CalErrorKind_FailedOperation _self; - final $Res Function(CalErrorKind_FailedOperation) _then; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') $Res call({Object? description = null,Object? internal = null,}) { - return _then(CalErrorKind_FailedOperation( -description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable -as String,internal: null == internal ? _self.internal : internal // ignore: cast_nullable_to_non_nullable -as bool, - )); -} - - -} - -/// @nodoc - - -class CalErrorKind_InitializationError extends CalErrorKind { - const CalErrorKind_InitializationError({required this.description, required this.internal}): super._(); - - - final String description; -/// `true` if caused within this library. `false` if caused by another library. - final bool internal; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalErrorKind_InitializationErrorCopyWith get copyWith => _$CalErrorKind_InitializationErrorCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_InitializationError&&(identical(other.description, description) || other.description == description)&&(identical(other.internal, internal) || other.internal == internal)); -} - - -@override -int get hashCode => Object.hash(runtimeType,description,internal); - -@override -String toString() { - return 'CalErrorKind.initializationError(description: $description, internal: $internal)'; -} - - -} - -/// @nodoc -abstract mixin class $CalErrorKind_InitializationErrorCopyWith<$Res> implements $CalErrorKindCopyWith<$Res> { - factory $CalErrorKind_InitializationErrorCopyWith(CalErrorKind_InitializationError value, $Res Function(CalErrorKind_InitializationError) _then) = _$CalErrorKind_InitializationErrorCopyWithImpl; -@useResult -$Res call({ - String description, bool internal -}); - - - - -} -/// @nodoc -class _$CalErrorKind_InitializationErrorCopyWithImpl<$Res> - implements $CalErrorKind_InitializationErrorCopyWith<$Res> { - _$CalErrorKind_InitializationErrorCopyWithImpl(this._self, this._then); - - final CalErrorKind_InitializationError _self; - final $Res Function(CalErrorKind_InitializationError) _then; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') $Res call({Object? description = null,Object? internal = null,}) { - return _then(CalErrorKind_InitializationError( -description: null == description ? _self.description : description // ignore: cast_nullable_to_non_nullable -as String,internal: null == internal ? _self.internal : internal // ignore: cast_nullable_to_non_nullable -as bool, - )); -} - - -} - -/// @nodoc - - -class CalErrorKind_NonExportable extends CalErrorKind { - const CalErrorKind_NonExportable(): super._(); - - - - - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_NonExportable); -} - - -@override -int get hashCode => runtimeType.hashCode; - -@override -String toString() { - return 'CalErrorKind.nonExportable()'; -} - - -} - - - - -/// @nodoc - - -class CalErrorKind_UnsupportedAlgorithm extends CalErrorKind { - const CalErrorKind_UnsupportedAlgorithm(this.field0): super._(); - - - final String field0; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$CalErrorKind_UnsupportedAlgorithmCopyWith get copyWith => _$CalErrorKind_UnsupportedAlgorithmCopyWithImpl(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_UnsupportedAlgorithm&&(identical(other.field0, field0) || other.field0 == field0)); -} - - -@override -int get hashCode => Object.hash(runtimeType,field0); - -@override -String toString() { - return 'CalErrorKind.unsupportedAlgorithm(field0: $field0)'; -} - - -} - -/// @nodoc -abstract mixin class $CalErrorKind_UnsupportedAlgorithmCopyWith<$Res> implements $CalErrorKindCopyWith<$Res> { - factory $CalErrorKind_UnsupportedAlgorithmCopyWith(CalErrorKind_UnsupportedAlgorithm value, $Res Function(CalErrorKind_UnsupportedAlgorithm) _then) = _$CalErrorKind_UnsupportedAlgorithmCopyWithImpl; -@useResult -$Res call({ - String field0 -}); - - - - -} -/// @nodoc -class _$CalErrorKind_UnsupportedAlgorithmCopyWithImpl<$Res> - implements $CalErrorKind_UnsupportedAlgorithmCopyWith<$Res> { - _$CalErrorKind_UnsupportedAlgorithmCopyWithImpl(this._self, this._then); - - final CalErrorKind_UnsupportedAlgorithm _self; - final $Res Function(CalErrorKind_UnsupportedAlgorithm) _then; - -/// Create a copy of CalErrorKind -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) { - return _then(CalErrorKind_UnsupportedAlgorithm( -null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable -as String, - )); -} - - -} - -/// @nodoc - - -class CalErrorKind_EphemeralKeyError extends CalErrorKind { - const CalErrorKind_EphemeralKeyError(): super._(); - - - - - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_EphemeralKeyError); -} - - -@override -int get hashCode => runtimeType.hashCode; - -@override -String toString() { - return 'CalErrorKind.ephemeralKeyError()'; -} - - -} - - - - -/// @nodoc - - -class CalErrorKind_Other extends CalErrorKind { - const CalErrorKind_Other(): super._(); - - - - - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is CalErrorKind_Other); -} - - -@override -int get hashCode => runtimeType.hashCode; - -@override -String toString() { - return 'CalErrorKind.other()'; -} - - -} - - - - -// dart format on diff --git a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/factory.dart b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/factory.dart index 0a3f47c5..eec235d0 100644 --- a/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/factory.dart +++ b/cal_flutter_plugin/lib/src/rust/third_party/crypto_layer/common/factory.dart @@ -11,21 +11,18 @@ import 'crypto/algorithms/encryption.dart'; import 'crypto/algorithms/hashes.dart'; import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; -/// Returns a provider which supports the given requierements. +/// Returns a provider which supports the given requirements and is initializable. /// -/// This function returns the first provider, which supports the given requirements and has a [`ProviderImplConfig`]. +/// This function returns the first provider, which supports the given requirements (see [`ProviderConfig`]) +/// and can be initialized on the target platform with the given [`ProviderImplConfig`]. /// -/// * `conf` - A provider config that the provider must at least contain. -/// * `impl_conf_vec` - A `Vec` of [`ProviderImplConfig`]. Only providers, which have [`ProviderImplConfig`] are returned. -/// -/// # Example +/// ### Example /// ``` -/// use std::collections::HashSet; -/// -/// use crypto_layer::prelude::*; +/// # use std::collections::HashSet; +/// # use crypto_layer::prelude::*; /// -/// let specific_provider_config = ProviderImplConfig{additional_config: vec![]}; -/// let provider_config = ProviderConfig { +/// let platform_specific_provider_config = ProviderImplConfig{additional_config: vec![]}; +/// let required_capabilities = ProviderConfig { /// min_security_level: SecurityLevel::Software, /// max_security_level: SecurityLevel::Hardware, /// supported_asym_spec: HashSet::new(), @@ -33,7 +30,7 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; /// supported_hashes: HashSet::new(), /// }; /// -/// let provider_option: Option = create_provider(&provider_config, specific_provider_config); +/// let provider_option: Option = create_provider(&required_capabilities, platform_specific_provider_config); /// ``` Future createProvider({ required ProviderConfig conf, @@ -45,8 +42,10 @@ Future createProvider({ /// Returns the provider matching the given name. /// -/// * `name` - Name of the provider. See `get_name()`. -/// * `impl_config` - Specif configuration for said provider. +/// Returns `None` if the provider requested is not available on the target platform or it is not initializable. +/// +/// A providers name is a hardcoded string unique to a provider (see [`Provider::provider_name()`](crate::prelude::Provider::provider_name) +/// and [`get_all_providers()`](crate::prelude::get_all_providers)). Future createProviderFromName({ required String name, required ProviderImplConfig implConf, @@ -56,10 +55,12 @@ Future createProviderFromName({ ); /// Returns the names of all available providers. +/// +/// A provider is available if it is initializable on the target platform. Future> getAllProviders() => RustLib.instance.api.cryptoLayerCommonFactoryGetAllProviders(); -/// Returns the names and capabilities of all providers that can be initialized with the given [ProviderImplConfig]. +/// Returns the names and capabilities of all providers that can be initialized with the given [ProviderImplConfig] on the target platform. Future> getProviderCapabilities({ required ProviderImplConfig implConfig, }) => RustLib.instance.api.cryptoLayerCommonFactoryGetProviderCapabilities( diff --git a/cal_flutter_plugin/rust/src/frb_generated.rs b/cal_flutter_plugin/rust/src/frb_generated.rs index d6434df9..7586922d 100644 --- a/cal_flutter_plugin/rust/src/frb_generated.rs +++ b/cal_flutter_plugin/rust/src/frb_generated.rs @@ -3030,47 +3030,6 @@ const _: fn() = || { let _: u32 = Argon2Options.iterations; let _: u32 = Argon2Options.parallelism; } - match None::.unwrap() { - crypto_layer::common::error::CalErrorKind::NotImplemented => {} - crypto_layer::common::error::CalErrorKind::BadParameter { - description, - internal, - } => { - let _: String = description; - let _: bool = internal; - } - crypto_layer::common::error::CalErrorKind::MissingKey { key_id, key_type } => { - let _: String = key_id; - let _: crypto_layer::common::error::KeyType = key_type; - } - crypto_layer::common::error::CalErrorKind::MissingValue { - description, - internal, - } => { - let _: String = description; - let _: bool = internal; - } - crypto_layer::common::error::CalErrorKind::FailedOperation { - description, - internal, - } => { - let _: String = description; - let _: bool = internal; - } - crypto_layer::common::error::CalErrorKind::InitializationError { - description, - internal, - } => { - let _: String = description; - let _: bool = internal; - } - crypto_layer::common::error::CalErrorKind::NonExportable => {} - crypto_layer::common::error::CalErrorKind::UnsupportedAlgorithm(field0) => { - let _: String = field0; - } - crypto_layer::common::error::CalErrorKind::EphemeralKeyError => {} - crypto_layer::common::error::CalErrorKind::Other => {} - } match None::.unwrap() { crypto_layer::common::crypto::algorithms::key_derivation::KDF::Argon2d(field0) => { let _: crypto_layer::common::crypto::algorithms::key_derivation::Argon2Options = field0; @@ -3290,6 +3249,9 @@ flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); +flutter_rust_bridge::frb_generated_moi_arc_impl_value!( + flutter_rust_bridge::for_generated::RustAutoOpaqueInner +); flutter_rust_bridge::frb_generated_moi_arc_impl_value!( flutter_rust_bridge::for_generated::RustAutoOpaqueInner ); @@ -3371,6 +3333,16 @@ impl SseDecode for CalError { } } +impl SseDecode for CalErrorKind { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = , + >>::sse_decode(deserializer); + return flutter_rust_bridge::for_generated::rust_auto_opaque_decode_owned(inner); + } +} + impl SseDecode for DHExchange { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3485,6 +3457,16 @@ impl SseDecode } } +impl SseDecode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = ::sse_decode(deserializer); + return decode_rust_opaque_moi(inner); + } +} + impl SseDecode for RustOpaqueMoi> { @@ -3681,75 +3663,6 @@ impl SseDecode for bool { } } -impl SseDecode for crypto_layer::common::error::CalErrorKind { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut tag_ = ::sse_decode(deserializer); - match tag_ { - 0 => { - return crypto_layer::common::error::CalErrorKind::NotImplemented; - } - 1 => { - let mut var_description = ::sse_decode(deserializer); - let mut var_internal = ::sse_decode(deserializer); - return crypto_layer::common::error::CalErrorKind::BadParameter { - description: var_description, - internal: var_internal, - }; - } - 2 => { - let mut var_keyId = ::sse_decode(deserializer); - let mut var_keyType = - ::sse_decode(deserializer); - return crypto_layer::common::error::CalErrorKind::MissingKey { - key_id: var_keyId, - key_type: var_keyType, - }; - } - 3 => { - let mut var_description = ::sse_decode(deserializer); - let mut var_internal = ::sse_decode(deserializer); - return crypto_layer::common::error::CalErrorKind::MissingValue { - description: var_description, - internal: var_internal, - }; - } - 4 => { - let mut var_description = ::sse_decode(deserializer); - let mut var_internal = ::sse_decode(deserializer); - return crypto_layer::common::error::CalErrorKind::FailedOperation { - description: var_description, - internal: var_internal, - }; - } - 5 => { - let mut var_description = ::sse_decode(deserializer); - let mut var_internal = ::sse_decode(deserializer); - return crypto_layer::common::error::CalErrorKind::InitializationError { - description: var_description, - internal: var_internal, - }; - } - 6 => { - return crypto_layer::common::error::CalErrorKind::NonExportable; - } - 7 => { - let mut var_field0 = ::sse_decode(deserializer); - return crypto_layer::common::error::CalErrorKind::UnsupportedAlgorithm(var_field0); - } - 8 => { - return crypto_layer::common::error::CalErrorKind::EphemeralKeyError; - } - 9 => { - return crypto_layer::common::error::CalErrorKind::Other; - } - _ => { - unimplemented!(""); - } - } - } -} - impl SseDecode for crypto_layer::common::crypto::algorithms::encryption::Cipher { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -3880,20 +3793,6 @@ impl SseDecode for crypto_layer::common::config::KeySpec { } } -impl SseDecode for crypto_layer::common::error::KeyType { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { - let mut inner = ::sse_decode(deserializer); - return match inner { - 0 => crypto_layer::common::error::KeyType::Public, - 1 => crypto_layer::common::error::KeyType::Private, - 2 => crypto_layer::common::error::KeyType::PublicAndPrivate, - 3 => crypto_layer::common::error::KeyType::Symmetric, - _ => unreachable!("Invalid variant for KeyType: {}", inner), - }; - } -} - impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -4468,6 +4367,21 @@ impl flutter_rust_bridge::IntoIntoDart> for CalError { } } +// Codec=Dco (DartCObject based), see doc to use other codecs +impl flutter_rust_bridge::IntoDart for FrbWrapper { + fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { + flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self.0) + .into_dart() + } +} +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for FrbWrapper {} + +impl flutter_rust_bridge::IntoIntoDart> for CalErrorKind { + fn into_into_dart(self) -> FrbWrapper { + self.into() + } +} + // Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { @@ -4647,80 +4561,6 @@ impl } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for FrbWrapper { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self.0 { - crypto_layer::common::error::CalErrorKind::NotImplemented => { - [0.into_dart()].into_dart() - } - crypto_layer::common::error::CalErrorKind::BadParameter { - description, - internal, - } => [ - 1.into_dart(), - description.into_into_dart().into_dart(), - internal.into_into_dart().into_dart(), - ] - .into_dart(), - crypto_layer::common::error::CalErrorKind::MissingKey { key_id, key_type } => [ - 2.into_dart(), - key_id.into_into_dart().into_dart(), - key_type.into_into_dart().into_dart(), - ] - .into_dart(), - crypto_layer::common::error::CalErrorKind::MissingValue { - description, - internal, - } => [ - 3.into_dart(), - description.into_into_dart().into_dart(), - internal.into_into_dart().into_dart(), - ] - .into_dart(), - crypto_layer::common::error::CalErrorKind::FailedOperation { - description, - internal, - } => [ - 4.into_dart(), - description.into_into_dart().into_dart(), - internal.into_into_dart().into_dart(), - ] - .into_dart(), - crypto_layer::common::error::CalErrorKind::InitializationError { - description, - internal, - } => [ - 5.into_dart(), - description.into_into_dart().into_dart(), - internal.into_into_dart().into_dart(), - ] - .into_dart(), - crypto_layer::common::error::CalErrorKind::NonExportable => [6.into_dart()].into_dart(), - crypto_layer::common::error::CalErrorKind::UnsupportedAlgorithm(field0) => { - [7.into_dart(), field0.into_into_dart().into_dart()].into_dart() - } - crypto_layer::common::error::CalErrorKind::EphemeralKeyError => { - [8.into_dart()].into_dart() - } - crypto_layer::common::error::CalErrorKind::Other => [9.into_dart()].into_dart(), - _ => { - unimplemented!(""); - } - } - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for FrbWrapper -{ -} -impl flutter_rust_bridge::IntoIntoDart> - for crypto_layer::common::error::CalErrorKind -{ - fn into_into_dart(self) -> FrbWrapper { - self.into() - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { @@ -4887,29 +4727,6 @@ impl flutter_rust_bridge::IntoIntoDart { - fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { - match self.0 { - crypto_layer::common::error::KeyType::Public => 0.into_dart(), - crypto_layer::common::error::KeyType::Private => 1.into_dart(), - crypto_layer::common::error::KeyType::PublicAndPrivate => 2.into_dart(), - crypto_layer::common::error::KeyType::Symmetric => 3.into_dart(), - _ => unreachable!(), - } - } -} -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive - for FrbWrapper -{ -} -impl flutter_rust_bridge::IntoIntoDart> - for crypto_layer::common::error::KeyType -{ - fn into_into_dart(self) -> FrbWrapper { - self.into() - } -} -// Codec=Dco (DartCObject based), see doc to use other codecs impl flutter_rust_bridge::IntoDart for FrbWrapper { @@ -5213,6 +5030,13 @@ impl SseEncode for CalError { } } +impl SseEncode for CalErrorKind { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >>::sse_encode(flutter_rust_bridge::for_generated::rust_auto_opaque_encode::<_, MoiArc<_>>(self), serializer); + } +} + impl SseEncode for DHExchange { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -5319,6 +5143,17 @@ impl SseEncode } } +impl SseEncode + for RustOpaqueMoi> +{ + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + let (ptr, size) = self.sse_encode_raw(); + ::sse_encode(ptr, serializer); + ::sse_encode(size, serializer); + } +} + impl SseEncode for RustOpaqueMoi> { @@ -5501,70 +5336,6 @@ impl SseEncode for bool { } } -impl SseEncode for crypto_layer::common::error::CalErrorKind { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - match self { - crypto_layer::common::error::CalErrorKind::NotImplemented => { - ::sse_encode(0, serializer); - } - crypto_layer::common::error::CalErrorKind::BadParameter { - description, - internal, - } => { - ::sse_encode(1, serializer); - ::sse_encode(description, serializer); - ::sse_encode(internal, serializer); - } - crypto_layer::common::error::CalErrorKind::MissingKey { key_id, key_type } => { - ::sse_encode(2, serializer); - ::sse_encode(key_id, serializer); - ::sse_encode(key_type, serializer); - } - crypto_layer::common::error::CalErrorKind::MissingValue { - description, - internal, - } => { - ::sse_encode(3, serializer); - ::sse_encode(description, serializer); - ::sse_encode(internal, serializer); - } - crypto_layer::common::error::CalErrorKind::FailedOperation { - description, - internal, - } => { - ::sse_encode(4, serializer); - ::sse_encode(description, serializer); - ::sse_encode(internal, serializer); - } - crypto_layer::common::error::CalErrorKind::InitializationError { - description, - internal, - } => { - ::sse_encode(5, serializer); - ::sse_encode(description, serializer); - ::sse_encode(internal, serializer); - } - crypto_layer::common::error::CalErrorKind::NonExportable => { - ::sse_encode(6, serializer); - } - crypto_layer::common::error::CalErrorKind::UnsupportedAlgorithm(field0) => { - ::sse_encode(7, serializer); - ::sse_encode(field0, serializer); - } - crypto_layer::common::error::CalErrorKind::EphemeralKeyError => { - ::sse_encode(8, serializer); - } - crypto_layer::common::error::CalErrorKind::Other => { - ::sse_encode(9, serializer); - } - _ => { - unimplemented!(""); - } - } - } -} - impl SseEncode for crypto_layer::common::crypto::algorithms::encryption::Cipher { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -5688,24 +5459,6 @@ impl SseEncode for crypto_layer::common::config::KeySpec { } } -impl SseEncode for crypto_layer::common::error::KeyType { - // Codec=Sse (Serialization based), see doc to use other codecs - fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { - ::sse_encode( - match self { - crypto_layer::common::error::KeyType::Public => 0, - crypto_layer::common::error::KeyType::Private => 1, - crypto_layer::common::error::KeyType::PublicAndPrivate => 2, - crypto_layer::common::error::KeyType::Symmetric => 3, - _ => { - unimplemented!(""); - } - }, - serializer, - ); - } -} - impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -6155,6 +5908,20 @@ mod io { MoiArc::>::decrement_strong_count(ptr as _); } + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_cal_flutter_plugin_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[unsafe(no_mangle)] + pub extern "C" fn frbgen_cal_flutter_plugin_rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[unsafe(no_mangle)] pub extern "C" fn frbgen_cal_flutter_plugin_rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( ptr: *const std::ffi::c_void, @@ -6344,6 +6111,20 @@ mod web { MoiArc::>::decrement_strong_count(ptr as _); } + #[wasm_bindgen] + pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::increment_strong_count(ptr as _); + } + + #[wasm_bindgen] + pub fn rust_arc_decrement_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerCalErrorKind( + ptr: *const std::ffi::c_void, + ) { + MoiArc::>::decrement_strong_count(ptr as _); + } + #[wasm_bindgen] pub fn rust_arc_increment_strong_count_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerDHExchange( ptr: *const std::ffi::c_void,