Skip to content

Commit

Permalink
New interface for PKCS8 key encryption
Browse files Browse the repository at this point in the history
Quite a few interfaces exist for this but there really are only two
things that change between them: if the PBKDF runtime is specified in
"iterations" or in a duration, and if the result is PEM encoded or not.

Add a new single interface for PKCS8 encryption, PKCS8::encrypt_private_key,
then define all of the previously existing functions in terms of that.
  • Loading branch information
randombit committed Jan 25, 2025
1 parent 79027d2 commit 212e628
Show file tree
Hide file tree
Showing 8 changed files with 359 additions and 295 deletions.
70 changes: 35 additions & 35 deletions src/cli/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,30 @@ class PK_Keygen final : public Command {
const std::string pass = get_passphrase_arg("Key passphrase", "passphrase");
const bool der_out = flag_set("der-out");

const std::chrono::milliseconds pbkdf_ms(get_arg_sz("pbkdf-ms"));

if(der_out) {
if(pass.empty()) {
if(pass.empty()) {
if(der_out) {
write_output(Botan::PKCS8::BER_encode(*key));
} else {
if(get_arg("pbkdf-iter").empty()) {
write_output(Botan::PKCS8::BER_encode_encrypted_pbkdf_msec(
*key, rng(), pass, pbkdf_ms, nullptr, get_arg("cipher"), get_arg("pbkdf")));
} else {
write_output(Botan::PKCS8::BER_encode_encrypted_pbkdf_iter(
*key, rng(), pass, get_arg_sz("pbkdf-iter"), get_arg("cipher"), get_arg("pbkdf")));
}
output() << Botan::PKCS8::PEM_encode(*key);
}
} else {
if(pass.empty()) {
output() << Botan::PKCS8::PEM_encode(*key);
} else {
auto options = [&]() {
std::string cipher = get_arg("cipher");
std::string pwhash = get_arg("pbkdf");
if(get_arg("pbkdf-iter").empty()) {
output() << Botan::PKCS8::PEM_encode_encrypted_pbkdf_msec(
*key, rng(), pass, pbkdf_ms, nullptr, get_arg("cipher"), get_arg("pbkdf"));
const std::chrono::milliseconds pwhash_ms(get_arg_sz("pbkdf-ms"));
return Botan::PKCS8::KeyEncryptionOptions(cipher, pwhash, pwhash_ms);
} else {
output() << Botan::PKCS8::PEM_encode_encrypted_pbkdf_iter(
*key, rng(), pass, get_arg_sz("pbkdf-iter"), get_arg("cipher"), get_arg("pbkdf"));
return Botan::PKCS8::KeyEncryptionOptions(cipher, pwhash, get_arg_sz("pbkdf-iter"));
}
}();

auto pkcs8 = Botan::PKCS8::encrypt_private_key(*key, pass, rng(), options);

if(der_out) {
write_output(pkcs8.as_bytes());
} else {
output() << pkcs8.as_pem();
}
}
}
Expand Down Expand Up @@ -222,7 +221,7 @@ class PK_Sign final : public Command {
if(passphrase.empty()) {
updated_key << Botan::PKCS8::PEM_encode(*key);
} else {
updated_key << Botan::PKCS8::PEM_encode(*key, rng(), passphrase);
updated_key << Botan::PKCS8::encrypt_private_key(*key, passphrase, rng()).as_pem();
}
}

Expand Down Expand Up @@ -316,29 +315,30 @@ class PKCS8_Tool final : public Command {
} else {
const std::string pass_out = get_passphrase_arg("Passphrase to encrypt key", "pass-out");

if(der_out) {
if(pass_out.empty()) {
if(pass_out.empty()) {
if(der_out) {
write_output(Botan::PKCS8::BER_encode(*key));
} else {
if(get_arg("pbkdf-iter").empty()) {
write_output(Botan::PKCS8::BER_encode_encrypted_pbkdf_msec(
*key, rng(), pass_out, pbkdf_ms, nullptr, get_arg("cipher"), get_arg("pbkdf")));
} else {
write_output(Botan::PKCS8::BER_encode_encrypted_pbkdf_iter(
*key, rng(), pass_out, get_arg_sz("pbkdf-iter"), get_arg("cipher"), get_arg("pbkdf")));
}
output() << Botan::PKCS8::PEM_encode(*key);
}
} else {
if(pass_out.empty()) {
output() << Botan::PKCS8::PEM_encode(*key);
} else {
auto options = [&]() {
std::string cipher = get_arg("cipher");
std::string pwhash = get_arg("pbkdf");
if(get_arg("pbkdf-iter").empty()) {
output() << Botan::PKCS8::PEM_encode_encrypted_pbkdf_msec(
*key, rng(), pass_out, pbkdf_ms, nullptr, get_arg("cipher"), get_arg("pbkdf"));
const std::chrono::milliseconds pwhash_ms(get_arg_sz("pbkdf-ms"));
return Botan::PKCS8::KeyEncryptionOptions(cipher, pwhash, pwhash_ms);
} else {
output() << Botan::PKCS8::PEM_encode_encrypted_pbkdf_iter(
*key, rng(), pass_out, get_arg_sz("pbkdf-iter"), get_arg("cipher"), get_arg("pbkdf"));
return Botan::PKCS8::KeyEncryptionOptions(cipher, pwhash, get_arg_sz("pbkdf-iter"));
}
}();

auto pkcs8 = Botan::PKCS8::encrypt_private_key(*key, pass_out, rng(), options);

if(der_out) {
write_output(pkcs8.as_bytes());
} else {
output() << pkcs8.as_pem();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/cli/x509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void update_stateful_private_key(const Botan::Private_Key& key,
if(pass.empty()) {
updated_key << Botan::PKCS8::PEM_encode(key);
} else {
updated_key << Botan::PKCS8::PEM_encode(key, rng, pass);
updated_key << Botan::PKCS8::encrypt_private_key(key, pass, rng).as_pem();
}
}

Expand Down
36 changes: 16 additions & 20 deletions src/lib/ffi/ffi_pkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,16 +233,14 @@ int botan_privkey_view_encrypted_der_timed(botan_privkey_t key,
}

return BOTAN_FFI_VISIT(key, [=](const auto& k) {
const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

const std::string cipher = (maybe_cipher ? maybe_cipher : "");
const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

auto pkcs8 =
Botan::PKCS8::BER_encode_encrypted_pbkdf_msec(k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);

return invoke_view_callback(view, ctx, pkcs8);
auto options = Botan::PKCS8::KeyEncryptionOptions(cipher, pbkdf_algo, pbkdf_time);
auto pkcs8 = Botan::PKCS8::encrypt_private_key(k, passphrase, rng, options);
return invoke_view_callback(view, ctx, pkcs8.as_bytes());
});
}

Expand All @@ -259,16 +257,14 @@ int botan_privkey_view_encrypted_pem_timed(botan_privkey_t key,
}

return BOTAN_FFI_VISIT(key, [=](const auto& k) {
const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

const std::string cipher = (maybe_cipher ? maybe_cipher : "");
const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
const std::chrono::milliseconds pbkdf_time(pbkdf_runtime_msec);
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);

auto pkcs8 =
Botan::PKCS8::PEM_encode_encrypted_pbkdf_msec(k, rng, passphrase, pbkdf_time, nullptr, cipher, pbkdf_algo);

return invoke_view_callback(view, ctx, pkcs8);
auto options = Botan::PKCS8::KeyEncryptionOptions(cipher, pbkdf_algo, pbkdf_time);
auto pkcs8 = Botan::PKCS8::encrypt_private_key(k, passphrase, rng, options);
return invoke_view_callback(view, ctx, pkcs8.as_pem());
});
}

Expand Down Expand Up @@ -311,9 +307,9 @@ int botan_privkey_view_encrypted_der(botan_privkey_t key,
const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);

auto pkcs8 = Botan::PKCS8::BER_encode_encrypted_pbkdf_iter(k, rng, passphrase, pbkdf_iter, cipher, pbkdf_algo);

return invoke_view_callback(view, ctx, pkcs8);
auto options = Botan::PKCS8::KeyEncryptionOptions(cipher, pbkdf_algo, pbkdf_iter);
auto pkcs8 = Botan::PKCS8::encrypt_private_key(k, passphrase, rng, options);
return invoke_view_callback(view, ctx, pkcs8.as_bytes());
});
}

Expand All @@ -336,9 +332,9 @@ int botan_privkey_view_encrypted_pem(botan_privkey_t key,
const std::string pbkdf_algo = (maybe_pbkdf_algo ? maybe_pbkdf_algo : "");
const size_t pbkdf_iter = (maybe_pbkdf_iterations ? maybe_pbkdf_iterations : 100000);

auto pkcs8 = Botan::PKCS8::PEM_encode_encrypted_pbkdf_iter(k, rng, passphrase, pbkdf_iter, cipher, pbkdf_algo);

return invoke_view_callback(view, ctx, pkcs8);
auto options = Botan::PKCS8::KeyEncryptionOptions(cipher, pbkdf_algo, pbkdf_iter);
auto pkcs8 = Botan::PKCS8::encrypt_private_key(k, passphrase, rng, options);
return invoke_view_callback(view, ctx, pkcs8.as_pem());
});
}

Expand Down
Loading

0 comments on commit 212e628

Please sign in to comment.