Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/lockstore/lockstore_rs/src/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 8 kB image not shown  

Quelle  lib.rs

  Sprache: Rust
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


pub mod crypto;
mod datastore;
mod keystore;
mod pbkdf2;
mod utils;

pub use crypto::CipherSuite;
pub use crypto::DEFAULT_CIPHER_SUITE;
pub use datastore::LockstoreDatastore;
pub use keystore::{ConnectionHandle, Keystore};
pub use utils::{bytes_to_value, value_to_bytes};

use kvstore::{DatabaseError, StoreError};
use nss_rs::Error as NssError;
use serde::{Deserialize, Serialize};
use thiserror::Error;

pub const KEYSTORE_FILENAME: &str = "lockstore.keys.sqlite";
pub const DATASTORE_FILENAME_PREFIX: &str = "lockstore.data.";
pub const DATASTORE_FILENAME_SUFFIX: &str = ".sqlite";

pub fn datastore_filename(collection_name: &str) -> String {
    format!(
        "{}{}{}",
        DATASTORE_FILENAME_PREFIX, collection_name, DATASTORE_FILENAME_SUFFIX
    )
}

#[derive(Error, Debug)]
pub enum LockstoreError {
    #[error("Store error: {0}")]
    Store(#[from] StoreError),
    #[error("Database error: {0}")]
    Database(#[from] DatabaseError),
    #[error("Serialization error: {0}")]
    Serialization(String),
    #[error("Key not found: {0}")]
    NotFound(String),
    #[error("Encryption error: {0}")]
    Encryption(String),
    #[error("Decryption error: {0}")]
    Decryption(String),
    #[error("Invalid configuration: {0}")]
    InvalidConfiguration(String),
    #[error("DEK is not extractable: {0}")]
    NotExtractable(String),
    #[error("Authentication cancelled")]
    AuthenticationCancelled,
    #[error("Authentication failed")]
    AuthenticationFailed,
    #[error("Token error: {0}")]
    TokenError(String),
    #[error("Invalid kek_ref: {0}")]
    InvalidKekRef(String),
    #[error("NSS initialization failed: {0}")]
    NssInitialization(String),
    #[error("Password KEK is locked")]
    Locked,
    #[error("Password is incorrect")]
    WrongPassword,
    #[error("Password KEK is not initialized")]
    NotInitialized,
    #[error("Locking failure: {0}")]
    LockingFailure(String),
}

impl From<serde_json::Error> for LockstoreError {
    fn from(err: serde_json::Error) -> Self {
        LockstoreError::Serialization(err.to_string())
    }
}

impl From<NssError> for LockstoreError {
    fn from(err: NssError) -> Self {
        LockstoreError::Encryption(err.to_string())
    }
}

pub const KEK_REF_PREFIX: &str = "lockstore::kek::";
/// Prefix for kek_refs that hold raw software AES key bytes. The suffix
/// is a base64url-encoded random ID minted at `createKek` time, so a
/// profile can host many independent local KEKs.
pub const KEK_REF_LOCAL_PREFIX: &str = "lockstore::kek::local:";
/// Prefix for kek_refs that resolve via a PBKDF2-wrapped password. Each
/// kek_ref carries an independent salt + iteration count + wrapped KEK;
/// a profile can host many independent password KEKs.
pub const KEK_REF_PASSWORD_PREFIX: &str = "lockstore::kek::password:";
/// Prefix for kek_refs that resolve via a PKCS#11 token. The suffix is
/// a base64url-encoded random ID minted at `createKek` time, so a
/// single token can host many independent Lockstore KEKs.
pub const KEK_REF_PKCS11_PREFIX: &str = "lockstore::kek::pkcs11:";

/// The kind of KEK identified by a `kek_ref`. Every `KekType` follows the
/// same multi-instance shape: each KEK is one row at
/// `lockstore::kek::<type>:<base64url(random_id)>`, and there are no
/// canonical singletons.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum KekType {
    #[default]
    #[serde(rename = "local")]
    LocalKey,
    #[serde(rename = "pkcs11")]
    Pkcs11Token,
    #[serde(rename = "password")]
    Password,
}

impl KekType {
    pub fn as_str(&self) -> &str {
        match self {
            KekType::LocalKey => "local",
            KekType::Pkcs11Token => "pkcs11",
            KekType::Password => "password",
        }
    }

    pub fn parse(s: &str) -> Option<Self> {
        match s {
            "local" => Some(KekType::LocalKey),
            "pkcs11" => Some(KekType::Pkcs11Token),
            "password" => Some(KekType::Password),
            _ => None,
        }
    }

    pub fn from_kek_ref(kek_ref: &str) -> Result<Self, LockstoreError> {
        if kek_ref.starts_with(KEK_REF_LOCAL_PREFIX) {
            Ok(KekType::LocalKey)
        } else if kek_ref.starts_with(KEK_REF_PASSWORD_PREFIX) {
            Ok(KekType::Password)
        } else if kek_ref.starts_with(KEK_REF_PKCS11_PREFIX) {
            Ok(KekType::Pkcs11Token)
        } else {
            Err(LockstoreError::InvalidKekRef(kek_ref.to_string()))
        }
    }
}

/// Persistent record for a software-only LocalKey. Stored at row
/// `kek_ref` in `lockstore.keys.sqlite` as JSON.
///
/// The KEK is a freshly-generated AES-256 key stored verbatim in
/// `kek_bytes`. LocalKey has no auth mechanism — there's nothing to
/// "unlock" — so the bytes live plaintext in the row. Confidentiality
/// at rest is provided by the underlying SQLite encryption layer; if
/// the keystore file is exfiltrated without that layer's key, the
/// bytes here are still recoverable only with the SQLite key.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LocalKekRecord {
    /// Raw AES-256 KEK bytes (32 bytes for the default cipher suite).
    pub kek_bytes: Vec<u8>,
}

/// Persistent record for a password-protected KEK. Stored at row
/// `kek_ref` in `lockstore.keys.sqlite` as JSON.
///
/// The KEK is a freshly-generated AES-256 software key whose plaintext
/// is never persisted. The on-disk `ciphertext` is the output of
/// `AEAD(AES-GCM, KEY = PBKDF2(password, salt, iterations), PLAINTEXT = kek_plaintext)`
/// produced by `crypto::encrypt_with_key`. AEAD tag verification on
/// unwrap doubles as the wrong-password check: a tag failure means the
/// supplied password did not yield the original wrapping key.
///
/// Each password kek_ref carries an independent salt and iteration
/// count, so a profile can host any number of password KEKs (e.g. one
/// per user, or per security boundary) with no shared state.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PasswordKekRecord {
    /// AES-GCM ciphertext of the software KEK, self-describing
    /// (`[cipher_suite_id || nonce || ct+tag]`).
    pub ciphertext: Vec<u8>,
    /// PBKDF2 salt. 16 bytes per `pbkdf2::PBKDF2_SALT_SIZE`.
    pub salt: Vec<u8>,
    /// PBKDF2 iteration count active when this record was minted.
    /// Persisted so a future hardening pass can rotate the global
    /// default without invalidating existing records.
    pub iterations: u32,
    /// Cipher suite used for the AES-GCM wrap. Persisted alongside
    /// the ciphertext so unwrap can pick the matching algorithm even
    /// after the global default changes.
    pub cipher_suite: CipherSuite,
}

/// Persistent record for a PKCS#11-backed KEK. Stored at row `kek_ref`
/// in `lockstore.keys.sqlite` as JSON.
///
/// The KEK is a freshly-generated AES-256 software key whose plaintext
/// is never persisted. The on-disk `ciphertext` is the output of
/// `AEAD(AES-GCM, KEY = wrapping_key, PLAINTEXT = kek_plaintext)`
/// produced by `crypto::encrypt_with_symkey`, where `wrapping_key` is
/// a long-lived AES key resident on the PKCS#11 token (identified by
/// `wrapping_key_nickname`). Recovery therefore requires the
/// authenticated token slot.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Pkcs11KekRecord {
    /// AES-GCM ciphertext of the software KEK, self-describing
    /// (`[cipher_suite_id || nonce || ct+tag]`).
    pub ciphertext: Vec<u8>,
    /// PKCS#11 URI naming the slot/token that holds the wrapping key.
    pub pkcs11_uri: String,
    /// Nickname (CKA_LABEL) under which the wrapping key is stored on
    /// the token. A fixed per-token nickname is used today, but the
    /// record persists the name explicitly so a future migration can
    /// rotate it without invalidating existing records.
    pub wrapping_key_nickname: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredValue {
    pub data: Vec<u8>,
    pub timestamp: u64,
}

Messung V0.5 in Prozent
C=82 H=100 G=91

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.