/src/openssl41/crypto/ml_dsa/ml_dsa_poly.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2024-2026 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | #if !defined(OSSL_LIBCRYPTO_ML_DSA_ML_DSA_POLY_H) |
10 | | #define OSSL_LIBCRYPTO_ML_DSA_ML_DSA_POLY_H |
11 | | |
12 | | #include <openssl/crypto.h> |
13 | | |
14 | | #include "internal/common.h" |
15 | | #include "ml_dsa_local.h" |
16 | | |
17 | 149M | #define ML_DSA_NUM_POLY_COEFFICIENTS 256 |
18 | | |
19 | | /* Polynomial object with 256 coefficients. The coefficients are unsigned 32 bits */ |
20 | | struct poly_st { |
21 | | #if defined(VX_COMPILER_SUPPORT_VEC128) |
22 | | ALIGN16 uint32_t coeff[ML_DSA_NUM_POLY_COEFFICIENTS]; |
23 | | #elif defined(_ARCH_PPC64) |
24 | | ALIGN16 uint32_t coeff[ML_DSA_NUM_POLY_COEFFICIENTS]; |
25 | | #else |
26 | | uint32_t coeff[ML_DSA_NUM_POLY_COEFFICIENTS]; |
27 | | #endif |
28 | | }; |
29 | | |
30 | | static ossl_inline ossl_unused void |
31 | | poly_zero(POLY *p) |
32 | 4.92k | { |
33 | 4.92k | memset(p->coeff, 0, sizeof(*p)); |
34 | 4.92k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_zero Unexecuted instantiation: ml_dsa_key.c:poly_zero Unexecuted instantiation: ml_dsa_matrix.c:poly_zero Unexecuted instantiation: ml_dsa_ntt.c:poly_zero ml_dsa_sample.c:poly_zero Line | Count | Source | 32 | 4.92k | { | 33 | 4.92k | memset(p->coeff, 0, sizeof(*p)); | 34 | 4.92k | } |
Unexecuted instantiation: ml_dsa_sign.c:poly_zero |
35 | | |
36 | | /** |
37 | | * @brief Polynomial addition. |
38 | | * |
39 | | * @param lhs A polynomial with coefficients in the range (0..q-1) |
40 | | * @param rhs A polynomial with coefficients in the range (0..q-1) to add |
41 | | * to the 'lhs'. |
42 | | * @param out The returned addition result with the coefficients all in the |
43 | | * range 0..q-1 |
44 | | */ |
45 | | static ossl_inline ossl_unused void |
46 | | poly_add(const POLY *lhs, const POLY *rhs, POLY *out) |
47 | 258k | { |
48 | 258k | int i; |
49 | | |
50 | 66.5M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
51 | 66.2M | out->coeff[i] = reduce_once(lhs->coeff[i] + rhs->coeff[i]); |
52 | 258k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_add Line | Count | Source | 47 | 12.8k | { | 48 | 12.8k | int i; | 49 | | | 50 | 3.30M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 51 | 3.29M | out->coeff[i] = reduce_once(lhs->coeff[i] + rhs->coeff[i]); | 52 | 12.8k | } |
Line | Count | Source | 47 | 225k | { | 48 | 225k | int i; | 49 | | | 50 | 57.9M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 51 | 57.7M | out->coeff[i] = reduce_once(lhs->coeff[i] + rhs->coeff[i]); | 52 | 225k | } |
Unexecuted instantiation: ml_dsa_ntt.c:poly_add Unexecuted instantiation: ml_dsa_sample.c:poly_add Line | Count | Source | 47 | 20.5k | { | 48 | 20.5k | int i; | 49 | | | 50 | 5.29M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 51 | 5.27M | out->coeff[i] = reduce_once(lhs->coeff[i] + rhs->coeff[i]); | 52 | 20.5k | } |
|
53 | | |
54 | | /** |
55 | | * @brief Polynomial subtraction. |
56 | | * |
57 | | * @param lhs A polynomial with coefficients in the range (0..q-1) |
58 | | * @param rhs A polynomial with coefficients in the range (0..q-1) to subtract |
59 | | * from the 'lhs'. |
60 | | * @param out The returned subtraction result with the coefficients all in the |
61 | | * range 0..q-1 |
62 | | */ |
63 | | static ossl_inline ossl_unused void |
64 | | poly_sub(const POLY *lhs, const POLY *rhs, POLY *out) |
65 | 28.1k | { |
66 | 28.1k | int i; |
67 | | |
68 | 7.24M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
69 | 7.21M | out->coeff[i] = mod_sub(lhs->coeff[i], rhs->coeff[i]); |
70 | 28.1k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_sub Unexecuted instantiation: ml_dsa_key.c:poly_sub Unexecuted instantiation: ml_dsa_matrix.c:poly_sub Unexecuted instantiation: ml_dsa_ntt.c:poly_sub Unexecuted instantiation: ml_dsa_sample.c:poly_sub Line | Count | Source | 65 | 28.1k | { | 66 | 28.1k | int i; | 67 | | | 68 | 7.24M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 69 | 7.21M | out->coeff[i] = mod_sub(lhs->coeff[i], rhs->coeff[i]); | 70 | 28.1k | } |
|
71 | | |
72 | | /* @returns 1 if the polynomials are equal, or 0 otherwise */ |
73 | | static ossl_inline ossl_unused int |
74 | | poly_equal(const POLY *a, const POLY *b) |
75 | 2 | { |
76 | 2 | return CRYPTO_memcmp(a, b, sizeof(*a)) == 0; |
77 | 2 | } Unexecuted instantiation: ml_dsa_encoders.c:poly_equal Line | Count | Source | 75 | 2 | { | 76 | 2 | return CRYPTO_memcmp(a, b, sizeof(*a)) == 0; | 77 | 2 | } |
Unexecuted instantiation: ml_dsa_matrix.c:poly_equal Unexecuted instantiation: ml_dsa_ntt.c:poly_equal Unexecuted instantiation: ml_dsa_sample.c:poly_equal Unexecuted instantiation: ml_dsa_sign.c:poly_equal |
78 | | |
79 | | static ossl_inline ossl_unused void |
80 | | poly_ntt(POLY *p) |
81 | 4.92k | { |
82 | 4.92k | ossl_ml_dsa_poly_ntt(p); |
83 | 4.92k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_ntt Unexecuted instantiation: ml_dsa_key.c:poly_ntt Unexecuted instantiation: ml_dsa_matrix.c:poly_ntt Unexecuted instantiation: ml_dsa_ntt.c:poly_ntt Unexecuted instantiation: ml_dsa_sample.c:poly_ntt Line | Count | Source | 81 | 4.92k | { | 82 | 4.92k | ossl_ml_dsa_poly_ntt(p); | 83 | 4.92k | } |
|
84 | | |
85 | | static ossl_inline ossl_unused int |
86 | | poly_sample_in_ball_ntt(POLY *out, const uint8_t *seed, int seed_len, |
87 | | EVP_MD_CTX *h_ctx, const EVP_MD *md, uint32_t tau) |
88 | 4.92k | { |
89 | 4.92k | if (!ossl_ml_dsa_poly_sample_in_ball(out, seed, seed_len, h_ctx, md, tau)) |
90 | 0 | return 0; |
91 | 4.92k | poly_ntt(out); |
92 | 4.92k | return 1; |
93 | 4.92k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_sample_in_ball_ntt Unexecuted instantiation: ml_dsa_key.c:poly_sample_in_ball_ntt Unexecuted instantiation: ml_dsa_matrix.c:poly_sample_in_ball_ntt Unexecuted instantiation: ml_dsa_ntt.c:poly_sample_in_ball_ntt Unexecuted instantiation: ml_dsa_sample.c:poly_sample_in_ball_ntt ml_dsa_sign.c:poly_sample_in_ball_ntt Line | Count | Source | 88 | 4.92k | { | 89 | 4.92k | if (!ossl_ml_dsa_poly_sample_in_ball(out, seed, seed_len, h_ctx, md, tau)) | 90 | 0 | return 0; | 91 | 4.92k | poly_ntt(out); | 92 | 4.92k | return 1; | 93 | 4.92k | } |
|
94 | | |
95 | | static ossl_inline ossl_unused int |
96 | | poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len, |
97 | | uint32_t gamma1, EVP_MD_CTX *h_ctx, const EVP_MD *md) |
98 | 5.85k | { |
99 | 5.85k | return ossl_ml_dsa_poly_expand_mask(out, seed, seed_len, gamma1, h_ctx, md); |
100 | 5.85k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_expand_mask Unexecuted instantiation: ml_dsa_key.c:poly_expand_mask Unexecuted instantiation: ml_dsa_matrix.c:poly_expand_mask Unexecuted instantiation: ml_dsa_ntt.c:poly_expand_mask ml_dsa_sample.c:poly_expand_mask Line | Count | Source | 98 | 5.85k | { | 99 | 5.85k | return ossl_ml_dsa_poly_expand_mask(out, seed, seed_len, gamma1, h_ctx, md); | 100 | 5.85k | } |
|
101 | | |
102 | | /** |
103 | | * @brief Decompose the coefficients of a polynomial into (r1, r0) such that |
104 | | * coeff[i] == t1[i] * 2^13 + t0[i] mod q |
105 | | * See FIPS 204, Algorithm 35, Power2Round() |
106 | | * |
107 | | * @param t A polynomial containing coefficients in the range 0..q-1 |
108 | | * @param t1 The returned polynomial containing coefficients that represent |
109 | | * the top 10 MSB of each coefficient in t (i.e each ranging from 0..1023) |
110 | | * @param t0 The remainder coefficients of t in the range (0..4096 or q-4095..q-1) |
111 | | * Each t0 coefficient has an effective range of 8192 (i.e. 13 bits). |
112 | | */ |
113 | | static ossl_inline ossl_unused void |
114 | | poly_power2_round(const POLY *t, POLY *t1, POLY *t0) |
115 | 12.8k | { |
116 | 12.8k | int i; |
117 | | |
118 | 3.30M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
119 | 3.29M | ossl_ml_dsa_key_compress_power2_round(t->coeff[i], |
120 | 3.29M | t1->coeff + i, t0->coeff + i); |
121 | 12.8k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_power2_round ml_dsa_key.c:poly_power2_round Line | Count | Source | 115 | 12.8k | { | 116 | 12.8k | int i; | 117 | | | 118 | 3.30M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 119 | 3.29M | ossl_ml_dsa_key_compress_power2_round(t->coeff[i], | 120 | 3.29M | t1->coeff + i, t0->coeff + i); | 121 | 12.8k | } |
Unexecuted instantiation: ml_dsa_matrix.c:poly_power2_round Unexecuted instantiation: ml_dsa_ntt.c:poly_power2_round Unexecuted instantiation: ml_dsa_sample.c:poly_power2_round Unexecuted instantiation: ml_dsa_sign.c:poly_power2_round |
122 | | |
123 | | static ossl_inline ossl_unused void |
124 | | poly_scale_power2_round(POLY *in, POLY *out) |
125 | 5.13k | { |
126 | 5.13k | int i; |
127 | | |
128 | 1.31M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
129 | 1.31M | out->coeff[i] = (in->coeff[i] << ML_DSA_D_BITS); |
130 | 5.13k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_scale_power2_round Unexecuted instantiation: ml_dsa_key.c:poly_scale_power2_round Unexecuted instantiation: ml_dsa_matrix.c:poly_scale_power2_round Unexecuted instantiation: ml_dsa_ntt.c:poly_scale_power2_round Unexecuted instantiation: ml_dsa_sample.c:poly_scale_power2_round ml_dsa_sign.c:poly_scale_power2_round Line | Count | Source | 125 | 5.13k | { | 126 | 5.13k | int i; | 127 | | | 128 | 1.31M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 129 | 1.31M | out->coeff[i] = (in->coeff[i] << ML_DSA_D_BITS); | 130 | 5.13k | } |
|
131 | | |
132 | | static ossl_inline ossl_unused void |
133 | | poly_high_bits(const POLY *in, uint32_t gamma2, POLY *out) |
134 | 23.0k | { |
135 | 23.0k | int i; |
136 | | |
137 | 5.92M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
138 | 5.90M | out->coeff[i] = ossl_ml_dsa_key_compress_high_bits(in->coeff[i], gamma2); |
139 | 23.0k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_high_bits Unexecuted instantiation: ml_dsa_key.c:poly_high_bits Unexecuted instantiation: ml_dsa_matrix.c:poly_high_bits Unexecuted instantiation: ml_dsa_ntt.c:poly_high_bits Unexecuted instantiation: ml_dsa_sample.c:poly_high_bits ml_dsa_sign.c:poly_high_bits Line | Count | Source | 134 | 23.0k | { | 135 | 23.0k | int i; | 136 | | | 137 | 5.92M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 138 | 5.90M | out->coeff[i] = ossl_ml_dsa_key_compress_high_bits(in->coeff[i], gamma2); | 139 | 23.0k | } |
|
140 | | |
141 | | static ossl_inline ossl_unused void |
142 | | poly_low_bits(const POLY *in, uint32_t gamma2, POLY *out) |
143 | 23.0k | { |
144 | 23.0k | int i; |
145 | | |
146 | 5.92M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
147 | 5.90M | out->coeff[i] = ossl_ml_dsa_key_compress_low_bits(in->coeff[i], gamma2); |
148 | 23.0k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_low_bits Unexecuted instantiation: ml_dsa_key.c:poly_low_bits Unexecuted instantiation: ml_dsa_matrix.c:poly_low_bits Unexecuted instantiation: ml_dsa_ntt.c:poly_low_bits Unexecuted instantiation: ml_dsa_sample.c:poly_low_bits ml_dsa_sign.c:poly_low_bits Line | Count | Source | 143 | 23.0k | { | 144 | 23.0k | int i; | 145 | | | 146 | 5.92M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 147 | 5.90M | out->coeff[i] = ossl_ml_dsa_key_compress_low_bits(in->coeff[i], gamma2); | 148 | 23.0k | } |
|
149 | | |
150 | | static ossl_inline ossl_unused void |
151 | | poly_make_hint(const POLY *ct0, const POLY *cs2, const POLY *w, uint32_t gamma2, |
152 | | POLY *out) |
153 | 5.16k | { |
154 | 5.16k | int i; |
155 | | |
156 | 1.32M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
157 | 1.32M | out->coeff[i] = ossl_ml_dsa_key_compress_make_hint(ct0->coeff[i], |
158 | 1.32M | cs2->coeff[i], |
159 | 1.32M | gamma2, w->coeff[i]); |
160 | 5.16k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_make_hint Unexecuted instantiation: ml_dsa_key.c:poly_make_hint Unexecuted instantiation: ml_dsa_matrix.c:poly_make_hint Unexecuted instantiation: ml_dsa_ntt.c:poly_make_hint Unexecuted instantiation: ml_dsa_sample.c:poly_make_hint ml_dsa_sign.c:poly_make_hint Line | Count | Source | 153 | 5.16k | { | 154 | 5.16k | int i; | 155 | | | 156 | 1.32M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 157 | 1.32M | out->coeff[i] = ossl_ml_dsa_key_compress_make_hint(ct0->coeff[i], | 158 | 1.32M | cs2->coeff[i], | 159 | 1.32M | gamma2, w->coeff[i]); | 160 | 5.16k | } |
|
161 | | |
162 | | static ossl_inline ossl_unused void |
163 | | poly_use_hint(const POLY *h, const POLY *r, uint32_t gamma2, POLY *out) |
164 | 5.13k | { |
165 | 5.13k | int i; |
166 | | |
167 | 1.31M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) |
168 | 1.31M | out->coeff[i] = ossl_ml_dsa_key_compress_use_hint(h->coeff[i], |
169 | 1.31M | r->coeff[i], gamma2); |
170 | 5.13k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_use_hint Unexecuted instantiation: ml_dsa_key.c:poly_use_hint Unexecuted instantiation: ml_dsa_matrix.c:poly_use_hint Unexecuted instantiation: ml_dsa_ntt.c:poly_use_hint Unexecuted instantiation: ml_dsa_sample.c:poly_use_hint ml_dsa_sign.c:poly_use_hint Line | Count | Source | 164 | 5.13k | { | 165 | 5.13k | int i; | 166 | | | 167 | 1.31M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) | 168 | 1.31M | out->coeff[i] = ossl_ml_dsa_key_compress_use_hint(h->coeff[i], | 169 | 1.31M | r->coeff[i], gamma2); | 170 | 5.13k | } |
|
171 | | |
172 | | static ossl_inline ossl_unused void |
173 | | poly_max(const POLY *p, uint32_t *mx) |
174 | 30.3k | { |
175 | 30.3k | int i; |
176 | | |
177 | 7.80M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) { |
178 | 7.77M | uint32_t c = p->coeff[i]; |
179 | 7.77M | uint32_t abs = abs_mod_prime(c); |
180 | | |
181 | 7.77M | *mx = maximum(*mx, abs); |
182 | 7.77M | } |
183 | 30.3k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_max Unexecuted instantiation: ml_dsa_key.c:poly_max Unexecuted instantiation: ml_dsa_matrix.c:poly_max Unexecuted instantiation: ml_dsa_ntt.c:poly_max Unexecuted instantiation: ml_dsa_sample.c:poly_max Line | Count | Source | 174 | 30.3k | { | 175 | 30.3k | int i; | 176 | | | 177 | 7.80M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) { | 178 | 7.77M | uint32_t c = p->coeff[i]; | 179 | 7.77M | uint32_t abs = abs_mod_prime(c); | 180 | | | 181 | 7.77M | *mx = maximum(*mx, abs); | 182 | 7.77M | } | 183 | 30.3k | } |
|
184 | | |
185 | | static ossl_inline ossl_unused void |
186 | | poly_max_signed(const POLY *p, uint32_t *mx) |
187 | 23.0k | { |
188 | 23.0k | int i; |
189 | | |
190 | 5.92M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) { |
191 | 5.90M | uint32_t c = p->coeff[i]; |
192 | 5.90M | uint32_t abs = abs_signed(c); |
193 | | |
194 | 5.90M | *mx = maximum(*mx, abs); |
195 | 5.90M | } |
196 | 23.0k | } Unexecuted instantiation: ml_dsa_encoders.c:poly_max_signed Unexecuted instantiation: ml_dsa_key.c:poly_max_signed Unexecuted instantiation: ml_dsa_matrix.c:poly_max_signed Unexecuted instantiation: ml_dsa_ntt.c:poly_max_signed Unexecuted instantiation: ml_dsa_sample.c:poly_max_signed ml_dsa_sign.c:poly_max_signed Line | Count | Source | 187 | 23.0k | { | 188 | 23.0k | int i; | 189 | | | 190 | 5.92M | for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) { | 191 | 5.90M | uint32_t c = p->coeff[i]; | 192 | 5.90M | uint32_t abs = abs_signed(c); | 193 | | | 194 | 5.90M | *mx = maximum(*mx, abs); | 195 | 5.90M | } | 196 | 23.0k | } |
|
197 | | |
198 | | #endif /* !defined(OSSL_LIBCRYPTO_ML_DSA_ML_DSA_POLY_H) */ |