qualia-bioauth 0.1.0

Auth-bound key storage: wrapping a 32-byte key behind platform user authentication (Android BiometricPrompt, Windows Hello).
Documentation
// Copyright (C) 2026 Qualia2FA contributors
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option) any
// later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, see <https://www.gnu.org/licenses/>.

//! Auth-bound key storage: wrapping a 32-byte key so that using it requires the
//! platform's user authentication.
//!
//! # What it is for
//!
//! An application can protect its master key with a password
//! ([`qualia2fa-core`](https://crates.io/crates/qualia2fa-core)'s lock wrap), but a
//! password is something the user types and an attacker can guess. This crate adds
//! the other way in: a **platform-authenticated** wrap. On Android that is an AES key
//! in the Keystore whose use requires a `BiometricPrompt` `CryptoObject`; on Windows
//! it is a Windows Hello credential whose `hmac-secret` output is released only by a
//! Hello gesture.
//!
//! The two wraps are independent: either one opens the same master key, and an
//! application keeps both so that a forgotten password or a re-enrolled fingerprint
//! does not lock the user out.
//!
//! # What this crate is not
//!
//! - It does not know the vault format, the password wrap or any Qualia2FA protocol.
//!   It has no dependency on `qualia2fa-core`; its key type is local.
//! - It does no I/O. The generated bytes are returned to the caller, which decides
//!   where they live.
//! - It is **not** a substitute for a password. The platform can be unavailable, the
//!   user can remove the PIN or the fingerprint, and a credential can be invalidated
//!   by a re-enrolment; the password path must stay in place.
//!
//! # How the guarantee is drawn
//!
//! The wrapped bytes are encrypted with a key that lives in the platform's
//! authentication boundary: the Keystore key on Android, the Hello-bound
//! `hmac-secret` on Windows. A popup whose success callback is merely checked in
//! user-mode is **not** enough — the same process can ignore the callback. The test
//! is "can this process decrypt the wrapped bytes without the platform releasing the
//! key?" If the answer is yes, the wrap is not auth-bound.
//!
//! # File format
//!
//! The outer blob is platform-neutral and self-describing:
//!
//! ```text
//!   magic `Q2FABIO1` (8) | version 1 (1) | backend (1) | wrapped length (4, BE)
//!   | wrapped bytes
//! ```
//!
//! The backend identifies which platform wrote the blob, and the wrapped bytes are
//! private to that backend. See [`crate::format`] for the limits and the rejection rules.
//!
//! # Status
//!
//! - Implemented: the outer format, the key type, the trait, the mock backend, the
//!   unsupported fallback, and the Windows backend (Windows Hello through WebAuthn
//!   `hmac-secret`).
//! - The Windows backend does not trust the attestation's `bPrfEnabled` flag; the first
//!   `GetAssertion` is the test. On Windows 11 23H2 (WebAuthn API version 7) the credential
//!   is created with the flag at zero and the assertion returns without the secret, so the
//!   store reports [`Availability::Unavailable`]; the password path is unaffected. A machine
//!   where the assertion succeeds works even when the flag is zero.
//! - Planned: the Android Keystore backend. Until it is present, Android reports
//!   [`platform::stub::UnsupportedKeyStore`] and the password path is the only way in.

mod error;

pub mod format;
pub mod host;
pub mod key;
#[cfg(any(test, feature = "mock"))]
pub mod mock;
pub mod platform;
pub mod traits;

pub use error::{Error, Result};
pub use host::{DelegatingKeyStore, PlatformSealer};
pub use key::{MASTER_KEY_LEN, MasterKey};
pub use traits::{AuthBoundKeyStore, Availability, Backend};