Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/nss-rs/src/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 6 kB image not shown  

Quelle  lib.rs

  Sprache: Rust
 

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![cfg_attr(coverage_nightly, feature(coverage_attribute))]

pub mod agent;
mod agentio;
mod auth;
mod cert;
pub mod constants;
mod ech;
#[macro_use]
mod util;
#[macro_use]
mod err;
#[macro_use]
mod exp;
pub mod ext;
#[cfg(all(not(feature = "disable-encryption"), feature = "blapi"))]
pub(cratemod freebl;
pub mod hkdf;
pub mod hp;

pub mod aead;
pub mod der;
pub mod ec;
pub mod hash;
pub mod hmac;
pub mod p11;
pub mod pbkdf2;
pub mod pk11_utils;
mod prio;
mod replay;
mod secrets;
pub mod selfencrypt;
mod ssl;
pub mod time;

use std::{
    ffi::CString,
    path::{Path, PathBuf},
    ptr::null,
};

use log::error;
use once_cell::sync::OnceCell;

#[cfg(windows)]
#[expect(unused_imports, reason = "Force Advapi32 linkage")]
mod _link_anchor {
    use windows::Win32::Security::Authentication::Identity::RtlGenRandom as _;
}

pub use self::{
    aead::{Mode, RecordProtection, RecordProtectionOps},
    agent::{
        Agent, AllowZeroRtt, Client, HandshakeState, Record, RecordList, ResumptionToken,
        SecretAgent, SecretAgentInfo, SecretAgentPreInfo, Server, ZeroRttCheckResult,
        ZeroRttChecker,
    },
    auth::AuthenticationStatus,
    constants::*,
    ech::{
        AeadId, KdfId, KemId, SymmetricSuite, encode_config as encode_ech_config,
        generate_keys as generate_ech_keys,
    },
    err::{Error, IntoResult, PRErrorCode, Res, secstatus_to_res},
    ext::{ExtensionHandler, ExtensionHandlerResult, ExtensionWriterResult},
    p11::{PrivateKey, PublicKey, SymKey, random, randomize},
    replay::AntiReplay,
    secrets::SecretDirection,
    ssl::Opt,
    util::*,
};

mod min_version;
use min_version::MINIMUM_NSS_VERSION;

pub mod nss_prelude {
    #![allow(
        non_snake_case,
        non_upper_case_globals,
        clippy::restriction,
        reason = "For included bindgen code."
    )]
    pub use _SECStatus::*;

    include!(concat!(env!("OUT_DIR"), "/nss_prelude.rs"));
}
pub use nss_prelude::{SECItem, SECItemArray, SECItemType, SECStatus};

#[expect(non_upper_case_globals, reason = "Code is bindgen-generated.")]
mod nss {
    use crate::nss_prelude::*;
    include!(concat!(env!("OUT_DIR"), "/nss_init.rs"));
}

enum NssLoaded {
    External,
    NoDb,
    #[expect(dead_code)]
    Db(Box<Path>),
}

impl Drop for NssLoaded {
    fn drop(&mut self) {
        if !matches!(selfSelf::External) {
            unsafe {
                secstatus_to_res(nss::NSS_Shutdown()).expect("NSS Shutdown failed");
            }
        }
    }
}

static INITIALIZED: OnceCell<Res<NssLoaded>> = OnceCell::new();

fn version_check() -> Res<()> {
    let min_ver = CString::new(MINIMUM_NSS_VERSION)?;
    if unsafe { nss::NSS_VersionCheck(min_ver.as_ptr()) } == 0 {
        error!("Minimum NSS version of {MINIMUM_NSS_VERSION} not supported");
        return Err(Error::UnsupportedVersion);
    }
    Ok(())
}

/// This enables SSLTRACE by calling a simple, harmless function to trigger its
/// side effects.  SSLTRACE is not enabled in NSS until a socket is made or
/// global options are accessed.  Reading an option is the least impact approach.
/// This allows us to use SSLTRACE in all of our unit tests and programs.
#[cfg(debug_assertions)]
fn enable_ssl_trace() -> Res<()> {
    let opt = Opt::Locking.as_int();
    let mut v: ::std::os::raw::c_int = 0;
    secstatus_to_res(unsafe { ssl::SSL_OptionGetDefault(opt, &raw mut v) })
}

fn init_once(db: Option<PathBuf>) -> Res<NssLoaded> {
    // Set time zero.
    time::init();
    version_check()?;
    if unsafe { nss::NSS_IsInitialized() != 0 } {
        return Ok(NssLoaded::External);
    }

    let state = if let Some(path) = db {
        if !path.is_dir() {
            return Err(Error::Internal);
        }
        let pathstr = path.to_str().ok_or(Error::Internal)?;
        let dircstr = CString::new(pathstr)?;
        let empty = CString::new("")?;
        secstatus_to_res(unsafe {
            nss::NSS_Initialize(
                dircstr.as_ptr(),
                empty.as_ptr(),
                empty.as_ptr(),
                nss::SECMOD_DB.as_ptr().cast(),
                nss::NSS_INIT_READONLY,
            )
        })?;

        secstatus_to_res(unsafe {
            ssl::SSL_ConfigServerSessionIDCache(102400, dircstr.as_ptr())
        })?;
        NssLoaded::Db(path.into_boxed_path())
    } else {
        secstatus_to_res(unsafe { nss::NSS_NoDB_Init(null()) })?;
        NssLoaded::NoDb
    };

    secstatus_to_res(unsafe { nss::NSS_SetDomesticPolicy() })?;

    #[cfg(debug_assertions)]
    enable_ssl_trace()?;

    Ok(state)
}

/// Initialize NSS.  This only executes the initialization routines once, so if there is any chance
/// that this is invoked twice, that's OK.
///
/// # Errors
///
/// When NSS initialization fails.
pub fn init() -> Res<()> {
    let res = INITIALIZED.get_or_init(|| init_once(None));
    res.as_ref().map(|_| ()).map_err(Clone::clone)
}

/// The path to the default NSS database used for testing.
pub const TEST_FIXTURE_DB: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/test-fixture/db");

/// The path to the FIPS-mode NSS database used for testing.
pub const TEST_FIXTURE_DB_FIPS: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/test-fixture/db-fips");

/// Initialize with a database.
///
/// # Errors
///
/// If NSS cannot be initialized.
pub fn init_db<P: Into<PathBuf>>(dir: P) -> Res<()> {
    let res = INITIALIZED.get_or_init(|| init_once(Some(dir.into())));
    res.as_ref().map(|_| ()).map_err(Clone::clone)
}

/// # Panics
///
/// If NSS isn't initialized.
pub fn assert_initialized() {
    INITIALIZED
        .get()
        .expect("NSS not initialized with init or init_db");
}

/// NSS tends to return empty "slices" with a null pointer, which will cause
/// `std::slice::from_raw_parts` to panic if passed directly.  This wrapper avoids
/// that issue.  It also performs conversion for lengths, as a convenience.
///
/// # Panics
/// If the provided length doesn't fit into a `usize`.
///
/// # Safety
/// The caller must adhere to the safety constraints of `std::slice::from_raw_parts`,
/// except that this will accept a null value for `data`.
unsafe fn null_safe_slice<'a, T, L>(data: *const T, len: L) -> &'a [T]
where
    usize: TryFrom<L>,
{
    let len = usize::try_from(len).unwrap_or_else(|_| panic!("null_safe_slice: size overflow"));
    if data.is_null() || len == 0 {
        &[]
    } else {
        unsafe {
            #[expect(clippy::disallowed_methods, reason = "This is non-null.")]
            std::slice::from_raw_parts(data, len)
        }
    }
}

Messung V0.5 in Prozent
C=86 H=91 G=88

¤ Dauer der Verarbeitung: 0.26 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.