From 74f8c77e975bd84aa94211562c6666e0e06ff2b7 Mon Sep 17 00:00:00 2001 From: Kris Kwiatkowski Date: Wed, 24 Mar 2021 10:25:45 +0000 Subject: [PATCH] KEM C-API --- .cmake/common.mk | 36 +++++------------------------ CMakeLists.txt | 18 ++++++++------- src/capi/pqapi.c | 53 +++++++++++++++++++++++++++++++++--------- src/capi/pqapi.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ test/mytest.cpp | 26 ++++++++++++++++++--- 5 files changed, 141 insertions(+), 52 deletions(-) create mode 100644 src/capi/pqapi.h diff --git a/.cmake/common.mk b/.cmake/common.mk index beacaef1..89c166e2 100644 --- a/.cmake/common.mk +++ b/.cmake/common.mk @@ -1,5 +1,8 @@ # Common function for defining algorithm component -function(define_crypto_alg name namespace src inc test_src) +function(define_crypto_alg name namespace src inc) + get_property(OBJ_LIBS GLOBAL PROPERTY obj_libs) + set_property(GLOBAL PROPERTY obj_libs ${OBJ_LIBS} pqclean_${name}) + add_library( pqclean_${name} OBJECT @@ -17,38 +20,11 @@ function(define_crypto_alg name namespace src inc test_src) -DPQCLEAN_NAMESPACE=${namespace} ) - add_library( - pqclean_test_${name} - OBJECT - ${test_src} - ) - - target_compile_definitions( - pqclean_test_${name} PRIVATE - -DPQCLEAN_NAMESPACE=${namespace} - ) - - target_include_directories( - pqclean_test_${name} PRIVATE - src/common - ${inc} - ) - - add_executable( - test_runner_${name} - ) - target_link_libraries( - test_runner_${name} - - common - pqclean_${name} - pqclean_test_${name} - ) endfunction() function(define_kem_alg name namespace src inc) - define_crypto_alg(${name} ${namespace} "${src}" "${inc}" ${PROJECT_SOURCE_DIR}/test/kem/testvectors.c) + define_crypto_alg(${name} ${namespace} "${src}" "${inc}") endfunction() function(define_sig_alg name namespace src inc) - define_crypto_alg(${name} ${namespace} "${src}" "${inc}" ${PROJECT_SOURCE_DIR}/test/sign/testvectors.c) + define_crypto_alg(${name} ${namespace} "${src}" "${inc}") endfunction() diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b743ecf..75ba3e3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "~/.cmake/Modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "3rd/cmake-modules") set(CMAKE_CXX_STANDARD 11) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) @@ -81,6 +82,9 @@ include_directories( src ) +set_property(GLOBAL PROPERTY obj_libs "") + + # Set CPU architecture set(CMAKE_C_FLAGS "${C_CXX_FLAGS} -D${ARCH}") set(CMAKE_CXX_FLAGS "${C_CXX_FLAGS} -D${ARCH}") @@ -118,6 +122,7 @@ add_subdirectory(src/sign/sphincs/sphincs-sha256-256s-robust/clean) add_subdirectory(src/sign/sphincs/sphincs-sha256-128s-robust/clean) add_subdirectory(src/sign/sphincs/sphincs-sha256-128f-simple/clean) add_subdirectory(src/sign/sphincs/sphincs-sha256-192f-robust/clean) + add_subdirectory(src/kem/kyber/kyber512/clean) add_subdirectory(src/kem/kyber/kyber768/clean) add_subdirectory(src/kem/kyber/kyber1024/clean) @@ -217,21 +222,18 @@ add_library( pqclean_s STATIC ) +get_property(OBJ_LIBS GLOBAL PROPERTY obj_libs) target_link_libraries( pqclean common - pqclean_dilithium2_clean - pqclean_dilithium3_clean - pqclean_dilithium5_clean + ${OBJ_LIBS} ) target_link_libraries( pqclean_s common - pqclean_dilithium2_clean - pqclean_dilithium3_clean - pqclean_dilithium5_clean + ${OBJ_LIBS} ) add_executable( @@ -243,8 +245,8 @@ add_executable( target_link_libraries( mytest gtest - pqclean_s - gtest_main) + gtest_main + pqclean_s) target_include_directories( mytest PRIVATE diff --git a/src/capi/pqapi.c b/src/capi/pqapi.c index ee08b9b7..2aa7ad96 100644 --- a/src/capi/pqapi.c +++ b/src/capi/pqapi.c @@ -1,11 +1,16 @@ #include +#include #include "pqapi.h" #include "kem/kyber/kyber512/clean/api.h" +#include "kem/kyber/kyber512/avx2/api.h" +#include "kem/kyber/kyber768/clean/api.h" +#include "kem/kyber/kyber768/avx2/api.h" +#include "kem/kyber/kyber1024/clean/api.h" +#include "kem/kyber/kyber1024/avx2/api.h" // helpers #define OPT_VERSION _CLEAN_ - // Helper to stringify constants #define STR(x) STR_(x) #define STR_(x) #x @@ -29,23 +34,49 @@ #define PQC_SIGN_BSZ(x) GLUE(A(x), CRYPTO_BYTES) #define PQC_CT_BSZ(x) GLUE(A(x), CRYPTO_CIPHERTEXTBYTES) #define PQC_NAME(x) GLUE(A(x), CRYPTO_ALGNAME) +#define PQC_FN_KEYGEN(x) GLUE(A(x), crypto_kem_keypair) +#define PQC_FN_ENCAPS(x) GLUE(A(x), crypto_kem_enc) +#define PQC_FN_DECAPS(x) GLUE(A(x), crypto_kem_dec) +#define REG_ALG(ID) \ +{ \ + .alg_id = ID, \ + .alg_name = STR(ID), \ + .prv_key_bsz = PQC_PRV_KEY_BSZ(ID), \ + .pub_key_bsz = PQC_PUB_KEY_BSZ(ID), \ + .keygen = PQC_FN_KEYGEN(ID), \ +} // Macro magic needed to initialize parameters for a scheme -#define REG_KEM(ID) \ -{ \ - .p.alg_id = ID, \ - .p.alg_name = STR(ID), \ - .p.prv_key_bsz = PQC_PRV_KEY_BSZ(ID), \ - .p.pub_key_bsz = PQC_PUB_KEY_BSZ(ID), \ - .ciphertext_bsz = PQC_CT_BSZ(ID), \ - .secret_bsz = PQC_KEM_BSZ(ID) \ +#define REG_KEM(ID) \ +{ \ + .p = REG_ALG(ID), \ + .ciphertext_bsz = PQC_CT_BSZ(ID),\ + .secret_bsz = PQC_KEM_BSZ(ID), \ + .encapsulate = PQC_FN_ENCAPS(ID),\ + .decapsulate = PQC_FN_DECAPS(ID),\ } enum { - KYBER512 + KYBER512, + KYBER768, + KYBER1024 }; const kem_params_t kems[] = { - REG_KEM(KYBER512) + REG_KEM(KYBER512), + REG_KEM(KYBER768), + REG_KEM(KYBER1024), }; + +bool pqc_keygen(const params_t *p, uint8_t *sk, uint8_t *pk) { + return !p->keygen(sk, pk); +} + +bool pqc_kem_encapsulate(const params_t *p, uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + return !((kem_params_t*)p)->encapsulate(ct, ss, pk); +} + +bool pqc_kem_decapsulate(const params_t *p, uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + return !((kem_params_t*)p)->decapsulate(ss, ct, sk); +} diff --git a/src/capi/pqapi.h b/src/capi/pqapi.h new file mode 100644 index 00000000..85954184 --- /dev/null +++ b/src/capi/pqapi.h @@ -0,0 +1,60 @@ +#ifndef PQAPI_H_ +#define PQAPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +// Parameters of the scheme +typedef struct params_t { + const uint8_t alg_id; + const char* alg_name; + const uint32_t prv_key_bsz; + const uint32_t pub_key_bsz; + const bool is_kem; + + int (*keygen)(uint8_t *sk, uint8_t *pk); +} params_t; + +typedef struct kem_params_t { + params_t p; + const uint32_t ciphertext_bsz; + const uint32_t secret_bsz; + + int (*encapsulate)(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + int (*decapsulate)(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); +} kem_params_t; + +typedef struct sig_params_t { + params_t p; + const uint32_t sign_bsz; +} sig_params_t; + +bool pqc_keygen(const params_t *p, uint8_t *sk, uint8_t *pk); +bool pqc_kem_encapsulate(const params_t *p, uint8_t *ct, uint8_t *ss, const uint8_t *pk); +bool pqc_kem_decapsulate(const params_t *p, uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +inline uint32_t ciphertext_bsz(const params_t *p) { + return ((kem_params_t *)p)->ciphertext_bsz; +} + +inline uint32_t shared_secret_bsz(const params_t *p) { + return ((kem_params_t *)p)->secret_bsz; +} + +inline uint32_t public_key_bsz(const params_t *p) { + return p->pub_key_bsz; +} + +inline uint32_t private_key_bsz(const params_t *p) { + return p->prv_key_bsz; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mytest.cpp b/test/mytest.cpp index a2f38ce5..423619d0 100644 --- a/test/mytest.cpp +++ b/test/mytest.cpp @@ -1,9 +1,29 @@ +#include +#include #include #include "capi/pqapi.h" extern const kem_params_t kems[]; // TODO: change - just to see if function registration works OK. -TEST(Kyber,XXX) { - ASSERT_EQ(kems[0].p.prv_key_bsz, 1632); -} \ No newline at end of file +TEST(Kyber,KEMOneOff) { + + for (int i=0; i<3; i++) { + const params_t *p = (params_t*)&kems[i]; + + std::vector ct(ciphertext_bsz(p)); + std::vector ss1(shared_secret_bsz(p)); + std::vector ss2(shared_secret_bsz(p)); + std::vector sk(private_key_bsz(p)); + std::vector pk(public_key_bsz(p)); + + ASSERT_TRUE( + pqc_keygen(p, pk.data(), sk.data())); + ASSERT_TRUE( + pqc_kem_encapsulate(p, ct.data(), ss1.data(), pk.data())); + ASSERT_TRUE( + pqc_kem_decapsulate(p, ss2.data(), ct.data(), sk.data())); + ASSERT_TRUE( + std::equal(ss1.begin(), ss1.end(), ss2.begin())); + } +}