Skip to content

Commit

Permalink
CBMC: Add proof for crypto_kem_keypair
Browse files Browse the repository at this point in the history
Straightforward extension of crypto_kem_keypair_derand(),
axiomatizing `randombytes()`.

Signed-off-by: Hanno Becker <[email protected]>
  • Loading branch information
hanno-becker authored and rod-chapman committed Nov 13, 2024
1 parent 1491f84 commit 5eea727
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 26 deletions.
2 changes: 1 addition & 1 deletion cbmc/proofs/crypto_kem_enc_derand/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
PROJECT_SOURCES += $(SRCDIR)/mlkem/kem.c

CHECK_FUNCTION_CONTRACTS=$(MLKEM_NAMESPACE)enc_derand
USE_FUNCTION_CONTRACTS=$(FIPS202_NAMESPACE)sha3_256 $(FIPS202_NAMESPACE)sha3_512 $(MLKEM_NAMESPACE)indcpa_enc $(MLKEM_NAMESPACE)polyvec_frombytes $(MLKEM_NAMESPACE)polyvec_reduce $(MLKEM_NAMESPACE)polyvec_tobytes pk_cmp_polyvec
USE_FUNCTION_CONTRACTS=$(FIPS202_NAMESPACE)sha3_256 $(FIPS202_NAMESPACE)sha3_512 $(MLKEM_NAMESPACE)indcpa_enc $(MLKEM_NAMESPACE)polyvec_frombytes $(MLKEM_NAMESPACE)polyvec_reduce $(MLKEM_NAMESPACE)polyvec_tobytes memcmp
APPLY_LOOP_CONTRACTS=on
USE_DYNAMIC_FRAMES=1

Expand Down
54 changes: 54 additions & 0 deletions cbmc/proofs/crypto_kem_keypair/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SPDX-License-Identifier: Apache-2.0

include ../Makefile_params.common

HARNESS_ENTRY = harness
HARNESS_FILE = crypto_kem_keypair_harness

# This should be a unique identifier for this proof, and will appear on the
# Litani dashboard. It can be human-readable and contain spaces if you wish.
PROOF_UID = crypto_kem_keypair

DEFINES +=
INCLUDES +=

REMOVE_FUNCTION_BODY +=
UNWINDSET +=

PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
PROJECT_SOURCES += $(SRCDIR)/mlkem/kem.c

CHECK_FUNCTION_CONTRACTS=$(MLKEM_NAMESPACE)keypair
USE_FUNCTION_CONTRACTS=$(MLKEM_NAMESPACE)keypair_derand randombytes
APPLY_LOOP_CONTRACTS=on
USE_DYNAMIC_FRAMES=1

# Disable any setting of EXTERNAL_SAT_SOLVER, and choose SMT backend instead
EXTERNAL_SAT_SOLVER=
CBMCFLAGS=--smt2

FUNCTION_NAME = $(MLKEM_NAMESPACE)keypair

# If this proof is found to consume huge amounts of RAM, you can set the
# EXPENSIVE variable. With new enough versions of the proof tools, this will
# restrict the number of EXPENSIVE CBMC jobs running at once. See the
# documentation in Makefile.common under the "Job Pools" heading for details.
# EXPENSIVE = true

# This function is large enough to need...
CBMC_OBJECT_BITS = 10

# If you require access to a file-local ("static") function or object to conduct
# your proof, set the following (and do not include the original source file
# ("mlkem/poly.c") in PROJECT_SOURCES).
# REWRITTEN_SOURCES = $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i
# include ../Makefile.common
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_SOURCE = $(SRCDIR)/mlkem/poly.c
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_FUNCTIONS = foo bar
# $(PROOFDIR)/<__SOURCE_FILE_BASENAME__>.i_OBJECTS = baz
# Care is required with variables on the left-hand side: REWRITTEN_SOURCES must
# be set before including Makefile.common, but any use of variables on the
# left-hand side requires those variables to be defined. Hence, _SOURCE,
# _FUNCTIONS, _OBJECTS is set after including Makefile.common.

include ../Makefile.common
3 changes: 3 additions & 0 deletions cbmc/proofs/crypto_kem_keypair/cbmc-proof.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: Apache-2.0

# This file marks this directory as containing a CBMC proof.
27 changes: 27 additions & 0 deletions cbmc/proofs/crypto_kem_keypair/crypto_kem_keypair_harness.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0

/*
* Insert copyright notice
*/

/**
* @file crypto_kem_keypair_harness.c
* @brief Implements the proof harness for crypto_kem_keypair function.
*/

/*
* Insert project header files that
* - include the declaration of the function
* - include the types needed to declare function arguments
*/
#include <kem.h>

/**
* @brief Starting point for formal analysis
*
*/
void harness(void) {
uint8_t *a, *b;
crypto_kem_keypair(a, b);
}
31 changes: 7 additions & 24 deletions mlkem/kem.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,13 @@
#include "symmetric.h"
#include "verify.h"

// This helper function is only to prevent CBMC from inlining
// `memcmp`, and is expected to be inlined by the compiler.
static int pk_cmp_polyvec(
const uint8_t pk[MLKEM_PUBLICKEYBYTES],
const uint8_t pv[MLKEM_POLYVECBYTES]) // clang-format off
REQUIRES(IS_FRESH(pk, MLKEM_PUBLICKEYBYTES))
REQUIRES(IS_FRESH(pv, MLKEM_POLYVECBYTES))
#if defined(CBMC)
// Redeclaration with contract needed for CBMC only
int memcmp(const void *str1, const void *str2, size_t n) // clang-format off
REQUIRES(IS_FRESH(str1, n))
REQUIRES(IS_FRESH(str2, n));
// clang-format on
{
return memcmp(pk, pv, MLKEM_POLYVECBYTES);
}
#endif

/*************************************************
* Name: check_pk
Expand All @@ -40,7 +36,7 @@ static int check_pk(const uint8_t pk[MLKEM_PUBLICKEYBYTES]) {
polyvec_reduce(&p);
polyvec_tobytes(p_reencoded, &p);
// Data is public, so a variable-time memcmp() is OK
if (pk_cmp_polyvec(pk, p_reencoded)) {
if (memcmp(pk, p_reencoded, MLKEM_POLYVECBYTES)) {
return -1;
}
return 0;
Expand Down Expand Up @@ -99,19 +95,6 @@ int crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk, const uint8_t *coins) {
return 0;
}

/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure ML-KEM key encapsulation mechanism
*
* Arguments: - uint8_t *pk: pointer to output public key
* (an already allocated array of MLKEM_PUBLICKEYBYTES bytes)
* - uint8_t *sk: pointer to output private key
* (an already allocated array of MLKEM_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
uint8_t coins[2 * MLKEM_SYMBYTES] ALIGN;
randombytes(coins, 2 * MLKEM_SYMBYTES);
Expand Down
20 changes: 19 additions & 1 deletion mlkem/kem.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,25 @@ int crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk,
// clang-format on

#define crypto_kem_keypair MLKEM_NAMESPACE(keypair)
int crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure ML-KEM key encapsulation mechanism
*
* Arguments: - uint8_t *pk: pointer to output public key
* (an already allocated array of MLKEM_PUBLICKEYBYTES bytes)
* - uint8_t *sk: pointer to output private key
* (an already allocated array of MLKEM_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int crypto_kem_keypair(uint8_t *pk, uint8_t *sk) // clang-format off
REQUIRES(IS_FRESH(pk, MLKEM_PUBLICKEYBYTES))
REQUIRES(IS_FRESH(sk, MLKEM_SECRETKEYBYTES))
ASSIGNS(OBJECT_WHOLE(pk))
ASSIGNS(OBJECT_WHOLE(sk));
// clang-format on

#define crypto_kem_enc_derand MLKEM_NAMESPACE(enc_derand)
/*************************************************
Expand Down

0 comments on commit 5eea727

Please sign in to comment.