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

Add support for Webauthn L3 options #435

Merged
merged 5 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions compat_tester/webauthn-rs-demo-shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ rust-version = "1.70.0"
core = ["webauthn-rs-core"]

[dependencies]
base64urlsafedata.workspace = true
serde.workspace = true

webauthn-rs-core = { workspace = true, optional = true }
Expand Down
4 changes: 3 additions & 1 deletion compat_tester/webauthn-rs-demo-shared/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#![deny(warnings)]
#![warn(unused_extern_crates)]

use base64urlsafedata::HumanBinaryData;
use serde::{Deserialize, Serialize};
#[cfg(feature = "core")]
use webauthn_rs_core::error::WebauthnError;

pub use webauthn_rs_core::proto::CredentialID;
pub use webauthn_rs_proto::{
AttestationConveyancePreference, AuthenticationExtensions, AuthenticatorAttachment,
COSEAlgorithm, CreationChallengeResponse, CredProtect, CredentialProtectionPolicy, ExtnState,
Expand All @@ -14,6 +14,8 @@ pub use webauthn_rs_proto::{
UserVerificationPolicy,
};

pub type CredentialID = HumanBinaryData;

#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub enum AttestationLevel {
None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export interface InitOutput {
readonly __wbindgen_malloc: (a: number, b: number) => number;
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
readonly __wbindgen_export_2: WebAssembly.Table;
readonly wasm_bindgen__convert__closures__invoke1_mut_ref__h015a6d4beac911b9: (a: number, b: number, c: number) => void;
readonly wasm_bindgen__convert__closures__invoke1__h9385f9b96e74d99b: (a: number, b: number, c: number) => void;
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hcb3dcc208685cd98: (a: number, b: number, c: number) => void;
readonly wasm_bindgen__convert__closures__invoke1_mut_ref__h0f42758389f9ef59: (a: number, b: number, c: number) => void;
readonly wasm_bindgen__convert__closures__invoke1__h3626c9e41e52d750: (a: number, b: number, c: number) => void;
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h458d161319ed8eb6: (a: number, b: number, c: number) => void;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly __wbindgen_exn_store: (a: number) => void;
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
Expand Down
18 changes: 9 additions & 9 deletions compat_tester/webauthn-rs-demo/pkg/webauthn_rs_demo_wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ function addBorrowedObject(obj) {
}
function __wbg_adapter_48(arg0, arg1, arg2) {
try {
wasm.wasm_bindgen__convert__closures__invoke1_mut_ref__h015a6d4beac911b9(arg0, arg1, addBorrowedObject(arg2));
wasm.wasm_bindgen__convert__closures__invoke1_mut_ref__h0f42758389f9ef59(arg0, arg1, addBorrowedObject(arg2));
} finally {
heap[stack_pointer++] = undefined;
}
Expand Down Expand Up @@ -260,11 +260,11 @@ function makeClosure(arg0, arg1, dtor, f) {
return real;
}
function __wbg_adapter_51(arg0, arg1, arg2) {
wasm.wasm_bindgen__convert__closures__invoke1__h9385f9b96e74d99b(arg0, arg1, addHeapObject(arg2));
wasm.wasm_bindgen__convert__closures__invoke1__h3626c9e41e52d750(arg0, arg1, addHeapObject(arg2));
}

function __wbg_adapter_54(arg0, arg1, arg2) {
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hcb3dcc208685cd98(arg0, arg1, addHeapObject(arg2));
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h458d161319ed8eb6(arg0, arg1, addHeapObject(arg2));
}

/**
Expand Down Expand Up @@ -944,16 +944,16 @@ function __wbg_get_imports() {
const ret = wasm.memory;
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper1109 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 529, __wbg_adapter_48);
imports.wbg.__wbindgen_closure_wrapper1147 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 541, __wbg_adapter_48);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper1612 = function(arg0, arg1, arg2) {
const ret = makeClosure(arg0, arg1, 644, __wbg_adapter_51);
imports.wbg.__wbindgen_closure_wrapper1653 = function(arg0, arg1, arg2) {
const ret = makeClosure(arg0, arg1, 654, __wbg_adapter_51);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_closure_wrapper1703 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 659, __wbg_adapter_54);
imports.wbg.__wbindgen_closure_wrapper1743 = function(arg0, arg1, arg2) {
const ret = makeMutClosure(arg0, arg1, 669, __wbg_adapter_54);
return addHeapObject(ret);
};

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ export function run_app(a: number): void;
export function __wbindgen_malloc(a: number, b: number): number;
export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
export const __wbindgen_export_2: WebAssembly.Table;
export function wasm_bindgen__convert__closures__invoke1_mut_ref__h015a6d4beac911b9(a: number, b: number, c: number): void;
export function wasm_bindgen__convert__closures__invoke1__h9385f9b96e74d99b(a: number, b: number, c: number): void;
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hcb3dcc208685cd98(a: number, b: number, c: number): void;
export function wasm_bindgen__convert__closures__invoke1_mut_ref__h0f42758389f9ef59(a: number, b: number, c: number): void;
export function wasm_bindgen__convert__closures__invoke1__h3626c9e41e52d750(a: number, b: number, c: number): void;
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h458d161319ed8eb6(a: number, b: number, c: number): void;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function __wbindgen_exn_store(a: number): void;
export function __wbindgen_free(a: number, b: number, c: number): void;
4 changes: 2 additions & 2 deletions compat_tester/webauthn-rs-demo/src/actors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,11 @@ impl WebauthnActor {
.ok_or(WebauthnError::CredentialNotFound)?;

self.wan
.generate_challenge_authenticate(vec![cred], uv, extensions, None)
.generate_challenge_authenticate(vec![cred], uv, extensions, None, None)
}
None => self
.wan
.generate_challenge_authenticate(creds, None, extensions, None),
.generate_challenge_authenticate(creds, None, extensions, None, None),
}?;

debug!("complete ChallengeAuthenticate -> {:?}", acr);
Expand Down
9 changes: 4 additions & 5 deletions sshkey-attest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ use uuid::Uuid;
pub use webauthn_rs_core::error::WebauthnError;
use webauthn_rs_core::{
attestation::{
assert_packed_attest_req, validate_extension, verify_attestation_ca_chain,
AttestationFormat, FidoGenCeAaguid,
assert_packed_attest_req, validate_extension, verify_attestation_ca_chain, FidoGenCeAaguid,
},
crypto::{compute_sha256, verify_signature},
internals::AuthenticatorData,
proto::{
AttestationCaList, AttestationMetadata, COSEAlgorithm, COSEKey, COSEKeyType,
CredentialProtectionPolicy, ExtnState, ParsedAttestation, ParsedAttestationData,
RegisteredExtensions, Registration,
AttestationCaList, AttestationFormat, AttestationMetadata, COSEAlgorithm, COSEKey,
COSEKeyType, CredentialProtectionPolicy, ExtnState, ParsedAttestation,
ParsedAttestationData, RegisteredExtensions, Registration,
},
};

Expand Down
3 changes: 1 addition & 2 deletions sshkey-attest/src/proto.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Serialisable formats of attested ssh keys

use serde::{Deserialize, Serialize};
use webauthn_rs_core::attestation::AttestationFormat;
use webauthn_rs_core::proto::{ParsedAttestation, RegisteredExtensions};
use webauthn_rs_core::proto::{AttestationFormat, ParsedAttestation, RegisteredExtensions};

pub use sshkeys::PublicKey;

Expand Down
1 change: 1 addition & 0 deletions webauthn-authenticator-rs/examples/authenticate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ async fn main() {
hmac_get_secret: None,
}),
None,
None,
)
.unwrap();

Expand Down
3 changes: 3 additions & 0 deletions webauthn-authenticator-rs/src/authenticator_hashed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ pub fn perform_register_with_request(
timeout: Some(timeout_ms),
exclude_credentials: Some(request.exclude_list),
// TODO
hints: None,
attestation: None,
attestation_formats: None,
authenticator_selection: None,
extensions: None,
};
Expand Down Expand Up @@ -192,6 +194,7 @@ pub fn perform_auth_with_request(
rp_id: request.rp_id,
allow_credentials: request.allow_list,
// TODO
hints: None,
user_verification: webauthn_rs_proto::UserVerificationPolicy::Preferred,
extensions: None,
};
Expand Down
2 changes: 1 addition & 1 deletion webauthn-authenticator-rs/src/softpasskey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ mod tests {
let cred = wan.register_credential(&r, &reg_state, None).unwrap();

let (chal, auth_state) = wan
.generate_challenge_authenticate(vec![cred], None, None, None)
.generate_challenge_authenticate(vec![cred], None, None, None, None)
.unwrap();

let r = wa
Expand Down
4 changes: 2 additions & 2 deletions webauthn-authenticator-rs/src/softtoken.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ mod tests {
info!("Credential -> {:?}", cred);

let (chal, auth_state) = wan
.generate_challenge_authenticate(vec![cred], None, None, None)
.generate_challenge_authenticate(vec![cred], None, None, None, None)
.unwrap();

let r = wa
Expand Down Expand Up @@ -1014,7 +1014,7 @@ mod tests {
let mut wa = WebauthnAuthenticator::new(soft_token);

let (chal, auth_state) = wan
.generate_challenge_authenticate(vec![cred], None, None, None)
.generate_challenge_authenticate(vec![cred], None, None, None, None)
.unwrap();

let r = wa
Expand Down
48 changes: 2 additions & 46 deletions webauthn-rs-core/src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,52 +341,6 @@ where
})
}

/// The type of attestation on the credential
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash)]
pub enum AttestationFormat {
/// Packed attestation
Packed,
/// TPM attestation (like Micrsoft)
Tpm,
/// Android hardware attestation
AndroidKey,
/// Older Android Safety Net
AndroidSafetyNet,
/// Old U2F attestation type
FIDOU2F,
/// Apple touchID/faceID
AppleAnonymous,
/// No attestation
None,
}

impl AttestationFormat {
/// Only a small number of devices correctly report their transports. These are
/// limited to attested devices, and exclusively packed (fido2) and tpms. Most
/// other devices/browsers will get this wrong, meaning that authentication will
/// fail or not offer the correct transports to the user.
pub(crate) fn transports_valid(&self) -> bool {
matches!(self, AttestationFormat::Packed | AttestationFormat::Tpm)
}
}

impl TryFrom<&str> for AttestationFormat {
type Error = WebauthnError;

fn try_from(a: &str) -> Result<AttestationFormat, Self::Error> {
match a {
"packed" => Ok(AttestationFormat::Packed),
"tpm" => Ok(AttestationFormat::Tpm),
"android-key" => Ok(AttestationFormat::AndroidKey),
"android-safetynet" => Ok(AttestationFormat::AndroidSafetyNet),
"fido-u2f" => Ok(AttestationFormat::FIDOU2F),
"apple" => Ok(AttestationFormat::AppleAnonymous),
"none" => Ok(AttestationFormat::None),
_ => Err(WebauthnError::AttestationNotSupported),
}
}
}

// Perform the Verification procedure for 8.2. Packed Attestation Statement Format
// https://w3c.github.io/webauthn/#sctn-packed-attestation
pub(crate) fn verify_packed_attestation(
Expand Down Expand Up @@ -1432,9 +1386,11 @@ pub fn verify_attestation_ca_chain<'a>(
ParsedAttestationData::AnonCa(chain) => chain,
ParsedAttestationData::Self_ | ParsedAttestationData::None => {
// nothing to check
debug!("No attestation present");
return Ok(None);
}
ParsedAttestationData::ECDAA | ParsedAttestationData::Uncertain => {
debug!("attestation is an unsupported format");
return Err(WebauthnError::AttestationNotVerifiable);
}
};
Expand Down
Loading
Loading