From 7dcf71dbaa5de15750e3084a7ffaccbeb41b04b0 Mon Sep 17 00:00:00 2001 From: Manuthor Date: Fri, 27 Sep 2024 03:53:00 +0200 Subject: [PATCH] fix: reenable wrap/unwrap on ckms by linking statically on openssl --- .../{windows_build.ps1 => cargo_build.ps1} | 76 +++--- .github/workflows/build_all.yml | 1 + .github/workflows/build_windows.yml | 40 ++- .pre-commit-config.yaml | 18 +- Cargo.lock | 8 +- Cargo.toml | 10 +- README.md | 85 +++--- crate/cli/Cargo.toml | 7 +- crate/cli/src/actions/cover_crypt/keys/mod.rs | 8 +- .../src/actions/elliptic_curves/keys/mod.rs | 8 +- crate/cli/src/actions/rsa/keys/mod.rs | 8 +- crate/cli/src/actions/shared/mod.rs | 4 - crate/cli/src/actions/shared/unwrap_key.rs | 4 + crate/cli/src/actions/symmetric/keys/mod.rs | 8 +- crate/cli/src/tests/shared/mod.rs | 2 +- crate/cli/src/tests/shared/wrap_unwrap.rs | 34 ++- crate/cli/src/tests/utils/extract_uids.rs | 9 +- crate/client/Cargo.toml | 13 +- crate/kmip/Cargo.toml | 9 +- .../src/crypto/cover_crypt/kmip_requests.rs | 13 +- crate/kmip/src/crypto/elliptic_curves/mod.rs | 1 - .../src/crypto/elliptic_curves/operation.rs | 18 +- crate/kmip/src/crypto/mod.rs | 3 - crate/kmip/src/crypto/password_derivation.rs | 1 + crate/kmip/src/crypto/rsa/mod.rs | 4 - crate/kmip/src/crypto/secret.rs | 3 - crate/kmip/src/crypto/symmetric/mod.rs | 5 - crate/kmip/src/crypto/wrap/mod.rs | 6 +- crate/kmip/src/crypto/wrap/unwrap_key.rs | 14 + crate/kmip/src/crypto/wrap/wrap_key.rs | 2 - crate/kmip/src/error/mod.rs | 1 - crate/kmip/src/kmip/extra/mod.rs | 1 - crate/kmip/src/kmip/kmip_data_structures.rs | 4 +- crate/kmip/src/kmip/kmip_types.rs | 6 +- crate/kmip/src/lib.rs | 1 - crate/logger/Cargo.toml | 2 +- crate/pkcs11/module/Cargo.toml | 11 +- crate/pkcs11/provider/Cargo.toml | 4 +- crate/pyo3/Cargo.toml | 2 +- crate/server/Cargo.toml | 8 +- documentation/docs/cli/main_commands.md | 248 ++++++++++++++++-- vcpkg.json | 14 + vcpkg_fips.json | 15 ++ 43 files changed, 486 insertions(+), 253 deletions(-) rename .github/scripts/{windows_build.ps1 => cargo_build.ps1} (52%) create mode 100644 vcpkg.json create mode 100644 vcpkg_fips.json diff --git a/.github/scripts/windows_build.ps1 b/.github/scripts/cargo_build.ps1 similarity index 52% rename from .github/scripts/windows_build.ps1 rename to .github/scripts/cargo_build.ps1 index 1699df48..5cfd5400 100644 --- a/.github/scripts/windows_build.ps1 +++ b/.github/scripts/cargo_build.ps1 @@ -1,6 +1,6 @@ -function Build-Project { +function BuildProject { param ( - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] [ValidateSet("debug", "release")] [string]$BuildType ) @@ -8,47 +8,57 @@ function Build-Project { # Add target rustup target add x86_64-pc-windows-msvc - # Build `ckms` - cd crate/cli - if ($BuildType -eq "release") { - cargo build --release --target x86_64-pc-windows-msvc - } else { - cargo build --target x86_64-pc-windows-msvc - } - - # Build pkcs11 provider - cd ../pkcs11/provider - if ($BuildType -eq "release") { - cargo build --release --target x86_64-pc-windows-msvc - } else { - cargo build --target x86_64-pc-windows-msvc - } - cd ../../.. - - # Set up environment for vcpkg - $env:VCPKG_INSTALLATION_ROOT - dir $env:VCPKG_INSTALLATION_ROOT - vcpkg install openssl[fips,weak-ssl-ciphers] - - vcpkg integrate install - $env:VCPKGRS_DYNAMIC = 1 - $env:OPENSSL_DIR = "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows" + $env:OPENSSL_DIR = "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows-static" Get-ChildItem -Recurse $env:OPENSSL_DIR - # Copy fips.dll to the specified directory - Copy-Item -Path "C:/vcpkg/packages/openssl_x64-windows/bin/*.dll" -Destination "D:/a/kms/kms" + # Build pkcs11 provider + Get-ChildItem crate\pkcs11\provider + if ($BuildType -eq "release") { + cargo build --release --target x86_64-pc-windows-msvc + } + else { + cargo build --target x86_64-pc-windows-msvc + } + Get-ChildItem ..\..\.. + + # Build `ckms` + Get-ChildItem crate\cli + if ($BuildType -eq "release") { + cargo build --release --target x86_64-pc-windows-msvc + } + else { + cargo build --target x86_64-pc-windows-msvc + } + Get-ChildItem ..\.. + + # Check dynamic links + $output = & "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\dumpbin.exe" /dependents target\x86_64-pc-windows-msvc\$BuildType\ckms.exe | Select-String "libcrypto" + if ($output) { + throw "OpenSSL (libcrypto) found in dynamic dependencies. Error: $output" + } # Build `server` - cd crate/server + Set-Location crate\server if ($BuildType -eq "release") { cargo build --release --target x86_64-pc-windows-msvc cargo test --release --target x86_64-pc-windows-msvc -p cosmian_kms_server -- --nocapture --skip test_sql_cipher --skip test_sqlite --skip test_mysql --skip test_postgresql --skip test_redis --skip google_cse - } else { + } + else { cargo build --target x86_64-pc-windows-msvc cargo test --target x86_64-pc-windows-msvc -p cosmian_kms_server -- --nocapture --skip test_sql_cipher --skip test_sqlite --skip test_mysql --skip test_postgresql --skip test_redis --skip google_cse } + Get-ChildItem ..\.. + + # Check dynamic links + $output = & "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\dumpbin.exe" /dependents target\x86_64-pc-windows-msvc\$BuildType\cosmian_kms_server.exe | Select-String "libcrypto" + if ($output) { + throw "OpenSSL (libcrypto) found in dynamic dependencies. Error: $output" + } + + exit 0 } + # Example usage: -# Build-Project -BuildType debug -# Build-Project -BuildType release +# BuildProject -BuildType debug +# BuildProject -BuildType release diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index de88f2af..7fd6d08b 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -105,6 +105,7 @@ jobs: /usr/local/openssl/lib/ossl-modules/legacy.dylib windows-2022: + if: inputs.debug_or_release == 'release' uses: ./.github/workflows/build_windows.yml with: toolchain: ${{ inputs.toolchain }} diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index 13dbde94..4647234c 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -29,17 +29,53 @@ jobs: toolchain: ${{ inputs.toolchain }} components: rustfmt, clippy + # - name: Discover dumpbin location + # shell: pwsh + # run: | + # Get-ChildItem -Recurse "C:\Program Files\Microsoft Visual Studio" + + - name: Discover environment variables on Runner + shell: pwsh + run: | + Get-ChildItem env: + + - name: Locate VCPKG_INSTALLATION_ROOT + shell: pwsh + run: | + Get-ChildItem $env:VCPKG_INSTALLATION_ROOT + + - name: Build static OpenSSL + shell: pwsh + run: | + vcpkg install --triplet x64-windows-static + vcpkg integrate install + + Get-ChildItem -Recurse "$env:VCPKG_INSTALLATION_ROOT\packages" + - name: Build shell: pwsh run: | - . .\.github\scripts\windows_build.ps1 - Build-Project -BuildType ${{ inputs.debug_or_release }} + . .\.github\scripts\cargo_build.ps1 + BuildProject -BuildType ${{ inputs.debug_or_release }} env: # Google variables TEST_GOOGLE_OAUTH_CLIENT_ID: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_ID }} TEST_GOOGLE_OAUTH_CLIENT_SECRET: ${{ secrets.TEST_GOOGLE_OAUTH_CLIENT_SECRET }} TEST_GOOGLE_OAUTH_REFRESH_TOKEN: ${{ secrets.TEST_GOOGLE_OAUTH_REFRESH_TOKEN }} + - name: Build FIPS OpenSSL + shell: pwsh + run: | + Copy-Item -Path "vcpkg_fips.json" -Destination "vcpkg.json" + vcpkg install + vcpkg integrate install + + Get-ChildItem -Recurse "$env:VCPKG_INSTALLATION_ROOT\packages" + + # Copy fips.dll to the specified directory + Copy-Item -Path "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows\bin\legacy.dll" -Destination "D:\a\kms\kms" + Copy-Item -Path "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows\bin\fips.dll" -Destination "D:\a\kms\kms" + - name: Upload KMS for windows-2022 uses: actions/upload-artifact@v3 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e64f6309..5b88715e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,15 +16,15 @@ repos: stages: [commit-msg] args: [] # optional: list of Conventional Commits types to allow e.g. [feat, fix, ci, chore, test] - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v4.0.0-alpha.8 - hooks: - - id: prettier - stages: [commit] - exclude_types: - - yaml - - markdown - exclude: documentation/theme_overrides|.cargo_check + # - repo: https://github.com/pre-commit/mirrors-prettier + # rev: v4.0.0-alpha.8 + # hooks: + # - id: prettier + # stages: [commit] + # exclude_types: + # - yaml + # - markdown + # exclude: documentation/theme_overrides|.cargo_check - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.40.0 diff --git a/Cargo.lock b/Cargo.lock index 274b6d94..1464b8f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3339,9 +3339,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", "syn", @@ -4416,9 +4416,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 4917873d..242c1d60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,23 +57,29 @@ base64 = "0.21" chrono = "0.4" clap = { version = "4.5", default-features = false } cloudproof = "3.0" +der = { version = "0.7", default-features = false } env_logger = "0.11" -hex = "0.4" +hex = { version = "0.4", default-features = false } +log = { version = "0.4", default-features = false } native-tls = "0.2" num_cpus = "1.13" num-bigint-dig = { version = "0.8", default-features = false } openssl = { version = "0.10", default-features = false } +pem = "3.0" pyo3 = { version = "0.20", default-features = false } reqwest = { version = "0.11", default-features = false } rustls = "0.21" serde = "1.0" serde_json = "1.0" +sha3 = { version = "0.10", default-features = false} strum = { version = "0.25", default-features = false } thiserror = "1.0" time = "0.3" tokio = { version = "1.39", default-features = false } +tracing-subscriber = { version = "0.3", default-features = false } tracing = "0.1" url = "2.5" uuid = "1.10" +x509-cert = { version = "0.2.5", default-features = false } x509-parser = "0.16" -zeroize = "1.8" +zeroize = { version = "1.8", default-features = false } diff --git a/README.md b/README.md index 44b5a732..7cd5294b 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,10 @@ Keys can be wrapped and unwrapped using RSA, ECIES or RFC5649/AES KWP. - [Example](#example) - [Repository content](#repository-content) - [Building the KMS](#building-the-kms) - - [Linux](#linux) - - [MacOS](#macos) + - [Linux or MacOS (CPU Intel or MacOs ARM)](#linux-or-macos-cpu-intel-or-macos-arm) - [Windows](#windows) - - [Build the Docker container](#build-the-docker-container) + - [Build the KMS](#build-the-kms) + - [Build the Docker Ubuntu container](#build-the-docker-ubuntu-container) - [Running the unit and integration tests](#running-the-unit-and-integration-tests) - [Development: running the server with cargo](#development-running-the-server-with-cargo) - [Setup as a `Supervisor` service](#setup-as-a-supervisor-service) @@ -62,9 +62,7 @@ docker run -p 9998:9998 --name kms ghcr.io/cosmian/kms:4.18.0 ``` Then, use the CLI to issue commands to the KMS. -The CLI, called `ckms`, can be either downloaded -from [Cosmian packages](https://package.cosmian.com/kms/) or built and launched from this GitHub -project by running +The CLI, called `ckms`, can be either downloaded from [Cosmian packages](https://package.cosmian.com/kms/) or built and launched from this GitHub project by running ```sh cargo run --bin ckms -- --help @@ -72,7 +70,6 @@ cargo run --bin ckms -- --help ### Example -1. Create a 256-bit symmetric key 1. Create a 256-bit symmetric key ```sh @@ -80,6 +77,9 @@ cargo run --bin ckms -- --help ... The symmetric key was successfully generated. Unique identifier: 87e9e2a8-4538-4701-aa8c-e3af94e44a9e + + Tags: + - my-key-file ``` 2. Encrypt the `image.png` file with AES GCM using the key @@ -121,38 +121,19 @@ directory. ## Building the KMS -To avoid the _additive feature_ issues, the main artifacts - the CLI, the KMS server, and the -PKCS11 provider - should directly be built using `cargo build --release`within their own crate, not -from the project root. +OpenSSL v3.2.0 is required to build the KMS. -In addition, the KMS server must be built against a local installation of OpenSSL 3. Other -artifacts do not have this requirement. +### Linux or MacOS (CPU Intel or MacOs ARM) -### Linux - -Unless you require a FIPS-certified cryptographic module, the distribution provided by OpenSSL -should be enough. - -You need to have the development packages of OpenSSL installed. On Ubuntu, you can install them -with: +Build OpenSSL v3.2.0 with the following commands: ```sh -sudo apt install libssl-dev +export OPENSSL_DIR=/usr/local/openssl +sudo mkdir -p ${OPENSSL_DIR} +sudo chown -R $USER ${OPENSSL_DIR} +bash .github/scripts/local_ossl_instl.sh ${OPENSSL_DIR} ``` -You may also need to install the `pkg-config` package (on Ubuntu server typically). - -### MacOS - -Install OpenSSL 3 with Homebrew: - -```sh -brew install openssl@3 -``` - -The builder should find it automatically; if not, you can set the `OPENSSL_DIR` environment variable -to the OpenSSL installation directory. - ### Windows 1. Install Visual Studio Community with the C++ workload and clang support. @@ -160,22 +141,40 @@ to the OpenSSL installation directory. 3. Install `vcpkg` following [these instructions](https://github.com/Microsoft/vcpkg#quick-start-windows) -4. Then install OpenSSL 3: +4. Then install OpenSSL 3.2.0: + +The files `vcpkg.json` and `vcpkg_fips.json` are provided in the repository to install OpenSSL v3.2.0: ```powershell -vcpkg.exe install openssl[fips,weak-ssl-ciphers] -vcpkg.exe integrate install -set VCPKGRS_DYNAMIC=1 -$env:OPENSSL_DIR = "\installed\>" +vcpkg install --triplet x64-windows-static +vcpkg integrate install +$env:OPENSSL_DIR = "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows-static" ``` -where `` is the path to the vcpkg installation directory, -and `` is the architecture e.g `x64-windows`, `arm64-windows`, etc. +For a FIPS compliant build, use the following commands (in order to build fips.dll), run also: -To run the server from the command line, add `\installed\\bin` to the `PATH` -environment variable. +```powershell +Copy-Item -Path "vcpkg_fips.json" -Destination "vcpkg.json" +vcpkg install +vcpkg integrate install +``` -### Build the Docker container +### Build the KMS + +Once OpenSSL is installed, you can build the KMS. To avoid the _additive feature_ issues, the main artifacts - the CLI, the KMS server and the PKCS11 provider - should directly be built using `cargo build --release` within their own crate, not +from the project root. + +Build the server and CLI binaries: + +```sh +cd crate/server +cargo build --release +cd ../.. +cd crate/ckms +cargo build --release +``` + +### Build the Docker Ubuntu container You can build a docker containing the KMS server as follows: diff --git a/crate/cli/Cargo.toml b/crate/cli/Cargo.toml index 9b97f35c..4709e3af 100644 --- a/crate/cli/Cargo.toml +++ b/crate/cli/Cargo.toml @@ -22,7 +22,6 @@ doctest = false # default is used to run tests with the remote kms test server. Otherwise, the test runs a local kms server. default = [] fips = ["cosmian_kms_client/fips"] -openssl = ["cosmian_kms_client/openssl"] [dependencies] actix-web = { workspace = true, features = ["macros"] } @@ -39,13 +38,13 @@ clap = { workspace = true, features = [ cloudproof = { workspace = true } cosmian_kms_client = { path = "../client" } cosmian_logger = { path = "../logger" } -der = { version = "0.7", features = ["pem"] } +der = { workspace = true, features = ["pem"] } hex = { workspace = true } jwt-simple = { version = "0.12", default-features = false, features = [ "pure-rust", ] } oauth2 = { version = "4.4", features = ["reqwest"] } -pem = "3.0" +pem = { workspace = true } reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -55,7 +54,7 @@ tokio = { workspace = true, features = ["full"] } tracing = { workspace = true } url = { workspace = true } uuid = { workspace = true } -x509-cert = { version = "0.2", features = ["pem"] } +x509-cert = { workspace = true, features = ["pem"] } zeroize = { workspace = true } [dev-dependencies] diff --git a/crate/cli/src/actions/cover_crypt/keys/mod.rs b/crate/cli/src/actions/cover_crypt/keys/mod.rs index 8c132a35..32252e73 100644 --- a/crate/cli/src/actions/cover_crypt/keys/mod.rs +++ b/crate/cli/src/actions/cover_crypt/keys/mod.rs @@ -8,10 +8,8 @@ use self::{ rekey::{PruneAction, RekeyAction}, revoke_key::RevokeKeyAction, }; -#[cfg(feature = "openssl")] -use crate::actions::shared::{UnwrapKeyAction, WrapKeyAction}; use crate::{ - actions::shared::{ExportKeyAction, ImportKeyAction}, + actions::shared::{ExportKeyAction, ImportKeyAction, UnwrapKeyAction, WrapKeyAction}, error::result::CliResult, }; @@ -28,9 +26,7 @@ pub enum KeysCommands { CreateUserKey(CreateUserKeyAction), Export(ExportKeyAction), Import(ImportKeyAction), - #[cfg(feature = "openssl")] Wrap(WrapKeyAction), - #[cfg(feature = "openssl")] Unwrap(UnwrapKeyAction), Revoke(RevokeKeyAction), Destroy(DestroyKeyAction), @@ -45,9 +41,7 @@ impl KeysCommands { Self::CreateUserKey(action) => action.run(kms_rest_client).await?, Self::Export(action) => action.run(kms_rest_client).await?, Self::Import(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Wrap(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Unwrap(action) => action.run(kms_rest_client).await?, Self::Revoke(action) => action.run(kms_rest_client).await?, Self::Destroy(action) => action.run(kms_rest_client).await?, diff --git a/crate/cli/src/actions/elliptic_curves/keys/mod.rs b/crate/cli/src/actions/elliptic_curves/keys/mod.rs index f3e9455b..5df393f0 100644 --- a/crate/cli/src/actions/elliptic_curves/keys/mod.rs +++ b/crate/cli/src/actions/elliptic_curves/keys/mod.rs @@ -5,10 +5,8 @@ use self::{ create_key_pair::CreateKeyPairAction, destroy_key::DestroyKeyAction, revoke_key::RevokeKeyAction, }; -#[cfg(feature = "openssl")] -use crate::actions::shared::{UnwrapKeyAction, WrapKeyAction}; use crate::{ - actions::shared::{ExportKeyAction, ImportKeyAction}, + actions::shared::{ExportKeyAction, ImportKeyAction, UnwrapKeyAction, WrapKeyAction}, error::result::CliResult, }; @@ -22,9 +20,7 @@ pub enum KeysCommands { Create(CreateKeyPairAction), Export(ExportKeyAction), Import(ImportKeyAction), - #[cfg(feature = "openssl")] Wrap(WrapKeyAction), - #[cfg(feature = "openssl")] Unwrap(UnwrapKeyAction), Revoke(RevokeKeyAction), Destroy(DestroyKeyAction), @@ -36,9 +32,7 @@ impl KeysCommands { Self::Create(action) => action.run(kms_rest_client).await?, Self::Export(action) => action.run(kms_rest_client).await?, Self::Import(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Wrap(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Unwrap(action) => action.run(kms_rest_client).await?, Self::Revoke(action) => action.run(kms_rest_client).await?, Self::Destroy(action) => action.run(kms_rest_client).await?, diff --git a/crate/cli/src/actions/rsa/keys/mod.rs b/crate/cli/src/actions/rsa/keys/mod.rs index b3d9f798..f9e65dad 100644 --- a/crate/cli/src/actions/rsa/keys/mod.rs +++ b/crate/cli/src/actions/rsa/keys/mod.rs @@ -5,10 +5,8 @@ use self::{ create_key_pair::CreateKeyPairAction, destroy_key::DestroyKeyAction, revoke_key::RevokeKeyAction, }; -#[cfg(feature = "openssl")] -use crate::actions::shared::{UnwrapKeyAction, WrapKeyAction}; use crate::{ - actions::shared::{ExportKeyAction, ImportKeyAction}, + actions::shared::{ExportKeyAction, ImportKeyAction, UnwrapKeyAction, WrapKeyAction}, error::result::CliResult, }; @@ -22,9 +20,7 @@ pub enum KeysCommands { Create(CreateKeyPairAction), Export(ExportKeyAction), Import(ImportKeyAction), - #[cfg(feature = "openssl")] Wrap(WrapKeyAction), - #[cfg(feature = "openssl")] Unwrap(UnwrapKeyAction), Revoke(RevokeKeyAction), Destroy(DestroyKeyAction), @@ -36,9 +32,7 @@ impl KeysCommands { Self::Create(action) => action.run(kms_rest_client).await?, Self::Export(action) => action.run(kms_rest_client).await?, Self::Import(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Wrap(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Unwrap(action) => action.run(kms_rest_client).await?, Self::Revoke(action) => action.run(kms_rest_client).await?, Self::Destroy(action) => action.run(kms_rest_client).await?, diff --git a/crate/cli/src/actions/shared/mod.rs b/crate/cli/src/actions/shared/mod.rs index 2e5d0363..d4e45769 100644 --- a/crate/cli/src/actions/shared/mod.rs +++ b/crate/cli/src/actions/shared/mod.rs @@ -6,10 +6,8 @@ mod locate; mod set_attributes; pub mod utils; -#[cfg(feature = "openssl")] mod wrap_key; -#[cfg(feature = "openssl")] mod unwrap_key; pub use delete_attributes::DeleteAttributesAction; @@ -18,9 +16,7 @@ pub use get_attributes::GetAttributesAction; pub use import_key::ImportKeyAction; pub use locate::LocateObjectsAction; pub use set_attributes::{SetAttributesAction, SetOrDeleteAttributes, VendorAttributeCli}; -#[cfg(feature = "openssl")] pub use unwrap_key::UnwrapKeyAction; -#[cfg(feature = "openssl")] pub use wrap_key::WrapKeyAction; /// The size of a symmetric wrapping key in bytes derived from a password diff --git a/crate/cli/src/actions/shared/unwrap_key.rs b/crate/cli/src/actions/shared/unwrap_key.rs index 9735b3d2..6758ff0e 100644 --- a/crate/cli/src/actions/shared/unwrap_key.rs +++ b/crate/cli/src/actions/shared/unwrap_key.rs @@ -10,6 +10,7 @@ use cosmian_kms_client::{ export_object, read_object_from_json_ttlv_file, write_kmip_object_to_file, ExportObjectParams, KmsClient, }; +use tracing::trace; use crate::{ actions::console, @@ -90,15 +91,18 @@ impl UnwrapKeyAction { // if the key must be unwrapped, prepare the unwrapping key let unwrapping_key = if let Some(b64) = &self.unwrap_key_b64 { + trace!("unwrap using a base64 encoded key: {b64}"); let key_bytes = general_purpose::STANDARD .decode(b64) .with_context(|| "failed decoding the unwrap key")?; create_symmetric_key_kmip_object(&key_bytes, CryptographicAlgorithm::AES)? } else if let Some(key_id) = &self.unwrap_key_id { + trace!("unwrap using the KMS server with the unique identifier of the unwrapping key"); export_object(kms_rest_client, key_id, ExportObjectParams::default()) .await? .0 } else if let Some(key_file) = &self.unwrap_key_file { + trace!("unwrap using a key file path"); read_object_from_json_ttlv_file(key_file)? } else { cli_bail!("one of the unwrapping options must be specified"); diff --git a/crate/cli/src/actions/symmetric/keys/mod.rs b/crate/cli/src/actions/symmetric/keys/mod.rs index 52f2fa3a..1002f825 100644 --- a/crate/cli/src/actions/symmetric/keys/mod.rs +++ b/crate/cli/src/actions/symmetric/keys/mod.rs @@ -5,10 +5,8 @@ use self::{ create_key::CreateKeyAction, destroy_key::DestroyKeyAction, rekey::ReKeyAction, revoke_key::RevokeKeyAction, }; -#[cfg(feature = "openssl")] -use crate::actions::shared::{UnwrapKeyAction, WrapKeyAction}; use crate::{ - actions::shared::{ExportKeyAction, ImportKeyAction}, + actions::shared::{ExportKeyAction, ImportKeyAction, UnwrapKeyAction, WrapKeyAction}, error::result::CliResult, }; @@ -24,9 +22,7 @@ pub enum KeysCommands { ReKey(ReKeyAction), Export(ExportKeyAction), Import(ImportKeyAction), - #[cfg(feature = "openssl")] Wrap(WrapKeyAction), - #[cfg(feature = "openssl")] Unwrap(UnwrapKeyAction), Revoke(RevokeKeyAction), Destroy(DestroyKeyAction), @@ -39,9 +35,7 @@ impl KeysCommands { Self::ReKey(action) => action.run(kms_rest_client).await?, Self::Export(action) => action.run(kms_rest_client).await?, Self::Import(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Wrap(action) => action.run(kms_rest_client).await?, - #[cfg(feature = "openssl")] Self::Unwrap(action) => action.run(kms_rest_client).await?, Self::Revoke(action) => action.run(kms_rest_client).await?, Self::Destroy(action) => action.run(kms_rest_client).await?, diff --git a/crate/cli/src/tests/shared/mod.rs b/crate/cli/src/tests/shared/mod.rs index 9f6efe97..1e3baaf3 100644 --- a/crate/cli/src/tests/shared/mod.rs +++ b/crate/cli/src/tests/shared/mod.rs @@ -18,5 +18,5 @@ mod import_export_wrapping; mod locate; mod revoke; mod set_attributes; -#[cfg(all(not(feature = "fips"), feature = "openssl"))] +#[cfg(not(feature = "fips"))] mod wrap_unwrap; diff --git a/crate/cli/src/tests/shared/wrap_unwrap.rs b/crate/cli/src/tests/shared/wrap_unwrap.rs index 54ce94a7..65bb812d 100644 --- a/crate/cli/src/tests/shared/wrap_unwrap.rs +++ b/crate/cli/src/tests/shared/wrap_unwrap.rs @@ -9,14 +9,15 @@ use cloudproof::reexport::crypto_core::{ reexport::rand_core::{RngCore, SeedableRng}, CsRng, }; -use cosmian_kmip::kmip::kmip_types::{EncodingOption, WrappingMethod}; use cosmian_kms_client::{ cosmian_kmip::kmip::kmip_types::{EncodingOption, WrappingMethod}, read_object_from_json_ttlv_file, KMS_CLI_CONF_ENV, }; +use cosmian_logger::log_utils::log_init; use kms_test_server::{start_default_test_kms_server, TestsContext}; use tempfile::TempDir; +use super::ExportKeyParams; use crate::{ error::{result::CliResult, CliError}, tests::{ @@ -30,7 +31,7 @@ use crate::{ }; #[allow(clippy::too_many_arguments)] -pub fn wrap( +pub(crate) fn wrap( cli_conf_path: &str, sub_command: &str, key_file_in: &Path, @@ -69,7 +70,6 @@ pub fn wrap( cmd.arg(sub_command).args(args); let output = recover_cmd_logs(&mut cmd); - println!("wrap output: {output:?}"); if output.status.success() { let wrap_output = std::str::from_utf8(&output.stdout)?; let b64_wrapping_key = extract_wrapping_key(wrap_output) @@ -83,7 +83,7 @@ pub fn wrap( } #[allow(clippy::too_many_arguments)] -pub fn unwrap( +pub(crate) fn unwrap( cli_conf_path: &str, sub_command: &str, key_file_in: &Path, @@ -130,7 +130,8 @@ pub fn unwrap( } #[tokio::test] -pub async fn test_password_wrap_import() -> CliResult<()> { +pub(crate) async fn test_password_wrap_import() -> CliResult<()> { + log_init(option_env!("RUST_LOG")); let ctx = start_default_test_kms_server().await; // CC @@ -147,14 +148,14 @@ pub async fn test_password_wrap_import() -> CliResult<()> { create_ec_key_pair(&ctx.owner_client_conf_path, "nist-p256", &[])?; password_wrap_import_test(ctx, "ec", &private_key_id)?; - // syn + // sym let key_id = create_symmetric_key(&ctx.owner_client_conf_path, None, None, None, &[])?; password_wrap_import_test(ctx, "sym", &key_id)?; Ok(()) } -pub fn password_wrap_import_test( +pub(crate) fn password_wrap_import_test( ctx: &TestsContext, sub_command: &str, private_key_id: &str, @@ -163,18 +164,13 @@ pub fn password_wrap_import_test( // Export let key_file = temp_dir.path().join("master_private.key"); - export_key( - &ctx.owner_client_conf_path, - sub_command, - private_key_id, - key_file.to_str().unwrap(), - None, - false, - None, - false, - None, - None, - )?; + export_key(ExportKeyParams { + cli_conf_path: ctx.owner_client_conf_path.to_string(), + sub_command: sub_command.to_owned(), + key_id: private_key_id.to_owned(), + key_file: key_file.to_str().unwrap().to_owned(), + ..Default::default() + })?; let object = read_object_from_json_ttlv_file(&key_file)?; let key_bytes = object.key_block()?.key_bytes()?; diff --git a/crate/cli/src/tests/utils/extract_uids.rs b/crate/cli/src/tests/utils/extract_uids.rs index eff58a4d..31a0cec0 100644 --- a/crate/cli/src/tests/utils/extract_uids.rs +++ b/crate/cli/src/tests/utils/extract_uids.rs @@ -68,5 +68,12 @@ pub(crate) fn extract_locate_uids(text: &str) -> Option> { /// Extract the wrapping key from a test. #[cfg(not(feature = "fips"))] pub(crate) fn extract_wrapping_key(text: &str) -> Option<&str> { - extract_uid(text, "Wrapping key") + let formatted = r"Wrapping key:\s*(?P[a-zA-Z0-9+/=]+)"; + let uid_regex = RegexBuilder::new(formatted) + .multi_line(true) + .build() + .unwrap(); + uid_regex + .captures(text) + .and_then(|cap| cap.name("uid").map(|uid| uid.as_str())) } diff --git a/crate/client/Cargo.toml b/crate/client/Cargo.toml index 6b0b79f5..537773ef 100644 --- a/crate/client/Cargo.toml +++ b/crate/client/Cargo.toml @@ -14,22 +14,21 @@ doctest = false [features] fips = ["cosmian_kmip/fips"] -openssl = ["cosmian_kmip/openssl"] [dependencies] base64 = { workspace = true } cloudproof = { workspace = true } cosmian_kmip = { path = "../kmip", default-features = true } -der = "0.7.9" -log = "0.4" -pem = "3.0.4" +der = { workspace = true } +log = { workspace = true } +pem = { workspace = true } reqwest = { workspace = true, features = ["default", "json", "native-tls"] } rustls = { workspace = true, features = ["dangerous_configuration"] } serde = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } -tracing = "0.1" +tracing = { workspace = true } url = { workspace = true } webpki-roots = "0.22" -x509-cert = "0.2.5" -zeroize = "1.8.1" +x509-cert = { workspace = true } +zeroize = { workspace = true } diff --git a/crate/kmip/Cargo.toml b/crate/kmip/Cargo.toml index 938b6d26..fdf9a209 100644 --- a/crate/kmip/Cargo.toml +++ b/crate/kmip/Cargo.toml @@ -14,10 +14,9 @@ doctest = false [features] default = ["dep:sha3"] -openssl = ["dep:openssl", "dep:x509-parser"] pyo3 = ["dep:pyo3"] # Enable FIPS module feature build. KMS builds in FIPS mode when this is enabled. -fips = ["openssl"] +fips = [] [dependencies] argon2 = "0.5" @@ -42,18 +41,18 @@ num-bigint-dig = { workspace = true, features = [ "serde", "zeroize", ] } -openssl = { workspace = true, optional = true } +openssl = { workspace = true } pyo3 = { workspace = true, optional = true } rust-ini = "0.21" serde = { workspace = true } serde_json = { workspace = true } -sha3 = { version = "0.10", optional = true } +sha3 = { workspace = true, optional = true } strum = { workspace = true, features = ["std", "derive", "strum_macros"] } thiserror = { workspace = true } time = { workspace = true, features = ["formatting", "parsing", "serde"] } tracing = { workspace = true } uuid = { workspace = true, features = ["v4"] } -x509-parser = { workspace = true, optional = true } +x509-parser = { workspace = true } zeroize = { workspace = true, features = ["zeroize_derive", "serde"] } [package.metadata.cargo-machete] diff --git a/crate/kmip/src/crypto/cover_crypt/kmip_requests.rs b/crate/kmip/src/crypto/cover_crypt/kmip_requests.rs index 66b20107..4612bdea 100644 --- a/crate/kmip/src/crypto/cover_crypt/kmip_requests.rs +++ b/crate/kmip/src/crypto/cover_crypt/kmip_requests.rs @@ -5,21 +5,16 @@ use super::attributes::{ access_policy_as_vendor_attribute, policy_as_vendor_attribute, rekey_edit_action_as_vendor_attribute, RekeyEditAction, }; -#[cfg(feature = "openssl")] use crate::{ crypto::wrap::wrap_key_bytes, - kmip::kmip_data_structures::KeyWrappingData, - kmip::kmip_types::{KeyWrapType, WrappingMethod}, -}; -use crate::{ error::KmipError, kmip::{ - kmip_data_structures::{KeyBlock, KeyMaterial, KeyValue}, + kmip_data_structures::{KeyBlock, KeyMaterial, KeyValue, KeyWrappingData}, kmip_objects::{Object, ObjectType}, kmip_operations::{Create, CreateKeyPair, Destroy, Import, Locate, ReKeyKeyPair}, kmip_types::{ - Attributes, CryptographicAlgorithm, CryptographicUsageMask, KeyFormatType, Link, - LinkType, LinkedObjectIdentifier, UniqueIdentifier, + Attributes, CryptographicAlgorithm, CryptographicUsageMask, KeyFormatType, KeyWrapType, + Link, LinkType, LinkedObjectIdentifier, UniqueIdentifier, WrappingMethod, }, }, }; @@ -76,7 +71,6 @@ pub fn build_create_user_decryption_private_key_request>>( private_key: &[u8], unique_identifier: Option, @@ -153,7 +147,6 @@ pub fn build_import_decryption_private_key_request>>( private_key: &[u8], unique_identifier: Option, diff --git a/crate/kmip/src/crypto/elliptic_curves/mod.rs b/crate/kmip/src/crypto/elliptic_curves/mod.rs index 3bb261e1..3fe01f23 100644 --- a/crate/kmip/src/crypto/elliptic_curves/mod.rs +++ b/crate/kmip/src/crypto/elliptic_curves/mod.rs @@ -2,7 +2,6 @@ use crate::kmip::kmip_types::CryptographicUsageMask; #[cfg(not(feature = "fips"))] -#[cfg(feature = "openssl")] pub mod ecies; pub mod kmip_requests; pub mod operation; diff --git a/crate/kmip/src/crypto/elliptic_curves/operation.rs b/crate/kmip/src/crypto/elliptic_curves/operation.rs index dcef1cfb..38be2e08 100644 --- a/crate/kmip/src/crypto/elliptic_curves/operation.rs +++ b/crate/kmip/src/crypto/elliptic_curves/operation.rs @@ -1,4 +1,3 @@ -#[cfg(feature = "openssl")] use openssl::{ bn::BigNumContext, ec::{EcGroup, EcKey, PointConversionForm}, @@ -6,7 +5,6 @@ use openssl::{ pkey::PKey, }; use tracing::trace; -#[cfg(feature = "openssl")] use zeroize::Zeroizing; #[cfg(feature = "fips")] @@ -15,8 +13,8 @@ use crate::crypto::elliptic_curves::{ FIPS_PUBLIC_ECC_MASK_ECDH, FIPS_PUBLIC_ECC_MASK_SIGN, FIPS_PUBLIC_ECC_MASK_SIGN_ECDH, }; use crate::{ - crypto::secret::SafeBigUint, - error::result::KmipResult, + crypto::{secret::SafeBigUint, KeyPair}, + error::{result::KmipResult, KmipError}, kmip::{ kmip_data_structures::{KeyBlock, KeyMaterial, KeyValue}, kmip_objects::{Object, ObjectType}, @@ -26,9 +24,8 @@ use crate::{ LinkedObjectIdentifier, RecommendedCurve, }, }, + kmip_bail, }; -#[cfg(feature = "openssl")] -use crate::{crypto::KeyPair, error::KmipError, kmip_bail}; #[cfg(feature = "fips")] /// Check that bits set in `mask` are only bits set in `flags`. If any bit set @@ -243,7 +240,7 @@ pub fn to_ec_private_key( } /// Generate an X25519 Key Pair. Not FIPS 140-3 compliant. -#[cfg(all(not(feature = "fips"), feature = "openssl"))] +#[cfg(not(feature = "fips"))] pub fn create_x25519_key_pair( private_key_uid: &str, public_key_uid: &str, @@ -275,7 +272,7 @@ pub fn create_x25519_key_pair( } /// Generate an X448 Key Pair. Not FIPS 140-3 compliant. -#[cfg(all(not(feature = "fips"), feature = "openssl"))] +#[cfg(not(feature = "fips"))] pub fn create_x448_key_pair( private_key_uid: &str, public_key_uid: &str, @@ -312,7 +309,6 @@ pub fn create_x448_key_pair( /// Sources: /// - NIST.SP.800-186 - Section 3.1.2 table 2. /// - NIST.FIPS.186-5 -#[cfg(feature = "openssl")] pub fn create_ed25519_key_pair( private_key_uid: &str, public_key_uid: &str, @@ -361,7 +357,6 @@ pub fn create_ed25519_key_pair( /// Sources: /// - NIST.SP.800-186 - Section 3.1.2 table 2. /// - NIST.FIPS.186-5 -#[cfg(feature = "openssl")] pub fn create_ed448_key_pair( private_key_uid: &str, public_key_uid: &str, @@ -404,7 +399,6 @@ pub fn create_ed448_key_pair( Ok(KeyPair::new(private_key, public_key)) } -#[cfg(feature = "openssl")] pub fn create_approved_ecc_key_pair( private_key_uid: &str, public_key_uid: &str, @@ -469,7 +463,7 @@ pub fn create_approved_ecc_key_pair( } #[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] -#[cfg(all(test, feature = "openssl"))] +#[cfg(test)] mod tests { #[cfg(not(feature = "fips"))] use openssl::pkey::{Id, PKey}; diff --git a/crate/kmip/src/crypto/mod.rs b/crate/kmip/src/crypto/mod.rs index c2fac8c6..61fe7200 100644 --- a/crate/kmip/src/crypto/mod.rs +++ b/crate/kmip/src/crypto/mod.rs @@ -1,5 +1,4 @@ pub use elliptic_curves::CURVE_25519_Q_LENGTH_BITS; -#[cfg(any(feature = "openssl", feature = "fips"))] pub use password_derivation::FIPS_MIN_SALT_SIZE; use crate::{ @@ -15,13 +14,11 @@ pub mod cover_crypt; pub mod dh_shared_keys; pub mod elliptic_curves; pub mod generic; -#[cfg(any(feature = "openssl", feature = "fips"))] pub mod password_derivation; pub mod rsa; pub mod secret; pub mod symmetric; -#[cfg(feature = "openssl")] pub mod wrap; pub trait EncryptionSystem { diff --git a/crate/kmip/src/crypto/password_derivation.rs b/crate/kmip/src/crypto/password_derivation.rs index 3b05e44f..53502d8f 100644 --- a/crate/kmip/src/crypto/password_derivation.rs +++ b/crate/kmip/src/crypto/password_derivation.rs @@ -11,6 +11,7 @@ use crate::kmip_bail; /// Minimum random salt size in bytes to use when deriving keys. pub const FIPS_MIN_SALT_SIZE: usize = 16; + #[cfg(feature = "fips")] /// Output size in bits of the hash function used in PBKDF2. pub const FIPS_HLEN: usize = 512; diff --git a/crate/kmip/src/crypto/rsa/mod.rs b/crate/kmip/src/crypto/rsa/mod.rs index d03152e6..b75cd35a 100644 --- a/crate/kmip/src/crypto/rsa/mod.rs +++ b/crate/kmip/src/crypto/rsa/mod.rs @@ -4,15 +4,11 @@ use crate::kmip::kmip_types::{ CryptographicAlgorithm, CryptographicParameters, HashingAlgorithm, PaddingMethod, }; -#[cfg(feature = "openssl")] pub mod ckm_rsa_aes_key_wrap; -#[cfg(feature = "openssl")] #[cfg(not(feature = "fips"))] pub mod ckm_rsa_pkcs; -#[cfg(feature = "openssl")] pub mod ckm_rsa_pkcs_oaep; pub mod kmip_requests; -#[cfg(feature = "openssl")] pub mod operation; #[cfg(feature = "fips")] diff --git a/crate/kmip/src/crypto/secret.rs b/crate/kmip/src/crypto/secret.rs index 71ea1e19..47e81398 100644 --- a/crate/kmip/src/crypto/secret.rs +++ b/crate/kmip/src/crypto/secret.rs @@ -4,12 +4,10 @@ use std::{ }; use num_bigint_dig::BigUint; -#[cfg(feature = "openssl")] use openssl::rand::rand_bytes; use serde::Deserialize; use zeroize::{Zeroize, ZeroizeOnDrop}; -#[cfg(feature = "openssl")] use crate::error::KmipError; /// Holds a big integer secret information. Wraps around `BigUint` type which is @@ -68,7 +66,6 @@ impl Secret { } /// Creates a new random secret. - #[cfg(feature = "openssl")] pub fn new_random() -> Result { let mut secret = Self::new(); rand_bytes(&mut secret)?; diff --git a/crate/kmip/src/crypto/symmetric/mod.rs b/crate/kmip/src/crypto/symmetric/mod.rs index f8fbdd32..ab24c975 100644 --- a/crate/kmip/src/crypto/symmetric/mod.rs +++ b/crate/kmip/src/crypto/symmetric/mod.rs @@ -1,9 +1,7 @@ mod symmetric_key; pub use symmetric_key::{create_symmetric_key_kmip_object, symmetric_key_create_request}; -#[cfg(feature = "openssl")] mod aes_256_gcm; -#[cfg(feature = "openssl")] pub use aes_256_gcm::AesGcmSystem; /// AES 128 GCM key length in bytes. @@ -23,13 +21,10 @@ pub const AES_256_GCM_MAC_LENGTH: usize = 16; /// AES KEY WRAP with padding key length in bytes. pub const AES_KWP_KEY_LENGTH: usize = 0x20; -#[cfg(feature = "openssl")] pub mod aead; -#[cfg(feature = "openssl")] pub mod rfc5649; -#[cfg(feature = "openssl")] #[cfg(test)] #[allow(clippy::unwrap_used, clippy::panic_in_result_fn)] mod tests; diff --git a/crate/kmip/src/crypto/wrap/mod.rs b/crate/kmip/src/crypto/wrap/mod.rs index 067c0296..91eb51b0 100644 --- a/crate/kmip/src/crypto/wrap/mod.rs +++ b/crate/kmip/src/crypto/wrap/mod.rs @@ -2,14 +2,10 @@ mod common; #[allow(clippy::unwrap_used, clippy::panic_in_result_fn)] #[cfg(test)] mod tests; -#[cfg(feature = "openssl")] mod unwrap_key; -#[cfg(feature = "openssl")] mod wrap_key; const WRAPPING_SECRET_LENGTH: usize = 32; -#[cfg(feature = "openssl")] -pub use unwrap_key::unwrap_key_block; -#[cfg(feature = "openssl")] +pub use unwrap_key::{unwrap_key_block, unwrap_key_bytes}; pub use wrap_key::{wrap_key_block, wrap_key_bytes}; diff --git a/crate/kmip/src/crypto/wrap/unwrap_key.rs b/crate/kmip/src/crypto/wrap/unwrap_key.rs index 137b7b42..9763c8eb 100644 --- a/crate/kmip/src/crypto/wrap/unwrap_key.rs +++ b/crate/kmip/src/crypto/wrap/unwrap_key.rs @@ -2,10 +2,12 @@ use openssl::pkey::{Id, PKey, Private}; use tracing::debug; use zeroize::Zeroizing; +use super::WRAPPING_SECRET_LENGTH; #[cfg(not(feature = "fips"))] use crate::crypto::elliptic_curves::ecies::ecies_decrypt; use crate::{ crypto::{ + password_derivation::derive_key_from_password, rsa::{ ckm_rsa_aes_key_wrap::ckm_rsa_aes_key_unwrap, ckm_rsa_pkcs_oaep::ckm_rsa_pkcs_oaep_key_unwrap, @@ -15,6 +17,7 @@ use crate::{ rfc5649::rfc5649_unwrap, }, wrap::common::rsa_parameters, + FIPS_MIN_SALT_SIZE, }, error::{result::KmipResultHelper, KmipError}, kmip::{ @@ -33,6 +36,17 @@ use crate::{ const NONCE_LENGTH: usize = 12; const TAG_LENGTH: usize = 16; +/// Unwrap a key using a password +pub fn unwrap_key_bytes( + salt: &[u8; FIPS_MIN_SALT_SIZE], + key: &[u8], + wrapping_password: &str, +) -> Result>, KmipError> { + let wrapping_secret = + derive_key_from_password::(salt, wrapping_password.as_bytes())?; + rfc5649_unwrap(key, wrapping_secret.as_ref()).map_err(|e| KmipError::Default(e.to_string())) +} + /// Unwrap a key block with a wrapping key /// /// # Arguments diff --git a/crate/kmip/src/crypto/wrap/wrap_key.rs b/crate/kmip/src/crypto/wrap/wrap_key.rs index 4b896ba4..b11d176c 100644 --- a/crate/kmip/src/crypto/wrap/wrap_key.rs +++ b/crate/kmip/src/crypto/wrap/wrap_key.rs @@ -266,7 +266,6 @@ pub(crate) fn wrap( Ok(ciphertext) } } - #[cfg(feature = "openssl")] KeyFormatType::TransparentECPublicKey | KeyFormatType::TransparentRSAPublicKey => { // convert to transparent key and wrap // note: when moving to full openssl this double conversion will be unnecessary @@ -274,7 +273,6 @@ pub(crate) fn wrap( wrap_with_public_key(&p_key, key_wrapping_data, key_to_wrap) } // this really is SPKI - #[cfg(feature = "openssl")] KeyFormatType::PKCS8 => { let p_key = PKey::public_key_from_der(&key_block.key_bytes()?)?; wrap_with_public_key(&p_key, key_wrapping_data, key_to_wrap) diff --git a/crate/kmip/src/error/mod.rs b/crate/kmip/src/error/mod.rs index 2773fef2..0ae2af84 100644 --- a/crate/kmip/src/error/mod.rs +++ b/crate/kmip/src/error/mod.rs @@ -105,7 +105,6 @@ impl From for pyo3::PyErr { } } -#[cfg(feature = "openssl")] impl From for KmipError { fn from(e: openssl::error::ErrorStack) -> Self { Self::OpenSSL(format!("Error: {e}. Details: {e:?}")) diff --git a/crate/kmip/src/kmip/extra/mod.rs b/crate/kmip/src/kmip/extra/mod.rs index bec25320..008af823 100644 --- a/crate/kmip/src/kmip/extra/mod.rs +++ b/crate/kmip/src/kmip/extra/mod.rs @@ -1,7 +1,6 @@ mod bulk_data; mod certificates; pub mod tagging; -#[cfg(feature = "openssl")] pub mod x509_extensions; pub use bulk_data::BulkData; diff --git a/crate/kmip/src/kmip/kmip_data_structures.rs b/crate/kmip/src/kmip/kmip_data_structures.rs index 5565735c..5f4a6166 100644 --- a/crate/kmip/src/kmip/kmip_data_structures.rs +++ b/crate/kmip/src/kmip/kmip_data_structures.rs @@ -9,8 +9,6 @@ use serde::{ use zeroize::Zeroizing; use super::kmip_types::{LinkType, LinkedObjectIdentifier}; -#[cfg(feature = "openssl")] -use crate::pad_be_bytes; use crate::{ crypto::secret::SafeBigUint, error::KmipError, @@ -22,6 +20,7 @@ use crate::{ WrappingMethod, }, }, + pad_be_bytes, }; /// A Key Block object is a structure used to encapsulate all of the information @@ -64,7 +63,6 @@ impl KeyBlock { match &self.key_value.key_material { KeyMaterial::ByteString(v) => Ok(v.clone()), KeyMaterial::TransparentSymmetricKey { key } => Ok(key.clone()), - #[cfg(feature = "openssl")] KeyMaterial::TransparentECPrivateKey { d, recommended_curve, diff --git a/crate/kmip/src/kmip/kmip_types.rs b/crate/kmip/src/kmip/kmip_types.rs index 99bbbb63..c0b22ce8 100644 --- a/crate/kmip/src/kmip/kmip_types.rs +++ b/crate/kmip/src/kmip/kmip_types.rs @@ -9,7 +9,6 @@ use std::{ }; use clap::ValueEnum; -#[cfg(feature = "openssl")] use openssl::{ hash::MessageDigest, md::{Md, MdRef}, @@ -24,14 +23,13 @@ use tracing::trace; use uuid::Uuid; use super::kmip_objects::ObjectType; -#[cfg(feature = "openssl")] -use crate::kmip_error; use crate::{ error::KmipError, kmip::{ extra::{tagging::VENDOR_ATTR_TAG, VENDOR_ID_COSMIAN}, kmip_operations::ErrorReason, }, + kmip_error, }; pub const VENDOR_ATTR_AAD: &str = "aad"; @@ -2456,7 +2454,6 @@ pub enum HashingAlgorithm { SHA3512 = 0x0000_0011, } -#[cfg(feature = "openssl")] impl TryFrom for &'static MdRef { type Error = KmipError; @@ -2478,7 +2475,6 @@ impl TryFrom for &'static MdRef { } } -#[cfg(feature = "openssl")] impl TryFrom for MessageDigest { type Error = KmipError; diff --git a/crate/kmip/src/lib.rs b/crate/kmip/src/lib.rs index 7462ebcb..f900c364 100644 --- a/crate/kmip/src/lib.rs +++ b/crate/kmip/src/lib.rs @@ -59,7 +59,6 @@ pub use error::{result::KmipResultHelper, KmipError}; pub mod crypto; mod error; pub mod kmip; -#[cfg(feature = "openssl")] pub mod openssl; pub fn pad_be_bytes(bytes: &mut Vec, size: usize) { diff --git a/crate/logger/Cargo.toml b/crate/logger/Cargo.toml index 0568c861..7807f796 100644 --- a/crate/logger/Cargo.toml +++ b/crate/logger/Cargo.toml @@ -9,4 +9,4 @@ rust-version.workspace = true [dependencies] tracing = { workspace = true } -tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } diff --git a/crate/pkcs11/module/Cargo.toml b/crate/pkcs11/module/Cargo.toml index ed4586cc..4f705b92 100644 --- a/crate/pkcs11/module/Cargo.toml +++ b/crate/pkcs11/module/Cargo.toml @@ -13,8 +13,8 @@ doctest = false [dependencies] bincode = "1.3.3" -hex = "0.4.3" -log = "0.4.22" +hex = { workspace = true } +log = { workspace = true } once_cell = "1.19.0" p256 = { version = "0.13.2", default-features = false, features = [ "arithmetic", @@ -28,12 +28,9 @@ serde = { version = "1.0.204", features = ["derive"] } strum_macros = "0.26.4" thiserror = "1.0.63" tracing = "0.1.40" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -zeroize = "1.8.1" +tracing-subscriber = { workspace = true, features = ["env-filter"] } +zeroize = { workspace = true } [dev-dependencies] serial_test = { version = "3.1.1", default-features = false } tracing = { version = "0.1.40", default-features = false } -tracing-subscriber = { version = "0.3.18", default-features = false, features = [ - "env-filter", -] } diff --git a/crate/pkcs11/provider/Cargo.toml b/crate/pkcs11/provider/Cargo.toml index 889051a1..d702ecc2 100644 --- a/crate/pkcs11/provider/Cargo.toml +++ b/crate/pkcs11/provider/Cargo.toml @@ -25,8 +25,8 @@ thiserror = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread"] } tracing = { workspace = true } tracing-error = "0.2.0" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -x509-cert = { version = "0.2.5", default-features = false } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +x509-cert = { workspace = true } zeroize = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] diff --git a/crate/pyo3/Cargo.toml b/crate/pyo3/Cargo.toml index 4e781602..f79e56ca 100644 --- a/crate/pyo3/Cargo.toml +++ b/crate/pyo3/Cargo.toml @@ -13,7 +13,7 @@ name = "cosmian_kms" [dependencies] cloudproof = { workspace = true } -cosmian_kmip = { path = "../kmip", features = ["pyo3", "openssl"] } +cosmian_kmip = { path = "../kmip", features = ["pyo3"] } cosmian_kms_client = { path = "../client" } openssl = { workspace = true } pyo3 = { workspace = true, features = [ diff --git a/crate/server/Cargo.toml b/crate/server/Cargo.toml index d52f6c8f..468f3ab2 100644 --- a/crate/server/Cargo.toml +++ b/crate/server/Cargo.toml @@ -51,7 +51,7 @@ clap = { workspace = true, features = [ ] } cloudproof = { workspace = true } cloudproof_findex = { version = "5.0", features = ["findex-redis"] } -cosmian_kmip = { path = "../kmip", features = ["openssl"] } +cosmian_kmip = { path = "../kmip" } cosmian_kms_client = { path = "../client" } dotenvy = "0.15" futures = "0.3" @@ -100,18 +100,18 @@ tokio = { workspace = true, features = ["full"] } toml = "0.8" tracing = { workspace = true } tracing-opentelemetry = "0.24.0" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } url = { workspace = true } uuid = { workspace = true, features = ["v4"] } version-compare = "0.2.0" x509-parser = { workspace = true } zeroize = { workspace = true } -log = "0.4.22" +log = { workspace = true } [dev-dependencies] actix-http = "3.6" cosmian_logger = { path = "../logger" } -pem = "3.0.4" +pem = { workspace = true } tempfile = "3.11" [build-dependencies] diff --git a/documentation/docs/cli/main_commands.md b/documentation/docs/cli/main_commands.md index 3cf2894f..50086761 100644 --- a/documentation/docs/cli/main_commands.md +++ b/documentation/docs/cli/main_commands.md @@ -188,13 +188,17 @@ Create, destroy, import, export, and rekey `Covercrypt` master and user keys **`import`** [[2.1.4]](#214-ckms-cc-keys-import) Import a private or public key in the KMS. -**`revoke`** [[2.1.5]](#215-ckms-cc-keys-revoke) Revoke a Covercrypt master or user decryption key +**`wrap`** [[2.1.5]](#215-ckms-cc-keys-wrap) Locally wrap a key in KMIP JSON TTLV format. -**`destroy`** [[2.1.6]](#216-ckms-cc-keys-destroy) Destroy a Covercrypt master or user decryption key +**`unwrap`** [[2.1.6]](#216-ckms-cc-keys-unwrap) Locally unwrap a key in KMIP JSON TTLV format. -**`rekey`** [[2.1.7]](#217-ckms-cc-keys-rekey) Rekey the master and user keys for a given access policy. +**`revoke`** [[2.1.7]](#217-ckms-cc-keys-revoke) Revoke a Covercrypt master or user decryption key -**`prune`** [[2.1.8]](#218-ckms-cc-keys-prune) Prune the master and user keys for a given access policy. +**`destroy`** [[2.1.8]](#218-ckms-cc-keys-destroy) Destroy a Covercrypt master or user decryption key + +**`rekey`** [[2.1.9]](#219-ckms-cc-keys-rekey) Rekey the master and user keys for a given access policy. + +**`prune`** [[2.1.10]](#2110-ckms-cc-keys-prune) Prune the master and user keys for a given access policy. --- @@ -327,7 +331,55 @@ Possible values: `"sign", "verify", "encrypt", "decrypt", "wrap-key", "unwrap-k --- -## 2.1.5 ckms cc keys revoke +## 2.1.5 ckms cc keys wrap + +Locally wrap a key in KMIP JSON TTLV format. + +### Usage +`ckms cc keys wrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to wrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--wrap-password [-p] ` A password to wrap the imported key. This password will be derived into a AES-256 symmetric key. For security reasons, a fresh salt is internally handled and generated by `ckms` and this final AES symmetric key will be displayed only once + +`--wrap-key-b64 [-k] ` A symmetric key as a base 64 string to wrap the imported key + +`--wrap-key-id [-i] ` The id of a wrapping key in the KMS that will be exported and used to wrap the key + +`--wrap-key-file [-f] ` A wrapping key in a KMIP JSON TTLV file used to wrap the key + + + +--- + +## 2.1.6 ckms cc keys unwrap + +Locally unwrap a key in KMIP JSON TTLV format. + +### Usage +`ckms cc keys unwrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to unwrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--unwrap-key-b64 [-k] ` A symmetric key as a base 64 string to unwrap the imported key + +`--unwrap-key-id [-i] ` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key + +`--unwrap-key-file [-f] ` A unwrapping key in a KMIP JSON TTLV file used to unwrap the key + + + +--- + +## 2.1.7 ckms cc keys revoke Revoke a Covercrypt master or user decryption key @@ -345,7 +397,7 @@ Revoke a Covercrypt master or user decryption key --- -## 2.1.6 ckms cc keys destroy +## 2.1.8 ckms cc keys destroy Destroy a Covercrypt master or user decryption key @@ -360,7 +412,7 @@ Destroy a Covercrypt master or user decryption key --- -## 2.1.7 ckms cc keys rekey +## 2.1.9 ckms cc keys rekey Rekey the master and user keys for a given access policy. @@ -378,7 +430,7 @@ Rekey the master and user keys for a given access policy. --- -## 2.1.8 ckms cc keys prune +## 2.1.10 ckms cc keys prune Prune the master and user keys for a given access policy. @@ -906,9 +958,13 @@ Create, destroy, import, and export elliptic curve key pairs **`import`** [[4.1.3]](#413-ckms-ec-keys-import) Import a private or public key in the KMS. -**`revoke`** [[4.1.4]](#414-ckms-ec-keys-revoke) Revoke a public or private key +**`wrap`** [[4.1.4]](#414-ckms-ec-keys-wrap) Locally wrap a key in KMIP JSON TTLV format. -**`destroy`** [[4.1.5]](#415-ckms-ec-keys-destroy) Destroy a public or private key +**`unwrap`** [[4.1.5]](#415-ckms-ec-keys-unwrap) Locally unwrap a key in KMIP JSON TTLV format. + +**`revoke`** [[4.1.6]](#416-ckms-ec-keys-revoke) Revoke a public or private key + +**`destroy`** [[4.1.7]](#417-ckms-ec-keys-destroy) Destroy a public or private key --- @@ -1022,7 +1078,55 @@ Possible values: `"sign", "verify", "encrypt", "decrypt", "wrap-key", "unwrap-k --- -## 4.1.4 ckms ec keys revoke +## 4.1.4 ckms ec keys wrap + +Locally wrap a key in KMIP JSON TTLV format. + +### Usage +`ckms ec keys wrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to wrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--wrap-password [-p] ` A password to wrap the imported key. This password will be derived into a AES-256 symmetric key. For security reasons, a fresh salt is internally handled and generated by `ckms` and this final AES symmetric key will be displayed only once + +`--wrap-key-b64 [-k] ` A symmetric key as a base 64 string to wrap the imported key + +`--wrap-key-id [-i] ` The id of a wrapping key in the KMS that will be exported and used to wrap the key + +`--wrap-key-file [-f] ` A wrapping key in a KMIP JSON TTLV file used to wrap the key + + + +--- + +## 4.1.5 ckms ec keys unwrap + +Locally unwrap a key in KMIP JSON TTLV format. + +### Usage +`ckms ec keys unwrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to unwrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--unwrap-key-b64 [-k] ` A symmetric key as a base 64 string to unwrap the imported key + +`--unwrap-key-id [-i] ` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key + +`--unwrap-key-file [-f] ` A unwrapping key in a KMIP JSON TTLV file used to unwrap the key + + + +--- + +## 4.1.6 ckms ec keys revoke Revoke a public or private key @@ -1040,7 +1144,7 @@ Revoke a public or private key --- -## 4.1.5 ckms ec keys destroy +## 4.1.7 ckms ec keys destroy Destroy a public or private key @@ -1316,9 +1420,13 @@ Create, destroy, import, and export RSA key pairs **`import`** [[10.1.3]](#1013-ckms-rsa-keys-import) Import a private or public key in the KMS. -**`revoke`** [[10.1.4]](#1014-ckms-rsa-keys-revoke) Revoke a public or private key +**`wrap`** [[10.1.4]](#1014-ckms-rsa-keys-wrap) Locally wrap a key in KMIP JSON TTLV format. -**`destroy`** [[10.1.5]](#1015-ckms-rsa-keys-destroy) Destroy a public or private key +**`unwrap`** [[10.1.5]](#1015-ckms-rsa-keys-unwrap) Locally unwrap a key in KMIP JSON TTLV format. + +**`revoke`** [[10.1.6]](#1016-ckms-rsa-keys-revoke) Revoke a public or private key + +**`destroy`** [[10.1.7]](#1017-ckms-rsa-keys-destroy) Destroy a public or private key --- @@ -1430,7 +1538,55 @@ Possible values: `"sign", "verify", "encrypt", "decrypt", "wrap-key", "unwrap-k --- -## 10.1.4 ckms rsa keys revoke +## 10.1.4 ckms rsa keys wrap + +Locally wrap a key in KMIP JSON TTLV format. + +### Usage +`ckms rsa keys wrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to wrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--wrap-password [-p] ` A password to wrap the imported key. This password will be derived into a AES-256 symmetric key. For security reasons, a fresh salt is internally handled and generated by `ckms` and this final AES symmetric key will be displayed only once + +`--wrap-key-b64 [-k] ` A symmetric key as a base 64 string to wrap the imported key + +`--wrap-key-id [-i] ` The id of a wrapping key in the KMS that will be exported and used to wrap the key + +`--wrap-key-file [-f] ` A wrapping key in a KMIP JSON TTLV file used to wrap the key + + + +--- + +## 10.1.5 ckms rsa keys unwrap + +Locally unwrap a key in KMIP JSON TTLV format. + +### Usage +`ckms rsa keys unwrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to unwrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--unwrap-key-b64 [-k] ` A symmetric key as a base 64 string to unwrap the imported key + +`--unwrap-key-id [-i] ` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key + +`--unwrap-key-file [-f] ` A unwrapping key in a KMIP JSON TTLV file used to unwrap the key + + + +--- + +## 10.1.6 ckms rsa keys revoke Revoke a public or private key @@ -1448,7 +1604,7 @@ Revoke a public or private key --- -## 10.1.5 ckms rsa keys destroy +## 10.1.7 ckms rsa keys destroy Destroy a public or private key @@ -1573,9 +1729,13 @@ Create, destroy, import, and export symmetric keys **`import`** [[12.1.4]](#1214-ckms-sym-keys-import) Import a private or public key in the KMS. -**`revoke`** [[12.1.5]](#1215-ckms-sym-keys-revoke) Revoke a symmetric key +**`wrap`** [[12.1.5]](#1215-ckms-sym-keys-wrap) Locally wrap a key in KMIP JSON TTLV format. -**`destroy`** [[12.1.6]](#1216-ckms-sym-keys-destroy) Destroy a symmetric key +**`unwrap`** [[12.1.6]](#1216-ckms-sym-keys-unwrap) Locally unwrap a key in KMIP JSON TTLV format. + +**`revoke`** [[12.1.7]](#1217-ckms-sym-keys-revoke) Revoke a symmetric key + +**`destroy`** [[12.1.8]](#1218-ckms-sym-keys-destroy) Destroy a symmetric key --- @@ -1706,7 +1866,55 @@ Possible values: `"sign", "verify", "encrypt", "decrypt", "wrap-key", "unwrap-k --- -## 12.1.5 ckms sym keys revoke +## 12.1.5 ckms sym keys wrap + +Locally wrap a key in KMIP JSON TTLV format. + +### Usage +`ckms sym keys wrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to wrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--wrap-password [-p] ` A password to wrap the imported key. This password will be derived into a AES-256 symmetric key. For security reasons, a fresh salt is internally handled and generated by `ckms` and this final AES symmetric key will be displayed only once + +`--wrap-key-b64 [-k] ` A symmetric key as a base 64 string to wrap the imported key + +`--wrap-key-id [-i] ` The id of a wrapping key in the KMS that will be exported and used to wrap the key + +`--wrap-key-file [-f] ` A wrapping key in a KMIP JSON TTLV file used to wrap the key + + + +--- + +## 12.1.6 ckms sym keys unwrap + +Locally unwrap a key in KMIP JSON TTLV format. + +### Usage +`ckms sym keys unwrap [options] + [KEY_FILE_OUT] +` +### Arguments +` ` The KMIP JSON TTLV input key file to unwrap + +` ` The KMIP JSON output file. When not specified the input file is overwritten + +`--unwrap-key-b64 [-k] ` A symmetric key as a base 64 string to unwrap the imported key + +`--unwrap-key-id [-i] ` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key + +`--unwrap-key-file [-f] ` A unwrapping key in a KMIP JSON TTLV file used to unwrap the key + + + +--- + +## 12.1.7 ckms sym keys revoke Revoke a symmetric key @@ -1724,7 +1932,7 @@ Revoke a symmetric key --- -## 12.1.6 ckms sym keys destroy +## 12.1.8 ckms sym keys destroy Destroy a symmetric key diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 00000000..6bf1bfcc --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,14 @@ +{ + "dependencies": [ + { + "name": "openssl" + } + ], + "overrides": [ + { + "name": "openssl", + "version": "3.2.0" + } + ], + "builtin-baseline": "9760ce6194ef51aa4faf77b6321e1280daa4545c" +} diff --git a/vcpkg_fips.json b/vcpkg_fips.json new file mode 100644 index 00000000..18b004f5 --- /dev/null +++ b/vcpkg_fips.json @@ -0,0 +1,15 @@ +{ + "dependencies": [ + { + "name": "openssl", + "features": ["fips"] + } + ], + "overrides": [ + { + "name": "openssl", + "version": "3.2.0" + } + ], + "builtin-baseline": "9760ce6194ef51aa4faf77b6321e1280daa4545c" +}