Skip to content

Commit

Permalink
Integrate C. McEliece into FFI and Python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
reneme committed Oct 18, 2024
1 parent 15759b0 commit 083e153
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/lib/ffi/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,22 @@ int botan_privkey_load_frodokem(botan_privkey_t* key, const uint8_t privkey[], s
BOTAN_FFI_EXPORT(3, 6)
int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size_t key_len, const char* frodo_mode);

/**
* Algorithm specific key operation: Classic McEliece
*/

BOTAN_FFI_EXPORT(3, 6)
int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
const uint8_t privkey[],
size_t key_len,
const char* cmce_mode);

BOTAN_FFI_EXPORT(3, 6)
int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
const uint8_t pubkey[],
size_t key_len,
const char* cmce_mode);

/*
* Algorithm specific key operations: ML-KEM
*/
Expand Down
54 changes: 54 additions & 0 deletions src/lib/ffi/ffi_pkey_algs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@
#include <botan/slh_dsa.h>
#endif

#if defined(BOTAN_HAS_CLASSICMCELIECE)
#include <botan/cmce.h>
#endif

namespace {

#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
Expand Down Expand Up @@ -1243,6 +1247,56 @@ int botan_pubkey_load_frodokem(botan_pubkey_t* key, const uint8_t pubkey[], size
#endif
}

/*
* Algorithm specific key operations : Classic McEliece
*/

int botan_privkey_load_classic_mceliece(botan_privkey_t* key,
const uint8_t privkey[],
size_t key_len,
const char* cmce_mode) {
#if defined(BOTAN_HAS_CLASSICMCELIECE)
if(key == nullptr || privkey == nullptr || cmce_mode == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

*key = nullptr;

return ffi_guard_thunk(__func__, [=]() -> int {
const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
auto cmce_key = std::make_unique<Botan::Classic_McEliece_PrivateKey>(std::span{privkey, key_len}, mode);
*key = new botan_privkey_struct(std::move(cmce_key));
return BOTAN_FFI_SUCCESS;
});
#else
BOTAN_UNUSED(key, privkey, key_len, cmce_mode);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}

int botan_pubkey_load_classic_mceliece(botan_pubkey_t* key,
const uint8_t pubkey[],
size_t key_len,
const char* cmce_mode) {
#if defined(BOTAN_HAS_CLASSICMCELIECE)
if(key == nullptr || pubkey == nullptr || cmce_mode == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

*key = nullptr;

return ffi_guard_thunk(__func__, [=]() -> int {
const auto mode = Botan::Classic_McEliece_Parameter_Set::from_string(cmce_mode);
auto cmce_key = std::make_unique<Botan::Classic_McEliece_PublicKey>(std::span{pubkey, key_len}, mode);
*key = new botan_pubkey_struct(std::move(cmce_key));
return BOTAN_FFI_SUCCESS;
});
#else
BOTAN_UNUSED(key, pubkey, key_len, cmce_mode);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}

int botan_pubkey_view_ec_public_point(const botan_pubkey_t key, botan_view_ctx ctx, botan_view_bin_fn view) {
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
return BOTAN_FFI_VISIT(key, [=](const auto& k) -> int {
Expand Down
14 changes: 14 additions & 0 deletions src/python/botan3.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ def ffi_api(fn, args, allowed_errors=None):
ffi_api(dll.botan_pubkey_load_ml_kem, [c_void_p, c_void_p, c_int, c_char_p])
ffi_api(dll.botan_privkey_load_frodokem, [c_void_p, c_void_p, c_int, c_char_p])
ffi_api(dll.botan_pubkey_load_frodokem, [c_void_p, c_void_p, c_int, c_char_p])
ffi_api(dll.botan_privkey_load_classic_mceliece, [c_void_p, c_void_p, c_int, c_char_p])
ffi_api(dll.botan_pubkey_load_classic_mceliece, [c_void_p, c_void_p, c_int, c_char_p])
ffi_api(dll.botan_privkey_load_ecdsa, [c_void_p, c_void_p, c_char_p])
ffi_api(dll.botan_pubkey_load_ecdsa, [c_void_p, c_void_p, c_void_p, c_char_p])
ffi_api(dll.botan_pubkey_load_ecdh, [c_void_p, c_void_p, c_void_p, c_char_p])
Expand Down Expand Up @@ -1264,6 +1266,12 @@ def load_frodokem(cls, frodo_mode, key):
_DLL.botan_pubkey_load_frodokem(byref(obj), key, len(key), _ctype_str(frodo_mode))
return PublicKey(obj)

@classmethod
def load_classic_mceliece(cls, cmce_mode, key):
obj = c_void_p(0)
_DLL.botan_pubkey_load_classic_mceliece(byref(obj), key, len(key), _ctype_str(cmce_mode))
return PublicKey(obj)

def __del__(self):
_DLL.botan_pubkey_destroy(self.__obj)

Expand Down Expand Up @@ -1447,6 +1455,12 @@ def load_frodokem(cls, frodo_mode, key):
_DLL.botan_privkey_load_frodokem(byref(obj), key, len(key), _ctype_str(frodo_mode))
return PrivateKey(obj)

@classmethod
def load_classic_mceliece(cls, cmce_mode, key):
obj = c_void_p(0)
_DLL.botan_privkey_load_classic_mceliece(byref(obj), key, len(key), _ctype_str(cmce_mode))
return PrivateKey(obj)

def __del__(self):
_DLL.botan_privkey_destroy(self.__obj)

Expand Down
15 changes: 15 additions & 0 deletions src/scripts/test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,21 @@ def test_frodokem_raw_keys(self):
self.assertEqual(sk_read.to_raw(), sk_bits)
self.assertEqual(pk_read.to_raw(), pk_bits)

def test_classic_mceliece_raw_keys(self):
cmce_mode = "mceliece348864f"
sk = botan.PrivateKey.create("ClassicMcEliece", cmce_mode, botan.RandomNumberGenerator("user"))
pk = sk.get_public_key()

sk_bits = sk.to_raw()
pk_bits = pk.to_raw()

sk_read = botan.PrivateKey.load_classic_mceliece(cmce_mode, sk_bits)
pk_read = botan.PublicKey.load_classic_mceliece(cmce_mode, pk_bits)

self.assertEqual(sk_read.to_raw(), sk_bits)
self.assertEqual(pk_read.to_raw(), pk_bits)


class BotanPythonZfecTests(unittest.TestCase):
"""
Tests relating to the ZFEC bindings
Expand Down
40 changes: 40 additions & 0 deletions src/tests/test_ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3818,6 +3818,45 @@ class FFI_SLH_DSA_Test final : public FFI_Signature_Roundtrip_Test {
const char* hash_algo_or_padding() const override { return ""; }
};

class FFI_Classic_McEliece_Test final : public FFI_KEM_Roundtrip_Test {
public:
std::string name() const override { return "FFI Classic McEliece"; }

protected:
const char* algo() const override { return "ClassicMcEliece"; }

privkey_loader_fn_t private_key_load_function() const override { return botan_privkey_load_classic_mceliece; }

pubkey_loader_fn_t public_key_load_function() const override { return botan_pubkey_load_classic_mceliece; }

std::vector<const char*> modes() const override {
auto modes = std::vector{
"mceliece348864f",
"mceliece460896f",
};
if(Test::run_long_tests()) {
modes = Botan::concat(modes,
std::vector{
"mceliece348864",
"mceliece460896",
"mceliece6688128",
"mceliece6688128f",
"mceliece6688128pc",
"mceliece6688128pcf",
"mceliece6960119",
"mceliece6960119f",
"mceliece6960119pc",
"mceliece6960119pcf",
"mceliece8192128",
"mceliece8192128f",
"mceliece8192128pc",
"mceliece8192128pcf",
});
}
return modes;
}
};

class FFI_ElGamal_Test final : public FFI_Test {
public:
std::string name() const override { return "FFI ElGamal"; }
Expand Down Expand Up @@ -4064,6 +4103,7 @@ BOTAN_REGISTER_TEST("ffi", "ffi_ml_kem", FFI_ML_KEM_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_ml_dsa", FFI_ML_DSA_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_slh_dsa", FFI_SLH_DSA_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_frodokem", FFI_FrodoKEM_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_cmce", FFI_Classic_McEliece_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_elgamal", FFI_ElGamal_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_dh", FFI_DH_Test);

Expand Down

0 comments on commit 083e153

Please sign in to comment.