summaryrefslogtreecommitdiff
path: root/lib/liboqs/src/sig/dilithium/pqcrystals-dilithium_dilithium5_ref/sign.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/liboqs/src/sig/dilithium/pqcrystals-dilithium_dilithium5_ref/sign.c')
-rw-r--r--lib/liboqs/src/sig/dilithium/pqcrystals-dilithium_dilithium5_ref/sign.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/lib/liboqs/src/sig/dilithium/pqcrystals-dilithium_dilithium5_ref/sign.c b/lib/liboqs/src/sig/dilithium/pqcrystals-dilithium_dilithium5_ref/sign.c
new file mode 100644
index 000000000..16333eb84
--- /dev/null
+++ b/lib/liboqs/src/sig/dilithium/pqcrystals-dilithium_dilithium5_ref/sign.c
@@ -0,0 +1,337 @@
+#include <stdint.h>
+#include "params.h"
+#include "sign.h"
+#include "packing.h"
+#include "polyvec.h"
+#include "poly.h"
+#include "randombytes.h"
+#include "symmetric.h"
+#include "fips202.h"
+
+/*************************************************
+* Name: crypto_sign_keypair
+*
+* Description: Generates public and private key.
+*
+* Arguments: - uint8_t *pk: pointer to output public key (allocated
+* array of CRYPTO_PUBLICKEYBYTES bytes)
+* - uint8_t *sk: pointer to output private key (allocated
+* array of CRYPTO_SECRETKEYBYTES bytes)
+*
+* Returns 0 (success)
+**************************************************/
+int crypto_sign_keypair(uint8_t *pk, uint8_t *sk) {
+ uint8_t seedbuf[2*SEEDBYTES + CRHBYTES];
+ uint8_t tr[SEEDBYTES];
+ const uint8_t *rho, *rhoprime, *key;
+ polyvecl mat[K];
+ polyvecl s1, s1hat;
+ polyveck s2, t1, t0;
+
+ /* Get randomness for rho, rhoprime and key */
+ randombytes(seedbuf, SEEDBYTES);
+ shake256(seedbuf, 2*SEEDBYTES + CRHBYTES, seedbuf, SEEDBYTES);
+ rho = seedbuf;
+ rhoprime = rho + SEEDBYTES;
+ key = rhoprime + CRHBYTES;
+
+ /* Expand matrix */
+ polyvec_matrix_expand(mat, rho);
+
+ /* Sample short vectors s1 and s2 */
+ polyvecl_uniform_eta(&s1, rhoprime, 0);
+ polyveck_uniform_eta(&s2, rhoprime, L);
+
+ /* Matrix-vector multiplication */
+ s1hat = s1;
+ polyvecl_ntt(&s1hat);
+ polyvec_matrix_pointwise_montgomery(&t1, mat, &s1hat);
+ polyveck_reduce(&t1);
+ polyveck_invntt_tomont(&t1);
+
+ /* Add error vector s2 */
+ polyveck_add(&t1, &t1, &s2);
+
+ /* Extract t1 and write public key */
+ polyveck_caddq(&t1);
+ polyveck_power2round(&t1, &t0, &t1);
+ pack_pk(pk, rho, &t1);
+
+ /* Compute H(rho, t1) and write secret key */
+ shake256(tr, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES);
+ pack_sk(sk, rho, tr, key, &t0, &s1, &s2);
+
+ return 0;
+}
+
+/*************************************************
+* Name: crypto_sign_signature
+*
+* Description: Computes signature.
+*
+* Arguments: - uint8_t *sig: pointer to output signature (of length CRYPTO_BYTES)
+* - size_t *siglen: pointer to output length of signature
+* - uint8_t *m: pointer to message to be signed
+* - size_t mlen: length of message
+* - uint8_t *sk: pointer to bit-packed secret key
+*
+* Returns 0 (success)
+**************************************************/
+int crypto_sign_signature(uint8_t *sig,
+ size_t *siglen,
+ const uint8_t *m,
+ size_t mlen,
+ const uint8_t *sk)
+{
+ unsigned int n;
+ uint8_t seedbuf[3*SEEDBYTES + 2*CRHBYTES];
+ uint8_t *rho, *tr, *key, *mu, *rhoprime;
+ uint16_t nonce = 0;
+ polyvecl mat[K], s1, y, z;
+ polyveck t0, s2, w1, w0, h;
+ poly cp;
+ shake256incctx state;
+
+ rho = seedbuf;
+ tr = rho + SEEDBYTES;
+ key = tr + SEEDBYTES;
+ mu = key + SEEDBYTES;
+ rhoprime = mu + CRHBYTES;
+ unpack_sk(rho, tr, key, &t0, &s1, &s2, sk);
+
+ /* Compute CRH(tr, msg) */
+ shake256_inc_init(&state);
+ shake256_inc_absorb(&state, tr, SEEDBYTES);
+ shake256_inc_absorb(&state, m, mlen);
+ shake256_inc_finalize(&state);
+ shake256_inc_squeeze(mu, CRHBYTES, &state);
+
+#ifdef DILITHIUM_RANDOMIZED_SIGNING
+ randombytes(rhoprime, CRHBYTES);
+#else
+ shake256(rhoprime, CRHBYTES, key, SEEDBYTES + CRHBYTES);
+#endif
+
+ /* Expand matrix and transform vectors */
+ polyvec_matrix_expand(mat, rho);
+ polyvecl_ntt(&s1);
+ polyveck_ntt(&s2);
+ polyveck_ntt(&t0);
+
+rej:
+ /* Sample intermediate vector y */
+ polyvecl_uniform_gamma1(&y, rhoprime, nonce++);
+
+ /* Matrix-vector multiplication */
+ z = y;
+ polyvecl_ntt(&z);
+ polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
+ polyveck_reduce(&w1);
+ polyveck_invntt_tomont(&w1);
+
+ /* Decompose w and call the random oracle */
+ polyveck_caddq(&w1);
+ polyveck_decompose(&w1, &w0, &w1);
+ polyveck_pack_w1(sig, &w1);
+
+ shake256_inc_ctx_reset(&state);
+ shake256_inc_absorb(&state, mu, CRHBYTES);
+ shake256_inc_absorb(&state, sig, K*POLYW1_PACKEDBYTES);
+ shake256_inc_finalize(&state);
+ shake256_inc_squeeze(sig, SEEDBYTES, &state);
+ poly_challenge(&cp, sig);
+ poly_ntt(&cp);
+
+ /* Compute z, reject if it reveals secret */
+ polyvecl_pointwise_poly_montgomery(&z, &cp, &s1);
+ polyvecl_invntt_tomont(&z);
+ polyvecl_add(&z, &z, &y);
+ polyvecl_reduce(&z);
+ if(polyvecl_chknorm(&z, GAMMA1 - BETA))
+ goto rej;
+
+ /* Check that subtracting cs2 does not change high bits of w and low bits
+ * do not reveal secret information */
+ polyveck_pointwise_poly_montgomery(&h, &cp, &s2);
+ polyveck_invntt_tomont(&h);
+ polyveck_sub(&w0, &w0, &h);
+ polyveck_reduce(&w0);
+ if(polyveck_chknorm(&w0, GAMMA2 - BETA))
+ goto rej;
+
+ /* Compute hints for w1 */
+ polyveck_pointwise_poly_montgomery(&h, &cp, &t0);
+ polyveck_invntt_tomont(&h);
+ polyveck_reduce(&h);
+ if(polyveck_chknorm(&h, GAMMA2))
+ goto rej;
+
+ polyveck_add(&w0, &w0, &h);
+ n = polyveck_make_hint(&h, &w0, &w1);
+ if(n > OMEGA)
+ goto rej;
+
+ shake256_inc_ctx_release(&state);
+
+ /* Write signature */
+ pack_sig(sig, sig, &z, &h);
+ *siglen = CRYPTO_BYTES;
+ return 0;
+}
+
+/*************************************************
+* Name: crypto_sign
+*
+* Description: Compute signed message.
+*
+* Arguments: - uint8_t *sm: pointer to output signed message (allocated
+* array with CRYPTO_BYTES + mlen bytes),
+* can be equal to m
+* - size_t *smlen: pointer to output length of signed
+* message
+* - const uint8_t *m: pointer to message to be signed
+* - size_t mlen: length of message
+* - const uint8_t *sk: pointer to bit-packed secret key
+*
+* Returns 0 (success)
+**************************************************/
+int crypto_sign(uint8_t *sm,
+ size_t *smlen,
+ const uint8_t *m,
+ size_t mlen,
+ const uint8_t *sk)
+{
+ size_t i;
+
+ for(i = 0; i < mlen; ++i)
+ sm[CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i];
+ crypto_sign_signature(sm, smlen, sm + CRYPTO_BYTES, mlen, sk);
+ *smlen += mlen;
+ return 0;
+}
+
+/*************************************************
+* Name: crypto_sign_verify
+*
+* Description: Verifies signature.
+*
+* Arguments: - uint8_t *m: pointer to input signature
+* - size_t siglen: length of signature
+* - const uint8_t *m: pointer to message
+* - size_t mlen: length of message
+* - const uint8_t *pk: pointer to bit-packed public key
+*
+* Returns 0 if signature could be verified correctly and -1 otherwise
+**************************************************/
+int crypto_sign_verify(const uint8_t *sig,
+ size_t siglen,
+ const uint8_t *m,
+ size_t mlen,
+ const uint8_t *pk)
+{
+ unsigned int i;
+ uint8_t buf[K*POLYW1_PACKEDBYTES];
+ uint8_t rho[SEEDBYTES];
+ uint8_t mu[CRHBYTES];
+ uint8_t c[SEEDBYTES];
+ uint8_t c2[SEEDBYTES];
+ poly cp;
+ polyvecl mat[K], z;
+ polyveck t1, w1, h;
+ shake256incctx state;
+
+ if(siglen != CRYPTO_BYTES)
+ return -1;
+
+ unpack_pk(rho, &t1, pk);
+ if(unpack_sig(c, &z, &h, sig))
+ return -1;
+ if(polyvecl_chknorm(&z, GAMMA1 - BETA))
+ return -1;
+
+ /* Compute CRH(H(rho, t1), msg) */
+ shake256(mu, SEEDBYTES, pk, CRYPTO_PUBLICKEYBYTES);
+ shake256_inc_init(&state);
+ shake256_inc_absorb(&state, mu, SEEDBYTES);
+ shake256_inc_absorb(&state, m, mlen);
+ shake256_inc_finalize(&state);
+ shake256_inc_squeeze(mu, CRHBYTES, &state);
+
+ /* Matrix-vector multiplication; compute Az - c2^dt1 */
+ poly_challenge(&cp, c);
+ polyvec_matrix_expand(mat, rho);
+
+ polyvecl_ntt(&z);
+ polyvec_matrix_pointwise_montgomery(&w1, mat, &z);
+
+ poly_ntt(&cp);
+ polyveck_shiftl(&t1);
+ polyveck_ntt(&t1);
+ polyveck_pointwise_poly_montgomery(&t1, &cp, &t1);
+
+ polyveck_sub(&w1, &w1, &t1);
+ polyveck_reduce(&w1);
+ polyveck_invntt_tomont(&w1);
+
+ /* Reconstruct w1 */
+ polyveck_caddq(&w1);
+ polyveck_use_hint(&w1, &w1, &h);
+ polyveck_pack_w1(buf, &w1);
+
+ /* Call random oracle and verify challenge */
+ shake256_inc_ctx_reset(&state);
+ shake256_inc_absorb(&state, mu, CRHBYTES);
+ shake256_inc_absorb(&state, buf, K*POLYW1_PACKEDBYTES);
+ shake256_inc_finalize(&state);
+ shake256_inc_squeeze(c2, SEEDBYTES, &state);
+ shake256_inc_ctx_release(&state);
+ for(i = 0; i < SEEDBYTES; ++i)
+ if(c[i] != c2[i])
+ return -1;
+
+ return 0;
+}
+
+/*************************************************
+* Name: crypto_sign_open
+*
+* Description: Verify signed message.
+*
+* Arguments: - uint8_t *m: pointer to output message (allocated
+* array with smlen bytes), can be equal to sm
+* - size_t *mlen: pointer to output length of message
+* - const uint8_t *sm: pointer to signed message
+* - size_t smlen: length of signed message
+* - const uint8_t *pk: pointer to bit-packed public key
+*
+* Returns 0 if signed message could be verified correctly and -1 otherwise
+**************************************************/
+int crypto_sign_open(uint8_t *m,
+ size_t *mlen,
+ const uint8_t *sm,
+ size_t smlen,
+ const uint8_t *pk)
+{
+ size_t i;
+
+ if(smlen < CRYPTO_BYTES)
+ goto badsig;
+
+ *mlen = smlen - CRYPTO_BYTES;
+ if(crypto_sign_verify(sm, CRYPTO_BYTES, sm + CRYPTO_BYTES, *mlen, pk))
+ goto badsig;
+ else {
+ /* All good, copy msg, return 0 */
+ for(i = 0; i < *mlen; ++i)
+ m[i] = sm[CRYPTO_BYTES + i];
+ return 0;
+ }
+
+badsig:
+ /* Signature verification failed */
+ *mlen = -1;
+ for(i = 0; i < smlen; ++i)
+ m[i] = 0;
+
+ return -1;
+}