Skip to content

Commit

Permalink
Update implementation to spec version 2.1
Browse files Browse the repository at this point in the history
Update the reference implementation to spec version 2.1, submitted to
the 2nd round of the NIST competition. This change breaks backwards
compatibility.

Signed-off-by: Greg Zaverucha <[email protected]>
  • Loading branch information
zaverucha committed Apr 12, 2019
1 parent a7cde50 commit 3198218
Show file tree
Hide file tree
Showing 26 changed files with 718 additions and 145 deletions.
16 changes: 11 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@
CC=gcc
WARNING_FLAGS=-Wall -Wextra -Wpedantic -Werror
CFLAGS= -O2 -march=native $(WARNING_FLAGS) -std=gnu99 -D__LINUX__ -D__X64__ -I./sha3
CFLAGS_DEBUG= -g -march=native $(WARNING_FLAGS) -std=gnu99 -fsanitize=address -D__LINUX__ -D__X64__ -I./sha3
CFLAGS_DEBUG= -g -march=native $(WARNING_FLAGS) -std=gnu99 -D__LINUX__ -D__X64__ -I./sha3
NISTKATFLAGS = -Wno-sign-compare -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-unused-result
SHA3LIB=libshake.a
SHA3_PATH=sha3
LDFLAGS= $(SHA3_PATH)/$(SHA3LIB)

SOURCES= picnic_impl.c picnic2_impl.c picnic.c lowmc_constants.c
PICNIC_OBJECTS= picnic_impl.o picnic2_impl.o tree.o picnic.o lowmc_constants.o hash.o picnic_types.o
PICNIC_OBJECTS= picnic_impl.o picnic2_impl.o picnic.o lowmc_constants.o hash.o picnic_types.o tree.o
PICNIC_LIB= libpicnic.a
EXECUTABLE_EXAMPLE=example
EXECUTABLE_TESTVECTORS=create_test_vectors
EXECUTABLE_UNITTEST=unit_test
EXECUTABLE_BENCHMARK=bench
EXECUTABLE_KATSTEST=kats_test
EXECUTABLE_TREETEST=tree_test

all: $(SHA3LIB) $(SOURCES) $(PICNIC_LIB) $(EXECUTABLE_EXAMPLE) $(EXECUTABLE_TESTVECTORS) $(EXECUTABLE_UNITTEST) $(EXECUTABLE_KATSTEST)
all: $(SHA3LIB) $(SOURCES) $(PICNIC_LIB) $(EXECUTABLE_EXAMPLE) $(EXECUTABLE_TESTVECTORS) $(EXECUTABLE_UNITTEST) $(EXECUTABLE_KATSTEST) $(EXECUTABLE_TREETEST)

$(SHA3LIB):
$(MAKE) -C $(SHA3_PATH)
Expand All @@ -31,6 +33,9 @@ $(EXECUTABLE_EXAMPLE): $(PICNIC_LIB)
$(EXECUTABLE_UNITTEST): $(PICNIC_LIB)
$(CC) $(@).c $(CFLAGS) $(PICNIC_LIB) -o $@ $(LDFLAGS)

$(EXECUTABLE_TREETEST): $(PICNIC_LIB)
$(CC) $(@).c $(CFLAGS) $(PICNIC_LIB) -o $@ $(LDFLAGS)

$(EXECUTABLE_TESTVECTORS): $(PICNIC_LIB)
$(CC) $(@).c $(CFLAGS) $(PICNIC_LIB) -o $@ $(LDFLAGS)

Expand All @@ -40,21 +45,22 @@ $(EXECUTABLE_BENCHMARK): $(PICNIC_LIB)
$(EXECUTABLE_KATSTEST): $(PICNIC_LIB)
$(CC) $(@).c $(CFLAGS) $(PICNIC_LIB) -o $@ $(LDFLAGS)


.c.o:
$(CC) -c $(CFLAGS) $< -o $@

$(PICNIC_LIB): $(PICNIC_OBJECTS)
ar rcs $@ $^


clean:
rm *.o 2>/dev/null || true
rm *.exe 2>/dev/null || true
rm $(EXECUTABLE_TESTVECTORS) 2>/dev/null || true
rm $(EXECUTABLE_EXAMPLE) 2>/dev/null || true
rm $(EXECUTABLE_UNITTEST) 2>/dev/null || true
rm $(EXECUTABLE_TREETEST) 2>/dev/null || true
rm $(EXECUTABLE_KATSTEST) 2>/dev/null || true
rm $(EXECUTABLE_TESTVECTORS) 2>/dev/null || true
rm $(EXECUTABLE_BENCHMARK) 2>/dev/null || true
rm $(PICNIC_LIB) 2>/dev/null || true
$(MAKE) -C $(SHA3_PATH) clean

13 changes: 2 additions & 11 deletions create_test_vectors.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#define MSG_LEN 500

/* Defined in picni_impl.c */
void printHex(const char* s, uint8_t* data, size_t len);
void printHex(const char* s, const uint8_t* data, size_t len);

int createTestVectors(picnic_params_t parameters)
{
Expand Down Expand Up @@ -88,7 +88,7 @@ int createTestVectors(picnic_params_t parameters)
printf("\n");

/* Print the parsed signature */
print_siganture(signature, signature_len, parameters);
print_signature(signature, signature_len, parameters);

printf("verify: ");
ret = picnic_verify(&pk, message, sizeof(message), signature, signature_len);
Expand All @@ -111,15 +111,6 @@ int main(int argc, char** argv)
printf("provide an integer specifying the parameter set\n");
exit(-1);
}
picnic_params_t parameters = atoi(argv[1]);

if (parameters == Picnic2_L1_FS ||
parameters == Picnic2_L3_FS ||
parameters == Picnic2_L5_FS ) {
printf("Picnic2 parameter sets not supported yet\n");
exit(-1);
}


createTestVectors(atoi(argv[1]));

Expand Down
29 changes: 8 additions & 21 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@
#include "hash.h"
#include <stdio.h>
#include <assert.h>
#if defined(__WINDOWS__)
#include <Windows.h>
#include <bcrypt.h>
#else
#include <endian.h>
#endif

#include "sha3/brg_endian.h"

void HashUpdate(HashInstance* ctx, const uint8_t* data, size_t byteLen)
{
Expand Down Expand Up @@ -65,27 +59,20 @@ void HashSqueeze(HashInstance* ctx, uint8_t* digest, size_t byteLen)

uint16_t toLittleEndian(uint16_t x)
{
#if defined(__WINDOWS__)
#if BYTE_ORDER == LITTLE_ENDIAN
return x;
#else
return __builtin_bswap16(x);
#endif
#if (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)
return (x << 8) | (x >> 8);
#else
return htole16(x);
return x;
#endif

}

uint16_t fromLittleEndian(uint16_t x)
{
#if defined(__WINDOWS__)
#if BYTE_ORDER == LITTLE_ENDIAN
return x;
#else
return __builtin_bswap16(x);
#endif
#if (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN)
return (x << 8) | (x >> 8);
#else
return le16toh(x);
return x;
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static const uint8_t HASH_PREFIX_NONE = -1;
static const uint8_t HASH_PREFIX_0 = 0;
static const uint8_t HASH_PREFIX_1 = 1;
static const uint8_t HASH_PREFIX_2 = 2;
static const uint8_t HASH_PREFIX_3 = 2;
static const uint8_t HASH_PREFIX_3 = 3;
static const uint8_t HASH_PREFIX_4 = 4;
static const uint8_t HASH_PREFIX_5 = 5;

Expand Down
5 changes: 2 additions & 3 deletions kats/kat_l1_fs.txt

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions kats/kat_l1_ur.txt

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions kats/kat_l3_fs.txt

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions kats/kat_l3_ur.txt

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion kats/kat_l5_fs.txt

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion kats/kat_l5_ur.txt

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions kats/kat_picnic2_l1_fs.txt

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions kats/kat_picnic2_l3_fs.txt

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions kats/kat_picnic2_l5_fs.txt

Large diffs are not rendered by default.

116 changes: 81 additions & 35 deletions kats_test.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* This file is part of the optimized 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.h"

#include <memory.h>
Expand All @@ -8,17 +17,38 @@
#ifndef KATDIR
#define KATDIR "kats"
#endif
#define PICNIC_CONCAT2(a, b) a##_##b
#define PICNIC_CONCAT(a, b) PICNIC_CONCAT2(a, b)

#define LOWMC_BLOCK_SIZE_Picnic_L1_FS 16
#define LOWMC_BLOCK_SIZE_Picnic_L1_UR 16
#define LOWMC_BLOCK_SIZE_Picnic_L3_FS 24
#define LOWMC_BLOCK_SIZE_Picnic_L3_UR 24
#define LOWMC_BLOCK_SIZE_Picnic_L5_FS 32
#define LOWMC_BLOCK_SIZE_Picnic_L5_UR 32
#define LOWMC_BLOCK_SIZE_Picnic2_L1_FS 16
#define LOWMC_BLOCK_SIZE_Picnic2_L3_FS 24
#define LOWMC_BLOCK_SIZE_Picnic2_L5_FS 32

#define LOWMC_BLOCK_SIZE(p) PICNIC_CONCAT(LOWMC_BLOCK_SIZE, p)

#define MAX_LOWMC_ROUNDS 38
#define MAX_LOWMC_SBOXES 10
#define MAX_ROUNDS 438

#define PICNIC_PRIVATE_KEY_SIZE(p) (1 + 3 * LOWMC_BLOCK_SIZE(p))
#define PICNIC_PUBLIC_KEY_SIZE(p) (1 + 2 * LOWMC_BLOCK_SIZE(p))

typedef struct {
size_t mlen;
uint8_t *msg;
uint8_t* msg;
uint8_t pk[PICNIC_MAX_PUBLICKEY_SIZE];
uint8_t sk[PICNIC_MAX_PRIVATEKEY_SIZE];
size_t smlen;
uint8_t *sm;
uint8_t* sm;
} test_vector_t;

static void clear_test_vector(test_vector_t *tv) {
static void clear_test_vector(test_vector_t* tv) {
free(tv->msg);
free(tv->sm);
memset(tv, 0, sizeof(*tv));
Expand All @@ -36,10 +66,10 @@ static uint8_t parse_hex_c(const char c) {
}
}

static int parse_hex(uint8_t *dst, const char *src, size_t len) {
static int parse_hex(uint8_t* dst, const char* src, size_t len) {
for (size_t s = 0; s < len; ++s, src += 2, ++dst) {
uint8_t high = parse_hex_c(src[0]);
uint8_t low = parse_hex_c(src[1]);
uint8_t low = parse_hex_c(src[1]);
if (high == UINT8_MAX || low == UINT8_MAX) {
printf("parse_hex failed\n");
return -1;
Expand All @@ -49,9 +79,8 @@ static int parse_hex(uint8_t *dst, const char *src, size_t len) {
return 0;
}

static int read_test_vector(FILE *file, test_vector_t *tv, size_t pks,
size_t sks) {
char *line = NULL;
static int read_test_vector(FILE* file, test_vector_t* tv, size_t pks, size_t sks) {
char* line = NULL;
size_t len = 0;
ssize_t nread;
bool expect_data = false;
Expand Down Expand Up @@ -79,8 +108,7 @@ static int read_test_vector(FILE *file, test_vector_t *tv, size_t pks,
if (sscanf(line + 7, "%zu", &tv->mlen) != 1) {
goto err;
}
} else if (strncmp(line, "msg = ", 6) == 0 && tv->mlen &&
uread >= 2 * tv->mlen + 6) {
} else if (strncmp(line, "msg = ", 6) == 0 && tv->mlen && uread >= 2 * tv->mlen + 6) {
// read message
tv->msg = calloc(1, tv->mlen);
if (parse_hex(tv->msg, line + 6, tv->mlen) == -1) {
Expand All @@ -101,8 +129,7 @@ static int read_test_vector(FILE *file, test_vector_t *tv, size_t pks,
if (sscanf(line + 8, "%zu", &tv->smlen) != 1) {
goto err;
}
} else if (strncmp(line, "sm = ", 5) == 0 && tv->smlen &&
uread >= 2 * tv->smlen + 5) {
} else if (strncmp(line, "sm = ", 5) == 0 && tv->smlen && uread >= 2 * tv->smlen + 5) {
// read signature
tv->sm = calloc(1, tv->smlen);
if (parse_hex(tv->sm, line + 5, tv->smlen) == -1) {
Expand All @@ -127,14 +154,13 @@ static int read_test_vector(FILE *file, test_vector_t *tv, size_t pks,
return -1;
}

static int run_picnic_test(const uint8_t *msg, size_t msg_len,
const uint8_t *pk, size_t pk_len, const uint8_t *sk,
size_t sk_len, const uint8_t *sig, size_t sig_len) {
static int run_picnic_test(const uint8_t* msg, size_t msg_len, const uint8_t* pk, size_t pk_len,
const uint8_t* sk, size_t sk_len, const uint8_t* sig, size_t sig_len) {
picnic_privatekey_t private_key;
picnic_publickey_t public_key;
size_t signature_len = sig_len + 5000;

uint8_t *signature = malloc(signature_len);
uint8_t* signature = malloc(signature_len);

int ret = picnic_read_private_key(&private_key, sk, sk_len);
if (ret != 0) {
Expand Down Expand Up @@ -185,25 +211,22 @@ static int run_picnic_test(const uint8_t *msg, size_t msg_len,
return 0;
}

static int run_test_vectors_from_file(const char *path, size_t pks,
size_t sks) {
FILE *file = fopen(path, "r");
static int run_test_vectors_from_file(const char* path, size_t pks, size_t sks) {
FILE* file = fopen(path, "r");
if (!file) {
return 0;
}

size_t vectors_run = 0;
size_t vectors_run = 0;
size_t vectors_succeeded = 0;
test_vector_t tv = {0};
test_vector_t tv = {0, NULL, {0}, {0}, 0, NULL};
while (read_test_vector(file, &tv, pks, sks) != -1) {
// Test vectors generated for NIST have message length and the message at
// the beginning.
// Test vectors generated for NIST have message length and the message at the beginning.
const size_t offset = tv.mlen + sizeof(uint32_t);

++vectors_run;
vectors_succeeded +=
run_picnic_test(tv.msg, tv.mlen, tv.pk, pks, tv.sk, sks, tv.sm + offset,
tv.smlen - offset);
run_picnic_test(tv.msg, tv.mlen, tv.pk, pks, tv.sk, sks, tv.sm + offset, tv.smlen - offset);
clear_test_vector(&tv);
};
fclose(file);
Expand All @@ -212,38 +235,61 @@ static int run_test_vectors_from_file(const char *path, size_t pks,
}

static int picnic_test_vector_L1FS(void) {
return run_test_vectors_from_file(KATDIR "/kat_l1_fs.txt", 33, 49);
return run_test_vectors_from_file(KATDIR "/kat_l1_fs.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic_L1_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L1_FS));
}

static int picnic_test_vector_L1UR(void) {
return run_test_vectors_from_file(KATDIR "/kat_l1_ur.txt", 33, 49);
return run_test_vectors_from_file(KATDIR "/kat_l1_ur.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic_L1_UR),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L1_FS));
}

static int picnic_test_vector_L3FS(void) {
return run_test_vectors_from_file(KATDIR "/kat_l3_fs.txt", 49, 73);
return run_test_vectors_from_file(KATDIR "/kat_l3_fs.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic_L3_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L3_FS));
}

static int picnic_test_vector_L3UR(void) {
return run_test_vectors_from_file(KATDIR "/kat_l3_ur.txt", 49, 73);
return run_test_vectors_from_file(KATDIR "/kat_l3_ur.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic_L3_UR),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L3_FS));
}

static int picnic_test_vector_L5FS(void) {
return run_test_vectors_from_file(KATDIR "/kat_l5_fs.txt", 65, 97);
return run_test_vectors_from_file(KATDIR "/kat_l5_fs.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic_L5_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L5_FS));
}

static int picnic_test_vector_L5UR(void) {
return run_test_vectors_from_file(KATDIR "/kat_l5_ur.txt", 65, 97);
return run_test_vectors_from_file(KATDIR "/kat_l5_ur.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic_L5_UR),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L5_FS));
}

static int picnic2_test_vector_L1FS(void) {
return run_test_vectors_from_file(KATDIR "/kat_picnic2_l1_fs.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic2_L1_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic2_L1_FS));
}

static int picnic2_test_vector_L3FS(void) {
return run_test_vectors_from_file(KATDIR "/kat_picnic2_l3_fs.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic2_L3_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic2_L3_FS));
}

static int picnic2_test_vector_L5FS(void) {
return run_test_vectors_from_file(KATDIR "/kat_picnic2_l5_fs.txt", PICNIC_PUBLIC_KEY_SIZE(Picnic2_L5_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic2_L5_FS));
}

typedef int (*test_fn_t)(void);

static const test_fn_t tests[] = {
picnic_test_vector_L1FS, picnic_test_vector_L1UR, picnic_test_vector_L3FS,
picnic_test_vector_L3UR, picnic_test_vector_L5FS, picnic_test_vector_L5UR};
static const test_fn_t tests[] = {picnic_test_vector_L1FS, picnic_test_vector_L1UR,
picnic_test_vector_L3FS, picnic_test_vector_L3UR,
picnic_test_vector_L5FS, picnic_test_vector_L5UR,
picnic2_test_vector_L1FS, picnic2_test_vector_L3FS,
picnic2_test_vector_L5FS};

static const size_t num_tests = sizeof(tests) / sizeof(tests[0]);

int main() {
int main(void) {
int ret = 0;
for (size_t s = 0; s < num_tests; ++s) {
const int t = tests[s]();
Expand Down
Loading

0 comments on commit 3198218

Please sign in to comment.