Merge pull request #397 from open-quantum-safe/master-sync-with-nist

Sync common files on master with nist-branch
This commit is contained in:
Shravan Mishra 2018-10-03 22:43:53 -04:00 committed by GitHub
commit fa7cf526e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 732 additions and 108 deletions

View File

@ -70,16 +70,6 @@ matrix:
before_install:
- brew update
- brew install libsodium doxygen graphviz
- os: osx
compiler: clang
env:
- CC_OVERRIDE=clang
- AES_NI=0
- USE_OPENSSL=1
- OPENSSL_DIR=/usr/local/opt/openssl # openssl is a keg-only package
before_install:
- brew update
- brew install libsodium doxygen graphviz
- os: osx
compiler: clang
env:

View File

@ -8,16 +8,20 @@ set -e
source $(dirname $0)/defs.sh
# get the list of KEMs from the list of algorithm identifiers in enum OQS_KEM_alg_name in src/kem/kem.h
KEMS=`grep 'define OQS_KEM_alg_' src/kem/kem.h | grep -v 'default' | sed -e 's/^[^"]*"//' | sed -e 's/".*$//' | tr -d '[:blank:]'`
# get the list of KEMs and signatures from the list of algorithm identifiers src/kem/kem.h and src/sig/sig.h
# FIXME: temporarily disabling signature algorithms
ALGS=$(grep -E 'define OQS_(KEM|SIG)_alg_' src/kem/kem.h | grep -v 'default' | sed -e 's/^[^"]*"//' | sed -e 's/".*$//' | tr -d '[:blank:]')
# ALGS=$(grep -E 'define OQS_(KEM|SIG)_alg_' src/kem/kem.h src/sig/sig.h | grep -v 'default' | sed -e 's/^[^"]*"//' | sed -e 's/".*$//' | tr -d '[:blank:]')
RET=0
for kem in ${KEMS}; do
FOUND=`grep ${kem} docs/algorithms/*.md`
for alg in ${ALGS}; do
set +e
FOUND=$(grep ${alg} docs/algorithms/*.md)
set -e
if [[ -z "${FOUND}" ]];
then
${PRINT_RED}
echo "Could not find algorithm datasheet containing '${kem}'."
echo "Could not find algorithm datasheet containing '${alg}'."
${PRINT_RESET}
RET=1
fi
@ -26,7 +30,9 @@ done
if [[ "${RET}" == "0" ]];
then
${PRINT_GREEN}
echo "Algorithm datasheet present for all KEMs #defined in src/kem/kem.h.";
# FIXME: temporarily disabling signature algorithms
echo "Algorithm datasheet present for all algs #defined in src/kem/kem.h.";
# echo "Algorithm datasheet present for all algs #defined in src/kem/kem.h and src/sig/sig.h.";
${PRINT_RESET}
fi

View File

@ -12,7 +12,7 @@ RET=0
# We need to temporarily remove bash fail-on-error for the last command, because grep returns with error code 1 when there are no lines found
set +e
FREE=`find src -name '*.c' | grep -v upstream | xargs grep '[^_]free' | grep "free(" | grep -v 'IGNORE free-check'`
FREE=$(find src -name '*.c' | grep -v upstream | xargs grep '[^_]free' | grep "free(" | grep -v 'IGNORE free-check')
ERROR_CODE=$?
set -e

View File

@ -18,7 +18,7 @@ then
fi
# Make sure that there are no modified files to start with
MODIFIED=`git status -s`
MODIFIED=$(git status -s)
if [[ ! -z "${MODIFIED}" ]];
then
${PRINT_RED}
@ -29,22 +29,26 @@ then
fi;
# Find clang-format
TRY_CLANGFORMAT="clang-format-3.9"
TRY_CLANGFORMAT="/usr/local/Cellar/clang-format/2016-06-27/bin/clang-format"
if [[ ! -x $(which ${TRY_CLANGFORMAT}) ]];
then
TRY_CLANGFORMAT="clang-format"
TRY_CLANGFORMAT="clang-format-3.9"
if [[ ! -x $(which ${TRY_CLANGFORMAT}) ]];
then
${PRINT_RED}
echo "Cannot find clang-format."
${PRINT_RESET}
exit 1
TRY_CLANGFORMAT="clang-format"
if [[ ! -x $(which ${TRY_CLANGFORMAT}) ]];
then
${PRINT_RED}
echo "Cannot find clang-format."
${PRINT_RESET}
exit 1
fi
fi
fi
# Check clang-format version
set +e
CLANG_FORMAT_VERSION=`${TRY_CLANGFORMAT} -version | grep 3.9`
CLANG_FORMAT_VERSION=$(${TRY_CLANGFORMAT} -version | grep 3.9)
ERROR_CODE=$?
set -e
if [ ${ERROR_CODE} -ne 0 ];
@ -60,7 +64,7 @@ fi;
make prettyprint CLANGFORMAT=${TRY_CLANGFORMAT}
# Check if there are any modified files
MODIFIED=`git status -s`
MODIFIED=$(git status -s)
if [[ ! -z "${MODIFIED}" ]]; then
${PRINT_RED}
echo "Code does not adhere to the project standards. Run \"make prettyprint\".";

View File

@ -26,7 +26,7 @@ Security
Parameter set 1
---------------
"qTESLA-I" parameter set from [qTesla]
`qTESLA_I` parameter set from [qTesla]
**Claimed classical security:**
@ -45,7 +45,7 @@ Parameter set 1
Parameter set 2
---------------
"qTESLA-III-speed" parameter set from [qTesla]
`qTESLA_III_speed` parameter set from [qTesla]
**Claimed classical security:**
@ -64,7 +64,7 @@ Parameter set 2
Parameter set 3
---------------
"qTESLA-III-size" parameter set from [qTesla]
`qTESLA_III_size` parameter set from [qTesla]
**Claimed classical security:**

View File

@ -11,10 +11,10 @@ PRINT_YELLOW="tput setaf 3"
RET=0
ALGS=`grep -E 'define OQS_(KEM|SIG)_alg_' src/kem/kem.h src/sig/sig.h | grep -v 'default' | grep -v 'sidh' | sed -e 's/^[^"]*"//' | sed -e 's/".*$//' | tr -d '[:blank:]'`
ALGS=$(grep -E 'define OQS_(KEM|SIG)_alg_' src/kem/kem.h src/sig/sig.h | grep -v 'default' | grep -v 'sidh' | sed -e 's/^[^"]*"//' | sed -e 's/".*$//' | tr -d '[:blank:]')
for alg in ${ALGS}; do
kat=`find kat_*_rsp -name ${alg}.kat |tr '\n' ' '`
kat=$(find kat_*_rsp -name ${alg}.kat |tr '\n' ' ')
if [ -z "${kat}" ];
then
${PRINT_YELLOW}
@ -24,7 +24,7 @@ for alg in ${ALGS}; do
continue
fi
origs=`find src -name ${alg}.kat -o -name ${alg}.*.kat |tr '\n' ' '`
origs=$(find src -name ${alg}.kat -o -name ${alg}.*.kat |tr '\n' ' ')
if [[ "x${origs}x" == "xx" ]];
then
${PRINT_RED}

View File

@ -8,7 +8,7 @@
#include <windows.h>
#endif
void OQS_API OQS_MEM_cleanse(void *ptr, size_t len) {
OQS_API void OQS_MEM_cleanse(void *ptr, size_t len) {
#if defined(_WIN32)
SecureZeroMemory(ptr, len);
#elif defined(HAVE_MEMSET_S)
@ -22,14 +22,14 @@ void OQS_API OQS_MEM_cleanse(void *ptr, size_t len) {
#endif
}
void OQS_API OQS_MEM_secure_free(void *ptr, size_t len) {
OQS_API void OQS_MEM_secure_free(void *ptr, size_t len) {
if (ptr != NULL) {
OQS_MEM_cleanse(ptr, len);
free(ptr); // IGNORE free-check
}
}
void OQS_API OQS_MEM_insecure_free(void *ptr) {
OQS_API void OQS_MEM_insecure_free(void *ptr) {
free(ptr); // IGNORE free-check
}

View File

@ -8,6 +8,7 @@
#include <stdint.h>
#include <stdlib.h>
#if defined(_WIN32)
#include <oqs/winconfig.h>
#else
@ -97,16 +98,6 @@ void OQS_MEM_secure_free(void *ptr, size_t len);
*/
void OQS_MEM_insecure_free(void *ptr);
/**
* Function to print a message to standard error. Workaround on Android to print
* directly to stdout.
*/
#if __ANDROID__
#define eprintf(...) printf(__VA_ARGS__);
#else
#define eprintf(...) fprintf(stderr, __VA_ARGS__);
#endif
/**
* Macros that indicates a function argument may be unused. Used to comply with
* an API specification but when an implementation doesn't actually use the argument

View File

@ -9,11 +9,13 @@
#include <unistd.h>
#include <strings.h>
#endif
#include <fcntl.h>
#include <oqs/oqs.h>
void OQS_randombytes_system(uint8_t *random_array, size_t bytes_to_read);
void OQS_randombytes_nist_kat(uint8_t *random_array, size_t bytes_to_read);
#ifdef USE_OPENSSL
#include <openssl/rand.h>
// Use OpenSSL's RAND_bytes as the default PRNG
@ -22,8 +24,6 @@ static void (*oqs_randombytes_algorithm)(uint8_t *, size_t) = (void (*)(uint8_t
static void (*oqs_randombytes_algorithm)(uint8_t *, size_t) = &OQS_randombytes_system;
#endif
void OQS_randombytes_nist_kat(uint8_t *random_array, size_t bytes_to_read);
OQS_STATUS OQS_randombytes_switch_algorithm(const char *algorithm) {
if (0 == strcasecmp(OQS_RAND_alg_system, algorithm)) {
oqs_randombytes_algorithm = &OQS_randombytes_system;

View File

@ -12,19 +12,12 @@
#include <oqs/common.h>
/*********************
*** START NEW API ***
*********************/
/* TODO: Consider adding NIST-KAT PRNGs from nist-branch */
/* TODO: Decide how to do statistical testing of new PRNG */
/** Algorithm identifier for system PRNG. */
#define OQS_RAND_alg_system "system"
/** Algorithm identifier for using OpenSSL's PRNG. */
#define OQS_RAND_alg_openssl "OpenSSL"
/** Algorithm identifier for NIST deterministic RNG for KATs. */
#define OQS_RAND_alg_nist_kat "NIST-KAT"
/** Algorithm identifier for using OpenSSL's PRNG. */
#define OQS_RAND_alg_openssl "OpenSSL"
/**
* Switches OQS_randombytes to use the specified algorithm.
@ -58,19 +51,6 @@ void OQS_randombytes_custom_algorithm(void (*algorithm_ptr)(uint8_t *, size_t));
*/
void OQS_randombytes(uint8_t *random_array, size_t bytes_to_read);
/**
* Fills the given memory with the requested number of random bytes.
*
* This implementation reads the bytes directly from `/dev/urandom` and will
* block until the requested number of bytes have been read.
*
* The caller is responsible for providing a buffer allocated with sufficient room.
*
* @param[out] random_array Pointer to the memory to fill with random bytes
* @param[in] bytes_to_read The number of random bytes to read into memory
*/
void OQS_randombytes_system(uint8_t *random_array, size_t bytes_to_read);
/**
* Initializes the NIST DRBG with a given seed.
*
@ -80,10 +60,6 @@ void OQS_randombytes_system(uint8_t *random_array, size_t bytes_to_read);
*/
void OQS_randombytes_nist_kat_init(const uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength);
/********************
*** STOP NEW API ***
********************/
/************************************************************
*** START DEPRECATED CODE *** expected removal Sep. 2018 ***
************************************************************/

View File

@ -10,6 +10,7 @@
#include <string.h>
#include <oqs/common.h>
#if USE_OPENSSL
#include <openssl/conf.h>
#include <openssl/evp.h>

View File

@ -142,6 +142,7 @@ OQS_API OQS_STATUS OQS_KEM_keypair(const OQS_KEM *kem, uint8_t *public_key, uint
return kem->keypair(public_key, secret_key);
}
}
OQS_API OQS_STATUS OQS_KEM_encaps(const OQS_KEM *kem, uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key) {
if (kem == NULL) {
return OQS_ERROR;
@ -149,6 +150,7 @@ OQS_API OQS_STATUS OQS_KEM_encaps(const OQS_KEM *kem, uint8_t *ciphertext, uint8
return kem->encaps(ciphertext, shared_secret, public_key);
}
}
OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key) {
if (kem == NULL) {
return OQS_ERROR;

View File

@ -207,7 +207,7 @@ OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, co
*
* @param[in] kem The OQS_KEM object to free.
*/
void OQS_KEM_free(OQS_KEM *kem);
OQS_API void OQS_KEM_free(OQS_KEM *kem);
#include <oqs/kem_bike.h>
#include <oqs/kem_frodokem.h>

View File

@ -28,7 +28,7 @@ OQS_API const char *OQS_SIG_alg_identifier(size_t i) {
}
}
OQS_SIG *OQS_SIG_new(const char *method_name) {
OQS_API OQS_SIG *OQS_SIG_new(const char *method_name) {
if (0 == strcasecmp(method_name, OQS_SIG_alg_default)) {
return OQS_SIG_new(OQS_SIG_DEFAULT);
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_qTESLA_I)) {
@ -91,7 +91,7 @@ OQS_SIG *OQS_SIG_new(const char *method_name) {
}
}
OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key) {
OQS_API OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key) {
if (sig == NULL || sig->keypair(public_key, secret_key) != OQS_SUCCESS) {
return OQS_ERROR;
} else {
@ -99,7 +99,7 @@ OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *sec
}
}
OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
OQS_API OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) {
if (sig == NULL || sig->sign(signature, signature_len, message, message_len, secret_key) != OQS_SUCCESS) {
return OQS_ERROR;
} else {
@ -107,7 +107,7 @@ OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signatur
}
}
OQS_STATUS OQS_SIG_verify(const OQS_SIG *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
OQS_API OQS_STATUS OQS_SIG_verify(const OQS_SIG *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) {
if (sig == NULL || sig->verify(message, message_len, signature, signature_len, public_key) != OQS_SUCCESS) {
return OQS_ERROR;
} else {
@ -115,6 +115,6 @@ OQS_STATUS OQS_SIG_verify(const OQS_SIG *sig, const uint8_t *message, size_t mes
}
}
void OQS_SIG_free(OQS_SIG *sig) {
OQS_API void OQS_SIG_free(OQS_SIG *sig) {
OQS_MEM_insecure_free(sig);
}

View File

@ -74,7 +74,7 @@ typedef struct OQS_SIG {
/** Printable string representing the name of the signature scheme. */
const char *method_name;
/** The NIST security level (1, 2, 3, 4, 5) claimed for this algorithm. */
/** The NIST security level (1, 2, 3, 4, 5) claimed in this algorithm's original NIST submission. */
uint8_t claimed_nist_level;
/** Whether the signature offers EUF-CMA security (TRUE) or not (FALSE). */
@ -142,7 +142,7 @@ typedef struct OQS_SIG {
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_SIG_algs`.
* @return An OQS_SIG for the particular algorithm, or `NULL` if the algorithm has been disabled at compile-time.
*/
OQS_SIG *OQS_SIG_new(const char *method_name);
OQS_API OQS_SIG *OQS_SIG_new(const char *method_name);
/**
* Keypair generation algorithm.
@ -156,7 +156,7 @@ OQS_SIG *OQS_SIG_new(const char *method_name);
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key);
/**
* Signature generation algorithm.
@ -173,7 +173,7 @@ OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *sec
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
OQS_API OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
/**
* Signature verification algorithm.
@ -186,14 +186,14 @@ OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signatur
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS OQS_SIG_verify(const OQS_SIG *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_SIG_verify(const OQS_SIG *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
/**
* Frees an OQS_SIG object that was constructed by OQS_SIG_new.
*
* @param[in] sig The OQS_SIG object to free.
*/
void OQS_SIG_free(OQS_SIG *sig);
OQS_API void OQS_SIG_free(OQS_SIG *sig);
#include <oqs/sig_qtesla.h>
#include <oqs/sig_picnic.h>

View File

@ -41,4 +41,5 @@ test_kem_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
test_rand_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
test_sha3_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
test_sig_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
kat_kem_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
endif

View File

@ -48,7 +48,7 @@ START_TIMER
// another operation here
STOP_TIMER
FINALIZE_TIMER
PRINT_TIME_HEADER
PRINT_TIMER_HEADER
PRINT_TIMER_AVG("my operation")
PRINT_TIMER_FOOTER
@ -113,26 +113,55 @@ int gettimeofday(struct timeval *tp, struct timezone *tzp) {
}
#endif
static uint64_t rdtsc(void) {
#if defined(_WIN32)
static uint64_t _bench_rdtsc(void) {
#if defined(_WIN32) || defined(_WIN64)
return __rdtsc();
#elif defined(__aarch64__)
uint64_t x;
asm volatile("isb; mrs %0, cntvct_el0"
: "=r"(x));
return x;
#elif defined(__arm__)
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return (int64_t)(time.tv_sec * 1e9 + time.tv_nsec);
#else
#elif defined(__i586__) || defined(__amd64__)
uint64_t x;
__asm__ volatile(".byte 0x0f, 0x31"
: "=A"(x));
return x;
#elif defined(__arm__)
/* Use the ARM performance counters. */
unsigned int value;
/* Read CCNT Register */
asm volatile("mrc p15, 0, %0, c9, c13, 0\t\n"
: "=r"(value));
return value;
#else
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return (int64_t)(time.tv_sec * 1e9 + time.tv_nsec);
#endif
}
#if defined(__arm__)
static void _bench_init_perfcounters(int32_t do_reset, int32_t enable_divider) {
/* In general enable all counters (including cycle counter) */
int32_t value = 1;
/* Peform reset */
if (do_reset) {
value |= 2; /* reset all counters to zero */
value |= 4; /* reset cycle counter to zero */
}
if (enable_divider)
value |= 8; /* enable "by 64" divider for CCNT */
value |= 16;
/* Program the performance-counter control-register */
asm volatile("mcr p15, 0, %0, c9, c12, 0\t\n" ::"r"(value));
/* Enable all counters */
asm volatile("mcr p15, 0, %0, c9, c12, 1\t\n" ::"r"(0x8000000f));
/* Clear overflows */
asm volatile("mcr p15, 0, %0, c9, c12, 3\t\n" ::"r"(0x8000000f));
}
#endif
#define DEFINE_TIMER_VARIABLES \
volatile uint64_t _bench_cycles_start, _bench_cycles_end; \
uint64_t _bench_cycles_cumulative = 0; \
@ -142,6 +171,16 @@ static uint64_t rdtsc(void) {
double _bench_cycles_x, _bench_cycles_mean, _bench_cycles_delta, _bench_cycles_M2, _bench_cycles_stdev; \
double _bench_time_x, _bench_time_mean, _bench_time_delta, _bench_time_M2, _bench_time_stdev;
#if defined(__arm__)
#define INITIALIZE_TIMER \
_bench_init_perfcounters(1, 0); \
_bench_iterations = 0; \
_bench_cycles_mean = 0.0; \
_bench_cycles_M2 = 0.0; \
_bench_time_cumulative = 0; \
_bench_time_mean = 0.0; \
_bench_time_M2 = 0.0;
#else
#define INITIALIZE_TIMER \
_bench_iterations = 0; \
_bench_cycles_mean = 0.0; \
@ -149,15 +188,17 @@ static uint64_t rdtsc(void) {
_bench_time_cumulative = 0; \
_bench_time_mean = 0.0; \
_bench_time_M2 = 0.0;
#endif
#define START_TIMER \
gettimeofday(&_bench_timeval_start, NULL); \
_bench_cycles_start = rdtsc();
_bench_cycles_start = _bench_rdtsc();
// Mean and population standard deviation are calculated in an online way using the algorithm in
// http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
#define STOP_TIMER \
_bench_cycles_end = rdtsc(); \
_bench_cycles_end = _bench_rdtsc(); \
gettimeofday(&_bench_timeval_end, NULL); \
_bench_iterations += 1; \
if (_bench_cycles_end < _bench_cycles_start) { \

View File

@ -42,8 +42,7 @@ OQS_STATUS example_stack() {
printf("[example_stack] OQS_KEM_frodokem_640_aes was not enabled at "
"compile-time.\n");
return OQS_ERROR;
#endif
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
#else
uint8_t public_key[OQS_KEM_frodokem_640_aes_length_public_key];
uint8_t secret_key[OQS_KEM_frodokem_640_aes_length_secret_key];
uint8_t ciphertext[OQS_KEM_frodokem_640_aes_length_ciphertext];

160
tests/minimal_kex_oqs.c Normal file
View File

@ -0,0 +1,160 @@
/*
* 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/oqs.h>
#if __ANDROID__
#define eprintf(...) printf(__VA_ARGS__);
#else
#define eprintf(...) fprintf(stderr, __VA_ARGS__);
#endif
/* 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);
#ifdef ENABLE_KEX_NTRU
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_default; // Alg. name
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, NULL, 0, NULL);
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 */
OQS_STATUS 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;
}
OQS_print_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;
}
OQS_print_part_hex_string("Bob message", bob_msg, bob_msg_len, 20);
OQS_print_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;
}
OQS_print_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");
OQS_print_hex_string("Alice session key", alice_key, alice_key_len);
OQS_print_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;
}
#else // !ENABLE_KEX_LWE_FRODO
int main(void) {
printf("KEX algorithm not available. Make sure configure was run properly; see Readme.md.\n");
return EXIT_FAILURE;
}
#endif
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,9 +1,14 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oqs/oqs.h>
typedef struct magic_s {
uint8_t val[32];
} magic_t;
static OQS_STATUS kem_test_correctness(const char *method_name) {
OQS_KEM *kem = NULL;
@ -15,6 +20,13 @@ static OQS_STATUS kem_test_correctness(const char *method_name) {
OQS_STATUS rc, ret = OQS_ERROR;
int rv;
//The magic numbers are 32 random values.
//The length of the magic number was chosen arbitrarilly to 32.
magic_t magic = {{0xfa, 0xfa, 0xfa, 0xfa, 0xbc, 0xbc, 0xbc, 0xbc,
0x15, 0x61, 0x15, 0x61, 0x15, 0x61, 0x15, 0x61,
0xad, 0xad, 0x43, 0x43, 0xad, 0xad, 0x34, 0x34,
0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78}};
kem = OQS_KEM_new(method_name);
if (kem == NULL) {
return OQS_SUCCESS;
@ -24,11 +36,18 @@ static OQS_STATUS kem_test_correctness(const char *method_name) {
printf("Sample computation for KEM %s\n", kem->method_name);
printf("================================================================================\n");
public_key = malloc(kem->length_public_key);
secret_key = malloc(kem->length_secret_key);
ciphertext = malloc(kem->length_ciphertext);
shared_secret_e = malloc(kem->length_shared_secret);
shared_secret_d = malloc(kem->length_shared_secret);
public_key = malloc(kem->length_public_key + sizeof(magic_t));
secret_key = malloc(kem->length_secret_key + sizeof(magic_t));
ciphertext = malloc(kem->length_ciphertext + sizeof(magic_t));
shared_secret_e = malloc(kem->length_shared_secret + sizeof(magic_t));
shared_secret_d = malloc(kem->length_shared_secret + sizeof(magic_t));
//Set the magic numbers
memcpy(public_key + kem->length_public_key, magic.val, sizeof(magic_t));
memcpy(secret_key + kem->length_secret_key, magic.val, sizeof(magic_t));
memcpy(ciphertext + kem->length_ciphertext, magic.val, sizeof(magic_t));
memcpy(shared_secret_e + kem->length_shared_secret, magic.val, sizeof(magic_t));
memcpy(shared_secret_d + kem->length_shared_secret, magic.val, sizeof(magic_t));
if ((public_key == NULL) || (secret_key == NULL) || (ciphertext == NULL) || (shared_secret_e == NULL) || (shared_secret_d == NULL)) {
fprintf(stderr, "ERROR: malloc failed\n");
@ -63,6 +82,16 @@ static OQS_STATUS kem_test_correctness(const char *method_name) {
printf("shared secrets are equal\n");
}
rv = memcmp(public_key + kem->length_public_key, magic.val, sizeof(magic_t));
rv |= memcmp(secret_key + kem->length_secret_key, magic.val, sizeof(magic_t));
rv |= memcmp(ciphertext + kem->length_ciphertext, magic.val, sizeof(magic_t));
rv |= memcmp(shared_secret_e + kem->length_shared_secret, magic.val, sizeof(magic_t));
rv |= memcmp(shared_secret_d + kem->length_shared_secret, magic.val, sizeof(magic_t));
if (rv != 0) {
fprintf(stderr, "ERROR: Magic numbers do not match\n");
goto err;
}
ret = OQS_SUCCESS;
goto cleanup;
@ -83,6 +112,7 @@ cleanup:
}
int main() {
int ret = EXIT_SUCCESS;
OQS_STATUS rc;

410
tests/test_kex.c Normal file
View File

@ -0,0 +1,410 @@
#if defined(_WIN32)
#pragma warning(disable : 4244 4293)
#endif
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oqs/oqs.h>
#include "ds_benchmark.h"
#if __ANDROID__
#define eprintf(...) printf(__VA_ARGS__);
#else
#define eprintf(...) fprintf(stderr, __VA_ARGS__);
#endif
struct kex_testcase {
enum OQS_KEX_alg_name alg_name;
unsigned char *seed;
size_t seed_len;
const char *named_parameters;
const char *id;
int run;
int iter;
};
/* Add new testcases here */
struct kex_testcase kex_testcases[] = {
#ifndef DISABLE_NTRU_ON_WINDOWS_BY_DEFAULT
#ifdef ENABLE_KEX_NTRU
{OQS_KEX_alg_ntru, NULL, 0, NULL, "ntru", 0, 25},
#endif
#endif
};
#define KEX_TEST_ITERATIONS 100
#define KEX_BENCH_SECONDS_DEFAULT 1
static OQS_STATUS kex_test_correctness(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters, const int print, unsigned long occurrences[256]) {
OQS_KEX *kex = NULL;
OQS_STATUS rc;
void *alice_priv = NULL;
uint8_t *alice_msg = NULL;
size_t alice_msg_len;
uint8_t *alice_key = NULL;
size_t alice_key_len = 0;
uint8_t *bob_msg = NULL;
size_t bob_msg_len;
uint8_t *bob_key = NULL;
size_t bob_key_len = 0;
/* setup KEX */
kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
if (kex == NULL) {
eprintf("new_method failed\n");
goto err;
}
if (print) {
printf("================================================================================\n");
printf("Sample computation for key exchange method %s\n", kex->method_name);
printf("================================================================================\n");
}
/* Alice's initial message */
rc = OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len);
if (rc != OQS_SUCCESS) {
eprintf("OQS_KEX_alice_0 failed\n");
goto err;
}
if (print) {
OQS_print_part_hex_string("Alice message", alice_msg, alice_msg_len, 20);
}
/* Bob's response */
rc = OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len);
if (rc != OQS_SUCCESS) {
eprintf("OQS_KEX_bob failed\n");
goto err;
}
if (print) {
OQS_print_part_hex_string("Bob message", bob_msg, bob_msg_len, 20);
OQS_print_hex_string("Bob session key", bob_key, bob_key_len);
}
/* Alice processes Bob's response */
rc = OQS_KEX_alice_1(kex, alice_priv, bob_msg, bob_msg_len, &alice_key, &alice_key_len);
if (rc != OQS_SUCCESS) {
eprintf("OQS_KEX_alice_1 failed\n");
goto err;
}
if (print) {
OQS_print_hex_string("Alice session key", alice_key, alice_key_len);
}
/* compare session key lengths and values */
if (alice_key_len != bob_key_len) {
eprintf("ERROR: Alice's session key and Bob's session key are different lengths (%zu vs %zu)\n", alice_key_len, bob_key_len);
goto err;
}
if (memcmp(alice_key, bob_key, alice_key_len) != 0) {
eprintf("ERROR: Alice's session key and Bob's session key are not equal\n");
OQS_print_hex_string("Alice session key", alice_key, alice_key_len);
OQS_print_hex_string("Bob session key", bob_key, bob_key_len);
goto err;
}
if (print) {
printf("Alice and Bob's session keys match.\n");
printf("\n\n");
}
/* record generated bytes for statistical analysis */
for (size_t i = 0; i < alice_key_len; i++) {
OQS_RAND_test_record_occurrence(alice_key[i], occurrences);
}
rc = OQS_SUCCESS;
goto cleanup;
err:
rc = OQS_ERROR;
cleanup:
OQS_MEM_insecure_free(alice_msg);
OQS_MEM_secure_free(alice_key, alice_key_len);
OQS_MEM_insecure_free(bob_msg);
OQS_MEM_secure_free(bob_key, bob_key_len);
OQS_KEX_alice_priv_free(kex, alice_priv);
OQS_KEX_free(kex);
return rc;
}
static OQS_STATUS kex_test_correctness_wrapper(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters, int iterations, bool quiet) {
OQS_KEX *kex = NULL;
OQS_STATUS ret;
unsigned long occurrences[256];
for (int i = 0; i < 256; i++) {
occurrences[i] = 0;
}
ret = kex_test_correctness(rand, alg_name, seed, seed_len, named_parameters, quiet ? 0 : 1, occurrences);
if (ret != OQS_SUCCESS) {
goto err;
}
/* setup KEX */
kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
if (kex == NULL) {
goto err;
}
printf("================================================================================\n");
printf("Testing correctness and randomness of key exchange method %s (params=%s) for %d iterations\n",
kex->method_name, named_parameters, iterations);
printf("================================================================================\n");
for (int i = 0; i < iterations; i++) {
ret = kex_test_correctness(rand, alg_name, seed, seed_len, named_parameters, 0, occurrences);
if (ret != OQS_SUCCESS) {
goto err;
}
}
printf("All session keys matched.\n");
OQS_RAND_report_statistics(occurrences, "");
printf("\n\n");
ret = OQS_SUCCESS;
goto cleanup;
err:
ret = OQS_ERROR;
cleanup:
OQS_KEX_free(kex);
return ret;
}
static void cleanup_alice_0(OQS_KEX *kex, void *alice_priv, uint8_t *alice_msg) {
OQS_MEM_insecure_free(alice_msg);
OQS_KEX_alice_priv_free(kex, alice_priv);
}
static void cleanup_bob(uint8_t *bob_msg, uint8_t *bob_key, size_t bob_key_len) {
OQS_MEM_insecure_free(bob_msg);
OQS_MEM_secure_free(bob_key, bob_key_len);
}
static OQS_STATUS kex_bench_wrapper(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters, const size_t seconds) {
OQS_KEX *kex = NULL;
OQS_STATUS rc;
void *alice_priv = NULL;
uint8_t *alice_msg = NULL;
size_t alice_msg_len;
uint8_t *alice_key = NULL;
size_t alice_key_len = 0;
uint8_t *bob_msg = NULL;
size_t bob_msg_len;
uint8_t *bob_key = NULL;
size_t bob_key_len = 0;
/* setup KEX */
kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
if (kex == NULL) {
eprintf("new_method failed\n");
goto err;
}
printf("%-30s | %10s | %14s | %15s | %10s | %16s | %10s\n", kex->method_name, "", "", "", "", "", "");
TIME_OPERATION_SECONDS({ OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len); cleanup_alice_0(kex, alice_priv, alice_msg); }, "alice 0", seconds);
OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len);
TIME_OPERATION_SECONDS({ OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len); cleanup_bob(bob_msg, bob_key, bob_key_len); }, "bob", seconds);
OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len);
TIME_OPERATION_SECONDS({ OQS_KEX_alice_1(kex, alice_priv, bob_msg, bob_msg_len, &alice_key, &alice_key_len); OQS_MEM_secure_free(alice_key, alice_key_len); }, "alice 1", seconds);
alice_key = NULL;
printf("Communication (bytes): A->B: %zu, B->A: %zu, total: %zu; classical/quantum security bits [%u:%u] \n", alice_msg_len, bob_msg_len, alice_msg_len + bob_msg_len, kex->estimated_classical_security, kex->estimated_quantum_security);
rc = OQS_SUCCESS;
goto cleanup;
err:
rc = OQS_ERROR;
cleanup:
OQS_MEM_insecure_free(alice_msg);
OQS_MEM_secure_free(alice_key, alice_key_len);
OQS_MEM_insecure_free(bob_msg);
OQS_MEM_secure_free(bob_key, bob_key_len);
OQS_KEX_alice_priv_free(kex, alice_priv);
OQS_KEX_free(kex);
return rc;
}
static OQS_STATUS kex_mem_bench_wrapper(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8_t *seed, const size_t seed_len, const char *named_parameters) {
OQS_KEX *kex = NULL;
OQS_STATUS rc;
void *alice_priv = NULL;
uint8_t *alice_msg = NULL;
size_t alice_msg_len;
uint8_t *alice_key = NULL;
size_t alice_key_len = 0;
uint8_t *bob_msg = NULL;
size_t bob_msg_len;
uint8_t *bob_key = NULL;
size_t bob_key_len = 0;
kex = OQS_KEX_new(rand, alg_name, seed, seed_len, named_parameters);
if (kex == NULL) {
fprintf(stderr, "new_method failed\n");
goto err;
}
printf("running %s..\n", kex->method_name);
OQS_KEX_alice_0(kex, &alice_priv, &alice_msg, &alice_msg_len);
OQS_KEX_bob(kex, alice_msg, alice_msg_len, &bob_msg, &bob_msg_len, &bob_key, &bob_key_len);
OQS_KEX_alice_1(kex, alice_priv, bob_msg, bob_msg_len, &alice_key, &alice_key_len);
rc = OQS_SUCCESS;
goto cleanup;
err:
rc = OQS_ERROR;
cleanup:
OQS_MEM_insecure_free(alice_msg);
OQS_MEM_secure_free(alice_key, alice_key_len);
OQS_MEM_insecure_free(bob_msg);
OQS_MEM_secure_free(bob_key, bob_key_len);
OQS_KEX_alice_priv_free(kex, alice_priv);
OQS_KEX_free(kex);
return rc;
}
void print_help() {
printf("Usage: ./test_kex [options] [algorithms]\n");
printf("\nOptions:\n");
printf(" --quiet, -q\n");
printf(" Less verbose output\n");
printf(" --bench, -b\n");
printf(" Run benchmarks\n");
printf(" --seconds -s [SECONDS]\n");
printf(" Number of seconds to run benchmarks (default==%d)\n", KEX_BENCH_SECONDS_DEFAULT);
printf(" --mem-bench\n");
printf(" Run memory benchmarks (run once and allocate only what is required)\n");
printf("\nalgorithms:\n");
size_t kex_testcases_len = sizeof(kex_testcases) / sizeof(struct kex_testcase);
for (size_t i = 0; i < kex_testcases_len; i++) {
printf(" %s\n", kex_testcases[i].id);
}
}
int main(int argc, char **argv) {
OQS_STATUS success = OQS_SUCCESS;
bool run_all = true;
bool quiet = false;
bool bench = false;
bool mem_bench = false;
size_t kex_testcases_len = sizeof(kex_testcases) / sizeof(struct kex_testcase);
size_t kex_bench_seconds = KEX_BENCH_SECONDS_DEFAULT;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-help") == 0) || (strcmp(argv[i], "--help") == 0)) {
print_help();
return EXIT_SUCCESS;
} else if (strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "-q") == 0) {
quiet = true;
} else if (strcmp(argv[i], "--bench") == 0 || strcmp(argv[i], "-b") == 0) {
bench = true;
} else if (strcmp(argv[i], "--seconds") == 0 || strcmp(argv[i], "-s") == 0) {
if (++i == argc) {
print_help();
return EXIT_SUCCESS;
}
char *end;
int kex_bench_seconds_input = strtol(argv[i], &end, 10);
if (kex_bench_seconds_input < 1) {
print_help();
return EXIT_SUCCESS;
}
kex_bench_seconds = kex_bench_seconds_input;
} else if ((strcmp(argv[i], "--mem-bench") == 0 || strcmp(argv[i], "-m") == 0)) {
mem_bench = true;
}
} else {
run_all = false;
for (size_t j = 0; j < kex_testcases_len; j++) {
if (strcmp(argv[i], kex_testcases[j].id) == 0) {
kex_testcases[j].run = 1;
}
}
}
}
/* setup RAND */
OQS_RAND *rand = OQS_RAND_new(OQS_RAND_alg_urandom_chacha20);
if (rand == NULL) {
goto err;
}
if (mem_bench) {
for (size_t i = 0; i < kex_testcases_len; i++) {
if (run_all || kex_testcases[i].run == 1) {
success = kex_mem_bench_wrapper(rand, kex_testcases[i].alg_name, kex_testcases[i].seed, kex_testcases[i].seed_len, kex_testcases[i].named_parameters);
}
if (success != OQS_SUCCESS) {
goto err;
}
}
printf("memory benchmarks done, exiting..\n");
success = OQS_SUCCESS;
goto cleanup;
}
for (size_t i = 0; i < kex_testcases_len; i++) {
if (run_all || kex_testcases[i].run == 1) {
int num_iter = kex_testcases[i].iter;
success = kex_test_correctness_wrapper(rand, kex_testcases[i].alg_name, kex_testcases[i].seed, kex_testcases[i].seed_len, kex_testcases[i].named_parameters, num_iter, quiet);
}
if (success != OQS_SUCCESS) {
goto err;
}
}
if (bench) {
PRINT_TIMER_HEADER
for (size_t i = 0; i < kex_testcases_len; i++) {
if (run_all || kex_testcases[i].run == 1) {
kex_bench_wrapper(rand, kex_testcases[i].alg_name, kex_testcases[i].seed, kex_testcases[i].seed_len, kex_testcases[i].named_parameters, kex_bench_seconds);
}
}
PRINT_TIMER_FOOTER
}
success = OQS_SUCCESS;
goto cleanup;
err:
success = OQS_ERROR;
eprintf("ERROR!\n");
cleanup:
OQS_RAND_free(rand);
return (success == OQS_SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -7,6 +7,12 @@
#include <oqs/oqs.h>
#if __ANDROID__
#define eprintf(...) printf(__VA_ARGS__);
#else
#define eprintf(...) fprintf(stderr, __VA_ARGS__);
#endif
struct rand_testcase {
enum OQS_RAND_alg_name alg_name;
};

View File

@ -58,8 +58,15 @@ static OQS_STATUS sig_test_correctness(const char *method_name) {
goto err;
}
printf("Signature is valid\n");
/* modify the signature to invalidate it */
signature[0]++;
rc = OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key);
if (rc != OQS_ERROR) {
fprintf(stderr, "ERROR: OQS_SIG_verify should have failed!\n");
goto err;
}
printf("verification passes as expected\n");
ret = OQS_SUCCESS;
goto cleanup;