mirror of
https://github.com/luxfi/pqclean.git
synced 2026-11-03 09:57:54 +00:00
175 lines
5.5 KiB
C
175 lines
5.5 KiB
C
/*
|
|
* Falcon signature verification.
|
|
*
|
|
* =============================================================================
|
|
* Copyright (c) 2023 by Cryptographic Engineering Research Group (CERG)
|
|
* ECE Department, George Mason University
|
|
* Fairfax, VA, U.S.A.
|
|
* Author: Duc Tri Nguyen
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
* =============================================================================
|
|
* @author Duc Tri Nguyen <[email protected]>, <[email protected]>
|
|
*/
|
|
|
|
#include "inner.h"
|
|
#include "poly.h"
|
|
|
|
/* see inner.h */
|
|
void PQCLEAN_FALCON512_AARCH64_to_ntt(int16_t *h) {
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(h, NTT_NONE);
|
|
}
|
|
|
|
void PQCLEAN_FALCON512_AARCH64_to_ntt_monty(int16_t *h) {
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(h, NTT_MONT);
|
|
}
|
|
|
|
/* see inner.h */
|
|
int PQCLEAN_FALCON512_AARCH64_verify_raw(const int16_t *c0, const int16_t *s2,
|
|
int16_t *h, int16_t *tmp) {
|
|
int16_t *tt = tmp;
|
|
|
|
/*
|
|
* Compute s1 = c0 - s2*h mod phi mod q (in tt[]).
|
|
*/
|
|
|
|
memcpy(tt, s2, sizeof(int16_t) * FALCON_N);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(h, NTT_NONE);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(tt, NTT_MONT_INV);
|
|
PQCLEAN_FALCON512_AARCH64_poly_montmul_ntt(tt, h);
|
|
PQCLEAN_FALCON512_AARCH64_poly_invntt(tt, INVNTT_NONE);
|
|
PQCLEAN_FALCON512_AARCH64_poly_sub_barrett(tt, c0, tt);
|
|
|
|
/*
|
|
* Signature is valid if and only if the aggregate (s1,s2) vector
|
|
* is short enough.
|
|
*/
|
|
return PQCLEAN_FALCON512_AARCH64_is_short(tt, s2);
|
|
}
|
|
|
|
/* see inner.h */
|
|
int PQCLEAN_FALCON512_AARCH64_compute_public(int16_t *h, const int8_t *f, const int8_t *g, int16_t *tmp) {
|
|
int16_t *tt = tmp;
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_int8_to_int16(h, g);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(h, NTT_NONE);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_int8_to_int16(tt, f);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(tt, NTT_MONT);
|
|
|
|
if (PQCLEAN_FALCON512_AARCH64_poly_compare_with_zero(tt)) {
|
|
return 0;
|
|
}
|
|
PQCLEAN_FALCON512_AARCH64_poly_div_12289(h, tt);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_invntt(h, INVNTT_NINV);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_convert_to_unsigned(h);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* see inner.h */
|
|
int PQCLEAN_FALCON512_AARCH64_complete_private(int8_t *G, const int8_t *f,
|
|
const int8_t *g, const int8_t *F,
|
|
uint8_t *tmp) {
|
|
int16_t *t1, *t2;
|
|
|
|
t1 = (int16_t *)tmp;
|
|
t2 = t1 + FALCON_N;
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_int8_to_int16(t1, g);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(t1, NTT_NONE);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_int8_to_int16(t2, F);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(t2, NTT_MONT);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_montmul_ntt(t1, t2);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_int8_to_int16(t2, f);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(t2, NTT_MONT);
|
|
|
|
if (PQCLEAN_FALCON512_AARCH64_poly_compare_with_zero(t2)) {
|
|
return 0;
|
|
}
|
|
PQCLEAN_FALCON512_AARCH64_poly_div_12289(t1, t2);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_invntt(t1, INVNTT_NINV);
|
|
|
|
if (PQCLEAN_FALCON512_AARCH64_poly_int16_to_int8(G, t1)) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* see inner.h */
|
|
int PQCLEAN_FALCON512_AARCH64_is_invertible(const int16_t *s2, uint8_t *tmp) {
|
|
int16_t *tt = (int16_t *)tmp;
|
|
uint16_t r;
|
|
|
|
memcpy(tt, s2, sizeof(int16_t) * FALCON_N);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(tt, NTT_MONT);
|
|
|
|
r = PQCLEAN_FALCON512_AARCH64_poly_compare_with_zero(tt);
|
|
|
|
return (int)(1u - (r >> 15));
|
|
}
|
|
|
|
/* see inner.h */
|
|
int PQCLEAN_FALCON512_AARCH64_verify_recover(int16_t *h, const int16_t *c0,
|
|
const int16_t *s1, const int16_t *s2,
|
|
uint8_t *tmp) {
|
|
int16_t *tt = (int16_t *)tmp;
|
|
uint16_t r;
|
|
|
|
/*
|
|
* Compute h = (c0 - s1) / s2. If one of the coefficients of s2
|
|
* is zero (in NTT representation) then the operation fails. We
|
|
* keep that information into a flag so that we do not deviate
|
|
* from strict constant-time processing; if all coefficients of
|
|
* s2 are non-zero, then the high bit of r will be zero.
|
|
*/
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_sub_barrett(h, c0, s1);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(h, NTT_NONE);
|
|
|
|
/*
|
|
* Reduce elements of s1 and s2 modulo q; then write s2 into tt[]
|
|
* and c0 - s1 into h[].
|
|
*/
|
|
memcpy(tt, s2, sizeof(int16_t) * FALCON_N);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(tt, NTT_MONT);
|
|
r = PQCLEAN_FALCON512_AARCH64_poly_compare_with_zero(tt);
|
|
PQCLEAN_FALCON512_AARCH64_poly_div_12289(h, tt);
|
|
|
|
PQCLEAN_FALCON512_AARCH64_poly_invntt(h, INVNTT_NINV);
|
|
|
|
/*
|
|
* Signature is acceptable if and only if it is short enough,
|
|
* and s2 was invertible mod phi mod q. The caller must still
|
|
* check that the rebuilt public key matches the expected
|
|
* value (e.g. through a hash).
|
|
*/
|
|
r = (uint16_t) (~r & (uint16_t) - PQCLEAN_FALCON512_AARCH64_is_short(s1, s2));
|
|
return (int)(r >> 15);
|
|
}
|
|
|
|
/* see inner.h */
|
|
int PQCLEAN_FALCON512_AARCH64_count_nttzero(const int16_t *sig, uint8_t *tmp) {
|
|
int16_t *s2 = (int16_t *)tmp;
|
|
|
|
memcpy(s2, sig, sizeof(int16_t) * FALCON_N);
|
|
PQCLEAN_FALCON512_AARCH64_poly_ntt(s2, NTT_MONT);
|
|
|
|
int r = PQCLEAN_FALCON512_AARCH64_poly_compare_with_zero(s2);
|
|
|
|
return r;
|
|
}
|