Skip to main content

soft_fido2_crypto/
lib.rs

1//! Pure Rust cryptographic primitives for FIDO2/CTAP
2//!
3//! This crate provides the cryptographic operations required by the CTAP protocol:
4//!
5//! - **ECDH**: P-256 key agreement for PIN protocol
6//! - **ECDSA**: ES256 signatures for attestation and assertions
7//! - **EdDSA**: Ed25519 signatures for attestation and assertions
8//! - **PIN Protocols**: V1 (AES-256-CBC + HMAC) and V2 (HMAC-only)
9//! - **HMAC-SHA256**: For hmac-secret extension
10//!
11//! All implementations follow the FIDO2 specification:
12//! <https://fidoalliance.org/specs/fido-v2.2-rd-20230321/fido-client-to-authenticator-protocol-v2.2-rd-20230321.html>
13
14#![cfg_attr(not(feature = "std"), no_std)]
15
16pub mod ecdh;
17pub mod ecdsa;
18pub mod eddsa;
19pub mod error;
20pub mod pin_protocol;
21
22// Re-export commonly used types
23pub use error::{CryptoError, Result};
24
25// Re-export zeroize for callers to use with sensitive data
26pub use zeroize::Zeroizing;
27
28/// Compute HMAC-SHA-256
29///
30/// Used by the hmac-secret extension to derive secrets from credentials.
31///
32/// # Arguments
33/// * `key` - The HMAC key (e.g., credential random)
34/// * `data` - The data to authenticate (e.g., salt)
35///
36/// # Returns
37/// 32-byte HMAC-SHA-256 output
38pub fn hmac_sha256(key: &[u8], data: &[u8]) -> [u8; 32] {
39    use hmac::{Hmac, Mac};
40    use sha2::Sha256;
41
42    // SAFETY: HMAC-SHA256 accepts keys of any size per RFC 2104.
43    // If the key is shorter than the block size, it's padded with zeros.
44    // If longer, it's hashed first. This never fails.
45    let mut mac = Hmac::<Sha256>::new_from_slice(key).expect("HMAC-SHA256 accepts any key size");
46    mac.update(data);
47    let result = mac.finalize();
48
49    let mut output = [0u8; 32];
50    output.copy_from_slice(&result.into_bytes());
51    output
52}