Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

352 serde bincode #353

Closed
wants to merge 2 commits into from
Closed
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
9 changes: 8 additions & 1 deletion base64urlsafedata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ static ALLOWED_DECODING_FORMATS: &[GeneralPurpose] =
/// when deserializing, will decode from many different types of base64 possible.
pub struct Base64UrlSafeData(pub Vec<u8>);

impl Base64UrlSafeData {
pub fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
}

impl fmt::Display for Base64UrlSafeData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", URL_SAFE_NO_PAD.encode(self))
Expand Down Expand Up @@ -125,7 +131,8 @@ impl<'de> Deserialize<'de> for Base64UrlSafeData {
where
D: Deserializer<'de>,
{
// Was previously _str
// This is deserialize_any because it allows us to pivot between arrays
// of bytes, and strings inside the visitor.
deserializer.deserialize_any(Base64UrlSafeDataVisitor)
}
}
Expand Down
2 changes: 2 additions & 0 deletions webauthn-rs-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ license = "MPL-2.0"
[features]
default = []

danger_serde_bincode = []

[package.metadata.docs.rs]
rustdoc-args = ["--cfg", "docsrs"]

Expand Down
4 changes: 2 additions & 2 deletions webauthn-rs-core/src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ pub(crate) fn verify_tpm_attestation(
// cose_rsa.e != tpm_parms.exponent ||

// check the pkey is the same.
if cose_rsa.n.as_ref() != tpm_modulus {
if cose_rsa.n.as_slice() != tpm_modulus {
return Err(WebauthnError::AttestationTpmPubAreaMismatch);
}
}
Expand All @@ -762,7 +762,7 @@ pub(crate) fn verify_tpm_attestation(
}
}

if x.0 != ecc_points.x || y.0 != ecc_points.y {
if x.as_slice() != ecc_points.x || y.as_slice() != ecc_points.y {
debug!("Invalid X or Y coords in TpmuPublicId");
return Err(WebauthnError::AttestationTpmPubAreaMismatch);
}
Expand Down
38 changes: 25 additions & 13 deletions webauthn-rs-core/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ impl WebauthnCore {
// OUT OF SPEC - exclude any credential that is in our exclude list.
let excluded = exclude_credentials
.iter()
.any(|credid| credid.0.as_slice() == credential.cred_id.0.as_slice());
.any(|credid| credid.as_slice() == credential.cred_id.as_slice());

if excluded {
return Err(WebauthnError::CredentialAlteredAlgFromRequest);
Expand Down Expand Up @@ -927,7 +927,8 @@ impl WebauthnCore {
.iter()
.map(|cred| AllowCredentials {
type_: "public-key".to_string(),
id: cred.cred_id.clone(),
#[allow(clippy::useless_conversion)]
id: cred.cred_id.clone().into(),
transports: cred.transports.clone(),
})
.collect();
Expand Down Expand Up @@ -1015,7 +1016,7 @@ impl WebauthnCore {
// inappropriate for your use case), look up the corresponding credential public key.
let mut found_cred: Option<&Credential> = None;
for cred in creds {
if cred.cred_id.0 == rsp.raw_id.0 {
if cred.cred_id.as_slice() == rsp.raw_id.as_slice() {
found_cred = Some(cred);
break;
}
Expand Down Expand Up @@ -1095,8 +1096,9 @@ impl WebauthnCore {
}
}

#[allow(clippy::useless_conversion)]
Ok(AuthenticationResult {
cred_id: cred.cred_id.clone(),
cred_id: cred.cred_id.clone().into(),
needs_update,
user_verified,
backup_eligible,
Expand Down Expand Up @@ -1651,12 +1653,13 @@ mod tests {

// Create the fake credential that we know is associated
let cred = Credential {
cred_id: Base64UrlSafeData(vec![
cred_id: vec![
106, 223, 133, 124, 161, 172, 56, 141, 181, 18, 27, 66, 187, 181, 113, 251, 187,
123, 20, 169, 41, 80, 236, 138, 92, 137, 4, 4, 16, 255, 188, 47, 158, 202, 111,
192, 117, 110, 152, 245, 95, 22, 200, 172, 71, 154, 40, 181, 212, 64, 80, 17, 238,
238, 21, 13, 27, 145, 140, 27, 208, 101, 166, 81,
]),
]
.into(),
cred: COSEKey {
type_: COSEAlgorithm::ES256,
key: COSEKeyType::EC_EC2(COSEEC2Key {
Expand Down Expand Up @@ -1775,10 +1778,11 @@ mod tests {
let cred = Credential {
counter: 1,
transports: None,
cred_id: Base64UrlSafeData(vec![
cred_id: vec![
179, 64, 237, 0, 28, 248, 197, 30, 213, 228, 250, 139, 28, 11, 156, 130, 69, 242,
21, 48, 84, 77, 103, 163, 66, 204, 167, 147, 82, 214, 212,
]),
]
.into(),
cred: COSEKey {
type_: COSEAlgorithm::ES256,
key: COSEKeyType::EC_EC2(COSEEC2Key {
Expand Down Expand Up @@ -1996,7 +2000,13 @@ mod tests {
let _ = tracing_subscriber::fmt()
.with_max_level(tracing::Level::TRACE)
.try_init();
let ser_cred = r#"{"cred_id":"uZcVDBVS68E_MtAgeQpElJxldF_6cY9sSvbWqx_qRh8wiu42lyRBRmh5yFeD_r9k130dMbFHBHI9RTFgdJQIzQ","cred":{"type_":"ES256","key":{"EC_EC2":{"curve":"SECP256R1","x":[194,126,127,109,252,23,131,21,252,6,223,99,44,254,140,27,230,17,94,5,133,28,104,41,144,69,171,149,161,26,200,243],"y":[143,123,183,156,24,178,21,248,117,159,162,69,171,52,188,252,26,59,6,47,103,92,19,58,117,103,249,0,219,8,95,196]}}},"counter":2,"user_verified":false,"backup_eligible":false,"backup_state":false,"registration_policy":"preferred","extensions":{"cred_protect":"NotRequested","hmac_create_secret":"NotRequested"},"attestation":{"data":{"Basic":["MIICvTCCAaWgAwIBAgIEK_F8eDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzM3MjQ2MzI4MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdMLHhCPIcS6bSPJZWGb8cECuTN8H13fVha8Ek5nt-pI8vrSflxb59Vp4bDQlH8jzXj3oW1ZwUDjHC6EnGWB5i6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjcwEwYLKwYBBAGC5RwCAQEEBAMCAiQwIQYLKwYBBAGC5RwBAQQEEgQQxe9V_62aS5-1gK3rr-Am0DAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCLbpN2nXhNbunZANJxAn_Cd-S4JuZsObnUiLnLLS0FPWa01TY8F7oJ8bE-aFa4kTe6NQQfi8-yiZrQ8N-JL4f7gNdQPSrH-r3iFd4SvroDe1jaJO4J9LeiFjmRdcVa-5cqNF4G1fPCofvw9W4lKnObuPakr0x_icdVq1MXhYdUtQk6Zr5mBnc4FhN9qi7DXqLHD5G7ZFUmGwfIcD2-0m1f1mwQS8yRD5-_aDCf3vutwddoi3crtivzyromwbKklR4qHunJ75LGZLZA8pJ_mXnUQ6TTsgRqPvPXgQPbSyGMf2z_DIPbQqCD_Bmc4dj9o6LozheBdDtcZCAjSPTAd_ui"]},"metadata":"None"},"attestation_format":"Packed"}"#;

let ser_cred = if cfg!(feature = "danger_serde_bincode") {
r#"{"cred_id":[185, 151, 21, 12, 21, 82, 235, 193, 63, 50, 208, 32, 121, 10, 68, 148, 156, 101, 116, 95, 250, 113, 143, 108, 74, 246, 214, 171, 31, 234, 70, 31, 48, 138, 238, 54, 151, 36, 65, 70, 104, 121, 200, 87, 131, 254, 191, 100, 215, 125, 29, 49, 177, 71, 4, 114, 61, 69, 49, 96, 116, 148, 8, 205],"cred":{"type_":"ES256","key":{"EC_EC2":{"curve":"SECP256R1","x":[194,126,127,109,252,23,131,21,252,6,223,99,44,254,140,27,230,17,94,5,133,28,104,41,144,69,171,149,161,26,200,243],"y":[143,123,183,156,24,178,21,248,117,159,162,69,171,52,188,252,26,59,6,47,103,92,19,58,117,103,249,0,219,8,95,196]}}},"counter":2,"user_verified":false,"backup_eligible":false,"backup_state":false,"registration_policy":"preferred","extensions":{"cred_protect":"NotRequested","hmac_create_secret":"NotRequested"},"attestation":{"data":{"Basic":["MIICvTCCAaWgAwIBAgIEK_F8eDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzM3MjQ2MzI4MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdMLHhCPIcS6bSPJZWGb8cECuTN8H13fVha8Ek5nt-pI8vrSflxb59Vp4bDQlH8jzXj3oW1ZwUDjHC6EnGWB5i6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjcwEwYLKwYBBAGC5RwCAQEEBAMCAiQwIQYLKwYBBAGC5RwBAQQEEgQQxe9V_62aS5-1gK3rr-Am0DAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCLbpN2nXhNbunZANJxAn_Cd-S4JuZsObnUiLnLLS0FPWa01TY8F7oJ8bE-aFa4kTe6NQQfi8-yiZrQ8N-JL4f7gNdQPSrH-r3iFd4SvroDe1jaJO4J9LeiFjmRdcVa-5cqNF4G1fPCofvw9W4lKnObuPakr0x_icdVq1MXhYdUtQk6Zr5mBnc4FhN9qi7DXqLHD5G7ZFUmGwfIcD2-0m1f1mwQS8yRD5-_aDCf3vutwddoi3crtivzyromwbKklR4qHunJ75LGZLZA8pJ_mXnUQ6TTsgRqPvPXgQPbSyGMf2z_DIPbQqCD_Bmc4dj9o6LozheBdDtcZCAjSPTAd_ui"]},"metadata":"None"},"attestation_format":"Packed"}"#
} else {
r#"{"cred_id":"uZcVDBVS68E_MtAgeQpElJxldF_6cY9sSvbWqx_qRh8wiu42lyRBRmh5yFeD_r9k130dMbFHBHI9RTFgdJQIzQ","cred":{"type_":"ES256","key":{"EC_EC2":{"curve":"SECP256R1","x":[194,126,127,109,252,23,131,21,252,6,223,99,44,254,140,27,230,17,94,5,133,28,104,41,144,69,171,149,161,26,200,243],"y":[143,123,183,156,24,178,21,248,117,159,162,69,171,52,188,252,26,59,6,47,103,92,19,58,117,103,249,0,219,8,95,196]}}},"counter":2,"user_verified":false,"backup_eligible":false,"backup_state":false,"registration_policy":"preferred","extensions":{"cred_protect":"NotRequested","hmac_create_secret":"NotRequested"},"attestation":{"data":{"Basic":["MIICvTCCAaWgAwIBAgIEK_F8eDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowbjELMAkGA1UEBhMCU0UxEjAQBgNVBAoMCVl1YmljbyBBQjEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEnMCUGA1UEAwweWXViaWNvIFUyRiBFRSBTZXJpYWwgNzM3MjQ2MzI4MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdMLHhCPIcS6bSPJZWGb8cECuTN8H13fVha8Ek5nt-pI8vrSflxb59Vp4bDQlH8jzXj3oW1ZwUDjHC6EnGWB5i6NsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjcwEwYLKwYBBAGC5RwCAQEEBAMCAiQwIQYLKwYBBAGC5RwBAQQEEgQQxe9V_62aS5-1gK3rr-Am0DAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCLbpN2nXhNbunZANJxAn_Cd-S4JuZsObnUiLnLLS0FPWa01TY8F7oJ8bE-aFa4kTe6NQQfi8-yiZrQ8N-JL4f7gNdQPSrH-r3iFd4SvroDe1jaJO4J9LeiFjmRdcVa-5cqNF4G1fPCofvw9W4lKnObuPakr0x_icdVq1MXhYdUtQk6Zr5mBnc4FhN9qi7DXqLHD5G7ZFUmGwfIcD2-0m1f1mwQS8yRD5-_aDCf3vutwddoi3crtivzyromwbKklR4qHunJ75LGZLZA8pJ_mXnUQ6TTsgRqPvPXgQPbSyGMf2z_DIPbQqCD_Bmc4dj9o6LozheBdDtcZCAjSPTAd_ui"]},"metadata":"None"},"attestation_format":"Packed"}"#
};

let cred: Credential = serde_json::from_str(ser_cred).unwrap();
trace!("{:?}", cred);
}
Expand Down Expand Up @@ -2855,12 +2865,13 @@ mod tests {
// Given two credentials with differening policy
let mut creds = vec![
Credential {
cred_id: Base64UrlSafeData(vec![
cred_id: vec![
205, 198, 18, 130, 133, 220, 73, 23, 199, 211, 240, 143, 220, 154, 172, 117,
91, 18, 164, 211, 24, 147, 16, 203, 118, 76, 33, 65, 31, 92, 236, 211, 79, 67,
240, 30, 65, 247, 46, 134, 19, 136, 170, 209, 11, 115, 37, 12, 88, 244, 244,
240, 148, 132, 191, 165, 150, 166, 252, 39, 97, 137, 21, 186,
]),
]
.into(),
cred: COSEKey {
type_: COSEAlgorithm::ES256,
key: COSEKeyType::EC_EC2(COSEEC2Key {
Expand Down Expand Up @@ -2895,12 +2906,13 @@ mod tests {
attestation_format: AttestationFormat::None,
},
Credential {
cred_id: Base64UrlSafeData(vec![
cred_id: vec![
211, 204, 163, 253, 101, 149, 83, 136, 242, 175, 211, 104, 215, 131, 122, 175,
187, 84, 13, 3, 21, 24, 11, 138, 50, 137, 55, 225, 180, 109, 49, 28, 98, 8, 28,
181, 149, 241, 106, 124, 110, 149, 154, 198, 23, 8, 8, 4, 41, 69, 236, 203,
122, 120, 204, 174, 28, 58, 171, 43, 218, 81, 195, 177,
]),
]
.into(),
cred: COSEKey {
type_: COSEAlgorithm::ES256,
key: COSEKeyType::EC_EC2(COSEEC2Key {
Expand Down
4 changes: 2 additions & 2 deletions webauthn-rs-core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,8 +677,8 @@ impl COSEKey {
COSEKeyType::EC_EC2(ecpk) => {
let r: [u8; 1] = [0x04];
Ok(r.iter()
.chain(ecpk.x.0.iter())
.chain(ecpk.y.0.iter())
.chain(ecpk.x.as_slice().iter())
.chain(ecpk.y.as_slice().iter())
.copied()
.collect())
}
Expand Down
47 changes: 40 additions & 7 deletions webauthn-rs-core/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,45 @@ use webauthn_rs_proto::cose::*;
use webauthn_rs_proto::extensions::*;
use webauthn_rs_proto::options::*;

use base64urlsafedata::Base64UrlSafeData;
pub use webauthn_attestation_ca::*;

use base64urlsafedata::Base64UrlSafeData;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

use openssl::{bn, ec, nid, pkey, x509};
use uuid::Uuid;

#[cfg(not(feature = "danger_serde_bincode"))]
type BinaryData = Base64UrlSafeData;

#[cfg(feature = "danger_serde_bincode")]
type BinaryData = Vec<u8>;

/*
#[cfg(feature = "danger_serde_bincode")]
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
/// This is a datawrapper used when the feature `danger_serde_bincode` is enabled. It allows
/// transparently swapping between base64 and vec<u8> for applications that require it.
pub struct DataWrapper(pub Vec<u8>);

#[cfg(feature = "danger_serde_bincode")]
impl DataWrapper {
/// Return a reference to the inner slice of this data.
pub fn as_ref(&self) -> &[u8] {
self.0.as_slice()
}
}

#[cfg(feature = "danger_serde_bincode")]
impl From<Vec<u8>> for DataWrapper {
fn from(data: Vec<u8>) -> Self {
DataWrapper(data)
}
}
*/

/// Representation of an AAGUID
/// <https://www.w3.org/TR/webauthn/#aaguid>
pub type Aaguid = [u8; 16];
Expand Down Expand Up @@ -134,9 +163,9 @@ pub struct COSEEC2Key {
/// The curve that this key references.
pub curve: ECDSACurve,
/// The key's public X coordinate.
pub x: Base64UrlSafeData,
pub x: BinaryData,
/// The key's public Y coordinate.
pub y: Base64UrlSafeData,
pub y: BinaryData,
}

impl TryFrom<&COSEEC2Key> for ec::EcKey<pkey::Public> {
Expand All @@ -146,8 +175,8 @@ impl TryFrom<&COSEEC2Key> for ec::EcKey<pkey::Public> {
let group = ec::EcGroup::from_curve_name((&k.curve).into())?;
let mut ctx = bn::BigNumContext::new()?;
let mut point = ec::EcPoint::new(&group)?;
let x = bn::BigNum::from_slice(k.x.0.as_slice())?;
let y = bn::BigNum::from_slice(k.y.0.as_slice())?;
let x = bn::BigNum::from_slice(k.x.as_slice())?;
let y = bn::BigNum::from_slice(k.y.as_slice())?;
point.set_affine_coordinates_gfp(&group, &x, &y, &mut ctx)?;

ec::EcKey::from_public_key(&group, &point)
Expand All @@ -173,7 +202,7 @@ pub struct COSEOKPKey {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct COSERSAKey {
/// An RSA modulus
pub n: Base64UrlSafeData,
pub n: BinaryData,
/// An RSA exponent
pub e: [u8; 3],
}
Expand Down Expand Up @@ -233,8 +262,12 @@ pub struct COSEKey {
/// and a counter of how many times the authenticator has been used.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Credential {
#[cfg(not(feature = "danger_serde_bincode"))]
/// The ID of this credential.
pub cred_id: CredentialID,
#[cfg(feature = "danger_serde_bincode")]
/// The ID of this credential as a raw u8 array.
pub cred_id: BinaryData,
/// The public key of this credential
pub cred: COSEKey,
/// The counter for this credential
Expand Down Expand Up @@ -318,7 +351,7 @@ impl From<CredentialV3> for Credential {

// prior to 20220520 no multi-device credentials existed to migrate from.
Credential {
cred_id: Base64UrlSafeData(cred_id),
cred_id: cred_id.into(),
cred,
counter,
transports: None,
Expand Down
3 changes: 2 additions & 1 deletion webauthn-rs-core/src/internals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ impl Credential {
let transports = None;

Credential {
cred_id: acd.credential_id.clone(),
#[allow(clippy::useless_conversion)]
cred_id: acd.credential_id.clone().into(),
cred: ck,
counter,
transports,
Expand Down