Skip to content

Commit

Permalink
Merge branch 'main' into dh-asn1
Browse files Browse the repository at this point in the history
  • Loading branch information
justsmth authored Oct 14, 2024
2 parents 9660aaf + cf969b5 commit 0ae4a99
Show file tree
Hide file tree
Showing 37 changed files with 1,003 additions and 927 deletions.
1 change: 0 additions & 1 deletion crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ if(ENABLE_DILITHIUM)
set(
DILITHIUM_SOURCES

dilithium/dilithium3r3_ref.c
dilithium/p_dilithium3.c
dilithium/p_dilithium3_asn1.c
dilithium/sig_dilithium3.c
Expand Down
26 changes: 0 additions & 26 deletions crypto/dilithium/dilithium3r3_ref.c

This file was deleted.

File renamed without changes.
8 changes: 4 additions & 4 deletions crypto/dilithium/p_dilithium3.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <openssl/evp.h>
#include <openssl/err.h>
Expand Down Expand Up @@ -31,7 +31,7 @@ static int pkey_dilithium3_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {

evp_pkey_set_method(pkey, &dilithium3_asn1_meth);

if (DILITHIUM3_keypair(key->pub, key->priv) != 0) {
if (ml_dsa_65_keypair(key->pub, key->priv) != 0) {
goto err;
}

Expand Down Expand Up @@ -74,7 +74,7 @@ static int pkey_dilithium3_sign_message(EVP_PKEY_CTX *ctx, uint8_t *sig,
return 0;
}

if (DILITHIUM3_sign(sig, siglen, tbs, tbslen, NULL, 0, key->priv) != 0) {
if (ml_dsa_65_sign(sig, siglen, tbs, tbslen, NULL, 0, key->priv) != 0) {
OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
Expand All @@ -92,7 +92,7 @@ static int pkey_dilithium3_verify_message(EVP_PKEY_CTX *ctx, const uint8_t *sig,
DILITHIUM3_KEY *key = ctx->pkey->pkey.ptr;

if (siglen != DILITHIUM3_SIGNATURE_BYTES ||
DILITHIUM3_verify(tbs, tbslen, sig, siglen, NULL, 0, key->pub) != 0) {
ml_dsa_65_verify(tbs, tbslen, sig, siglen, NULL, 0, key->pub) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion crypto/dilithium/p_dilithium3_asn1.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <openssl/evp.h>

Expand Down
150 changes: 87 additions & 63 deletions crypto/dilithium/p_dilithium_test.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <gtest/gtest.h>
#include <openssl/base.h>
Expand Down Expand Up @@ -679,70 +679,94 @@ TEST(Dilithium3Test, SIGOperations) {
md_ctx.Reset();
}

static void RunKat(FileTest *t)
{
std::string count, mlen, smlen;
std::vector<uint8_t> seed, msg, pk, sk, sm;

ASSERT_TRUE(t->GetAttribute(&count, "count"));
ASSERT_TRUE(t->GetBytes(&seed, "seed"));
ASSERT_TRUE(t->GetAttribute(&mlen, "mlen"));
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
ASSERT_TRUE(t->GetBytes(&pk, "pk"));
ASSERT_TRUE(t->GetBytes(&sk, "sk"));
ASSERT_TRUE(t->GetAttribute(&smlen, "smlen"));
ASSERT_TRUE(t->GetBytes(&sm, "sm"));

// The KAT files generated by the dilithium team use the optional APIs that
// create a signature for a message m and append the message to the end of
// the signature. We only want to bring the APIs that create and verify just
// the signature, therefore each signature is a constant
// DILITHIUM3_SIGNATURE_BYTES and we truncate the signed message down to a
// constant DILITHIUM3_SIGNATURE_BYTES.
uint8_t signature[DILITHIUM3_SIGNATURE_BYTES];
size_t signature_len = DILITHIUM3_SIGNATURE_BYTES;
sm.resize(signature_len);

// Convert string read from KAT to int
size_t mlen_int = std::stoi(mlen);

// Here we fix the DRBG (AES-CTR) so that we are able to seed it with the
// seed from the KAT (testing only)
pq_custom_randombytes_use_deterministic_for_testing();
pq_custom_randombytes_init_for_testing(seed.data());

// Generate our dilithium public and private key pair
EVP_PKEY_CTX *dilithium_pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DILITHIUM3, nullptr);
ASSERT_NE(dilithium_pkey_ctx, nullptr);

EVP_PKEY *dilithium_pkey = EVP_PKEY_new();
ASSERT_NE(dilithium_pkey, nullptr);

EXPECT_TRUE(EVP_PKEY_keygen_init(dilithium_pkey_ctx));
EXPECT_TRUE(EVP_PKEY_keygen(dilithium_pkey_ctx, &dilithium_pkey));
const DILITHIUM3_KEY *dilithium3Key = (DILITHIUM3_KEY *)(dilithium_pkey->pkey.ptr);
EXPECT_EQ(Bytes(pk), Bytes(dilithium3Key->pub, DILITHIUM3_PUBLIC_KEY_BYTES));
EXPECT_EQ(Bytes(sk), Bytes(dilithium3Key->priv, DILITHIUM3_PRIVATE_KEY_BYTES));

// Generate a signature for the message
bssl::ScopedEVP_MD_CTX md_ctx;
// We have to use EVP_DigestSign because dilithium supports the use of
// non-hash-then-sign (just like ed25519) so we first init EVP_DigestSign
// WITHOUT a hash function.
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), NULL, NULL, NULL, dilithium_pkey));
ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), signature, &signature_len, msg.data(), mlen_int));
EXPECT_EQ(Bytes(sm), Bytes(signature, signature_len));

// Verify the signature for the message
ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature, signature_len, msg.data(), mlen_int));
struct ML_DSA {
const char name[20];
const int nid;
const size_t public_key_len;
const size_t secret_key_len;
const size_t signature_len;
const char *kat_filename;
};

EVP_PKEY_free(dilithium_pkey);
EVP_PKEY_CTX_free(dilithium_pkey_ctx);
md_ctx.Reset();
}
static const struct ML_DSA parameterSet[] = {
{"MLDSA65", NID_DILITHIUM3_R3, 1952, 4032, 3309, "dilithium/kat/mldsa65.txt"},
};

TEST(Dilithium3Test, KAT) {
FileTestGTest("crypto/dilithium/kat/dilithium3_r3.txt", RunKat);
class MLDSAParameterTest : public testing::TestWithParam<ML_DSA> {};

INSTANTIATE_TEST_SUITE_P(All, MLDSAParameterTest, testing::ValuesIn(parameterSet),
[](const testing::TestParamInfo<ML_DSA> &params)
-> std::string { return params.param.name; });


TEST_P(MLDSAParameterTest, KAT) {
std::string kat_filepath = "crypto/";
kat_filepath += GetParam().kat_filename;

FileTestGTest(kat_filepath.c_str(), [&](FileTest *t) {
std::string count, mlen, smlen;
std::vector<uint8_t> seed, msg, pk, sk, sm;

ASSERT_TRUE(t->GetAttribute(&count, "count"));
ASSERT_TRUE(t->GetBytes(&seed, "seed"));
ASSERT_TRUE(t->GetAttribute(&mlen, "mlen"));
ASSERT_TRUE(t->GetBytes(&msg, "msg"));
ASSERT_TRUE(t->GetBytes(&pk, "pk"));
ASSERT_TRUE(t->GetBytes(&sk, "sk"));
ASSERT_TRUE(t->GetAttribute(&smlen, "smlen"));
ASSERT_TRUE(t->GetBytes(&sm, "sm"));

size_t pk_len = GetParam().public_key_len;
size_t sk_len = GetParam().secret_key_len;
size_t sig_len = GetParam().signature_len;

// The KAT files generated by the dilithium team use the optional APIs that
// create a signature for a message m and append the message to the end of
// the signature. We only want to bring the APIs that create and verify just
// the signature, therefore each signature is a constant
// DILITHIUM3_SIGNATURE_BYTES and we truncate the signed message down to a
// constant DILITHIUM3_SIGNATURE_BYTES.

std::vector<uint8_t> signature(sig_len);
sm.resize(sig_len);

// Convert string read from KAT to int
size_t mlen_int = std::stoi(mlen);

// Here we fix the DRBG (AES-CTR) so that we are able to seed it with the
// seed from the KAT (testing only)
pq_custom_randombytes_use_deterministic_for_testing();
pq_custom_randombytes_init_for_testing(seed.data());

// Generate our dilithium public and private key pair
EVP_PKEY_CTX *dilithium_pkey_ctx = EVP_PKEY_CTX_new_id(GetParam().nid, nullptr);
ASSERT_NE(dilithium_pkey_ctx, nullptr);

EVP_PKEY *dilithium_pkey = EVP_PKEY_new();
ASSERT_NE(dilithium_pkey, nullptr);

ASSERT_TRUE(EVP_PKEY_keygen_init(dilithium_pkey_ctx));
ASSERT_TRUE(EVP_PKEY_keygen(dilithium_pkey_ctx, &dilithium_pkey));
const DILITHIUM3_KEY *dilithium3Key = (DILITHIUM3_KEY *)(dilithium_pkey->pkey.ptr); //called dilithium3 but is generic
EXPECT_EQ(Bytes(pk), Bytes(dilithium3Key->pub, pk_len));
EXPECT_EQ(Bytes(sk), Bytes(dilithium3Key->priv, sk_len));

// Generate a signature for the message
bssl::ScopedEVP_MD_CTX md_ctx;
// We have to use EVP_DigestSign because dilithium supports the use of
// non-hash-then-sign (just like ed25519) so we first init EVP_DigestSign
// WITHOUT a hash function.
ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), NULL, NULL, NULL, dilithium_pkey));
ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), signature.data(), &sig_len, msg.data(), mlen_int));
EXPECT_EQ(Bytes(sm), Bytes(signature.data(), sig_len));

// Verify the signature for the message
ASSERT_TRUE(EVP_DigestVerify(md_ctx.get(), signature.data(), sig_len, msg.data(), mlen_int));

EVP_PKEY_free(dilithium_pkey);
EVP_PKEY_CTX_free(dilithium_pkey_ctx);
md_ctx.Reset();
});
}

#else
Expand Down
3 changes: 2 additions & 1 deletion crypto/dilithium/pqcrystals_dilithium_ref_common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ The source code in this folder implements ML-DSA as defined in FIPS 204 Module-L

The source code was imported from a branch of the official repository of the Crystals-Dilithium team: https://github.com/pq-crystals/dilithium. The code was taken at [commit](https://github.com/pq-crystals/dilithium/commit/cbcd8753a43402885c90343cd6335fb54712cda1) as of 10/01/2024. At the moment, only the reference C implementation is imported.

The `api.h`, `fips202.h` and `params.h` header files were modified to support our [prefixed symbols build](https://github.com/awslabs/aws-lc/blob/main/BUILDING.md#building-with-prefixed-symbols).
The code was refactored in [this PR](https://github.com/aws/aws-lc/pull/1910) by parameterizing all functions that depend on values that are specific to a parameter set, i.e., that directly or indirectly depend on the value of `DILITHIUM_MODE`. To do this, in `params.h` we defined a structure that holds those ML-DSA parameters and functions
that initialize a given structure with values corresponding to a parameter set. This structure is then passed to every function that requires it as a function argument. In addition, the following changes were made to the source code in `pqcrystals_dilithium_ref_common` directory:

- `randombytes.{h|c}` are deleted because we are using the randomness generation functions provided by AWS-LC.
- `sign.c`: calls to `randombytes` function is replaced with calls to `pq_custom_randombytes` and the appropriate header file is included (`crypto/rand_extra/pq_custom_randombytes.h`).
Expand Down
122 changes: 0 additions & 122 deletions crypto/dilithium/pqcrystals_dilithium_ref_common/api.h

This file was deleted.

Loading

0 comments on commit 0ae4a99

Please sign in to comment.