Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hard-coded usage of the system RNG in ffi_pk_op #4411

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/lib/ffi/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,10 @@ typedef struct botan_pk_op_encrypt_struct* botan_pk_op_encrypt_t;
BOTAN_FFI_EXPORT(2, 0)
int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op, botan_pubkey_t key, const char* padding, uint32_t flags);

BOTAN_FFI_EXPORT(3, 7)
int botan_pk_op_encrypt_create_with_rng(
botan_pk_op_encrypt_t* op, botan_rng_t rng, botan_pubkey_t key, const char* padding, uint32_t flags);

/**
* @return 0 if success, error if invalid object handle
*/
Expand All @@ -1650,6 +1654,10 @@ typedef struct botan_pk_op_decrypt_struct* botan_pk_op_decrypt_t;
BOTAN_FFI_EXPORT(2, 0)
int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op, botan_privkey_t key, const char* padding, uint32_t flags);

BOTAN_FFI_EXPORT(3, 7)
int botan_pk_op_decrypt_create_with_rng(
botan_pk_op_decrypt_t* op, botan_rng_t rng, botan_privkey_t key, const char* padding, uint32_t flags);

/**
* @return 0 if success, error if invalid object handle
*/
Expand All @@ -1673,6 +1681,10 @@ typedef struct botan_pk_op_sign_struct* botan_pk_op_sign_t;
BOTAN_FFI_EXPORT(2, 0)
int botan_pk_op_sign_create(botan_pk_op_sign_t* op, botan_privkey_t key, const char* hash_and_padding, uint32_t flags);

BOTAN_FFI_EXPORT(3, 7)
int botan_pk_op_sign_create_with_rng(
botan_pk_op_sign_t* op, botan_rng_t rng, botan_privkey_t key, const char* hash_and_padding, uint32_t flags);

/**
* @return 0 if success, error if invalid object handle
*/
Expand Down Expand Up @@ -1712,6 +1724,10 @@ typedef struct botan_pk_op_ka_struct* botan_pk_op_ka_t;
BOTAN_FFI_EXPORT(2, 0)
int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op, botan_privkey_t key, const char* kdf, uint32_t flags);

BOTAN_FFI_EXPORT(3, 7)
int botan_pk_op_key_agreement_create_with_rng(
botan_pk_op_ka_t* op, botan_rng_t rng, botan_privkey_t key, const char* kdf, uint32_t flags);

/**
* @return 0 if success, error if invalid object handle
*/
Expand Down Expand Up @@ -1771,6 +1787,12 @@ typedef struct botan_pk_op_kem_decrypt_struct* botan_pk_op_kem_decrypt_t;
BOTAN_FFI_EXPORT(3, 0)
int botan_pk_op_kem_decrypt_create(botan_pk_op_kem_decrypt_t* op, botan_privkey_t key, const char* kdf);

BOTAN_FFI_EXPORT(3, 7)
int botan_pk_op_kem_decrypt_create_with_rng(botan_pk_op_kem_decrypt_t* op,
botan_rng_t rng,
botan_privkey_t key,
const char* kdf);

/**
* @return 0 if success, error if invalid object handle
*/
Expand Down
101 changes: 101 additions & 0 deletions src/lib/ffi/ffi_pk_op.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op, botan_pubkey_t key_obj
});
}

int botan_pk_op_encrypt_create_with_rng(
botan_pk_op_encrypt_t* op, botan_rng_t rng_obj, botan_pubkey_t key_obj, const char* padding, uint32_t flags) {
if(op == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

if(flags != 0 && flags != BOTAN_PUBKEY_DER_FORMAT_SIGNATURE) {
return BOTAN_FFI_ERROR_BAD_FLAG;
}

return ffi_guard_thunk(__func__, [=]() -> int {
*op = nullptr;

Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

auto pk = std::make_unique<Botan::PK_Encryptor_EME>(safe_get(key_obj), rng, padding);
*op = new botan_pk_op_encrypt_struct(std::move(pk));
return BOTAN_FFI_SUCCESS;
});
}

int botan_pk_op_encrypt_destroy(botan_pk_op_encrypt_t op) {
return BOTAN_FFI_CHECKED_DELETE(op);
}
Expand Down Expand Up @@ -89,6 +110,27 @@ int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op,
});
}

int botan_pk_op_decrypt_create_with_rng(
botan_pk_op_decrypt_t* op, botan_rng_t rng_obj, botan_privkey_t key_obj, const char* padding, uint32_t flags) {
if(op == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

if(flags != 0) {
return BOTAN_FFI_ERROR_BAD_FLAG;
}

return ffi_guard_thunk(__func__, [=]() -> int {
*op = nullptr;

Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

auto pk = std::make_unique<Botan::PK_Decryptor_EME>(safe_get(key_obj), rng, padding);
*op = new botan_pk_op_decrypt_struct(std::move(pk));
return BOTAN_FFI_SUCCESS;
});
}

int botan_pk_op_decrypt_destroy(botan_pk_op_decrypt_t op) {
return BOTAN_FFI_CHECKED_DELETE(op);
}
Expand Down Expand Up @@ -130,6 +172,30 @@ int botan_pk_op_sign_create(botan_pk_op_sign_t* op, botan_privkey_t key_obj, con
});
}

int botan_pk_op_sign_create_with_rng(
botan_pk_op_sign_t* op, botan_rng_t rng_obj, botan_privkey_t key_obj, const char* hash, uint32_t flags) {
if(op == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

if(flags != 0 && flags != BOTAN_PUBKEY_DER_FORMAT_SIGNATURE) {
return BOTAN_FFI_ERROR_BAD_FLAG;
}

return ffi_guard_thunk(__func__, [=]() -> int {
*op = nullptr;

auto format = (flags & BOTAN_PUBKEY_DER_FORMAT_SIGNATURE) ? Botan::Signature_Format::DerSequence
: Botan::Signature_Format::Standard;

Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

auto pk = std::make_unique<Botan::PK_Signer>(safe_get(key_obj), rng, hash, format);
*op = new botan_pk_op_sign_struct(std::move(pk));
return BOTAN_FFI_SUCCESS;
});
}

int botan_pk_op_sign_destroy(botan_pk_op_sign_t op) {
return BOTAN_FFI_CHECKED_DELETE(op);
}
Expand Down Expand Up @@ -205,6 +271,25 @@ int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op, botan_privkey_t key_o
});
}

int botan_pk_op_key_agreement_create_with_rng(
botan_pk_op_ka_t* op, botan_rng_t rng_obj, botan_privkey_t key_obj, const char* kdf, uint32_t flags) {
if(op == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

if(flags != 0) {
return BOTAN_FFI_ERROR_BAD_FLAG;
}

return ffi_guard_thunk(__func__, [=]() -> int {
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
*op = nullptr;
auto pk = std::make_unique<Botan::PK_Key_Agreement>(safe_get(key_obj), rng, kdf);
*op = new botan_pk_op_ka_struct(std::move(pk));
return BOTAN_FFI_SUCCESS;
});
}

int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op) {
return BOTAN_FFI_CHECKED_DELETE(op);
}
Expand Down Expand Up @@ -318,6 +403,22 @@ int botan_pk_op_kem_decrypt_create(botan_pk_op_kem_decrypt_t* op, botan_privkey_
});
}

int botan_pk_op_kem_decrypt_create_with_rng(botan_pk_op_kem_decrypt_t* op,
botan_rng_t rng_obj,
botan_privkey_t key_obj,
const char* padding) {
if(op == nullptr || padding == nullptr) {
return BOTAN_FFI_ERROR_NULL_POINTER;
}

return ffi_guard_thunk(__func__, [=]() -> int {
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
auto pk = std::make_unique<Botan::PK_KEM_Decryptor>(safe_get(key_obj), rng, padding);
*op = new botan_pk_op_kem_decrypt_struct(std::move(pk));
return BOTAN_FFI_SUCCESS;
});
}

int botan_pk_op_kem_decrypt_shared_key_length(botan_pk_op_kem_decrypt_t op,
size_t desired_shared_key_length,
size_t* output_shared_key_length) {
Expand Down
72 changes: 59 additions & 13 deletions src/tests/test_ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2484,9 +2484,7 @@ class FFI_RSA_Test final : public FFI_Test {
result.test_eq("algo name", std::string(namebuf), "RSA");
}

botan_pk_op_encrypt_t encrypt;

if(TEST_FFI_INIT(botan_pk_op_encrypt_create, (&encrypt, loaded_pubkey, "OAEP(SHA-256)", 0))) {
auto test_encrypt_opt_fn = [&result, &rng, &priv](botan_pk_op_encrypt_t encrypt) {
std::vector<uint8_t> plaintext(32);
TEST_FFI_OK(botan_rng_get, (rng, plaintext.data(), plaintext.size()));

Expand All @@ -2499,7 +2497,7 @@ class FFI_RSA_Test final : public FFI_Test {
ciphertext.resize(ctext_len);

botan_pk_op_decrypt_t decrypt;
if(TEST_FFI_OK(botan_pk_op_decrypt_create, (&decrypt, priv, "OAEP(SHA-256)", 0))) {
if(TEST_FFI_OK(botan_pk_op_decrypt_create_with_rng, (&decrypt, rng, priv, "OAEP(SHA-256)", 0))) {
size_t decrypted_len;
TEST_FFI_OK(botan_pk_op_decrypt_output_length, (decrypt, ciphertext.size(), &decrypted_len));
std::vector<uint8_t> decrypted(decrypted_len);
Expand All @@ -2514,6 +2512,16 @@ class FFI_RSA_Test final : public FFI_Test {
}

TEST_FFI_OK(botan_pk_op_encrypt_destroy, (encrypt));
};

botan_pk_op_encrypt_t encrypt;

if(TEST_FFI_INIT(botan_pk_op_encrypt_create, (&encrypt, loaded_pubkey, "OAEP(SHA-256)", 0))) {
test_encrypt_opt_fn(encrypt);
}

if(TEST_FFI_INIT(botan_pk_op_encrypt_create_with_rng, (&encrypt, rng, loaded_pubkey, "OAEP(SHA-256)", 0))) {
test_encrypt_opt_fn(encrypt);
}

TEST_FFI_OK(botan_pubkey_destroy, (loaded_pubkey));
Expand Down Expand Up @@ -2975,7 +2983,7 @@ class FFI_ECDH_Test final : public FFI_Test {
botan_pk_op_ka_t ka1;
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "KDF2(SHA-256)", 0));
botan_pk_op_ka_t ka2;
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "KDF2(SHA-256)", 0));
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create_with_rng, (&ka2, rng, priv2, "KDF2(SHA-256)", 0));

size_t pubkey1_len = 0;
TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE,
Expand Down Expand Up @@ -3150,10 +3158,9 @@ class FFI_Ed448_Test final : public FFI_Test {
TEST_FFI_OK(botan_pubkey_destroy, (pub));
TEST_FFI_OK(botan_pubkey_load_ed448, (&pub, pk_ref.data()));

botan_pk_op_sign_t signer;
std::vector<uint8_t> signature;

if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv, "Pure", 0))) {
auto sign_fn = [&result, &rng, &msg, &signature](botan_pk_op_sign_t signer) {
TEST_FFI_OK(botan_pk_op_sign_update, (signer, msg.data(), msg.size()));

size_t sig_len;
Expand All @@ -3165,6 +3172,18 @@ class FFI_Ed448_Test final : public FFI_Test {
signature.resize(sig_len);

TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
};

botan_pk_op_sign_t signer;

if(TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv, "Pure", 0))) {
sign_fn(signer);
}

result.test_eq("Expected signature", signature, sig_ref);

if(TEST_FFI_OK(botan_pk_op_sign_create_with_rng, (&signer, rng, priv, "Pure", 0))) {
sign_fn(signer);
}

result.test_eq("Expected signature", signature, sig_ref);
Expand Down Expand Up @@ -3340,6 +3359,7 @@ class FFI_KEM_Roundtrip_Test : public FFI_Test {

public:
void ffi_test(Test::Result& result, botan_rng_t rng) override {
bool use_explicit_rng = true;
for(auto mode : modes()) {
// generate a key pair
botan_privkey_t priv;
Expand Down Expand Up @@ -3423,7 +3443,11 @@ class FFI_KEM_Roundtrip_Test : public FFI_Test {

// KEM decryption (using the generated private key)
botan_pk_op_kem_decrypt_t kem_dec;
TEST_FFI_OK(botan_pk_op_kem_decrypt_create, (&kem_dec, priv, "Raw"));
if(use_explicit_rng) {
TEST_FFI_OK(botan_pk_op_kem_decrypt_create_with_rng, (&kem_dec, rng, priv, "Raw"));
} else {
TEST_FFI_OK(botan_pk_op_kem_decrypt_create, (&kem_dec, priv, "Raw"));
}
size_t shared_key_length2 = 0;
TEST_FFI_OK(botan_pk_op_kem_decrypt_shared_key_length, (kem_dec, shared_key_length, &shared_key_length2));
result.test_eq("shared key lengths are consistent", shared_key_length, shared_key_length2);
Expand Down Expand Up @@ -3465,6 +3489,8 @@ class FFI_KEM_Roundtrip_Test : public FFI_Test {
TEST_FFI_OK(botan_pubkey_destroy, (pub_loaded));
TEST_FFI_OK(botan_privkey_destroy, (priv));
TEST_FFI_OK(botan_privkey_destroy, (priv_loaded));

use_explicit_rng = !use_explicit_rng;
}
}
};
Expand All @@ -3489,6 +3515,7 @@ class FFI_Signature_Roundtrip_Test : public FFI_Test {
const std::vector<uint8_t> message1 = {'H', 'e', 'l', 'l', 'o', ' '};
const std::vector<uint8_t> message2 = {'W', 'o', 'r', 'l', 'd', '!'};

bool use_explicit_rng = true;
for(auto mode : modes()) {
// generate a key pair
botan_privkey_t priv;
Expand Down Expand Up @@ -3522,7 +3549,11 @@ class FFI_Signature_Roundtrip_Test : public FFI_Test {

// Signature Creation (using the loaded private key)
botan_pk_op_sign_t signer;
TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv_loaded, hash_algo_or_padding(), 0));
if(use_explicit_rng) {
TEST_FFI_OK(botan_pk_op_sign_create_with_rng, (&signer, rng, priv_loaded, hash_algo_or_padding(), 0));
} else {
TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv_loaded, hash_algo_or_padding(), 0));
}

// explicitly query the signature output length
size_t sig_output_length = 0;
Expand All @@ -3541,7 +3572,11 @@ class FFI_Signature_Roundtrip_Test : public FFI_Test {

// Recreate signer and try again
TEST_FFI_OK(botan_pk_op_sign_destroy, (signer));
TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv_loaded, hash_algo_or_padding(), 0));
if(use_explicit_rng) {
TEST_FFI_OK(botan_pk_op_sign_create_with_rng, (&signer, rng, priv_loaded, hash_algo_or_padding(), 0));
} else {
TEST_FFI_OK(botan_pk_op_sign_create, (&signer, priv_loaded, hash_algo_or_padding(), 0));
}
TEST_FFI_OK(botan_pk_op_sign_update, (signer, message1.data(), message1.size()));
TEST_FFI_OK(botan_pk_op_sign_update, (signer, message2.data(), message2.size()));

Expand Down Expand Up @@ -3575,6 +3610,8 @@ class FFI_Signature_Roundtrip_Test : public FFI_Test {
TEST_FFI_OK(botan_pubkey_destroy, (pub_loaded));
TEST_FFI_OK(botan_privkey_destroy, (priv));
TEST_FFI_OK(botan_privkey_destroy, (priv_loaded));

use_explicit_rng = !use_explicit_rng;
}
}
};
Expand Down Expand Up @@ -3885,15 +3922,24 @@ class FFI_ElGamal_Test final : public FFI_Test {
}

// Test decryption
botan_pk_op_decrypt_t op_dec;
if(TEST_FFI_OK(botan_pk_op_decrypt_create, (&op_dec, loaded_privkey, "Raw", 0))) {
auto test_decrypt_fn = [&result, &decryption, &ciphertext](botan_pk_op_decrypt_t op_dec) {
size_t ptext_len;
TEST_FFI_OK(botan_pk_op_decrypt_output_length, (op_dec, ciphertext.size(), &ptext_len));
decryption.resize(ptext_len);
TEST_FFI_OK(botan_pk_op_decrypt,
(op_dec, decryption.data(), &ptext_len, ciphertext.data(), ciphertext.size()));
decryption.resize(ptext_len);
TEST_FFI_OK(botan_pk_op_decrypt_destroy, (op_dec));
};

botan_pk_op_decrypt_t op_dec;

if(TEST_FFI_OK(botan_pk_op_decrypt_create, (&op_dec, loaded_privkey, "Raw", 0))) {
test_decrypt_fn(op_dec);
}

if(TEST_FFI_OK(botan_pk_op_decrypt_create_with_rng, (&op_dec, rng, loaded_privkey, "Raw", 0))) {
test_decrypt_fn(op_dec);
}

result.test_eq("decryption worked", decryption, plaintext);
Expand Down Expand Up @@ -3966,7 +4012,7 @@ class FFI_DH_Test final : public FFI_Test {
result.confirm("bigint_mp_cmp(y, y)", cmp == 0);

botan_pk_op_ka_t ka1;
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka1, loaded_privkey1, "Raw", 0));
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create_with_rng, (&ka1, rng, loaded_privkey1, "Raw", 0));
botan_pk_op_ka_t ka2;
REQUIRE_FFI_OK(botan_pk_op_key_agreement_create, (&ka2, priv2, "Raw", 0));

Expand Down
Loading