106 lines
4.0 KiB
Diff
106 lines
4.0 KiB
Diff
From 933b57d8e8915280d671e4796c8919a06bcbb2fb Mon Sep 17 00:00:00 2001
|
|
From: Cropi <alakatos@redhat.com>
|
|
Date: Wed, 21 Jan 2026 11:00:08 +0100
|
|
Subject: [PATCH] kbs: replace concat-kdf dependency with internal
|
|
implementation
|
|
|
|
Remove the 'concat-kdf' crate dependency and replace it with a local
|
|
implementation of the Single-Step Concatenation Key Derivation Function
|
|
(Concat KDF), using standard 'openssl' primitives.
|
|
|
|
This change reduces the external dependency footprint while maintaining
|
|
compatibility with the algorithm used by other guest components (based
|
|
on NIST SP 800-56A).
|
|
Inspired by attestation-agent/deps/crypto/src/native/ec.rs
|
|
---
|
|
kbs/Cargo.toml | 1 -
|
|
kbs/src/jwe.rs | 46 +++++++++++++++++++++++++++++++++-------------
|
|
2 files changed, 33 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/kbs/Cargo.toml b/kbs/Cargo.toml
|
|
index 52968e2..1bd4adf 100644
|
|
--- a/kbs/Cargo.toml
|
|
+++ b/kbs/Cargo.toml
|
|
@@ -52,7 +52,6 @@ base64.workspace = true
|
|
cfg-if.workspace = true
|
|
clap = { workspace = true, features = ["derive", "env"] }
|
|
config.workspace = true
|
|
-concat-kdf = "0.1.0"
|
|
cryptoki = { version = "0.10.0", optional = true }
|
|
env_logger.workspace = true
|
|
hex.workspace = true
|
|
diff --git a/kbs/src/jwe.rs b/kbs/src/jwe.rs
|
|
index 27b4863..6eb25a2 100644
|
|
--- a/kbs/src/jwe.rs
|
|
+++ b/kbs/src/jwe.rs
|
|
@@ -19,6 +19,7 @@ use p256::{
|
|
use rand::{rngs::OsRng, Rng};
|
|
use rsa::{sha2::Sha256, BigUint, Oaep, Pkcs1v15Encrypt, RsaPublicKey};
|
|
use serde_json::{json, Map};
|
|
+use openssl::hash::{Hasher, MessageDigest};
|
|
|
|
/// RSA PKCS#1 v1.5
|
|
const RSA1_5_ALGORITHM: &str = "RSA1_5";
|
|
@@ -41,6 +42,36 @@ const AES_GCM_256_ALGORITHM: &str = "A256GCM";
|
|
/// AES 256 GCM Key length in bits
|
|
const AES_GCM_256_KEY_BITS: u32 = 256;
|
|
|
|
+// Concat KDF as per NIST SP 800-56A
|
|
+// Based on the implementation from attestation-agent/deps/crypto/src/native/ec.rs
|
|
+fn concat_kdf(alg: &str, target_length: usize, z: &[u8]) -> Result<Vec<u8>> {
|
|
+ let target_length_bytes = ((target_length * 8) as u32).to_be_bytes();
|
|
+ let alg_len_bytes = (alg.len() as u32).to_be_bytes();
|
|
+
|
|
+ let mut output = Vec::new();
|
|
+ let md = MessageDigest::sha256();
|
|
+ let count = target_length.div_ceil(md.size());
|
|
+ for i in 0..count {
|
|
+ let mut hasher = Hasher::new(md)?;
|
|
+ hasher.update(&((i + 1) as u32).to_be_bytes())?;
|
|
+ hasher.update(z)?;
|
|
+ hasher.update(&alg_len_bytes)?;
|
|
+ hasher.update(alg.as_bytes())?;
|
|
+ hasher.update(&0_u32.to_be_bytes())?;
|
|
+ hasher.update(&0_u32.to_be_bytes())?;
|
|
+ hasher.update(&target_length_bytes)?;
|
|
+
|
|
+ let digest = hasher.finish()?;
|
|
+ output.extend(digest.to_vec());
|
|
+ }
|
|
+
|
|
+ if output.len() > target_length {
|
|
+ output.truncate(target_length);
|
|
+ }
|
|
+
|
|
+ Ok(output)
|
|
+}
|
|
+
|
|
/// Use RSAv1.5 to encrypt the payload data.
|
|
/// Warning: This algorithm is deprecated per
|
|
/// <https://www.ietf.org/archive/id/draft-madden-jose-deprecate-none-rsa15-00.html#section-1.2>
|
|
@@ -167,19 +198,8 @@ fn ecdh_es_a256kw_p256(x: String, y: String, mut payload_data: Vec<u8>) -> Resul
|
|
.diffie_hellman(&public_key)
|
|
.raw_secret_bytes()
|
|
.to_vec();
|
|
- let mut key_derivation_materials = Vec::new();
|
|
- key_derivation_materials.extend_from_slice(&(ECDH_ES_A256KW.len() as u32).to_be_bytes());
|
|
- key_derivation_materials.extend_from_slice(ECDH_ES_A256KW.as_bytes());
|
|
- key_derivation_materials.extend_from_slice(&(0_u32).to_be_bytes());
|
|
- key_derivation_materials.extend_from_slice(&(0_u32).to_be_bytes());
|
|
- key_derivation_materials.extend_from_slice(&AES_GCM_256_KEY_BITS.to_be_bytes());
|
|
- let mut wrapping_key = vec![0; 32];
|
|
- concat_kdf::derive_key_into::<rsa::sha2::Sha256>(
|
|
- &z,
|
|
- &key_derivation_materials,
|
|
- &mut wrapping_key,
|
|
- )
|
|
- .map_err(|e| anyhow!("failed to do concat KDF: {e:?}"))?;
|
|
+
|
|
+ let wrapping_key = concat_kdf(ECDH_ES_A256KW, 32, &z).context("failed to do concat KDF")?;
|
|
let wrapping_key: [u8; 32] = wrapping_key
|
|
.try_into()
|
|
.map_err(|_| anyhow!("invalid bytes length of AES wrapping key"))?;
|
|
--
|
|
2.52.0
|
|
|