Repository: Cosmian/kms (language: python)

Issue:
ARM 64 / MacOs Problem building KMS 4.18
It's not possible to build the KMS on MacOs ARM64 (M CPU) architecture.

Line 56 in the Dockerfile is erroring 
COPY --from=builder $OPENSSL_DIR/lib64/ossl-modules/legacy.so $OPENSSL_DIR/lib64/ossl-modules/legacy.so

 /lib64 does not exist on mac OS. The openssl@3 install with homebrew have the libraries in /lib and the libraries are with extension .dylib

Also even modifying the line does not allow to build the KMS.

The only solution is to use the AMD64 build with QEMU

docker pull --platform linux/amd64 ghcr.io/cosmian/kms:4.18.0 
  


Discussion / hints:

Fix patch:
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 1699df484..5cfd5400c 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
+    $env:OPENSSL_DIR = "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows-static"
+    Get-ChildItem -Recurse $env:OPENSSL_DIR
+
+    # Build pkcs11 provider
+    Get-ChildItem crate\pkcs11\provider
     if ($BuildType -eq "release") {
         cargo build --release --target x86_64-pc-windows-msvc
-    } else {
+    }
+    else {
         cargo build --target x86_64-pc-windows-msvc
     }
+    Get-ChildItem ..\..\..
 
-    # Build pkcs11 provider
-    cd ../pkcs11/provider
+    # Build `ckms`
+    Get-ChildItem crate\cli
     if ($BuildType -eq "release") {
         cargo build --release --target x86_64-pc-windows-msvc
-    } else {
+    }
+    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]
+    Get-ChildItem ..\..
 
-    vcpkg integrate install
-    $env:VCPKGRS_DYNAMIC = 1
-    $env:OPENSSL_DIR = "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows"
-    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"
+    # 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 de88f2afc..7fd6d08b1 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 13dbde94b..4647234cc 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 e64f6309e..5b88715eb 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 274b6d942..1464b8f0d 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 4917873d3..242c1d602 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 44b5a732c..7cd5294b8 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.
-
-In addition, the KMS server must be built against a local installation of OpenSSL 3. Other
-artifacts do not have this requirement.
-
-### 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:
-
-```sh
-sudo apt install libssl-dev
-```
-
-You may also need to install the `pkg-config` package (on Ubuntu server typically).
+OpenSSL v3.2.0 is required to build the KMS.
 
-### MacOS
+### Linux or MacOS (CPU Intel or MacOs ARM)
 
-Install OpenSSL 3 with Homebrew:
+Build OpenSSL v3.2.0 with the following commands:
 
 ```sh
-brew install openssl@3
+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}
 ```
 
-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 install --triplet x64-windows-static
+vcpkg integrate install
+$env:OPENSSL_DIR = "$env:VCPKG_INSTALLATION_ROOT\packages\openssl_x64-windows-static"
+```
+
+For a FIPS compliant build, use the following commands (in order to build fips.dll), run also:
 
 ```powershell
-vcpkg.exe install openssl[fips,weak-ssl-ciphers]
-vcpkg.exe integrate install
-set VCPKGRS_DYNAMIC=1
-$env:OPENSSL_DIR = "<vcpkg>\installed\<archi>>"
+Copy-Item -Path "vcpkg_fips.json" -Destination "vcpkg.json"
+vcpkg install
+vcpkg integrate install
 ```
 
-where `<vcpkg>` is the path to the vcpkg installation directory,
-and `<archi>` is the architecture e.g `x64-windows`, `arm64-windows`, etc.
+### Build the KMS
 
-To run the server from the command line, add `<vcpkg>\installed\<archi>\bin` to the `PATH`
-environment variable.
+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 container
+### 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 9b97f35c9..4709e3aff 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 8c132a355..32252e732 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 f3e9455b3..5df393f0f 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 b3d9f7985..f9e65dadb 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 2e5d03639..d4e457697 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 9735b3d2d..6758ff0e1 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 52f2fa3a0..1002f8251 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/client/Cargo.toml b/crate/client/Cargo.toml
index 6b0b79f59..537773efb 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 938b6d261..fdf9a2090 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 66b20107f..4612bdead 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<T: IntoIterator<Item = i
 ///
 /// A unique identifier will be generated if none is supplied
 #[allow(clippy::too_many_arguments)]
-#[cfg(feature = "openssl")]
 pub fn build_import_decryption_private_key_request<T: IntoIterator<Item = impl AsRef<str>>>(
     private_key: &[u8],
     unique_identifier: Option<String>,
@@ -153,7 +147,6 @@ pub fn build_import_decryption_private_key_request<T: IntoIterator<Item = impl A
 ///
 /// A unique identifier will be generated if none is supplied
 #[allow(clippy::too_many_arguments)]
-#[cfg(feature = "openssl")]
 pub fn build_import_private_key_request<T: IntoIterator<Item = impl AsRef<str>>>(
     private_key: &[u8],
     unique_identifier: Option<String>,
diff --git a/crate/kmip/src/crypto/elliptic_curves/mod.rs b/crate/kmip/src/crypto/elliptic_curves/mod.rs
index 3bb261e16..3fe01f231 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 dcef1cfbb..38be2e089 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 c2fac8c63..61fe72005 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 3b05e44f4..53502d8f7 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 d03152e66..b75cd35a8 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 71ea1e193..47e813986 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<const LENGTH: usize> Secret<LENGTH> {
     }
 
     /// Creates a new random secret.
-    #[cfg(feature = "openssl")]
     pub fn new_random() -> Result<Self, KmipError> {
         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 f8fbdd322..ab24c9759 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 067c02966..91eb51b00 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 137b7b424..9763c8eb9 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<Zeroizing<Vec<u8>>, KmipError> {
+    let wrapping_secret =
+        derive_key_from_password::<WRAPPING_SECRET_LENGTH>(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 4b896ba4e..b11d176c8 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 2773fef22..0ae2af84f 100644
--- a/crate/kmip/src/error/mod.rs
+++ b/crate/kmip/src/error/mod.rs
@@ -105,7 +105,6 @@ impl From<KmipError> for pyo3::PyErr {
     }
 }
 
-#[cfg(feature = "openssl")]
 impl From<openssl::error::ErrorStack> 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 bec253200..008af823e 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 5565735c3..5f4a61664 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 99bbbb63e..c0b22ce81 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<HashingAlgorithm> for &'static MdRef {
     type Error = KmipError;
 
@@ -2478,7 +2475,6 @@ impl TryFrom<HashingAlgorithm> for &'static MdRef {
     }
 }
 
-#[cfg(feature = "openssl")]
 impl TryFrom<HashingAlgorithm> for MessageDigest {
     type Error = KmipError;
 
diff --git a/crate/kmip/src/lib.rs b/crate/kmip/src/lib.rs
index 7462ebcb8..f900c3644 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<u8>, size: usize) {
diff --git a/crate/logger/Cargo.toml b/crate/logger/Cargo.toml
index 0568c8613..7807f7969 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 ed4586cc8..4f705b923 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 889051a1a..d702ecc2b 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 4e781602d..f79e56ca0 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 d52f6c8fb..468f3ab25 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 3cf2894fe..500867613 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to wrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--wrap-password [-p] <WRAP_PASSWORD>` 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] <WRAP_KEY_B64>` A symmetric key as a base 64 string to wrap the imported key
+
+`--wrap-key-id [-i] <WRAP_KEY_ID>` The id of a wrapping key in the KMS that will be exported and used to wrap the key
+
+`--wrap-key-file [-f] <WRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to unwrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--unwrap-key-b64 [-k] <UNWRAP_KEY_B64>` A symmetric key as a base 64 string to unwrap the imported key
+
+`--unwrap-key-id [-i] <UNWRAP_KEY_ID>` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key
+
+`--unwrap-key-file [-f] <UNWRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to wrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--wrap-password [-p] <WRAP_PASSWORD>` 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] <WRAP_KEY_B64>` A symmetric key as a base 64 string to wrap the imported key
+
+`--wrap-key-id [-i] <WRAP_KEY_ID>` The id of a wrapping key in the KMS that will be exported and used to wrap the key
+
+`--wrap-key-file [-f] <WRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to unwrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--unwrap-key-b64 [-k] <UNWRAP_KEY_B64>` A symmetric key as a base 64 string to unwrap the imported key
+
+`--unwrap-key-id [-i] <UNWRAP_KEY_ID>` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key
+
+`--unwrap-key-file [-f] <UNWRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to wrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--wrap-password [-p] <WRAP_PASSWORD>` 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] <WRAP_KEY_B64>` A symmetric key as a base 64 string to wrap the imported key
+
+`--wrap-key-id [-i] <WRAP_KEY_ID>` The id of a wrapping key in the KMS that will be exported and used to wrap the key
+
+`--wrap-key-file [-f] <WRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to unwrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--unwrap-key-b64 [-k] <UNWRAP_KEY_B64>` A symmetric key as a base 64 string to unwrap the imported key
+
+`--unwrap-key-id [-i] <UNWRAP_KEY_ID>` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key
+
+`--unwrap-key-file [-f] <UNWRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to wrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--wrap-password [-p] <WRAP_PASSWORD>` 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] <WRAP_KEY_B64>` A symmetric key as a base 64 string to wrap the imported key
+
+`--wrap-key-id [-i] <WRAP_KEY_ID>` The id of a wrapping key in the KMS that will be exported and used to wrap the key
+
+`--wrap-key-file [-f] <WRAP_KEY_FILE>` 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_IN>
+ [KEY_FILE_OUT]
+`
+### Arguments
+` <KEY_FILE_IN>` The KMIP JSON TTLV input key file to unwrap
+
+` <KEY_FILE_OUT>` The KMIP JSON output file. When not specified the input file is overwritten
+
+`--unwrap-key-b64 [-k] <UNWRAP_KEY_B64>` A symmetric key as a base 64 string to unwrap the imported key
+
+`--unwrap-key-id [-i] <UNWRAP_KEY_ID>` The id of a unwrapping key in the KMS that will be exported and used to unwrap the key
+
+`--unwrap-key-file [-f] <UNWRAP_KEY_FILE>` 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 000000000..6bf1bfccc
--- /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 000000000..18b004f5a
--- /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"
+}


Test patch:
diff --git a/crate/cli/src/tests/shared/mod.rs b/crate/cli/src/tests/shared/mod.rs
index 9f6efe97b..1e3baaf37 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 54ce94a7a..65bb812d5 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 eff58a4de..31a0cec09 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<Vec<String>> {
 /// 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<uid>[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()))
 }