Skip to content

Commit

Permalink
Merge pull request #46 from patricklonga/master
Browse files Browse the repository at this point in the history
Add constant-time and undefined behavior sanitizer tests, add continuous integration tests on GitHub actions
  • Loading branch information
patricklonga authored Jun 7, 2021
2 parents 10b0f4d + 2b804aa commit 38eb452
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 15 deletions.
97 changes: 97 additions & 0 deletions .github/workflows/c.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Test C implementation

on:
push:
paths:
- '.github/workflows/c.yml'
- Makefile
- 'KAT/**'
- 'src/**'
- 'tests/**'
pull_request:
paths:
- '.github/workflows/c.yml'
- Makefile
- 'KAT/**'
- 'src/**'
- 'tests/**'

jobs:
test-basic:
runs-on: ubuntu-latest
strategy:
matrix:
opt_level: ['GENERIC', 'FAST']
steps:
- uses: actions/checkout@v2
- name: Build
env:
OPT_LEVEL: ${{ matrix.opt_level }}
run: make
- name: SIKEp434
run: make test434
- name: SIKEp503
run: make test503
- name: SIKEp610
run: make test610
- name: SIKEp751
run: make test751
- name: SIKEp434 KATs
run: sike434/PQCtestKAT_kem
- name: SIKEp503 KATs
run: sike503/PQCtestKAT_kem
- name: SIKEp610 KATs
run: sike610/PQCtestKAT_kem
- name: SIKEp751 KATs
run: sike751/PQCtestKAT_kem
test-sanitize:
runs-on: ubuntu-latest
strategy:
matrix:
opt_level: ['GENERIC', 'FAST']
sanitizer: ['address', 'undefined']
steps:
- uses: actions/checkout@v2
- name: Build
env:
OPT_LEVEL: ${{ matrix.opt_level }}
EXTRA_CFLAGS: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fsanitize=${{ matrix.sanitizer }} -fno-sanitize-recover=${{ matrix.sanitizer }}
run: make CC=clang-11
- name: SIKEp434
run: sike434/test_SIKE nobench
- name: SIKEp503
run: sike503/test_SIKE nobench
- name: SIKEp610
run: sike610/test_SIKE nobench
- name: SIKEp751
run: sike751/test_SIKE nobench
test-valgrind-constant-time:
runs-on: ubuntu-latest
strategy:
matrix:
opt_level: ['GENERIC', 'FAST']
steps:
- uses: actions/checkout@v2
- name: Install valgrind
run: sudo apt-get install -y valgrind
- name: Build
env:
DO_VALGRIND_CHECK: "TRUE"
OPT_LEVEL: ${{ matrix.opt_level }}
run: make CC=clang-11
- name: SIKEp434
env:
DO_VALGRIND_CHECK: "TRUE"
run: make test434
- name: SIKEp503
env:
DO_VALGRIND_CHECK: "TRUE"
run: make test503
- name: SIKEp610
env:
DO_VALGRIND_CHECK: "TRUE"
run: make test610
- name: SIKEp751
env:
DO_VALGRIND_CHECK: "TRUE"
run: make test751
43 changes: 40 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#### Makefile for compilation on Unix-like operative systems ####

OPT=-O3 # Optimization option by default

CC=clang
ifeq "$(CC)" "gcc"
COMPILER=gcc
Expand Down Expand Up @@ -65,7 +63,18 @@ ifeq "$(ARCHITECTURE)" "_S390X_"
ADDITIONAL_SETTINGS=-march=z10
endif

CFLAGS=$(OPT) -std=gnu11 $(ADDITIONAL_SETTINGS) -D $(ARCHITECTURE) -D __NIX__ -D $(USE_OPT_LEVEL) $(MULX) $(ADX)
VALGRIND_CFLAGS=
ifeq "$(DO_VALGRIND_CHECK)" "TRUE"
VALGRIND_CFLAGS= -g -O0 -DDO_VALGRIND_CHECK
endif

ifeq "$(EXTRA_CFLAGS)" ""
CFLAGS= -O3 # Optimization option by default
else
CFLAGS= $(EXTRA_CFLAGS)
endif
CFLAGS+= $(VALGRIND_CFLAGS)
CFLAGS+= -std=gnu11 $(ADDITIONAL_SETTINGS) -D $(ARCHITECTURE) -D __NIX__ -D $(USE_OPT_LEVEL) $(MULX) $(ADX)
LDFLAGS=-lm
ifeq "$(USE_OPT_LEVEL)" "_GENERIC_"
EXTRA_OBJECTS_434=objs434/fp_generic.o
Expand Down Expand Up @@ -320,6 +329,34 @@ KATS: lib434_for_KATs lib503_for_KATs lib610_for_KATs lib751_for_KATs lib434comp

check: tests

test434:
ifeq "$(DO_VALGRIND_CHECK)" "TRUE"
valgrind --tool=memcheck --error-exitcode=1 --max-stackframe=20480000 sike434/test_SIKE
else
sike434/test_SIKE
endif

test503:
ifeq "$(DO_VALGRIND_CHECK)" "TRUE"
valgrind --tool=memcheck --error-exitcode=1 --max-stackframe=20480000 sike503/test_SIKE
else
sike503/test_SIKE
endif

test610:
ifeq "$(DO_VALGRIND_CHECK)" "TRUE"
valgrind --tool=memcheck --error-exitcode=1 --max-stackframe=20480000 sike610/test_SIKE
else
sike610/test_SIKE
endif

test751:
ifeq "$(DO_VALGRIND_CHECK)" "TRUE"
valgrind --tool=memcheck --error-exitcode=1 --max-stackframe=20480000 sike751/test_SIKE
else
sike751/test_SIKE
endif

.PHONY: clean

clean:
Expand Down
24 changes: 23 additions & 1 deletion src/sike.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
#include <string.h>
#include "sha3/fips202.h"

#ifdef DO_VALGRIND_CHECK
#include <valgrind/memcheck.h>
#endif


int crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
{ // SIKE's key generation
Expand All @@ -16,13 +20,19 @@ int crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
// Generate lower portion of secret key sk <- s||SK
randombytes(sk, MSG_BYTES);
random_mod_order_B(sk + MSG_BYTES);
#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_UNDEFINED(sk, MSG_BYTES + SECRETKEY_B_BYTES);
#endif

// Generate public key pk
EphemeralKeyGeneration_B(sk + MSG_BYTES, pk);

// Append public key pk to secret key sk
memcpy(&sk[MSG_BYTES + SECRETKEY_B_BYTES], pk, CRYPTO_PUBLICKEYBYTES);

#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_DEFINED(sk, MSG_BYTES + SECRETKEY_B_BYTES);
#endif
return 0;
}

Expand All @@ -39,6 +49,9 @@ int crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk

// Generate ephemeralsk <- G(m||pk) mod oA
randombytes(temp, MSG_BYTES);
#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_UNDEFINED(temp, MSG_BYTES);
#endif
memcpy(&temp[MSG_BYTES], pk, CRYPTO_PUBLICKEYBYTES);
shake256(ephemeralsk, SECRETKEY_A_BYTES, temp, CRYPTO_PUBLICKEYBYTES+MSG_BYTES);
ephemeralsk[SECRETKEY_A_BYTES - 1] &= MASK_ALICE;
Expand All @@ -55,6 +68,9 @@ int crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk
memcpy(&temp[MSG_BYTES], ct, CRYPTO_CIPHERTEXTBYTES);
shake256(ss, CRYPTO_BYTES, temp, CRYPTO_CIPHERTEXTBYTES+MSG_BYTES);

#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_DEFINED(temp, MSG_BYTES);
#endif
return 0;
}

Expand All @@ -69,6 +85,9 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch
unsigned char h_[MSG_BYTES];
unsigned char c0_[CRYPTO_PUBLICKEYBYTES];
unsigned char temp[CRYPTO_CIPHERTEXTBYTES+MSG_BYTES];
#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_UNDEFINED(sk, CRYPTO_SECRETKEYBYTES);
#endif

// Decrypt
EphemeralSecretAgreement_B(sk + MSG_BYTES, ct, jinvariant_);
Expand All @@ -89,6 +108,9 @@ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned ch
ct_cmov(temp, sk, MSG_BYTES, selector);
memcpy(&temp[MSG_BYTES], ct, CRYPTO_CIPHERTEXTBYTES);
shake256(ss, CRYPTO_BYTES, temp, CRYPTO_CIPHERTEXTBYTES+MSG_BYTES);


#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_DEFINED(sk, CRYPTO_SECRETKEYBYTES);
#endif
return 0;
}
51 changes: 40 additions & 11 deletions tests/test_sike.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@

#include "../src/random/random.h"

#ifdef DO_VALGRIND_CHECK
#include <valgrind/memcheck.h>
#endif

// Benchmark and test parameters
#ifdef DO_VALGRIND_CHECK
#define TEST_LOOPS 1
#else
#if defined(GENERIC_IMPLEMENTATION) || (TARGET == TARGET_ARM)
#define BENCH_LOOPS 5 // Number of iterations per bench
#define TEST_LOOPS 5 // Number of iterations per test
#else
#define BENCH_LOOPS 100
#define TEST_LOOPS 10
#endif
#endif

#if defined(GENERIC_IMPLEMENTATION) || (TARGET == TARGET_ARM)
#define BENCH_LOOPS 5 // Number of iterations per bench
#else
#define BENCH_LOOPS 100
#endif


Expand All @@ -29,6 +39,14 @@ int cryptotest_kem()
uint32_t* pos = (uint32_t*)bytes;
bool passed = true;

#ifdef DO_VALGRIND_CHECK
if (!RUNNING_ON_VALGRIND) {
fprintf(stderr, "This test can only usefully be run inside valgrind.\n");
fprintf(stderr, "valgrind sikexxx/test_SIKE\n");
exit(1);
}
#endif

printf("\n\nTESTING ISOGENY-BASED KEY ENCAPSULATION MECHANISM %s\n", SCHEME_NAME);
printf("--------------------------------------------------------------------------------------------------------\n\n");

Expand All @@ -37,6 +55,10 @@ int cryptotest_kem()
crypto_kem_keypair(pk, sk);
crypto_kem_enc(ct, ss, pk);
crypto_kem_dec(ss_, ct, sk);
#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_DEFINED(ss, CRYPTO_BYTES);
VALGRIND_MAKE_MEM_DEFINED(ss_, CRYPTO_BYTES);
#endif

if (memcmp(ss, ss_, CRYPTO_BYTES) != 0) {
passed = false;
Expand All @@ -48,6 +70,10 @@ int cryptotest_kem()
*pos %= CRYPTO_CIPHERTEXTBYTES;
ct[*pos] ^= 1;
crypto_kem_dec(ss_, ct, sk);
#ifdef DO_VALGRIND_CHECK
VALGRIND_MAKE_MEM_DEFINED(ss, CRYPTO_BYTES);
VALGRIND_MAKE_MEM_DEFINED(ss_, CRYPTO_BYTES);
#endif

if (memcmp(ss, ss_, CRYPTO_BYTES) == 0) {
passed = false;
Expand Down Expand Up @@ -108,21 +134,24 @@ int cryptorun_kem()
}


int main()
int main(int argc, char **argv)
{
int Status = PASSED;

Status = cryptotest_kem(); // Test key encapsulation mechanism
Status = cryptotest_kem(); // Test key encapsulation mechanism
if (Status != PASSED) {
printf("\n\n Error detected: KEM_ERROR_SHARED_KEY \n\n");
return FAILED;
}

Status = cryptorun_kem(); // Benchmark key encapsulation mechanism
if (Status != PASSED) {
printf("\n\n Error detected: KEM_ERROR_SHARED_KEY \n\n");
return FAILED;

if ((argc > 1) && (strcmp("nobench", argv[1]) == 0)) {}
else {
Status = cryptorun_kem(); // Benchmark key encapsulation mechanism
if (Status != PASSED) {
printf("\n\n Error detected: KEM_ERROR_SHARED_KEY \n\n");
return FAILED;
}
}

return Status;
}
}

0 comments on commit 38eb452

Please sign in to comment.