Skip to content

Commit

Permalink
Add tests for rnp_revocation_signature_create() and related functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
ni4 committed Jan 17, 2024
1 parent bdbfba0 commit ee0a376
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 1 deletion.
139 changes: 138 additions & 1 deletion src/tests/ffi-key-sig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1749,4 +1749,141 @@ TEST_F(rnp_tests, test_ffi_add_revoker_signature)
/* Check v5 key */

rnp_ffi_destroy(ffi);
}
}

TEST_F(rnp_tests, test_ffi_create_revocation_signature)
{
rnp_ffi_t ffi = NULL;
assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
assert_true(import_all_keys(ffi, "data/test_stream_key_load/ecc-25519-2subs-sec.asc"));
assert_true(import_pub_keys(ffi, "data/test_stream_key_load/ecc-p256-sec.asc"));
rnp_key_handle_t key = NULL;
assert_rnp_success(rnp_locate_key(ffi, "userid", "ecc-25519", &key));
/* Create self revocation */
rnp_signature_handle_t newsig = NULL;
assert_rnp_failure(rnp_key_revocation_signature_create(NULL, key, &newsig));
assert_rnp_failure(rnp_key_revocation_signature_create(key, key, NULL));
assert_rnp_failure(rnp_key_revocation_signature_create(key, NULL, NULL));
assert_rnp_success(rnp_key_revocation_signature_create(key, NULL, &newsig));
const char *revcode = "compromised";
const char *revreason = "custom revocation reason";
const char *hash = "SHA512";
assert_rnp_failure(rnp_key_signature_set_hash(NULL, hash));
assert_rnp_failure(rnp_key_signature_set_hash(newsig, NULL));
assert_rnp_failure(rnp_key_signature_set_hash(newsig, "wrong"));
assert_rnp_success(rnp_key_signature_set_hash(newsig, hash));
assert_rnp_failure(rnp_key_signature_set_revocation_reason(NULL, revcode, revreason));
assert_rnp_success(rnp_key_signature_set_revocation_reason(newsig, NULL, NULL));
assert_rnp_success(rnp_key_signature_set_revocation_reason(newsig, NULL, "wrong reason"));
assert_rnp_failure(rnp_key_signature_set_revocation_reason(newsig, "wrong code", NULL));
assert_rnp_success(rnp_key_signature_set_revocation_reason(newsig, revcode, revreason));
assert_rnp_failure(rnp_key_signature_sign(newsig));
rnp_ffi_set_pass_provider(ffi, ffi_string_password_provider, (void *) "password");
assert_rnp_success(rnp_key_signature_sign(newsig));
rnp_signature_handle_destroy(newsig);
/* Check signature parameters */
assert_rnp_success(rnp_key_get_signature_at(key, 0, &newsig));
assert_true(check_sig_hash(newsig, hash));
assert_true(check_sig_type(newsig, "key revocation"));
char *sigcode = NULL;
char *sigreason = NULL;
/* Some edge cases of the new function */
assert_rnp_failure(rnp_signature_get_revocation_reason(NULL, &sigcode, &sigreason));
assert_rnp_success(rnp_signature_get_revocation_reason(newsig, &sigcode, NULL));
assert_string_equal(sigcode, revcode);
rnp_buffer_destroy(sigcode);
assert_rnp_success(rnp_signature_get_revocation_reason(newsig, NULL, &sigreason));
assert_string_equal(sigreason, revreason);
rnp_buffer_destroy(sigreason);
assert_true(check_sig_revreason(newsig, revcode, revreason));
rnp_signature_handle_destroy(newsig);
assert_true(check_key_revoked(key, true));
assert_true(check_key_revreason(key, revreason));
bool compromised = false;
assert_rnp_success(rnp_key_is_compromised(key, &compromised));
assert_true(compromised);
/* Export key and make sure data is saved */
auto keydata = export_key(key, true);
rnp_key_handle_destroy(key);
rnp_ffi_t newffi = NULL;
assert_rnp_success(rnp_ffi_create(&newffi, "GPG", "GPG"));
assert_true(import_all_keys(newffi, keydata.data(), keydata.size()));
assert_rnp_success(rnp_locate_key(newffi, "userid", "ecc-25519", &key));
assert_true(check_key_revoked(key, true));
assert_true(check_key_revreason(key, revreason));
assert_rnp_success(rnp_key_get_signature_at(key, 0, &newsig));
assert_true(check_sig_type(newsig, "key revocation"));
rnp_signature_handle_destroy(newsig);
rnp_key_handle_destroy(key);
rnp_ffi_destroy(newffi);
/* Create revocation for other key, using the designated revoker */
rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET);
assert_true(import_all_keys(ffi, "data/test_stream_key_load/ecc-25519-sec.asc"));
assert_true(
import_pub_keys(ffi, "data/test_stream_key_load/ecc-p256-desig-rev-1-pub.asc"));
key = get_key_by_uid(ffi, "ecc-p256");
rnp_key_handle_t revoker = get_key_by_uid(ffi, "ecc-25519");
assert_true(check_key_locked(revoker, true));
assert_true(check_key_revoked(key, false));
assert_rnp_success(rnp_key_revocation_signature_create(revoker, key, &newsig));
assert_rnp_success(rnp_key_signature_set_hash(newsig, hash));
assert_rnp_success(rnp_key_signature_set_revocation_reason(newsig, revcode, revreason));
assert_rnp_success(rnp_key_signature_sign(newsig));
assert_true(check_key_locked(revoker, true));
rnp_signature_handle_destroy(newsig);
rnp_key_handle_destroy(revoker);
assert_true(check_key_revoked(key, true));
assert_true(check_key_revreason(key, revreason));
assert_rnp_success(rnp_key_is_compromised(key, &compromised));
assert_true(compromised);
/* Export/import and check */
keydata = export_key(key, false);
rnp_key_handle_destroy(key);
assert_rnp_success(rnp_ffi_create(&newffi, "GPG", "GPG"));
assert_true(import_all_keys(newffi, keydata.data(), keydata.size()));
assert_true(import_all_keys(newffi, "data/test_stream_key_load/ecc-25519-pub.asc"));
key = get_key_by_uid(ffi, "ecc-p256");
assert_true(check_key_revoked(key, true));
assert_true(check_key_revreason(key, revreason));
assert_rnp_success(rnp_key_get_signature_at(key, 0, &newsig));
assert_true(check_sig_type(newsig, "key revocation"));
rnp_signature_handle_destroy(newsig);
rnp_key_handle_destroy(key);
rnp_ffi_destroy(newffi);
/* Create self subkey revocation */
rnp_unload_keys(ffi, RNP_KEY_UNLOAD_PUBLIC | RNP_KEY_UNLOAD_SECRET);
assert_true(import_all_keys(ffi, "data/test_stream_key_load/ecc-p256-sec.asc"));
key = get_key_by_uid(ffi, "ecc-p256");
rnp_key_handle_t subkey = get_key_by_fp(ffi, "40e608afbc8d62cdcc08904f37e285e9e9851491");
assert_rnp_success(rnp_key_revocation_signature_create(key, subkey, &newsig));
assert_rnp_success(rnp_key_signature_sign(newsig));
assert_true(check_key_revoked(subkey, true));
assert_true(check_key_revreason(subkey, "No reason specified"));
assert_rnp_success(rnp_key_is_compromised(subkey, &compromised));
assert_false(compromised);
rnp_signature_handle_destroy(newsig);
assert_rnp_success(rnp_key_get_signature_at(subkey, 0, &newsig));
assert_true(check_sig_type(newsig, "subkey revocation"));
assert_rnp_success(rnp_signature_get_revocation_reason(newsig, &sigcode, &sigreason));
assert_string_equal(sigcode, "");
assert_string_equal(sigreason, "");
rnp_signature_handle_destroy(newsig);
rnp_key_handle_destroy(subkey);
/* Export and recheck */
keydata = export_key(key, false);
rnp_key_handle_destroy(key);
assert_rnp_success(rnp_ffi_create(&newffi, "GPG", "GPG"));
assert_true(import_all_keys(newffi, keydata.data(), keydata.size()));
subkey = get_key_by_fp(newffi, "40e608afbc8d62cdcc08904f37e285e9e9851491");
assert_true(check_key_revoked(subkey, true));
assert_true(check_key_revreason(subkey, "No reason specified"));
assert_rnp_success(rnp_key_is_compromised(subkey, &compromised));
assert_false(compromised);
rnp_key_handle_destroy(subkey);
rnp_ffi_destroy(newffi);
/* Revoke other key using subkey as revoker with designated revoker */
/* Attempt to revoke primary key using the subkey without designated revoker */
/* Attempt to revoke primary key using the subkey with designated revoker */

rnp_ffi_destroy(ffi);
}
76 changes: 76 additions & 0 deletions src/tests/support.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,16 @@ check_key_revoked(rnp_key_handle_t key, bool revoked)
return rev == revoked;
}

bool
check_key_locked(rnp_key_handle_t key, bool locked)
{
bool lock = !locked;
if (rnp_key_is_locked(key, &lock)) {
return false;

Check warning on line 1114 in src/tests/support.cpp

View check run for this annotation

Codecov / codecov/patch

src/tests/support.cpp#L1114

Added line #L1114 was not covered by tests
}
return lock == locked;
}

uint32_t
get_key_expiry(rnp_key_handle_t key)
{
Expand Down Expand Up @@ -1159,6 +1169,18 @@ check_key_fp(rnp_key_handle_t key, const std::string &expected)
return res;
}

bool
check_key_revreason(rnp_key_handle_t key, const char *reason)
{
char *rstr = NULL;
if (rnp_key_get_revocation_reason(key, &rstr)) {
return false;

Check warning on line 1177 in src/tests/support.cpp

View check run for this annotation

Codecov / codecov/patch

src/tests/support.cpp#L1177

Added line #L1177 was not covered by tests
}
bool res = !strcmp(rstr, reason);
rnp_buffer_destroy(rstr);
return res;
}

bool
check_has_key(rnp_ffi_t ffi, const std::string &id, bool secret, bool valid)
{
Expand Down Expand Up @@ -1196,6 +1218,60 @@ check_has_key(rnp_ffi_t ffi, const std::string &id, bool secret, bool valid)
return res;
}

bool
check_sig_hash(rnp_signature_handle_t sig, const char *hash)
{
char *sighash = NULL;
if (rnp_signature_get_hash_alg(sig, &sighash)) {
return false;

Check warning on line 1226 in src/tests/support.cpp

View check run for this annotation

Codecov / codecov/patch

src/tests/support.cpp#L1226

Added line #L1226 was not covered by tests
}
bool res = !strcmp(sighash, hash);
rnp_buffer_destroy(sighash);
return res;
}

bool
check_sig_type(rnp_signature_handle_t sig, const char *type)
{
char *sigtype = NULL;
if (rnp_signature_get_type(sig, &sigtype)) {
return false;

Check warning on line 1238 in src/tests/support.cpp

View check run for this annotation

Codecov / codecov/patch

src/tests/support.cpp#L1238

Added line #L1238 was not covered by tests
}
bool res = !strcmp(sigtype, type);
rnp_buffer_destroy(sigtype);
return res;
}

bool
check_sig_revreason(rnp_signature_handle_t sig, const char *revcode, const char *revreason)
{
char *sigcode = NULL;
char *sigreason = NULL;
if (rnp_signature_get_revocation_reason(sig, &sigcode, &sigreason)) {
return false;

Check warning on line 1251 in src/tests/support.cpp

View check run for this annotation

Codecov / codecov/patch

src/tests/support.cpp#L1251

Added line #L1251 was not covered by tests
}
bool res = !strcmp(sigcode, revcode) && !strcmp(sigreason, revreason);
rnp_buffer_destroy(sigcode);
rnp_buffer_destroy(sigreason);
return res;
}

rnp_key_handle_t
get_key_by_fp(rnp_ffi_t ffi, const char *fp)
{
rnp_key_handle_t key = NULL;
rnp_locate_key(ffi, "fingerprint", fp, &key);
return key;
}

rnp_key_handle_t
get_key_by_uid(rnp_ffi_t ffi, const char *uid)
{
rnp_key_handle_t key = NULL;
rnp_locate_key(ffi, "userid", uid, &key);
return key;
}

rnp_key_handle_t
bogus_key_handle(rnp_ffi_t ffi)
{
Expand Down
10 changes: 10 additions & 0 deletions src/tests/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ void dump_key_stdout(rnp_key_handle_t key, bool secret = false);
/* some shortcuts for less code */
bool check_key_valid(rnp_key_handle_t key, bool validity);
bool check_key_revoked(rnp_key_handle_t key, bool revoked);
bool check_key_locked(rnp_key_handle_t key, bool locked);
uint32_t get_key_expiry(rnp_key_handle_t key);
size_t get_key_uids(rnp_key_handle_t key);
bool check_sub_valid(rnp_key_handle_t key, size_t idx, bool validity);
Expand All @@ -265,10 +266,19 @@ void check_loaded_keys(const char * format,
bool secret);
bool check_key_grip(rnp_key_handle_t key, const std::string &expected);
bool check_key_fp(rnp_key_handle_t key, const std::string &expected);
bool check_key_revreason(rnp_key_handle_t key, const char *reason);
bool check_has_key(rnp_ffi_t ffi,
const std::string &id,
bool secret = false,
bool valid = true);
bool check_sig_hash(rnp_signature_handle_t sig, const char *hash);
bool check_sig_type(rnp_signature_handle_t sig, const char *type);
bool check_sig_revreason(rnp_signature_handle_t sig,
const char * revcode,
const char * revreason);

rnp_key_handle_t get_key_by_fp(rnp_ffi_t ffi, const char *fp);
rnp_key_handle_t get_key_by_uid(rnp_ffi_t ffi, const char *uid);

/* create bogus key handle with NULL pub/sec keys */
rnp_key_handle_t bogus_key_handle(rnp_ffi_t ffi);
Expand Down

0 comments on commit ee0a376

Please sign in to comment.