Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions kbs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ default = ["coco-as-builtin", "coco-as-grpc"]
encrypted-local-fs = []

# Enable encrypted DB-backed resource backend (multi-replica wrap-key sharing)
encrypted-db = ["sqlx", "argon2", "zeroize", "chrono"]
encrypted-db = ["sqlx", "argon2", "chrono"]

# Support a backend attestation service for KBS
as = []
Expand Down Expand Up @@ -47,7 +47,11 @@ tpm-pca = []
actix = "0.13.5"
actix-web = { workspace = true, features = ["openssl"] }
actix-web-httpauth.workspace = true
aes-gcm = "0.10.1"
aes-gcm = { version = "0.10.1", features = ["zeroize"] }
# Direct deps to activate their `zeroize` feature: `aes-gcm`'s own `zeroize`
# feature does not propagate down to `aes` or `polyval`. Do not remove.
aes = { version = "0.8", features = ["zeroize"] }
polyval = { version = "0.6", features = ["zeroize"] }
aes-kw = "0.2.1"
anyhow.workspace = true
argon2 = { workspace = true, optional = true }
Expand Down Expand Up @@ -93,7 +97,7 @@ derivative = "2.2.0"
rustls-pki-types = "1.14.0"
rustls-webpki = { version = "0.103.9", features = ["ring"] }
x509-cert = "0.2.5"
zeroize = { workspace = true, optional = true }
zeroize.workspace = true

[target.'cfg(not(any(target_arch = "s390x", target_arch = "aarch64")))'.dependencies]
attestation-service = { path = "../attestation-service", default-features = false, features = [
Expand Down
32 changes: 15 additions & 17 deletions kbs/src/jwe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 zeroize::Zeroizing;

/// RSA PKCS#1 v1.5
const RSA1_5_ALGORITHM: &str = "RSA1_5";
Expand Down Expand Up @@ -49,7 +50,7 @@ fn rsa_1v15(k_mod: String, k_exp: String, mut payload_data: Vec<u8>) -> Result<R
warn!("Get JWE request using deprecated kcs#1 v1.5 encryption, which has potential security issues.");
let mut rng = rand::thread_rng();

let aes_sym_key = Aes256Gcm::generate_key(&mut OsRng);
let aes_sym_key = Zeroizing::new(Aes256Gcm::generate_key(&mut OsRng));
let mut cipher = Aes256Gcm::new(&aes_sym_key);
let iv = rng.gen::<[u8; 12]>();
let nonce = Nonce::from_slice(&iv);
Expand Down Expand Up @@ -94,7 +95,7 @@ fn rsa_1v15(k_mod: String, k_exp: String, mut payload_data: Vec<u8>) -> Result<R
fn rsa_oaep256(k_mod: String, k_exp: String, mut payload_data: Vec<u8>) -> Result<Response> {
let mut rng = rand::thread_rng();

let aes_sym_key = Aes256Gcm::generate_key(&mut OsRng);
let aes_sym_key = Zeroizing::new(Aes256Gcm::generate_key(&mut OsRng));
let mut cipher = Aes256Gcm::new(&aes_sym_key);
let iv = rng.gen::<[u8; 12]>();
let nonce = Nonce::from_slice(&iv);
Expand Down Expand Up @@ -141,7 +142,7 @@ fn ecdh_es_a256kw_p256(x: String, y: String, mut payload_data: Vec<u8>) -> Resul
let mut rng = rand::thread_rng();

// 1. Generate a random CEK
let cek = Aes256Gcm::generate_key(&mut rng);
let cek = Zeroizing::new(Aes256Gcm::generate_key(&mut rng));

// 2. Wrap the CEK and generate ProtectedHeader
let x: [u8; 32] = URL_SAFE_NO_PAD
Expand All @@ -163,32 +164,29 @@ fn ecdh_es_a256kw_p256(x: String, y: String, mut payload_data: Vec<u8>) -> Resul
.into_option()
.ok_or(anyhow!("invalid TEE public key"))?;
let encrypter_secret = EphemeralSecret::random(&mut rng);
let z = encrypter_secret
.diffie_hellman(&public_key)
.raw_secret_bytes()
.to_vec();
let z = Zeroizing::new(
encrypter_secret
.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];
let mut wrapping_key = Zeroizing::new(vec![0u8; 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: [u8; 32] = wrapping_key
.try_into()
.map_err(|_| anyhow!("invalid bytes length of AES wrapping key"))?;
let wrapping_key: KekAes256 = Kek::new(&GenericArray::from(wrapping_key));
let wrapping_kek: KekAes256 = Kek::new(GenericArray::from_slice(&wrapping_key));
let mut encrypted_key = vec![0; 40];
encrypted_key.resize(40, 0);
let cek = cek.to_vec();
wrapping_key
.wrap(&cek, &mut encrypted_key)
wrapping_kek
.wrap(cek.as_slice(), &mut encrypted_key)
.map_err(|e| anyhow!("failed to do AES wrapping: {e:?}"))?;

let point = EncodedPoint::from(encrypter_secret.public_key());
Expand Down Expand Up @@ -217,7 +215,7 @@ fn ecdh_es_a256kw_p256(x: String, y: String, mut payload_data: Vec<u8>) -> Resul
};

// 3. Encrypt content with CEK
let mut cek_cipher = Aes256Gcm::new(GenericArray::from_slice(&cek));
let mut cek_cipher = Aes256Gcm::new(&cek);

let iv = rand::thread_rng().gen::<[u8; 12]>();
let nonce = Nonce::from_slice(&iv);
Expand Down
Loading