Skip to content

Commit

Permalink
expose kyber 768 in the ffi interface
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderkjall committed May 13, 2023
1 parent ce428cb commit 2e7880d
Show file tree
Hide file tree
Showing 3 changed files with 149 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 @@ -1492,6 +1492,22 @@ BOTAN_FFI_EXPORT(2,8) int botan_privkey_x25519_get_privkey(botan_privkey_t key,
BOTAN_FFI_EXPORT(2,8) int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key,
uint8_t pubkey[32]);

/*
* Algorithm specific key operations: Kyber768
*/

BOTAN_FFI_EXPORT(3,1) int botan_privkey_load_kyber768(botan_privkey_t* key,
const uint8_t privkey[2400]);

BOTAN_FFI_EXPORT(3,1) int botan_pubkey_load_kyber768(botan_pubkey_t* key,
const uint8_t pubkey[1184]);

BOTAN_FFI_EXPORT(3,1) int botan_privkey_kyber768_get_privkey(botan_privkey_t key,
uint8_t output[2400]);

BOTAN_FFI_EXPORT(3,1) int botan_pubkey_kyber768_get_pubkey(botan_pubkey_t key,
uint8_t pubkey[1184]);

/*
* Algorithm specific key operations: ECDSA and ECDH
*/
Expand Down
90 changes: 90 additions & 0 deletions src/lib/ffi/ffi_pkey_algs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
#include <botan/dh.h>
#endif

#if defined(BOTAN_HAS_KYBER)
#include <botan/kyber.h>
#endif

namespace {

Expand Down Expand Up @@ -868,6 +871,93 @@ int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key,
#endif
}

/*
* Algorithm specific key operations: Kyber768
*/

int botan_privkey_load_kyber768(botan_privkey_t* key,
const uint8_t privkey[2400])
{
#if defined(BOTAN_HAS_KYBER)
*key = nullptr;
return ffi_guard_thunk(__func__, [=]() -> int {
const Botan::secure_vector<uint8_t> privkey_vec(privkey, privkey + 2400);
auto kyber768 = std::make_unique<Botan::Kyber_PrivateKey>(privkey_vec, Botan::KyberMode::Kyber768);
*key = new botan_privkey_struct(std::move(kyber768));
return BOTAN_FFI_SUCCESS;
});
#else
BOTAN_UNUSED(key, privkey);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}

int botan_pubkey_load_kyber768(botan_pubkey_t* key,
const uint8_t pubkey[1184])
{
#if defined(BOTAN_HAS_KYBER)
*key = nullptr;
return ffi_guard_thunk(__func__, [=]() -> int {
const std::vector<uint8_t> pubkey_vec(pubkey, pubkey + 1184);
auto kyber768 = std::make_unique<Botan::Kyber_PublicKey>(pubkey_vec, Botan::KyberMode::Kyber768);
*key = new botan_pubkey_struct(std::move(kyber768));
return BOTAN_FFI_SUCCESS;
});
#else
BOTAN_UNUSED(key, pubkey);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}

int botan_privkey_kyber768_get_privkey(botan_privkey_t key,
uint8_t output[2400])
{
#if defined(BOTAN_HAS_KYBER)
return BOTAN_FFI_VISIT(key, [=](const auto& k) {
if(auto kyber768 = dynamic_cast<const Botan::Kyber_PrivateKey*>(&k))
{
const auto kyber768_key = kyber768->raw_private_key_bits();
if(kyber768_key.size() != 2400)
return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
Botan::copy_mem(output, kyber768_key.data(), kyber768_key.size());
return BOTAN_FFI_SUCCESS;
}
else
{
return BOTAN_FFI_ERROR_BAD_PARAMETER;
}
});
#else
BOTAN_UNUSED(key, output);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}

int botan_pubkey_kyber768_get_pubkey(botan_pubkey_t key,
uint8_t pubkey[1184])
{
#if defined(BOTAN_HAS_KYBER)
return BOTAN_FFI_VISIT(key, [=](const auto& k) {
if(auto kyber768 = dynamic_cast<const Botan::Kyber_PublicKey*>(&k))
{
const std::vector<uint8_t>& kyber768_key = kyber768->public_key_bits();
if(kyber768_key.size() != 1184)
return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
Botan::copy_mem(pubkey, kyber768_key.data(), kyber768_key.size());
return BOTAN_FFI_SUCCESS;
}
else
{
return BOTAN_FFI_ERROR_BAD_PARAMETER;
}
});
#else
BOTAN_UNUSED(key, pubkey);
return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}


int botan_pubkey_view_ec_public_point(
const botan_pubkey_t key,
botan_view_ctx ctx,
Expand Down
43 changes: 43 additions & 0 deletions src/tests/test_ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2672,6 +2672,48 @@ class FFI_X25519_Test final : public FFI_Test
}
};

class FFI_Kyber768_Test final : public FFI_Test
{
public:
std::string name() const override { return "FFI Kyber768"; }

void ffi_test(Test::Result& result, botan_rng_t /*unused*/) override
{
const std::vector<uint8_t> a_pub_bits =
Botan::hex_decode("38d4851e5c010da39a7470bc1c80916f78c7bd5891dcd3b1ea84b6f051b346b803c1b97c94604020b7279b27836c3049ea0b9a3758510b7559593237ade72587462206b709f365848c96559326a5fe6c6f4cf531fd1a18477267f66ba14af20163c41f1138a01995147f271ddfc2be5361b281e6029d210584b2859b7383667284f767bb32782baad10933da0138a3a0660a149531c03f9c8ffccb33e3c3a5a7984e21fab26aa72a8a6b942f265e52551a9c800e5a44805f0c0141a05554213387f105df56458496bd8f469051886da223cb9fe78e7b390bf94b0a937691af9550082b76d045cb4d29c23c67942608d078a1c80f24767a945d19f077d82c9b9b197073464abe69cf7c5626177308f384672d5263b0c4826db4470e1a70e4751e3918abe8fcbc3bc0531ae89e5512214b5cc94a16a014bcb3826c79fbf4add0825eeefbab88cb7cff37bb8d491f8de902578a1e961655565b7718782a23504fdc13c783f130e177925e305d1fbc63cc8c15c2c67f85500cca785de9f480490558ef71aaf0fb5b513914401269b309c4c59c64d2a757d8855f58465615925f1ea6812cb143fff383e1048e285118bf932944b86fbdf4b1b9e65685664a07775c46952aaada1168f54b47c7a231e7355c64637467b5a3c09cab67bb35f58640c2726283bb63530a15f66eca48a840c00ca8862e283c73bfbb413a2915b8d1159a043f12c59bfa828248249b76106faa61a127a0280c586350e7a42cb74ca49cabd606891ec7cb8e84affe4b2e14c71658332b755611bab7977fa76ce736b21ed34a17ac0ec3561ca9b282d4a2bc407697924b1cf918ba83d3a4fdc82564c95bd904bdeee91ed6ccb36baa88a05c80712901bf280aee6538ec2078c2a84ee5862fc137cd92e97968d69fc3453a1e1cb161c50c9f2473a0d09037b188a0fa01efc344c2ac8fe8592b0a58456662a95033659a158a2d90a6e50c253a87975785ce29c4570000a154d4b3b2c642205c8c7cf9ac6b1071fbb368ab950a744b88c95ba5243017831120a9048338d29847830d12a933a09abd21a46b828cb14e808cd35129c9dc6e5b931d4a126fefe07909618e2b4586e7b6b424963b7323ba505ba112bb9b834a7d1b78ad0df53d556a1c69369f09148b1dc9938df59223f087fd6833be5b2bc2651fe58911ac01467f9297dfdc22b41a0f1702718710b78cf35b1865813a896d45214d338155b6c043c532330c002d520739467a504a866637fb3451c849f8f83e6a94147f168da53acdf9d8affd968a84124a9abc09af960cd3b29f2344831bb41e67605eebf00df202857117399dd748b6514aed61bb2f6cb841d168d5f35e20054573a331cd4882a04b072c179158825bcf471266da0dcceab1a021c73254751d5a161c1a92062c220a217a69d9823314b4de996fe8d45f6db5af16c1561495a4c43090bc394c94e1b0ec738eb56267201c2ecd1c7b4993c0efc0284bdc9a091c294f95703a7178822c8a95b79b1e4591e0998d893875c1a879c08a073cc67df426bba792c18ae6c1feba879bec54812c2affa012973b700ad48e271078280864268600a7aa309eaa1098750a0f8a522eb929577b412f7855613688b72f9bc85c0a13b9d041586fd583feb12afd5a402dd33b43543f5fa4eb436c8d");
const std::vector<uint8_t> b_priv_bits =
Botan::hex_decode("9bc4986eec853ac90896c7300f914216773baa687f57f81f94e6b5a26515c0a74c73b19dc6b9888755a1d1db6a1128b02c5144ed9ba75e874a68a14dee3a9bf770b767121fbbdb292e097444757fe2f324a875b0a07a4fbdcc8fd6137fce80c69f412be103b01f8b3bed392600f830d1b20d73ca0b386666d16c5d96db10e309041890bfd4ab7bdec27191979abe7637e76153918cc2af1545724abfd95ca496281a0cc6ca63a87819b75aa86452e5027d429cad64a9c029112a3a7b9fb993c6a6d0671f6c9e24986b83f67cf1236d94c051559616826a947eaa15074025d1ab810c80220e8a8c2c222d4e8594bf35811b444a57e9bf94fb2479d174d6b38c8c3b4730437c244b2513232ec798adec4a8e597bca83bca5948468f93c022ba65311a91e3d95c299c70c3f1a43cd0c83dd500bd2211b9b385b82f2c003b10d295765b3e367563a5f19033fc1231db9620f835c95f5a261190a5da1c24ed528316f0a1520d223e208a8c99b24d28598ade74fc88370e7f45102c5a6411891c661b356b9a32e1cc0fafaa085d7670e8bcb5e768eb255204f2445b5b73b04079881903a553c865744343a925c7899777b1c9dd5579a481512f8157061606a9a67c041d38bc179048be17dd9e19dc0a572bce595afa3b68ff21bf78a63a7560636b6bb01ec3362e2aaabc8965818b7f2417ca8f66a5a2a67f72a3931e125d638a872862a7b680a54aa1f25d90dbd567635ec6664919e29517325a5c5048cc8d1c31af5e4866e85025b9184a7b75ed7f2c9c8d88259fa2ec5b05ed3751584f88308c67ff1a72fa2453305160baf404db7d4be56f1547b20bb7dec23f02b10db584b28ca40d8b39c1c3ab9f3d7bbda0822604ca48f26694d69810aa888ae3c0983c5ba4cb74211f7a5361ccdee694f4202aebe13a75b1b2dda1b3232376be213582afc4fde3474766671fe865e2fd98384eb65b2f349f1e24269b91bd9d08c80849735a9951304afd130b5c2211314630aed4b6ac3b1252a0999ff5a3ec26a283342389d219fd243706128b389eb2334fb2a6184a4eab6735d7428df5633ce030b8f853ee47c4401fc5d06b43c9b66b7aeeb23b5f000a30a6f88f027ee3994fe8b63e51b83bc24bb733a3773a35cbe138f6d9c91a3a3898bca6776030d740ac355176547d624719656a9a44e91c63faf7699dc6c2c45575718d48828828b39043c2fda2af416837efc38d17c56d4b63c63a5ab43434647d029f7b236b288958f06910763610f8b2f027a8dcd780039ab34a6871427476ff6500240e83b87c95dcfa45ac5315ef34b343fb609eb296e915c849bb8c57f57c69b177eaa8456377403fe8c6627a3282d45308f675d67085a15f0b1b55aa2a8f21afd6c05c3c00e9eb8c32418cb41963ce427b43e7545c58325c7b9368db2333de424dbeb3430f007d18a68d73b7dc67960b28206a68a1be400a770b5cd9d45a72824ca00345ac56491c1414fe5287a2eb2ad61f3bdcd0c84c335b04a703425d79dbd02b0a0e90de5b331c3c29f6562969e04cdf7095b2a7646b3d006b0b83cb68580b5ccb71de1b4d9f131bac133d6088e10613a00599d81d4818403a4bea83905304cc45ca645a9b2c6484cf9490f1755c744d9988ed60475e6ae44355ed15c7b549366f29581ec2721fd6704e0ca3f878812805675141c0a15a7b7ac35a9e3f8b2a010bc184981c57852895b2695d56131e32326717f6b101df1bc82b3ba0222d52656d118538c4ca3416be1c76ba37a9901a36e4883be6c541f2bbb561818cd2f136b98f658250545c1fa5bcfdc04374016db1c5132447fd6d568866451c25412f72967de868eaeb9c546fb40ea88cd84a1a586ca51c74bc9c3e56e104323afb658d1ac003151bdc35879a4b6762648bff0caa682f1b3319805d2326d5a46af832aacefbaa1ea820568ea3925870e9b6577eb93898e1b0cfbd1c995cb4cd6cabb979813819749b40a9952f50e97c4365e777dcfe9084219294c205acb350e07db9c98f53444546460962e2bf5aa1cc12273d882fcc215a7397b3f9b307c56b9a0429b30f88453a2376669b28b4bc4b84b51714b6652b7a1a0b53e9ec61b55ca51cdb38243239ee5f18243e515f178768a888f475b3d9060136bb22ee355b3da02c16ad83bdbb4aaa13809cb4bcd5bb53710737d3883632f9254e3336af61621a376720572450e3937c0d930e349adbfa7642ff822b9135e18f943e0178617604d10e0c09ffb3e09783c09d12cbe93311757af9857b77d1488ed39321ca97c3745c5bc176ca81274c8321bcb2029938b32bbd01aec137032f9760849701649120050b50d8353c36b8bb7724a67e7660fc93324065d63912c35a86d8fe60683067bbd2685c552ad8c65c77c57c937676fd61595c453174bf996e9d3a9ccb837b25464115c1ba3343ac097b80735aed3225091167cd8f841ffe49c5e698ef542124253084623179394433a4b61547b9ee09c98c2736ea086bd69d1bc7ae68a6ae5ce682a215860006b4604dee45a3e212f97643acb77a79a880382e483537c5198d4483a176d25aac9c3670a3f30956f18ad441904776bcd48131c7d6465bce0c133010f3176c92ec962f5c6b84d4c3ae949619cf48172997ca3b1ccf5c8cc7a67923e1295801048a3d40ac4f2c6467c750fc71314a0c1fc22637dd52e7ea50907ea973d765a6a9bb2b11aa405b9187f72026696710e61af3e41c33da1a05eb65e6523704f078e74e32f10e00247967aee3a8c6546889ef67cd613ad7236583f2104122ac6c6a40a84dc96d81c569e76a952c0a25f396e48337a4fe029a4c91cc7406872706a55573b75f160a4facad7c85fab141c63454bf48990729096ce9965604c7cc1e60ae6868dcc41bc3df71c3e5593f0488b0c6a3063e817f9f4bacb17599c8666ff3591126b4891fb7f5d29660bab60cf5007043a4311d41ab3b29787184f3d3c9ab7cc247f635145b67e970505ba44ad0e06b11ec5cda4175295199d19d660204cbdc17947cc66442d3a2cd408a20fe98174f31ee4e5bb3fa8bcd102bedc26527e9bae836442978a6ccbe510f93ab77569ab1f09d0e6312dd0cc0bcaf095fa8a52a7212d14714a7bf852416c9b026301bd965c30a43d24d97298346a46b2c4bc814ba4059653358b03c9456c60bf0193932eaa2f24ea8e4b010a5a4425ce4540fbab90d8e55c97ac2687f15ff5299278824a08d4743e1a62e1c6619cd3278cd75a97a5b4e3a38668b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb3339ae9c9ce46d9da0e714c0bae8712a670d0e5dcfdd1dd0d045932c79c559b2ab3c7300e2d894b0eaa40a6ab254506d8c1176a33c4a1b2879604b1b80df48d31dd");
const std::vector<uint8_t> b_pub_bits =
Botan::hex_decode("f9490f1755c744d9988ed60475e6ae44355ed15c7b549366f29581ec2721fd6704e0ca3f878812805675141c0a15a7b7ac35a9e3f8b2a010bc184981c57852895b2695d56131e32326717f6b101df1bc82b3ba0222d52656d118538c4ca3416be1c76ba37a9901a36e4883be6c541f2bbb561818cd2f136b98f658250545c1fa5bcfdc04374016db1c5132447fd6d568866451c25412f72967de868eaeb9c546fb40ea88cd84a1a586ca51c74bc9c3e56e104323afb658d1ac003151bdc35879a4b6762648bff0caa682f1b3319805d2326d5a46af832aacefbaa1ea820568ea3925870e9b6577eb93898e1b0cfbd1c995cb4cd6cabb979813819749b40a9952f50e97c4365e777dcfe9084219294c205acb350e07db9c98f53444546460962e2bf5aa1cc12273d882fcc215a7397b3f9b307c56b9a0429b30f88453a2376669b28b4bc4b84b51714b6652b7a1a0b53e9ec61b55ca51cdb38243239ee5f18243e515f178768a888f475b3d9060136bb22ee355b3da02c16ad83bdbb4aaa13809cb4bcd5bb53710737d3883632f9254e3336af61621a376720572450e3937c0d930e349adbfa7642ff822b9135e18f943e0178617604d10e0c09ffb3e09783c09d12cbe93311757af9857b77d1488ed39321ca97c3745c5bc176ca81274c8321bcb2029938b32bbd01aec137032f9760849701649120050b50d8353c36b8bb7724a67e7660fc93324065d63912c35a86d8fe60683067bbd2685c552ad8c65c77c57c937676fd61595c453174bf996e9d3a9ccb837b25464115c1ba3343ac097b80735aed3225091167cd8f841ffe49c5e698ef542124253084623179394433a4b61547b9ee09c98c2736ea086bd69d1bc7ae68a6ae5ce682a215860006b4604dee45a3e212f97643acb77a79a880382e483537c5198d4483a176d25aac9c3670a3f30956f18ad441904776bcd48131c7d6465bce0c133010f3176c92ec962f5c6b84d4c3ae949619cf48172997ca3b1ccf5c8cc7a67923e1295801048a3d40ac4f2c6467c750fc71314a0c1fc22637dd52e7ea50907ea973d765a6a9bb2b11aa405b9187f72026696710e61af3e41c33da1a05eb65e6523704f078e74e32f10e00247967aee3a8c6546889ef67cd613ad7236583f2104122ac6c6a40a84dc96d81c569e76a952c0a25f396e48337a4fe029a4c91cc7406872706a55573b75f160a4facad7c85fab141c63454bf48990729096ce9965604c7cc1e60ae6868dcc41bc3df71c3e5593f0488b0c6a3063e817f9f4bacb17599c8666ff3591126b4891fb7f5d29660bab60cf5007043a4311d41ab3b29787184f3d3c9ab7cc247f635145b67e970505ba44ad0e06b11ec5cda4175295199d19d660204cbdc17947cc66442d3a2cd408a20fe98174f31ee4e5bb3fa8bcd102bedc26527e9bae836442978a6ccbe510f93ab77569ab1f09d0e6312dd0cc0bcaf095fa8a52a7212d14714a7bf852416c9b026301bd965c30a43d24d97298346a46b2c4bc814ba4059653358b03c9456c60bf0193932eaa2f24ea8e4b010a5a4425ce4540fbab90d8e55c97ac2687f15ff5299278824a08d4743e1a62e1c6619cd3278cd75a97a5b4e3a38668b26c99bf8461495793bbb1b12ca369c825cb31d68731326bf4764b416bb333");
const std::vector<uint8_t> shared_secret_bits =
Botan::hex_decode("2ea203f65a441678ee65629efccfd0907a090e4226064d513aa7d9b4cf4837b4");

botan_privkey_t b_priv;
if(!TEST_FFI_INIT(botan_privkey_load_kyber768, (&b_priv, b_priv_bits.data())))
return;

std::vector<uint8_t> privkey_read(2400);
TEST_FFI_OK(botan_privkey_kyber768_get_privkey, (b_priv, privkey_read.data()));
result.test_eq("kyber768 private key", privkey_read, b_priv_bits);

std::vector<uint8_t> pubkey_read(1184);

botan_pubkey_t b_pub;
TEST_FFI_OK(botan_privkey_export_pubkey, (&b_pub, b_priv));
TEST_FFI_OK(botan_pubkey_kyber768_get_pubkey, (b_pub, pubkey_read.data()));
result.test_eq("kyber768 public key b", pubkey_read, b_pub_bits);

botan_pubkey_t a_pub;
TEST_FFI_OK(botan_pubkey_load_kyber768, (&a_pub, a_pub_bits.data()));
TEST_FFI_OK(botan_pubkey_kyber768_get_pubkey, (a_pub, pubkey_read.data()));
result.test_eq("kyber768 public key a", pubkey_read, a_pub_bits);

TEST_FFI_OK(botan_pubkey_destroy, (a_pub));
TEST_FFI_OK(botan_pubkey_destroy, (b_pub));
TEST_FFI_OK(botan_privkey_destroy, (b_priv));
}
};

class FFI_ElGamal_Test final : public FFI_Test
{
public:
Expand Down Expand Up @@ -2911,6 +2953,7 @@ BOTAN_REGISTER_TEST("ffi", "ffi_ecdh", FFI_ECDH_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_mceliece", FFI_McEliece_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_ed25519", FFI_Ed25519_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_x25519", FFI_X25519_Test);
BOTAN_REGISTER_TEST("ffi", "ffi_kyber768", FFI_Kyber768_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 2e7880d

Please sign in to comment.