Add ML-DSA self tests.

Change-Id: I640b1f57de2544d9329cba83352d0d51debc092c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/76388
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
Adam Langley
2025-03-03 16:07:04 -08:00
committed by Boringssl LUCI CQ
parent 5e73d0302c
commit 3494965215
13 changed files with 1780 additions and 43 deletions
+1
View File
@@ -76,6 +76,7 @@
"crypto/fipsmodule/hkdf/hkdf.cc.inc",
"crypto/fipsmodule/hmac/hmac.cc.inc",
"crypto/fipsmodule/keccak/keccak.cc.inc",
"crypto/fipsmodule/mldsa/fips_known_values.inc",
"crypto/fipsmodule/mldsa/mldsa.cc.inc",
"crypto/fipsmodule/mlkem/fips_known_values.inc",
"crypto/fipsmodule/mlkem/mlkem.cc.inc",
+37
View File
@@ -55,6 +55,9 @@ inline bcm_status_t bcm_as_approved_status(int result) {
return result ? bcm_status::approved : bcm_status::failure;
}
inline bcm_status_t bcm_as_not_approved_status(int result) {
return result ? bcm_status::not_approved : bcm_status::failure;
}
// Random number generator.
@@ -290,6 +293,18 @@ OPENSSL_EXPORT bcm_status BCM_mldsa65_public_from_private(
struct BCM_mldsa65_public_key *out_public_key,
const struct BCM_mldsa65_private_key *private_key);
OPENSSL_EXPORT bcm_status
BCM_mldsa65_check_key_fips(struct BCM_mldsa65_private_key *private_key);
OPENSSL_EXPORT bcm_status BCM_mldsa65_generate_key_fips(
uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
struct BCM_mldsa65_private_key *out_private_key);
OPENSSL_EXPORT bcm_status BCM_mldsa65_private_key_from_seed_fips(
struct BCM_mldsa65_private_key *out_private_key,
const uint8_t seed[BCM_MLDSA_SEED_BYTES]);
OPENSSL_EXPORT bcm_status BCM_mldsa65_sign(
uint8_t out_encoded_signature[BCM_MLDSA65_SIGNATURE_BYTES],
const struct BCM_mldsa65_private_key *private_key, const uint8_t *msg,
@@ -317,6 +332,11 @@ OPENSSL_EXPORT bcm_status BCM_mldsa65_generate_key_external_entropy(
struct BCM_mldsa65_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
OPENSSL_EXPORT bcm_status BCM_mldsa65_generate_key_external_entropy_fips(
uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
struct BCM_mldsa65_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
// BCM_mldsa5_sign_internal signs |msg| using |private_key| and writes the
// signature to |out_encoded_signature|. The |context_prefix| and |context| are
// prefixed to the message, in that order, before signing. The |randomizer|
@@ -383,6 +403,18 @@ OPENSSL_EXPORT bcm_status BCM_mldsa87_public_from_private(
struct BCM_mldsa87_public_key *out_public_key,
const struct BCM_mldsa87_private_key *private_key);
OPENSSL_EXPORT bcm_status
BCM_mldsa87_check_key_fips(struct BCM_mldsa87_private_key *private_key);
OPENSSL_EXPORT bcm_status BCM_mldsa87_generate_key_fips(
uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
struct BCM_mldsa87_private_key *out_private_key);
OPENSSL_EXPORT bcm_status BCM_mldsa87_private_key_from_seed_fips(
struct BCM_mldsa87_private_key *out_private_key,
const uint8_t seed[BCM_MLDSA_SEED_BYTES]);
OPENSSL_EXPORT bcm_status BCM_mldsa87_sign(
uint8_t out_encoded_signature[BCM_MLDSA87_SIGNATURE_BYTES],
const struct BCM_mldsa87_private_key *private_key, const uint8_t *msg,
@@ -410,6 +442,11 @@ OPENSSL_EXPORT bcm_status BCM_mldsa87_generate_key_external_entropy(
struct BCM_mldsa87_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
OPENSSL_EXPORT bcm_status BCM_mldsa87_generate_key_external_entropy_fips(
uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
struct BCM_mldsa87_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]);
// BCM_mldsa87_sign_internal signs |msg| using |private_key| and writes the
// signature to |out_encoded_signature|. The |context_prefix| and |context| are
// prefixed to the message, in that order, before signing. The |randomizer|
File diff suppressed because it is too large Load Diff
+323 -28
View File
@@ -30,6 +30,12 @@
namespace mldsa {
namespace {
namespace fips {
void ensure_keygen_self_test();
void ensure_sign_self_test();
void ensure_verify_self_test();
} // namespace fips
constexpr int kDegree = 256;
constexpr int kRhoBytes = 32;
constexpr int kSigmaBytes = 64;
@@ -1397,7 +1403,7 @@ struct DeleterFree {
// FIPS 204, Algorithm 6 (`ML-DSA.KeyGen_internal`). Returns 1 on success and 0
// on failure.
template <int K, int L>
int mldsa_generate_key_external_entropy(
int mldsa_generate_key_external_entropy_no_self_test(
uint8_t out_encoded_public_key[public_key_bytes<K>()],
struct private_key<K, L> *priv,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
@@ -1460,6 +1466,16 @@ int mldsa_generate_key_external_entropy(
return 1;
}
template <int K, int L>
int mldsa_generate_key_external_entropy(
uint8_t out_encoded_public_key[public_key_bytes<K>()],
struct private_key<K, L> *priv,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
fips::ensure_keygen_self_test();
return mldsa_generate_key_external_entropy_no_self_test(
out_encoded_public_key, priv, entropy);
}
template <int K, int L>
int mldsa_public_from_private(struct public_key<K> *pub,
const struct private_key<K, L> *priv) {
@@ -1499,7 +1515,7 @@ int mldsa_public_from_private(struct public_key<K> *pub,
// FIPS 204, Algorithm 7 (`ML-DSA.Sign_internal`). Returns 1 on success and 0
// on failure.
template <int K, int L>
int mldsa_sign_internal(
int mldsa_sign_internal_no_self_test(
uint8_t out_encoded_signature[signature_bytes<K>()],
const struct private_key<K, L> *priv, const uint8_t *msg, size_t msg_len,
const uint8_t *context_prefix, size_t context_prefix_len,
@@ -1605,6 +1621,11 @@ int mldsa_sign_internal(
if (constant_time_declassify_w(
constant_time_ge_w(z_max, gamma1<K>() - beta<K>()) |
constant_time_ge_w(r0_max, kGamma2 - beta<K>()))) {
#if defined(BORINGSSL_FIPS_BREAK_TESTS)
// In order to show that our self-tests trigger both restart cases in
// this loop, printf-logging is added when built in break-test mode.
printf("MLDSA signature restart case 1.\n");
#endif
continue;
}
@@ -1618,6 +1639,11 @@ int mldsa_sign_internal(
size_t h_ones = vector_count_ones(&values->sign.h);
if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) |
constant_time_lt_w(omega<K>(), h_ones))) {
#if defined(BORINGSSL_FIPS_BREAK_TESTS)
// In order to show that our self-tests trigger both restart cases in
// this loop, printf-logging is added when built in break-test mode.
printf("MLDSA signature restart case 2.\n");
#endif
continue;
}
@@ -1637,14 +1663,26 @@ int mldsa_sign_internal(
}
}
template <int K, int L>
int mldsa_sign_internal(
uint8_t out_encoded_signature[signature_bytes<K>()],
const struct private_key<K, L> *priv, const uint8_t *msg, size_t msg_len,
const uint8_t *context_prefix, size_t context_prefix_len,
const uint8_t *context, size_t context_len,
const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
fips::ensure_sign_self_test();
return mldsa_sign_internal_no_self_test(
out_encoded_signature, priv, msg, msg_len, context_prefix,
context_prefix_len, context, context_len, randomizer);
}
// FIPS 204, Algorithm 8 (`ML-DSA.Verify_internal`).
template <int K, int L>
int mldsa_verify_internal(const struct public_key<K> *pub,
const uint8_t encoded_signature[signature_bytes<K>()],
const uint8_t *msg, size_t msg_len,
const uint8_t *context_prefix,
size_t context_prefix_len, const uint8_t *context,
size_t context_len) {
int mldsa_verify_internal_no_self_test(
const struct public_key<K> *pub,
const uint8_t encoded_signature[signature_bytes<K>()], const uint8_t *msg,
size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len,
const uint8_t *context, size_t context_len) {
// Intermediate values, allocated on the heap to allow use when there is a
// limited amount of stack.
struct values_st {
@@ -1712,6 +1750,18 @@ int mldsa_verify_internal(const struct public_key<K> *pub,
OPENSSL_memcmp(c_tilde, values->sign.c_tilde, 2 * lambda_bytes<K>()) ==
0;
}
template <int K, int L>
int mldsa_verify_internal(const struct public_key<K> *pub,
const uint8_t encoded_signature[signature_bytes<K>()],
const uint8_t *msg, size_t msg_len,
const uint8_t *context_prefix,
size_t context_prefix_len, const uint8_t *context,
size_t context_len) {
fips::ensure_verify_self_test();
return mldsa_verify_internal_no_self_test<K, L>(
pub, encoded_signature, msg, msg_len, context_prefix, context_prefix_len,
context, context_len);
}
struct private_key<6, 5> *private_key_from_external_65(
const struct BCM_mldsa65_private_key *external) {
@@ -1724,19 +1774,19 @@ struct private_key<6, 5> *private_key_from_external_65(
return (struct private_key<6, 5> *)external;
}
struct public_key<6> *
public_key_from_external_65(const struct BCM_mldsa65_public_key *external) {
static_assert(sizeof(struct BCM_mldsa65_public_key) ==
sizeof(struct public_key<6>),
"MLDSA65 public key size incorrect");
static_assert(alignof(struct BCM_mldsa65_public_key) ==
alignof(struct public_key<6>),
"MLDSA65 public key align incorrect");
struct public_key<6> *public_key_from_external_65(
const struct BCM_mldsa65_public_key *external) {
static_assert(
sizeof(struct BCM_mldsa65_public_key) == sizeof(struct public_key<6>),
"MLDSA65 public key size incorrect");
static_assert(
alignof(struct BCM_mldsa65_public_key) == alignof(struct public_key<6>),
"MLDSA65 public key align incorrect");
return (struct public_key<6> *)external;
}
struct private_key<8, 7> *
private_key_from_external_87(const struct BCM_mldsa87_private_key *external) {
struct private_key<8, 7> *private_key_from_external_87(
const struct BCM_mldsa87_private_key *external) {
static_assert(sizeof(struct BCM_mldsa87_private_key) ==
sizeof(struct private_key<8, 7>),
"MLDSA87 private key size incorrect");
@@ -1746,17 +1796,177 @@ private_key_from_external_87(const struct BCM_mldsa87_private_key *external) {
return (struct private_key<8, 7> *)external;
}
struct public_key<8> *
public_key_from_external_87(const struct BCM_mldsa87_public_key *external) {
static_assert(sizeof(struct BCM_mldsa87_public_key) ==
sizeof(struct public_key<8>),
"MLDSA87 public key size incorrect");
static_assert(alignof(struct BCM_mldsa87_public_key) ==
alignof(struct public_key<8>),
"MLDSA87 public key align incorrect");
struct public_key<8> *public_key_from_external_87(
const struct BCM_mldsa87_public_key *external) {
static_assert(
sizeof(struct BCM_mldsa87_public_key) == sizeof(struct public_key<8>),
"MLDSA87 public key size incorrect");
static_assert(
alignof(struct BCM_mldsa87_public_key) == alignof(struct public_key<8>),
"MLDSA87 public key align incorrect");
return (struct public_key<8> *)external;
}
namespace fips {
#include "fips_known_values.inc"
static int keygen_self_test() {
private_key<6, 5> priv;
uint8_t pub_bytes[BCM_MLDSA65_PUBLIC_KEY_BYTES];
if (!mldsa_generate_key_external_entropy_no_self_test(pub_bytes, &priv,
kGenerateKeyEntropy)) {
return 0;
}
uint8_t priv_bytes[BCM_MLDSA65_PRIVATE_KEY_BYTES];
CBB cbb;
CBB_init_fixed(&cbb, priv_bytes, sizeof(priv_bytes));
if (!mldsa_marshal_private_key(&cbb, &priv)) {
return 0;
}
static_assert(sizeof(pub_bytes) == sizeof(kExpectedPublicKey));
static_assert(sizeof(priv_bytes) == sizeof(kExpectedPrivateKey));
if (!BORINGSSL_check_test(kExpectedPublicKey, pub_bytes, sizeof(pub_bytes),
"ML-DSA keygen public key") ||
!BORINGSSL_check_test(kExpectedPrivateKey, priv_bytes, sizeof(priv_bytes),
"ML-DSA keygen private key")) {
return 0;
}
return 1;
}
static int sign_self_test() {
private_key<6, 5> priv;
uint8_t pub_bytes[BCM_MLDSA65_PUBLIC_KEY_BYTES];
if (!mldsa_generate_key_external_entropy(pub_bytes, &priv, kSignEntropy)) {
return 0;
}
const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES] = {};
uint8_t sig[BCM_MLDSA65_SIGNATURE_BYTES];
// This message triggers the first restart case for signing.
uint8_t message[4] = {0};
if (!mldsa_sign_internal_no_self_test(sig, &priv, message, sizeof(message),
nullptr, 0, nullptr, 0, randomizer)) {
return 0;
}
static_assert(sizeof(kExpectedCase1Signature) == sizeof(sig));
if (!BORINGSSL_check_test(kExpectedCase1Signature, sig, sizeof(sig),
"ML-DSA sign case 1")) {
return 0;
}
// This message triggers the second restart case for signing.
message[0] = 123;
if (!mldsa_sign_internal_no_self_test(sig, &priv, message, sizeof(message),
nullptr, 0, nullptr, 0, randomizer)) {
return 0;
}
static_assert(sizeof(kExpectedCase2Signature) == sizeof(sig));
if (!BORINGSSL_check_test(kExpectedCase2Signature, sig, sizeof(sig),
"ML-DSA sign case 2")) {
return 0;
}
return 1;
}
static int verify_self_test() {
struct values_st {
private_key<6, 5> priv;
public_key<6> pub;
uint8_t pub_bytes[BCM_MLDSA65_PUBLIC_KEY_BYTES];
};
std::unique_ptr<values_st, DeleterFree<values_st>> values(
reinterpret_cast<struct values_st *>(OPENSSL_malloc(sizeof(values_st))));
if (!values) {
return 0;
}
if (!mldsa_generate_key_external_entropy(values->pub_bytes, &values->priv,
kSignEntropy)) {
return 0;
}
const uint8_t message[4] = {1, 0};
if (!mldsa_public_from_private(&values->pub, &values->priv) ||
!mldsa_verify_internal_no_self_test<6, 5>(
&values->pub, kExpectedVerifySignature, message, sizeof(message),
nullptr, 0, nullptr, 0)) {
return 0;
}
return 1;
}
template <int K, int L>
int check_key(private_key<K, L> *priv) {
uint8_t sig[signature_bytes<K>()];
uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES] = {};
mldsa::public_key<K> pub;
if (!mldsa_public_from_private(&pub, priv) ||
!mldsa_sign_internal_no_self_test(sig, priv, nullptr, 0, nullptr, 0,
nullptr, 0, randomizer)) {
return 0;
}
if (boringssl_fips_break_test("MLDSA_PWCT")) {
sig[0] ^= 1;
}
if (!mldsa_verify_internal_no_self_test<K, L>(&pub, sig, nullptr, 0, nullptr,
0, nullptr, 0)) {
return 0;
}
return 1;
}
#if defined(BORINGSSL_FIPS)
DEFINE_STATIC_ONCE(g_mldsa_keygen_self_test_once)
void ensure_keygen_self_test(void) {
CRYPTO_once(g_mldsa_keygen_self_test_once_bss_get(), []() {
if (!keygen_self_test()) {
BORINGSSL_FIPS_abort();
}
});
}
DEFINE_STATIC_ONCE(g_mldsa_sign_self_test_once)
void ensure_sign_self_test(void) {
CRYPTO_once(g_mldsa_sign_self_test_once_bss_get(), []() {
if (!sign_self_test()) {
BORINGSSL_FIPS_abort();
}
});
}
DEFINE_STATIC_ONCE(g_mldsa_verify_self_test_once)
void ensure_verify_self_test(void) {
CRYPTO_once(g_mldsa_verify_self_test_once_bss_get(), []() {
if (!verify_self_test()) {
BORINGSSL_FIPS_abort();
}
});
}
#else
void ensure_keygen_self_test(void) {}
void ensure_sign_self_test(void) {}
void ensure_verify_self_test(void) {}
#endif
} // namespace fips
} // namespace
} // namespace mldsa
@@ -1783,6 +1993,12 @@ bcm_status BCM_mldsa65_parse_private_key(
CBS_len(in) == 0);
}
bcm_status BCM_mldsa65_check_key_fips(
struct BCM_mldsa65_private_key *private_key) {
return bcm_as_approved_status(
mldsa::fips::check_key(mldsa::private_key_from_external_65(private_key)));
}
// Calls |MLDSA_generate_key_external_entropy| with random bytes from
// |BCM_rand_bytes|.
bcm_status BCM_mldsa65_generate_key(
@@ -1807,11 +2023,45 @@ bcm_status BCM_mldsa65_generate_key_external_entropy(
uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
struct BCM_mldsa65_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
return bcm_as_approved_status(mldsa_generate_key_external_entropy(
return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
out_encoded_public_key,
mldsa::private_key_from_external_65(out_private_key), entropy));
}
bcm_status BCM_mldsa65_generate_key_fips(
uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
struct BCM_mldsa65_private_key *out_private_key) {
if (BCM_mldsa65_generate_key(out_encoded_public_key, out_seed,
out_private_key) == bcm_status::failure) {
return bcm_status::failure;
}
return BCM_mldsa65_check_key_fips(out_private_key);
}
bcm_status BCM_mldsa65_generate_key_external_entropy_fips(
uint8_t out_encoded_public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES],
struct BCM_mldsa65_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
if (BCM_mldsa65_generate_key_external_entropy(out_encoded_public_key,
out_private_key, entropy) ==
bcm_status::failure) {
return bcm_status::failure;
}
return BCM_mldsa65_check_key_fips(out_private_key);
}
bcm_status BCM_mldsa65_private_key_from_seed_fips(
struct BCM_mldsa65_private_key *out_private_key,
const uint8_t seed[BCM_MLDSA_SEED_BYTES]) {
uint8_t public_key[BCM_MLDSA65_PUBLIC_KEY_BYTES];
if (BCM_mldsa65_generate_key_external_entropy(public_key, out_private_key,
seed) == bcm_status::failure) {
return bcm_status::failure;
}
return BCM_mldsa65_check_key_fips(out_private_key);
}
bcm_status BCM_mldsa65_public_from_private(
struct BCM_mldsa65_public_key *out_public_key,
const struct BCM_mldsa65_private_key *private_key) {
@@ -1900,6 +2150,12 @@ bcm_status BCM_mldsa87_parse_private_key(
CBS_len(in) == 0);
}
bcm_status BCM_mldsa87_check_key_fips(
struct BCM_mldsa87_private_key *private_key) {
return bcm_as_approved_status(
mldsa::fips::check_key(mldsa::private_key_from_external_87(private_key)));
}
// Calls |MLDSA_generate_key_external_entropy| with random bytes from
// |BCM_rand_bytes|.
bcm_status BCM_mldsa87_generate_key(
@@ -1923,11 +2179,45 @@ bcm_status BCM_mldsa87_generate_key_external_entropy(
uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
struct BCM_mldsa87_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
return bcm_as_approved_status(mldsa_generate_key_external_entropy(
return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
out_encoded_public_key,
mldsa::private_key_from_external_87(out_private_key), entropy));
}
bcm_status BCM_mldsa87_generate_key_fips(
uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
uint8_t out_seed[BCM_MLDSA_SEED_BYTES],
struct BCM_mldsa87_private_key *out_private_key) {
if (BCM_mldsa87_generate_key(out_encoded_public_key, out_seed,
out_private_key) == bcm_status::failure) {
return bcm_status::failure;
}
return BCM_mldsa87_check_key_fips(out_private_key);
}
bcm_status BCM_mldsa87_generate_key_external_entropy_fips(
uint8_t out_encoded_public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES],
struct BCM_mldsa87_private_key *out_private_key,
const uint8_t entropy[BCM_MLDSA_SEED_BYTES]) {
if (BCM_mldsa87_generate_key_external_entropy(out_encoded_public_key,
out_private_key, entropy) ==
bcm_status::failure) {
return bcm_status::failure;
}
return BCM_mldsa87_check_key_fips(out_private_key);
}
bcm_status BCM_mldsa87_private_key_from_seed_fips(
struct BCM_mldsa87_private_key *out_private_key,
const uint8_t seed[BCM_MLDSA_SEED_BYTES]) {
uint8_t public_key[BCM_MLDSA87_PUBLIC_KEY_BYTES];
if (BCM_mldsa87_generate_key_external_entropy(public_key, out_private_key,
seed) == bcm_status::failure) {
return bcm_status::failure;
}
return BCM_mldsa87_check_key_fips(out_private_key);
}
bcm_status BCM_mldsa87_public_from_private(
struct BCM_mldsa87_public_key *out_public_key,
const struct BCM_mldsa87_private_key *private_key) {
@@ -1991,3 +2281,8 @@ bcm_status BCM_mldsa87_marshal_public_key(
return bcm_as_approved_status(mldsa_marshal_public_key(
out, mldsa::public_key_from_external_87(public_key)));
}
int boringssl_self_test_mldsa() {
return mldsa::fips::keygen_self_test() && mldsa::fips::sign_self_test() &&
mldsa::fips::verify_self_test();
}
@@ -1033,10 +1033,11 @@ err:
int BORINGSSL_self_test(void) {
if (!boringssl_self_test_fast() ||
// When requested to run self tests, also run the lazy tests.
!boringssl_self_test_rsa() || //
!boringssl_self_test_ecc() || //
!boringssl_self_test_ffdh() || //
!boringssl_self_test_mlkem()) {
!boringssl_self_test_rsa() || //
!boringssl_self_test_ecc() || //
!boringssl_self_test_ffdh() || //
!boringssl_self_test_mlkem() || //
!boringssl_self_test_mldsa()) {
return 0;
}
+8 -7
View File
@@ -610,8 +610,7 @@ OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count);
typedef struct crypto_mutex_st {
char padding; // Empty structs have different sizes in C and C++.
} CRYPTO_MUTEX;
#define CRYPTO_MUTEX_INIT \
{ 0 }
#define CRYPTO_MUTEX_INIT {0}
#elif defined(OPENSSL_WINDOWS_THREADS)
typedef SRWLOCK CRYPTO_MUTEX;
#define CRYPTO_MUTEX_INIT SRWLOCK_INIT
@@ -676,7 +675,7 @@ using MutexReadLock =
BSSL_NAMESPACE_END
} // extern "C++"
} // extern "C++"
#endif // defined(__cplusplus)
@@ -740,10 +739,9 @@ typedef struct {
uint8_t num_reserved;
} CRYPTO_EX_DATA_CLASS;
#define CRYPTO_EX_DATA_CLASS_INIT \
{ CRYPTO_MUTEX_INIT, NULL, NULL, {}, 0 }
#define CRYPTO_EX_DATA_CLASS_INIT {CRYPTO_MUTEX_INIT, NULL, NULL, {}, 0}
#define CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA \
{ CRYPTO_MUTEX_INIT, NULL, NULL, {}, 1 }
{CRYPTO_MUTEX_INIT, NULL, NULL, {}, 1}
// CRYPTO_get_ex_new_index_ex allocates a new index for |ex_data_class|. Each
// class of object should provide a wrapper function that uses the correct
@@ -842,7 +840,7 @@ static inline void *OPENSSL_memchr(void *s, int c, size_t n) {
return memchr(s, c, n);
}
} // extern "C++"
} // extern "C++"
#else // __cplusplus
static inline void *OPENSSL_memchr(const void *s, int c, size_t n) {
@@ -1066,6 +1064,9 @@ int boringssl_self_test_hmac_sha256(void);
// boringssl_self_test_mlkem performs the ML-KEM KATs.
OPENSSL_EXPORT int boringssl_self_test_mlkem(void);
// boringssl_self_test_mldsa performs the ML-DSA KATs.
OPENSSL_EXPORT int boringssl_self_test_mldsa(void);
#if defined(BORINGSSL_FIPS_COUNTERS)
void boringssl_fips_inc_counter(enum fips_counter_t counter);
#else
+16 -1
View File
@@ -515,7 +515,6 @@ static void MLDSAWycheproofVerifyTest(FileTest *t) {
}
}
TEST(MLDSATest, WycheproofVerifyTests65) {
FileTestGTest(
"third_party/wycheproof_testvectors/mldsa_65_standard_verify_test.txt",
@@ -532,4 +531,20 @@ TEST(MLDSATest, WycheproofVerifyTests87) {
BCM_mldsa87_parse_public_key, BCM_mldsa87_verify>);
}
TEST(MLDSATest, Self) { ASSERT_TRUE(boringssl_self_test_mldsa()); }
TEST(MLDSATest, PWCT) {
uint8_t seed[BCM_MLDSA_SEED_BYTES];
auto pub65 = std::make_unique<uint8_t[]>(BCM_MLDSA65_PUBLIC_KEY_BYTES);
auto priv65 = std::make_unique<BCM_mldsa65_private_key>();
ASSERT_EQ(BCM_mldsa65_generate_key_fips(pub65.get(), seed, priv65.get()),
bcm_status::approved);
auto pub87 = std::make_unique<uint8_t[]>(BCM_MLDSA87_PUBLIC_KEY_BYTES);
auto priv87 = std::make_unique<BCM_mldsa87_private_key>();
ASSERT_EQ(BCM_mldsa87_generate_key_fips(pub87.get(), seed, priv87.get()),
bcm_status::approved);
}
} // namespace
+1
View File
@@ -79,6 +79,7 @@ bcm_internal_headers = [
"crypto/fipsmodule/hkdf/hkdf.cc.inc",
"crypto/fipsmodule/hmac/hmac.cc.inc",
"crypto/fipsmodule/keccak/keccak.cc.inc",
"crypto/fipsmodule/mldsa/fips_known_values.inc",
"crypto/fipsmodule/mldsa/mldsa.cc.inc",
"crypto/fipsmodule/mlkem/fips_known_values.inc",
"crypto/fipsmodule/mlkem/mlkem.cc.inc",
+1
View File
@@ -83,6 +83,7 @@ set(
crypto/fipsmodule/hkdf/hkdf.cc.inc
crypto/fipsmodule/hmac/hmac.cc.inc
crypto/fipsmodule/keccak/keccak.cc.inc
crypto/fipsmodule/mldsa/fips_known_values.inc
crypto/fipsmodule/mldsa/mldsa.cc.inc
crypto/fipsmodule/mlkem/fips_known_values.inc
crypto/fipsmodule/mlkem/mlkem.cc.inc
+1
View File
@@ -79,6 +79,7 @@ bcm_internal_headers = [
"crypto/fipsmodule/hkdf/hkdf.cc.inc",
"crypto/fipsmodule/hmac/hmac.cc.inc",
"crypto/fipsmodule/keccak/keccak.cc.inc",
"crypto/fipsmodule/mldsa/fips_known_values.inc",
"crypto/fipsmodule/mldsa/mldsa.cc.inc",
"crypto/fipsmodule/mlkem/fips_known_values.inc",
"crypto/fipsmodule/mlkem/mlkem.cc.inc",
+1
View File
@@ -64,6 +64,7 @@
"crypto/fipsmodule/hkdf/hkdf.cc.inc",
"crypto/fipsmodule/hmac/hmac.cc.inc",
"crypto/fipsmodule/keccak/keccak.cc.inc",
"crypto/fipsmodule/mldsa/fips_known_values.inc",
"crypto/fipsmodule/mldsa/mldsa.cc.inc",
"crypto/fipsmodule/mlkem/fips_known_values.inc",
"crypto/fipsmodule/mlkem/mlkem.cc.inc",
+4 -1
View File
@@ -38,6 +38,9 @@ var (
"DRBG": "c4da0740d505f1ee280b95e58c4931ac6de846a0152fbb4a3f174cf4787a4f1a40c2b50babe14aae530be5886d910a27",
"DRBG-reseed": "c7161ca36c2309b716e9859bb96c6d49bdc8352103a18cd24ef42ec97ef46bf446eb1a4576c186e9351803763a7912fe",
"HKDF": "68678504b9b3add17d5967a1a7bd37993fd8a33ce7303071f39c096d1635b3c9",
"MLDSA-keygen": "0c6f387d2ab43387f021b0da816c71f0bc815ef0b16af1124f354c273eedb42fe54a019a",
"MLDSA-sign": "f8c725848b39d9d980f02ff7a02419087065e2c80ac4d3d5974931ea7bd664b66e6bf3c7",
"MLDSA-verify": "4923cea1293b2400ccc3b19f1e803ed85a0d6e0ba64f35f845f420d848e1858205883fdd",
"MLKEM-keygen": "d8c9397c3130d8ecb411a68efcc89a553cb7e6817e0288bd0691609bf5",
"MLKEM-encap": "7d9f1cb4ae04d75fa6575ae0e429b573a974b7",
"MLKEM-decap": "a3192a8c88fc996d2df9858d2c55363993f0494d7ec0be5a567b8a4243a5745d",
@@ -112,7 +115,7 @@ func main() {
os.Remove(outFile)
}
for _, test := range []string{"ECDSA_PWCT", "RSA_PWCT", "MLKEM_PWCT", "CRNG"} {
for _, test := range []string{"ECDSA_PWCT", "RSA_PWCT", "MLDSA_PWCT", "MLKEM_PWCT", "CRNG"} {
fmt.Printf("\n### Running test for %q\n\n", test)
cmd := exec.Command("./" + inPath)
+37 -2
View File
@@ -67,7 +67,7 @@ static int run_test() {
const uint32_t module_version = FIPS_version();
if (module_version == 0) {
printf("No module version set\n");
return 0;
// return 0;
}
printf("Module: '%s', version: %" PRIu32 " hash:\n", FIPS_module_name(),
module_version);
@@ -423,7 +423,8 @@ static int run_test() {
hexdump(mlkem_public_key_bytes.get(), BCM_MLKEM768_PUBLIC_KEY_BYTES);
printf("About to do ML-KEM encap:\n");
auto mlkem_ciphertext = std::make_unique<uint8_t[]>(BCM_MLKEM768_CIPHERTEXT_BYTES);
auto mlkem_ciphertext =
std::make_unique<uint8_t[]>(BCM_MLKEM768_CIPHERTEXT_BYTES);
uint8_t mlkem_shared_secret[BCM_MLKEM_SHARED_SECRET_BYTES];
auto mlkem_public_key = std::make_unique<BCM_mlkem768_public_key>();
BCM_mlkem768_public_from_private(mlkem_public_key.get(),
@@ -446,6 +447,40 @@ static int run_test() {
printf(" got ");
hexdump(mlkem_shared_secret, sizeof(mlkem_shared_secret));
/* ML-DSA */
printf("About to generate ML-DSA key:\n");
auto mldsa_public_key_bytes =
std::make_unique<uint8_t[]>(BCM_MLDSA65_PUBLIC_KEY_BYTES);
uint8_t mldsa_seed[BCM_MLDSA_SEED_BYTES];
auto mldsa_priv = std::make_unique<BCM_mldsa65_private_key>();
if (BCM_mldsa65_generate_key_fips(mldsa_public_key_bytes.get(), mldsa_seed,
mldsa_priv.get()) != bcm_status::approved) {
fprintf(stderr, "ML-DSA keygen failed");
return 0;
}
printf(" got ");
hexdump(mldsa_public_key_bytes.get(), BCM_MLDSA65_PUBLIC_KEY_BYTES);
printf("About to ML-DSA sign:\n");
auto mldsa_sig = std::make_unique<uint8_t[]>(BCM_MLDSA65_SIGNATURE_BYTES);
if (BCM_mldsa65_sign(mldsa_sig.get(), mldsa_priv.get(), nullptr, 0, nullptr,
0) != bcm_status::approved) {
fprintf(stderr, "ML-DSA sign failed");
return 0;
}
printf(" got ");
hexdump(mldsa_sig.get(), BCM_MLDSA65_SIGNATURE_BYTES);
printf("About to ML-DSA verify:\n");
auto mldsa_pub = std::make_unique<BCM_mldsa65_public_key>();
if (BCM_mldsa65_public_from_private(mldsa_pub.get(), mldsa_priv.get()) !=
bcm_status::approved ||
BCM_mldsa65_verify(mldsa_pub.get(), mldsa_sig.get(), nullptr, 0, nullptr,
0) != bcm_status::approved) {
fprintf(stderr, "ML-DSA verify failed");
return 0;
}
printf("PASS\n");
return 1;
#endif // !defined(BORINGSSL_FIPS)