Skip to content
Draft
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
26 changes: 16 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace.package]
version = "0.5.2"
version = "0.6.0-dev"
authors = [
"William Brown <[email protected]>",
"Michael Farrell <[email protected]>",
Expand Down Expand Up @@ -54,16 +54,20 @@ members = [
# Due to --cfg=web_sys_unstable_apis
exclude = ["compat_tester/webauthn-rs-demo-wasm", "tutorial/wasm"]

[patch.crates-io]
# crypto-glue = { path = "../crypto-glue" }
crypto-glue = { git = "https://github.com/kanidm/crypto-glue.git", branch = "6.0-webauthn-rs" }

[workspace.dependencies]
# These are in release/dependency order.
base64urlsafedata = { path = "./base64urlsafedata", version = "=0.5.2" }
fido-hid-rs = { path = "./fido-hid-rs", version = "=0.5.2" }
webauthn-attestation-ca = { path = "./attestation-ca", version = "=0.5.2" }
webauthn-rs-proto = { path = "./webauthn-rs-proto", version = "=0.5.2" }
fido-mds = { path = "./fido-mds", version = "=0.5.2" }
webauthn-rs-core = { path = "./webauthn-rs-core", version = "=0.5.2" }
webauthn-rs = { path = "./webauthn-rs", version = "=0.5.2" }
webauthn-authenticator-rs = { path = "./webauthn-authenticator-rs", version = "=0.5.2" }
base64urlsafedata = { path = "./base64urlsafedata", version = "=0.6.0-dev" }
fido-hid-rs = { path = "./fido-hid-rs", version = "=0.6.0-dev" }
webauthn-attestation-ca = { path = "./attestation-ca", version = "=0.6.0-dev" }
webauthn-rs-proto = { path = "./webauthn-rs-proto", version = "=0.6.0-dev" }
fido-mds = { path = "./fido-mds", version = "=0.6.0-dev" }
webauthn-rs-core = { path = "./webauthn-rs-core", version = "=0.6.0-dev" }
webauthn-rs = { path = "./webauthn-rs", version = "=0.6.0-dev" }
webauthn-authenticator-rs = { path = "./webauthn-authenticator-rs", version = "=0.6.0-dev" }

# Currently un-released
cable-tunnel-server-common = { path = "./cable-tunnel-server/common", version = "0.1.0" }
Expand All @@ -73,7 +77,9 @@ async-std = { version = "1.6", features = ["attributes"] }
anyhow = "1.0"
base64 = "0.21"
clap = { version = "^4.5", features = ["derive", "env"] }
compact_jwt = "0.4.2"

crypto-glue = "^0.1.8"
compact_jwt = "0.5.1-dev"
futures = "^0.3.25"
hex = "0.4.3"
http = "^0.2.9"
Expand Down
7 changes: 6 additions & 1 deletion attestation-ca/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ repository = { workspace = true }
base64urlsafedata.workspace = true
serde.workspace = true
tracing.workspace = true
uuid = { workspace = true, features = ["serde"] }
crypto-glue.workspace = true

openssl.workspace = true
openssl-sys.workspace = true
uuid = { workspace = true, features = ["serde"] }

[build-dependencies]
openssl.workspace = true
35 changes: 25 additions & 10 deletions attestation-ca/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use base64urlsafedata::Base64UrlSafeData;
use openssl::error::ErrorStack as OpenSSLErrorStack;
use openssl::{hash, x509};
use openssl::{hash, x509 as ox509};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

use crypto_glue::{
traits::{DecodeDer, DecodePem, EncodeDer},
x509,
};

use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -45,7 +50,8 @@ pub struct SerialisableAttestationCa {
)]
pub struct AttestationCa {
/// The x509 root CA of the attestation chain that a security key will be attested to.
ca: x509::X509,
ca_openssl: ox509::X509,
ca: x509::Certificate,
/// If not empty, the set of acceptable AAGUIDS (Device Ids) that are allowed to be
/// attested as trusted by this CA. AAGUIDS that are not in this set, but signed by
/// this CA will NOT be trusted.
Expand All @@ -69,18 +75,23 @@ impl TryFrom<SerialisableAttestationCa> for AttestationCa {

fn try_from(data: SerialisableAttestationCa) -> Result<Self, Self::Error> {
Ok(AttestationCa {
ca: x509::X509::from_der(data.ca.as_slice())?,
ca_openssl: ox509::X509::from_der(data.ca.as_slice())?,
ca: x509::Certificate::from_der(data.ca.as_slice()).unwrap(),
aaguids: data.aaguids,
blanket_allow: data.blanket_allow,
})
}
}

impl AttestationCa {
pub fn ca(&self) -> &x509::X509 {
pub fn ca(&self) -> &x509::Certificate {
&self.ca
}

pub fn ca_openssl(&self) -> &ox509::X509 {
&self.ca_openssl
}

pub fn aaguids(&self) -> &BTreeMap<Uuid, DeviceDescription> {
&self.aaguids
}
Expand All @@ -91,7 +102,7 @@ impl AttestationCa {

/// Retrieve the Key Identifier for this Attestation Ca
pub fn get_kid(&self) -> Result<Vec<u8>, OpenSSLErrorStack> {
self.ca
self.ca_openssl
.digest(hash::MessageDigest::sha256())
.map(|bytes| bytes.to_vec())
}
Expand All @@ -114,7 +125,8 @@ impl AttestationCa {

fn new_from_pem(data: &[u8]) -> Result<Self, OpenSSLErrorStack> {
Ok(AttestationCa {
ca: x509::X509::from_pem(data)?,
ca_openssl: ox509::X509::from_pem(data)?,
ca: x509::Certificate::from_pem(data).unwrap(),
aaguids: BTreeMap::default(),
blanket_allow: true,
})
Expand Down Expand Up @@ -249,19 +261,22 @@ impl AttestationCaListBuilder {

pub fn insert_device_x509(
&mut self,
ca: x509::X509,
ca_openssl: ox509::X509,
aaguid: Uuid,
desc_english: String,
desc_localised: BTreeMap<String, String>,
) -> Result<(), OpenSSLErrorStack> {
let kid = ca
let ca = x509::Certificate::from_der(&ca_openssl.to_der().unwrap()).unwrap();

let kid = ca_openssl
.digest(hash::MessageDigest::sha256())
.map(|bytes| bytes.to_vec())?;

let mut att_ca = if let Some(att_ca) = self.cas.remove(&kid) {
att_ca
} else {
AttestationCa {
ca_openssl,
ca,
aaguids: BTreeMap::default(),
blanket_allow: false,
Expand All @@ -282,7 +297,7 @@ impl AttestationCaListBuilder {
desc_english: String,
desc_localised: BTreeMap<String, String>,
) -> Result<(), OpenSSLErrorStack> {
let ca = x509::X509::from_der(ca_der)?;
let ca = ox509::X509::from_der(ca_der)?;
self.insert_device_x509(ca, aaguid, desc_english, desc_localised)
}

Expand All @@ -293,7 +308,7 @@ impl AttestationCaListBuilder {
desc_english: String,
desc_localised: BTreeMap<String, String>,
) -> Result<(), OpenSSLErrorStack> {
let ca = x509::X509::from_pem(ca_pem)?;
let ca = ox509::X509::from_pem(ca_pem)?;
self.insert_device_x509(ca, aaguid, desc_english, desc_localised)
}

Expand Down
1 change: 0 additions & 1 deletion fido-mds/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ webauthn-attestation-ca.workspace = true
base64.workspace = true
crc32c = "^0.6.4"
compact_jwt.workspace = true
openssl.workspace = true
peg = "0.8.1"
serde.workspace = true
serde_json.workspace = true
Expand Down
27 changes: 15 additions & 12 deletions fido-mds/src/mds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
//! This allows parsing the fido metadata blob and consuming it's content. See `FidoMds`
//! for more.

use compact_jwt::{crypto::JwsX509VerifierBuilder, JwsCompact, JwsVerifier, JwtError};
use openssl::x509;
use compact_jwt::{
crypto::{Certificate, DecodePem, JwsX509VerifierBuilder},
JwsCompact, JwsVerifier, JwtError,
};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;

use std::collections::BTreeMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::str::FromStr;
use std::time::SystemTime;
use uuid::Uuid;

static GLOBAL_SIGN_ROOT_CA_R3: &str = r#"
Expand Down Expand Up @@ -1129,20 +1131,21 @@ impl FromStr for FidoMds {

fn from_str(s: &str) -> Result<Self, Self::Err> {
// Setup the trusted CA store so that we can validate the authenticity of the MDS blob.
let root_ca = x509::X509::from_pem(GLOBAL_SIGN_ROOT_CA_R3.as_bytes())
.map_err(|_| JwtError::OpenSSLError)?;
let root_ca = Certificate::from_pem(GLOBAL_SIGN_ROOT_CA_R3.as_bytes())
.map_err(|_| JwtError::CryptoError)?;

let jws = JwsCompact::from_str(s)?;

let fullchain = jws
let (leaf, chain) = jws
.get_x5c_chain()
.and_then(|chain| chain.ok_or(JwtError::InvalidHeaderFormat))?;

let verifier = JwsX509VerifierBuilder::new()
.add_fullchain(fullchain)
let now = SystemTime::now();

let verifier = JwsX509VerifierBuilder::new(&leaf, &chain)
.add_trust_root(root_ca)
.build()
.map_err(|_| JwtError::OpenSSLError)?;
.build(now)
.map_err(|_| JwtError::CryptoError)?;

// Now we can release the embedded cert, since we have asserted the trust in the chain
// that has signed this metadata.
Expand Down
2 changes: 1 addition & 1 deletion sshkey-attest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ repository = { workspace = true }
[dependencies]
base64.workspace = true
base64urlsafedata.workspace = true
crypto-glue.workspace = true
nom.workspace = true
openssl.workspace = true
serde.workspace = true
serde_cbor_2.workspace = true
sshkeys = { version = "0.3.3", features = ["serde"] }
Expand Down
Loading
Loading