pq_crypto 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/SECURITY.md +7 -0
- data/ext/pqcrypto/pqcrypto_version.h +1 -1
- data/ext/pqcrypto/vendor/.vendored +4 -4
- data/ext/pqcrypto/vendor/mldsa-native/README.md +23 -10
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/README.md +23 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +114 -58
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +498 -461
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +145 -85
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +456 -422
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +47 -25
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +26 -14
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +56 -81
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +17 -24
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.c +33 -40
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.h +67 -87
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +19 -14
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +13 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +84 -10
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +10 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +6 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +22 -15
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_aarch64_asm.S +376 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_aarch64_asm.S +204 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_aarch64_asm.S +259 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_aarch64_asm.S +1077 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_aarch64_asm.S +987 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +16 -10
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +2 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +4 -2
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +2 -2
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +60 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +48 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +18 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +658 -582
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +5 -100
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +26 -25
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +334 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +355 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +8 -3
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/{xkcp.h → keccak_f1600_x4_avx2.h} +11 -8
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/fips202_native_x86_64.h +44 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2_asm.S +454 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/keccakf1600_constants.c +52 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +37 -28
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +213 -196
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +248 -64
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt_aarch64_asm.S +753 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4_aarch64_asm.S +129 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5_aarch64_asm.S +145 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7_aarch64_asm.S +177 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt_aarch64_asm.S +653 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery_aarch64_asm.S +84 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_aarch64_asm.S +53 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_aarch64_asm.S +55 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_aarch64_asm.S +86 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_aarch64_asm.S +86 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_aarch64_asm.S +103 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_aarch64_asm.S +111 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_aarch64_asm.S +75 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_aarch64_asm.S +72 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +23 -11
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_aarch64_asm.S +189 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_aarch64_asm.S +137 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_aarch64_asm.S +130 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +520 -516
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +34 -33
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +202 -242
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +25 -17
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +112 -28
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +1 -1
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt_avx2_asm.S +2311 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt_avx2_asm.S +2383 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack_avx2_asm.S +238 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4_avx2_asm.S +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5_avx2_asm.S +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7_avx2_asm.S +187 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_avx2_asm.S +130 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2_asm.S +190 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +9 -8
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +10 -9
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +8 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +8 -5
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +6 -4
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +130 -129
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +109 -180
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +169 -150
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +56 -40
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +149 -164
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +52 -57
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +132 -167
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +57 -424
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +167 -474
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.c +308 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec_lazy.h +653 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +22 -29
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +37 -43
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +511 -367
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +456 -417
- data/lib/pq_crypto/version.rb +1 -1
- data/script/vendor_libs.rb +3 -3
- metadata +41 -35
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +0 -376
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +0 -204
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +0 -259
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +0 -1077
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +0 -987
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.c +0 -488
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.h +0 -16
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt.S +0 -753
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4.S +0 -129
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5.S +0 -145
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7.S +0 -177
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt.S +0 -653
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery.S +0 -79
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_asm.S +0 -53
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_asm.S +0 -55
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_asm.S +0 -85
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_asm.S +0 -85
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_asm.S +0 -102
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_asm.S +0 -110
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_asm.S +0 -72
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_asm.S +0 -69
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_asm.S +0 -189
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_asm.S +0 -135
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_asm.S +0 -128
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt.S +0 -2311
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt.S +0 -2383
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack.S +0 -239
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise.S +0 -131
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4.S +0 -139
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5.S +0 -155
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7.S +0 -187
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2.c +0 -61
|
@@ -48,39 +48,43 @@
|
|
|
48
48
|
#define mld_compute_pack_z MLD_ADD_PARAM_SET(mld_compute_pack_z)
|
|
49
49
|
#define mld_attempt_signature_generation \
|
|
50
50
|
MLD_ADD_PARAM_SET(mld_attempt_signature_generation) MLD_CONTEXT_PARAMETERS_8
|
|
51
|
-
#define
|
|
52
|
-
MLD_ADD_PARAM_SET(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
#define mld_compute_pack_t0_t1 \
|
|
52
|
+
MLD_ADD_PARAM_SET(mld_compute_pack_t0_t1) MLD_CONTEXT_PARAMETERS_5
|
|
53
|
+
#define mld_get_max_signing_attempts \
|
|
54
|
+
MLD_ADD_PARAM_SET(mld_get_max_signing_attempts)
|
|
56
55
|
|
|
56
|
+
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
|
|
57
57
|
static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
58
58
|
uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
59
59
|
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
60
60
|
__contract__(
|
|
61
61
|
requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
|
|
62
62
|
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
|
|
63
|
-
ensures(return_value == 0
|
|
64
|
-
|| return_value == MLD_ERR_FAIL
|
|
65
|
-
|| return_value == MLD_ERR_OUT_OF_MEMORY
|
|
66
|
-
|| return_value == MLD_ERR_RNG_FAIL)
|
|
63
|
+
ensures(return_value == 0 || MLD_ANY_ERROR(return_value))
|
|
67
64
|
);
|
|
68
65
|
|
|
69
66
|
#if defined(MLD_CONFIG_KEYGEN_PCT)
|
|
70
|
-
|
|
71
|
-
*
|
|
72
|
-
*
|
|
67
|
+
/**
|
|
68
|
+
* Pair-wise Consistency Test (PCT) for DSA keypairs.
|
|
69
|
+
*
|
|
70
|
+
* @[FIPS140_3_IG] TE10.35.02
|
|
71
|
+
* (https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf).
|
|
72
|
+
*
|
|
73
|
+
* Validates that a generated public/private key pair can correctly sign and
|
|
74
|
+
* verify data. Performs signature generation using the private key (sk),
|
|
75
|
+
* followed by signature verification using the public key (pk).
|
|
73
76
|
*
|
|
74
|
-
*
|
|
77
|
+
* @note @[FIPS204] requires that public/private key pairs are to be used
|
|
78
|
+
* only for the calculation and/or verification of digital signatures.
|
|
75
79
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
+
* @param[in] pk Public key.
|
|
81
|
+
* @param[in] sk Secret key.
|
|
82
|
+
* @param context Application context. Only present when
|
|
83
|
+
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
|
|
84
|
+
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
|
|
80
85
|
*
|
|
81
|
-
*
|
|
82
|
-
|
|
83
|
-
**************************************************/
|
|
86
|
+
* @return 0 if the signature was successfully verified, non-zero otherwise.
|
|
87
|
+
*/
|
|
84
88
|
static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
85
89
|
uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
86
90
|
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
@@ -195,52 +199,56 @@ __contract__(
|
|
|
195
199
|
#endif /* !MLD_CONFIG_SERIAL_FIPS202_ONLY */
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
|
|
199
|
-
*
|
|
202
|
+
/**
|
|
203
|
+
* Compute t = A*s1hat + s2 row by row, decompose each row into t0[k] and
|
|
204
|
+
* t1[k] via power2round, and bit-pack t1[k] into pk_t1 and t0[k] into the
|
|
205
|
+
* t0_packed buffer. Used by both keygen and pk_from_sk.
|
|
200
206
|
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
207
|
+
* @param[out] pk_t1 Output buffer for packed t1 (size
|
|
208
|
+
* MLDSA_K * MLDSA_POLYT1_PACKEDBYTES; i.e. the t1
|
|
209
|
+
* region of pk).
|
|
210
|
+
* @param[out] t0_packed Output buffer for packed t0 (size
|
|
211
|
+
* MLDSA_K * MLDSA_POLYT0_PACKEDBYTES).
|
|
212
|
+
* @param[in] s1hat s1 in NTT domain.
|
|
213
|
+
* @param[in] s2 s2.
|
|
214
|
+
* @param[in] rho Byte array containing seed rho.
|
|
215
|
+
* @param context Application context. Only present when
|
|
216
|
+
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
|
|
217
|
+
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
|
|
205
218
|
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
|
|
210
|
-
* - const uint8_t rho[MLDSA_SEEDBYTES]: input rho
|
|
211
|
-
* - const mld_polyvecl *s1: input s1
|
|
212
|
-
* - const mld_polyveck *s2: input s2
|
|
213
|
-
**************************************************/
|
|
219
|
+
* @return - 0: Success.
|
|
220
|
+
* - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is used and
|
|
221
|
+
* an allocation via MLD_CUSTOM_ALLOC returned NULL.
|
|
222
|
+
*/
|
|
214
223
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
215
|
-
static int
|
|
216
|
-
|
|
217
|
-
uint8_t
|
|
218
|
-
const mld_polyvecl *
|
|
224
|
+
static int mld_compute_pack_t0_t1(
|
|
225
|
+
uint8_t pk_t1[MLDSA_K * MLDSA_POLYT1_PACKEDBYTES],
|
|
226
|
+
uint8_t t0_packed[MLDSA_K * MLDSA_POLYT0_PACKEDBYTES],
|
|
227
|
+
const mld_polyvecl *s1hat, const mld_polyveck *s2,
|
|
228
|
+
const uint8_t rho[MLDSA_SEEDBYTES],
|
|
219
229
|
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
220
230
|
__contract__(
|
|
221
|
-
requires(memory_no_alias(
|
|
222
|
-
requires(memory_no_alias(
|
|
223
|
-
requires(memory_no_alias(
|
|
224
|
-
requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
|
|
225
|
-
requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
|
|
226
|
-
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
|
|
231
|
+
requires(memory_no_alias(pk_t1, MLDSA_K * MLDSA_POLYT1_PACKEDBYTES))
|
|
232
|
+
requires(memory_no_alias(t0_packed, MLDSA_K * MLDSA_POLYT0_PACKEDBYTES))
|
|
233
|
+
requires(memory_no_alias(s1hat, sizeof(mld_polyvecl)))
|
|
227
234
|
requires(memory_no_alias(s2, sizeof(mld_polyveck)))
|
|
228
|
-
requires(
|
|
229
|
-
requires(forall(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
235
|
+
requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
|
|
236
|
+
requires(forall(l1, 0, MLDSA_L,
|
|
237
|
+
array_abs_bound(s1hat->vec[l1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
238
|
+
requires(forall(k2, 0, MLDSA_K,
|
|
239
|
+
array_bound(s2->vec[k2].coeffs, 0, MLDSA_N,
|
|
240
|
+
MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
|
|
241
|
+
assigns(memory_slice(pk_t1, MLDSA_K * MLDSA_POLYT1_PACKEDBYTES))
|
|
242
|
+
assigns(memory_slice(t0_packed, MLDSA_K * MLDSA_POLYT0_PACKEDBYTES))
|
|
236
243
|
ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY))
|
|
237
244
|
{
|
|
245
|
+
unsigned int k;
|
|
238
246
|
int ret;
|
|
239
247
|
MLD_ALLOC(mat, mld_polymat, 1, context);
|
|
240
|
-
MLD_ALLOC(
|
|
241
|
-
MLD_ALLOC(
|
|
248
|
+
MLD_ALLOC(t0k, mld_poly, 1, context);
|
|
249
|
+
MLD_ALLOC(t1k, mld_poly, 1, context);
|
|
242
250
|
|
|
243
|
-
if (mat == NULL ||
|
|
251
|
+
if (mat == NULL || t0k == NULL || t1k == NULL)
|
|
244
252
|
{
|
|
245
253
|
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
246
254
|
goto cleanup;
|
|
@@ -249,40 +257,52 @@ __contract__(
|
|
|
249
257
|
/* Expand matrix */
|
|
250
258
|
mld_polyvec_matrix_expand(mat, rho);
|
|
251
259
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
260
|
+
for (k = 0; k < MLDSA_K; k++)
|
|
261
|
+
__loop__(
|
|
262
|
+
assigns(k, memory_slice(pk_t1, MLDSA_K * MLDSA_POLYT1_PACKEDBYTES),
|
|
263
|
+
memory_slice(t0_packed, MLDSA_K * MLDSA_POLYT0_PACKEDBYTES),
|
|
264
|
+
memory_slice(t0k, sizeof(mld_poly)),
|
|
265
|
+
memory_slice(t1k, sizeof(mld_poly))
|
|
266
|
+
MLD_IF_REDUCE_RAM(, memory_slice(mat, sizeof(mld_polymat))))
|
|
267
|
+
invariant(k <= MLDSA_K)
|
|
268
|
+
decreases(MLDSA_K - k)
|
|
269
|
+
)
|
|
270
|
+
{
|
|
271
|
+
/* t0k = (A * s1hat)_k in NTT domain */
|
|
272
|
+
mld_polyvec_matrix_pointwise_montgomery_row(t0k, mat, s1hat, k);
|
|
273
|
+
|
|
274
|
+
/* t0k = invNTT(t0k) */
|
|
275
|
+
mld_poly_invntt_tomont(t0k);
|
|
276
|
+
|
|
277
|
+
/* t0k += s2[k] */
|
|
278
|
+
mld_poly_add(t0k, &s2->vec[k]);
|
|
279
|
+
|
|
280
|
+
/* Reference: The following reduction is not present in the reference
|
|
281
|
+
* implementation. Omitting this reduction requires the output
|
|
282
|
+
* of the invntt to be small enough such that the addition of
|
|
283
|
+
* s2 does not result in absolute values >= MLDSA_Q. While our
|
|
284
|
+
* C, x86_64, and AArch64 invntt implementations produce small
|
|
285
|
+
* enough values for this to work out, it complicates the
|
|
286
|
+
* bounds reasoning. We instead add an additional reduction,
|
|
287
|
+
* and can consequently, relax the bounds requirements for the
|
|
288
|
+
* invntt.
|
|
289
|
+
*/
|
|
290
|
+
mld_poly_reduce(t0k);
|
|
291
|
+
|
|
292
|
+
/* Decompose into t1[k] and t0[k] (in place into t0k). */
|
|
293
|
+
mld_poly_caddq(t0k);
|
|
294
|
+
mld_poly_power2round(t1k, t0k, t0k);
|
|
295
|
+
|
|
296
|
+
/* Pack t1[k] into pk and t0[k] into the t0 output buffer. */
|
|
297
|
+
mld_polyt1_pack(pk_t1 + k * MLDSA_POLYT1_PACKEDBYTES, t1k);
|
|
298
|
+
mld_polyt0_pack(t0_packed + k * MLDSA_POLYT0_PACKEDBYTES, t0k);
|
|
299
|
+
}
|
|
279
300
|
|
|
280
301
|
ret = 0;
|
|
281
|
-
|
|
282
302
|
cleanup:
|
|
283
303
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
284
|
-
MLD_FREE(
|
|
285
|
-
MLD_FREE(
|
|
304
|
+
MLD_FREE(t1k, mld_poly, 1, context);
|
|
305
|
+
MLD_FREE(t0k, mld_poly, 1, context);
|
|
286
306
|
MLD_FREE(mat, mld_polymat, 1, context);
|
|
287
307
|
return ret;
|
|
288
308
|
}
|
|
@@ -296,16 +316,15 @@ int mld_sign_keypair_internal(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
|
296
316
|
{
|
|
297
317
|
int ret;
|
|
298
318
|
const uint8_t *rho, *rhoprime, *key;
|
|
319
|
+
|
|
299
320
|
MLD_ALLOC(seedbuf, uint8_t, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, context);
|
|
300
321
|
MLD_ALLOC(inbuf, uint8_t, MLDSA_SEEDBYTES + 2, context);
|
|
301
322
|
MLD_ALLOC(tr, uint8_t, MLDSA_TRBYTES, context);
|
|
302
323
|
MLD_ALLOC(s1, mld_polyvecl, 1, context);
|
|
303
324
|
MLD_ALLOC(s2, mld_polyveck, 1, context);
|
|
304
|
-
MLD_ALLOC(t1, mld_polyveck, 1, context);
|
|
305
|
-
MLD_ALLOC(t0, mld_polyveck, 1, context);
|
|
306
325
|
|
|
307
326
|
if (seedbuf == NULL || inbuf == NULL || tr == NULL || s1 == NULL ||
|
|
308
|
-
s2 == NULL
|
|
327
|
+
s2 == NULL)
|
|
309
328
|
{
|
|
310
329
|
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
311
330
|
goto cleanup;
|
|
@@ -327,24 +346,38 @@ int mld_sign_keypair_internal(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
|
327
346
|
/* Sample s1 and s2 */
|
|
328
347
|
mld_sample_s1_s2(s1, s2, rhoprime);
|
|
329
348
|
|
|
330
|
-
/*
|
|
331
|
-
|
|
332
|
-
|
|
349
|
+
/* Pack s1 into sk before NTT */
|
|
350
|
+
mld_pack_sk_s1(sk, s1);
|
|
351
|
+
|
|
352
|
+
/* NTT s1 in place to use as s1hat */
|
|
353
|
+
mld_polyvecl_ntt(s1);
|
|
354
|
+
|
|
355
|
+
/* Pack rho into pk */
|
|
356
|
+
mld_memcpy(pk, rho, MLDSA_SEEDBYTES);
|
|
357
|
+
|
|
358
|
+
/* Compute t = A*s1hat + s2 row by row, decompose into t1/t0, and pack
|
|
359
|
+
* t1 into pk and t0 directly into the t0 region of sk. */
|
|
360
|
+
ret = mld_compute_pack_t0_t1(pk + MLDSA_SEEDBYTES,
|
|
361
|
+
sk + 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES +
|
|
362
|
+
MLDSA_L * MLDSA_POLYETA_PACKEDBYTES +
|
|
363
|
+
MLDSA_K * MLDSA_POLYETA_PACKEDBYTES,
|
|
364
|
+
s1, s2, rho, context);
|
|
333
365
|
if (ret != 0)
|
|
334
366
|
{
|
|
335
367
|
goto cleanup;
|
|
336
368
|
}
|
|
337
369
|
|
|
338
|
-
/*
|
|
339
|
-
|
|
370
|
+
/* Compute tr = H(pk) */
|
|
371
|
+
mld_shake256(tr, MLDSA_TRBYTES, pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
372
|
+
|
|
373
|
+
/* Pack remaining secret key components (s1 and t0 already packed) */
|
|
374
|
+
mld_pack_sk_rho_key_tr_s2(sk, rho, tr, key, s2);
|
|
340
375
|
|
|
341
376
|
/* Constant time: pk is the public key, inherently public data */
|
|
342
377
|
MLD_CT_TESTING_DECLASSIFY(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
343
378
|
|
|
344
379
|
cleanup:
|
|
345
380
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
346
|
-
MLD_FREE(t0, mld_polyveck, 1, context);
|
|
347
|
-
MLD_FREE(t1, mld_polyveck, 1, context);
|
|
348
381
|
MLD_FREE(s2, mld_polyveck, 1, context);
|
|
349
382
|
MLD_FREE(s1, mld_polyvecl, 1, context);
|
|
350
383
|
MLD_FREE(tr, uint8_t, MLDSA_TRBYTES, context);
|
|
@@ -361,6 +394,7 @@ cleanup:
|
|
|
361
394
|
return mld_check_pct(pk, sk, context);
|
|
362
395
|
}
|
|
363
396
|
|
|
397
|
+
#if !defined(MLD_CONFIG_CORE_API_ONLY)
|
|
364
398
|
#if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
|
|
365
399
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
366
400
|
MLD_EXTERNAL_API
|
|
@@ -368,45 +402,48 @@ int mld_sign_keypair(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
|
368
402
|
uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
369
403
|
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
370
404
|
{
|
|
371
|
-
MLD_ALIGN uint8_t seed[MLDSA_SEEDBYTES];
|
|
372
405
|
int ret;
|
|
406
|
+
MLD_ALLOC(seed, uint8_t, MLDSA_SEEDBYTES, context);
|
|
407
|
+
|
|
408
|
+
if (seed == NULL)
|
|
409
|
+
{
|
|
410
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
411
|
+
goto cleanup;
|
|
412
|
+
}
|
|
413
|
+
|
|
373
414
|
if (mld_randombytes(seed, MLDSA_SEEDBYTES) != 0)
|
|
374
415
|
{
|
|
375
416
|
ret = MLD_ERR_RNG_FAIL;
|
|
376
417
|
goto cleanup;
|
|
377
418
|
}
|
|
378
|
-
MLD_CT_TESTING_SECRET(seed,
|
|
419
|
+
MLD_CT_TESTING_SECRET(seed, MLDSA_SEEDBYTES);
|
|
379
420
|
ret = mld_sign_keypair_internal(pk, sk, seed, context);
|
|
380
421
|
|
|
381
422
|
cleanup:
|
|
382
423
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
383
|
-
|
|
424
|
+
MLD_FREE(seed, uint8_t, MLDSA_SEEDBYTES, context);
|
|
384
425
|
return ret;
|
|
385
426
|
}
|
|
386
427
|
#endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
|
|
428
|
+
#endif /* !MLD_CONFIG_CORE_API_ONLY */
|
|
429
|
+
#endif /* !MLD_CONFIG_NO_KEYPAIR_API */
|
|
387
430
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
* one, two or three blocks of data,
|
|
393
|
-
* yielding a user-requested size of
|
|
394
|
-
* output.
|
|
431
|
+
#if !defined(MLD_CONFIG_NO_SIGN_API) || !defined(MLD_CONFIG_NO_VERIFY_API)
|
|
432
|
+
/**
|
|
433
|
+
* Abstracts application of SHAKE256 to one, two or three blocks of data,
|
|
434
|
+
* yielding a user-requested size of output.
|
|
395
435
|
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
|
|
407
|
-
* this block is ignored
|
|
408
|
-
* - size_t in3len: length of input in3 bytes
|
|
409
|
-
**************************************************/
|
|
436
|
+
* @param[out] out Pointer to output.
|
|
437
|
+
* @param outlen Requested output length in bytes.
|
|
438
|
+
* @param[in] in1 Pointer to input block 1. Must NOT be NULL.
|
|
439
|
+
* @param in1len Length of input in1 in bytes.
|
|
440
|
+
* @param[in] in2 Pointer to input block 2. May be NULL if in2len == 0,
|
|
441
|
+
* in which case this block is ignored.
|
|
442
|
+
* @param in2len Length of input in2 in bytes.
|
|
443
|
+
* @param[in] in3 Pointer to input block 3. May be NULL if in3len == 0,
|
|
444
|
+
* in which case this block is ignored.
|
|
445
|
+
* @param in3len Length of input in3 in bytes.
|
|
446
|
+
*/
|
|
410
447
|
static void mld_H(uint8_t *out, size_t outlen, const uint8_t *in1,
|
|
411
448
|
size_t in1len, const uint8_t *in2, size_t in2len,
|
|
412
449
|
const uint8_t *in3, size_t in3len)
|
|
@@ -440,44 +477,62 @@ __contract__(
|
|
|
440
477
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
441
478
|
mld_zeroize(&state, sizeof(state));
|
|
442
479
|
}
|
|
480
|
+
#endif /* !MLD_CONFIG_NO_SIGN_API || !MLD_CONFIG_NO_VERIFY_API */
|
|
443
481
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
482
|
+
#if !defined(MLD_CONFIG_NO_SIGN_API)
|
|
483
|
+
/* Reference: The reference implementation does not explicitly check the
|
|
484
|
+
* maximum nonce value, but instead loops indefinitely (even when the nonce
|
|
485
|
+
* would overflow). Internally, sampling of y uses
|
|
486
|
+
* (nonce*L), (nonce*L+1), ..., (nonce*L + L - 1).
|
|
487
|
+
* Hence, there are no overflows if nonce < (UINT16_MAX - L)/L.
|
|
488
|
+
* Explicitly checking for this explicitly allows us to prove type-safety. */
|
|
489
|
+
#define MLD_NONCE_UB ((UINT16_MAX - MLDSA_L) / MLDSA_L)
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Compute z = y + s1*c, check that z has coefficients smaller than
|
|
493
|
+
* MLDSA_GAMMA1 - MLDSA_BETA, and pack z into the signature buffer.
|
|
450
494
|
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
* - const polyvecl *s1: secret vector s1
|
|
454
|
-
* - const polyvecl *y: masking vector y
|
|
495
|
+
* @reference{This function is inlined into mld_sign_signature in the
|
|
496
|
+
* reference implementation.}
|
|
455
497
|
*
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
*
|
|
498
|
+
* @param[in,out] sig Output signature.
|
|
499
|
+
* @param[in] cp Challenge polynomial.
|
|
500
|
+
* @param[in] s1hat Secret vector s1 in NTT domain.
|
|
501
|
+
* @param[in] y Masking vector y (or seed in REDUCE_RAM mode).
|
|
502
|
+
* @param[out] z Scratch polynomial for z computation.
|
|
503
|
+
* @param[out] tmp Scratch polynomial.
|
|
461
504
|
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
|
|
505
|
+
* @return - 0: Success (z has coefficients smaller than
|
|
506
|
+
* MLDSA_GAMMA1 - MLDSA_BETA).
|
|
507
|
+
* - MLD_ERR_FAIL: z rejected (norm check failed).
|
|
508
|
+
* - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is used and
|
|
509
|
+
* an allocation via MLD_CUSTOM_ALLOC returned NULL.
|
|
510
|
+
*/
|
|
465
511
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
466
512
|
static int mld_compute_pack_z(uint8_t sig[MLDSA_CRYPTO_BYTES],
|
|
467
|
-
const mld_poly *cp, const
|
|
468
|
-
const
|
|
513
|
+
const mld_poly *cp, const mld_sk_s1hat *s1hat,
|
|
514
|
+
const mld_yvec *y, mld_poly *z, mld_poly *tmp)
|
|
469
515
|
__contract__(
|
|
470
516
|
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
|
|
471
517
|
requires(memory_no_alias(cp, sizeof(mld_poly)))
|
|
472
|
-
requires(memory_no_alias(
|
|
473
|
-
requires(memory_no_alias(y, sizeof(
|
|
518
|
+
requires(memory_no_alias(s1hat, sizeof(mld_sk_s1hat)))
|
|
519
|
+
requires(memory_no_alias(y, sizeof(mld_yvec)))
|
|
474
520
|
requires(memory_no_alias(z, sizeof(mld_poly)))
|
|
521
|
+
requires(memory_no_alias(tmp, sizeof(mld_poly)))
|
|
475
522
|
requires(array_abs_bound(cp->coeffs, 0, MLDSA_N, MLD_NTT_BOUND))
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
523
|
+
MLD_IF_NOT_REDUCE_RAM(
|
|
524
|
+
requires(forall(k0, 0, MLDSA_L,
|
|
525
|
+
array_bound(y->vec.vec[k0].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
|
|
526
|
+
requires(forall(k1, 0, MLDSA_L, array_abs_bound(s1hat->vec.vec[k1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
527
|
+
)
|
|
528
|
+
MLD_IF_REDUCE_RAM(
|
|
529
|
+
requires(memory_no_alias(s1hat->packed, MLDSA_L * MLDSA_POLYETA_PACKEDBYTES))
|
|
530
|
+
requires(memory_no_alias(y->rhoprime, MLDSA_CRHBYTES))
|
|
531
|
+
requires(y->nonce <= MLD_NONCE_UB)
|
|
532
|
+
)
|
|
479
533
|
assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
480
534
|
assigns(memory_slice(z, sizeof(mld_poly)))
|
|
535
|
+
assigns(memory_slice(tmp, sizeof(mld_poly)))
|
|
481
536
|
ensures(return_value == 0 || return_value == MLD_ERR_FAIL ||
|
|
482
537
|
return_value == MLD_ERR_OUT_OF_MEMORY)
|
|
483
538
|
)
|
|
@@ -486,14 +541,18 @@ __contract__(
|
|
|
486
541
|
uint32_t z_invalid;
|
|
487
542
|
for (i = 0; i < MLDSA_L; i++)
|
|
488
543
|
__loop__(
|
|
489
|
-
assigns(i, memory_slice(z, sizeof(mld_poly)),
|
|
544
|
+
assigns(i, memory_slice(z, sizeof(mld_poly)),
|
|
545
|
+
memory_slice(tmp, sizeof(mld_poly)),
|
|
546
|
+
memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
490
547
|
invariant(i <= MLDSA_L)
|
|
491
548
|
decreases(MLDSA_L - i)
|
|
492
549
|
)
|
|
493
550
|
{
|
|
494
|
-
|
|
551
|
+
mld_sk_s1hat_get_poly(z, s1hat, i);
|
|
552
|
+
mld_poly_pointwise_montgomery(z, cp);
|
|
495
553
|
mld_poly_invntt_tomont(z);
|
|
496
|
-
|
|
554
|
+
mld_yvec_get_poly(tmp, y, i);
|
|
555
|
+
mld_poly_add(z, tmp);
|
|
497
556
|
mld_poly_reduce(z);
|
|
498
557
|
|
|
499
558
|
z_invalid = mld_poly_chknorm(z, MLDSA_GAMMA1 - MLDSA_BETA);
|
|
@@ -521,118 +580,133 @@ __contract__(
|
|
|
521
580
|
return 0;
|
|
522
581
|
}
|
|
523
582
|
|
|
524
|
-
/*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
* Note that FIPS204 explicitly allows an upper-bound this loop of
|
|
531
|
-
* 814 (< (UINT16_MAX - L)/L) - see @[FIPS204, Appendix C]. */
|
|
532
|
-
#define MLD_NONCE_UB ((UINT16_MAX - MLDSA_L) / MLDSA_L)
|
|
583
|
+
/* User-facing bound on signing attempts. See MLD_CONFIG_MAX_SIGNING_ATTEMPTS
|
|
584
|
+
* in mldsa_native_config.h. Default is chosen so that failure probability
|
|
585
|
+
* is < 2^{-256}, that is, signatures will practically always succeed. */
|
|
586
|
+
#ifndef MLD_CONFIG_MAX_SIGNING_ATTEMPTS
|
|
587
|
+
#define MLD_CONFIG_MAX_SIGNING_ATTEMPTS MLD_NONCE_UB
|
|
588
|
+
#endif
|
|
533
589
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
590
|
+
#if !defined(MLD_ALLOW_NONCOMPLIANT_SIGNING_BOUND) && \
|
|
591
|
+
MLD_CONFIG_MAX_SIGNING_ATTEMPTS < 814
|
|
592
|
+
#error Bad configuration: MLD_CONFIG_MAX_SIGNING_ATTEMPTS must be >= 814 for FIPS 204 compliance @[FIPS204, Appendix C]
|
|
593
|
+
#endif
|
|
594
|
+
|
|
595
|
+
#if MLD_CONFIG_MAX_SIGNING_ATTEMPTS < 1
|
|
596
|
+
#error Bad configuration: MLD_CONFIG_MAX_SIGNING_ATTEMPTS must be >= 1
|
|
597
|
+
#endif
|
|
598
|
+
|
|
599
|
+
#if MLD_CONFIG_MAX_SIGNING_ATTEMPTS > MLD_NONCE_UB
|
|
600
|
+
#error Bad configuration: MLD_CONFIG_MAX_SIGNING_ATTEMPTS exceeds the maximum allowed value.
|
|
601
|
+
#endif
|
|
602
|
+
|
|
603
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
604
|
+
static MLD_INLINE uint16_t mld_get_max_signing_attempts(void)
|
|
605
|
+
__contract__(
|
|
606
|
+
ensures(return_value >= 1)
|
|
607
|
+
ensures(return_value <= MLD_NONCE_UB)
|
|
608
|
+
)
|
|
609
|
+
{
|
|
610
|
+
/* cassert(0) ensures CBMC uses the contract rather than inlining the body,
|
|
611
|
+
* keeping proofs agnostic of the configured value. */
|
|
612
|
+
cassert(0);
|
|
613
|
+
return MLD_CONFIG_MAX_SIGNING_ATTEMPTS;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Attempt to generate a single signature.
|
|
538
618
|
*
|
|
539
|
-
*
|
|
540
|
-
*
|
|
541
|
-
*
|
|
542
|
-
* - const uint8_t *rhoprime: pointer to randomness seed
|
|
543
|
-
* - uint16_t nonce: current nonce value
|
|
544
|
-
* - const mld_polymat *mat: expanded matrix
|
|
545
|
-
* - const polyvecl *s1: secret vector s1
|
|
546
|
-
* - const polyveck *s2: secret vector s2
|
|
547
|
-
* - const polyveck *t0: vector t0
|
|
619
|
+
* @reference{This code differs from the reference implementation in that it
|
|
620
|
+
* factors out the core signature generation step into a distinct function
|
|
621
|
+
* here in order to improve efficiency of CBMC proof.}
|
|
548
622
|
*
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
552
|
-
*
|
|
623
|
+
* @param[out] sig Pointer to output signature.
|
|
624
|
+
* @param[in] mu Pointer to message or hash of exactly MLDSA_CRHBYTES
|
|
625
|
+
* bytes.
|
|
626
|
+
* @param[in] rhoprime Pointer to randomness seed.
|
|
627
|
+
* @param nonce Current nonce value.
|
|
628
|
+
* @param[in] mat Expanded matrix.
|
|
629
|
+
* @param[in] s1hat Secret vector s1 in NTT domain.
|
|
630
|
+
* @param[in] s2hat Secret vector s2 in NTT domain.
|
|
631
|
+
* @param[in] t0hat Vector t0 in NTT domain.
|
|
632
|
+
* @param context Application context. Only present when
|
|
633
|
+
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
|
|
634
|
+
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
|
|
553
635
|
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
|
|
636
|
+
* @return - 0: Signature generation succeeded.
|
|
637
|
+
* - MLD_ERR_FAIL: Signature rejected (norm check failed).
|
|
638
|
+
* - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is used and
|
|
639
|
+
* an allocation via MLD_CUSTOM_ALLOC returned NULL.
|
|
640
|
+
*/
|
|
559
641
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
560
642
|
static int mld_attempt_signature_generation(
|
|
561
643
|
uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *mu,
|
|
562
644
|
const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t nonce, mld_polymat *mat,
|
|
563
|
-
const
|
|
564
|
-
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
645
|
+
const mld_sk_s1hat *s1hat, const mld_sk_s2hat *s2hat,
|
|
646
|
+
const mld_sk_t0hat *t0hat, MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
565
647
|
__contract__(
|
|
566
648
|
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
|
|
567
649
|
requires(memory_no_alias(mu, MLDSA_CRHBYTES))
|
|
568
650
|
requires(memory_no_alias(rhoprime, MLDSA_CRHBYTES))
|
|
569
651
|
requires(memory_no_alias(mat, sizeof(mld_polymat)))
|
|
570
|
-
requires(memory_no_alias(
|
|
571
|
-
requires(memory_no_alias(
|
|
572
|
-
requires(memory_no_alias(
|
|
652
|
+
requires(memory_no_alias(s1hat, sizeof(mld_sk_s1hat)))
|
|
653
|
+
requires(memory_no_alias(s2hat, sizeof(mld_sk_s2hat)))
|
|
654
|
+
requires(memory_no_alias(t0hat, sizeof(mld_sk_t0hat)))
|
|
573
655
|
requires(nonce <= MLD_NONCE_UB)
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
656
|
+
MLD_IF_NOT_REDUCE_RAM(
|
|
657
|
+
requires(forall(k1, 0, MLDSA_K, forall(l1, 0, MLDSA_L,
|
|
658
|
+
array_bound(mat->vec[k1].vec[l1].coeffs, 0, MLDSA_N, 0, MLDSA_Q))))
|
|
659
|
+
requires(forall(k2, 0, MLDSA_K, array_abs_bound(t0hat->vec.vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
660
|
+
requires(forall(k3, 0, MLDSA_L, array_abs_bound(s1hat->vec.vec[k3].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
661
|
+
requires(forall(k4, 0, MLDSA_K, array_abs_bound(s2hat->vec.vec[k4].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
662
|
+
)
|
|
663
|
+
MLD_IF_REDUCE_RAM(
|
|
664
|
+
requires(memory_no_alias(s1hat->packed, MLDSA_L * MLDSA_POLYETA_PACKEDBYTES))
|
|
665
|
+
requires(memory_no_alias(s2hat->packed, MLDSA_K * MLDSA_POLYETA_PACKEDBYTES))
|
|
666
|
+
requires(memory_no_alias(t0hat->packed, MLDSA_K * MLDSA_POLYT0_PACKEDBYTES))
|
|
667
|
+
)
|
|
579
668
|
assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
669
|
+
MLD_IF_REDUCE_RAM(
|
|
670
|
+
assigns(memory_slice(mat, sizeof(mld_polymat)))
|
|
671
|
+
)
|
|
580
672
|
ensures(return_value == 0 || return_value == MLD_ERR_FAIL ||
|
|
581
673
|
return_value == MLD_ERR_OUT_OF_MEMORY)
|
|
582
674
|
)
|
|
583
675
|
{
|
|
584
|
-
unsigned int
|
|
676
|
+
unsigned int k;
|
|
585
677
|
uint32_t w0_invalid, h_invalid;
|
|
586
678
|
int ret;
|
|
587
|
-
/* TODO: Remove the following workaround for
|
|
588
|
-
* https://github.com/diffblue/cbmc/issues/8813 */
|
|
589
|
-
typedef MLD_UNION_OR_STRUCT
|
|
590
|
-
{
|
|
591
|
-
mld_polyvecl y;
|
|
592
|
-
mld_polyveck h;
|
|
593
|
-
}
|
|
594
|
-
yh_u;
|
|
595
|
-
mld_polyvecl *y;
|
|
596
|
-
mld_polyveck *h;
|
|
597
679
|
|
|
598
|
-
|
|
599
|
-
* https://github.com/diffblue/cbmc/issues/8813 */
|
|
600
|
-
typedef MLD_UNION_OR_STRUCT
|
|
680
|
+
typedef union
|
|
601
681
|
{
|
|
602
682
|
mld_polyveck w1;
|
|
603
683
|
mld_polyvecl tmp;
|
|
604
|
-
}
|
|
605
|
-
w1tmp_u;
|
|
684
|
+
} w1tmp_u;
|
|
606
685
|
mld_polyveck *w1;
|
|
607
686
|
mld_polyvecl *tmp;
|
|
608
687
|
|
|
609
688
|
MLD_ALLOC(challenge_bytes, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
610
|
-
MLD_ALLOC(
|
|
689
|
+
MLD_ALLOC(y, mld_yvec, 1, context);
|
|
611
690
|
MLD_ALLOC(z, mld_poly, 1, context);
|
|
612
691
|
MLD_ALLOC(w1tmp, w1tmp_u, 1, context);
|
|
613
692
|
MLD_ALLOC(w0, mld_polyveck, 1, context);
|
|
614
693
|
MLD_ALLOC(cp, mld_poly, 1, context);
|
|
615
694
|
MLD_ALLOC(t, mld_poly, 1, context);
|
|
616
695
|
|
|
617
|
-
if (challenge_bytes == NULL ||
|
|
696
|
+
if (challenge_bytes == NULL || y == NULL || z == NULL || w1tmp == NULL ||
|
|
618
697
|
w0 == NULL || cp == NULL || t == NULL)
|
|
619
698
|
{
|
|
620
699
|
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
621
700
|
goto cleanup;
|
|
622
701
|
}
|
|
623
|
-
y = &yh->y;
|
|
624
|
-
h = &yh->h;
|
|
625
702
|
w1 = &w1tmp->w1;
|
|
626
703
|
tmp = &w1tmp->tmp;
|
|
627
704
|
|
|
628
|
-
/* Sample intermediate vector y */
|
|
629
|
-
|
|
705
|
+
/* Sample/initialize intermediate vector y */
|
|
706
|
+
mld_yvec_init(y, rhoprime, nonce);
|
|
630
707
|
|
|
631
|
-
/* Matrix-vector multiplication */
|
|
632
|
-
|
|
633
|
-
mld_polyvecl_ntt(tmp);
|
|
634
|
-
mld_polyvec_matrix_pointwise_montgomery(w0, mat, tmp);
|
|
635
|
-
mld_polyveck_invntt_tomont(w0);
|
|
708
|
+
/* Matrix-vector multiplication, fused with y sampling in REDUCE_RAM mode */
|
|
709
|
+
mld_polyvec_matrix_pointwise_montgomery_yvec(w0, mat, y, tmp);
|
|
636
710
|
|
|
637
711
|
/* Decompose w and call the random oracle */
|
|
638
712
|
mld_polyveck_caddq(w0);
|
|
@@ -650,63 +724,84 @@ __contract__(
|
|
|
650
724
|
mld_poly_ntt(cp);
|
|
651
725
|
|
|
652
726
|
/* Compute z, reject if it reveals secret */
|
|
653
|
-
ret = mld_compute_pack_z(sig, cp,
|
|
654
|
-
if (ret)
|
|
727
|
+
ret = mld_compute_pack_z(sig, cp, s1hat, y, t, z);
|
|
728
|
+
if (ret != 0)
|
|
655
729
|
{
|
|
656
730
|
goto cleanup;
|
|
657
731
|
}
|
|
658
732
|
|
|
659
|
-
/*
|
|
660
|
-
*
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
733
|
+
/* Compute w0 - cs2 + ct0 per-component, checking norms incrementally.
|
|
734
|
+
* This avoids allocating a full polyveck for h. */
|
|
735
|
+
for (k = 0; k < MLDSA_K; k++)
|
|
736
|
+
__loop__(
|
|
737
|
+
assigns(k,
|
|
738
|
+
object_whole(z),
|
|
739
|
+
object_whole(w0))
|
|
740
|
+
invariant(k <= MLDSA_K)
|
|
741
|
+
invariant(forall(k0, k, MLDSA_K,
|
|
742
|
+
array_abs_bound(w0->vec[k0].coeffs, 0, MLDSA_N, MLDSA_GAMMA2 + 1)))
|
|
743
|
+
decreases(MLDSA_K - k)
|
|
744
|
+
)
|
|
670
745
|
{
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
746
|
+
/* Compute cs2[k] and subtract from w0[k] */
|
|
747
|
+
mld_sk_s2hat_get_poly(z, s2hat, k);
|
|
748
|
+
mld_poly_pointwise_montgomery(z, cp);
|
|
749
|
+
mld_poly_invntt_tomont(z);
|
|
674
750
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
mld_polyveck_invntt_tomont(h);
|
|
678
|
-
mld_polyveck_reduce(h);
|
|
751
|
+
mld_poly_sub(&w0->vec[k], z);
|
|
752
|
+
mld_poly_reduce(&w0->vec[k]);
|
|
679
753
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
754
|
+
/* Check that subtracting cs2 does not change high bits of w and low bits
|
|
755
|
+
* do not reveal secret information */
|
|
756
|
+
w0_invalid = mld_poly_chknorm(&w0->vec[k], MLDSA_GAMMA2 - MLDSA_BETA);
|
|
757
|
+
/* Constant time: w0_invalid may be leaked - see comment for z_invalid. */
|
|
758
|
+
MLD_CT_TESTING_DECLASSIFY(&w0_invalid, sizeof(uint32_t));
|
|
759
|
+
if (w0_invalid)
|
|
760
|
+
{
|
|
761
|
+
ret = MLD_ERR_FAIL; /* reject */
|
|
762
|
+
goto cleanup;
|
|
763
|
+
}
|
|
688
764
|
|
|
689
|
-
|
|
765
|
+
/* Compute ct0[k], check norm, and add to w0[k] */
|
|
766
|
+
mld_sk_t0hat_get_poly(z, t0hat, k);
|
|
767
|
+
mld_poly_pointwise_montgomery(z, cp);
|
|
768
|
+
mld_poly_invntt_tomont(z);
|
|
769
|
+
mld_poly_reduce(z);
|
|
770
|
+
|
|
771
|
+
h_invalid = mld_poly_chknorm(z, MLDSA_GAMMA2);
|
|
772
|
+
/* Constant time: h_invalid may be leaked - see comment for z_invalid. */
|
|
773
|
+
MLD_CT_TESTING_DECLASSIFY(&h_invalid, sizeof(uint32_t));
|
|
774
|
+
if (h_invalid)
|
|
775
|
+
{
|
|
776
|
+
ret = MLD_ERR_FAIL; /* reject */
|
|
777
|
+
goto cleanup;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
mld_poly_add(&w0->vec[k], z);
|
|
781
|
+
}
|
|
690
782
|
|
|
691
783
|
/* Constant time: At this point all norm checks have passed and we, hence,
|
|
692
784
|
* know that the signature does not leak any secret information.
|
|
693
785
|
* Consequently, any value that can be computed from the signature and public
|
|
694
786
|
* key is considered public.
|
|
695
787
|
* w0 and w1 are public as they can be computed from Az - ct = \alpha w1 + w0.
|
|
696
|
-
* h=c*t0 is public as both c and t0 are public.
|
|
697
|
-
*
|
|
788
|
+
* h=c*t0 is public as both c and t0 are considered public.
|
|
789
|
+
* While t0 is not part of the public key, it can be reconstructed from
|
|
790
|
+
* a small number of signatures and need not be regarded as secret
|
|
791
|
+
* (see @[FIPS204, Section 6.1]).
|
|
698
792
|
*/
|
|
699
793
|
MLD_CT_TESTING_DECLASSIFY(w0, sizeof(*w0));
|
|
700
794
|
MLD_CT_TESTING_DECLASSIFY(w1, sizeof(*w1));
|
|
701
|
-
|
|
702
|
-
|
|
795
|
+
|
|
796
|
+
/* Pack challenge bytes and hints. */
|
|
797
|
+
mld_pack_sig_c(sig, challenge_bytes);
|
|
798
|
+
|
|
799
|
+
ret = mld_pack_sig_h(sig, w0, w1);
|
|
800
|
+
if (ret != 0)
|
|
703
801
|
{
|
|
704
|
-
ret = MLD_ERR_FAIL; /* reject */
|
|
705
802
|
goto cleanup;
|
|
706
803
|
}
|
|
707
804
|
|
|
708
|
-
/* All is well - write signature */
|
|
709
|
-
mld_pack_sig_c_h(sig, challenge_bytes, h, n);
|
|
710
805
|
/* Constant time: At this point it is clear that the signature is valid - it
|
|
711
806
|
* can, hence, be considered public. */
|
|
712
807
|
MLD_CT_TESTING_DECLASSIFY(sig, MLDSA_CRYPTO_BYTES);
|
|
@@ -719,7 +814,7 @@ cleanup:
|
|
|
719
814
|
MLD_FREE(w0, mld_polyveck, 1, context);
|
|
720
815
|
MLD_FREE(w1tmp, w1tmp_u, 1, context);
|
|
721
816
|
MLD_FREE(z, mld_poly, 1, context);
|
|
722
|
-
MLD_FREE(
|
|
817
|
+
MLD_FREE(y, mld_yvec, 1, context);
|
|
723
818
|
MLD_FREE(challenge_bytes, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
724
819
|
|
|
725
820
|
return ret;
|
|
@@ -737,14 +832,16 @@ int mld_sign_signature_internal(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
|
737
832
|
int ret;
|
|
738
833
|
uint8_t *rho, *tr, *key, *mu, *rhoprime;
|
|
739
834
|
uint16_t nonce = 0;
|
|
835
|
+
const uint16_t nonce_limit = mld_get_max_signing_attempts();
|
|
740
836
|
MLD_ALLOC(seedbuf, uint8_t,
|
|
741
837
|
2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES, context);
|
|
742
838
|
MLD_ALLOC(mat, mld_polymat, 1, context);
|
|
743
|
-
MLD_ALLOC(
|
|
744
|
-
MLD_ALLOC(
|
|
745
|
-
MLD_ALLOC(
|
|
839
|
+
MLD_ALLOC(s1hat, mld_sk_s1hat, 1, context);
|
|
840
|
+
MLD_ALLOC(t0hat, mld_sk_t0hat, 1, context);
|
|
841
|
+
MLD_ALLOC(s2hat, mld_sk_s2hat, 1, context);
|
|
746
842
|
|
|
747
|
-
if (seedbuf == NULL || mat == NULL ||
|
|
843
|
+
if (seedbuf == NULL || mat == NULL || s1hat == NULL || t0hat == NULL ||
|
|
844
|
+
s2hat == NULL)
|
|
748
845
|
{
|
|
749
846
|
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
750
847
|
goto cleanup;
|
|
@@ -755,7 +852,7 @@ int mld_sign_signature_internal(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
|
755
852
|
key = tr + MLDSA_TRBYTES;
|
|
756
853
|
mu = key + MLDSA_SEEDBYTES;
|
|
757
854
|
rhoprime = mu + MLDSA_CRHBYTES;
|
|
758
|
-
mld_unpack_sk(rho, tr, key,
|
|
855
|
+
mld_unpack_sk(rho, tr, key, t0hat, s1hat, s2hat, sk);
|
|
759
856
|
|
|
760
857
|
if (!externalmu)
|
|
761
858
|
{
|
|
@@ -776,47 +873,46 @@ int mld_sign_signature_internal(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
|
776
873
|
MLD_CT_TESTING_DECLASSIFY(rho, MLDSA_SEEDBYTES);
|
|
777
874
|
/* Expand matrix and transform vectors */
|
|
778
875
|
mld_polyvec_matrix_expand(mat, rho);
|
|
779
|
-
mld_polyvecl_ntt(s1);
|
|
780
|
-
mld_polyveck_ntt(s2);
|
|
781
|
-
mld_polyveck_ntt(t0);
|
|
782
|
-
|
|
783
|
-
/* By default, return failure. Flip to success and write output
|
|
784
|
-
* once signature generation succeeds. */
|
|
785
|
-
ret = MLD_ERR_FAIL;
|
|
786
876
|
|
|
787
877
|
/* Reference: This code is re-structured using a while(1), */
|
|
788
878
|
/* with explicit "continue" statements (rather than "goto") */
|
|
789
879
|
/* to implement rejection of invalid signatures. */
|
|
790
880
|
while (1)
|
|
791
881
|
__loop__(
|
|
792
|
-
|
|
793
|
-
|
|
882
|
+
MLD_IF_NOT_REDUCE_RAM(
|
|
883
|
+
assigns(nonce, ret, object_whole(siglen), memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
884
|
+
)
|
|
885
|
+
MLD_IF_REDUCE_RAM(
|
|
886
|
+
assigns(nonce, ret, object_whole(siglen), memory_slice(sig, MLDSA_CRYPTO_BYTES),
|
|
887
|
+
memory_slice(mat, sizeof(mld_polymat)))
|
|
888
|
+
)
|
|
889
|
+
invariant(nonce <= nonce_limit)
|
|
794
890
|
|
|
795
891
|
/* t0, s1, s2, and mat are initialized above and are NOT changed by this */
|
|
796
892
|
/* loop. We can therefore re-assert their bounds here as part of the */
|
|
797
893
|
/* loop invariant. This makes proof noticeably faster with CBMC */
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
894
|
+
MLD_IF_NOT_REDUCE_RAM(
|
|
895
|
+
invariant(forall(k1, 0, MLDSA_K, forall(l1, 0, MLDSA_L,
|
|
896
|
+
array_bound(mat->vec[k1].vec[l1].coeffs, 0, MLDSA_N, 0, MLDSA_Q))))
|
|
897
|
+
invariant(forall(k2, 0, MLDSA_K, array_abs_bound(t0hat->vec.vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
898
|
+
invariant(forall(k3, 0, MLDSA_L, array_abs_bound(s1hat->vec.vec[k3].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
899
|
+
invariant(forall(k4, 0, MLDSA_K, array_abs_bound(s2hat->vec.vec[k4].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
900
|
+
)
|
|
901
|
+
decreases(nonce_limit - nonce)
|
|
805
902
|
)
|
|
806
903
|
{
|
|
807
|
-
/* Reference: this code explicitly checks for exhaustion of
|
|
808
|
-
/*
|
|
809
|
-
/* Checking here also means that incrementing nonce below can
|
|
810
|
-
/* be proven to be type-safe.
|
|
811
|
-
if (nonce ==
|
|
904
|
+
/* Reference: this code explicitly checks for exhaustion of signing */
|
|
905
|
+
/* attempts to provide predictable termination and results in that */
|
|
906
|
+
/* case. Checking here also means that incrementing nonce below can */
|
|
907
|
+
/* be proven to be type-safe. */
|
|
908
|
+
if (nonce == nonce_limit)
|
|
812
909
|
{
|
|
813
|
-
|
|
814
|
-
* don't need to set it here. */
|
|
910
|
+
ret = MLD_ERR_SIGN_ATTEMPTS_EXHAUSTED;
|
|
815
911
|
break;
|
|
816
912
|
}
|
|
817
913
|
|
|
818
|
-
ret = mld_attempt_signature_generation(sig, mu, rhoprime, nonce, mat,
|
|
819
|
-
|
|
914
|
+
ret = mld_attempt_signature_generation(sig, mu, rhoprime, nonce, mat, s1hat,
|
|
915
|
+
s2hat, t0hat, context);
|
|
820
916
|
nonce++;
|
|
821
917
|
if (ret == 0)
|
|
822
918
|
{
|
|
@@ -842,15 +938,16 @@ cleanup:
|
|
|
842
938
|
}
|
|
843
939
|
|
|
844
940
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
845
|
-
MLD_FREE(
|
|
846
|
-
MLD_FREE(
|
|
847
|
-
MLD_FREE(
|
|
941
|
+
MLD_FREE(s2hat, mld_sk_s2hat, 1, context);
|
|
942
|
+
MLD_FREE(t0hat, mld_sk_t0hat, 1, context);
|
|
943
|
+
MLD_FREE(s1hat, mld_sk_s1hat, 1, context);
|
|
848
944
|
MLD_FREE(mat, mld_polymat, 1, context);
|
|
849
945
|
MLD_FREE(seedbuf, uint8_t,
|
|
850
946
|
2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES, context);
|
|
851
947
|
return ret;
|
|
852
948
|
}
|
|
853
949
|
|
|
950
|
+
#if !defined(MLD_CONFIG_CORE_API_ONLY)
|
|
854
951
|
#if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
|
|
855
952
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
856
953
|
MLD_EXTERNAL_API
|
|
@@ -887,7 +984,7 @@ int mld_sign_signature(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
|
887
984
|
ret = MLD_ERR_RNG_FAIL;
|
|
888
985
|
goto cleanup;
|
|
889
986
|
}
|
|
890
|
-
MLD_CT_TESTING_SECRET(rnd,
|
|
987
|
+
MLD_CT_TESTING_SECRET(rnd, MLDSA_RNDBYTES);
|
|
891
988
|
|
|
892
989
|
ret = mld_sign_signature_internal(sig, siglen, m, mlen, pre, pre_len, rnd, sk,
|
|
893
990
|
0, context);
|
|
@@ -921,8 +1018,15 @@ int mld_sign_signature_extmu(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
|
921
1018
|
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
922
1019
|
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
923
1020
|
{
|
|
924
|
-
MLD_ALIGN uint8_t rnd[MLDSA_RNDBYTES];
|
|
925
1021
|
int ret;
|
|
1022
|
+
MLD_ALLOC(rnd, uint8_t, MLDSA_RNDBYTES, context);
|
|
1023
|
+
|
|
1024
|
+
if (rnd == NULL)
|
|
1025
|
+
{
|
|
1026
|
+
*siglen = 0;
|
|
1027
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
1028
|
+
goto cleanup;
|
|
1029
|
+
}
|
|
926
1030
|
|
|
927
1031
|
/* Randomized variant of ML-DSA. If you need the deterministic variant,
|
|
928
1032
|
* call mld_sign_signature_internal directly with all-zero rnd. */
|
|
@@ -932,14 +1036,14 @@ int mld_sign_signature_extmu(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
|
932
1036
|
ret = MLD_ERR_RNG_FAIL;
|
|
933
1037
|
goto cleanup;
|
|
934
1038
|
}
|
|
935
|
-
MLD_CT_TESTING_SECRET(rnd,
|
|
1039
|
+
MLD_CT_TESTING_SECRET(rnd, MLDSA_RNDBYTES);
|
|
936
1040
|
|
|
937
1041
|
ret = mld_sign_signature_internal(sig, siglen, mu, MLDSA_CRHBYTES, NULL, 0,
|
|
938
1042
|
rnd, sk, 1, context);
|
|
939
1043
|
|
|
940
1044
|
cleanup:
|
|
941
1045
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
942
|
-
|
|
1046
|
+
MLD_FREE(rnd, uint8_t, MLDSA_RNDBYTES, context);
|
|
943
1047
|
|
|
944
1048
|
return ret;
|
|
945
1049
|
}
|
|
@@ -967,11 +1071,17 @@ int mld_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen,
|
|
|
967
1071
|
}
|
|
968
1072
|
ret = mld_sign_signature(sm, smlen, sm + MLDSA_CRYPTO_BYTES, mlen, ctx,
|
|
969
1073
|
ctxlen, sk, context);
|
|
970
|
-
|
|
1074
|
+
if (ret == 0)
|
|
1075
|
+
{
|
|
1076
|
+
*smlen += mlen;
|
|
1077
|
+
}
|
|
971
1078
|
return ret;
|
|
972
1079
|
}
|
|
973
1080
|
#endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
|
|
1081
|
+
#endif /* !MLD_CONFIG_CORE_API_ONLY */
|
|
1082
|
+
#endif /* !MLD_CONFIG_NO_SIGN_API */
|
|
974
1083
|
|
|
1084
|
+
#if !defined(MLD_CONFIG_NO_VERIFY_API)
|
|
975
1085
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
976
1086
|
MLD_EXTERNAL_API
|
|
977
1087
|
int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
|
|
@@ -982,39 +1092,24 @@ int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
|
|
|
982
1092
|
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
983
1093
|
{
|
|
984
1094
|
int ret, cmp;
|
|
985
|
-
|
|
986
|
-
/* TODO: Remove the following workaround for
|
|
987
|
-
* https://github.com/diffblue/cbmc/issues/8813 */
|
|
988
|
-
typedef MLD_UNION_OR_STRUCT
|
|
989
|
-
{
|
|
990
|
-
mld_polyveck t1;
|
|
991
|
-
mld_polyveck w1;
|
|
992
|
-
}
|
|
993
|
-
t1w1_u;
|
|
994
|
-
mld_polyveck *t1;
|
|
995
|
-
mld_polyveck *w1;
|
|
1095
|
+
unsigned int i;
|
|
996
1096
|
|
|
997
1097
|
MLD_ALLOC(buf, uint8_t, (MLDSA_K * MLDSA_POLYW1_PACKEDBYTES), context);
|
|
998
|
-
MLD_ALLOC(rho, uint8_t, MLDSA_SEEDBYTES, context);
|
|
999
1098
|
MLD_ALLOC(mu, uint8_t, MLDSA_CRHBYTES, context);
|
|
1000
1099
|
MLD_ALLOC(c, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1001
1100
|
MLD_ALLOC(c2, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1101
|
+
MLD_ALLOC(z, mld_polyvecl, 1, context);
|
|
1002
1102
|
MLD_ALLOC(cp, mld_poly, 1, context);
|
|
1003
1103
|
MLD_ALLOC(mat, mld_polymat, 1, context);
|
|
1004
|
-
MLD_ALLOC(
|
|
1005
|
-
MLD_ALLOC(
|
|
1006
|
-
MLD_ALLOC(tmp, mld_polyveck, 1, context);
|
|
1007
|
-
MLD_ALLOC(h, mld_polyveck, 1, context);
|
|
1104
|
+
MLD_ALLOC(w1, mld_poly, 1, context);
|
|
1105
|
+
MLD_ALLOC(tmp, mld_poly, 1, context);
|
|
1008
1106
|
|
|
1009
|
-
if (buf == NULL ||
|
|
1010
|
-
cp == NULL || mat == NULL ||
|
|
1011
|
-
h == NULL)
|
|
1107
|
+
if (buf == NULL || mu == NULL || c == NULL || c2 == NULL || z == NULL ||
|
|
1108
|
+
cp == NULL || mat == NULL || w1 == NULL || tmp == NULL)
|
|
1012
1109
|
{
|
|
1013
1110
|
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
1014
1111
|
goto cleanup;
|
|
1015
1112
|
}
|
|
1016
|
-
t1 = &t1w1->t1;
|
|
1017
|
-
w1 = &t1w1->w1;
|
|
1018
1113
|
|
|
1019
1114
|
if (siglen != MLDSA_CRYPTO_BYTES)
|
|
1020
1115
|
{
|
|
@@ -1022,16 +1117,11 @@ int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
|
|
|
1022
1117
|
goto cleanup;
|
|
1023
1118
|
}
|
|
1024
1119
|
|
|
1025
|
-
|
|
1120
|
+
mld_memcpy(c, sig, MLDSA_CTILDEBYTES);
|
|
1121
|
+
mld_polyvecl_unpack_z(z, sig + MLDSA_CTILDEBYTES);
|
|
1026
1122
|
|
|
1027
|
-
/*
|
|
1028
|
-
*
|
|
1029
|
-
* Map it to MLD_ERR_FAIL explicitly. */
|
|
1030
|
-
if (mld_unpack_sig(c, z, h, sig))
|
|
1031
|
-
{
|
|
1032
|
-
ret = MLD_ERR_FAIL;
|
|
1033
|
-
goto cleanup;
|
|
1034
|
-
}
|
|
1123
|
+
/* mld_polyvecl_chknorm signals failure through a single non-zero error code
|
|
1124
|
+
* that's not yet aligned with MLD_ERR_XXX. Map it to MLD_ERR_FAIL. */
|
|
1035
1125
|
if (mld_polyvecl_chknorm(z, MLDSA_GAMMA1 - MLDSA_BETA))
|
|
1036
1126
|
{
|
|
1037
1127
|
ret = MLD_ERR_FAIL;
|
|
@@ -1055,24 +1145,51 @@ int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
|
|
|
1055
1145
|
mld_memcpy(mu, m, MLDSA_CRHBYTES);
|
|
1056
1146
|
}
|
|
1057
1147
|
|
|
1058
|
-
/* Matrix-vector multiplication
|
|
1148
|
+
/* Matrix-vector multiplication and per-row reconstruction of w1. */
|
|
1149
|
+
mld_polyvecl_ntt(z);
|
|
1150
|
+
mld_polyvec_matrix_expand(mat, pk);
|
|
1059
1151
|
mld_poly_challenge(cp, c);
|
|
1060
1152
|
mld_poly_ntt(cp);
|
|
1061
|
-
mld_polyveck_shiftl(t1);
|
|
1062
|
-
mld_polyveck_ntt(t1);
|
|
1063
|
-
mld_polyveck_pointwise_poly_montgomery(tmp, cp, t1);
|
|
1064
1153
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1154
|
+
for (i = 0; i < MLDSA_K; ++i)
|
|
1155
|
+
__loop__(
|
|
1156
|
+
assigns(MLD_IF_REDUCE_RAM(memory_slice(mat, sizeof(mld_polymat)),)
|
|
1157
|
+
i, ret,
|
|
1158
|
+
memory_slice(w1, sizeof(mld_poly)),
|
|
1159
|
+
memory_slice(tmp, sizeof(mld_poly)),
|
|
1160
|
+
memory_slice(buf, MLDSA_K * MLDSA_POLYW1_PACKEDBYTES)
|
|
1161
|
+
)
|
|
1162
|
+
invariant(i <= MLDSA_K)
|
|
1163
|
+
decreases(MLDSA_K - i)
|
|
1164
|
+
)
|
|
1165
|
+
{
|
|
1166
|
+
/* w1 = (A * z)_i in NTT domain */
|
|
1167
|
+
mld_polyvec_matrix_pointwise_montgomery_row(w1, mat, z, i);
|
|
1168
|
+
|
|
1169
|
+
/* tmp = c * t1_i * 2^d in NTT domain */
|
|
1170
|
+
mld_unpack_pk_t1(tmp, pk, i);
|
|
1171
|
+
mld_poly_shiftl(tmp);
|
|
1172
|
+
mld_poly_ntt(tmp);
|
|
1173
|
+
mld_poly_pointwise_montgomery(tmp, cp);
|
|
1174
|
+
|
|
1175
|
+
/* w1 = invNTT(w1 - c * t1_i * 2^d) */
|
|
1176
|
+
mld_poly_sub(w1, tmp);
|
|
1177
|
+
mld_poly_reduce(w1);
|
|
1178
|
+
mld_poly_invntt_tomont(w1);
|
|
1179
|
+
mld_poly_caddq(w1);
|
|
1180
|
+
|
|
1181
|
+
/* tmp = h_i (decoded and validated from signature) */
|
|
1182
|
+
ret = mld_sig_unpack_hints(tmp, sig, i);
|
|
1183
|
+
if (ret != 0)
|
|
1184
|
+
{
|
|
1185
|
+
goto cleanup;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/* w1 = use_hint(w1, tmp), then pack into buf[i] */
|
|
1189
|
+
mld_poly_use_hint(w1, tmp);
|
|
1190
|
+
mld_polyw1_pack(buf + i * MLDSA_POLYW1_PACKEDBYTES, w1);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1076
1193
|
/* Call random oracle and verify challenge */
|
|
1077
1194
|
mld_H(c2, MLDSA_CTILDEBYTES, mu, MLDSA_CRHBYTES, buf,
|
|
1078
1195
|
MLDSA_K * MLDSA_POLYW1_PACKEDBYTES, NULL, 0);
|
|
@@ -1086,20 +1203,19 @@ int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
|
|
|
1086
1203
|
|
|
1087
1204
|
cleanup:
|
|
1088
1205
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1089
|
-
MLD_FREE(
|
|
1090
|
-
MLD_FREE(
|
|
1091
|
-
MLD_FREE(t1w1, t1w1_u, 1, context);
|
|
1092
|
-
MLD_FREE(z, mld_polyvecl, 1, context);
|
|
1206
|
+
MLD_FREE(tmp, mld_poly, 1, context);
|
|
1207
|
+
MLD_FREE(w1, mld_poly, 1, context);
|
|
1093
1208
|
MLD_FREE(mat, mld_polymat, 1, context);
|
|
1094
1209
|
MLD_FREE(cp, mld_poly, 1, context);
|
|
1210
|
+
MLD_FREE(z, mld_polyvecl, 1, context);
|
|
1095
1211
|
MLD_FREE(c2, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1096
1212
|
MLD_FREE(c, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1097
1213
|
MLD_FREE(mu, uint8_t, MLDSA_CRHBYTES, context);
|
|
1098
|
-
MLD_FREE(rho, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1099
1214
|
MLD_FREE(buf, uint8_t, (MLDSA_K * MLDSA_POLYW1_PACKEDBYTES), context);
|
|
1100
1215
|
return ret;
|
|
1101
1216
|
}
|
|
1102
1217
|
|
|
1218
|
+
#if !defined(MLD_CONFIG_CORE_API_ONLY)
|
|
1103
1219
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
1104
1220
|
MLD_EXTERNAL_API
|
|
1105
1221
|
int mld_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m,
|
|
@@ -1184,8 +1300,11 @@ cleanup:
|
|
|
1184
1300
|
|
|
1185
1301
|
return ret;
|
|
1186
1302
|
}
|
|
1303
|
+
#endif /* !MLD_CONFIG_CORE_API_ONLY */
|
|
1304
|
+
#endif /* !MLD_CONFIG_NO_VERIFY_API */
|
|
1187
1305
|
|
|
1188
|
-
|
|
1306
|
+
#if !defined(MLD_CONFIG_CORE_API_ONLY)
|
|
1307
|
+
#if !defined(MLD_CONFIG_NO_SIGN_API)
|
|
1189
1308
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
1190
1309
|
MLD_EXTERNAL_API
|
|
1191
1310
|
int mld_sign_signature_pre_hash_internal(
|
|
@@ -1226,7 +1345,9 @@ cleanup:
|
|
|
1226
1345
|
mld_zeroize(pre, sizeof(pre));
|
|
1227
1346
|
return ret;
|
|
1228
1347
|
}
|
|
1348
|
+
#endif /* !MLD_CONFIG_NO_SIGN_API */
|
|
1229
1349
|
|
|
1350
|
+
#if !defined(MLD_CONFIG_NO_VERIFY_API)
|
|
1230
1351
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
1231
1352
|
MLD_EXTERNAL_API
|
|
1232
1353
|
int mld_sign_verify_pre_hash_internal(
|
|
@@ -1255,7 +1376,9 @@ cleanup:
|
|
|
1255
1376
|
mld_zeroize(pre, sizeof(pre));
|
|
1256
1377
|
return ret;
|
|
1257
1378
|
}
|
|
1379
|
+
#endif /* !MLD_CONFIG_NO_VERIFY_API */
|
|
1258
1380
|
|
|
1381
|
+
#if !defined(MLD_CONFIG_NO_SIGN_API)
|
|
1259
1382
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
1260
1383
|
MLD_EXTERNAL_API
|
|
1261
1384
|
int mld_sign_signature_pre_hash_shake256(
|
|
@@ -1275,7 +1398,9 @@ int mld_sign_signature_pre_hash_shake256(
|
|
|
1275
1398
|
mld_zeroize(ph, sizeof(ph));
|
|
1276
1399
|
return ret;
|
|
1277
1400
|
}
|
|
1401
|
+
#endif /* !MLD_CONFIG_NO_SIGN_API */
|
|
1278
1402
|
|
|
1403
|
+
#if !defined(MLD_CONFIG_NO_VERIFY_API)
|
|
1279
1404
|
MLD_MUST_CHECK_RETURN_VALUE
|
|
1280
1405
|
MLD_EXTERNAL_API
|
|
1281
1406
|
int mld_sign_verify_pre_hash_shake256(
|
|
@@ -1294,19 +1419,17 @@ int mld_sign_verify_pre_hash_shake256(
|
|
|
1294
1419
|
mld_zeroize(ph, sizeof(ph));
|
|
1295
1420
|
return ret;
|
|
1296
1421
|
}
|
|
1422
|
+
#endif /* !MLD_CONFIG_NO_VERIFY_API */
|
|
1297
1423
|
|
|
1298
|
-
|
|
1424
|
+
#if !defined(MLD_CONFIG_NO_SIGN_API) || !defined(MLD_CONFIG_NO_VERIFY_API)
|
|
1299
1425
|
#define MLD_PRE_HASH_OID_LEN 11
|
|
1300
1426
|
|
|
1301
|
-
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1304
|
-
* Description: Returns the OID of a given SHA-2/SHA-3 hash function.
|
|
1427
|
+
/**
|
|
1428
|
+
* Return the OID of a given SHA-2/SHA-3 hash function.
|
|
1305
1429
|
*
|
|
1306
|
-
*
|
|
1307
|
-
*
|
|
1308
|
-
|
|
1309
|
-
***************************************************/
|
|
1430
|
+
* @param[out] oid Pointer to output OID.
|
|
1431
|
+
* @param hashalg Hash algorithm constant (MLD_PREHASH_*).
|
|
1432
|
+
*/
|
|
1310
1433
|
static void mld_get_hash_oid(uint8_t oid[MLD_PRE_HASH_OID_LEN], int hashalg)
|
|
1311
1434
|
{
|
|
1312
1435
|
unsigned int i;
|
|
@@ -1421,7 +1544,9 @@ size_t mld_prepare_domain_separation_prefix(
|
|
|
1421
1544
|
mld_memcpy(prefix + 2 + ctxlen + MLD_PRE_HASH_OID_LEN, ph, phlen);
|
|
1422
1545
|
return 2 + ctxlen + MLD_PRE_HASH_OID_LEN + phlen;
|
|
1423
1546
|
}
|
|
1547
|
+
#endif /* !MLD_CONFIG_NO_SIGN_API || !MLD_CONFIG_NO_VERIFY_API */
|
|
1424
1548
|
|
|
1549
|
+
#if !defined(MLD_CONFIG_NO_KEYPAIR_API)
|
|
1425
1550
|
MLD_EXTERNAL_API
|
|
1426
1551
|
int mld_sign_pk_from_sk(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
1427
1552
|
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
@@ -1435,36 +1560,53 @@ int mld_sign_pk_from_sk(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
|
1435
1560
|
MLD_ALLOC(key, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1436
1561
|
MLD_ALLOC(s1, mld_polyvecl, 1, context);
|
|
1437
1562
|
MLD_ALLOC(s2, mld_polyveck, 1, context);
|
|
1438
|
-
MLD_ALLOC(
|
|
1439
|
-
MLD_ALLOC(t0_computed, mld_polyveck, 1, context);
|
|
1440
|
-
MLD_ALLOC(t1, mld_polyveck, 1, context);
|
|
1563
|
+
MLD_ALLOC(t0_packed, uint8_t, MLDSA_K *MLDSA_POLYT0_PACKEDBYTES, context);
|
|
1441
1564
|
|
|
1442
1565
|
if (rho == NULL || tr == NULL || tr_computed == NULL || key == NULL ||
|
|
1443
|
-
s1 == NULL || s2 == NULL ||
|
|
1444
|
-
t1 == NULL)
|
|
1566
|
+
s1 == NULL || s2 == NULL || t0_packed == NULL)
|
|
1445
1567
|
{
|
|
1446
1568
|
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
1447
1569
|
goto cleanup;
|
|
1448
1570
|
}
|
|
1449
1571
|
|
|
1450
|
-
/*
|
|
1451
|
-
|
|
1572
|
+
/* Inline unpack_sk: mld_unpack_sk uses lazy types for s1/s2/t0 which
|
|
1573
|
+
* we cannot use here. t0 stays in packed form -- we compare it against
|
|
1574
|
+
* the recomputed value below. */
|
|
1575
|
+
mld_memcpy(rho, sk, MLDSA_SEEDBYTES);
|
|
1576
|
+
mld_memcpy(key, sk + MLDSA_SEEDBYTES, MLDSA_SEEDBYTES);
|
|
1577
|
+
mld_memcpy(tr, sk + 2 * MLDSA_SEEDBYTES, MLDSA_TRBYTES);
|
|
1578
|
+
mld_polyvecl_unpack_eta(s1, sk + 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES);
|
|
1579
|
+
mld_polyveck_unpack_eta(s2, sk + 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES +
|
|
1580
|
+
MLDSA_L * MLDSA_POLYETA_PACKEDBYTES);
|
|
1452
1581
|
|
|
1453
1582
|
/* Validate s1 and s2 coefficients are within [-MLDSA_ETA, MLDSA_ETA] */
|
|
1454
1583
|
chk1 = mld_polyvecl_chknorm(s1, MLDSA_ETA + 1) & 0xFF;
|
|
1455
1584
|
chk2 = mld_polyveck_chknorm(s2, MLDSA_ETA + 1) & 0xFF;
|
|
1456
1585
|
|
|
1457
|
-
/*
|
|
1458
|
-
|
|
1459
|
-
|
|
1586
|
+
/* NTT s1 in place to use as s1hat */
|
|
1587
|
+
mld_polyvecl_ntt(s1);
|
|
1588
|
+
|
|
1589
|
+
/* Pack rho into pk */
|
|
1590
|
+
mld_memcpy(pk, rho, MLDSA_SEEDBYTES);
|
|
1591
|
+
|
|
1592
|
+
/* Recompute t row by row, decompose, and pack t1 into pk and t0 into
|
|
1593
|
+
* t0_packed. */
|
|
1594
|
+
ret = mld_compute_pack_t0_t1(pk + MLDSA_SEEDBYTES, t0_packed, s1, s2, rho,
|
|
1595
|
+
context);
|
|
1460
1596
|
if (ret != 0)
|
|
1461
1597
|
{
|
|
1462
1598
|
goto cleanup;
|
|
1463
1599
|
}
|
|
1464
1600
|
|
|
1465
|
-
/*
|
|
1466
|
-
cmp0 = mld_ct_memcmp(
|
|
1467
|
-
|
|
1601
|
+
/* Compare recomputed packed t0 against the t0 region of sk. */
|
|
1602
|
+
cmp0 = mld_ct_memcmp(t0_packed,
|
|
1603
|
+
sk + 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES +
|
|
1604
|
+
MLDSA_L * MLDSA_POLYETA_PACKEDBYTES +
|
|
1605
|
+
MLDSA_K * MLDSA_POLYETA_PACKEDBYTES,
|
|
1606
|
+
MLDSA_K * MLDSA_POLYT0_PACKEDBYTES);
|
|
1607
|
+
|
|
1608
|
+
/* Compute tr_computed = H(pk) and compare to the stored tr */
|
|
1609
|
+
mld_shake256(tr_computed, MLDSA_TRBYTES, pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
1468
1610
|
cmp1 = mld_ct_memcmp((const uint8_t *)tr, (const uint8_t *)tr_computed,
|
|
1469
1611
|
MLDSA_TRBYTES);
|
|
1470
1612
|
check = mld_value_barrier_u8(cmp0 | cmp1 | chk1 | chk2);
|
|
@@ -1484,9 +1626,7 @@ cleanup:
|
|
|
1484
1626
|
MLD_CT_TESTING_DECLASSIFY(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
1485
1627
|
|
|
1486
1628
|
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1487
|
-
MLD_FREE(
|
|
1488
|
-
MLD_FREE(t0_computed, mld_polyveck, 1, context);
|
|
1489
|
-
MLD_FREE(t0, mld_polyveck, 1, context);
|
|
1629
|
+
MLD_FREE(t0_packed, uint8_t, MLDSA_K *MLDSA_POLYT0_PACKEDBYTES, context);
|
|
1490
1630
|
MLD_FREE(s2, mld_polyveck, 1, context);
|
|
1491
1631
|
MLD_FREE(s1, mld_polyvecl, 1, context);
|
|
1492
1632
|
MLD_FREE(key, uint8_t, MLDSA_SEEDBYTES, context);
|
|
@@ -1496,6 +1636,8 @@ cleanup:
|
|
|
1496
1636
|
|
|
1497
1637
|
return ret;
|
|
1498
1638
|
}
|
|
1639
|
+
#endif /* !MLD_CONFIG_NO_KEYPAIR_API */
|
|
1640
|
+
#endif /* !MLD_CONFIG_CORE_API_ONLY */
|
|
1499
1641
|
|
|
1500
1642
|
/* To facilitate single-compilation-unit (SCU) builds, undefine all macros.
|
|
1501
1643
|
* Don't modify by hand -- this is auto-generated by scripts/autogen. */
|
|
@@ -1506,6 +1648,8 @@ cleanup:
|
|
|
1506
1648
|
#undef mld_H
|
|
1507
1649
|
#undef mld_compute_pack_z
|
|
1508
1650
|
#undef mld_attempt_signature_generation
|
|
1509
|
-
#undef
|
|
1651
|
+
#undef mld_compute_pack_t0_t1
|
|
1652
|
+
#undef mld_get_max_signing_attempts
|
|
1510
1653
|
#undef MLD_NONCE_UB
|
|
1654
|
+
#undef MLD_CONFIG_MAX_SIGNING_ATTEMPTS
|
|
1511
1655
|
#undef MLD_PRE_HASH_OID_LEN
|