Mojo-V RISC-V ISA Extension

repository·main·Indexed 40 days ago

https://github.com/toddmaustin/mojo-v

A RISC-V ISA extension providing privacy-oriented, secret computation capabilities. Mojo-V enables secure, data-oblivious execution using dedicated secret registers and encrypted memory. It includes a Certified Random Number Generator (CERTRNG) and supports verifiable mechanisms such as Certified Blind Audit Selection, Certified Lottery and Tie-Breaker, and Verifiable Differentially Private Count.

Tokens
12.3K
Snippets
40
Records
58
Agent score
99%

What's inside Mojo-V

  1. Overview of Mojo-V: Secret Computation for RISC-V

    main

    Mojo-V (pronounced "mojo-five") is a RISC-V ISA extension designed for privacy-oriented programming. It enables secure, efficient, and data-oblivious execution by sequestering sensitive data in dedicated secret registers and encrypting memory using a third-party key.

    Key features include:

    • Blind and Silent Execution: Prevents direct disclosures and side-channel leakage.
    • Seamless Integration: Integrates into the existing RISC-V ISA via a mode bit and four new instructions enforced at decode.
    • High Performance: Offers near-native execution speeds, providing a 5-7 orders of magnitude performance improvement over Fully Homomorphic Encryption (FHE).
  2. Overview of Bringup-Bench benchmarks

    main

    The Bringup-Bench benchmark suite consists of non-trivial code designed to run with minimal system and library dependencies. The benchmarks are categorized into two types:

    1. Integer and String benchmarks: Require only integer and string computation.
    2. Floating Point (FP) benchmarks: Require floating-point support.

    Key benchmark examples include:

    • Cryptographic: aes, blake2b, cipher, rsa-cipher.
    • Mathematical/Algorithmic: ackermann, gcd-list, hanoi, knapsack, monte-carlo, pi-calc, sieve.
    • Data Structures: avl-tree, bloom-filter, graph-tests, priority-queue.
    • Search/String: boyer-moore-search, fuzzy-match, rabinkarp-search, simple-grep.
    • Simulation/Physics: nbody-sim, spirograph, tetris-sim, verlet.
    • Encrypted/Secret Computation: blind-audit, dp-count, heldkarp-tsp, lcs, moving-average, partition-equal, risk-score, variability-sample.
  3. Use the Mojo-V EXO library for encrypted programming

    main

    The Mojo-V EXO library is a C/C++ header-based compatibility layer that allows you to write encrypted algorithms using standard C++ syntax. It provides encrypted scalar wrappers and operator overloading to target the Mojo-V execution model before full LLVM integration is complete.

    Core components include:

    • exo/mojov-exo.h: Provides encrypted scalar wrappers (inte_t<Bits, Signed>, fpe_t<Bits>) and overloaded operators (arithmetic, bitwise, relational, etc.).
    • exo/mojov-intrinsics.h: Provides low-level inline-assembly intrinsics (e.g., _add, _mul, _fadd, _slt, _cmov) that map directly to Mojo-V instruction semantics.

    Use EXO to write encrypted algorithms (like GEMM or bubble sort), exercise Mojo-V semantics in bring-up tests, and support multiple encryption formats from a single source code base.

    // Example of using EXO encrypted types
    #include "exo/mojov-exo.h"
    
    void encrypted_add(inte_t<64, true> a, inte_t<64, true> b) {
        inte_t<64, true> result = a + b; // Uses overloaded operator
    }
  4. What is Bringup-Bench and why use it?

    main

    Bringup-Bench is a collection of C code benchmarks designed for the "bringup" process—the phase where a newly designed CPU, accelerator, compiler, or operating system is verified for functionality.

    Key features for hardware/software developers:

    • Zero library dependencies: Uses the internal libmin library to implement necessary calls.
    • Minimal system dependencies: Only four simple system calls are required to support all benchmarks.
    • Code-based read-only file access: Allows benchmark input files to be packaged directly into the build, facilitating testing in environments without a filesystem.
  5. How certified randomness (CERTRNG) works in EXO

    main

    The CERTRNG rd, site_id instruction generates a fresh 64-bit random value in a secret integer register. It requires that secret-register mode and a valid data contract are active. The 12-bit site_id (0--4095) labels the random leaf in the proof-carrying dataflow graph for provenance tracking but does not affect the randomness itself.

    EXO exposes this at two levels:

    1. Low-level intrinsic: _certrng<SiteId>() in mojov-intrinsics.h. Returns the encrypted storage payload type _uint64e_t.
    2. Application interface: certified_random<SiteId>() in mojov-exo.h. Returns a uint64e_t that can be used directly with encrypted arithmetic and cmov().

    Security Note: Certification proves provenance and dataflow placement; it does not prevent an untrusted service from retrying. Applications should bind draws to a fresh encrypted, client-branded request nonce.

    // Using the application interface for certified randomness
    auto rnd = certified_random<123>();
    // rnd can now be used with encrypted arithmetic
  6. Execute benchmarks using Hash-Alone mode

    main

    Hash-alone execution (e.g., hashalone-host, hashalone-spike) allows pure bare-metal execution without requiring input or output devices.

    Workflow:

    1. Load the benchmark binary.
    2. Jump to the start address specified in the ELF binary.
    3. When the benchmark calls libtarg_success(), the program should spin to terminate.

    Verification:

    • All libtarg_putc() output is automatically routed to an FNV1a hash function.
    • The final hash signature is stored in the memory variable __hashval.
    • To verify your target, compare its __hashval against a reference target like hashalone-spike.
    • hashalone-spike is a deterministic RISC-V model that can be used for cycle-by-cycle comparisons to debug hash mismatches.
  7. How Mojo-V programming and data-oblivious computation works

    main

    Mojo-V is designed for secret computation on RISC-V. The programming model relies on two core pillars:

    1. Encrypted Abstractions: Developers use the EXO library to work with encrypted types rather than raw data.
    2. Data-Oblivious Execution: To prevent side-channel attacks, encrypted values cannot be used in standard conditional branching (e.g., if (encrypted_val == 0)) or as indices for memory access. Instead, developers must use data-oblivious control flow and memory-access patterns provided by the library to ensure the execution trace and memory access patterns remain independent of the secret data.
  8. Understand libmin: The minimal library for Bringup-Bench

    main

    To minimize system infrastructure requirements, Bringup-Bench does not rely on external system libraries. Instead, it uses an internal library called libmin (defined in common/libmin.h).

    libmin provides essential functionality for simple applications, including:

    • I/O & Parsing: Printing values, parsing numbers from text, and options parsing.
    • String & Memory: String processing, memory copy (memcpy), and memory setting (memset).
    • System Interfaces: Program exit interfaces and a dynamic storage allocator.
    • Math & Randomness: Floating-point math functions and pseudo-random number generation.
    • Utilities: Sorting functions, character class tests (similar to ctype.h), and code-based read-only file access functions.
  9. How Mojo-V Safe Disclosure Demonstrators work

    main

    Safe disclosure demonstrators show how Mojo-V can compute over sensitive inputs and disclose only explicitly authorized derived results while trapping unauthorized attempts to reuse data grants.

    Key demonstrators include:

    • private-auction: Finds max bid with encrypted comparisons; protects against raw bid disclosure and tampered grants.
    • vote-tally: Computes aggregate candidate counts; protects against raw ballot disclosure and stale grants.
    • gene-risk: Derives polygenic risk scores; protects against cross-use of score and bucket grants.

    To run a demonstrator manually, use Spike's --mojov-arg=<n> option to select the test path:

    • 0: The positive (honest) path.
    • 1 and higher: Negative disclosure tests (security controls).

    These applications are identified by the MOJOV_DISCAPPS environment variable.

    cd bringup-bench/private-auction
    make TARGET=mojov-spike clean build test
  10. Use data-oblivious selection with cmov

    main

    To maintain data-oblivious semantics and avoid plaintext branches over secret data, EXO provides cmov(...) overloads for both integer and floating-point types. This enables branchless, secret-dependent selection patterns compatible with the Mojo-V execution model.

    Common mappings:

    • cmov(pred, t, f) -> _cmov(...) (integer) or _fcmov(...) (floating-point).
    // Example of branchless selection
    auto result = cmov(predicate, value_if_true, value_if_false);
  11. What are Data Contracts and the DC Multi-tool?

    main

    Data contracts are encrypted packets that allow a Mojo-V CPU's hardware to access the data access key and configuration information (such as memory encryption mode) for a Mojo-V encrypted data set.

    The Data Contract (DC) Multi-tool provides the following capabilities:

    • For Hardware Developers: Create public/private ML-KEM512 key pairs. Public keys are shared with service providers, while private keys are embedded into the Mojo-V hardware.
    • For Data Owners: Create data contracts and encrypt them under the public ML-KEM512 keys of service providers, allowing Mojo-V hardware to perform secret computation on protected 3rd-party data.
  12. Data-oblivious programming restrictions

    main

    To maintain security, EXO code must follow data-oblivious execution patterns. Failure to do so may leak secrets through side channels.

    1. No branching on encrypted predicates: Never use if/else with an encrypted predicate. Use cmov instead.
    2. No secret loop bounds: Do not use encrypted values to control loop trip counts. Use fixed/public bounds and update values inside the loop using cmov or masking.
    3. Non-short-circuiting logic: Logical operators (&&, ||) are explicit operations that evaluate both sides. Do not rely on C++ short-circuiting behavior.
    4. Constant memory access patterns: Avoid secret-indexed memory access. Use regular scans or predicate-based writes (cmov) to ensure access patterns are independent of secrets.
    5. Restrict decryption: Only use .decrypt() in controlled debug or test environments after initializing debug_context(...).