Ver código fonte

picnic3L1: needed updates

kris/add_picnic
Henry Case 3 anos atrás
pai
commit
20cc113042
15 arquivos alterados com 55 adições e 1976 exclusões
  1. +1
    -0
      CMakeLists.txt
  2. +2
    -1
      public/pqc/pqc.h
  3. +1
    -0
      src/capi/schemes.h
  4. +0
    -277
      src/sign/picnic/picnic3l1/clean/NIST-KATs/PQCgenKAT_sign.c
  5. +0
    -222
      src/sign/picnic/picnic3l1/clean/NIST-KATs/rng.c
  6. +0
    -55
      src/sign/picnic/picnic3l1/clean/NIST-KATs/rng.h
  7. +22
    -57
      src/sign/picnic/picnic3l1/clean/api.c
  8. +14
    -12
      src/sign/picnic/picnic3l1/clean/api.h
  9. +0
    -4
      src/sign/picnic/picnic3l1/clean/hash.c
  10. +0
    -4
      src/sign/picnic/picnic3l1/clean/hash.h
  11. +2
    -15
      src/sign/picnic/picnic3l1/clean/picnic.h
  12. +10
    -55
      src/sign/picnic/picnic3l1/clean/picnic_impl.c
  13. +0
    -414
      src/sign/picnic/picnic3l1/clean/tree_test.c
  14. +0
    -857
      src/sign/picnic/picnic3l1/clean/unit_test.c
  15. +3
    -3
      test/ut.cpp

+ 1
- 0
CMakeLists.txt Ver arquivo

@@ -144,6 +144,7 @@ add_subdirectory(src/sign/sphincs/sphincs-sha256-256s-robust/clean)
add_subdirectory(src/sign/sphincs/sphincs-sha256-128s-robust/clean)
add_subdirectory(src/sign/sphincs/sphincs-sha256-128f-simple/clean)
add_subdirectory(src/sign/sphincs/sphincs-sha256-192f-robust/clean)
add_subdirectory(src/sign/picnic/picnic3l1/clean)

add_subdirectory(src/kem/kyber/kyber512/clean)
add_subdirectory(src/kem/kyber/kyber768/clean)


+ 2
- 1
public/pqc/pqc.h Ver arquivo

@@ -41,7 +41,8 @@ extern "C" {
_(SPHINCSSHA256256SROBUST) \
_(SPHINCSSHA256128SROBUST) \
_(SPHINCSSHA256128FSIMPLE) \
_(SPHINCSSHA256192FROBUST)
_(SPHINCSSHA256192FROBUST) \
_(PICNIC3L1)

// defines supported kem algorithm list
#define PQC_SUPPORTED_KEMS(_)\


+ 1
- 0
src/capi/schemes.h Ver arquivo

@@ -63,6 +63,7 @@
#include "sign/dilithium/dilithium3/avx2/api.h"
#include "sign/dilithium/dilithium5/clean/api.h"
#include "sign/dilithium/dilithium5/avx2/api.h"
#include "sign/picnic/picnic3l1/clean/api.h"
#include "kem/ntru/ntruhps4096821/clean/api.h"
#include "kem/ntru/ntruhps4096821/avx2/api.h"
#include "kem/ntru/ntruhps2048509/clean/api.h"


+ 0
- 277
src/sign/picnic/picnic3l1/clean/NIST-KATs/PQCgenKAT_sign.c Ver arquivo

@@ -1,277 +0,0 @@

//
// PQCgenKAT_sign.c
//
// Created by Bassham, Lawrence E (Fed) on 8/29/17.
// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "rng.h"
#include "api.h"

#define MAX_MARKER_LEN 50

#define KAT_SUCCESS 0
#define KAT_FILE_OPEN_ERROR -1
#define KAT_DATA_ERROR -3
#define KAT_CRYPTO_FAILURE -4

int FindMarker(FILE *infile, const char *marker);
int ReadHex(FILE *infile, unsigned char *A, int Length, char *str);
void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L);

char AlgName[] = "My Alg Name";
static const char* l1 = "L1";
static const char* l3 = "L3";
static const char* l5 = "L5";
static const char* unknown = "UNKNOWN_PARAM_SET";

int
main()
{
char fn_req[64], fn_rsp[64];
FILE *fp_req, *fp_rsp;
unsigned char seed[48];
unsigned char msg[3300];
unsigned char entropy_input[48];
unsigned char *m, *sm, *m1;
unsigned long long mlen, smlen, mlen1;
int count;
int done;
unsigned char pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES];
int ret_val;
const char* suffix;


switch(((CRYPTO_PUBLICKEYBYTES - 1)/2)*8) {
case 128:
case 136: // 129-bit keys, rounded to next byte
suffix = l1;
break;
case 192:
suffix = l3;
break;
case 256:
suffix = l5;
break;
default:
suffix = unknown;
break;
}

// Create the REQUEST file
sprintf(fn_req, "PQCsignKAT_%s.req", suffix);
if ( (fp_req = fopen(fn_req, "w")) == NULL ) {
printf("Couldn't open <%s> for write\n", fn_req);
return KAT_FILE_OPEN_ERROR;
}
sprintf(fn_rsp, "PQCsignKAT_%s.rsp", suffix);
if ( (fp_rsp = fopen(fn_rsp, "w")) == NULL ) {
printf("Couldn't open <%s> for write\n", fn_rsp);
return KAT_FILE_OPEN_ERROR;
}
for (int i=0; i<48; i++)
entropy_input[i] = i;

NIST_randombytes_init(entropy_input, NULL, 256);
for (int i=0; i<100; i++) {
fprintf(fp_req, "count = %d\n", i);
NIST_randombytes(seed, 48);
fprintBstr(fp_req, "seed = ", seed, 48);
mlen = 33*(i+1);
fprintf(fp_req, "mlen = %llu\n", mlen);
NIST_randombytes(msg, mlen);
fprintBstr(fp_req, "msg = ", msg, mlen);
fprintf(fp_req, "pk =\n");
fprintf(fp_req, "sk =\n");
fprintf(fp_req, "smlen =\n");
fprintf(fp_req, "sm =\n\n");
}
fclose(fp_req);
//Create the RESPONSE file based on what's in the REQUEST file
if ( (fp_req = fopen(fn_req, "r")) == NULL ) {
printf("Couldn't open <%s> for read\n", fn_req);
return KAT_FILE_OPEN_ERROR;
}
fprintf(fp_rsp, "# %s\n\n", CRYPTO_ALGNAME);
done = 0;
do {
if ( FindMarker(fp_req, "count = ") )
fscanf(fp_req, "%d", &count);
else {
done = 1;
break;
}
fprintf(fp_rsp, "count = %d\n", count);
if ( !ReadHex(fp_req, seed, 48, "seed = ") ) {
printf("ERROR: unable to read 'seed' from <%s>\n", fn_req);
return KAT_DATA_ERROR;
}
fprintBstr(fp_rsp, "seed = ", seed, 48);
NIST_randombytes_init(seed, NULL, 256);
if ( FindMarker(fp_req, "mlen = ") )
fscanf(fp_req, "%llu", &mlen);
else {
printf("ERROR: unable to read 'mlen' from <%s>\n", fn_req);
return KAT_DATA_ERROR;
}
fprintf(fp_rsp, "mlen = %llu\n", mlen);
m = (unsigned char *)calloc(mlen, sizeof(unsigned char));
m1 = (unsigned char *)calloc(mlen, sizeof(unsigned char));
sm = (unsigned char *)calloc(mlen+CRYPTO_BYTES, sizeof(unsigned char));
if ( !ReadHex(fp_req, m, (int)mlen, "msg = ") ) {
printf("ERROR: unable to read 'msg' from <%s>\n", fn_req);
return KAT_DATA_ERROR;
}
fprintBstr(fp_rsp, "msg = ", m, mlen);
// Generate the public/private keypair
if ( (ret_val = crypto_sign_keypair(pk, sk)) != 0) {
printf("crypto_sign_keypair returned <%d>\n", ret_val);
return KAT_CRYPTO_FAILURE;
}
fprintBstr(fp_rsp, "pk = ", pk, CRYPTO_PUBLICKEYBYTES);
fprintBstr(fp_rsp, "sk = ", sk, CRYPTO_SECRETKEYBYTES);
if ( (ret_val = crypto_sign(sm, &smlen, m, mlen, sk)) != 0) {
printf("crypto_sign returned <%d>\n", ret_val);
return KAT_CRYPTO_FAILURE;
}
fprintf(fp_rsp, "smlen = %llu\n", smlen);
fprintBstr(fp_rsp, "sm = ", sm, smlen);
fprintf(fp_rsp, "\n");
if ( (ret_val = crypto_sign_open(m1, &mlen1, sm, smlen, pk)) != 0) {
printf("crypto_sign_open returned <%d>\n", ret_val);
return KAT_CRYPTO_FAILURE;
}
if ( mlen != mlen1 ) {
printf("crypto_sign_open returned bad 'mlen': Got <%llu>, expected <%llu>\n", mlen1, mlen);
return KAT_CRYPTO_FAILURE;
}
if ( memcmp(m, m1, mlen) ) {
printf("crypto_sign_open returned bad 'm' value\n");
return KAT_CRYPTO_FAILURE;
}
free(m);
free(m1);
free(sm);

} while ( !done );
fclose(fp_req);
fclose(fp_rsp);

return KAT_SUCCESS;
}

//
// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.)
//
int
FindMarker(FILE *infile, const char *marker)
{
char line[MAX_MARKER_LEN];
int i, len;

len = (int)strlen(marker);
if ( len > MAX_MARKER_LEN-1 )
len = MAX_MARKER_LEN-1;

for ( i=0; i<len; i++ )
if ( (line[i] = fgetc(infile)) == EOF )
return 0;
line[len] = '\0';

while ( 1 ) {
if ( !strncmp(line, marker, len) )
return 1;

for ( i=0; i<len-1; i++ )
line[i] = line[i+1];
if ( (line[len-1] = fgetc(infile)) == EOF )
return 0;
line[len] = '\0';
}

// shouldn't get here
return 0;
}

//
// ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.)
//
int
ReadHex(FILE *infile, unsigned char *A, int Length, char *str)
{
int i, ch, started;
unsigned char ich;

if ( Length == 0 ) {
A[0] = 0x00;
return 1;
}
memset(A, 0x00, Length);
started = 0;
if ( FindMarker(infile, str) )
while ( (ch = fgetc(infile)) != EOF ) {
if ( !isxdigit(ch) ) {
if ( !started ) {
if ( ch == '\n' )
break;
else
continue;
}
else
break;
}
started = 1;
if ( (ch >= '0') && (ch <= '9') )
ich = ch - '0';
else if ( (ch >= 'A') && (ch <= 'F') )
ich = ch - 'A' + 10;
else if ( (ch >= 'a') && (ch <= 'f') )
ich = ch - 'a' + 10;
else // shouldn't ever get here
ich = 0;
for ( i=0; i<Length-1; i++ )
A[i] = (A[i] << 4) | (A[i+1] >> 4);
A[Length-1] = (A[Length-1] << 4) | ich;
}
else
return 0;

return 1;
}

void
fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L)
{
unsigned long long i;

fprintf(fp, "%s", S);

for ( i=0; i<L; i++ )
fprintf(fp, "%02X", A[i]);

if ( L == 0 )
fprintf(fp, "00");

fprintf(fp, "\n");
}


+ 0
- 222
src/sign/picnic/picnic3l1/clean/NIST-KATs/rng.c Ver arquivo

@@ -1,222 +0,0 @@
//
// rng.c
//
// Created by Bassham, Lawrence E (Fed) on 8/29/17.
// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
//

#include <string.h>
#include "rng.h"
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>

AES256_CTR_DRBG_struct DRBG_ctx;

void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer);

/*
seedexpander_init()
ctx - stores the current state of an instance of the seed expander
seed - a 32 byte random value
diversifier - an 8 byte diversifier
maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier
*/
int
seedexpander_init(AES_XOF_struct *ctx,
unsigned char *seed,
unsigned char *diversifier,
unsigned long maxlen)
{
if ( maxlen >= 0x100000000 )
return RNG_BAD_MAXLEN;
ctx->length_remaining = maxlen;
memcpy(ctx->key, seed, 32);
memcpy(ctx->ctr, diversifier, 8);
ctx->ctr[11] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[10] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[9] = maxlen % 256;
maxlen >>= 8;
ctx->ctr[8] = maxlen % 256;
memset(ctx->ctr+12, 0x00, 4);
ctx->buffer_pos = 16;
memset(ctx->buffer, 0x00, 16);
return RNG_SUCCESS;
}

/*
seedexpander()
ctx - stores the current state of an instance of the seed expander
x - returns the XOF data
xlen - number of bytes to return
*/
int
seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen)
{
unsigned long offset;
if ( x == NULL )
return RNG_BAD_OUTBUF;
if ( xlen >= ctx->length_remaining )
return RNG_BAD_REQ_LEN;
ctx->length_remaining -= xlen;
offset = 0;
while ( xlen > 0 ) {
if ( xlen <= (16-ctx->buffer_pos) ) { // buffer has what we need
memcpy(x+offset, ctx->buffer+ctx->buffer_pos, xlen);
ctx->buffer_pos += xlen;
return RNG_SUCCESS;
}
// take what's in the buffer
memcpy(x+offset, ctx->buffer+ctx->buffer_pos, 16-ctx->buffer_pos);
xlen -= 16-ctx->buffer_pos;
offset += 16-ctx->buffer_pos;
AES256_ECB(ctx->key, ctx->ctr, ctx->buffer);
ctx->buffer_pos = 0;
//increment the counter
for (int i=15; i>=12; i--) {
if ( ctx->ctr[i] == 0xff )
ctx->ctr[i] = 0x00;
else {
ctx->ctr[i]++;
break;
}
}
}
return RNG_SUCCESS;
}


void handleErrors(void)
{
ERR_print_errors_fp(stderr);
abort();
}

// Use whatever AES implementation you have. This uses AES from openSSL library
// key - 256-bit AES key
// ctr - a 128-bit plaintext value
// buffer - a 128-bit ciphertext value
void
AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
handleErrors();
if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16))
handleErrors();
ciphertext_len = len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
}

void
NIST_randombytes_init(unsigned char *entropy_input,
unsigned char *personalization_string,
int security_strength)
{
unsigned char seed_material[48];
memcpy(seed_material, entropy_input, 48);
if (personalization_string)
for (int i=0; i<48; i++)
seed_material[i] ^= personalization_string[i];
memset(DRBG_ctx.Key, 0x00, 32);
memset(DRBG_ctx.V, 0x00, 16);
AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
DRBG_ctx.reseed_counter = 1;
}

int
NIST_randombytes(unsigned char *x, unsigned long long xlen)
{
unsigned char block[16];
int i = 0;
while ( xlen > 0 ) {
//increment V
for (int j=15; j>=0; j--) {
if ( DRBG_ctx.V[j] == 0xff )
DRBG_ctx.V[j] = 0x00;
else {
DRBG_ctx.V[j]++;
break;
}
}
AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
if ( xlen > 15 ) {
memcpy(x+i, block, 16);
i += 16;
xlen -= 16;
}
else {
memcpy(x+i, block, xlen);
xlen = 0;
}
}
AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
DRBG_ctx.reseed_counter++;
return RNG_SUCCESS;
}

void
AES256_CTR_DRBG_Update(unsigned char *provided_data,
unsigned char *Key,
unsigned char *V)
{
unsigned char temp[48];
for (int i=0; i<3; i++) {
//increment V
for (int j=15; j>=0; j--) {
if ( V[j] == 0xff )
V[j] = 0x00;
else {
V[j]++;
break;
}
}
AES256_ECB(Key, V, temp+16*i);
}
if ( provided_data != NULL )
for (int i=0; i<48; i++)
temp[i] ^= provided_data[i];
memcpy(Key, temp, 32);
memcpy(V, temp+32, 16);
}










+ 0
- 55
src/sign/picnic/picnic3l1/clean/NIST-KATs/rng.h Ver arquivo

@@ -1,55 +0,0 @@
//
// rng.h
//
// Created by Bassham, Lawrence E (Fed) on 8/29/17.
// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
//

#ifndef rng_h
#define rng_h

#include <stdio.h>

#define RNG_SUCCESS 0
#define RNG_BAD_MAXLEN -1
#define RNG_BAD_OUTBUF -2
#define RNG_BAD_REQ_LEN -3

typedef struct {
unsigned char buffer[16];
int buffer_pos;
unsigned long length_remaining;
unsigned char key[32];
unsigned char ctr[16];
} AES_XOF_struct;

typedef struct {
unsigned char Key[32];
unsigned char V[16];
int reseed_counter;
} AES256_CTR_DRBG_struct;


void
AES256_CTR_DRBG_Update(unsigned char *provided_data,
unsigned char *Key,
unsigned char *V);

int
seedexpander_init(AES_XOF_struct *ctx,
unsigned char *seed,
unsigned char *diversifier,
unsigned long maxlen);

int
seedexpander(AES_XOF_struct *ctx, unsigned char *x, unsigned long xlen);

void
NIST_randombytes_init(unsigned char *entropy_input,
unsigned char *personalization_string,
int security_strength);

int
NIST_randombytes(unsigned char *x, unsigned long long xlen);

#endif /* rng_h */

+ 22
- 57
src/sign/picnic/picnic3l1/clean/api.c Ver arquivo

@@ -13,14 +13,10 @@

#include "api.h"

#ifdef SUPERCOP
#include "crypto_sign.h"
#endif

#include <string.h>

//#ifndef htole32
static uint32_t bswap32(uint32_t x)
static uint32_t bswap32(uint32_t x)
{
return ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) | ((x & 0x0000ff00) << 8) |
((x & 0x000000ff) << 24);
@@ -36,42 +32,42 @@ static int isBigEndianSystem()
return 0;
}

static uint32_t htole32_portable(uint32_t x)
static uint32_t htole32_portable(uint32_t x)
{
if(isBigEndianSystem()) {
return bswap32(x);
}
return x;
}
static uint32_t le32toh_portable(uint32_t x)
static uint32_t le32toh_portable(uint32_t x)
{
if(isBigEndianSystem()) {
return bswap32(x);
}
return x;
}
}

//#endif

picnic_params_t params = Picnic3_L1;
picnic_params_t PQCLEAN_PICNIC3L1_CLEAN_params = Picnic3_L1;

int crypto_sign_keypair(unsigned char *pk, unsigned char *sk)
int PQCLEAN_PICNIC3L1_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk)
{
picnic_publickey_t pubkey;
picnic_privatekey_t secret;

int ret = picnic_keygen(params, &pubkey, &secret);
int ret = picnic_keygen(PQCLEAN_PICNIC3L1_CLEAN_params, &pubkey, &secret);

if (ret != 0) {
return ret;
}

ret = picnic_write_public_key(&pubkey, pk, CRYPTO_PUBLICKEYBYTES);
ret = picnic_write_public_key(&pubkey, pk, PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_PUBLICKEYBYTES);
if (ret < 1) {
return ret;
}

ret = picnic_write_private_key(&secret, sk, CRYPTO_SECRETKEYBYTES);
ret = picnic_write_private_key(&secret, sk, PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_SECRETKEYBYTES);
if (ret < 1) {
return ret;
}
@@ -79,67 +75,36 @@ int crypto_sign_keypair(unsigned char *pk, unsigned char *sk)
return 0;
}

int crypto_sign(unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *sk)
int PQCLEAN_PICNIC3L1_CLEAN_crypto_sign_signature(
uint8_t *sm, size_t *smlen,
const uint8_t *m, size_t mlen, const uint8_t *sk)
{
picnic_privatekey_t secret;

int ret = picnic_read_private_key(&secret, sk, CRYPTO_SECRETKEYBYTES);

if (ret != 0) {
return ret;
if (picnic_read_private_key(&secret, sk, PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_SECRETKEYBYTES)) {
return -2;
}

/* Write out sm as
* 4-byte integer signature length | message | signature
*/
size_t signature_len = CRYPTO_BYTES;
ret = picnic_sign(&secret, m, mlen, sm + mlen + 4, &signature_len);
if (ret != 0) {
return ret;
}
if (signature_len > CRYPTO_BYTES) {
return -1;
*smlen = PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_BYTES;
if (picnic_sign(&secret, m, mlen, sm, smlen)) {
return -2;
}

*smlen = 4 + mlen + signature_len;
signature_len = htole32_portable(signature_len);
memcpy(sm, (uint8_t*)&signature_len, 4);
memcpy(sm + 4, m, mlen);

return 0;
}

int crypto_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk)
int PQCLEAN_PICNIC3L1_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk)
{
picnic_publickey_t pubkey;

int ret = picnic_read_public_key(&pubkey, pk, CRYPTO_PUBLICKEYBYTES);

if (ret != 0) {
return -2;
}

uint32_t signature_len;
memcpy((uint8_t*)&signature_len, sm, 4);
signature_len = le32toh_portable(signature_len);
if (signature_len > smlen - 1 - 4) {
if (picnic_read_public_key(&pubkey, pk, PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_PUBLICKEYBYTES)) {
return -2;
}

size_t message_len = smlen - signature_len - 4;
ret = picnic_verify(&pubkey, sm + 4, message_len,
sm + 4 + message_len, signature_len);
if (ret != 0) {
if (picnic_verify(&pubkey, m, mlen, sig, siglen)) {
return -1;
}

memmove(m, sm + 4, message_len);
*mlen = message_len;

return 0;
}


+ 14
- 12
src/sign/picnic/picnic3l1/clean/api.h Ver arquivo

@@ -16,25 +16,27 @@
#ifndef api_h
#define api_h

#include <stdint.h>
#include <stddef.h>

// Set these three values apropriately for your algorithm
#define CRYPTO_SECRETKEYBYTES 52
#define CRYPTO_PUBLICKEYBYTES 35
#define CRYPTO_BYTES 14612
#define PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_SECRETKEYBYTES 52
#define PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_PUBLICKEYBYTES 35
#define PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_BYTES 14612

// Change the algorithm name
#define CRYPTO_ALGNAME "picnic3l1"
#define PQCLEAN_PICNIC3L1_CLEAN_CRYPTO_ALGNAME "picnic3l1"

int
crypto_sign_keypair(unsigned char *pk, unsigned char *sk);
PQCLEAN_PICNIC3L1_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk);

int
crypto_sign(unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen,
const unsigned char *sk);
PQCLEAN_PICNIC3L1_CLEAN_crypto_sign_signature(
uint8_t *sig, size_t *siglen,
const uint8_t *m, size_t mlen, const uint8_t *sk);

int
crypto_sign_open(unsigned char *m, unsigned long long *mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk);
int PQCLEAN_PICNIC3L1_CLEAN_crypto_sign_verify(
const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen, const uint8_t *pk);

#endif /* api_h */

+ 0
- 4
src/sign/picnic/picnic3l1/clean/hash.c Ver arquivo

@@ -12,11 +12,7 @@
#include "hash.h"
#include <stdio.h>
#include <assert.h>
#if !defined(SUPERCOP)
#include "sha3/brg_endian.h"
#else
#include <libkeccak.a.headers/brg_endian.h>
#endif

void HashUpdate(HashInstance* ctx, const uint8_t* data, size_t byteLen)
{


+ 0
- 4
src/sign/picnic/picnic3l1/clean/hash.h Ver arquivo

@@ -12,11 +12,7 @@
#ifndef HASH_H
#define HASH_H

#ifndef SUPERCOP
#include "sha3/KeccakHash.h"
#else
#include <libkeccak.a.headers/KeccakHash.h>
#endif
#include "picnic_impl.h"

/* Wrap the Keccak API, checking return values, logging errors, and working


+ 2
- 15
src/sign/picnic/picnic3l1/clean/picnic.h Ver arquivo

@@ -31,6 +31,7 @@ extern "C" {

#include <stdint.h>
#include <stdlib.h>
#include "common/randombytes.h"

/* Maximum lengths in bytes */
#define PICNIC_MAX_LOWMC_BLOCK_SIZE 32
@@ -224,21 +225,7 @@ int picnic_validate_keypair(const picnic_privatekey_t* privatekey, const picnic_
* random_bytes_default, and change the definition of
* picnic_random_bytes.
*/
#ifdef USE_NIST_KAT_INSECURE_RNG
/* For the NIST submission, when generating known-answer-tests (KATs), we
* must use an RNG with a fixed seed so that re-running the program to
* generate KATs prduces the same results. The function randombytes is
* provided by NIST, in the file rng.c. */
#include "NIST-KATs/rng.h"
#define picnic_random_bytes NIST_randombytes
#elif SUPERCOP
int random_bytes_supercop(uint8_t* buf, size_t len);
#define picnic_random_bytes random_bytes_supercop
#else
#define PICNIC_BUILD_DEFAULT_RNG 1
#define picnic_random_bytes random_bytes_default
#endif

#define picnic_random_bytes randombytes

/** Parse the signature and print the individual parts. Used when creating test vectors */
void print_signature(const uint8_t* sigBytes, size_t sigBytesLen, picnic_params_t picnic_params);


+ 10
- 55
src/sign/picnic/picnic3l1/clean/picnic_impl.c Ver arquivo

@@ -122,7 +122,7 @@ void xor_three(uint32_t* output, const uint32_t* in1, const uint32_t* in2, const
output[i] = in1[i] ^ in2[i] ^ in3[i];
}
for(size_t i = wholeWords*sizeof(uint32_t); i < lenBytes; i++) {
out[i] = i1[i] ^ i2[i] ^ i3[i];
out[i] = i1[i] ^ i2[i] ^ i3[i];
}
}

@@ -138,13 +138,13 @@ void matrix_mul(
{
// Use temp to correctly handle the case when state = output
uint8_t prod;
uint32_t temp[LOWMC_MAX_WORDS];
uint32_t temp[LOWMC_MAX_WORDS];
temp[params->stateSizeWords-1] = 0;

for (uint32_t i = 0; i < params->stateSizeBits; i++) {
prod = 0;
for (uint32_t j = 0; j < params->stateSizeBits; j++) {
size_t index = i * params->stateSizeWords*WORD_SIZE_BITS + j;
size_t index = i * params->stateSizeWords*WORD_SIZE_BITS + j;
prod ^= (getBitFromWordArray(state,j) & getBitFromWordArray(matrix, index));
}
setBit((uint8_t*)temp, i, prod);
@@ -666,7 +666,7 @@ int verify(signature_t* sig, const uint32_t* pubKey, const uint32_t* plaintext,

VIEW_OUTPUTS(i, challenge) = view1s[i].outputShare;
VIEW_OUTPUTS(i, (challenge + 1) % 3) = view2s[i].outputShare;
xor_three(view3Output, view1s[i].outputShare, view2s[i].outputShare, pubKey, params->stateSizeBytes);
xor_three(view3Output, view1s[i].outputShare, view2s[i].outputShare, pubKey, params->stateSizeBytes);
VIEW_OUTPUTS(i, (challenge + 2) % 3) = view3Output;
view3Output = (uint32_t*) ((uint8_t*)view3Output + params->stateSizeBytes);
}
@@ -756,9 +756,9 @@ void print_reconstruct(const char* label, uint32_t* s[3], size_t lengthBytes)
xor_three(temp, s[0], s[1], s[2], lengthBytes);
#if 0
printf("\n");
printHex("s0", (uint8_t*)s[0], lengthBytes);
printHex("s1", (uint8_t*)s[1], lengthBytes);
printHex("s2", (uint8_t*)s[2], lengthBytes);
printHex("s0", (uint8_t*)s[0], lengthBytes);
printHex("s1", (uint8_t*)s[1], lengthBytes);
printHex("s2", (uint8_t*)s[2], lengthBytes);
#endif
printHex(label, (uint8_t*)temp, lengthBytes);
}
@@ -799,51 +799,6 @@ void mpc_LowMC(randomTape_t* tapes, view_t views[3],
}
}

#ifdef PICNIC_BUILD_DEFAULT_RNG
int random_bytes_default(uint8_t* buf, size_t len)
{

#if defined(__LINUX__)
FILE* urandom = fopen("/dev/urandom", "r");
if (urandom == NULL) {
return -1;
}

if (fread(buf, sizeof(uint8_t), len, urandom) != len) {
return -2;
}
fclose(urandom);

return 0;

#elif defined(__WINDOWS__)
#ifndef ULONG_MAX
#define ULONG_MAX 0xFFFFFFFFULL
#endif
if (len > ULONG_MAX) {
return -3;
}

if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
return -4;
}
return 0;
#else
#error "If neither __LINUX__ or __WINDOWS__ are defined, you'll have to implement the random number generator"
#endif

}
#endif /* PICNIC_BUILD_DEFAULT_RNG */

#ifdef SUPERCOP
#include "randombytes.h"
int random_bytes_supercop(uint8_t* buf, size_t len)
{
randombytes(buf, len); /* returns void */
return 0;
}
#endif /* SUPERCOP */

seeds_t* computeSeeds(uint32_t* privateKey, uint32_t*
publicKey, uint32_t* plaintext, const uint8_t* message, size_t messageByteLength, paramset_t* params)
{
@@ -952,7 +907,7 @@ int sign_picnic1(uint32_t* privateKey, uint32_t* pubKey, uint32_t* plaintext, co


#if 0 /* Self-test, verify the signature we just created */
printf("\n-----------\n");
printf("\n-----------\n");
int ret = verify(sig, pubKey, plaintext, message, messageByteLength, params);
if(ret != EXIT_SUCCESS) {
printf("Self-test of signature verification failed\n");
@@ -961,7 +916,7 @@ int sign_picnic1(uint32_t* privateKey, uint32_t* pubKey, uint32_t* plaintext, co
else {
printf("Self-test succeeded\n");
}
printf("\n-----------\n");
printf("\n-----------\n");
#endif


@@ -1068,7 +1023,7 @@ static int isChallengeValid(uint8_t* challengeBits, paramset_t* params)

int arePaddingBitsZero(uint8_t* data, size_t bitLength)
{
size_t byteLength = numBytes(bitLength);
size_t byteLength = numBytes(bitLength);
for (size_t i = bitLength; i < byteLength * 8; i++) {
uint8_t bit_i = getBit(data, i);
if (bit_i != 0) {


+ 0
- 414
src/sign/picnic/picnic3l1/clean/tree_test.c Ver arquivo

@@ -1,414 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include <limits.h>

#include "picnic_types.h"
#include "hash.h"
#include "picnic.h"
#include "picnic_impl.h"
#include "tree.h"

static int contains(uint16_t* list, size_t len, uint16_t value)
{
for(size_t i = 0; i < len; i++) {
if(list[i] == value) {
return 1;
}
}
return 0;
}



int get_param_set(picnic_params_t picnicParams, paramset_t* paramset);

void printTreeInfo(const char* label, tree_t* tree)
{
printf("%s:\n", label);
printf("tree->depth = %lu\n", tree->depth);
printHex("haveNode", tree->haveNode, tree->numNodes); ; // If we have the seed or hash for node i, haveNode[i] is 1
printf("tree->numNodes = %lu\n", tree->numNodes);
printf("tree->numLeaves = %lu\n", tree->numLeaves);
}

void printTree(const char* label, tree_t* tree)
{
printf("%s:\n", label);
for(size_t i = 0; i < tree->numNodes; i++) {
printf("node[%02lu] (have=%d, exists=%d) ", i, tree->haveNode[i], tree->exists[i]);
printHex("", tree->nodes[i], tree->dataSize);
}
}


int runSeedTest(uint16_t* hideList, size_t hideListSize, size_t numLeaves, paramset_t* params)
{
uint8_t iSeed[16];
uint8_t salt[16];
size_t repIndex = 19;
int freeHideList = 0;
int ret = 1;

if(numLeaves < hideListSize - 1) {
printf("%s invalid input (numLeaves = %lu, hideListSize = %lu)\n", __func__, numLeaves, hideListSize);
return 0;
}

if(hideList == NULL) {
hideList = malloc(hideListSize*sizeof(uint16_t));
freeHideList = 1;
uint16_t val;
for(size_t i = 0; i < hideListSize; i++) {
do{
val = ((uint16_t)rand()) % numLeaves;
} while(contains(hideList, i, val));
hideList[i] = val;
}
}

#if 0
printf("hideList: ");
for(size_t i = 0; i < hideListSize; i++) {
printf("%u, ", hideList[i]);
}
printf("\n");
#endif

memset(iSeed, 0x07, sizeof(iSeed));
memset(salt, 0x09, sizeof(salt));

//printf("%s: Generating seeds\n", __func__);
tree_t* tree = generateSeeds(numLeaves, iSeed, salt, repIndex, params);
tree_t* tree2 = createTree(numLeaves, params->seedSizeBytes);

#if 0
printTree("tree", tree);
#endif


size_t initialOutputSize = (tree->numLeaves)*params->seedSizeBytes;
uint8_t* output = malloc(initialOutputSize);

size_t expectedOutputLen = revealSeedsSize(numLeaves, hideList, hideListSize, params);
if(hideListSize > 0 && expectedOutputLen == 0) {
printf("Failed to get exepctedOutputLen\n");
ret = 0;
goto Exit;
}
if(expectedOutputLen % params->seedSizeBytes != 0) {
printf("ExepctedOutputLen is not a multiple of the seed length\n");
ret = 0;
goto Exit;
}

//printf("%s: Revealing seeds\n", __func__);
size_t outputLen = revealSeeds(tree, hideList, hideListSize, output, initialOutputSize, params);
if(outputLen == 0) {
printf("Failed to revealSeeds, output buffer too small\n");
ret = 0;
goto Exit;
}

if(outputLen != expectedOutputLen) {
printf("Expected output lengthd doesn't match output length\n");
ret = 0;
goto Exit;
}

#if 0
printf("%s: numLeaves = %lu, revealed %lu\n", __func__, tree->numLeaves, outputLen/tree->dataSize);
#endif

if(params->numOpenedRounds*ceil_log2(params->numMPCRounds/params->numOpenedRounds) < outputLen/tree->dataSize) {
printf("%s: Output length is larger than expected\n", __func__);
ret = 0;
goto Exit;
}


//printf("%s: Reconstructing seeds\n", __func__);
int res = reconstructSeeds(tree2, hideList, hideListSize, output, outputLen, salt, repIndex, params);
if(res != 0) {
printf("%s: Reconstructing seeds FAILED\n", __func__);
ret = 0;
goto Exit;
}

#if 0
printf("seeds in reconstructed tree:\n");
printSeeds(tree2->nodes[0], params->seedSizeBytes, 15 );
#endif

// Check that we have the correct seeds, and that they match
size_t firstLeaf = tree->numNodes - tree->numLeaves;
for(size_t i = firstLeaf; i < tree->numNodes; i++) {
if(contains(hideList, hideListSize, i - firstLeaf)) {
if(tree2->haveNode[i]) {
printf("%s FAIL: reconstructed tree contains a seed that should have been hidden, node %lu (leaf node %lu)\n", __func__, i, i - firstLeaf);
printHex("tree->nodes[i] ", tree->nodes[i], params->seedSizeBytes);
printHex("tree2->nodes[i]", tree2->nodes[i], params->seedSizeBytes);
ret = 0;
goto Exit;
}
}
else {

if(!tree2->haveNode[i]){
printf("%s FAIL: expected to have seed for node %lu, but don't\n", __func__, i);
ret = 0;
goto Exit;
}
if(!tree->haveNode[i]) {
printf("%s FAIL: initial tree is missing node %lu -- not contructed properly?\n", __func__, i);
//printTreeInfo("tree", tree);
ret = 0;
goto Exit;
}

if(memcmp(tree->nodes[i], tree2->nodes[i], params->seedSizeBytes) != 0) {
printf("%s FAIL: reconstructed tree has an incorrect seed node %lu\n", __func__, i);
ret = 0;
goto Exit;
}
}
}

Exit:
if(freeHideList) {
free(hideList);
}
free(output);
freeTree(tree);
freeTree(tree2);

return ret;
}


int runMerkleTest(uint16_t* missingLeaves, size_t missingLeavesSize, size_t numLeaves, paramset_t* params)
{
// uint8_t iSeed[16];
uint8_t salt[16];
// size_t repIndex = 19;
int freeMissingLeaves = 0;
int ret = 1;
tree_t* tree2 = NULL;

if(numLeaves < missingLeavesSize - 1) {
printf("%s invalid input\n", __func__);
return 0;
}

if(missingLeaves == NULL) {
missingLeaves = malloc(missingLeavesSize*sizeof(uint16_t));
freeMissingLeaves = 1;
uint16_t val;
for(size_t i = 0; i < missingLeavesSize; i++) {
do{
val = ((uint16_t)rand()) % numLeaves;
} while(contains(missingLeaves, i, val));
missingLeaves[i] = val;
}
}

#if 0
printf("missingLeaves: ");
for(size_t i = 0; i < missingLeavesSize; i++) {
printf("%u, ", missingLeaves[i]);
}
printf("\n");
#endif
// Prover side; all leaves are present

tree_t* tree = createTree(numLeaves, params->digestSizeBytes);

uint8_t** leafData = malloc(tree->numLeaves*sizeof(uint8_t*));
uint8_t* slab = malloc(tree->numLeaves*tree->dataSize);
uint8_t* slabToFree = slab;
for(size_t i = 0; i < tree->numLeaves; i++) {
leafData[i] = slab;
slab += tree->dataSize;
memset(leafData[i], (uint8_t)i+1, tree->dataSize);
}

memset(salt, 0x09, sizeof(salt));

buildMerkleTree(tree, leafData, salt, params);

#if 0
printTree("Tree after buildMerkleTree", tree);
#endif


size_t openDataSize = 0;
uint8_t* openData = openMerkleTree(tree, missingLeaves, missingLeavesSize, &openDataSize);
// root is tree->nodes[0]

if(params->numOpenedRounds*ceil_log2(params->numMPCRounds/params->numOpenedRounds) < openDataSize/tree->dataSize) {
printf("%s: Output length is larger than expected\n", __func__);
ret = 0;
goto Exit;
}


// prover sends openData, tree->nodes[0] to verifier

// Verifier side
tree2 = createTree(numLeaves, params->digestSizeBytes);

for(size_t i = 0; i < missingLeavesSize; i++) {
leafData[missingLeaves[i]] = NULL;
}

ret = addMerkleNodes(tree2, missingLeaves, missingLeavesSize, openData, openDataSize);
if(ret != 0) {
printf("Failed to add nodes to Merkle tree tree2\n");
ret = 0;
goto Exit;
}

//printTree("tree2 after addMerkleNodes", tree2);

ret = verifyMerkleTree(tree2, leafData, salt, params);
if(ret != 0) {
printf("Failed to verify Merkle tree\n");
#if 0
printTreeInfo("tree", tree);
printTreeInfo("tree2", tree2);
printTree("tree", tree);
printTree("tree2", tree2);
#endif
ret = 0;
goto Exit;
}

if(memcmp(tree->nodes[0], tree2->nodes[0], tree->dataSize) != 0) {
printf("Recomputed Merkle tree has different root; verification failed\n");
ret = 0;
goto Exit;
}

//printTree("tree", tree);
//printTree("tree2", tree2);


ret = 1;
Exit:
if(freeMissingLeaves) {
free(missingLeaves);
}
free(openData);
free(slabToFree);
free(leafData);
freeTree(tree);
freeTree(tree2);

return ret;
}




int main()
{
paramset_t params;
size_t tests = 0;
size_t passed = 0;

size_t numIterations = 50;

printf("Running seed tree tests\n");
#if 1
for (picnic_params_t p = Picnic3_L1; p <= Picnic3_L5; p++) {
get_param_set(p, &params);
for(size_t i = 0; i < numIterations; i++) {
passed += runSeedTest(NULL, params.numOpenedRounds, params.numMPCRounds, &params);
tests++;
}
for(size_t i = 0; i < numIterations; i++) {
passed += runSeedTest(NULL, 3, 8, &params);
tests++;
passed += runSeedTest(NULL, 3, 7, &params);
tests++;
passed += runSeedTest(NULL, 3, 6, &params);
tests++;
passed += runSeedTest(NULL, 4, 5, &params);
tests++;
passed += runSeedTest(NULL, 2, 5, &params);
tests++;
}
uint16_t hideList[3] = {2, 3, 6};
passed += runSeedTest(hideList, 3, 7, &params);
tests++;

uint16_t hideList2[2] = {2, 3};
passed += runSeedTest(hideList2, 2, 6, &params);
tests++;

uint16_t hideList3[2] = {2, 3};
passed += runSeedTest(hideList3, 2, 5, &params);
tests++;

uint16_t hideList5[2] = {2, 3};
passed += runSeedTest(hideList5, 2, 6, &params);
tests++;

}

#endif




#if 1
printf("Running Merkle tree tests\n");
for (picnic_params_t p = Picnic3_L1; p <= Picnic3_L5; p++) {
get_param_set(p, &params);
for(size_t i = 0; i < numIterations; i++) {
passed += runMerkleTest(NULL, params.numOpenedRounds, params.numMPCRounds, &params);
tests++;
}
for(size_t i = 0; i < numIterations; i++) {
passed += runMerkleTest(NULL, 3, 8, &params);
tests++;
passed += runMerkleTest(NULL, 3, 7, &params);
tests++;
passed += runMerkleTest(NULL, 3, 6, &params);
tests++;
passed += runMerkleTest(NULL, 4, 5, &params);
tests++;
passed += runMerkleTest(NULL, 2, 5, &params);
tests++;
}
uint16_t hideList6[3] = {2, 3, 6};
passed += runMerkleTest(hideList6, 3, 7, &params);
tests++;

uint16_t hideList4[2] = {2, 3};
passed += runMerkleTest(hideList4, 2, 5, &params);
tests++;

uint16_t missingLeaves0[2] = {2, 3};
passed += runMerkleTest(missingLeaves0, 2, 6, &params);
tests++;

uint16_t missingLeaves[4] = {4, 5, 6, 7};
passed += runMerkleTest(missingLeaves, 4, 8, &params);
tests++;
uint16_t missingLeaves2[5] = {2, 3, 4, 8, 11};
passed += runMerkleTest(missingLeaves2, 5, 13, &params);
tests++;
}

#endif

printf("Done, %lu of %lu tests passed\n", passed, tests);

return 0;
}


+ 0
- 857
src/sign/picnic/picnic3l1/clean/unit_test.c Ver arquivo

@@ -1,857 +0,0 @@
/*! @file unit_test.c
* @brief This program tests the LowMC implementation against known answers.
*
* This file is part of the reference implementation of the Picnic signature scheme.
* See the accompanying documentation for complete details.
*
* The code is provided under the MIT license, see LICENSE for
* more details.
* SPDX-License-Identifier: MIT
*/

#include "picnic_impl.h"
#include "picnic3_impl.h"
#include "picnic.h"
#include <stdio.h>
#include <memory.h>
#include <assert.h>


// The test vectors in test_sign* depend on this value
static const uint8_t MSG[500] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,};

#define MSG_LEN sizeof(MSG)

// internal function from picnic.c:
int get_param_set(picnic_params_t picnicParams, paramset_t* paramset);

#if 0
int printNewKeypair(picnic_params_t parameters)
{
/* Generate, serialize and pring a keypair to stdout */
picnic_publickey_t pk;
picnic_privatekey_t sk;
int ret = 0;

printf("Creating new key pair for parameter set: %s\n", picnic_get_param_name(parameters) );

ret = picnic_keygen(parameters, &pk, &sk);

if (ret != 0) {
printf("picnic_keygen failed\n");
exit(-1);
}
printf(" success\n");
uint8_t pk_b[PICNIC_MAX_PUBLICKEY_SIZE];
ret = picnic_write_public_key(&pk, pk_b, sizeof(pk_b));
if (ret <= 0) {
printf("Failed to serialize public key\n");
exit(-1);
}
printHex("pk", pk_b, ret);

uint8_t sk_b[PICNIC_MAX_PRIVATEKEY_SIZE];
ret = picnic_write_private_key(&sk, sk_b, sizeof(sk_b));
if (ret <= 0) {
printf("Failed to write private key\n");
exit(-1);
}
printHex("sk", sk_b, ret);

return 0;
}
#endif


int run_lowmc_enc_test(picnic_params_t param_name, const char* testname, const uint8_t* key, const uint8_t* plaintext, const uint8_t* ciphertext_expected)
{
paramset_t paramset;
uint8_t ciphertext_actual[32] = { 0 }; /* For all parameter sets the LowMC ciphertext is not more than 32 bytes */

int ret = get_param_set(param_name, &paramset);

if (ret != 0) {
printf("%s: Failed to get paramset\n", testname);
return 0;
}

LowMCEnc((uint32_t*)plaintext, (uint32_t*)ciphertext_actual, (uint32_t*)key, &paramset);

if (memcmp(ciphertext_expected, ciphertext_actual, paramset.stateSizeBytes) != 0) {
printf("%s: failed, encryption produced wrong ciphertext\n", testname);
printf("Got: ");
for(size_t i = 0; i < paramset.stateSizeBytes; i++) {
printf("%02X, ", ciphertext_actual[i]);
}
printf("\nExpected: ");
for(size_t i = 0; i < paramset.stateSizeBytes; i++) {
printf("%02X, ", ciphertext_expected[i]);
}
printf("\n");

return 0;
}

return 1;
}

int LowMC_test_vectorL1_1()
{
uint8_t key[16] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[16] = { 0xAB, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[16] = { 0x0E, 0x30, 0x72, 0x0B, 0x9F, 0x64, 0xD5, 0xC2, 0xA7, 0x77, 0x1C, 0x8C, 0x23, 0x8D, 0x8F, 0x70 };

return run_lowmc_enc_test(Picnic_L1_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL1_2()
{
uint8_t key[16] = { 0xB5, 0xDF, 0x53, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[16] = { 0xF7, 0x7D, 0xB5, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[16] = { 0x0E, 0x59, 0x61, 0xE9, 0x99, 0x21, 0x53, 0xB1, 0x32, 0x45, 0xAF, 0x24, 0x3D, 0xD7, 0xDD, 0xC0 };

return run_lowmc_enc_test(Picnic_L1_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL1_3()
{

uint8_t key[16] = { 0x08, 0x4c, 0x2a, 0x6e, 0x19, 0x5d, 0x3b, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[16] = { 0xf7, 0xb3, 0xd5, 0x91, 0xe6, 0xa2, 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[16] = { 0x91, 0x5c, 0x63, 0x21, 0xd7, 0x86, 0x46, 0xb6, 0xc7, 0x65, 0x43, 0xff, 0xb8, 0x52, 0x3b, 0x4d };

return run_lowmc_enc_test(Picnic_L1_FS, __func__, key, plaintext, ciphertext_expected);
}


int LowMC_test_vectorL3_1()
{
uint8_t key[24] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[24] = { 0xAB, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[24] = { 0xA8, 0x5B, 0x82, 0x44, 0x34, 0x4A, 0x2E, 0x1B, 0x10, 0xA1, 0x7B, 0xAB, 0x04, 0x30, 0x73, 0xF6, 0xBB, 0x64, 0x9A, 0xE6, 0xAF, 0x65, 0x9F, 0x6F };

return run_lowmc_enc_test(Picnic_L3_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL3_2()
{
uint8_t key[24] = { 0xB5, 0xDF, 0x53, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[24] = { 0xF7, 0x7D, 0xB5, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[24] = { 0x21, 0x0B, 0xBC, 0x4A, 0x43, 0x4B, 0x32, 0xDB, 0x1E, 0x85, 0xAE, 0x7A, 0x27, 0xFE, 0xE9, 0xE4, 0x15, 0x82, 0xFA, 0xC2, 0x1D, 0x03, 0x5A, 0xA1 };

return run_lowmc_enc_test(Picnic_L3_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL3_3()
{
uint8_t key[24] = { 0xF7, 0x7D, 0xB5, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[24] = { 0xB5, 0xDF, 0x53, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[24] = { 0xE4, 0x82, 0xBC, 0xF9, 0xAD, 0x2C, 0x04, 0x48, 0x31, 0x48, 0xD4, 0x6F, 0xBE, 0x1F, 0x8B, 0x51, 0x46, 0x0D, 0xCC, 0x3E, 0x8E, 0xFB, 0x31, 0x01 };

return run_lowmc_enc_test(Picnic_L3_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL5_1()
{
uint8_t key[32] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[32] = { 0xAB, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[32] = { 0xB8, 0xF2, 0x0A, 0x88, 0x8A, 0x0A, 0x9E, 0xC4, 0xE4, 0x95, 0xF1, 0xFB, 0x43, 0x9A, 0xBD, 0xDE, 0x18, 0xC1, 0xD3, 0xD2, 0x9C, 0xF2, 0x0D, 0xF4, 0xB1, 0x0A, 0x56, 0x7A, 0xA0, 0x2C, 0x72, 0x67 };

return run_lowmc_enc_test(Picnic_L5_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL5_2()
{
uint8_t key[32] = { 0xF7, 0x7D, 0xB5, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[32] = { 0xB5, 0xDF, 0x53, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[32] = { 0xEE, 0xEC, 0xCE, 0x6A, 0x58, 0x4A, 0x93, 0x30, 0x6D, 0xAE, 0xA0, 0x75, 0x19, 0xB4, 0x7A, 0xD6, 0x40, 0x2C, 0x11, 0xDD, 0x94, 0x2A, 0xA3, 0x16, 0x65, 0x41, 0x44, 0x49, 0x77, 0xA2, 0x14, 0xC5 };

return run_lowmc_enc_test(Picnic_L5_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL5_3()
{
uint8_t key[32] = { 0xB5, 0xDF, 0x53, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t plaintext[32] = { 0xF7, 0x7D, 0xB5, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t ciphertext_expected[32] = { 0x03, 0x37, 0x33, 0x26, 0xC0, 0xF5, 0x0E, 0x3B, 0x6B, 0x2E, 0x1C, 0xE8, 0xF9, 0x43, 0x0F, 0xF5, 0xEB, 0x0E, 0xC3, 0x45, 0xC7, 0x27, 0xA4, 0x74, 0x8F, 0xCF, 0x73, 0x17, 0x9D, 0x48, 0xE7, 0x9B };

return run_lowmc_enc_test(Picnic_L5_FS, __func__, key, plaintext, ciphertext_expected);
}

int LowMC_test_vectorL1_129_1()
{

const uint8_t key[17] = {0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
const uint8_t plaintext[17] = {0xab, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
const uint8_t ciphertext_expected[17] = {0x2f, 0xd7, 0xd5, 0x42, 0x5e, 0xe3, 0x5e, 0x66, 0x7c, 0x97, 0x2f, 0x12, 0xfb, 0x15, 0x3e, 0x9d, 0x80};

return run_lowmc_enc_test(Picnic3_L1, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL1_129_2(void) {
const uint8_t key[17] = { 0xab, 0x22, 0x42, 0x51, 0x49, 0xaa, 0x61, 0x2d, 0x7f, 0xff, 0x13, 0x72, 0x20, 0x27, 0x5b, 0x16, 0x80 };
const uint8_t plaintext[17] = { 0x4b, 0x99, 0x23, 0x53, 0xa6, 0x6, 0x65, 0xbf, 0x99, 0x2d, 0x3, 0x54, 0x82, 0xc1, 0xd2, 0x79, 0x00 };
const uint8_t ciphertext_expected[17] = { 0x2a, 0x40, 0x62, 0xd8, 0x35, 0xc5, 0x93, 0xea, 0x19, 0xf8, 0x22, 0xad, 0x24, 0x24, 0x77, 0xd2, 0x80 };

return run_lowmc_enc_test(Picnic3_L1, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL1_129_3(void) {
const uint8_t key[17] = { 0xe7, 0x3a, 0xf2, 0x9c, 0xfc, 0x7a, 0xe5, 0x3e, 0x52, 0x20, 0xd3, 0x1e, 0x2e, 0x59, 0x17, 0xda, 0x80 };
const uint8_t plaintext[17] = { 0x30, 0x4b, 0xa7, 0xa8, 0xde, 0x2b, 0x5c, 0xf8, 0x87, 0xf9, 0xa4, 0x8a, 0xb7, 0x56, 0x1b, 0xf6, 0x80 };
const uint8_t ciphertext_expected[17] = { 0x5c, 0xd2, 0xc3, 0x55, 0x32, 0x8e, 0xfd, 0xe9, 0xf3, 0x78, 0xc1, 0x61, 0x23, 0xd3, 0x3f, 0xb3, 0x00 };

return run_lowmc_enc_test(Picnic3_L1, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL1_129_4(void) {
const uint8_t key[17] = { 0x30, 0xf3, 0x34, 0x88, 0x53, 0x2d, 0x7e, 0xb8, 0xa5, 0xf8, 0xfb, 0x4f, 0x2e, 0x63, 0xba, 0x56, 0x00 };
const uint8_t plaintext[17] = { 0xc2, 0x6a, 0x5d, 0xf9, 0x6, 0x15, 0x8d, 0xcb, 0x6a, 0xc7, 0x89, 0x1d, 0xa9, 0xf4, 0x9f, 0x78, 0x00 };
const uint8_t ciphertext_expected[17] = { 0xb, 0x43, 0xb6, 0x5f, 0x7c, 0x53, 0x50, 0x6, 0xcf, 0x27, 0xe8, 0x6f, 0x55, 0x1b, 0xd0, 0x15, 0x80 };

return run_lowmc_enc_test(Picnic3_L1, __func__, key, plaintext, ciphertext_expected);
}


static int LowMC_test_vectorL3_192_1(void) {
const uint8_t key[24] = { 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
const uint8_t plaintext[24] = { 0xab, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
const uint8_t ciphertext_expected[24] = { 0xf8, 0xf7, 0xa2, 0x25, 0xde, 0x77, 0x12, 0x31, 0x29, 0x10, 0x7a, 0x20, 0xf5, 0x54, 0x3a, 0xfa, 0x78, 0x33, 0x7, 0x66, 0x53, 0xba, 0x2b, 0x29 };

return run_lowmc_enc_test(Picnic3_L3, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL3_192_2(void) {
const uint8_t key[24] = { 0x81, 0xb8, 0x5d, 0xfe, 0x40, 0xf6, 0x12, 0x27, 0x5a, 0xa3, 0xf9, 0x19, 0x91, 0x39, 0xeb, 0xaa, 0xe8, 0xdf, 0xf8, 0x36, 0x6f, 0x2d, 0xd3, 0x4e };
const uint8_t plaintext[24] = { 0xb8, 0x65, 0xcc, 0xf3, 0xfc, 0xda, 0x8d, 0xdb, 0xed, 0x52, 0x7d, 0xc3, 0x4d, 0xd4, 0x15, 0xd, 0x4a, 0x48, 0x2d, 0xcb, 0xf7, 0xe9, 0x64, 0x3c };
const uint8_t ciphertext_expected[24] = { 0x95, 0xef, 0x9e, 0xd7, 0xc3, 0x78, 0x72, 0xa7, 0xb4, 0x60, 0x2a, 0x3f, 0xa9, 0xc4, 0x6e, 0xbc, 0xb8, 0x42, 0x54, 0xed, 0xe, 0x44, 0xee, 0x9f };

return run_lowmc_enc_test(Picnic3_L3, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL3_192_3(void) {
const uint8_t key[24] = { 0x24, 0x5, 0x97, 0x8f, 0xda, 0xad, 0x9b, 0x6d, 0x8d, 0xcd, 0xd1, 0x8a, 0xc, 0x2c, 0xe, 0xc6, 0x8b, 0x69, 0xdd, 0xa, 0x37, 0x54, 0xfe, 0x38, };
const uint8_t plaintext[24] = { 0x33, 0xe8, 0xb4, 0x55, 0x2e, 0x95, 0xef, 0x52, 0x79, 0x49, 0x77, 0x6, 0xbc, 0xe0, 0x1e, 0xcb, 0x4a, 0xcb, 0x86, 0x1, 0x41, 0xb7, 0xfc, 0x43, };
const uint8_t ciphertext_expected[24] = { 0xdd, 0xaf, 0xf, 0x9d, 0x9e, 0xdd, 0x57, 0x20, 0x69, 0xa8, 0x94, 0x9f, 0xae, 0xa0, 0xd1, 0xfd, 0x2d, 0x91, 0xef, 0x26, 0x2b, 0x41, 0x1c, 0xaf, };

return run_lowmc_enc_test(Picnic3_L3, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL3_192_4(void) {
const uint8_t key[24] = { 0x56, 0x9d, 0x7d, 0x82, 0x23, 0x0, 0x94, 0x3d, 0x94, 0x83, 0x47, 0x74, 0x27, 0xe8, 0x8e, 0xa2, 0x27, 0xa2, 0xe3, 0x17, 0x2c, 0x4, 0xbc, 0xd3};
const uint8_t plaintext[24] = { 0xae, 0xeb, 0x9d, 0x5b, 0x61, 0xa2, 0xa5, 0x6d, 0xd5, 0x98, 0xf7, 0xda, 0x26, 0xdf, 0xd7, 0x8c, 0xc9, 0x92, 0xe0, 0xae, 0xa3, 0xfc, 0x2e, 0x39 };
const uint8_t ciphertext_expected[24] = { 0x86, 0x98, 0x70, 0xae, 0x65, 0x47, 0xad, 0xa, 0xfe, 0xf2, 0x77, 0x93, 0x17, 0xd, 0x96, 0xbc, 0x78, 0xe0, 0x40, 0x9, 0x69, 0x44, 0x80, 0x8f };

return run_lowmc_enc_test(Picnic3_L3, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL5_255_1(void) {
const uint8_t key[32] = { 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
const uint8_t plaintext[32] = { 0xab, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
const uint8_t ciphertext_expected[32] = { 0xd4, 0x72, 0x1d, 0x84, 0x6d, 0xd1, 0x4d, 0xba, 0x3a, 0x2c, 0x41, 0x50, 0x1c, 0x2, 0xda, 0x28, 0x2e, 0xca, 0xfd, 0x72, 0xdf, 0x77, 0x99, 0x2f, 0x39, 0x67, 0xef, 0xd6, 0xe8, 0xf3, 0xf3, 0x56 };

return run_lowmc_enc_test(Picnic3_L5, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL5_255_2(void) {
const uint8_t key[32] = { 0x7c, 0x20, 0xbe, 0x53, 0xb6, 0xd6, 0x0, 0x81, 0x49, 0xe1, 0x9a, 0x34, 0xb9, 0x7d, 0x96, 0x84, 0xa0, 0x91, 0x4c, 0xaf,0x9f, 0x7f, 0x38, 0xb2, 0x49, 0x98, 0x11, 0x36, 0x9c, 0x3f, 0x53, 0xda};
const uint8_t plaintext[32] = { 0x88, 0x63, 0xf1, 0x29, 0xc0, 0x38, 0x7a,0xe5, 0xa4, 0x2, 0xa4, 0x9b, 0xd6, 0x49, 0x27, 0xc4, 0xc6, 0x59, 0x64,0xfb, 0x85, 0x31, 0xb0, 0xd7, 0x61, 0xb1, 0x61, 0xb4, 0xc9, 0x7b, 0x75,0x5e, };
const uint8_t ciphertext_expected[32] = { 0x3, 0xb6, 0xe4, 0xb6, 0x3c, 0xc8,0xb0, 0x82, 0x68, 0xb6, 0x78, 0x1d, 0x5a, 0x62, 0x9d, 0x6e, 0x3, 0x2,0xc, 0x1c, 0x4, 0x8d, 0x46, 0x84, 0x16, 0x1b, 0x90, 0xad, 0x73, 0x33,0x91, 0x26, };

return run_lowmc_enc_test(Picnic3_L5, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL5_255_3(void) {
const uint8_t key[32] = {0x6d, 0xf9, 0xe7, 0x8d, 0xf, 0xc1, 0xb8, 0x70, 0xda, 0xbe, 0x52,0x5, 0x14, 0xb9, 0x59, 0x63, 0x6a, 0x42, 0x30, 0x4b, 0xf4, 0x3a,0x24, 0x8, 0x52, 0x45, 0x6, 0xc8, 0x1e, 0xa3, 0xb, 0x14};
const uint8_t plaintext[32] = {0x9e, 0x51, 0x78, 0x42, 0x5, 0x20, 0xb8, 0xcc, 0xa5, 0x29, 0x59,0x5b, 0x80, 0xc4, 0x70, 0x3b, 0x2d, 0xcf, 0x2a, 0x7, 0x30, 0x64,0x3a, 0x6f, 0x41, 0x27, 0x98, 0x60, 0x5f, 0x5, 0x2b, 0x68};
const uint8_t ciphertext_expected[32] = {0xf, 0x19, 0xfc, 0xc8, 0xbc, 0x18, 0x86, 0x9a, 0xab, 0x8e, 0x4f,0xe8, 0x1e, 0x97, 0x67, 0xd1, 0x8c, 0xfe, 0x71, 0x50, 0x81, 0x92,0x9f, 0x92, 0x96, 0x3b, 0x40, 0x0, 0x0, 0x6, 0x26, 0xf8};

return run_lowmc_enc_test(Picnic3_L5, __func__, key, plaintext, ciphertext_expected);
}

static int LowMC_test_vectorL5_255_4(void) {
const uint8_t key[32] = {0xb0, 0x71, 0xc6, 0xd4, 0xa3, 0x77, 0xe5, 0x51, 0x25, 0x4c, 0x5d,0xc4, 0x1, 0xa3, 0xd0, 0x8a, 0xcb, 0x99, 0x60, 0x9f, 0x41, 0x8a,0x8c, 0x22, 0x7, 0xf5, 0x12, 0x2b, 0x5a, 0x17, 0xfe, 0x9a,};
const uint8_t plaintext[32] = {0xf7, 0x61, 0x6d, 0xc5, 0x14, 0xfd, 0xe, 0x10, 0x28, 0x56, 0x1d,0x9, 0x8a, 0xaf, 0xa5, 0x4c, 0x34, 0xbe, 0x72, 0x8c, 0xf2, 0x4a,0x50, 0x24, 0xdf, 0x17, 0xb9, 0xcc, 0x2e, 0x33, 0xfb, 0xfa,};
const uint8_t ciphertext_expected[32] = {0x44, 0x48, 0xc7, 0xa, 0xc3, 0x86, 0x30, 0x21, 0xbe, 0x23, 0x2c, 0x63, 0x38, 0x16, 0x87, 0xcd,0x5d, 0xef, 0xb5, 0xb, 0xa2, 0x8d, 0x7b, 0x26, 0x8e, 0x19, 0x72, 0x7b, 0xae, 0xbc, 0x67, 0x9a,};

return run_lowmc_enc_test(Picnic3_L5, __func__, key, plaintext, ciphertext_expected);
}


int test_serialization_L1()
{
picnic_publickey_t pk;
picnic_privatekey_t sk;
picnic_publickey_t pk2;
picnic_privatekey_t sk2;
uint8_t pk_buf[PICNIC_MAX_PUBLICKEY_SIZE];
uint8_t sk_buf[PICNIC_MAX_PRIVATEKEY_SIZE];

int ret = picnic_keygen(Picnic_L1_FS, &pk, &sk);

if(ret != 0) {
printf("Keygen failed, %d\n", ret);
return 0;
}

ret = picnic_write_public_key(&pk, pk_buf, sizeof(pk_buf));
if(ret <= 1) {
printf("Failed to serialize public key\n");
return 0;
}

ret = picnic_write_private_key(&sk, sk_buf, sizeof(sk_buf));
if(ret <= 1) {
printf("Failed to serialize private key\n");
return 0;
}

ret = picnic_read_public_key(&pk2, pk_buf, sizeof(pk_buf));
if(ret != 0) {
printf("Failed to read public key\n");
return 0;
}

ret = picnic_read_private_key(&sk2, sk_buf, sizeof(sk_buf));
if(ret != 0) {
printf("Failed to read private key\n");
return 0;
}

ret = picnic_validate_keypair(&sk2, &pk2);
if(ret != 0) {
printf("Failed to validate key pair 2\n");
return 0;
}

ret = picnic_validate_keypair(&sk2, &pk);
if(ret != 0) {
printf("Failed to validate key pair 3\n");
return 0;
}

ret = picnic_validate_keypair(&sk, &pk2);
if(ret != 0) {
printf("Failed to validate key pair 4\n");
return 0;
}


return 1;
}


int test_serialize_roundtrip_picnic3(picnic_params_t parameters)
{
picnic_publickey_t pk;
picnic_privatekey_t sk;
paramset_t paramset;
signature2_t sig, sig2;

int ret = get_param_set(parameters, &paramset);
if (ret != 0) {
printf("invalid parameter set\n");
return 0;
}

ret = picnic_keygen(parameters, &pk, &sk);
if (ret != 0) {
printf("picnic_keygen failed\n");
return 0;
}

uint8_t message[MSG_LEN];
memset(message, 0x07, sizeof(message));
uint8_t* signature = NULL;

size_t signature_len = picnic_signature_size(parameters);
signature = (uint8_t*)malloc(signature_len);
if (signature == NULL) {
printf("failed to allocate signature\n");
return 0;
}

allocateSignature2(&sig, &paramset);

/* Compute a signature, then check that serialize(deserialize(sig)) == serialize(sig) */
ret = sign_picnic3((uint32_t*)sk.data, (uint32_t*)sk.pk.ciphertext, (uint32_t*)sk.pk.plaintext, message, MSG_LEN, &sig, &paramset);
if (ret != EXIT_SUCCESS) {
printf("%s: sign failed\n", __func__);
return 0;
}
ret = serializeSignature2(&sig, signature, signature_len, &paramset);
if (ret == -1) {
printf("%s: serialize failed\n", __func__);
return 0;
}
signature_len = ret;

allocateSignature2(&sig2, &paramset);
ret = deserializeSignature2(&sig2, signature, signature_len, &paramset);
if (ret != EXIT_SUCCESS) {
printf("%s: deserialize failed\n", __func__);
return 0;
}

uint8_t* signature2 = (uint8_t*)malloc(signature_len);
if (signature2 == NULL) {
printf("%s: failed to allocate signature\n", __func__);
return 0;
}
ret = serializeSignature2(&sig2, signature2, signature_len, &paramset);
if (ret == -1) {
printf("%s: serialize failed (2)\n", __func__);
return 0;
}

if(memcmp(signature, signature2, signature_len) != 0) {
printf("Round-trip serialization test failed (params %u)\n", (unsigned int)parameters);
// printHex("Sig one", signature, signature_len);
// printHex("Sig two", signature2, signature_len);
return 0;
}

free(signature);
free(signature2);
freeSignature2(&sig, &paramset);
freeSignature2(&sig2, &paramset);

return 1;

}

static int contains(uint16_t* list, size_t len, size_t value)
{
for (size_t i = 0; i < len; i++) {
if (list[i] == value) {
return 1;
}
}
return 0;
}
static int indexOf(uint16_t* list, size_t len, size_t value)
{
for (size_t i = 0; i < len; i++) {
if (list[i] == value) {
return i;
}
}
assert(!"indexOf called on list where value is not found. (caller bug)");
return -1;
}


static int compare_proofs(proof2_t* proof1, proof2_t* proof2, paramset_t* params, int compare_aux)
{
if(proof1->seedInfoLen != proof2->seedInfoLen ||
memcmp(proof1->seedInfo, proof2->seedInfo, proof1->seedInfoLen) != 0) {
printf("%s: seedInfo differs\n", __func__);
return 1;
}
if(compare_aux) {
if(!(proof1->aux == NULL && proof2->aux == NULL)) {
if((proof1->aux == NULL && proof2->aux != NULL) ||
(proof2->aux == NULL && proof1->aux != NULL) ||
memcmp(proof1->aux, proof2->aux, params->andSizeBytes) != 0 ) {
printf("%s: aux differs\n", __func__);
printHex("aux1", proof1->aux, params->andSizeBytes);
printHex("aux2", proof2->aux, params->andSizeBytes);

return 1;
}
}
}

if(memcmp(proof1->C, proof2->C, params->digestSizeBytes) != 0) {
printf("%s: C differs\n", __func__);
return 1;
}

if(memcmp(proof1->input, proof2->input, params->stateSizeBytes) != 0) {
printf("%s: input differs\n", __func__);
printHex("input1", proof1->input, params->stateSizeBytes);
printHex("input2", proof2->input, params->stateSizeBytes);
return 1;
}

if(memcmp(proof1->msgs, proof2->msgs, params->andSizeBytes) != 0) {
printf("%s: msgs differs\n", __func__);
return 1;
}

return 0;
}


static int compare_signatures(signature2_t* sig1, signature2_t* sig2, paramset_t* params)
{

if(memcmp(sig1->salt, sig2->salt, params->saltSizeBytes) != 0) {
printf("%s: salt differs\n", __func__);
return 1;
}

if(sig1->iSeedInfoLen != sig2->iSeedInfoLen ||
memcmp(sig1->iSeedInfo, sig2->iSeedInfo, sig1->iSeedInfoLen) != 0 ) {
printf("%s: iSeedInfo differs\n", __func__);
return 1;
}
if(sig1->cvInfoLen != sig2->cvInfoLen ||
memcmp(sig1->cvInfo, sig2->cvInfo, sig1->cvInfoLen) != 0) {
printf("%s: iSeedInfo differs\n", __func__);
return 1;
}

if(memcmp(sig1->challengeC, sig2->challengeC, params->numOpenedRounds*sizeof(uint16_t)) != 0) {
printf("%s: challengeC differs\n", __func__);
return 1;
}

if(memcmp(sig1->challengeP, sig2->challengeP, params->numOpenedRounds*sizeof(uint16_t)) != 0) {
printf("%s: challengeP differs\n", __func__);
return 1;
}

for (size_t t = 0; t < params->numMPCRounds; t++) {
if (contains(sig1->challengeC, params->numOpenedRounds, t)) {
size_t P_t = sig1->challengeP[indexOf(sig1->challengeC, params->numOpenedRounds, t)];
int compare_aux = (P_t != (params->numMPCParties - 1));
if(compare_proofs(&sig1->proofs[t], &sig2->proofs[t], params, compare_aux) != 0) {
printf("%s: proofs %u differ\n", __func__, (unsigned int) t);
return 1;
}
}
}

return 0;

}

int test_sig_serialize_picnic3(picnic_params_t parameters)
{
picnic_publickey_t pk;
picnic_privatekey_t sk;
paramset_t paramset;
signature2_t sig, sig2;

int ret = get_param_set(parameters, &paramset);
if (ret != 0) {
printf("invalid parameter set\n");
return 0;
}

ret = picnic_keygen(parameters, &pk, &sk);
if (ret != 0) {
printf("picnic_keygen failed\n");
return 0;
}

uint8_t message[MSG_LEN];
memset(message, 0x07, sizeof(message));
uint8_t* signature = NULL;

size_t signature_len = picnic_signature_size(parameters);
signature = (uint8_t*)malloc(signature_len);
if (signature == NULL) {
printf("failed to allocate signature\n");
return 0;
}

allocateSignature2(&sig, &paramset);

/* Compute a signature object sig, then sig2 = deserialize(serialize(sig)), ensure sig == sig2 */
ret = sign_picnic3((uint32_t*)sk.data, (uint32_t*)sk.pk.ciphertext, (uint32_t*)sk.pk.plaintext, message, MSG_LEN, &sig, &paramset);
if (ret != EXIT_SUCCESS) {
printf("%s: signing failed\n", __func__);
return 0;
}
ret = serializeSignature2(&sig, signature, signature_len, &paramset);
if (ret == -1) {
printf("%s: serialization failed\n", __func__);
return 0;
}
signature_len = ret;

allocateSignature2(&sig2, &paramset);
ret = deserializeSignature2(&sig2, signature, signature_len, &paramset);
if (ret != EXIT_SUCCESS) {
printf("%s: deserialization failed\n", __func__);
return 0;
}

if( compare_signatures(&sig, &sig2, &paramset) != 0) {
printf("%s: signatures differ\n", __func__);
return 0;
}

freeSignature2(&sig, &paramset);
freeSignature2(&sig2, &paramset);
free(signature);

return 1;

}


/* tests for deterministic picnic3 */
int do_test_sign(
uint8_t* pk_buf, size_t pk_buf_len,
uint8_t* sk_buf, size_t sk_buf_len,
uint8_t* expected_challenge, size_t expected_challenge_len,
uint8_t* expected_salt, size_t expected_salt_len,
size_t expected_sig_len)
{
picnic_publickey_t pk;
picnic_privatekey_t sk;
int ret = 0;


ret = picnic_read_public_key(&pk, pk_buf, pk_buf_len);
if (ret != 0) {
printf("%s: Failed to read public key\n", __func__);
return 0;
}
ret = picnic_read_private_key(&sk, sk_buf, sk_buf_len);
if (ret != 0) {
printf("%s: Failed to read private key\n", __func__);
return 0;
}

ret = picnic_validate_keypair(&sk, &pk);
if (ret != 0) {
printf("%s: Keypair invalid\n", __func__);
return 0;
}

uint8_t* signature = NULL;

size_t signature_len = picnic_signature_size(pk.params);
signature = (uint8_t*)malloc(signature_len);
if (signature == NULL) {
printf("%s: failed to allocate signature\n", __func__);
return 0;
}

ret = picnic_sign(&sk, MSG, MSG_LEN, signature, &signature_len);
if (ret != 0) {
printf("%s: picnic_sign failed (params = %d)\n", __func__, pk.params);
return 0;
}
if(signature_len != expected_sig_len) {
printf("%s: signature has length %lu bytes, but expected %lu (params = %d)\n", __func__, signature_len, expected_sig_len, pk.params);
return 0;
}

if(memcmp(signature, expected_challenge, expected_challenge_len) != 0) {
printf("%s: signature does not have the expected challenge value\n", __func__);
return 0;
}
if(memcmp(signature + expected_challenge_len, expected_salt, expected_salt_len) != 0) {
printf("%s: signature does not have the expected salt\n", __func__);
return 0;
}

ret = picnic_verify(&pk, MSG, MSG_LEN, signature, signature_len);
if (ret != 0) {
printf("%s: picnic_verify failed\n", __func__);
return 0;
}

free(signature);

return 1;
}

int test_sign_Picnic3_L1()
{
uint8_t pk[35] = {0x07, 0x8D, 0xCB, 0x2E, 0x06, 0x2E, 0xE1, 0x48, 0xF8, 0x81, 0xBD, 0xA2, 0xAD, 0x95, 0x39, 0x00, 0x31, 0x00, 0x05, 0xBB, 0x82, 0x75, 0xF0, 0x00, 0x5F, 0xAE, 0x73, 0x1C, 0xFE, 0x1A, 0xE6, 0xCA, 0xC6, 0x15, 0x00};
uint8_t sk[52] = {0x07, 0xA3, 0x4F, 0xEB, 0x0A, 0x24, 0x6F, 0xD7, 0xFC, 0x5B, 0xC6, 0x1E, 0x07, 0xFD, 0x73, 0x7A, 0xCF, 0x00, 0x8D, 0xCB, 0x2E, 0x06, 0x2E, 0xE1, 0x48, 0xF8, 0x81, 0xBD, 0xA2, 0xAD, 0x95, 0x39, 0x00, 0x31, 0x00, 0x05, 0xBB, 0x82, 0x75, 0xF0, 0x00, 0x5F, 0xAE, 0x73, 0x1C, 0xFE, 0x1A, 0xE6, 0xCA, 0xC6, 0x15, 0x00};
uint8_t expected_challenge[32] = {0x81, 0xE6, 0x74, 0x22, 0x2D, 0xC9, 0x77, 0xFF, 0xAB, 0xAC, 0x14, 0x71, 0xA5, 0xAB, 0xCB, 0xA5, 0x9D, 0x6E, 0x6B, 0x7A, 0x70, 0x5E, 0xE5, 0x16, 0xEF, 0x09, 0xD6, 0x30, 0x6C, 0x86, 0x41, 0x26};
uint8_t expected_salt[32] = {0xCE, 0x7F, 0x9E, 0x58, 0xE0, 0xCD, 0x54, 0x5D, 0xF9, 0x49, 0xDE, 0x41, 0xD0, 0x28, 0x56, 0x8A, 0xA6, 0xCB, 0x88, 0xEF, 0xC5, 0x06, 0x1D, 0xC7, 0xC7, 0x7A, 0xF8, 0x5A, 0xE0, 0x08, 0x7A, 0x1A};
size_t expected_sig_len = 12395;

return do_test_sign(pk, sizeof(pk), sk, sizeof(sk), expected_challenge, sizeof(expected_challenge), expected_salt, sizeof(expected_salt), expected_sig_len);
}

int test_sign_Picnic3_L3()
{
uint8_t pk[49] = {0x08, 0xAC, 0x52, 0x30, 0x73, 0x96, 0x70, 0x34, 0x7A, 0x12, 0x84, 0x0E, 0x58, 0x17, 0x6A, 0x5C, 0x88, 0x84, 0x71, 0xBC, 0x7E, 0xAF, 0x68, 0x7E, 0x5B, 0xCD, 0x5C, 0x79, 0xBE, 0x19, 0x5A, 0xEC, 0xF6, 0x55, 0x31, 0x96, 0xE0, 0x86, 0xA1, 0x7C, 0xD6, 0xE5, 0xB6, 0x0B, 0x37, 0x79, 0x16, 0x15, 0x24};
uint8_t sk[73] = {0x08, 0x98, 0xE1, 0x7B, 0xA4, 0x50, 0xA9, 0xF2, 0x5D, 0xC7, 0x48, 0x24, 0x4B, 0xF5, 0x3E, 0xE1, 0xB2, 0x8D, 0xA9, 0x6F, 0x17, 0xBC, 0xC3, 0x2F, 0xA0, 0xAC, 0x52, 0x30, 0x73, 0x96, 0x70, 0x34, 0x7A, 0x12, 0x84, 0x0E, 0x58, 0x17, 0x6A, 0x5C, 0x88, 0x84, 0x71, 0xBC, 0x7E, 0xAF, 0x68, 0x7E, 0x5B, 0xCD, 0x5C, 0x79, 0xBE, 0x19, 0x5A, 0xEC, 0xF6, 0x55, 0x31, 0x96, 0xE0, 0x86, 0xA1, 0x7C, 0xD6, 0xE5, 0xB6, 0x0B, 0x37, 0x79, 0x16, 0x15, 0x24};
uint8_t expected_challenge[48] = {0x2B, 0xAC, 0xC4, 0x1D, 0x18, 0x11, 0x97, 0x42, 0xA0, 0x92, 0xB9, 0xC6, 0x5F, 0x51, 0xE7, 0x85, 0x57, 0x59, 0x0F, 0x01, 0x30, 0x48, 0x30, 0xA5, 0x03, 0x35, 0x13, 0x72, 0x84, 0xDB, 0x47, 0x2B, 0x9F, 0x93, 0xB3, 0xF2, 0x3A, 0x91, 0x09, 0x5A, 0x38, 0x11, 0xC0, 0x82, 0xE2, 0xB8, 0xA8, 0x6E};
uint8_t expected_salt[32] = {0xA0, 0x8F, 0x16, 0xAF, 0x30, 0x3E, 0xD7, 0x79, 0xE6, 0x53, 0x6C, 0x9A, 0xE6, 0xE7, 0xC4, 0xC0, 0xB8, 0x64, 0xC1, 0xD6, 0xA4, 0x05, 0x70, 0x9A, 0x95, 0x76, 0xAF, 0x00, 0xAE, 0x00, 0x9C, 0xD9};
size_t expected_sig_len = 25712;

return do_test_sign(pk, sizeof(pk), sk, sizeof(sk), expected_challenge, sizeof(expected_challenge), expected_salt, sizeof(expected_salt), expected_sig_len);
}

int test_sign_Picnic3_L5()
{
uint8_t pk[65] = {0x09, 0x19, 0x75, 0x3E, 0x8D, 0x8F, 0xB6, 0x00, 0x5F, 0x6E, 0x2E, 0xA2, 0xB5, 0x4D, 0xA4, 0x3E, 0xD0, 0xAD, 0xAE, 0x0A, 0x2E, 0x53, 0x97, 0xA4, 0x7E, 0xEB, 0x8F, 0xB4, 0x33, 0x18, 0x30, 0x83, 0x52, 0xF9, 0x90, 0x33, 0x6B, 0x82, 0xC5, 0x03, 0xB9, 0x86, 0x36, 0x83, 0x34, 0xE7, 0x81, 0xD5, 0x04, 0x76, 0x40, 0x26, 0x21, 0x25, 0x48, 0x39, 0x97, 0x36, 0x15, 0xC0, 0x6A, 0x8C, 0x35, 0x53, 0x08};
uint8_t sk[97] = {0x09, 0xCE, 0x58, 0xA7, 0x51, 0x82, 0xC7, 0x51, 0x1C, 0x62, 0x78, 0x26, 0x6C, 0xAC, 0x38, 0x1E, 0xEF, 0x6F, 0x4F, 0xE2, 0x5A, 0x7F, 0x95, 0x7D, 0xE4, 0x13, 0xD8, 0x43, 0x48, 0xCB, 0x19, 0x83, 0x64, 0x19, 0x75, 0x3E, 0x8D, 0x8F, 0xB6, 0x00, 0x5F, 0x6E, 0x2E, 0xA2, 0xB5, 0x4D, 0xA4, 0x3E, 0xD0, 0xAD, 0xAE, 0x0A, 0x2E, 0x53, 0x97, 0xA4, 0x7E, 0xEB, 0x8F, 0xB4, 0x33, 0x18, 0x30, 0x83, 0x52, 0xF9, 0x90, 0x33, 0x6B, 0x82, 0xC5, 0x03, 0xB9, 0x86, 0x36, 0x83, 0x34, 0xE7, 0x81, 0xD5, 0x04, 0x76, 0x40, 0x26, 0x21, 0x25, 0x48, 0x39, 0x97, 0x36, 0x15, 0xC0, 0x6A, 0x8C, 0x35, 0x53, 0x08};
uint8_t expected_challenge[64] = {0x5B, 0xD1, 0x10, 0xA5, 0x25, 0x00, 0x1E, 0x15, 0xDE, 0xE0, 0xD7, 0xA0, 0x54, 0xF5, 0xDE, 0xF2, 0xB9, 0x0F, 0x03, 0x61, 0xC5, 0x6E, 0x34, 0x99, 0xE0, 0x6A, 0xAA, 0x12, 0x14, 0xBE, 0x1E, 0xD7, 0xDD, 0x92, 0x6F, 0xE5, 0x8E, 0x92, 0xDD, 0x97, 0x33, 0x70, 0x3F, 0x24, 0xE7, 0x28, 0x91, 0xBC, 0xB4, 0x7B, 0xB8, 0xE9, 0x68, 0x77, 0xCF, 0x6C, 0xDC, 0xDA, 0x51, 0x00, 0x01, 0xDB, 0x23, 0x11};
uint8_t expected_salt[32] = {0x0C, 0x8B, 0x86, 0x35, 0x9D, 0x1B, 0xE6, 0x1D, 0x35, 0x35, 0xAC, 0x68, 0xCC, 0xF3, 0x36, 0x39, 0x73, 0x70, 0xB7, 0xF9, 0x16, 0x20, 0x80, 0xA7, 0xBF, 0xBB, 0x59, 0xFD, 0xF6, 0x03, 0x41, 0xE2};
size_t expected_sig_len = 48576;

return do_test_sign(pk, sizeof(pk), sk, sizeof(sk), expected_challenge, sizeof(expected_challenge), expected_salt, sizeof(expected_salt), expected_sig_len);
}

int test_sign_Picnic_L1_full()
{

uint8_t pk[35] = {0x0A, 0xF0, 0xE4, 0x68, 0xF4, 0x66, 0xB3, 0xC1, 0x63, 0x7B, 0xED, 0xAE, 0xBE, 0x4E, 0xC9, 0xEA, 0xF3, 0x80, 0x88, 0xD7, 0x6C, 0xBC, 0xC3, 0xEC, 0x71, 0xE0, 0x0E, 0x0D, 0x42, 0x7C, 0x9A, 0xB0, 0x91, 0x0A, 0x00};
uint8_t sk[52] = {0x0A, 0x2B, 0x08, 0x4A, 0xAB, 0x0E, 0x55, 0xFB, 0xAA, 0x63, 0x3C, 0x13, 0x72, 0x72, 0xD0, 0xA5, 0x8A, 0x80, 0xF0, 0xE4, 0x68, 0xF4, 0x66, 0xB3, 0xC1, 0x63, 0x7B, 0xED, 0xAE, 0xBE, 0x4E, 0xC9, 0xEA, 0xF3, 0x80, 0x88, 0xD7, 0x6C, 0xBC, 0xC3, 0xEC, 0x71, 0xE0, 0x0E, 0x0D, 0x42, 0x7C, 0x9A, 0xB0, 0x91, 0x0A, 0x00};
uint8_t expected_challenge[55] = {0x88, 0x62, 0x95, 0x02, 0x80, 0xA4, 0x94, 0x06, 0x52, 0x81, 0x94, 0x65, 0x10, 0x04, 0x5A, 0x5A, 0x26, 0x06, 0x48, 0x25, 0x92, 0xA4, 0x60, 0x45, 0x28, 0xA8, 0x04, 0x50, 0x58, 0x66, 0x84, 0x06, 0x44, 0x22, 0x4A, 0x66, 0x46, 0xA9, 0x41, 0x44, 0x19, 0x11, 0x56, 0x15, 0x04, 0x29, 0x15, 0x11, 0x68, 0x1A, 0x2A, 0x1A, 0x86, 0xA1, 0x88};
uint8_t expected_salt[32] = {0x15, 0x4A, 0x74, 0xAD, 0x05, 0xD1, 0x1D, 0xDD, 0xEE, 0xC8, 0x7C, 0x93, 0x38, 0xC1, 0x49, 0x6E, 0xF1, 0xA8, 0xAB, 0xB7, 0xF5, 0x55, 0x30, 0x15, 0xBE, 0xE2, 0x0B, 0x58, 0x9B, 0x97, 0xC4, 0x9A};
size_t expected_sig_len = 30786;

return do_test_sign(pk, sizeof(pk), sk, sizeof(sk), expected_challenge, sizeof(expected_challenge), expected_salt, sizeof(expected_salt), expected_sig_len);
}

int test_sign_Picnic_L3_full()
{

uint8_t pk[49] = {0x0B, 0x31, 0x32, 0x8A, 0x63, 0xE2, 0x7B, 0x39, 0x33, 0x1A, 0x29, 0x22, 0xAA, 0xEB, 0x05, 0xBC, 0xAB, 0xCB, 0x94, 0x89, 0x03, 0xAC, 0x30, 0x9A, 0xD0, 0x6C, 0x00, 0x63, 0x40, 0x0D, 0xA0, 0xDA, 0x99, 0x19, 0x9F, 0xE6, 0xCA, 0x3E, 0x6D, 0xBC, 0x73, 0x30, 0xEF, 0xF9, 0x64, 0x3E, 0x85, 0x7D, 0x97};
uint8_t sk[73] = {0x0B, 0x79, 0x68, 0x54, 0xF1, 0x54, 0x2C, 0x4F, 0xB8, 0xD2, 0x26, 0xBE, 0x04, 0x33, 0xDD, 0x18, 0xF1, 0x04, 0x86, 0x90, 0xDA, 0x92, 0xE3, 0x5A, 0xCE, 0x31, 0x32, 0x8A, 0x63, 0xE2, 0x7B, 0x39, 0x33, 0x1A, 0x29, 0x22, 0xAA, 0xEB, 0x05, 0xBC, 0xAB, 0xCB, 0x94, 0x89, 0x03, 0xAC, 0x30, 0x9A, 0xD0, 0x6C, 0x00, 0x63, 0x40, 0x0D, 0xA0, 0xDA, 0x99, 0x19, 0x9F, 0xE6, 0xCA, 0x3E, 0x6D, 0xBC, 0x73, 0x30, 0xEF, 0xF9, 0x64, 0x3E, 0x85, 0x7D, 0x97};
uint8_t expected_challenge[83] = {0x44, 0xA2, 0x25, 0x45, 0x51, 0x60, 0x1A, 0x91, 0x5A, 0x64, 0x49, 0x04, 0x4A, 0x0A, 0x98, 0x81, 0x90, 0x82, 0x85, 0x0A, 0x09, 0x6A, 0x89, 0x8A, 0x85, 0x10, 0x96, 0x85, 0x04, 0x19, 0xA5, 0x69, 0xA8, 0x92, 0xA1, 0x45, 0x40, 0x45, 0xA6, 0x1A, 0x29, 0x84, 0x28, 0x68, 0x14, 0x81, 0x40, 0x00, 0xA9, 0x60, 0x51, 0x61, 0x29, 0x68, 0x16, 0x11, 0x22, 0x15, 0x85, 0x46, 0x60, 0x66, 0x22, 0xA1, 0x88, 0xA4, 0x98, 0x4A, 0x41, 0x95, 0x6A, 0xAA, 0x81, 0x80, 0x64, 0x28, 0x2A, 0x95, 0x42, 0x16, 0x19, 0x9A, 0x00};
uint8_t expected_salt[32] = {0xA4, 0xB4, 0x3E, 0x72, 0xD2, 0xE7, 0x70, 0x9E, 0xAD, 0x11, 0xB2, 0x64, 0xC4, 0x97, 0x29, 0x9F, 0x5D, 0x49, 0x43, 0x1A, 0xFF, 0x22, 0x5D, 0xAD, 0xCD, 0x99, 0xD1, 0x6D, 0xBD, 0x9E, 0x58, 0xE1};
size_t expected_sig_len = 68611;

return do_test_sign(pk, sizeof(pk), sk, sizeof(sk), expected_challenge, sizeof(expected_challenge), expected_salt, sizeof(expected_salt), expected_sig_len);
}

int test_sign_Picnic_L5_full()
{
uint8_t pk[65] = {0x0C, 0x2A, 0xF8, 0xCE, 0xBD, 0x72, 0x34, 0x30, 0x9D, 0x94, 0xB3, 0x08, 0xF7, 0xAD, 0xE1, 0x54, 0x13, 0xB6, 0xBB, 0x60, 0xBA, 0xCE, 0xF6, 0x31, 0x2B, 0xB5, 0xAA, 0x09, 0x25, 0x37, 0x0E, 0x2D, 0x00, 0x30, 0xAF, 0x6F, 0x08, 0x32, 0x92, 0xEB, 0x93, 0x6C, 0x1E, 0x89, 0xE1, 0x90, 0xCB, 0x08, 0x89, 0x6F, 0x70, 0xFB, 0xBD, 0x1D, 0xDC, 0x52, 0xEB, 0x26, 0xC4, 0xD2, 0xFE, 0xF7, 0xDC, 0xE4, 0x64};
uint8_t sk[97] = {0x0C, 0xF4, 0x76, 0x0B, 0x37, 0xBA, 0x6F, 0xEB, 0x62, 0xD1, 0x5E, 0xAC, 0x5F, 0x96, 0xDE, 0x8C, 0x22, 0x2B, 0x99, 0x80, 0xB5, 0x9B, 0x0F, 0x05, 0xF7, 0xFB, 0x6F, 0x18, 0xCD, 0x31, 0x6A, 0xB0, 0x6A, 0x2A, 0xF8, 0xCE, 0xBD, 0x72, 0x34, 0x30, 0x9D, 0x94, 0xB3, 0x08, 0xF7, 0xAD, 0xE1, 0x54, 0x13, 0xB6, 0xBB, 0x60, 0xBA, 0xCE, 0xF6, 0x31, 0x2B, 0xB5, 0xAA, 0x09, 0x25, 0x37, 0x0E, 0x2D, 0x00, 0x30, 0xAF, 0x6F, 0x08, 0x32, 0x92, 0xEB, 0x93, 0x6C, 0x1E, 0x89, 0xE1, 0x90, 0xCB, 0x08, 0x89, 0x6F, 0x70, 0xFB, 0xBD, 0x1D, 0xDC, 0x52, 0xEB, 0x26, 0xC4, 0xD2, 0xFE, 0xF7, 0xDC, 0xE4, 0x64};
uint8_t expected_challenge[110] = {0x24, 0xA2, 0x94, 0x5A, 0x50, 0x54, 0x92, 0x58, 0x42, 0x61, 0x56, 0x09, 0x29, 0x84, 0x48, 0x89, 0x26, 0x04, 0x46, 0x60, 0x10, 0x44, 0x16, 0x48, 0x45, 0x18, 0x20, 0x81, 0x0A, 0x68, 0x60, 0x02, 0xA1, 0x19, 0x56, 0x89, 0x15, 0x22, 0x60, 0x54, 0x84, 0x41, 0xA5, 0x42, 0x29, 0x65, 0x60, 0xAA, 0x66, 0x8A, 0x41, 0x84, 0x12, 0x00, 0x98, 0x00, 0x0A, 0x54, 0x25, 0x19, 0x52, 0x15, 0x60, 0x52, 0x41, 0x81, 0x58, 0xA1, 0x80, 0xA2, 0x25, 0x44, 0x89, 0x51, 0x06, 0x64, 0x48, 0x41, 0x81, 0x52, 0x29, 0xA1, 0x80, 0x18, 0x42, 0xA6, 0x44, 0x98, 0x02, 0x9A, 0x95, 0x4A, 0x54, 0x14, 0x52, 0x42, 0x19, 0x95, 0x01, 0x62, 0x06, 0x4A, 0x95, 0x55, 0x52, 0xA4, 0x52, 0x60, 0x11, 0x60};
uint8_t expected_salt[32] = {0x26, 0x66, 0xE8, 0x95, 0xAB, 0x6F, 0x25, 0x46, 0x9C, 0x01, 0x34, 0xC3, 0xA6, 0x71, 0x09, 0x2B, 0xD3, 0x63, 0xB9, 0x03, 0xFC, 0x80, 0xDD, 0x69, 0x8E, 0x05, 0xC4, 0x82, 0x89, 0xCC, 0x16, 0xCE};
size_t expected_sig_len = 121262;

return do_test_sign(pk, sizeof(pk), sk, sizeof(sk), expected_challenge, sizeof(expected_challenge), expected_salt, sizeof(expected_salt), expected_sig_len);
}

static int picnic_test_modified_signatures(picnic_params_t parameters) {
const size_t max_signature_size = picnic_signature_size(parameters);
if (!max_signature_size) {
/* not supported */
return 0;
}

picnic_publickey_t pk;
picnic_privatekey_t sk;

int ret = picnic_keygen(parameters, &pk, &sk);
if (ret != 0) {
return 0;
}

uint8_t* signature = malloc(max_signature_size);
uint8_t* message = malloc(MSG_LEN);
if (!signature || !message) {
return 0;
}

/* fill message with some data */
memset(message, rand() & 0xFF, MSG_LEN);

size_t signature_len = max_signature_size;
ret = picnic_sign(&sk, message, MSG_LEN, signature, &signature_len);
if (ret != 0) {
return 0;
}

/* must verify */
ret = picnic_verify(&pk, message, MSG_LEN, signature, signature_len);
if (ret != 0) {
return 0;
}

// printf("Signature is %lu bytes long\n", signature_len);
for (size_t l = 0; l < signature_len; l += signature_len/50) {

signature[l] += 1;

/* must fail */
ret = picnic_verify(&pk, message, MSG_LEN, signature, signature_len);
if (!ret) {
printf("Failed when mauling byte number %lu, byte value = %u\n", l, signature[l]);
printHex("signature", signature, signature_len);
return 0;
}

signature[l] -= 1;
}

free(message);
free(signature);

return 1;
}



int main(int argc, char** argv)
{
int passed = 0;
int tests_run = 0;

// printNewKeypair(Picnic_L1_full);
passed += LowMC_test_vectorL1_1(); tests_run++;
passed += LowMC_test_vectorL1_2(); tests_run++;
passed += LowMC_test_vectorL1_3(); tests_run++;
passed += LowMC_test_vectorL3_1(); tests_run++;
passed += LowMC_test_vectorL3_2(); tests_run++;
passed += LowMC_test_vectorL3_3(); tests_run++;
passed += LowMC_test_vectorL5_1(); tests_run++;
passed += LowMC_test_vectorL5_2(); tests_run++;
passed += LowMC_test_vectorL5_3(); tests_run++;
passed += test_serialization_L1(); tests_run++;

passed += LowMC_test_vectorL1_129_1(); tests_run++;
passed += LowMC_test_vectorL1_129_2(); tests_run++;
passed += LowMC_test_vectorL1_129_3(); tests_run++;
passed += LowMC_test_vectorL1_129_4(); tests_run++;

passed += LowMC_test_vectorL3_192_1(); tests_run++;
passed += LowMC_test_vectorL3_192_2(); tests_run++;
passed += LowMC_test_vectorL3_192_3(); tests_run++;
passed += LowMC_test_vectorL3_192_4(); tests_run++;

passed += LowMC_test_vectorL5_255_1(); tests_run++;
passed += LowMC_test_vectorL5_255_2(); tests_run++;
passed += LowMC_test_vectorL5_255_3(); tests_run++;
passed += LowMC_test_vectorL5_255_4(); tests_run++;

passed += test_sign_Picnic3_L1(); tests_run++;
passed += test_sign_Picnic3_L3(); tests_run++;
passed += test_sign_Picnic3_L5(); tests_run++;
passed += test_sign_Picnic_L1_full(); tests_run++;
passed += test_sign_Picnic_L3_full(); tests_run++;
passed += test_sign_Picnic_L5_full(); tests_run++;

for(int i = Picnic3_L1; i <= Picnic3_L5; i++) {
passed += test_serialize_roundtrip_picnic3(i); tests_run++;
passed += test_sig_serialize_picnic3(i); tests_run++;
}

(void) argv; // unused
if(argc > 1) { /* If any command line args are given, run the extended, slow tests */
for(int i = Picnic_L1_FS; i < PARAMETER_SET_MAX_INDEX; i++) {
printf("Running extended sig tests for params %s\n", picnic_get_param_name(i));
int ret = picnic_test_modified_signatures(i);
if(ret != 1) {
printf("Failed\n");
}
passed += ret;
tests_run++;
}
}

printf("Ran %d tests, %d passed\n", tests_run, passed);

return tests_run - passed;
}

+ 3
- 3
test/ut.cpp Ver arquivo

@@ -3,7 +3,7 @@
#include <gtest/gtest.h>
#include <pqc/pqc.h>

TEST(Kyber,KEMOneOff) {
TEST(RoundTrip,KEM) {

for (int i=0; i<PQC_ALG_KEM_MAX; i++) {
const params_t *p = pqc_kem_alg_by_id(i);
@@ -25,9 +25,9 @@ TEST(Kyber,KEMOneOff) {
}
}

TEST(Kyber,SIGNOneOff) {
TEST(RoundTrip,SIGN) {

for (int i=0; i<PQC_ALG_SIG_MAX; i++) {
for (int i=PICNIC3L1; i<PQC_ALG_SIG_MAX; i++) {
const params_t *p = pqc_sig_alg_by_id(i);

uint8_t msg[1234];


Carregando…
Cancelar
Salvar