KEM C-API

This commit is contained in:
Henry Case 2021-03-24 10:25:45 +00:00
parent 4a70142872
commit 74f8c77e97
5 changed files with 141 additions and 52 deletions

View File

@ -1,5 +1,8 @@
# Common function for defining algorithm component # 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( add_library(
pqclean_${name} pqclean_${name}
OBJECT OBJECT
@ -17,38 +20,11 @@ function(define_crypto_alg name namespace src inc test_src)
-DPQCLEAN_NAMESPACE=${namespace} -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() endfunction()
function(define_kem_alg name namespace src inc) 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() endfunction()
function(define_sig_alg name namespace src inc) 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() endfunction()

View File

@ -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} "~/.cmake/Modules")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "3rd/cmake-modules") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "3rd/cmake-modules")
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
@ -81,6 +82,9 @@ include_directories(
src src
) )
set_property(GLOBAL PROPERTY obj_libs "")
# Set CPU architecture # Set CPU architecture
set(CMAKE_C_FLAGS "${C_CXX_FLAGS} -D${ARCH}") set(CMAKE_C_FLAGS "${C_CXX_FLAGS} -D${ARCH}")
set(CMAKE_CXX_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-128s-robust/clean)
add_subdirectory(src/sign/sphincs/sphincs-sha256-128f-simple/clean) add_subdirectory(src/sign/sphincs/sphincs-sha256-128f-simple/clean)
add_subdirectory(src/sign/sphincs/sphincs-sha256-192f-robust/clean) add_subdirectory(src/sign/sphincs/sphincs-sha256-192f-robust/clean)
add_subdirectory(src/kem/kyber/kyber512/clean) add_subdirectory(src/kem/kyber/kyber512/clean)
add_subdirectory(src/kem/kyber/kyber768/clean) add_subdirectory(src/kem/kyber/kyber768/clean)
add_subdirectory(src/kem/kyber/kyber1024/clean) add_subdirectory(src/kem/kyber/kyber1024/clean)
@ -217,21 +222,18 @@ add_library(
pqclean_s pqclean_s
STATIC STATIC
) )
get_property(OBJ_LIBS GLOBAL PROPERTY obj_libs)
target_link_libraries( target_link_libraries(
pqclean pqclean
common common
pqclean_dilithium2_clean ${OBJ_LIBS}
pqclean_dilithium3_clean
pqclean_dilithium5_clean
) )
target_link_libraries( target_link_libraries(
pqclean_s pqclean_s
common common
pqclean_dilithium2_clean ${OBJ_LIBS}
pqclean_dilithium3_clean
pqclean_dilithium5_clean
) )
add_executable( add_executable(
@ -243,8 +245,8 @@ add_executable(
target_link_libraries( target_link_libraries(
mytest mytest
gtest gtest
pqclean_s gtest_main
gtest_main) pqclean_s)
target_include_directories( target_include_directories(
mytest PRIVATE mytest PRIVATE

View File

@ -1,11 +1,16 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "pqapi.h" #include "pqapi.h"
#include "kem/kyber/kyber512/clean/api.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 // helpers
#define OPT_VERSION _CLEAN_ #define OPT_VERSION _CLEAN_
// Helper to stringify constants // Helper to stringify constants
#define STR(x) STR_(x) #define STR(x) STR_(x)
#define STR_(x) #x #define STR_(x) #x
@ -29,23 +34,49 @@
#define PQC_SIGN_BSZ(x) GLUE(A(x), CRYPTO_BYTES) #define PQC_SIGN_BSZ(x) GLUE(A(x), CRYPTO_BYTES)
#define PQC_CT_BSZ(x) GLUE(A(x), CRYPTO_CIPHERTEXTBYTES) #define PQC_CT_BSZ(x) GLUE(A(x), CRYPTO_CIPHERTEXTBYTES)
#define PQC_NAME(x) GLUE(A(x), CRYPTO_ALGNAME) #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 // Macro magic needed to initialize parameters for a scheme
#define REG_KEM(ID) \ #define REG_KEM(ID) \
{ \ { \
.p.alg_id = ID, \ .p = REG_ALG(ID), \
.p.alg_name = STR(ID), \ .ciphertext_bsz = PQC_CT_BSZ(ID),\
.p.prv_key_bsz = PQC_PRV_KEY_BSZ(ID), \ .secret_bsz = PQC_KEM_BSZ(ID), \
.p.pub_key_bsz = PQC_PUB_KEY_BSZ(ID), \ .encapsulate = PQC_FN_ENCAPS(ID),\
.ciphertext_bsz = PQC_CT_BSZ(ID), \ .decapsulate = PQC_FN_DECAPS(ID),\
.secret_bsz = PQC_KEM_BSZ(ID) \
} }
enum { enum {
KYBER512 KYBER512,
KYBER768,
KYBER1024
}; };
const kem_params_t kems[] = { 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);
}

60
src/capi/pqapi.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef PQAPI_H_
#define PQAPI_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
// 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

View File

@ -1,9 +1,29 @@
#include <vector>
#include <algorithm>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "capi/pqapi.h" #include "capi/pqapi.h"
extern const kem_params_t kems[]; extern const kem_params_t kems[];
// TODO: change - just to see if function registration works OK. // TODO: change - just to see if function registration works OK.
TEST(Kyber,XXX) { TEST(Kyber,KEMOneOff) {
ASSERT_EQ(kems[0].p.prv_key_bsz, 1632);
for (int i=0; i<3; i++) {
const params_t *p = (params_t*)&kems[i];
std::vector<uint8_t> ct(ciphertext_bsz(p));
std::vector<uint8_t> ss1(shared_secret_bsz(p));
std::vector<uint8_t> ss2(shared_secret_bsz(p));
std::vector<uint8_t> sk(private_key_bsz(p));
std::vector<uint8_t> 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()));
}
} }