diff --git a/src/lib/rnp.cpp b/src/lib/rnp.cpp index 6a8d6223ce..8958b4cb97 100644 --- a/src/lib/rnp.cpp +++ b/src/lib/rnp.cpp @@ -1770,6 +1770,12 @@ try { if (expub && !ffi->secring->import_key(*expub, true)) { return RNP_ERROR_BAD_PARAMETERS; } + } else if (pub_status != PGP_KEY_IMPORT_STATUS_UNCHANGED) { + // public key was new or updated: sync into secring if a secret key exists there + auto *expub = ffi->pubring->get_key(key.fp()); + if (expub && ffi->secring->get_key(key.fp())) { + ffi->secring->import_key(*expub, true); + } } // now add key fingerprint to json based on statuses rnp_result_t tmpret = add_key_status(jsokeys, &key, pub_status, sec_status); diff --git a/src/tests/data/test_key_edge_cases/renee-new-expiration-pub.asc b/src/tests/data/test_key_edge_cases/renee-new-expiration-pub.asc new file mode 100644 index 0000000000..6591d57671 --- /dev/null +++ b/src/tests/data/test_key_edge_cases/renee-new-expiration-pub.asc @@ -0,0 +1,35 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +e6BWSTQ5PkHs8LoRjCZoKJ+PlAc= +=rs4Z +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/tests/data/test_key_edge_cases/renee-old-expiration-sec.asc b/src/tests/data/test_key_edge_cases/renee-old-expiration-sec.asc new file mode 100644 index 0000000000..86102fc3d9 --- /dev/null +++ b/src/tests/data/test_key_edge_cases/renee-old-expiration-sec.asc @@ -0,0 +1,69 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 ++rDPgPDDbw+EwLzBIY1Lxe4s/qtZBlBh +=hmU2 +-----END PGP PRIVATE KEY BLOCK----- diff --git a/src/tests/ffi-key.cpp b/src/tests/ffi-key.cpp index 9010999cdc..06355534a9 100644 --- a/src/tests/ffi-key.cpp +++ b/src/tests/ffi-key.cpp @@ -3736,6 +3736,67 @@ TEST_F(rnp_tests, test_ffi_key_import_edge_cases) rnp_ffi_destroy(ffi); } +TEST_F(rnp_tests, test_ffi_sec_key_expiry_update_via_pub_import) +{ + /* Regression test for https://github.com/rnpgp/rnp/issues/2383: + * importing an updated public key (with extended expiration) must also update the + * expiration stored in the secret keyring so that signing succeeds. */ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + + /* import secret key with short (already-expired) expiration */ + assert_true(import_sec_keys(ffi, "data/test_key_edge_cases/renee-old-expiration-sec.asc")); + + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "89dbb82dc8c6e5ef", &key)); + assert_non_null(key); + bool expired = false; + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_true(expired); + rnp_key_handle_destroy(key); + + /* adding expired key as signer must fail with no suitable key */ + rnp_input_t input = NULL; + rnp_output_t output = NULL; + assert_rnp_success(rnp_input_from_memory(&input, (const uint8_t *) "payload", 7, false)); + assert_rnp_success(rnp_output_to_null(&output)); + rnp_op_sign_t op = NULL; + assert_rnp_success(rnp_op_sign_create(&op, ffi, input, output)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "89dbb82dc8c6e5ef", &key)); + assert_int_equal(rnp_op_sign_add_signature(op, key, NULL), RNP_ERROR_NO_SUITABLE_KEY); + rnp_key_handle_destroy(key); + rnp_op_sign_destroy(op); + rnp_input_destroy(input); + rnp_output_destroy(output); + + /* import updated public key with extended expiration */ + assert_true(import_pub_keys(ffi, "data/test_key_edge_cases/renee-new-expiration-pub.asc")); + + assert_rnp_success(rnp_locate_key(ffi, "keyid", "89dbb82dc8c6e5ef", &key)); + assert_non_null(key); + expired = true; + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_false(expired); + bool valid = false; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + rnp_key_handle_destroy(key); + + /* signing must now succeed */ + assert_rnp_success(rnp_input_from_memory(&input, (const uint8_t *) "payload", 7, false)); + assert_rnp_success(rnp_output_to_null(&output)); + assert_rnp_success(rnp_op_sign_create(&op, ffi, input, output)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "89dbb82dc8c6e5ef", &key)); + assert_rnp_success(rnp_op_sign_add_signature(op, key, NULL)); + rnp_key_handle_destroy(key); + assert_rnp_success(rnp_op_sign_execute(op)); + rnp_op_sign_destroy(op); + rnp_input_destroy(input); + rnp_output_destroy(output); + + rnp_ffi_destroy(ffi); +} + TEST_F(rnp_tests, test_ffi_key_import_gpg_s2k) { rnp_ffi_t ffi = NULL;