diff options
Diffstat (limited to 'src/tests/ffi-key-prop.cpp')
-rw-r--r-- | src/tests/ffi-key-prop.cpp | 1406 |
1 files changed, 1406 insertions, 0 deletions
diff --git a/src/tests/ffi-key-prop.cpp b/src/tests/ffi-key-prop.cpp new file mode 100644 index 0000000..95185cf --- /dev/null +++ b/src/tests/ffi-key-prop.cpp @@ -0,0 +1,1406 @@ +/* + * Copyright (c) 2021 [Ribose Inc](https://www.ribose.com). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sstream> +#include <rnp/rnp.h> +#include "rnp_tests.h" +#include "support.h" +#include <librepgp/stream-ctx.h> +#include "pgp-key.h" +#include "ffi-priv-types.h" + +TEST_F(rnp_tests, test_ffi_key_set_expiry_multiple_uids) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + + /* load key with 3 uids with zero key expiration */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-3-uids.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + size_t count = 0; + assert_rnp_success(rnp_key_get_uid_count(key, &count)); + assert_int_equal(count, 3); + uint32_t expiry = 10; + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + bool expired = true; + assert_rnp_failure(rnp_key_is_expired(key, NULL)); + assert_rnp_failure(rnp_key_is_expired(NULL, &expired)); + rnp_key_handle_t bkey = bogus_key_handle(ffi); + assert_non_null(bkey); + assert_rnp_failure(rnp_key_is_expired(bkey, &expired)); + rnp_key_handle_destroy(bkey); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_false(expired); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + assert_true(check_uid_primary(key, 0, false)); + assert_true(check_uid_primary(key, 1, false)); + assert_true(check_uid_primary(key, 2, false)); + /* set expiration time to minimum value so key is expired now, but uids are still valid */ + assert_rnp_success(rnp_key_set_expiration(key, 1)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 1); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_true(expired); + bool valid = true; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_false(valid); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + /* reload */ + rnp_key_handle_destroy(key); + reload_keyrings(&ffi); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 1); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_true(expired); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + /* set expiration to maximum value */ + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + assert_rnp_success(rnp_key_set_expiration(key, 0xFFFFFFFF)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0xFFFFFFFF); + valid = false; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_false(expired); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + rnp_key_handle_destroy(key); + /* reload and make sure changes are saved */ + reload_keyrings(&ffi); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Caesar <caesar@rnp>", &key)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0xFFFFFFFF); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + rnp_key_handle_destroy(key); + + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + /* load key with 3 uids, including primary, with key expiration */ + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/alice-3-uids-primary-expiring.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + expiry = 0; + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 674700647); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_false(expired); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + assert_true(check_uid_primary(key, 0, true)); + assert_true(check_uid_primary(key, 1, false)); + assert_true(check_uid_primary(key, 2, false)); + assert_rnp_success(rnp_key_unlock(key, "password")); + assert_rnp_success(rnp_key_set_expiration(key, 0)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_false(expired); + valid = false; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + rnp_key_handle_destroy(key); + /* reload and make sure it is saved */ + reload_keyrings(&ffi); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Caesar <caesar@rnp>", &key)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_valid(key, 1, true)); + assert_true(check_uid_valid(key, 2, true)); + assert_true(check_uid_primary(key, 0, true)); + rnp_key_handle_destroy(key); + + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_primary_uid_conflict) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + + /* load key with 1 uid and two certifications: first marks uid primary, but expires key + * second marks uid as non-primary, but has zero key expiration */ + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/key-primary-uid-conflict-pub.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "userid_2_sigs", &key)); + assert_int_equal(get_key_uids(key), 1); + assert_int_equal(get_key_expiry(key), 0); + assert_true(check_key_valid(key, true)); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_primary(key, 0, false)); + rnp_key_handle_destroy(key); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_expired_certification_and_direct_sig) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + + /* load key with 2 uids and direct-key signature: + * - direct-key sig has 0 key expiration time but expires in 30 seconds + * - first uid is not primary, but key expiration is 60 seconds + * - second uid is marked as primary, doesn't expire key, but certification expires in 60 + * seconds */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-expired-cert-direct.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "primary-uid-expired-cert", &key)); + assert_null(key); + assert_rnp_success(rnp_locate_key(ffi, "userid", "expired-certifications", &key)); + assert_non_null(key); + assert_int_equal(get_key_uids(key), 2); + assert_int_equal(get_key_expiry(key), 60); + rnp_signature_handle_t sig = NULL; + assert_rnp_success(rnp_key_get_signature_at(key, 0, &sig)); + assert_non_null(sig); + assert_int_equal(rnp_signature_is_valid(sig, 0), RNP_ERROR_SIGNATURE_EXPIRED); + rnp_signature_handle_destroy(sig); + assert_true(check_key_valid(key, false)); + assert_true(check_uid_valid(key, 0, true)); + assert_true(check_uid_primary(key, 0, false)); + assert_true(check_uid_valid(key, 1, false)); + assert_true(check_uid_primary(key, 1, false)); + rnp_key_handle_destroy(key); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_25519_tweaked_bits) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + /* try public key */ + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/key-25519-non-tweaked.asc")); + rnp_key_handle_t sub = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + bool tweaked = true; + assert_rnp_failure(rnp_key_25519_bits_tweaked(NULL, &tweaked)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, NULL)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_rnp_failure(rnp_key_25519_bits_tweak(NULL)); + assert_rnp_failure(rnp_key_25519_bits_tweak(sub)); + rnp_key_handle_destroy(sub); + /* load secret key */ + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/key-25519-non-tweaked-sec.asc")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(NULL, &tweaked)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, NULL)); + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_false(tweaked); + /* protect key and try again */ + assert_rnp_success(rnp_key_protect(sub, "password", NULL, NULL, NULL, 100000)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_rnp_success(rnp_key_unlock(sub, "password")); + tweaked = true; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_false(tweaked); + assert_rnp_success(rnp_key_lock(sub)); + assert_rnp_failure(rnp_key_25519_bits_tweaked(sub, &tweaked)); + /* now let's tweak it */ + assert_rnp_failure(rnp_key_25519_bits_tweak(NULL)); + assert_rnp_failure(rnp_key_25519_bits_tweak(sub)); + assert_rnp_success(rnp_key_unlock(sub, "password")); + assert_rnp_failure(rnp_key_25519_bits_tweak(sub)); + assert_rnp_success(rnp_key_unprotect(sub, "password")); + assert_rnp_success(rnp_key_25519_bits_tweak(sub)); + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + /* export unprotected key */ + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "3176FC1486AA2528", &key)); + auto clearsecdata = export_key(key, true, true); + rnp_key_handle_destroy(key); + assert_rnp_success(rnp_key_protect(sub, "password", NULL, NULL, NULL, 100000)); + rnp_key_handle_destroy(sub); + /* make sure it is exported and saved tweaked and protected */ + assert_rnp_success(rnp_locate_key(ffi, "keyid", "3176FC1486AA2528", &key)); + auto secdata = export_key(key, true, true); + rnp_key_handle_destroy(key); + reload_keyrings(&ffi); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + bool prot = false; + assert_rnp_success(rnp_key_is_protected(sub, &prot)); + assert_true(prot); + assert_rnp_success(rnp_key_unlock(sub, "password")); + tweaked = false; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + rnp_key_handle_destroy(sub); + rnp_ffi_destroy(ffi); + /* import cleartext exported key */ + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_all_keys(ffi, clearsecdata.data(), clearsecdata.size())); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + prot = true; + assert_rnp_success(rnp_key_is_protected(sub, &prot)); + assert_false(prot); + tweaked = false; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + rnp_key_handle_destroy(sub); + rnp_ffi_destroy(ffi); + /* import exported key */ + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_all_keys(ffi, secdata.data(), secdata.size())); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "950EE0CD34613DBA", &sub)); + prot = false; + assert_rnp_success(rnp_key_is_protected(sub, &prot)); + assert_true(prot); + assert_rnp_success(rnp_key_unlock(sub, "password")); + tweaked = false; + assert_rnp_success(rnp_key_25519_bits_tweaked(sub, &tweaked)); + assert_true(tweaked); + rnp_key_handle_destroy(sub); + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_revoke) +{ + rnp_ffi_t ffi = NULL; + + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sub-pub.pgp")); + rnp_key_handle_t key_handle = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key_handle)); + /* check for failure with wrong parameters */ + assert_rnp_failure(rnp_key_revoke(NULL, 0, "SHA256", "superseded", "test key revocation")); + assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", NULL, NULL)); + assert_rnp_failure(rnp_key_revoke(key_handle, 0x17, "SHA256", NULL, NULL)); + assert_rnp_failure(rnp_key_revoke(key_handle, 0, "Wrong hash", NULL, NULL)); + assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", "Wrong reason code", NULL)); + /* attempt to revoke key without the secret */ + assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", "retired", "Custom reason")); + assert_rnp_success(rnp_key_handle_destroy(key_handle)); + /* attempt to revoke subkey without the secret */ + rnp_key_handle_t sub_handle = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle)); + assert_rnp_failure(rnp_key_revoke(sub_handle, 0, "SHA256", "retired", "Custom reason")); + assert_rnp_success(rnp_key_handle_destroy(sub_handle)); + /* load secret key */ + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sub-sec.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key_handle)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle)); + /* wrong password - must fail */ + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "wrong")); + assert_rnp_failure(rnp_key_revoke(key_handle, 0, "SHA256", "superseded", NULL)); + assert_rnp_failure(rnp_key_revoke(sub_handle, 0, "SHA256", "superseded", NULL)); + /* unlocked key - must succeed */ + bool revoked = false; + assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked)); + assert_false(revoked); + assert_rnp_success(rnp_key_unlock(key_handle, "password")); + assert_rnp_success(rnp_key_revoke(key_handle, 0, "SHA256", NULL, NULL)); + assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked)); + assert_true(revoked); + /* subkey */ + assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked)); + assert_false(revoked); + bool locked = true; + assert_rnp_success(rnp_key_is_locked(key_handle, &locked)); + assert_false(locked); + assert_rnp_success(rnp_key_revoke(sub_handle, 0, "SHA256", NULL, "subkey revoked")); + assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked)); + assert_true(revoked); + assert_rnp_success(rnp_key_lock(key_handle)); + assert_rnp_success(rnp_key_handle_destroy(key_handle)); + assert_rnp_success(rnp_key_handle_destroy(sub_handle)); + /* correct password provider - must succeed */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_SECRET | RNP_KEY_UNLOAD_PUBLIC)); + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sub-sec.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key_handle)); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked)); + assert_false(revoked); + assert_rnp_success( + rnp_key_revoke(key_handle, 0, "SHA256", "superseded", "test key revocation")); + assert_rnp_success(rnp_key_is_revoked(key_handle, &revoked)); + assert_true(revoked); + /* make sure FFI locks key back */ + assert_rnp_success(rnp_key_is_locked(key_handle, &locked)); + assert_true(locked); + assert_rnp_success(rnp_key_handle_destroy(key_handle)); + /* repeat for subkey */ + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub_handle)); + assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked)); + assert_false(revoked); + assert_rnp_success(rnp_key_revoke(sub_handle, 0, "SHA256", "no", "test sub revocation")); + assert_rnp_success(rnp_key_is_revoked(sub_handle, &revoked)); + assert_true(revoked); + assert_rnp_success(rnp_key_handle_destroy(sub_handle)); + assert_rnp_success(rnp_ffi_destroy(ffi)); +} + +TEST_F(rnp_tests, test_ffi_key_set_expiry) +{ + rnp_ffi_t ffi = NULL; + rnp_input_t input = NULL; + + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sub-pub.pgp")); + + /* check edge cases */ + assert_rnp_failure(rnp_key_set_expiration(NULL, 0)); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + /* cannot set key expiration with public key only */ + assert_rnp_failure(rnp_key_set_expiration(key, 1000)); + rnp_key_handle_t sub = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_failure(rnp_key_set_expiration(sub, 1000)); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* load secret key */ + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sub-sec.pgp")); + uint32_t expiry = 0; + const uint32_t new_expiry = 10 * 365 * 24 * 60 * 60; + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + expiry = 255; + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + assert_rnp_success(rnp_key_set_expiration(key, 0)); + /* will fail on locked key */ + assert_rnp_failure(rnp_key_set_expiration(key, new_expiry)); + assert_rnp_success(rnp_key_unlock(key, "password")); + assert_rnp_success(rnp_key_set_expiration(key, new_expiry)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, new_expiry); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + /* will succeed on locked subkey since it is not signing one */ + assert_rnp_success(rnp_key_set_expiration(sub, 0)); + assert_rnp_success(rnp_key_set_expiration(sub, new_expiry * 2)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, new_expiry * 2); + /* make sure new expiration times are properly saved */ + rnp_output_t keymem = NULL; + rnp_output_t seckeymem = NULL; + assert_rnp_success(rnp_output_to_memory(&keymem, 0)); + assert_rnp_success( + rnp_key_export(key, keymem, RNP_KEY_EXPORT_PUBLIC | RNP_KEY_EXPORT_SUBKEYS)); + assert_rnp_success(rnp_output_to_memory(&seckeymem, 0)); + assert_rnp_success( + rnp_key_export(key, seckeymem, RNP_KEY_EXPORT_SECRET | RNP_KEY_EXPORT_SUBKEYS)); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + uint8_t *keybuf = NULL; + size_t keylen = 0; + assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false)); + /* load public key */ + assert_true(import_pub_keys(ffi, keybuf, keylen)); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, new_expiry); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, new_expiry * 2); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + /* now load exported secret key */ + assert_rnp_success(rnp_output_memory_get_buf(seckeymem, &keybuf, &keylen, false)); + assert_true(import_sec_keys(ffi, keybuf, keylen)); + assert_rnp_success(rnp_output_destroy(seckeymem)); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, new_expiry); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, new_expiry * 2); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + /* now unset expiration time back, first loading the public key back */ + assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false)); + assert_true(import_pub_keys(ffi, keybuf, keylen)); + assert_rnp_success(rnp_output_destroy(keymem)); + /* set primary key expiration */ + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_key_unlock(key, "password")); + assert_rnp_success(rnp_key_set_expiration(key, 0)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_set_expiration(sub, 0)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 0); + /* let's export them and reload */ + assert_rnp_success(rnp_output_to_memory(&keymem, 0)); + assert_rnp_success( + rnp_key_export(key, keymem, RNP_KEY_EXPORT_PUBLIC | RNP_KEY_EXPORT_SUBKEYS)); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false)); + assert_true(import_pub_keys(ffi, keybuf, keylen)); + assert_rnp_success(rnp_output_destroy(keymem)); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + bool expired = true; + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_false(expired); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 0); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* now try the sign-able subkey */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sign-sub-pub.pgp")); + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sign-sub-sec.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 0); + assert_rnp_failure(rnp_key_set_expiration(sub, new_expiry)); + /* now unlock only primary key - should fail */ + assert_rnp_success(rnp_key_unlock(key, "password")); + assert_rnp_failure(rnp_key_set_expiration(sub, new_expiry)); + /* unlock subkey */ + assert_rnp_success(rnp_key_unlock(sub, "password")); + assert_rnp_success(rnp_key_set_expiration(sub, new_expiry)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, new_expiry); + assert_rnp_success(rnp_output_to_memory(&keymem, 0)); + assert_rnp_success( + rnp_key_export(key, keymem, RNP_KEY_EXPORT_PUBLIC | RNP_KEY_EXPORT_SUBKEYS)); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_rnp_success(rnp_output_memory_get_buf(keymem, &keybuf, &keylen, false)); + assert_true(import_pub_keys(ffi, keybuf, keylen)); + assert_rnp_success(rnp_output_destroy(keymem)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, new_expiry); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* check whether we can change expiration for already expired key */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sign-sub-pub.pgp")); + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sign-sub-sec.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); + assert_rnp_success(rnp_key_unlock(key, "password")); + assert_rnp_success(rnp_key_unlock(sub, "password")); + assert_rnp_success(rnp_key_set_expiration(key, 1)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 1); + assert_rnp_success(rnp_key_is_expired(key, &expired)); + assert_true(expired); + + /* key is invalid since it is expired */ + assert_false(key->pub->valid()); + bool valid = true; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_false(valid); + uint32_t till = 0; + assert_rnp_success(rnp_key_valid_till(key, &till)); + assert_int_equal(till, 1577369391 + 1); + uint64_t till64 = 0; + assert_rnp_success(rnp_key_valid_till64(key, &till64)); + assert_int_equal(till64, 1577369391 + 1); + assert_rnp_success(rnp_key_set_expiration(sub, 1)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 1); + assert_false(sub->pub->valid()); + valid = true; + assert_rnp_success(rnp_key_is_valid(sub, &valid)); + assert_false(valid); + till = 1; + assert_rnp_success(rnp_key_valid_till(sub, &till)); + assert_int_equal(till, 1577369391 + 1); + assert_rnp_success(rnp_key_valid_till64(sub, &till64)); + assert_int_equal(till64, 1577369391 + 1); + assert_rnp_success(rnp_key_set_expiration(key, 0)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + assert_true(key->pub->valid()); + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_valid_till(key, &till)); + assert_int_equal(till, 0xffffffff); + assert_rnp_success(rnp_key_valid_till64(key, &till64)); + assert_int_equal(till64, UINT64_MAX); + assert_rnp_success(rnp_key_set_expiration(sub, 0)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 0); + assert_true(sub->pub->valid()); + valid = false; + assert_rnp_success(rnp_key_is_valid(sub, &valid)); + assert_true(valid); + till = 0; + assert_rnp_success(rnp_key_valid_till(sub, &till)); + assert_int_equal(till, 0xffffffff); + till64 = 0; + assert_rnp_success(rnp_key_valid_till64(sub, &till64)); + assert_int_equal(till64, UINT64_MAX); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* check whether we can change expiration with password provider/locked key */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sign-sub-pub.pgp")); + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sign-sub-sec.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); + + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "wrong")); + assert_rnp_failure(rnp_key_set_expiration(key, 1)); + expiry = 255; + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, 0); + assert_rnp_failure(rnp_key_set_expiration(sub, 1)); + expiry = 255; + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 0); + + bool locked = true; + assert_rnp_success(rnp_key_is_locked(key, &locked)); + assert_true(locked); + locked = false; + assert_rnp_success(rnp_key_is_locked(sub, &locked)); + assert_true(locked); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + uint32_t creation = 0; + assert_rnp_success(rnp_key_get_creation(key, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(key, creation + 8)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, creation + 8); + locked = false; + assert_rnp_success(rnp_key_is_locked(key, &locked)); + assert_true(locked); + assert_rnp_success(rnp_key_get_creation(sub, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(sub, creation + 3)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, creation + 3); + locked = false; + assert_rnp_success(rnp_key_is_locked(sub, &locked)); + assert_true(locked); + locked = false; + assert_rnp_success(rnp_key_is_locked(key, &locked)); + assert_true(locked); + + /* now change just subkey's expiration - should also work */ + valid = false; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_set_expiration(sub, 4)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, 4); + assert_rnp_success(rnp_key_is_expired(sub, &expired)); + assert_true(expired); + locked = false; + assert_rnp_success(rnp_key_is_locked(sub, &locked)); + assert_true(locked); + locked = false; + assert_rnp_success(rnp_key_is_locked(key, &locked)); + assert_true(locked); + + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* now try to update already expired key and subkey */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sign-sub-exp-pub.asc")); + assert_true(import_sec_keys(ffi, "data/test_key_validity/alice-sign-sub-exp-sec.asc")); + /* Alice key is searchable by userid since self-sig is not expired, and it just marks key + * as expired */ + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + assert_non_null(key); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); + assert_rnp_success(rnp_key_is_valid(key, &valid)); + /* key is not valid since expired */ + assert_false(valid); + assert_rnp_success(rnp_key_valid_till(key, &till)); + assert_int_equal(till, 1577369391 + 16324055); + assert_rnp_success(rnp_key_valid_till64(key, &till64)); + assert_int_equal(till64, 1577369391 + 16324055); + assert_false(key->pub->valid()); + /* secret key part is also not valid till new sig is added */ + assert_false(key->sec->valid()); + assert_rnp_success(rnp_key_is_valid(sub, &valid)); + assert_false(valid); + assert_rnp_success(rnp_key_valid_till(sub, &till)); + /* subkey valid no longer then the primary key */ + assert_int_equal(till, 1577369391 + 16324055); + assert_rnp_success(rnp_key_valid_till64(sub, &till64)); + assert_int_equal(till64, 1577369391 + 16324055); + assert_false(sub->pub->valid()); + assert_false(sub->sec->valid()); + creation = 0; + uint32_t validity = 2 * 30 * 24 * 60 * 60; // 2 monthes + assert_rnp_success(rnp_key_get_creation(key, &creation)); + uint32_t keytill = creation + validity; + creation = time(NULL) - creation; + keytill += creation; + assert_rnp_success(rnp_key_set_expiration(key, creation + validity)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, creation + validity); + assert_rnp_success(rnp_key_get_creation(sub, &creation)); + /* use smaller validity for the subkey */ + validity = validity / 2; + uint32_t subtill = creation + validity; + creation = time(NULL) - creation; + subtill += creation; + assert_rnp_success(rnp_key_set_expiration(sub, creation + validity)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, creation + validity); + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_valid_till(key, &till)); + assert_int_equal(till, keytill); + assert_rnp_success(rnp_key_valid_till64(key, &till64)); + assert_int_equal(till64, keytill); + assert_true(key->pub->valid()); + assert_true(key->sec->valid()); + assert_rnp_success(rnp_key_is_valid(sub, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_valid_till(sub, &till)); + assert_int_equal(till, subtill); + assert_rnp_success(rnp_key_valid_till64(sub, &till64)); + assert_int_equal(till64, subtill); + assert_true(sub->pub->valid()); + assert_true(sub->sec->valid()); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* update expiration time when only secret key is available */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC)); + assert_rnp_success(rnp_locate_key(ffi, "userid", "Alice <alice@rnp>", &key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "22F3A217C0E439CB", &sub)); + validity = 30 * 24 * 60 * 60; // 1 month + assert_rnp_success(rnp_key_get_creation(key, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(key, creation + validity)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, creation + validity); + assert_rnp_success(rnp_key_get_creation(sub, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(sub, creation + validity)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, creation + validity); + /* public key is not available - bad parameters */ + assert_int_equal(rnp_key_is_valid(key, &valid), RNP_ERROR_BAD_PARAMETERS); + assert_int_equal(rnp_key_valid_till(key, &till), RNP_ERROR_BAD_PARAMETERS); + assert_int_equal(rnp_key_valid_till64(key, &till64), RNP_ERROR_BAD_PARAMETERS); + assert_null(key->pub); + assert_true(key->sec->valid()); + assert_int_equal(rnp_key_is_valid(sub, &valid), RNP_ERROR_BAD_PARAMETERS); + assert_int_equal(rnp_key_valid_till(sub, &till), RNP_ERROR_BAD_PARAMETERS); + assert_int_equal(rnp_key_valid_till64(sub, &till64), RNP_ERROR_BAD_PARAMETERS); + assert_null(sub->pub); + assert_true(sub->sec->valid()); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + assert_rnp_success(rnp_ffi_destroy(ffi)); + + /* check whether things work for G10 keyring */ + assert_rnp_success(rnp_ffi_create(&ffi, "KBX", "G10")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + assert_true(load_keys_kbx_g10( + ffi, "data/keyrings/3/pubring.kbx", "data/keyrings/3/private-keys-v1.d")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "4BE147BB22DF1E60", &key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "A49BAE05C16E8BC8", &sub)); + assert_rnp_success(rnp_key_get_creation(key, &creation)); + keytill = creation + validity; + creation = time(NULL) - creation; + keytill += creation; + assert_rnp_success(rnp_key_set_expiration(key, creation + validity)); + expiry = 255; + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, creation + validity); + size_t key_expiry = expiry; + assert_rnp_success(rnp_key_get_creation(sub, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(sub, creation + validity)); + expiry = 255; + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, creation + validity); + size_t sub_expiry = expiry; + assert_rnp_success(rnp_key_is_valid(key, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_valid_till(key, &till)); + assert_int_equal(till, keytill); + assert_rnp_success(rnp_key_valid_till64(key, &till64)); + assert_int_equal(till64, keytill); + assert_true(key->pub->valid()); + assert_true(key->sec->valid()); + assert_rnp_success(rnp_key_is_valid(sub, &valid)); + assert_true(valid); + assert_rnp_success(rnp_key_valid_till(sub, &till)); + assert_int_equal(till, keytill); + assert_rnp_success(rnp_key_valid_till64(sub, &till64)); + assert_int_equal(till64, keytill); + assert_true(sub->pub->valid()); + assert_true(sub->sec->valid()); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + /* save keyring to KBX and reload it: fails now */ + rnp_output_t output = NULL; + assert_rnp_success(rnp_output_to_path(&output, "pubring.kbx")); + assert_rnp_success(rnp_save_keys(ffi, "KBX", output, RNP_LOAD_SAVE_PUBLIC_KEYS)); + assert_rnp_success(rnp_output_destroy(output)); + assert_rnp_success(rnp_ffi_destroy(ffi)); + assert_rnp_success(rnp_ffi_create(&ffi, "KBX", "G10")); + assert_rnp_success(rnp_input_from_path(&input, "pubring.kbx")); + /* Saving to KBX doesn't work well, or was broken at some point. */ + assert_rnp_failure(rnp_import_keys(ffi, input, RNP_LOAD_SAVE_PUBLIC_KEYS, NULL)); + assert_rnp_success(rnp_input_destroy(input)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "4BE147BB22DF1E60", &key)); + assert_null(key); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "A49BAE05C16E8BC8", &sub)); + assert_null(sub); + expiry = 255; + assert_rnp_failure(rnp_key_get_expiration(key, &expiry)); + assert_int_not_equal(expiry, key_expiry); + expiry = 255; + assert_rnp_failure(rnp_key_get_expiration(sub, &expiry)); + assert_int_not_equal(expiry, sub_expiry); + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + assert_int_equal(rnp_unlink("pubring.kbx"), 0); + assert_rnp_success(rnp_ffi_destroy(ffi)); + + /* load G10/KBX and unload public keys - must succeed */ + assert_rnp_success(rnp_ffi_create(&ffi, "KBX", "G10")); + assert_rnp_success( + rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password")); + assert_true(load_keys_kbx_g10( + ffi, "data/keyrings/3/pubring.kbx", "data/keyrings/3/private-keys-v1.d")); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "4BE147BB22DF1E60", &key)); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "A49BAE05C16E8BC8", &sub)); + assert_rnp_success(rnp_key_get_creation(key, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(key, creation + validity)); + assert_rnp_success(rnp_key_get_expiration(key, &expiry)); + assert_int_equal(expiry, creation + validity); + key_expiry = expiry; + assert_rnp_success(rnp_key_get_creation(sub, &creation)); + creation = time(NULL) - creation; + assert_rnp_success(rnp_key_set_expiration(sub, creation + validity)); + assert_rnp_success(rnp_key_get_expiration(sub, &expiry)); + assert_int_equal(expiry, creation + validity); + sub_expiry = expiry; + assert_rnp_success(rnp_key_handle_destroy(key)); + assert_rnp_success(rnp_key_handle_destroy(sub)); + + // TODO: check expiration date in direct-key signature, check without + // self-signature/binding signature. + + assert_rnp_success(rnp_ffi_destroy(ffi)); +} + +TEST_F(rnp_tests, test_ffi_key_get_protection_info) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + + /* Edge cases - public key, NULL parameters, etc. */ + assert_true(import_pub_keys(ffi, "data/test_key_validity/alice-sub-pub.pgp")); + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + char *type = NULL; + assert_rnp_failure(rnp_key_get_protection_type(key, NULL)); + assert_rnp_failure(rnp_key_get_protection_type(NULL, &type)); + assert_rnp_failure(rnp_key_get_protection_type(key, &type)); + char *mode = NULL; + assert_rnp_failure(rnp_key_get_protection_mode(key, NULL)); + assert_rnp_failure(rnp_key_get_protection_mode(NULL, &mode)); + assert_rnp_failure(rnp_key_get_protection_mode(key, &mode)); + char *cipher = NULL; + assert_rnp_failure(rnp_key_get_protection_cipher(key, NULL)); + assert_rnp_failure(rnp_key_get_protection_cipher(NULL, &cipher)); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + char *hash = NULL; + assert_rnp_failure(rnp_key_get_protection_hash(key, NULL)); + assert_rnp_failure(rnp_key_get_protection_hash(NULL, &hash)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + size_t iterations = 0; + assert_rnp_failure(rnp_key_get_protection_iterations(key, NULL)); + assert_rnp_failure(rnp_key_get_protection_iterations(NULL, &iterations)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + /* Encrypted secret key with subkeys */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC)); + assert_true(import_all_keys(ffi, "data/test_key_validity/alice-sub-sec.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "Encrypted-Hashed"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "CFB"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(key, &cipher)); + assert_string_equal(cipher, "AES128"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(key, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(key, &iterations)); + assert_int_equal(iterations, 22020096); + assert_rnp_success(rnp_key_unprotect(key, "password")); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + rnp_key_handle_t sub = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "Encrypted-Hashed"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "CFB"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(sub, &cipher)); + assert_string_equal(cipher, "AES128"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(sub, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(sub, &iterations)); + assert_int_equal(iterations, 22020096); + assert_rnp_success(rnp_key_unprotect(sub, "password")); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(sub, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(sub, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(sub, &iterations)); + rnp_key_handle_destroy(sub); + + /* v3 secret key */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_pub_keys(ffi, "data/keyrings/4/pubring.pgp")); + assert_true(import_sec_keys(ffi, "data/keyrings/4/secring.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "7D0BC10E933404C9", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "Encrypted"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "CFB"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(key, &cipher)); + assert_string_equal(cipher, "IDEA"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(key, &hash)); + assert_string_equal(hash, "MD5"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(key, &iterations)); + assert_int_equal(iterations, 1); + if (idea_enabled()) { + assert_rnp_success(rnp_key_unprotect(key, "password")); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + } else { + assert_rnp_failure(rnp_key_unprotect(key, "password")); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "Encrypted"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "CFB"); + rnp_buffer_destroy(mode); + } + rnp_key_handle_destroy(key); + + /* G10 keys */ + rnp_ffi_destroy(ffi); + assert_rnp_success(rnp_ffi_create(&ffi, "KBX", "G10")); + + assert_true(load_keys_kbx_g10( + ffi, "data/keyrings/3/pubring.kbx", "data/keyrings/3/private-keys-v1.d")); + + assert_rnp_success(rnp_locate_key(ffi, "keyid", "4BE147BB22DF1E60", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "Encrypted-Hashed"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "CBC"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(key, &cipher)); + assert_string_equal(cipher, "AES128"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(key, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(key, &iterations)); + assert_int_equal(iterations, 1024); + assert_rnp_success(rnp_key_unprotect(key, "password")); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + assert_rnp_success(rnp_locate_key(ffi, "keyid", "A49BAE05C16E8BC8", &sub)); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "Encrypted-Hashed"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "CBC"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(sub, &cipher)); + assert_string_equal(cipher, "AES128"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(sub, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(sub, &iterations)); + assert_int_equal(iterations, 1024); + assert_rnp_success(rnp_key_unprotect(sub, "password")); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(sub, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(sub, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(sub, &iterations)); + rnp_key_handle_destroy(sub); + + /* Secret subkeys, exported via gpg --export-secret-subkeys (no primary secret key data) */ + rnp_ffi_destroy(ffi); + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-1-subs.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "GPG-None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "Unknown"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "Encrypted-Hashed"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "CFB"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(sub, &cipher)); + assert_string_equal(cipher, "AES128"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(sub, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(sub, &iterations)); + assert_int_equal(iterations, 30408704); + assert_rnp_success(rnp_key_unprotect(sub, "password")); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(sub, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(sub, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(sub, &iterations)); + rnp_key_handle_destroy(sub); + + /* secret subkey is available, but primary key is stored on the smartcard by gpg */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-2-card.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "GPG-Smartcard"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "Unknown"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + assert_rnp_success(rnp_locate_key(ffi, "keyid", "DD23CEB7FEBEFF17", &sub)); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "Encrypted-Hashed"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "CFB"); + rnp_buffer_destroy(mode); + assert_rnp_success(rnp_key_get_protection_cipher(sub, &cipher)); + assert_string_equal(cipher, "AES128"); + rnp_buffer_destroy(cipher); + assert_rnp_success(rnp_key_get_protection_hash(sub, &hash)); + assert_string_equal(hash, "SHA1"); + rnp_buffer_destroy(hash); + assert_rnp_success(rnp_key_get_protection_iterations(sub, &iterations)); + assert_int_equal(iterations, 30408704); + assert_rnp_success(rnp_key_unprotect(sub, "password")); + assert_rnp_success(rnp_key_get_protection_type(sub, &type)); + assert_string_equal(type, "None"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(sub, &mode)); + assert_string_equal(mode, "None"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(sub, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(sub, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(sub, &iterations)); + rnp_key_handle_destroy(sub); + + /* primary key is stored with unknown gpg s2k */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-3.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "Unknown"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "Unknown"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + /* primary key is stored with unknown s2k */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-unknown.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &key)); + assert_rnp_success(rnp_key_get_protection_type(key, &type)); + assert_string_equal(type, "Unknown"); + rnp_buffer_destroy(type); + assert_rnp_success(rnp_key_get_protection_mode(key, &mode)); + assert_string_equal(mode, "Unknown"); + rnp_buffer_destroy(mode); + assert_rnp_failure(rnp_key_get_protection_cipher(key, &cipher)); + assert_rnp_failure(rnp_key_get_protection_hash(key, &hash)); + assert_rnp_failure(rnp_key_get_protection_iterations(key, &iterations)); + rnp_key_handle_destroy(key); + + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_key_default_subkey) +{ + rnp_ffi_t ffi = NULL; + rnp_key_handle_t primary = NULL; + rnp_key_handle_t def_key = NULL; + char * keyid = NULL; + + test_ffi_init(&ffi); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "7bc6709b15c23a4a", &primary)); + + /* bad parameters */ + assert_rnp_failure(rnp_key_get_default_key(NULL, NULL, 0, NULL)); + assert_rnp_failure(rnp_key_get_default_key(primary, NULL, 0, NULL)); + assert_rnp_failure(rnp_key_get_default_key(primary, "nonexistentusage", 0, &def_key)); + assert_rnp_failure(rnp_key_get_default_key(primary, "sign", UINT32_MAX, &def_key)); + assert_rnp_failure(rnp_key_get_default_key(primary, "sign", 0, NULL)); + + assert_rnp_success( + rnp_key_get_default_key(primary, "encrypt", RNP_KEY_SUBKEYS_ONLY, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "8A05B89FAD5ADED1"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + + /* no signing subkey */ + assert_int_equal(RNP_ERROR_NO_SUITABLE_KEY, + rnp_key_get_default_key(primary, "sign", RNP_KEY_SUBKEYS_ONLY, &def_key)); + assert_null(def_key); + + /* primary key returned as a default one */ + assert_rnp_success(rnp_key_get_default_key(primary, "sign", 0, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "7BC6709B15C23A4A"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + + assert_rnp_success(rnp_key_get_default_key(primary, "certify", 0, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "7BC6709B15C23A4A"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + + rnp_key_handle_destroy(primary); + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + + /* primary key with encrypting capability */ + assert_true(import_pub_keys(ffi, "data/test_key_validity/encrypting-primary.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "92091b7b76c50017", &primary)); + + assert_rnp_success(rnp_key_get_default_key(primary, "encrypt", 0, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "92091B7B76C50017"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + + assert_rnp_success( + rnp_key_get_default_key(primary, "encrypt", RNP_KEY_SUBKEYS_ONLY, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "C2E243E872C1FE50"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + rnp_key_handle_destroy(primary); + + /* offline primary key - must select a subkey */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-1-subs.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &primary)); + def_key = NULL; + assert_rnp_success(rnp_key_get_default_key(primary, "sign", 0, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "22F3A217C0E439CB"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + rnp_key_handle_destroy(primary); + /* offline primary key, stored on card - must select a subkey */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true(import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-2-card.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &primary)); + def_key = NULL; + assert_rnp_success(rnp_key_get_default_key(primary, "sign", 0, &def_key)); + assert_rnp_success(rnp_key_get_keyid(def_key, &keyid)); + assert_string_equal(keyid, "22F3A217C0E439CB"); + rnp_buffer_destroy(keyid); + rnp_key_handle_destroy(def_key); + rnp_key_handle_destroy(primary); + /* offline primary key without the signing subkey - fail */ + assert_rnp_success(rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET)); + assert_true( + import_all_keys(ffi, "data/test_key_edge_cases/alice-s2k-101-no-sign-sub.pgp")); + assert_rnp_success(rnp_locate_key(ffi, "keyid", "0451409669FFDE3C", &primary)); + def_key = NULL; + assert_int_equal(rnp_key_get_default_key(primary, "sign", 0, &def_key), + RNP_ERROR_NO_SUITABLE_KEY); + rnp_key_handle_destroy(primary); + + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_rnp_key_get_primary_grip) +{ + rnp_ffi_t ffi = NULL; + rnp_key_handle_t key = NULL; + char * grip = NULL; + + // setup FFI + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + + // load our keyrings + assert_true(load_keys_gpg(ffi, "data/keyrings/1/pubring.gpg")); + + // locate primary key + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "7BC6709B15C23A4A", &key)); + assert_non_null(key); + + // some edge cases + assert_rnp_failure(rnp_key_get_primary_grip(NULL, NULL)); + assert_rnp_failure(rnp_key_get_primary_grip(NULL, &grip)); + assert_rnp_failure(rnp_key_get_primary_grip(key, NULL)); + assert_rnp_failure(rnp_key_get_primary_grip(key, &grip)); + assert_null(grip); + rnp_key_handle_destroy(key); + + // locate subkey 1 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "1ED63EE56FADC34D", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_grip(key, &grip)); + assert_non_null(grip); + assert_string_equal(grip, "66D6A0800A3FACDE0C0EB60B16B3669ED380FDFA"); + rnp_buffer_destroy(grip); + grip = NULL; + rnp_key_handle_destroy(key); + + // locate subkey 2 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "1D7E8A5393C997A8", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_grip(key, &grip)); + assert_non_null(grip); + assert_string_equal(grip, "66D6A0800A3FACDE0C0EB60B16B3669ED380FDFA"); + rnp_buffer_destroy(grip); + grip = NULL; + rnp_key_handle_destroy(key); + + // locate subkey 3 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "8A05B89FAD5ADED1", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_grip(key, &grip)); + assert_non_null(grip); + assert_string_equal(grip, "66D6A0800A3FACDE0C0EB60B16B3669ED380FDFA"); + rnp_buffer_destroy(grip); + grip = NULL; + rnp_key_handle_destroy(key); + + // cleanup + rnp_ffi_destroy(ffi); +} + +TEST_F(rnp_tests, test_ffi_rnp_key_get_primary_fprint) +{ + rnp_ffi_t ffi = NULL; + + // setup FFI + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + + // load our keyrings + assert_true(load_keys_gpg(ffi, "data/keyrings/1/pubring.gpg")); + + // locate primary key + rnp_key_handle_t key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "7BC6709B15C23A4A", &key)); + assert_non_null(key); + + // some edge cases + char *fp = NULL; + assert_rnp_failure(rnp_key_get_primary_fprint(NULL, NULL)); + assert_rnp_failure(rnp_key_get_primary_fprint(NULL, &fp)); + assert_rnp_failure(rnp_key_get_primary_fprint(key, NULL)); + assert_rnp_failure(rnp_key_get_primary_fprint(key, &fp)); + assert_null(fp); + rnp_key_handle_destroy(key); + + // locate subkey 1 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "1ED63EE56FADC34D", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_fprint(key, &fp)); + assert_non_null(fp); + assert_string_equal(fp, "E95A3CBF583AA80A2CCC53AA7BC6709B15C23A4A"); + rnp_buffer_destroy(fp); + fp = NULL; + rnp_key_handle_destroy(key); + + // locate subkey 2 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "1D7E8A5393C997A8", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_fprint(key, &fp)); + assert_non_null(fp); + assert_string_equal(fp, "E95A3CBF583AA80A2CCC53AA7BC6709B15C23A4A"); + rnp_buffer_destroy(fp); + fp = NULL; + rnp_key_handle_destroy(key); + + // locate subkey 3 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "8A05B89FAD5ADED1", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_fprint(key, &fp)); + assert_non_null(fp); + assert_string_equal(fp, "E95A3CBF583AA80A2CCC53AA7BC6709B15C23A4A"); + rnp_buffer_destroy(fp); + fp = NULL; + rnp_key_handle_destroy(key); + + // locate key 1 - subkey 0 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "54505A936A4A970E", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_fprint(key, &fp)); + assert_non_null(fp); + assert_string_equal(fp, "BE1C4AB951F4C2F6B604C7F82FCADF05FFA501BB"); + rnp_buffer_destroy(fp); + fp = NULL; + rnp_key_handle_destroy(key); + + // locate key 2 - subkey 1 + key = NULL; + assert_rnp_success(rnp_locate_key(ffi, "keyid", "326EF111425D14A5", &key)); + assert_non_null(key); + assert_rnp_success(rnp_key_get_primary_fprint(key, &fp)); + assert_non_null(fp); + assert_string_equal(fp, "BE1C4AB951F4C2F6B604C7F82FCADF05FFA501BB"); + rnp_buffer_destroy(fp); + fp = NULL; + rnp_key_handle_destroy(key); + + // cleanup + rnp_ffi_destroy(ffi); +} |