Merge remote-tracking branch 'upstream/master' into cp-update-picnic

Merged with upstream master.
This commit is contained in:
Christian Paquin 2018-01-25 10:25:18 -05:00
commit 38d4c6ad74
7 changed files with 425 additions and 43 deletions

2
.gitignore vendored
View File

@ -36,6 +36,8 @@ include
/test_sig
/test_rand
/test_aes
/minimal_kex_oqs
/minimal_sig_oqs
# Debug files
*.dSYM/

View File

@ -1,15 +1,17 @@
#!/bin/bash
if [[ $(nm -g liboqs.a | grep ' T ' | grep -E -v -i ' T [_]?[OQS|ntru|picnic|Keccak]') ]];
REGEX=' T [_]?(OQS|ntru|picnic|Keccak|.*SIKEp503|.*SIDHp503|.*SIKEp751|.*SIDHp751|.*shake128|.*shake256|rand_bytes|cpu_supports|uint64_from_char_array|uint64_to_char_array|print_hex|ntt_double|rec|aligned_alloc|aligned_free)'
if [[ $(nm -g liboqs.a | grep ' T ' | grep -E -v -i "$REGEX") ]];
then
tput setaf 1;
echo "Code contains the following non-namespaced global symbols; see https://github.com/open-quantum-safe/liboqs/wiki/Coding-conventions for function naming conventions.";
tput sgr 0
nm -g liboqs.a | grep ' T ' | grep -E -v -i ' T [_]?[OQS|ntru|picnic|Keccak]'
exit 1;
tput setaf 1;
echo "Code contains the following non-namespaced global symbols; see https://github.com/open-quantum-safe/liboqs/wiki/Coding-conventions for function naming conventions.";
tput sgr 0
nm -g liboqs.a | grep ' T ' | grep -E -v -i "$REGEX"
exit 1;
else
tput setaf 2;
echo "Code adheres to the project standards (global namespace).";
tput sgr 0
exit 0;
tput setaf 2;
echo "Code adheres to the project standards (global namespace).";
tput sgr 0
exit 0;
fi;

View File

@ -92,9 +92,6 @@ if USE_SIDH_IQC
cp src/kex_sidh_iqc_ref/kex_sidh_iqc_ref.h $(includedir)/oqs
endif
noinst_bin_PROGRAMS = test_rand test_kex test_aes
libmerge_external.la:
if USE_SIG_PICNIC
mkdir -p temp && cp liboqs.a temp/ && cp src/sig_picnic/external/build/libpicnic_static.a temp/
@ -102,7 +99,13 @@ if USE_SIG_PICNIC
cd .. && rm -rf temp
endif
noinst_bin_PROGRAMS = test_rand test_kex test_aes test_sig
noinst_bin_PROGRAMS = test_kex test_aes test_rand
if USE_KEX_LWE_FRODO
noinst_bin_PROGRAMS += minimal_kex_oqs
endif
if USE_SIG_PICNIC
noinst_bin_PROGRAMS += test_sig minimal_sig_oqs
endif
noinst_bindir=$(prefix)/tests
test_kex_LDADD = liboqs.la -lm
@ -119,6 +122,7 @@ if USE_SIDH_IQC
test_kex_LDADD += -L$(GMP_DIR)/lib -lgmp
endif
if USE_SIG_PICNIC
test_sig_LDADD = liboqs.la -lm
test_sig_SOURCES = src/sig/test_sig.c
test_sig_CPPFLAGS = -I./include
@ -127,6 +131,33 @@ if USE_OPENSSL
test_sig_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
endif
minimal_sig_oqs_LDADD = liboqs.la -lm
minimal_sig_oqs_SOURCES = src/sig/minimal_sig_oqs.c
minimal_sig_oqs_CPPFLAGS = -I./include
minimal_sig_oqs_CPPFLAGS += $(AM_CPPFLAGS)
if USE_OPENSSL
minimal_sig_oqs_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
endif
endif # USE_SIG_PICNIC
if USE_KEX_LWE_FRODO
minimal_kex_oqs_LDADD = liboqs.la -lm
minimal_kex_oqs_SOURCES = src/kex/minimal_kex_oqs.c
minimal_kex_oqs_CPPFLAGS = -I./include
minimal_kex_oqs_CPPFLAGS += $(AM_CPPFLAGS)
if USE_MCBITS
minimal_kex_oqs_LDADD += -L${SODIUM_DIR}/lib -lsodium
endif
if USE_OPENSSL
minimal_kex_oqs_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
endif
if USE_SIDH_IQC
minimal_kex_oqs_LDADD += -L$(GMP_DIR)/lib -lgmp
endif
endif # USE_KEX_LWE_FRODO
test_aes_LDADD = liboqs.la -lm
test_aes_SOURCES = src/crypto/aes/test_aes.c
test_aes_CPPFLAGS = -I./include
@ -147,15 +178,22 @@ else
if USE_AES_NI
test_rand_CPPFLAGS += -maes -msse2
endif
endif
endif # USE_OPENSSL
test: clean-tests
make
./test_kex --quiet
./test_rand --quiet
./test_aes
if USE_SIG_PICNIC
./test_sig
./minimal_sig_oqs
endif
if USE_KEX_LWE_FRODO
./minimal_kex_oqs
endif
links:
$(MKDIR_P) include/oqs
cp -f config.h include/oqs
@ -190,13 +228,19 @@ endif
clean-local:
rm -f liboqs.a
rm -rf include
if USE_KEX_LWE_FRODO
rm -f minimal_kex_oqs
endif
if USE_SIG_PICNIC
rm -f test_sig
rm -f minimal_sig_oqs
endif
if USE_SIDH_IQC
rm -f sample_params
endif
clean-tests:
rm -f test_kex test_rand test_aes test_sig
rm -f test_kex test_rand test_aes
prettyprint:
find src -name '*.c' -o -name '*.h' | grep -v sig_picnic/external* | grep -v "kex_rlwe_newhope/avx2" | grep -v "kex_sidh_msr" | xargs $(CLANGFORMAT) -style=file -i

View File

@ -69,7 +69,8 @@ This will generate:
- `test_aes`: A simple test harness for AES. This will test the correctness of the C implementation (and of the AES-NI implementation, if not disabled) of AES, and will compare the speed of these implementations against OpenSSL's AES implementation.
- `test_kex`: A simple test harness for the default key exchange algorithm. This will output key exchange messages; indicate whether the parties agree on the session key or not over a large number of trials; and measure the distance of the sessions keys from uniform using statistical distance.
- `test_sig`: A simple test harness for the signature algorithms.
- `minimal_kex_oqs`: A minimal runnable example showing the usage of KEX API.
- `minimal_sig_oqs`: A minimal runnable example showing the usage of SIG API.
### Running
To run the tests, simply type:

180
src/kex/minimal_kex_oqs.c Normal file
View File

@ -0,0 +1,180 @@
/*
* minimal_kex_oqs.c
*
* Minimal example of a Diffie-Hellman post-quantum key exchange method
* implemented in liboqs.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oqs/common.h>
#include <oqs/kex.h>
#include <oqs/rand.h>
/* Displays hexadecimal strings */
void disp_hex_string(const char *label, uint8_t *str, size_t len);
/* Partially displays hexadecimal strings */
void disp_part_hex_string(const char *label, uint8_t *str, size_t len,
size_t sub_len);
/* Cleaning up memory etc */
void cleanup(uint8_t *alice_msg, size_t alice_msg_len, uint8_t *alice_key,
size_t alice_key_len, uint8_t *bob_msg, size_t bob_msg_len,
uint8_t *bob_key, size_t bob_key_len, void *alice_priv,
OQS_KEX *kex, OQS_RAND *rnd);
int main(void) {
/* Key exchange parameters */
void *alice_priv = NULL; // Alice's private key
uint8_t *alice_msg = NULL; // Alice's message
size_t alice_msg_len = 0; // Alice's message length
uint8_t *alice_key = NULL; // Alice's final key
size_t alice_key_len = 0; // Alice's final key length
uint8_t *bob_msg = NULL; // Bob's message
size_t bob_msg_len = 0; // Bob's message length
uint8_t *bob_key = NULL; // Bob's final key
size_t bob_key_len = 0; // Bob's final key length
/* Setup the key exchange protocol */
enum OQS_KEX_alg_name alg_name = OQS_KEX_alg_lwe_frodo; // Alg. name
const uint8_t *seed = (unsigned char *) "01234567890123456"; // Rand. seed
const size_t seed_len = 16; // Seed length
const char *named_parameters = "recommended"; // Named params.
OQS_RAND *rnd = NULL; // Source of randomness
OQS_KEX *kex = NULL; // OQS_KEX structure
/* Setup the source of randomness */
rnd = OQS_RAND_new(OQS_RAND_alg_urandom_chacha20);
if (rnd == NULL) {
eprintf("ERROR: Setting up the randomness source!\n");
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
/* Populate the OQS_KEX structure, here's where liboqs sets up
* the specific details of the selected KEX implementation */
kex = OQS_KEX_new(rnd, alg_name, seed, seed_len, named_parameters);
if (kex == NULL) {
eprintf("ERROR: OQS_KEX_new failed!\n");
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
/* Proceed with the Diffie-Hellman key exchange mechanism */
printf("===============================================================\n");
printf("Diffie-Hellman post-quantum key exchange: %s\n", kex->method_name);
printf("===============================================================\n");
/* Alice's initial message */
int success = OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len);
if (success != OQS_SUCCESS) {
eprintf("ERROR: OQS_KEX_alice_0 failed!\n");
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
disp_part_hex_string("Alice message", alice_msg, alice_msg_len, 20);
/* Bob's response */
success = OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len,
&bob_key, &bob_key_len);
if (success != OQS_SUCCESS) {
eprintf("ERROR: OQS_KEX_bob failed!\n");
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
disp_part_hex_string("Bob message", bob_msg, bob_msg_len, 20);
disp_hex_string("Bob session key", bob_key, bob_key_len);
/* Alice processes Bob's response */
success = OQS_KEX_alice_1(kex, alice_priv, bob_msg, bob_msg_len, &alice_key,
&alice_key_len);
if (success != OQS_SUCCESS) {
eprintf("ERROR: OQS_KEX_alice_1 failed!\n");
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
disp_hex_string("Alice session key", alice_key, alice_key_len);
/* Compare key lengths */
if (alice_key_len != bob_key_len) {
eprintf("ERROR: Alice's session key and Bob's session keys "
"have different lengths (%zu vs %zu)!\n",
alice_key_len, bob_key_len);
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
/* Compare key values */
success = memcmp(alice_key, bob_key, alice_key_len);
if (success != 0) {
eprintf("ERROR: Alice's session key and Bob's session "
"key are not equal!\n");
disp_hex_string("Alice session key", alice_key, alice_key_len);
disp_hex_string("Bob session key", bob_key, bob_key_len);
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_FAILURE;
}
/* Success and clean-up */
printf("Alice and Bob's session keys match.\n");
cleanup(alice_msg, alice_msg_len, alice_key, alice_key_len, bob_msg,
bob_msg_len, bob_key, bob_key_len, alice_priv, kex, rnd);
return EXIT_SUCCESS;
}
void disp_hex_string(const char *label, uint8_t *str, size_t len) {
printf("%-20s (%4zu bytes): ", label, len);
for (size_t i = 0; i < (len); i++) {
printf("%02X", ((unsigned char *) (str))[i]);
}
printf("\n");
}
void disp_part_hex_string(const char *label, uint8_t *str, size_t len,
size_t sub_len) {
printf("%-20s (%4zu bytes): ", label, len);
for (size_t i = 0; i < (sub_len); i++) {
printf("%02X", ((unsigned char *) (str))[i]);
}
printf("...");
for (size_t i = 0; i < (sub_len); i++) {
printf("%02X", ((unsigned char *) (str))[len - sub_len + i]);
}
printf("\n");
}
void cleanup(uint8_t *alice_msg, size_t alice_msg_len, uint8_t *alice_key,
size_t alice_key_len, uint8_t *bob_msg, size_t bob_msg_len,
uint8_t *bob_key, size_t bob_key_len, void *alice_priv,
OQS_KEX *kex, OQS_RAND *rnd) {
/* Secure cleaning */
OQS_MEM_secure_free(alice_msg, alice_msg_len);
OQS_MEM_secure_free(alice_key, alice_key_len);
OQS_MEM_secure_free(bob_msg, bob_msg_len);
OQS_MEM_secure_free(bob_key, bob_key_len);
OQS_KEX_alice_priv_free(kex, alice_priv);
OQS_KEX_free(kex);
OQS_RAND_free(rnd);
}

View File

@ -1,24 +0,0 @@
/**
* \file kex_sike_msr.h
* \brief Header for SIKE key exchange protocol from the Microsoft SIDH library
*/
#ifndef __OQS_KEX_SIKE_MSR_H
#define __OQS_KEX_SIKE_MSR_H
#include <stddef.h>
#include <stdint.h>
#include <oqs/kex.h>
#include <oqs/rand.h>
OQS_KEX *OQS_KEX_sike_msr_new(OQS_RAND *rand, const char *named_parameters);
int OQS_KEX_sike_msr_alice_0(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len);
int OQS_KEX_sike_msr_bob(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len);
int OQS_KEX_sike_msr_alice_1(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len);
void OQS_KEX_sike_msr_alice_priv_free(OQS_KEX *k, void *alice_priv);
void OQS_KEX_sike_msr_free(OQS_KEX *k);
#endif

177
src/sig/minimal_sig_oqs.c Normal file
View File

@ -0,0 +1,177 @@
/*
* minimal_sig_oqs.c
*
* Minimal example of a post-quantum signature method implemented in liboqs.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <oqs/common.h>
#include <oqs/rand.h>
#include <oqs/sig.h>
/* Displays hexadecimal strings */
void disp_hex_string(const char *label, uint8_t *str, size_t len);
/* Partially displays hexadecimal strings */
void disp_part_hex_string(const char *label, uint8_t *str, size_t len,
size_t sub_len);
/* Cleaning up memory etc */
void cleanup(uint8_t *msg, size_t msg_len, uint8_t *sig, size_t sig_len,
uint8_t *pub, uint8_t *priv, OQS_SIG *s, OQS_RAND *rnd);
int main(void) {
uint8_t *priv = NULL; // Private key
uint8_t *pub = NULL; // Public key
uint8_t *msg = NULL; // Message
size_t msg_len = 0; // Message's length
uint8_t *sig = NULL; // Signature
size_t sig_len = 0; // Signature's length
enum OQS_SIG_algid alg_name = OQS_SIG_picnic_default; // Algorithm name
// Equivalent to OQS_SIG_picnic_L1_FS
OQS_RAND *rnd = NULL; // Source of randomness
OQS_SIG *s = NULL; // OQS_SIG structure
/* Setup the source of randomness */
rnd = OQS_RAND_new(OQS_RAND_alg_urandom_chacha20);
if (rnd == NULL) {
eprintf("ERROR: Setting up the randomness source!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Populate the OQS_SIG structure, here's where liboqs sets up
* the specific details of the selected SIG implementation */
s = OQS_SIG_new(rnd, alg_name);
if (s == NULL) {
eprintf("ERROR: OQS_SIG_new failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Proceed with the signature generation */
printf("====================================\n");
printf("Post-quantum signature: %s\n", s->method_name);
printf("====================================\n");
/* Private key memory allocation */
priv = malloc(s->priv_key_len);
if (priv == NULL) {
eprintf("ERROR: priv malloc failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Public key memory generation */
pub = malloc(s->pub_key_len);
if (pub == NULL) {
eprintf("ERROR: pub malloc failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Generates the signature key pair */
int success = OQS_SIG_keygen(s, priv, pub);
if (success != OQS_SUCCESS) {
eprintf("ERROR: OQS_SIG_keygen failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
disp_hex_string("Private key", priv, s->priv_key_len);
disp_hex_string("Public key", pub, s->pub_key_len);
/* Allocates the memory for the message to sign */
msg_len = 64; // TODO: randomize based on scheme's max length
msg = malloc(msg_len);
if (msg == NULL) {
eprintf("ERROR: msg malloc failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Generates a random message to sign */
OQS_RAND_n(rnd, msg, msg_len);
disp_hex_string("Message", msg, msg_len);
/* Allocates memory for the signature */
sig_len = s->max_sig_len;
sig = malloc(sig_len);
if (sig == NULL) {
eprintf("ERROR: sig malloc failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Signs the message */
success = OQS_SIG_sign(s, priv, msg, msg_len, sig, &sig_len);
if (success != OQS_SUCCESS) {
eprintf("ERROR: OQS_SIG_sign failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
if (sig_len > 40) {
// only print the parts of the sig if too long
disp_part_hex_string("Signature", sig, sig_len, 20);
}
/* Verification */
success = OQS_SIG_verify(s, pub, msg, msg_len, sig, sig_len);
if (success != OQS_SUCCESS) {
eprintf("ERROR: OQS_SIG_verify failed!\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_FAILURE;
}
/* Success and clean-up */
printf("Signature is valid.\n");
cleanup(msg, msg_len, sig, sig_len, pub, priv, s, rnd);
return EXIT_SUCCESS;
}
void disp_hex_string(const char *label, uint8_t *str, size_t len) {
printf("%-20s (%4zu bytes): ", label, len);
for (size_t i = 0; i < (len); i++) {
printf("%02X", ((unsigned char *) (str))[i]);
}
printf("\n");
}
void disp_part_hex_string(const char *label, uint8_t *str, size_t len,
size_t sub_len) {
printf("%-20s (%4zu bytes): ", label, len);
for (size_t i = 0; i < (sub_len); i++) {
printf("%02X", ((unsigned char *) (str))[i]);
}
printf("...");
for (size_t i = 0; i < (sub_len); i++) {
printf("%02X", ((unsigned char *) (str))[len - sub_len + i]);
}
printf("\n");
}
/* Cleaning up memory etc */
void cleanup(uint8_t *msg, size_t msg_len, uint8_t *sig, size_t sig_len,
uint8_t *pub, uint8_t *priv, OQS_SIG *s, OQS_RAND *rnd) {
OQS_MEM_secure_free(msg, msg_len);
OQS_MEM_secure_free(sig, sig_len);
OQS_MEM_secure_free(pub, s->pub_key_len);
OQS_MEM_secure_free(priv, s->priv_key_len);
OQS_SIG_free(s);
OQS_RAND_free(rnd);
}