-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
|
||
#include <vector> | ||
#include "../fipsmodule/evp/internal.h" | ||
#include "../fipsmodule/sha/internal.h" | ||
#include "../internal.h" | ||
#include "../fipsmodule/pqdsa/internal.h" | ||
|
||
|
@@ -1519,6 +1520,80 @@ TEST_P(PQDSAParameterTest, ParsePublicKey) { | |
ASSERT_TRUE(pkey_from_der); | ||
} | ||
|
||
// ML-DSA specific test framework to test pre-hash modes only applicable to ML-DSA | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jakemas
Author
Owner
|
||
struct KnownMLDSA { | ||
const char name[20]; | ||
const int nid; | ||
const size_t public_key_len; | ||
const size_t private_key_len; | ||
const size_t signature_len; | ||
}; | ||
|
||
//todo remove and use the one above | ||
static const struct KnownMLDSA kMLDSAs[] = { | ||
{"MLDSA44", NID_MLDSA44, 1312, 2560, 2420}, | ||
{"MLDSA65", NID_MLDSA65, 1952, 4032, 3309}, | ||
{"MLDSA87", NID_MLDSA87, 2592, 4896, 4627}, | ||
}; | ||
|
||
class PerMLDSATest : public testing::TestWithParam<KnownMLDSA> {}; | ||
|
||
INSTANTIATE_TEST_SUITE_P(All, PerMLDSATest, testing::ValuesIn(kMLDSAs), | ||
[](const testing::TestParamInfo<KnownMLDSA> ¶ms) | ||
-> std::string { return params.param.name; }); | ||
|
||
TEST_P(PerMLDSATest, ExternalMu) { | ||
// ---- 1. Setup phase: generate PQDSA EVP KEY and sign/verify contexts ---- | ||
bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(GetParam().nid)); | ||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey.get(), nullptr); | ||
bssl::ScopedEVP_MD_CTX md_ctx, md_ctx_verify, md_ctx_verify1; | ||
|
||
std::vector<uint8_t> msg1 = { | ||
0x4a, 0x41, 0x4b, 0x45, 0x20, 0x4d, 0x41, 0x53, 0x53, 0x49, | ||
0x4d, 0x4f, 0x20, 0x41, 0x57, 0x53, 0x32, 0x30, 0x32, 0x32, 0x2e}; | ||
|
||
// ----2. Pre-hash setup phase: compute tr, mu ---- | ||
size_t TRBYTES = 64; | ||
size_t CRHBYTES = 64; | ||
size_t pk_len = GetParam().public_key_len; | ||
|
||
std::vector<uint8_t> pk(pk_len); | ||
std::vector<uint8_t> tr(TRBYTES); | ||
std::vector<uint8_t> mu(TRBYTES); | ||
|
||
uint8_t pre[2]; | ||
pre[0] = 0; | ||
pre[1] = 0; | ||
|
||
//get public key and hash it | ||
ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len)); | ||
SHAKE256(pk.data(), pk.size(), tr.data(), TRBYTES); | ||
|
||
//compute mu | ||
KECCAK1600_CTX state; | ||
SHAKE_Init(&state, SHAKE256_BLOCKSIZE); | ||
SHA3_Update(&state, tr.data(), TRBYTES); | ||
SHA3_Update(&state, pre, 2); | ||
SHA3_Update(&state, msg1.data(), msg1.size()); | ||
SHAKE_Final(mu.data(), &state, CRHBYTES); | ||
|
||
// ----2. Init signing, get signature size and allocate signature buffer ---- | ||
size_t sig_len = GetParam().signature_len; | ||
std::vector<uint8_t> sig1(sig_len); | ||
|
||
// ----3. Sign mu ---- | ||
ASSERT_TRUE(EVP_PKEY_sign_init(ctx)); | ||
ASSERT_TRUE(EVP_PKEY_sign(ctx, sig1.data(), &sig_len, mu.data(), mu.size())); | ||
|
||
// ----4. Verify mu (pre-hash) ---- | ||
ASSERT_TRUE(EVP_PKEY_verify_init(ctx)); | ||
ASSERT_TRUE(EVP_PKEY_verify(ctx, sig1.data(), sig_len, mu.data(), mu.size())); | ||
|
||
// ----5. Bonus: Verify raw message with digest verify (no pre-hash) ---- | ||
ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx_verify.get(), nullptr, nullptr, nullptr, pkey.get())); | ||
ASSERT_TRUE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size())); | ||
} | ||
|
||
#else | ||
|
||
TEST(PQDSATest, EvpDisabled) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -139,7 +139,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, | |
return 0; | ||
} | ||
|
||
if (uses_prehash(ctx, op) || used_for_hmac(ctx)) { | ||
if ((uses_prehash(ctx, op) || used_for_hmac(ctx)) && pkey->type != EVP_PKEY_PQDSA) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jakemas
Author
Owner
|
||
if (type == NULL) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST); | ||
return 0; | ||
|
@@ -271,7 +271,7 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len, | |
SET_DIT_AUTO_RESET; | ||
int ret = 0; | ||
|
||
if (uses_prehash(ctx, evp_sign) || used_for_hmac(ctx)) { | ||
if ((uses_prehash(ctx, evp_sign) || used_for_hmac(ctx)) && ctx->pctx->pkey->type != EVP_PKEY_PQDSA) { | ||
// If |out_sig| is NULL, the caller is only querying the maximum output | ||
// length. |data| should only be incorporated in the final call. | ||
if (out_sig != NULL && !EVP_DigestSignUpdate(ctx, data, data_len)) { | ||
|
@@ -310,7 +310,7 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len, | |
SET_DIT_AUTO_RESET; | ||
int ret = 0; | ||
|
||
if (uses_prehash(ctx, evp_verify) && !used_for_hmac(ctx)) { | ||
if ((uses_prehash(ctx, evp_verify) && !used_for_hmac(ctx)) && ctx->pctx->pkey->type != EVP_PKEY_PQDSA) { | ||
ret = EVP_DigestVerifyUpdate(ctx, data, len) && | ||
EVP_DigestVerifyFinal(ctx, sig, sig_len); | ||
goto end; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,7 +97,53 @@ static int pkey_pqdsa_sign_message(EVP_PKEY_CTX *ctx, uint8_t *sig, | |
return 0; | ||
} | ||
|
||
if (!pqdsa->method->pqdsa_sign(key->private_key, sig, sig_len, message, message_len, NULL, 0)) { | ||
if (!pqdsa->method->pqdsa_sign_message(key->private_key, sig, sig_len, message, message_len, NULL, 0)) { | ||
This comment has been minimized.
Sorry, something went wrong.
nebeid
|
||
OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
static int pkey_pqdsa_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sig_len, | ||
const uint8_t *message, size_t message_len) { | ||
PQDSA_PKEY_CTX *dctx = ctx->data; | ||
const PQDSA *pqdsa = dctx->pqdsa; | ||
if (pqdsa == NULL) { | ||
if (ctx->pkey == NULL) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); | ||
return 0; | ||
} | ||
pqdsa = PQDSA_KEY_get0_dsa(ctx->pkey->pkey.pqdsa_key); | ||
} | ||
|
||
// Caller is getting parameter values. | ||
if (sig == NULL) { | ||
if (sig_len != NULL) { | ||
*sig_len = pqdsa->signature_len; | ||
return 1; | ||
} | ||
} | ||
|
||
if (*sig_len != pqdsa->signature_len) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); | ||
return 0; | ||
} | ||
|
||
// Check that the context is properly configured. | ||
if (ctx->pkey == NULL || | ||
ctx->pkey->pkey.pqdsa_key == NULL || | ||
ctx->pkey->type != EVP_PKEY_PQDSA) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); | ||
return 0; | ||
} | ||
|
||
PQDSA_KEY *key = ctx->pkey->pkey.pqdsa_key; | ||
if (!key->private_key) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET); | ||
return 0; | ||
} | ||
|
||
if (!pqdsa->method->pqdsa_sign(key->private_key, sig, sig_len, message, message_len)) { | ||
OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR); | ||
return 0; | ||
} | ||
|
@@ -129,14 +175,47 @@ static int pkey_pqdsa_verify_signature(EVP_PKEY_CTX *ctx, const uint8_t *sig, | |
PQDSA_KEY *key = ctx->pkey->pkey.pqdsa_key; | ||
|
||
if (sig_len != pqdsa->signature_len || | ||
!pqdsa->method->pqdsa_verify(key->public_key, sig, sig_len, message, message_len, NULL, 0)) { | ||
!pqdsa->method->pqdsa_verify_message(key->public_key, sig, sig_len, message, message_len, NULL, 0)) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE); | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
static int pkey_pqdsa_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, | ||
size_t sig_len, const uint8_t *message, | ||
size_t message_len) { | ||
PQDSA_PKEY_CTX *dctx = ctx->data; | ||
const PQDSA *pqdsa = dctx->pqdsa; | ||
|
||
if (pqdsa == NULL) { | ||
if (ctx->pkey == NULL) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); | ||
return 0; | ||
} | ||
|
||
pqdsa = PQDSA_KEY_get0_dsa(ctx->pkey->pkey.pqdsa_key); | ||
} | ||
// Check that the context is properly configured. | ||
if (ctx->pkey == NULL || | ||
ctx->pkey->pkey.pqdsa_key == NULL || | ||
ctx->pkey->type != EVP_PKEY_PQDSA) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED); | ||
return 0; | ||
} | ||
|
||
PQDSA_KEY *key = ctx->pkey->pkey.pqdsa_key; | ||
|
||
if (sig_len != pqdsa->signature_len || | ||
!pqdsa->method->pqdsa_verify(key->public_key, sig, sig_len, message, message_len)) { | ||
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE); | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
// Additional PQDSA specific EVP functions. | ||
|
||
// This function sets pqdsa parameters defined by |nid| in |pkey|. | ||
|
@@ -268,10 +347,10 @@ DEFINE_METHOD_FUNCTION(EVP_PKEY_METHOD, EVP_PKEY_pqdsa_pkey_meth) { | |
out->cleanup = pkey_pqdsa_cleanup; | ||
out->keygen = pkey_pqdsa_keygen; | ||
out->sign_init = NULL; | ||
out->sign = NULL; | ||
out->sign = pkey_pqdsa_sign; | ||
out->sign_message = pkey_pqdsa_sign_message; | ||
out->verify_init = NULL; | ||
out->verify = NULL; | ||
out->verify = pkey_pqdsa_verify; | ||
out->verify_message = pkey_pqdsa_verify_signature; | ||
out->verify_recover = NULL; | ||
out->encrypt = NULL; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,16 @@ int ml_dsa_44_sign(const uint8_t *private_key /* IN */, | |
ctx_string, ctx_string_len, private_key) == 0; | ||
} | ||
|
||
int ml_dsa_extmu_44_sign(const uint8_t *private_key /* IN */, | ||
This comment has been minimized.
Sorry, something went wrong.
nebeid
|
||
uint8_t *sig /* OUT */, | ||
size_t *sig_len /* OUT */, | ||
const uint8_t *message /* IN */, | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
size_t message_len /* IN */) { | ||
ml_dsa_params params; | ||
ml_dsa_44_params_init(¶ms); | ||
return ml_dsa_extmu_sign(¶ms, sig, sig_len, message, message_len, private_key) == 0; | ||
This comment has been minimized.
Sorry, something went wrong.
nebeid
|
||
} | ||
|
||
int ml_dsa_44_sign_internal(const uint8_t *private_key /* IN */, | ||
uint8_t *sig /* OUT */, | ||
size_t *sig_len /* OUT */, | ||
|
@@ -62,7 +72,7 @@ int ml_dsa_44_sign_internal(const uint8_t *private_key /* IN */, | |
ml_dsa_params params; | ||
ml_dsa_44_params_init(¶ms); | ||
return ml_dsa_sign_internal(¶ms, sig, sig_len, message, message_len, | ||
pre, pre_len, rnd, private_key) == 0; | ||
pre, pre_len, rnd, private_key, 0) == 0; | ||
} | ||
|
||
int ml_dsa_44_verify(const uint8_t *public_key /* IN */, | ||
|
@@ -78,6 +88,16 @@ int ml_dsa_44_verify(const uint8_t *public_key /* IN */, | |
ctx_string, ctx_string_len, public_key) == 0; | ||
} | ||
|
||
int ml_dsa_extmu_44_verify(const uint8_t *public_key /* IN */, | ||
const uint8_t *sig /* IN */, | ||
size_t sig_len /* IN */, | ||
const uint8_t *message /* IN */, | ||
size_t message_len /* IN */) { | ||
ml_dsa_params params; | ||
ml_dsa_44_params_init(¶ms); | ||
return ml_dsa_verify_internal(¶ms, sig, sig_len, message, message_len, NULL, 0, public_key, 1) == 0; | ||
} | ||
|
||
int ml_dsa_44_verify_internal(const uint8_t *public_key /* IN */, | ||
const uint8_t *sig /* IN */, | ||
size_t sig_len /* IN */, | ||
|
@@ -88,7 +108,7 @@ int ml_dsa_44_verify_internal(const uint8_t *public_key /* IN */, | |
ml_dsa_params params; | ||
ml_dsa_44_params_init(¶ms); | ||
return ml_dsa_verify_internal(¶ms, sig, sig_len, message, message_len, | ||
pre, pre_len, public_key) == 0; | ||
pre, pre_len, public_key, 0) == 0; | ||
} | ||
|
||
int ml_dsa_65_keypair(uint8_t *public_key /* OUT */, | ||
|
@@ -119,6 +139,16 @@ int ml_dsa_65_sign(const uint8_t *private_key /* IN */, | |
ctx_string, ctx_string_len, private_key) == 0; | ||
} | ||
|
||
int ml_dsa_extmu_65_sign(const uint8_t *private_key /* IN */, | ||
uint8_t *sig /* OUT */, | ||
size_t *sig_len /* OUT */, | ||
const uint8_t *message /* IN */, | ||
size_t message_len /* IN */) { | ||
ml_dsa_params params; | ||
ml_dsa_65_params_init(¶ms); | ||
return ml_dsa_extmu_sign(¶ms, sig, sig_len, message, message_len, private_key) == 0; | ||
} | ||
|
||
int ml_dsa_65_sign_internal(const uint8_t *private_key /* IN */, | ||
uint8_t *sig /* OUT */, | ||
size_t *sig_len /* OUT */, | ||
|
@@ -130,7 +160,7 @@ int ml_dsa_65_sign_internal(const uint8_t *private_key /* IN */, | |
ml_dsa_params params; | ||
ml_dsa_65_params_init(¶ms); | ||
return ml_dsa_sign_internal(¶ms, sig, sig_len, message, message_len, | ||
pre, pre_len, rnd, private_key) == 0; | ||
pre, pre_len, rnd, private_key, 0) == 0; | ||
} | ||
|
||
int ml_dsa_65_verify(const uint8_t *public_key /* IN */, | ||
|
@@ -146,6 +176,16 @@ int ml_dsa_65_verify(const uint8_t *public_key /* IN */, | |
ctx_string, ctx_string_len, public_key) == 0; | ||
} | ||
|
||
int ml_dsa_extmu_65_verify(const uint8_t *public_key /* IN */, | ||
const uint8_t *sig /* IN */, | ||
size_t sig_len /* IN */, | ||
const uint8_t *message /* IN */, | ||
size_t message_len /* IN */) { | ||
ml_dsa_params params; | ||
ml_dsa_65_params_init(¶ms); | ||
return ml_dsa_verify_internal(¶ms, sig, sig_len, message, message_len, NULL, 0, public_key, 1) == 0; | ||
} | ||
|
||
int ml_dsa_65_verify_internal(const uint8_t *public_key /* IN */, | ||
const uint8_t *sig /* IN */, | ||
size_t sig_len /* IN */, | ||
|
@@ -156,7 +196,7 @@ int ml_dsa_65_verify_internal(const uint8_t *public_key /* IN */, | |
ml_dsa_params params; | ||
ml_dsa_65_params_init(¶ms); | ||
return ml_dsa_verify_internal(¶ms, sig, sig_len, message, message_len, | ||
pre, pre_len, public_key) == 0; | ||
pre, pre_len, public_key, 0) == 0; | ||
} | ||
|
||
int ml_dsa_87_keypair(uint8_t *public_key /* OUT */, | ||
|
@@ -187,6 +227,16 @@ int ml_dsa_87_sign(const uint8_t *private_key /* IN */, | |
ctx_string, ctx_string_len, private_key) == 0; | ||
} | ||
|
||
int ml_dsa_extmu_87_sign(const uint8_t *private_key /* IN */, | ||
uint8_t *sig /* OUT */, | ||
size_t *sig_len /* OUT */, | ||
const uint8_t *message /* IN */, | ||
size_t message_len /* IN */) { | ||
ml_dsa_params params; | ||
ml_dsa_87_params_init(¶ms); | ||
return ml_dsa_extmu_sign(¶ms, sig, sig_len, message, message_len, private_key) == 0; | ||
} | ||
|
||
int ml_dsa_87_sign_internal(const uint8_t *private_key /* IN */, | ||
uint8_t *sig /* OUT */, | ||
size_t *sig_len /* OUT */, | ||
|
@@ -198,7 +248,7 @@ int ml_dsa_87_sign_internal(const uint8_t *private_key /* IN */, | |
ml_dsa_params params; | ||
ml_dsa_87_params_init(¶ms); | ||
return ml_dsa_sign_internal(¶ms, sig, sig_len, message, message_len, | ||
pre, pre_len, rnd, private_key) == 0; | ||
pre, pre_len, rnd, private_key, 0) == 0; | ||
} | ||
|
||
int ml_dsa_87_verify(const uint8_t *public_key /* IN */, | ||
|
@@ -214,6 +264,16 @@ int ml_dsa_87_verify(const uint8_t *public_key /* IN */, | |
ctx_string, ctx_string_len, public_key) == 0; | ||
} | ||
|
||
int ml_dsa_extmu_87_verify(const uint8_t *public_key /* IN */, | ||
const uint8_t *sig /* IN */, | ||
size_t sig_len /* IN */, | ||
const uint8_t *message /* IN */, | ||
size_t message_len /* IN */) { | ||
ml_dsa_params params; | ||
ml_dsa_87_params_init(¶ms); | ||
return ml_dsa_verify_internal(¶ms, sig, sig_len, message, message_len, NULL, 0, public_key, 1) == 0; | ||
} | ||
|
||
int ml_dsa_87_verify_internal(const uint8_t *public_key /* IN */, | ||
const uint8_t *sig /* IN */, | ||
size_t sig_len /* IN */, | ||
|
@@ -224,5 +284,5 @@ int ml_dsa_87_verify_internal(const uint8_t *public_key /* IN */, | |
ml_dsa_params params; | ||
ml_dsa_87_params_init(¶ms); | ||
return ml_dsa_verify_internal(¶ms, sig, sig_len, message, message_len, | ||
pre, pre_len, public_key) == 0; | ||
pre, pre_len, public_key, 0) == 0; | ||
} |
Are there test vectors we can use for external mu? Or we'll leave this for later?