Skip to content

Commit

Permalink
Add old ciphers check on library level
Browse files Browse the repository at this point in the history
  • Loading branch information
desvxx committed Sep 17, 2024
1 parent a2c0e25 commit 4c9fee3
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/lib/rnp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2714,13 +2714,43 @@ try {
}
FFI_GUARD

static bool
rnp_check_old_ciphers(rnp_ffi_t ffi, const char *cipher)
{
uint32_t security_level = 0;

if (rnp_get_security_rule(ffi,
RNP_FEATURE_SYMM_ALG,
cipher,
ffi->context.time(),
NULL,
NULL,
&security_level)) {
FFI_LOG(ffi, "Failed to get security rules for cipher algorithm \'%s\'!",
cipher);
return false;
}

if (security_level < RNP_SECURITY_DEFAULT) {
FFI_LOG(ffi, "Cipher algorithm \'%s\' is cryptographically weak!",
cipher);
return false;
}
/* TODO: check other weak algorithms and key sizes */
return true;
}

rnp_result_t
rnp_op_encrypt_set_cipher(rnp_op_encrypt_t op, const char *cipher)
try {
// checks
if (!op || !cipher) {
return RNP_ERROR_NULL_POINTER;
}
if (!rnp_check_old_ciphers(op->ffi, cipher)) {
FFI_LOG(op->ffi, "Deprecated cipher: %s", cipher);
return RNP_ERROR_BAD_PARAMETERS;
}
if (!str_to_cipher(cipher, &op->rnpctx.ealg)) {
FFI_LOG(op->ffi, "Invalid cipher: %s", cipher);
return RNP_ERROR_BAD_PARAMETERS;
Expand Down
120 changes: 120 additions & 0 deletions src/tests/ffi-enc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,126 @@ TEST_F(rnp_tests, test_ffi_encrypt_pk)
rnp_ffi_destroy(ffi);
}

TEST_F(rnp_tests, test_ffi_select_deprecated_ciphers)
{
rnp_ffi_t ffi = NULL;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
rnp_op_encrypt_t op = NULL;
const char * plaintext = "data1";

// setup FFI
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));

assert_rnp_success(
rnp_input_from_memory(&input, (const uint8_t *) plaintext, strlen(plaintext), false));
assert_rnp_success(rnp_output_to_path(&output, "encrypted"));
// create encrypt operation
assert_rnp_success(rnp_op_encrypt_create(&op, ffi, input, output));

/* check predefined rules */
uint32_t flags = 0;
uint64_t from = 0;
uint32_t level = 0;
assert_rnp_success(rnp_get_security_rule(
ffi, RNP_FEATURE_SYMM_ALG, "CAST5", CAST5_3DES_IDEA_BLOWFISH_FROM + 1, &flags, &from, &level));
assert_int_equal(from, CAST5_3DES_IDEA_BLOWFISH_FROM);
assert_int_equal(level, RNP_SECURITY_INSECURE);

ffi->context.set_time(CAST5_3DES_IDEA_BLOWFISH_FROM + 1);
// set the data encryption cipher
if (cast5_enabled()) {
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "CAST5"));
}
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "TRIPLEDES"));
if (idea_enabled()) {
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "IDEA"));
}
if (blowfish_enabled()) {
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "BLOWFISH"));
}

ffi->context.set_time(CAST5_3DES_IDEA_BLOWFISH_FROM - 1);

if (cast5_enabled()) {
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "CAST5"));
}
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "TRIPLEDES"));
if (idea_enabled()) {
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "IDEA"));
}
if (blowfish_enabled()) {
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "BLOWFISH"));
}

// cleanup
assert_rnp_success(rnp_op_encrypt_destroy(op));
op = NULL;
rnp_ffi_destroy(ffi);

// check again but with removing rules now
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
// create encrypt operation
assert_rnp_success(rnp_op_encrypt_create(&op, ffi, input, output));

ffi->context.set_time(CAST5_3DES_IDEA_BLOWFISH_FROM + 1);
// set the data encryption cipher
if (cast5_enabled()) {
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "CAST5"));
}
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "TRIPLEDES"));
if (idea_enabled()) {
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "IDEA"));
}
if (blowfish_enabled()) {
assert_rnp_failure(rnp_op_encrypt_set_cipher(op, "BLOWFISH"));
}

size_t removed = 0;
if (cast5_enabled()) {
removed = 0;
assert_rnp_success(rnp_remove_security_rule(
ffi, RNP_FEATURE_SYMM_ALG, "CAST5", 0, RNP_SECURITY_REMOVE_ALL, 0, &removed));
assert_int_equal(removed, 1);
}
removed = 0;
assert_rnp_success(
rnp_remove_security_rule(ffi, RNP_FEATURE_SYMM_ALG, "TRIPLEDES", 0, RNP_SECURITY_REMOVE_ALL, 0, &removed));
assert_int_equal(removed, 1);
if (idea_enabled()) {
removed = 0;
assert_rnp_success(rnp_remove_security_rule(
ffi, RNP_FEATURE_SYMM_ALG, "IDEA", 0, RNP_SECURITY_REMOVE_ALL, 0, &removed));
assert_int_equal(removed, 1);
}
if (blowfish_enabled()) {
removed = 0;
assert_rnp_success(rnp_remove_security_rule(
ffi, RNP_FEATURE_SYMM_ALG, "BLOWFISH", 0, RNP_SECURITY_REMOVE_ALL, 0, &removed));
assert_int_equal(removed, 1);
}

if (cast5_enabled()) {
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "CAST5"));
}
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "TRIPLEDES"));
if (idea_enabled()) {
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "IDEA"));
}
if (blowfish_enabled()) {
assert_rnp_success(rnp_op_encrypt_set_cipher(op, "BLOWFISH"));
}

// cleanup
assert_rnp_success(rnp_input_destroy(input));
input = NULL;
assert_rnp_success(rnp_output_destroy(output));
output = NULL;
assert_rnp_success(rnp_op_encrypt_destroy(op));
op = NULL;
rnp_ffi_destroy(ffi);
}

static bool
first_key_password_provider(rnp_ffi_t ffi,
void * app_ctx,
Expand Down
1 change: 1 addition & 0 deletions src/tests/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,5 +313,6 @@ bool test_load_gpg_check_key(rnp::KeyStore *pub, rnp::KeyStore *sec, const char
#define MD5_FROM 1325376000
#define SHA1_DATA_FROM 1547856000
#define SHA1_KEY_FROM 1705629600
#define CAST5_3DES_IDEA_BLOWFISH_FROM 1727730000 // TODO: tbd

#endif /* SUPPORT_H_ */

0 comments on commit 4c9fee3

Please sign in to comment.