Skip to content
Merged
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
2 changes: 1 addition & 1 deletion cmd/passless/src/authenticator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ impl<S: CredentialStorage + 'static> AuthenticatorService<S> {
plat: true, // Platform authenticator
client_pin: None, // Client PIN support
pin_uv_auth_token: Some(true), // PIN UV auth token
cred_mgmt: None, // Credential management disabled (using custom implementation)
cred_mgmt: Some(true), // Credential management enabled
bio_enroll: None,
large_blobs: None,
ep: None,
Expand Down
109 changes: 3 additions & 106 deletions cmd/passless/src/commands/custom.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/// Custom credential management command handler
///
/// This module provides compatibility with the Yubikey credential management variant (0x41).
/// The standard credential management (0x0a) is handled by soft-fido2's built-in implementation.
/// The standard credential management (0x0a) is handled by soft-fido2's built-in implementation,
/// which properly calls the AuthenticatorCallbacks methods (enumerate_rps, list_credentials, etc.)
/// that read from the actual storage backend.
use crate::authenticator::AuthenticatorService;
use crate::storage::CredentialStorage;

Expand All @@ -10,102 +12,6 @@ use log::debug;
/// Command byte for custom credential management (0x41 Yubikey variant)
pub const CMD_CUSTOM_CREDENTIAL_MGMT: u8 = 0x41;

/// Command byte for standard credential management (0x0a)
pub const CMD_STANDARD_CREDENTIAL_MGMT: u8 = 0x0a;

/// Register standard credential management command (0x0a)
///
/// This implements the standard CTAP credential management command
/// that properly integrates with the storage backend.
pub fn register_standard_credential_mgmt<S: CredentialStorage + 'static>(
service: &mut AuthenticatorService<S>,
) {
debug!("Registering standard credential management command (0x0a)");

service.register_custom_command(CMD_STANDARD_CREDENTIAL_MGMT, move |request| {
debug!(
"STANDARD CREDENTIAL MANAGEMENT HANDLER CALLED with {} bytes: {:02x?}",
request.len(),
&request[..request.len().min(64)]
);

// Parse the CBOR request using the same library as the client
let request_value: soft_fido2_ctap::cbor::Value =
match soft_fido2_ctap::cbor::decode(request) {
Ok(v) => {
debug!("Parsed CBOR request successfully: {:?}", v);
v
}
Err(e) => {
debug!(
"Failed to parse CBOR request: {:?}, raw bytes: {:02x?}",
e, request
);
return Ok(vec![0x36]); // CTAP2_ERR_INVALID_CBOR
}
};

let request_map = match request_value {
soft_fido2_ctap::cbor::Value::Map(m) => m,
_ => {
debug!("Request is not a CBOR map");
return Ok(vec![0x36]); // CTAP2_ERR_INVALID_CBOR
}
};

// Extract subCommand (0x01) - find it in the vec
let mut subcommand = None;
for (key, value) in &request_map {
if let (
soft_fido2_ctap::cbor::Value::Integer(1),
soft_fido2_ctap::cbor::Value::Integer(i),
) = (key, value)
{
subcommand = Some(*i as u8);
break;
}
}
let subcommand = match subcommand {
Some(s) => s,
None => {
debug!("Missing or invalid subCommand");
return Ok(vec![0x36]); // CTAP2_ERR_INVALID_CBOR
}
};

debug!("Processing subcommand: {}", subcommand);

// Handle different subcommands
match subcommand {
0x01 => {
// getMetadata - return hardcoded response for testing
debug!("getMetadata subcommand - returning test response");
// CBOR encoding of {1: 12, 2: 100} (existingCount: 12, maxRemaining: 100)
Ok(vec![0xa2, 0x01, 0x0c, 0x02, 0x18, 0x64])
}
0x02 => {
// enumerateRPsBegin - return hardcoded response for testing
debug!("enumerateRPsBegin subcommand - returning test response");
// CBOR encoding of {1: {1: "example.com"}, 2: h'', 3: 1} (rp: {id: "example.com"}, rpIDHash: empty, totalRPs: 1)
let mut response = vec![
0xa3, 0x01, 0xa1, 0x01, 0x6b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
0x63, 0x6f, 0x6d, 0x02, 0x58, 0x20,
];
response.extend(vec![0u8; 32]); // 32-byte hash
response.extend(vec![0x03, 0x01]); // totalRPs: 1
Ok(response)
}
_ => {
debug!("Unsupported subcommand: {}", subcommand);
// Return empty CBOR map for unsupported subcommands
Ok(vec![0xa0]) // Empty map
}
}
});

debug!("Standard credential management command (0x0a) registered successfully");
}

/// Register custom credential management command (0x41 Yubikey variant)
///
/// This registers a custom command handler that provides compatibility with the
Expand All @@ -127,12 +33,6 @@ pub fn register_yubikey_credential_mgmt<S: CredentialStorage + 'static>(
&request[..request.len().min(32)]
);

// For compatibility, the Yubikey 0x41 command typically expects the same
// format as the standard 0x0a credential management command.
// For now, we return a minimal success response.
// In a full implementation, this could forward to credential management logic
// or handle Yubikey-specific variations.

// Return empty CBOR map (success with no data)
// CBOR: 0xa0 = empty map {}
Ok(vec![0xa0])
Expand Down Expand Up @@ -165,9 +65,6 @@ mod tests {

register_yubikey_credential_mgmt(&mut service.unwrap());

// Test that custom command was registered
// (Further testing would require CTAP protocol simulation)

// Cleanup
let _ = std::fs::remove_dir_all(temp_dir);
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/passless/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::sync::atomic::{AtomicBool, Ordering};

use authenticator::AuthenticatorService;
use clap::Parser;
use commands::custom::{register_standard_credential_mgmt, register_yubikey_credential_mgmt};
use commands::custom::register_yubikey_credential_mgmt;
use env_logger::{Builder, Env};
use log::{debug, error, info, warn};
use shadow_rs::shadow;
Expand Down Expand Up @@ -81,7 +81,6 @@ fn run_with_service<S: CredentialStorage + 'static>(
info!("{}", service.storage_info());

// Register custom commands for compatibility (placeholder for now)
register_standard_credential_mgmt(&mut service);
register_yubikey_credential_mgmt(&mut service);

// Main loop - process CTAP packets
Expand Down
Loading