RustCrypto Utils

repository·master·Indexed 20 days ago

https://github.com/rustcrypto/utils

A collection of specialized utility crates for the RustCrypto project, providing low-level cryptographic primitives, hardware-specific optimizations, and secure data handling. Includes crates such as aarch64-dit for Data Independent Timing, blobby for binary data parsing, block-buffer and block-padding for data processing, cmov for constant-time conditional moves, cpubits for word size selection, cpufeatures for runtime CPU feature detection, and ctutils for constant-time Choice and CtOption types.

Tokens
32.7K
Snippets
100
Records
134
Agent score
71%

What's inside rustcrypto-utils

  1. Overview of the inout crate

    master

    The inout crate provides custom reference types designed for code that needs to be generic over two different modes of operation:

    1. In-place mode: Operations that modify data directly in its existing memory location.
    2. Buffer-to-buffer mode: Operations that read from an input buffer and write the result to a separate output buffer.

    This abstraction allows developers to write cryptographic or data-processing logic once and support both memory-efficient in-place updates and safer buffer-to-buffer transformations.

  2. Overview of RustCrypto: Utilities crates

    master

    The rustcrypto/utils repository is a collection of specialized utility crates designed for cryptographic applications. These crates provide low-level primitives, hardware feature detection, constant-time utilities, and data handling tools used across the broader RustCrypto ecosystem.

    Key functional areas include:

    • Hardware & CPU Features: aarch64-dit (AArch64 Data-Independent Timing), cpufeatures (efficient CPU feature detection), and cpubits (optimal word size detection).
    • Cryptographic Primitives & Helpers: ctutils (constant-time selection and equality), cmov (conditional move intrinsics), dbl (Galois Field double operations), and block-padding (message padding/unpadding).
    • Data Handling & Buffering: block-buffer (fixed-size block processing), blobby (binary blob storage decoder), sponge-cursor (sponge-based absorption/squeezing), and hex-literal (compile-time hex to byte array conversion).
    • Security & Memory: zeroize (secure memory zeroing) and inout (generic in-place/buffer-to-buffer reference types).
  3. Overview of the block-buffer crate

    master
    The block-buffer crate provides a specialized buffer type designed for block processing of data. Its primary goal is to minimize the occurrence of unreachable panics during cryptographic or data-processing operations involving fixed-size blocks.
  4. Overview of ctutils constant-time utilities

    master

    The ctutils crate provides constant-time equivalents of Rust's bool and Option types, specifically Choice and CtOption. It is designed for cryptographic applications where execution time must not depend on secret data.

    Key features include:

    • Choice: A constant-time boolean replacement.
    • CtOption: A constant-time Option replacement that uses eagerly evaluated combinators to maintain constant-time properties.
    • const fn support: Extensive use of const fn allows for constant-time logic to be executed at compile time.
    • Hardware Acceleration: Uses the cmov crate to leverage architecture-specific predication intrinsics (like conditional moves) on x86_64 and aarch64 for guaranteed constant-time equality and selection.
    • No Copy bounds: Unlike many constant-time libraries, ctutils works with both stack-allocated and heap-allocated types.
    • Expanded Traits: Includes CtFind and CtLookup for constant-time operations on arrays and slices.

    ⚠️ Security Warning: This implementation has never been independently audited. Use at your own risk.

  5. Use AArch64 Data-Independent Timing (DIT) to prevent timing sidechannels

    master
    The aarch64-dit crate provides wrappers for enabling or disabling the Data-Independent Timing (DIT) feature on modern AArch64 CPUs. Enabling DIT helps ensure that instructions execute in a constant amount of time regardless of the input data, which is a critical defense against information leaks via timing sidechannels in cryptographic implementations.
  6. Use the block-padding crate for message padding and unpadding

    master
    The block-padding crate provides tools for padding and unpadding messages that are divided into blocks. It is centered around the Padding trait, which defines the methods required to apply padding to a buffer or remove it (unpadding). The crate includes several common padding schemes ready for use out of the box.
  7. Use `zeroize_derive` for automatic memory zeroing

    master

    zeroize_derive provides custom derive support for the zeroize crate. It allows you to automatically implement the Zeroize trait for your structs and enums, ensuring that sensitive data in memory is securely zeroed out when dropped, while preventing compiler optimizations from removing the zeroing operation.

    Note: This crate is a helper for the zeroize crate and is not intended to be used directly. For core functionality and detailed API documentation, refer to the [zeroize] crate.

  8. Detect CPU features at runtime with `cpufeatures`

    master

    The cpufeatures crate provides lightweight, efficient, and no_std-compatible runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 architectures. It serves as an alternative to the std-dependent is_x86_feature_detected! macro, making it suitable for mobile targets (iOS, Android) and embedded environments.

    Key Characteristics

    • no_std support: Works in environments without the Rust standard library.
    • Caching: The first call to the detection logic caches the result, ensuring subsequent calls have minimal runtime overhead.
    • Compiler Optimization: If target features are enabled via compiler flags (e.g., RUSTFLAGS), the get() method will always return true and init() will skip the CPUID instruction, allowing the compiler to eliminate fallback code paths.
    • Architecture Support: Supports aarch64 (Linux, iOS, macOS/ARM), loongarch64 (Linux), and x86/x86_64 (OS independent).
    // Add cpufeatures to your Cargo.toml
    // [dependencies]
    // cpufeatures = "..."
    
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    pub mod x86_backend {
        // Use the `new!` macro to create a detection module for specific features.
        // Syntax: cpufeatures::new!(module_name, feature_1, feature_2, ...);
        cpufeatures::new!(cpuid_aes_sha, "aes", "sha");
    
        pub fn run() {
            // 1. Initialize the detection and get an `InitToken`.
            // The `InitToken` is a Zero Sized Type (ZST) that guarantees
            // the underlying static storage is initialized.
            let token: cpuid_aes_sha::InitToken = cpuid_aes_sha::init();
    
            // 2. Check if the features are supported.
            if token.get() {
                println!("CPU supports both SHA and AES extensions");
            } else {
                println!("SHA and AES extensions are not supported");
            }
    
            // 3. Alternative: Get the value directly without managing a token.
            // This is useful if the value is only needed once.
            let val = cpuid_aes_sha::get();
            assert_eq!(val, token.get());
        
            // 4. Alternative: Get both the token and the value at once.
            let (token, val) = cpuid_aes_sha::init_get();
            assert_eq!(val, token.get());
        }
    }
  9. What is the cmov crate and when to use it

    master

    The cmov crate provides low-level CPU intrinsics for conditional moves (predication). These allow selecting between values without using branch instructions, ensuring the operation is constant-time and resistant to timing side-channels caused by branch prediction or speculative execution.

    Key Characteristics:

    • Guaranteed Constant-Time: Uses inline asm! to prevent the compiler (e.g., LLVM) from rewriting instructions into branches (like the x86-cmov-conversion pass).
    • Low-Level API: Designed as a building block for creating portable constant-time abstractions across different CPU architectures.
    • Not for General Use: If you need a higher-level API, use the [ctutils] crate instead.

    Supported Architectures with Native Instructions:

    • x86/x86_64 (CMOVZ, CMOVNZ)
    • aarch64 (CSEL)

    Fallback Behavior: On other architectures (like arm, riscv32, or riscv64), the crate uses a "best effort" portable fallback based on bitwise arithmetic and core::hint::black_box. While designed to be branch-free, constant-time execution cannot be strictly guaranteed on these fallback paths due to potential future compiler optimizations.

  10. What is the `dbl` crate used for?

    master
    The dbl crate provides a double operation (also known as "multiply-by-x") in the Galois Field GF(2^n). It specifically uses the lexicographically first polynomial among the irreducible degree n polynomials that has a minimum number of coefficients.
  11. Understand the Blobby (.blb) storage format

    master

    The Blobby format is a deduplicated storage format for a sequence of binary blobs using git-flavored Variable-Length Quantity (VLQ) for encoding unsigned numbers.

    Format Structure

    1. Header: Contains two numbers:
      • n: Total number of blobs in the file.
      • d: Number of de-duplicated blobs.
    2. De-duplicated Entries: d entries follow the header. Each entry consists of an integer m (the size) followed by m bytes of the blob.
    3. Sequence Entries: n entries follow the de-duplicated section. Each entry starts with an unsigned integer l:
      • If the least significant bit of l is 0: The integer represents the length, followed by l >> 1 bytes of raw data.
      • If the least significant bit of l is 1: The integer represents a reference to a de-duplicated entry index (l >> 1), which must be less than d.