Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BIBLIOGRAPHY.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ source code and documentation.
* URL: https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-ig-announcements
* Referenced from:
- [examples/basic_deterministic/mldsa_native/mldsa_native_config.h](examples/basic_deterministic/mldsa_native/mldsa_native_config.h)
- [examples/basic_lowram/mldsa_native/mldsa_native_config.h](examples/basic_lowram/mldsa_native/mldsa_native_config.h)
- [examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h](examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h)
- [examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h](examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h)
- [examples/custom_backend/mldsa_native/mldsa_native_config.h](examples/custom_backend/mldsa_native/mldsa_native_config.h)
Expand Down Expand Up @@ -72,6 +73,7 @@ source code and documentation.
* Referenced from:
- [README.md](README.md)
- [examples/basic_deterministic/mldsa_native/mldsa_native_config.h](examples/basic_deterministic/mldsa_native/mldsa_native_config.h)
- [examples/basic_lowram/mldsa_native/mldsa_native_config.h](examples/basic_lowram/mldsa_native/mldsa_native_config.h)
- [examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h](examples/bring_your_own_fips202/mldsa_native/mldsa_native_config.h)
- [examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h](examples/bring_your_own_fips202_static/mldsa_native/mldsa_native_config.h)
- [examples/custom_backend/mldsa_native/mldsa_native_config.h](examples/custom_backend/mldsa_native/mldsa_native_config.h)
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ EXAMPLE_DIRS := \
examples/custom_backend \
examples/basic \
examples/basic_deterministic \
examples/basic_lowram \
examples/monolithic_build \
examples/monolithic_build_native \
examples/monolithic_build_multilevel \
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ make test

We use the [C Bounded Model Checker (CBMC)](https://github.com/diffblue/cbmc) to prove absence of various classes of undefined behaviour in C, including out of bounds memory accesses and integer overflows. The proofs cover all C code in [mldsa/src/*](mldsa) and [mldsa/src/fips202/*](mldsa/src/fips202) involved in running mldsa-native with its C backend. See [proofs/cbmc](proofs/cbmc) for details.

**Note:** The `MLD_CONFIG_REDUCE_RAM` configuration option is not currently covered by CBMC proofs.

HOL-Light functional correctness proofs can be found in [proofs/hol_light/x86_64](proofs/hol_light/x86_64). So far, the following functions have been proven correct:

- x86_64 NTT [ntt.S](mldsa/src/native/x86_64/src/ntt.S)
Expand Down
5 changes: 5 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ See [basic](basic) for a basic example of how to build a single instance of mlds
## Basic_deterministic

See [basic_deterministic](basic_deterministic) for a basic example of how to build a single instance of mldsa-native without `randombytes()` implementation. This allows users to build mldsa-native using only the deterministic API when randomized functions are not required.

## Basic_lowram

See [basic_lowram](basic_lowram) for a basic example of how to build a single instance of mldsa-native with reduced RAM usage (`MLD_CONFIG_REDUCE_RAM`). This is useful for embedded systems with tight RAM constraints.

## Multi-level build (C only)

See [multilevel_build](multilevel_build) for an example of how to build one instance of mldsa-native per security level,
Expand Down
24 changes: 24 additions & 0 deletions examples/basic_deterministic/mldsa_native/mldsa_native_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,30 @@
*****************************************************************************/
/* #define MLD_CONFIG_SERIAL_FIPS202_ONLY */

/******************************************************************************
* Name: MLD_CONFIG_REDUCE_RAM [EXPERIMENTAL]
*
* Description: Set this to reduce RAM usage.
*
* This configuration option is work in progress.
*
* At present it results the following memory saving in signing
* with no impact on performance:
* - ML-DSA-44: 4 KiB
* - ML-DSA-65: 5 KiB
* - ML-DSA-87: 7 KiB
*
* This option is useful for embedded systems with tight RAM
* constraints but relaxed performance requirements.
*
* WARNING: This option is experimental!
* CBMC proofs do not currently cover this configuration option.
* Its scope and configuration may change at any time.
*
*****************************************************************************/
/* #define MLD_CONFIG_REDUCE_RAM */


/************************* Config internals ********************************/

#endif /* MLD_BUILD_INTERNAL */
Expand Down
3 changes: 3 additions & 0 deletions examples/basic_lowram/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT

build/
119 changes: 119 additions & 0 deletions examples/basic_lowram/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Copyright (c) The mlkem-native project authors
# Copyright (c) The mldsa-native project authors
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT

.PHONY: build run clean
.DEFAULT_GOAL := all

CC ?= gcc

# Adjust CFLAGS if needed
CFLAGS := \
-Wall \
-Wextra \
-Werror=unused-result \
-Wpedantic \
-Werror \
-Wmissing-prototypes \
-Wshadow \
-Wpointer-arith \
-Wredundant-decls \
-Wconversion \
-Wsign-conversion \
-Wno-long-long \
-Wno-unknown-pragmas \
-Wno-unused-command-line-argument \
-O3 \
-fomit-frame-pointer \
-std=c99 \
-pedantic \
-MMD \
$(CFLAGS)

# If you want to use the native backends, the compiler needs to know about
# the target architecture. Here, we import the default host detection from
# mldsa-native's tests, but you can write your own or specialize accordingly.
AUTO ?= 1
include auto.mk

# The following only concerns the cross-compilation tests.
# You can likely ignore the following for your application.
#
# Append cross-prefix for cross compilation
# When called from the root Makefile, CROSS_PREFIX has already been added here
ifeq (,$(findstring $(CROSS_PREFIX),$(CC)))
CC := $(CROSS_PREFIX)$(CC)
endif

# Part A:
#
# mldsa-native source and header files
#
# If you are not concerned about minimizing for a specific backend,
# you can just include _all_ source files into your build.
#
# In this example, we compile the individual mldsa-native source files directly.
# Alternatively, you can compile the 'monobuild' source file mldsa_native.c.
# See examples/monolithic_build for that.
MLD_SOURCE=$(wildcard \
mldsa_native/src/*.c \
mldsa_native/src/**/*.c \
mldsa_native/src/**/**/*.c \
mldsa_native/src/**/**/**/*.c)

INC=-Imldsa_native

# Part B:
#
# Random number generator
#
# !!! WARNING !!!
#
# The randombytes() implementation used here is for TESTING ONLY.
# You MUST NOT use this implementation outside of testing.
#
# !!! WARNING !!!
RNG_SOURCE=$(wildcard test_only_rng/*.c)

# Part C:
#
# Your application source code
APP_SOURCE=$(wildcard *.c)

ALL_SOURCE=$(MLD_SOURCE) $(RNG_SOURCE) $(APP_SOURCE)

BUILD_DIR=build
BIN=test_binary

#
# Configuration adjustments
#

# Pick prefix
CFLAGS += -DMLD_CONFIG_NAMESPACE_PREFIX=mldsa

BINARY_NAME_FULL_44=$(BUILD_DIR)/$(BIN)44
BINARY_NAME_FULL_65=$(BUILD_DIR)/$(BIN)65
BINARY_NAME_FULL_87=$(BUILD_DIR)/$(BIN)87
BINARIES_FULL=$(BINARY_NAME_FULL_44) $(BINARY_NAME_FULL_65) $(BINARY_NAME_FULL_87)

$(BINARY_NAME_FULL_44): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=44
$(BINARY_NAME_FULL_65): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=65
$(BINARY_NAME_FULL_87): CFLAGS += -DMLD_CONFIG_PARAMETER_SET=87

$(BINARIES_FULL): $(ALL_SOURCE)
echo "$@"
mkdir -p $(BUILD_DIR)
$(CC) $(CFLAGS) $(INC) $^ -o $@

all: build

build: $(BINARIES_FULL)

run: $(BINARIES_FULL)
$(EXEC_WRAPPER) ./$(BINARY_NAME_FULL_44)
$(EXEC_WRAPPER) ./$(BINARY_NAME_FULL_65)
$(EXEC_WRAPPER) ./$(BINARY_NAME_FULL_87)

clean:
rm -rf $(BUILD_DIR)
45 changes: 45 additions & 0 deletions examples/basic_lowram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[//]: # (SPDX-License-Identifier: CC-BY-4.0)

# Low RAM build

This directory contains a minimal example for how to build mldsa-native with reduced RAM usage.

## Use Case

Use this approach when:
- You are building for an embedded system with tight RAM constraints
- You need to minimize stack usage
- Performance is less critical than memory footprint

## Configuration

The `MLD_CONFIG_REDUCE_RAM` option enables optimizations that reduce RAM usage:
- Uses unions for major allocations to reduce stack usage
- Trades some performance for lower memory footprint

## Components

1. mldsa-native source tree: [`mldsa/src/`](../../mldsa/src) and [`mldsa/src/fips202/`](../../mldsa/src/fips202)
2. A secure random number generator implementing [`randombytes.h`](../../mldsa/src/randombytes.h)
3. Your application source code

## Configuration

The configuration file [mldsa_native_config.h](mldsa_native/mldsa_native_config.h) sets:
- `MLD_CONFIG_PARAMETER_SET`: Security level (44, 65, or 87). Default is 65.
- `MLD_CONFIG_NAMESPACE_PREFIX`: Symbol prefix for the API. Set to `mldsa` in this example.
- `MLD_CONFIG_REDUCE_RAM`: Enables reduced RAM usage optimizations.

To change the security level, modify `MLD_CONFIG_PARAMETER_SET` in the config file or pass it via CFLAGS.

## Usage

```bash
make build # Build the example
make run # Run the example
```

## Warning

The `randombytes()` implementation in `test_only_rng/` is for TESTING ONLY.
You MUST provide a cryptographically secure RNG for production use.
1 change: 1 addition & 0 deletions examples/basic_lowram/auto.mk
1 change: 1 addition & 0 deletions examples/basic_lowram/expected_signatures.h
135 changes: 135 additions & 0 deletions examples/basic_lowram/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright (c) The mldsa-native project authors
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
*/

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Import public mldsa-native API
*
* This requires specifying the parameter set and namespace prefix
* used for the build.
*/
#include <mldsa_native.h>
#include "expected_signatures.h"
#include "test_only_rng/notrandombytes.h"

#define CHECK(x) \
do \
{ \
int rc; \
rc = (x); \
if (!rc) \
{ \
fprintf(stderr, "ERROR (%s,%d)\n", __FILE__, __LINE__); \
return 1; \
} \
} while (0)

#define TEST_MSG \
"This is a test message for ML-DSA digital signature algorithm!"
#define TEST_MSG_LEN (sizeof(TEST_MSG) - 1)

#define TEST_CTX "test_context_123"
#define TEST_CTX_LEN (sizeof(TEST_CTX) - 1)

int main(void)
{
const char test_msg[] = TEST_MSG;
const char test_ctx[] = TEST_CTX;

uint8_t pk[CRYPTO_PUBLICKEYBYTES];
uint8_t sk[CRYPTO_SECRETKEYBYTES];
uint8_t sig[CRYPTO_BYTES];
uint8_t sm[TEST_MSG_LEN + CRYPTO_BYTES]; /* signed message buffer */
uint8_t m2[TEST_MSG_LEN + CRYPTO_BYTES]; /* recovered message buffer */
size_t siglen;
size_t smlen;
size_t mlen;

/* WARNING: Test-only
* Normally, you would want to seed a PRNG with trustworthy entropy here. */
randombytes_reset();

printf("ML-DSA-%d Low RAM Example\n", MLD_CONFIG_PARAMETER_SET);
printf("========================\n\n");

printf("Message: %s\n", test_msg);
printf("Context: %s\n\n", test_ctx);

printf("Generating keypair ... ");

/* Alice generates a public/private key pair */
CHECK(crypto_sign_keypair(pk, sk) == 0);

printf("DONE\n");
printf("Signing message... ");

/* Alice signs the message */
CHECK(crypto_sign_signature(sig, &siglen, (const uint8_t *)test_msg,
TEST_MSG_LEN, (const uint8_t *)test_ctx,
TEST_CTX_LEN, sk) == 0);

printf("DONE\n");
printf("Verifying signature... ");

/* Bob verifies Alice's signature */
CHECK(crypto_sign_verify(sig, siglen, (const uint8_t *)test_msg, TEST_MSG_LEN,
(const uint8_t *)test_ctx, TEST_CTX_LEN, pk) == 0);

printf("DONE\n");
printf("Creating signed message... ");

/* Alternative API: Create a signed message (signature + message combined) */
CHECK(crypto_sign(sm, &smlen, (const uint8_t *)test_msg, TEST_MSG_LEN,
(const uint8_t *)test_ctx, TEST_CTX_LEN, sk) == 0);

printf("DONE\n");
printf("Opening signed message... ");

/* Bob opens the signed message to recover the original message */
CHECK(crypto_sign_open(m2, &mlen, sm, smlen, (const uint8_t *)test_ctx,
TEST_CTX_LEN, pk) == 0);

printf("DONE\n");
printf("Compare messages... ");

/* Verify the recovered message matches the original */
CHECK(mlen == TEST_MSG_LEN);
CHECK(memcmp(test_msg, m2, TEST_MSG_LEN) == 0);

printf("DONE\n\n");

printf("Results:\n");
printf("--------\n");
printf("Public key size: %d bytes\n", CRYPTO_PUBLICKEYBYTES);
printf("Secret key size: %d bytes\n", CRYPTO_SECRETKEYBYTES);
printf("Signature size: %d bytes\n", CRYPTO_BYTES);
printf("Message length: %lu bytes\n", (unsigned long)TEST_MSG_LEN);
printf("Signature length: %lu bytes\n", (unsigned long)siglen);
printf("Signed msg length: %lu bytes\n", (unsigned long)smlen);

#if !defined(MLD_CONFIG_KEYGEN_PCT)
/* Check against expected signature to make sure that
* we integrated the library correctly */
printf("Checking deterministic signature... ");
{
/* Compare the generated signature directly against the expected signature
*/
CHECK(siglen == sizeof(expected_signature));
CHECK(memcmp(sig, expected_signature, siglen) == 0);
}
printf("DONE\n");
#else /* !MLD_CONFIG_KEYGEN_PCT */
printf(
"[WARNING] Skipping KAT test since PCT is enabled and modifies PRNG\n");
#endif /* MLD_CONFIG_KEYGEN_PCT */

printf("Signature verification completed successfully!\n");

printf("\nAll tests passed! ML-DSA signature verification successful.\n");
return 0;
}
1 change: 1 addition & 0 deletions examples/basic_lowram/mldsa_native/mldsa_native.h
Loading