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
3 changes: 3 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/custom_no_randomized_config.h](examples/basic_deterministic/mldsa_native/custom_no_randomized_config.h)
- [examples/custom_backend/mldsa_native/custom_config.h](examples/custom_backend/mldsa_native/custom_config.h)
- [examples/monolithic_build/config_44.h](examples/monolithic_build/config_44.h)
- [examples/monolithic_build/config_65.h](examples/monolithic_build/config_65.h)
- [examples/monolithic_build/config_87.h](examples/monolithic_build/config_87.h)
Expand Down Expand Up @@ -69,6 +70,7 @@ source code and documentation.
* Referenced from:
- [README.md](README.md)
- [examples/basic_deterministic/mldsa_native/custom_no_randomized_config.h](examples/basic_deterministic/mldsa_native/custom_no_randomized_config.h)
- [examples/custom_backend/mldsa_native/custom_config.h](examples/custom_backend/mldsa_native/custom_config.h)
- [examples/monolithic_build/config_44.h](examples/monolithic_build/config_44.h)
- [examples/monolithic_build/config_65.h](examples/monolithic_build/config_65.h)
- [examples/monolithic_build/config_87.h](examples/monolithic_build/config_87.h)
Expand Down Expand Up @@ -363,6 +365,7 @@ source code and documentation.
- [examples/bring_your_own_fips202/README.md](examples/bring_your_own_fips202/README.md)
- [examples/bring_your_own_fips202_static/README.md](examples/bring_your_own_fips202_static/README.md)
- [examples/bring_your_own_fips202_static/custom_fips202/README.md](examples/bring_your_own_fips202_static/custom_fips202/README.md)
- [examples/custom_backend/README.md](examples/custom_backend/README.md)

### `tweetfips`

Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,4 @@ clean:
-make clean -C examples/monolithic_build_multilevel >/dev/null
-make clean -C examples/monolithic_build_native >/dev/null
-make clean -C examples/monolithic_build_multilevel_native >/dev/null
-make clean -C examples/custom_backend >/dev/null
3 changes: 3 additions & 0 deletions examples/custom_backend/.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
117 changes: 117 additions & 0 deletions examples/custom_backend/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# 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
#
# 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/mldsa/src/*.c \
mldsa_native/mldsa/src/**/*.c \
mldsa_native/mldsa/src/**/**/*.c \
mldsa_native/mldsa/src/**/**/**/*.c \
mldsa_native/mldsa/src/**/**/**/**/*.c)

INC=-Imldsa_native -Imldsa_native/mldsa

# 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)


#
# Configuration adjustments
#

# Pick custom config file
CFLAGS+=-DMLD_CONFIG_FILE="\"custom_config.h\""

BUILD_DIR=build
BIN=test_binary

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)
39 changes: 39 additions & 0 deletions examples/custom_backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[//]: # (SPDX-License-Identifier: CC-BY-4.0)

# Using a custom configuration and FIPS-202 backend

This directory contains a minimal example for how to use mldsa-native as a code package, with a custom FIPS-202
backend and a custom configuration. We use [^tiny_sha3] as an example.

## Components

An application using mldsa-native with a custom FIPS-202 backend and custom configuration needs the following:

1. Arithmetic part of the mldsa-native source tree: [`mldsa/src/`](../../mldsa/src). In this example, we disable arithmetic
backends, hence it is safe to remove the entire `native` subfolder.
2. A secure pseudo random number generator, implementing [`randombytes.h`](../../mldsa/src/randombytes.h). **WARNING:** The
`randombytes()` implementation used here is for TESTING ONLY. You MUST NOT use this implementation outside of testing.
3. FIPS-202 part of the mldsa-native source tree, [`fips202/`](../../mldsa/src/fips202). If you only want to use your backend,
you can remove all existing backends; that's what this example does.
4. A custom FIPS-202 backend. In this example, the backend file is
[custom.h](mldsa_native/mldsa/src/fips202/native/custom/custom.h), wrapping
[sha3.c](mldsa_native/mldsa/src/fips202/native/custom/src/sha3.c) and setting `MLD_USE_FIPS202_X1_NATIVE` to indicate that we
replace 1-fold Keccak-F1600.
5. Either modify the existing [config.h](mldsa_native/mldsa/src/config.h), or register a new config. In this example, we add
a new config [custom_config.h](mldsa_native/custom_config.h) and register it from the command line for
`-DMLD_CONFIG_FILE="custom_config.h"` -- no further changes to the build are needed. For the sake of
demonstration, we set a custom namespace. We set `MLD_CONFIG_FIPS202_BACKEND_FILE` to point to our custom FIPS-202
backend, but leave `MLD_CONFIG_USE_NATIVE_BACKEND_ARITH` undefined to indicate that we wish to use the C backend.

## Note

The tiny_sha3 code uses a byte-reversed presentation of the Keccakf1600 state for big-endian targets. Since
mldsa-native's FIPS202 frontend assumes a standard presentation, the corresponding byte-reversal in
[sha3.c](mldsa_native/mldsa/src/fips202/native/custom/src/sha3.c) is removed.

## Usage

Build this example with `make build`, run with `make run`.

<!--- bibliography --->
[^tiny_sha3]: Markku-Juhani O. Saarinen: tiny_sha3, [https://github.com/mjosaarinen/tiny_sha3](https://github.com/mjosaarinen/tiny_sha3)
1 change: 1 addition & 0 deletions examples/custom_backend/auto.mk
1 change: 1 addition & 0 deletions examples/custom_backend/expected_signatures.h
137 changes: 137 additions & 0 deletions examples/custom_backend/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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.
*/
#define MLD_CONFIG_API_PARAMETER_SET MLD_CONFIG_PARAMETER_SET
#define MLD_CONFIG_API_NAMESPACE_PREFIX CUSTOM_TINY_SHA3
#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 Custom Backend 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;
}
Loading