Skip to content

Commit dfa048b

Browse files
authored
Merge pull request #677 from pq-code-package/ntt_no_div
NTT: Simplify computation of zeta index
2 parents 36b611d + c71515d commit dfa048b

File tree

9 files changed

+63
-44
lines changed

9 files changed

+63
-44
lines changed

.github/workflows/base.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,26 @@ jobs:
272272
./scripts/autogen ${{ matrix.backend.arg }} ${{ matrix.simplify.arg }}
273273
make clean
274274
OPT=1 make quickcheck
275+
scan-build:
276+
strategy:
277+
fail-fast: false
278+
matrix:
279+
external:
280+
- ${{ github.repository_owner != 'pq-code-package' }}
281+
target:
282+
- runner: pqcp-arm64
283+
name: 'aarch64'
284+
- runner: ubuntu-latest
285+
name: 'x86_64'
286+
name: scan-build (${{ matrix.target.name }})
287+
runs-on: ${{ matrix.target.runner }}
288+
steps:
289+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
290+
- uses: ./.github/actions/setup-apt
291+
with:
292+
packages: clang-tools clang
293+
- name: make quickcheck
294+
run: |
295+
scan-build --status-bugs make quickcheck OPT=0
296+
make clean >/dev/null
297+
scan-build --status-bugs make quickcheck OPT=1

.github/workflows/bench_ec2_reusable.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ jobs:
100100
echo "Using AMI ID: $AMI_ID"
101101
echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
102102
- name: Configure AWS credentials
103-
uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3
103+
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
104104
with:
105105
role-to-assume: ${{ env.AWS_ROLE }}
106106
aws-region: ${{ inputs.aws_region }}
@@ -209,7 +209,7 @@ jobs:
209209
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
210210
steps:
211211
- name: Configure AWS credentials
212-
uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3
212+
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
213213
with:
214214
role-to-assume: ${{ env.AWS_ROLE }}
215215
aws-region: ${{ inputs.aws_region }}

.github/workflows/ci_ec2_container.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595
echo "Using AMI ID: $AMI_ID"
9696
echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
9797
- name: Configure AWS credentials
98-
uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3
98+
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
9999
with:
100100
role-to-assume: ${{ env.AWS_ROLE }}
101101
aws-region: ${{ env.AWS_REGION }}
@@ -168,7 +168,7 @@ jobs:
168168
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
169169
steps:
170170
- name: Configure AWS credentials
171-
uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3
171+
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
172172
with:
173173
role-to-assume: ${{ env.AWS_ROLE }}
174174
aws-region: ${{ env.AWS_REGION }}

.github/workflows/ci_ec2_reusable.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
echo "Using AMI ID: $AMI_ID"
9393
echo "AMI_ID=$AMI_ID" >> $GITHUB_OUTPUT
9494
- name: Configure AWS credentials
95-
uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3
95+
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
9696
with:
9797
role-to-assume: ${{ env.AWS_ROLE }}
9898
aws-region: ${{ env.AWS_REGION }}
@@ -153,7 +153,7 @@ jobs:
153153
if: ${{ always() }} # required to stop the runner even if the error happened in the previous jobs
154154
steps:
155155
- name: Configure AWS credentials
156-
uses: aws-actions/configure-aws-credentials@4fc4975a852c8cd99761e2de1f4ba73402e44dd9 # v4.0.3
156+
uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 # v4.1.0
157157
with:
158158
role-to-assume: ${{ env.AWS_ROLE }}
159159
aws-region: ${{ env.AWS_REGION }}

.github/workflows/scorecard.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
persist-credentials: false
3131

3232
- name: "Run analysis"
33-
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
33+
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
3434
with:
3535
results_file: results.sarif
3636
results_format: sarif
@@ -48,7 +48,7 @@ jobs:
4848
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
4949
# format to the repository Actions tab.
5050
- name: "Upload artifact"
51-
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
51+
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
5252
with:
5353
name: SARIF file
5454
path: results.sarif

mlkem/poly.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -349,29 +349,22 @@ __contract__(
349349
* Compute one layer of forward NTT
350350
* Parameters:
351351
* - r: Pointer to base of polynomial
352-
* - len: Stride of butterflies in this layer.
353-
* - layer: Ghost variable indicating which layer is being applied.
354-
* Must match `len` via `len == MLKEM_N >> layer`.
355-
* Note: `len` could be dropped and computed in the function, but
356-
* we are following the structure of the reference NTT from the
357-
* official Kyber implementation here, merely adding `layer` as
358-
* a ghost variable for the specifications.
352+
* - layer: Variable indicating which layer is being applied.
359353
*/
360354

361355
/* Reference: Embedded in `ntt()` in the reference implementation. */
362-
static void mlk_ntt_layer(int16_t r[MLKEM_N], unsigned len, unsigned layer)
356+
static void mlk_ntt_layer(int16_t r[MLKEM_N], unsigned layer)
363357
__contract__(
364358
requires(memory_no_alias(r, sizeof(int16_t) * MLKEM_N))
365-
requires(1 <= layer && layer <= 7 && len == (MLKEM_N >> layer))
359+
requires(1 <= layer && layer <= 7)
366360
requires(array_abs_bound(r, 0, MLKEM_N, layer * MLKEM_Q))
367361
assigns(memory_slice(r, sizeof(int16_t) * MLKEM_N))
368362
ensures(array_abs_bound(r, 0, MLKEM_N, (layer + 1) * MLKEM_Q)))
369363
{
370-
unsigned start, k;
371-
/* `layer` is a ghost variable only needed in the CBMC specification */
372-
((void)layer);
373-
/* Twiddle factors for layer n start at index 2^(layer-1) */
374-
k = MLKEM_N / (2 * len);
364+
unsigned start, k, len;
365+
/* Twiddle factors for layer n are at indices 2^(n-1)..2^n-1. */
366+
k = 1u << (layer - 1);
367+
len = MLKEM_N >> layer;
375368
for (start = 0; start < MLKEM_N; start += 2 * len)
376369
__loop__(
377370
invariant(start < MLKEM_N + 2 * len)
@@ -393,21 +386,23 @@ __contract__(
393386
* the proof may need strengthening.
394387
*/
395388

396-
/* Reference: `ntt()` in the reference implementation. */
389+
/* Reference: `ntt()` in the reference implementation.
390+
* - Iterate over `layer` instead of `len` in the outer loop
391+
* to simplify computation of zeta index. */
397392
MLK_INTERNAL_API
398393
void mlk_poly_ntt(mlk_poly *p)
399394
{
400-
unsigned len, layer;
395+
unsigned layer;
401396
int16_t *r;
402397
mlk_assert_abs_bound(p, MLKEM_N, MLKEM_Q);
403398
r = p->coeffs;
404399

405-
for (len = 128, layer = 1; len >= 2; len >>= 1, layer++)
400+
for (layer = 1; layer <= 7; layer++)
406401
__loop__(
407-
invariant(1 <= layer && layer <= 8 && len == (MLKEM_N >> layer))
402+
invariant(1 <= layer && layer <= 8)
408403
invariant(array_abs_bound(r, 0, MLKEM_N, layer * MLKEM_Q)))
409404
{
410-
mlk_ntt_layer(r, len, layer);
405+
mlk_ntt_layer(r, layer);
411406
}
412407

413408
/* Check the stronger bound */
@@ -429,19 +424,17 @@ void mlk_poly_ntt(mlk_poly *p)
429424
/* Compute one layer of inverse NTT */
430425

431426
/* Reference: Embedded into `invntt()` in the reference implementation */
432-
static void mlk_invntt_layer(int16_t *r, unsigned len, unsigned layer)
427+
static void mlk_invntt_layer(int16_t *r, unsigned layer)
433428
__contract__(
434429
requires(memory_no_alias(r, sizeof(int16_t) * MLKEM_N))
435-
requires(2 <= len && len <= 128 && 1 <= layer && layer <= 7)
436-
requires(len == (1 << (8 - layer)))
430+
requires(1 <= layer && layer <= 7)
437431
requires(array_abs_bound(r, 0, MLKEM_N, MLKEM_Q))
438432
assigns(memory_slice(r, sizeof(int16_t) * MLKEM_N))
439433
ensures(array_abs_bound(r, 0, MLKEM_N, MLKEM_Q)))
440434
{
441-
unsigned start, k;
442-
/* `layer` is a ghost variable used only in the specification */
443-
((void)layer);
444-
k = MLKEM_N / len - 1;
435+
unsigned start, k, len;
436+
len = (MLKEM_N >> layer);
437+
k = (1u << layer) - 1;
445438
for (start = 0; start < MLKEM_N; start += 2 * len)
446439
__loop__(
447440
invariant(array_abs_bound(r, 0, MLKEM_N, MLKEM_Q))
@@ -478,7 +471,7 @@ void mlk_poly_invntt_tomont(mlk_poly *p)
478471
* and NTT twist. This also brings coefficients down to
479472
* absolute value < MLKEM_Q.
480473
*/
481-
unsigned j, len, layer;
474+
unsigned j, layer;
482475
const int16_t f = 1441; /* check-magic: 1441 == pow(2,32 - 7,MLKEM_Q) */
483476
int16_t *r = p->coeffs;
484477

@@ -491,12 +484,12 @@ void mlk_poly_invntt_tomont(mlk_poly *p)
491484
}
492485

493486
/* Run the invNTT layers */
494-
for (len = 2, layer = 7; len <= 128; len <<= 1, layer--)
487+
for (layer = 7; layer > 0; layer--)
495488
__loop__(
496-
invariant(2 <= len && len <= 256 && layer <= 7 && len == (1 << (8 - layer)))
489+
invariant(0 <= layer && layer < 8)
497490
invariant(array_abs_bound(r, 0, MLKEM_N, MLKEM_Q)))
498491
{
499-
mlk_invntt_layer(p->coeffs, len, layer);
492+
mlk_invntt_layer(r, layer);
500493
}
501494

502495
mlk_assert_abs_bound(p, MLKEM_N, MLK_INVNTT_BOUND);

proofs/cbmc/invntt_layer/invntt_layer_harness.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
#include "common.h"
77

88

9-
void mlk_invntt_layer(int16_t *p, unsigned len, unsigned layer);
9+
void mlk_invntt_layer(int16_t *p, unsigned layer);
1010

1111
void harness(void)
1212
{
1313
int16_t *a;
14-
unsigned len, layer;
15-
mlk_invntt_layer(a, len, layer);
14+
unsigned layer;
15+
mlk_invntt_layer(a, layer);
1616
}

proofs/cbmc/ntt_layer/ntt_layer_harness.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
#include "poly.h"
66

77

8-
void mlk_ntt_layer(int16_t *p, unsigned len, unsigned layer);
8+
void mlk_ntt_layer(int16_t *p, unsigned layer);
99

1010
void harness(void)
1111
{
1212
int16_t *a;
13-
unsigned len, layer;
14-
mlk_ntt_layer(a, len, layer);
13+
unsigned layer;
14+
mlk_ntt_layer(a, layer);
1515
}

test/mk/rules.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ $(BUILD_DIR)/%.a: $(CONFIG)
2020
$(Q)[ -d $(@D) ] || mkdir -p $(@D)
2121
$(Q)rm -f $@
2222
$(Q)$(CC_AR) rcs $@ $(filter %.o,$^)
23+
# skip test when run in scan-build as it does not work
24+
ifneq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer)
2325
# $AR doesn't care about duplicated symbols, one can only find it out
2426
# via actually linking. The easiest one to do this that one can think
2527
# of is to create a dummy C file with empty main function on the fly,
@@ -42,6 +44,7 @@ else # if not on macOS or cross compil
4244
$(Q)rm -f $(@:%.a=%_tmp.a.out)
4345
endif
4446
$(Q)echo " AR Checked for duplicated symbols"
47+
endif
4548

4649
$(BUILD_DIR)/mlkem512/%.c.o: %.c $(CONFIG)
4750
$(Q)echo " CC $@"

0 commit comments

Comments
 (0)