diff --git a/Cargo.lock b/Cargo.lock index 293429d0f..7232f036d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3348,12 +3348,13 @@ dependencies = [ [[package]] name = "kbs-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6441ed73b0faa50707d4de41c6b45c76654b661b96aaf7b26a41331eedc0a5" +version = "0.9.1" +source = "git+https://github.com/virtee/kbs-types.git?rev=a704036#a70403665bfaa61c0984ae05654df0ad72591e96" dependencies = [ + "base64 0.22.1", "serde", "serde_json", + "thiserror 2.0.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2d6a0b2f2..087c9ab74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,8 +34,10 @@ ctr = "0.9.2" env_logger = "0.11.5" hex = "0.4.3" hmac = "0.12.1" -jwt-simple = { version = "0.12", default-features = false, features = ["pure-rust"] } -kbs-types = "0.7.0" +jwt-simple = { version = "0.12", default-features = false, features = [ + "pure-rust", +] } +kbs-types = { git = "https://github.com/virtee/kbs-types.git", rev = "a704036" } lazy_static = "1.5.0" log = "0.4.22" nix = "0.29" diff --git a/attestation-agent/deps/crypto/src/native/aes256gcm.rs b/attestation-agent/deps/crypto/src/native/aes256gcm.rs index 73a883a4e..3e1c11a8a 100644 --- a/attestation-agent/deps/crypto/src/native/aes256gcm.rs +++ b/attestation-agent/deps/crypto/src/native/aes256gcm.rs @@ -10,6 +10,19 @@ use openssl::symm::Cipher; const TAG_LENGTH: usize = 16; +pub fn decrypt_with_aad( + encrypted_data: &[u8], + key: &[u8], + iv: &[u8], + aad: &[u8], + tag: &[u8], +) -> Result> { + let cipher = Cipher::aes_256_gcm(); + + openssl::symm::decrypt_aead(cipher, key, Some(iv), aad, encrypted_data, tag) + .map_err(|e| anyhow!("{e:?}")) +} + pub fn decrypt(encrypted_data: &[u8], key: &[u8], iv: &[u8]) -> Result> { let cipher = Cipher::aes_256_gcm(); if encrypted_data.len() < TAG_LENGTH { diff --git a/attestation-agent/deps/crypto/src/rust/aes256gcm.rs b/attestation-agent/deps/crypto/src/rust/aes256gcm.rs index 00a4a0d55..d8dde91df 100644 --- a/attestation-agent/deps/crypto/src/rust/aes256gcm.rs +++ b/attestation-agent/deps/crypto/src/rust/aes256gcm.rs @@ -4,10 +4,27 @@ // //! This mod implements aes-256-gcm encryption & decryption. - -use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit, Nonce}; +use aes_gcm::{aead::Aead, AeadInPlace, Aes256Gcm, Key, KeyInit, Nonce}; use anyhow::*; +pub fn decrypt_with_aad( + encrypted_data: &[u8], + key: &[u8], + iv: &[u8], + aad: &[u8], + tag: &[u8], +) -> Result> { + let decrypting_key = Key::::from_slice(key); + let cipher = Aes256Gcm::new(decrypting_key); + let nonce = Nonce::from_slice(iv); + let mut plaintext = encrypted_data.to_vec(); + cipher + .decrypt_in_place_detached(nonce, aad, &mut plaintext, tag.into()) + .map_err(|e| anyhow!("aes-256-gcm decrypt failed: {:?}", e))?; + + Ok(plaintext) +} + pub fn decrypt(encrypted_data: &[u8], key: &[u8], iv: &[u8]) -> Result> { let decrypting_key = Key::::from_slice(key); let cipher = Aes256Gcm::new(decrypting_key); diff --git a/attestation-agent/deps/crypto/src/symmetric.rs b/attestation-agent/deps/crypto/src/symmetric.rs index 900c95f93..0f7f1c5e2 100644 --- a/attestation-agent/deps/crypto/src/symmetric.rs +++ b/attestation-agent/deps/crypto/src/symmetric.rs @@ -48,6 +48,17 @@ pub fn decrypt( } } +/// Decrypt the given `ciphertext` with AES256-GCM algorithm. +pub fn aes256gcm_decrypt( + key: Zeroizing>, + ciphertext: Vec, + iv: Vec, + aad: Vec, + tag: Vec, +) -> Result> { + aes256gcm::decrypt_with_aad(&ciphertext, &key, &iv, &aad, &tag) +} + /// Encrypt the given `plaintext`. /// Note: /// - IV length for A256GCM: 12 bytes diff --git a/attestation-agent/kbs_protocol/src/client/mod.rs b/attestation-agent/kbs_protocol/src/client/mod.rs index 5febb6911..fdb7f23db 100644 --- a/attestation-agent/kbs_protocol/src/client/mod.rs +++ b/attestation-agent/kbs_protocol/src/client/mod.rs @@ -48,7 +48,7 @@ pub struct KbsClient { pub(crate) token: Option, } -pub const KBS_PROTOCOL_VERSION: &str = "0.1.1"; +pub const KBS_PROTOCOL_VERSION: &str = "0.2.0"; pub const KBS_GET_RESOURCE_MAX_ATTEMPT: u64 = 3; diff --git a/attestation-agent/kbs_protocol/src/client/rcar_client.rs b/attestation-agent/kbs_protocol/src/client/rcar_client.rs index 45b194ebb..155aae339 100644 --- a/attestation-agent/kbs_protocol/src/client/rcar_client.rs +++ b/attestation-agent/kbs_protocol/src/client/rcar_client.rs @@ -450,7 +450,7 @@ mod test { assert!( e.to_string() .contains("KBS Client Protocol Version Mismatch"), - "Actual error: {e:#?}" + "{e:#?}" ); println!("NOTE: the test is skipped due to KBS protocol incompatibility."); return (); diff --git a/attestation-agent/kbs_protocol/src/keypair.rs b/attestation-agent/kbs_protocol/src/keypair.rs index 897724e3e..4fb307da5 100644 --- a/attestation-agent/kbs_protocol/src/keypair.rs +++ b/attestation-agent/kbs_protocol/src/keypair.rs @@ -6,12 +6,8 @@ use anyhow::{Context, Result}; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use crypto::{ - rsa::{PaddingMode, RSAKeyPair}, - WrapType, -}; +use crypto::rsa::{PaddingMode, RSAKeyPair}; use kbs_types::{Response, TeePubKey}; -use serde::Deserialize; use zeroize::Zeroizing; #[derive(Clone, Debug)] @@ -55,28 +51,21 @@ impl TeeKeyPair { } pub fn decrypt_response(&self, response: Response) -> Result> { - // deserialize the jose header and check that the key type matches - let protected: ProtectedHeader = serde_json::from_str(&response.protected)?; - let padding_mode = PaddingMode::try_from(&protected.alg[..]) + let padding_mode = PaddingMode::try_from(&response.protected.alg[..]) .context("Unsupported padding mode for wrapped key")?; // unwrap the wrapped key - let wrapped_symkey: Vec = URL_SAFE_NO_PAD.decode(&response.encrypted_key)?; - let symkey = self.decrypt(padding_mode, wrapped_symkey)?; + let symkey = self.decrypt(padding_mode, response.encrypted_key)?; - let iv = URL_SAFE_NO_PAD.decode(&response.iv)?; - let ciphertext = URL_SAFE_NO_PAD.decode(&response.ciphertext)?; - - let plaintext = crypto::decrypt(Zeroizing::new(symkey), ciphertext, iv, protected.enc)?; + let aad = response.protected.generate_aad()?; + let plaintext = crypto::aes256gcm_decrypt( + Zeroizing::new(symkey), + response.ciphertext, + response.iv, + aad, + response.tag, + )?; Ok(plaintext) } } - -#[derive(Deserialize)] -struct ProtectedHeader { - /// enryption algorithm for encrypted key - alg: String, - /// encryption algorithm for payload - enc: WrapType, -}