Skip to content

Commit

Permalink
cdh/kms/aliyun: fix credential reading
Browse files Browse the repository at this point in the history
Openssl was used before. However currently openssl marks RC2 in pkcs12
as `legacy`, which will cause an error when try to decrypt the
credential with password.

This commit tries to decrypt the pkcs12 manually with der bytes.

Signed-off-by: Xynnn007 <[email protected]>
  • Loading branch information
Xynnn007 committed Oct 18, 2023
1 parent 917d5cf commit 414942c
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 9 deletions.
47 changes: 46 additions & 1 deletion 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 confidential-data-hub/kms/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ kbs_protocol = { path = "../../attestation-agent/kbs_protocol", default-features
lazy_static.workspace = true
log.workspace = true
openssl = { workspace = true, optional = true }
p12 = { version = "0.6.3", optional = true }
prost = { workspace = true, optional = true }
resource_uri = { path = "../../attestation-agent/deps/resource_uri" }
sha2 = { workspace = true, optional = true }
Expand All @@ -31,6 +32,7 @@ tokio = { workspace = true, features = ["fs"] }
toml.workspace = true
tonic = { workspace = true, optional = true }
uuid = { workspace = true, features = ["serde", "v4"], optional = true }
yasna = { version = "0.5.2", optional = true }
zeroize = { workspace = true, optional = true }

[dev-dependencies]
Expand All @@ -44,6 +46,6 @@ tonic-build.workspace = true
[features]
default = ["aliyun", "kbs"]

aliyun = ["chrono", "hex", "openssl", "prost", "reqwest", "sha2", "tonic"]
aliyun = ["chrono", "hex", "openssl", "p12", "prost", "reqwest", "sha2", "tonic", "yasna"]
kbs = ["kbs_protocol"]
sev = ["bincode", "crypto", "dep:sev", "prost", "tonic", "uuid", "zeroize"]
65 changes: 58 additions & 7 deletions confidential-data-hub/kms/src/plugins/aliyun/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
use anyhow::*;
use base64::{engine::general_purpose::STANDARD, Engine};
use log::debug;
use openssl::{
pkcs12::Pkcs12,
pkey::{PKey, Private},
sign::Signer,
};
use p12::{CertBag, ContentInfo, MacData, SafeBagKind, PFX};
use serde::Deserialize;
use yasna::ASN1Result;

#[derive(Clone, Debug)]
pub(crate) struct Credential {
Expand All @@ -39,13 +41,10 @@ impl Credential {

let password: Password = serde_json::from_str(pswd)?;

let private_key_der = STANDARD.decode(ck.private_key_data.as_bytes())?;
let pkcs12 = Pkcs12::from_der(&private_key_der)?;
let parsed = pkcs12.parse2(&password.client_key_password)?;
let private_key = parsed
.pkey
.ok_or_else(|| anyhow!("no private key included in pkcs12"))?;
let private_key =
Self::parse_private_key(ck.private_key_data, password.client_key_password)?;

let private_key = PKey::private_key_from_der(&private_key)?;
let credential = Credential {
client_key_id: ck.key_id.clone(),
private_key,
Expand All @@ -61,4 +60,56 @@ impl Credential {

Ok(format!("Bearer {}", STANDARD.encode(signature)))
}

pub(crate) fn parse_private_key(private_key_data: String, password: String) -> Result<Vec<u8>> {
let private_key_der = STANDARD.decode(private_key_data.as_bytes())?;
let pfx = yasna::parse_der(&private_key_der, |r| -> ASN1Result<PFX> {
r.read_sequence(|r| {
let version = r.next().read_u8()?;
let auth_safe = ContentInfo::parse(r.next())?;
let mac_data = r.read_optional(MacData::parse).ok().flatten();
std::result::Result::Ok(PFX {
version,
auth_safe,
mac_data,
})
})
})?;

let bags = pfx.bags(&password)?;
for bag in &bags {
match &bag.bag {
SafeBagKind::Pkcs8ShroudedKeyBag(k) => {
let pass = Self::bmp_string(&password);
let private_key = k
.encryption_algorithm
.decrypt_pbe(&k.encrypted_data, &pass)
.ok_or(anyhow!("decrypt pbe failed"))?;
return Ok(private_key);
}
SafeBagKind::CertBag(e) => match e {
CertBag::X509(x) => {
debug!("parse aliyun pkcs12 credential X509: {}", hex::encode(x))
}
CertBag::SDSI(s) => debug!("parse aliyun pkcs12 credential SDSI: {:?}", s),
},
_ => continue,
}
}

Err(anyhow!("no private key found!"))
}

fn bmp_string(s: &str) -> Vec<u8> {
let utf16: Vec<u16> = s.encode_utf16().collect();

let mut bytes = Vec::with_capacity(utf16.len() * 2 + 2);
for c in utf16 {
bytes.push((c / 256) as u8);
bytes.push((c % 256) as u8);
}
bytes.push(0x00);
bytes.push(0x00);
bytes
}
}

0 comments on commit 414942c

Please sign in to comment.