Coverage Report

Created: 2026-10-16 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/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
0
#define ML_DSA_NUM_POLY_COEFFICIENTS 256
18
19
/*
20
 * Polynomial object with 256 coefficients.  The coefficients are unsigned
21
 * 32-bit integers.
22
 *
23
 * ALIGN16 is applied unconditionally on s390x builds that include the VX
24
 * vector object (OPENSSL_ML_DSA_S390X && __s390x__).  This matches the guard
25
 * used in ml_dsa_local.h and ml_dsa_ntt.c so that every translation unit
26
 * (including ml_dsa_matrix.c) sees _Alignof(POLY) == 16 and allocates stack
27
 * objects (e.g. the local `product` in ossl_ml_dsa_matrix_mult_vector) with
28
 * the correct 16-byte alignment required by ossl_poly_ntt_mult_scalar_vec128.
29
 *
30
 * Using VX_COMPILER_SUPPORT_VEC128 here was incorrect: that macro is only
31
 * defined inside ml_dsa_ntt_vec128.c (a separate translation unit compiled
32
 * with -march=z13), so baseline TUs would see _Alignof(POLY) == 4 and pass
33
 * misaligned pointers to the vector implementation.
34
 */
35
struct poly_st {
36
#if defined(OPENSSL_ML_DSA_S390X) && defined(__s390x__)
37
    ALIGN16 uint32_t coeff[ML_DSA_NUM_POLY_COEFFICIENTS];
38
#elif defined(_ARCH_PPC64)
39
    ALIGN16 uint32_t coeff[ML_DSA_NUM_POLY_COEFFICIENTS];
40
#else
41
    uint32_t coeff[ML_DSA_NUM_POLY_COEFFICIENTS];
42
#endif
43
};
44
45
static ossl_inline ossl_unused void
46
poly_zero(POLY *p)
47
0
{
48
0
    memset(p->coeff, 0, sizeof(*p));
49
0
}
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
Unexecuted instantiation: ml_dsa_sample.c:poly_zero
Unexecuted instantiation: ml_dsa_sign.c:poly_zero
50
51
/**
52
 * @brief Polynomial addition.
53
 *
54
 * @param lhs A polynomial with coefficients in the range (0..q-1)
55
 * @param rhs A polynomial with coefficients in the range (0..q-1) to add
56
 *            to the 'lhs'.
57
 * @param out The returned addition result with the coefficients all in the
58
 *            range 0..q-1
59
 */
60
static ossl_inline ossl_unused void
61
poly_add(const POLY *lhs, const POLY *rhs, POLY *out)
62
0
{
63
0
    int i;
64
65
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
66
0
        out->coeff[i] = reduce_once(lhs->coeff[i] + rhs->coeff[i]);
67
0
}
Unexecuted instantiation: ml_dsa_encoders.c:poly_add
Unexecuted instantiation: ml_dsa_key.c:poly_add
Unexecuted instantiation: ml_dsa_matrix.c:poly_add
Unexecuted instantiation: ml_dsa_ntt.c:poly_add
Unexecuted instantiation: ml_dsa_sample.c:poly_add
Unexecuted instantiation: ml_dsa_sign.c:poly_add
68
69
/**
70
 * @brief Polynomial subtraction.
71
 *
72
 * @param lhs A polynomial with coefficients in the range (0..q-1)
73
 * @param rhs A polynomial with coefficients in the range (0..q-1) to subtract
74
 *            from the 'lhs'.
75
 * @param out The returned subtraction result with the coefficients all in the
76
 *            range 0..q-1
77
 */
78
static ossl_inline ossl_unused void
79
poly_sub(const POLY *lhs, const POLY *rhs, POLY *out)
80
0
{
81
0
    int i;
82
83
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
84
0
        out->coeff[i] = mod_sub(lhs->coeff[i], rhs->coeff[i]);
85
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_sub
86
87
/* @returns 1 if the polynomials are equal, or 0 otherwise */
88
static ossl_inline ossl_unused int
89
poly_equal(const POLY *a, const POLY *b)
90
0
{
91
0
    return CRYPTO_memcmp(a, b, sizeof(*a)) == 0;
92
0
}
Unexecuted instantiation: ml_dsa_encoders.c:poly_equal
Unexecuted instantiation: ml_dsa_key.c:poly_equal
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
93
94
static ossl_inline ossl_unused void
95
poly_ntt(POLY *p)
96
0
{
97
0
    ossl_ml_dsa_poly_ntt(p);
98
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_ntt
99
100
static ossl_inline ossl_unused int
101
poly_sample_in_ball_ntt(POLY *out, const uint8_t *seed, int seed_len,
102
    EVP_MD_CTX *h_ctx, const EVP_MD *md, uint32_t tau)
103
0
{
104
0
    if (!ossl_ml_dsa_poly_sample_in_ball(out, seed, seed_len, h_ctx, md, tau))
105
0
        return 0;
106
0
    poly_ntt(out);
107
0
    return 1;
108
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_sample_in_ball_ntt
109
110
static ossl_inline ossl_unused int
111
poly_expand_mask(POLY *out, const uint8_t *seed, size_t seed_len,
112
    uint32_t gamma1, EVP_MD_CTX *h_ctx, const EVP_MD *md)
113
0
{
114
0
    return ossl_ml_dsa_poly_expand_mask(out, seed, seed_len, gamma1, h_ctx, md);
115
0
}
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
Unexecuted instantiation: ml_dsa_sample.c:poly_expand_mask
Unexecuted instantiation: ml_dsa_sign.c:poly_expand_mask
116
117
/**
118
 * @brief Decompose the coefficients of a polynomial into (r1, r0) such that
119
 * coeff[i] == t1[i] * 2^13 + t0[i] mod q
120
 * See FIPS 204, Algorithm 35, Power2Round()
121
 *
122
 * @param t A polynomial containing coefficients in the range 0..q-1
123
 * @param t1 The returned polynomial containing coefficients that represent
124
 *           the top 10 MSB of each coefficient in t (i.e each ranging from 0..1023)
125
 * @param t0 The remainder coefficients of t in the range (0..4096 or q-4095..q-1)
126
 *           Each t0 coefficient has an effective range of 8192 (i.e. 13 bits).
127
 */
128
static ossl_inline ossl_unused void
129
poly_power2_round(const POLY *t, POLY *t1, POLY *t0)
130
0
{
131
0
    int i;
132
133
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
134
0
        ossl_ml_dsa_key_compress_power2_round(t->coeff[i],
135
0
            t1->coeff + i, t0->coeff + i);
136
0
}
Unexecuted instantiation: ml_dsa_encoders.c:poly_power2_round
Unexecuted instantiation: ml_dsa_key.c:poly_power2_round
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
137
138
static ossl_inline ossl_unused void
139
poly_scale_power2_round(POLY *in, POLY *out)
140
0
{
141
0
    int i;
142
143
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
144
0
        out->coeff[i] = (in->coeff[i] << ML_DSA_D_BITS);
145
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_scale_power2_round
146
147
static ossl_inline ossl_unused void
148
poly_high_bits(const POLY *in, uint32_t gamma2, POLY *out)
149
0
{
150
0
    int i;
151
152
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
153
0
        out->coeff[i] = ossl_ml_dsa_key_compress_high_bits(in->coeff[i], gamma2);
154
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_high_bits
155
156
static ossl_inline ossl_unused void
157
poly_low_bits(const POLY *in, uint32_t gamma2, POLY *out)
158
0
{
159
0
    int i;
160
161
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
162
0
        out->coeff[i] = ossl_ml_dsa_key_compress_low_bits(in->coeff[i], gamma2);
163
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_low_bits
164
165
static ossl_inline ossl_unused void
166
poly_make_hint(const POLY *ct0, const POLY *cs2, const POLY *w, uint32_t gamma2,
167
    POLY *out)
168
0
{
169
0
    int i;
170
171
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
172
0
        out->coeff[i] = ossl_ml_dsa_key_compress_make_hint(ct0->coeff[i],
173
0
            cs2->coeff[i],
174
0
            gamma2, w->coeff[i]);
175
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_make_hint
176
177
static ossl_inline ossl_unused void
178
poly_use_hint(const POLY *h, const POLY *r, uint32_t gamma2, POLY *out)
179
0
{
180
0
    int i;
181
182
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++)
183
0
        out->coeff[i] = ossl_ml_dsa_key_compress_use_hint(h->coeff[i],
184
0
            r->coeff[i], gamma2);
185
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_use_hint
186
187
static ossl_inline ossl_unused void
188
poly_max(const POLY *p, uint32_t *mx)
189
0
{
190
0
    int i;
191
192
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) {
193
0
        uint32_t c = p->coeff[i];
194
0
        uint32_t abs = abs_mod_prime(c);
195
196
0
        *mx = maximum(*mx, abs);
197
0
    }
198
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_max
199
200
static ossl_inline ossl_unused void
201
poly_max_signed(const POLY *p, uint32_t *mx)
202
0
{
203
0
    int i;
204
205
0
    for (i = 0; i < ML_DSA_NUM_POLY_COEFFICIENTS; i++) {
206
0
        uint32_t c = p->coeff[i];
207
0
        uint32_t abs = abs_signed(c);
208
209
0
        *mx = maximum(*mx, abs);
210
0
    }
211
0
}
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
Unexecuted instantiation: ml_dsa_sign.c:poly_max_signed
212
213
#endif /* !defined(OSSL_LIBCRYPTO_ML_DSA_ML_DSA_POLY_H) */