mirror of
https://github.com/open-quantum-safe/liboqs.git
synced 2025-10-06 00:03:35 -04:00
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:
commit
fa7cf526e0
10
.travis.yml
10
.travis.yml
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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\".";
|
||||
|
@ -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:**
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 ***
|
||||
************************************************************/
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <oqs/common.h>
|
||||
|
||||
#if USE_OPENSSL
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/evp.h>
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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) { \
|
||||
|
@ -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
160
tests/minimal_kex_oqs.c
Normal 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);
|
||||
}
|
@ -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
410
tests/test_kex.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user