Skip to content

Commit

Permalink
DO NOT MERGE: only for test
Browse files Browse the repository at this point in the history
Signed-off-by: Xynnn007 <[email protected]>
  • Loading branch information
Xynnn007 committed Dec 17, 2024
1 parent 3b7afdd commit ff56818
Show file tree
Hide file tree
Showing 13 changed files with 520 additions and 54 deletions.
29 changes: 25 additions & 4 deletions Cargo.lock

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

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ hmac = "0.12.1"
jwt-simple = { version = "0.12", default-features = false, features = [
"pure-rust",
] }
kbs-types = { git = "https://github.com/virtee/kbs-types.git", rev = "a704036" }
# TODO: change this rev to official repo
# Once https://github.com/virtee/kbs-types/pull/53 gets merged
kbs-types = { git = "https://github.com/Xynnn007/kbs-types.git", rev = "f56c565" }
lazy_static = "1.5.0"
log = "0.4.22"
nix = "0.29"
Expand Down
9 changes: 6 additions & 3 deletions attestation-agent/deps/crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ edition = "2021"

[dependencies]
aes-gcm = { workspace = true, optional = true }
aes-kw = { version = "0.2.1", optional = true }
anyhow.workspace = true
base64.workspace = true
concat-kdf = { version = "0.1.0", optional = true }
ctr = { workspace = true, optional = true }
kbs-types.workspace = true
openssl = { workspace = true, features = ["vendored"], optional = true}
openssl = { workspace = true, features = ["vendored"], optional = true }
p256 = { version = "0.13.1", features = ["ecdh"] }
rand.workspace = true
rsa = { workspace = true, optional = true }
serde.workspace = true
Expand All @@ -25,5 +28,5 @@ rstest.workspace = true

[features]
default = ["rust-crypto"]
rust-crypto = ["dep:aes-gcm", "ctr", "rsa"]
openssl = ["dep:openssl"]
rust-crypto = ["dep:aes-gcm", "ctr", "rsa/sha2", "aes-kw", "concat-kdf"]
openssl = ["dep:openssl"]
35 changes: 34 additions & 1 deletion attestation-agent/deps/crypto/src/asymmetric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
// SPDX-License-Identifier: Apache-2.0
//

// This lint checker is for [`rsa::PaddingMode::PKCS1v15`]
// TODO: remove this when the deprecated attribute is removed
#[allow(deprecated)]
pub mod rsa {
#[cfg(feature = "openssl")]
pub use crate::native::rsa::*;
Expand All @@ -15,9 +18,12 @@ pub mod rsa {
/// more information.
#[derive(EnumString, AsRefStr)]
pub enum PaddingMode {
#[strum(serialize = "RSA-OAEP")]
/// RSAES OAEP using SHA-256 and MGF1 with SHA-256
#[strum(serialize = "RSA-OAEP-256")]
OAEP,

/// RSA PKCS#1 v1.5
#[deprecated(note = "This algorithm is no longer recommended.")]
#[strum(serialize = "RSA1_5")]
PKCS1v15,
}
Expand All @@ -26,3 +32,30 @@ pub mod rsa {

pub const RSA_KTY: &str = "RSA";
}

pub mod ec {
#[cfg(feature = "openssl")]
pub use crate::native::ec::*;

#[cfg(all(feature = "rust-crypto", not(feature = "openssl")))]
pub use crate::rust::ec::*;

/// The elliptic curve key type
pub const EC_KTY: &str = "EC";

/// Definations of different key wrapping algorithms. Refer to
/// <https://datatracker.ietf.org/doc/html/rfc7518> for
/// more information.
#[derive(EnumString, AsRefStr)]
pub enum KeyWrapAlgorithm {
/// ECDH-ES using Concat KDF and CEK wrapped with "A256KW"
#[strum(serialize = "ECDH-ES+A256KW")]
EcdhEsA256Kw,
}

#[derive(EnumString, AsRefStr)]
pub enum Curve {
#[strum(serialize = "P-256")]
P256,
}
}
168 changes: 168 additions & 0 deletions attestation-agent/deps/crypto/src/native/ec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright (c) 2024 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

use anyhow::{anyhow, Context, Result};
use openssl::{
aes::{self, AesKey},
bn::{BigNum, BigNumContext},
derive::Deriver,
ec::{EcGroup, EcKey},
hash::{Hasher, MessageDigest},
nid::Nid,
pkey::{PKey, Private},
};

use crate::{
ec::{Curve, KeyWrapAlgorithm},
AES_GCM_256_KEY_BITS,
};

#[derive(Clone, Debug)]
pub enum EcKeyPair {
P256(P256EcKeyPair),
}

impl Default for EcKeyPair {
fn default() -> Self {
Self::P256(P256EcKeyPair::new().expect("Create P256 key pair failed"))
}
}

impl EcKeyPair {
fn private_key(&self) -> &PKey<Private> {
match self {
Self::P256(p256) => p256.private_key(),
}
}

pub fn curve(&self) -> Curve {
match self {
Self::P256(_) => Curve::P256,
}
}

pub fn x(&self) -> Result<Vec<u8>> {
match self {
Self::P256(p256) => p256.x(),
}
}

pub fn y(&self) -> Result<Vec<u8>> {
match self {
Self::P256(p256) => p256.y(),
}
}

pub fn unwrap_key(
&self,
encrypted_key: Vec<u8>,
epk_x: Vec<u8>,
epk_y: Vec<u8>,
wrapping_algorithm: KeyWrapAlgorithm,
) -> Result<Vec<u8>> {
let group = match self.curve() {
Curve::P256 => EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?,
};
let point = group.generator();
let mut point = point.to_owned(&group)?;

let epk_x = BigNum::from_slice(&epk_x)?;
let epk_y = BigNum::from_slice(&epk_y)?;

let mut ctx = BigNumContext::new()?;
point.set_affine_coordinates_gfp(&group, &epk_x, &epk_y, &mut ctx)?;

let epk = EcKey::from_public_key(&group, &point)?;
let epk = PKey::from_ec_key(epk)?;
match wrapping_algorithm {
KeyWrapAlgorithm::EcdhEsA256Kw => {
let mut deriver = Deriver::new(self.private_key())?;
deriver.set_peer(&epk)?;
let z = deriver.derive_to_vec()?;
let shared_key = concat_kdf(
KeyWrapAlgorithm::EcdhEsA256Kw.as_ref(),
AES_GCM_256_KEY_BITS as usize / 8,
&z,
)?;
let mut key = vec![0; encrypted_key.len() - 8];
let unwrapping_key = AesKey::new_decrypt(&shared_key)
.map_err(|e| anyhow!("failed to create AES unwrapping key: {e:?}"))?;
aes::unwrap_key(&unwrapping_key, None, &mut key, &encrypted_key)
.map_err(|e| anyhow!("failed to unwrap key: {e:?}"))?;
Ok(key)
}
}
}
}

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)
}

#[derive(Clone, Debug)]
pub struct P256EcKeyPair {
private_key: PKey<Private>,
}

impl P256EcKeyPair {
fn private_key(&self) -> &PKey<Private> {
&self.private_key
}

pub fn new() -> Result<Self> {
let ec_group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)?;
let ec_key = EcKey::generate(&ec_group)?;
let private_key = PKey::from_ec_key(ec_key)?;
Ok(Self { private_key })
}

pub fn x(&self) -> Result<Vec<u8>> {
let private_key = self.private_key.ec_key().context("must be a ec key")?;
let public_key = private_key.public_key();
let mut x = BigNum::new()?;
let mut _y = BigNum::new()?;
let mut ctx = BigNumContext::new()?;
public_key.affine_coordinates_gfp(private_key.group(), &mut x, &mut _y, &mut ctx)?;
let mut x = x.to_vec();
x.resize(32, b'0');
Ok(x)
}

pub fn y(&self) -> Result<Vec<u8>> {
let private_key = self.private_key.ec_key().context("must be a ec key")?;
let public_key = private_key.public_key();
let mut _x = BigNum::new()?;
let mut y = BigNum::new()?;
let mut ctx = BigNumContext::new()?;
public_key.affine_coordinates_gfp(private_key.group(), &mut _x, &mut y, &mut ctx)?;
let mut y = y.to_vec();
y.resize(32, b'0');
Ok(y)
}
}
1 change: 1 addition & 0 deletions attestation-agent/deps/crypto/src/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
pub mod aes256ctr;
pub mod aes256gcm;

pub mod ec;
pub mod rsa;
1 change: 1 addition & 0 deletions attestation-agent/deps/crypto/src/native/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl RSAKeyPair {
.private_key
.private_decrypt(&cipher_text, &mut plaintext, Padding::PKCS1_OAEP)
.map_err(|e| anyhow!("RSA key decrypt OAEP failed: {:?}", e))?,
#[allow(deprecated)]
PaddingMode::PKCS1v15 => self
.private_key
.private_decrypt(&cipher_text, &mut plaintext, Padding::PKCS1)
Expand Down
Loading

0 comments on commit ff56818

Please sign in to comment.