Revision control
Copy as Markdown
Other Tools
/*
* 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 "../librekey/key_store_pgp.h"
#include "pgp-key.h"
#include "rnp_tests.h"
#include "support.h"
/* This test loads a pgp keyring and adds a few userids to the key.
*/
TEST_F(rnp_tests, test_key_add_userid)
{
pgp_key_t * key = NULL;
pgp_source_t src = {};
pgp_dest_t dst = {};
const uint32_t base_expiry = 1234567890;
static const char *keyids[] = {"7bc6709b15c23a4a", // primary
"1ed63ee56fadc34d",
"1d7e8a5393c997a8",
"8a05b89fad5aded1",
"2fcadf05ffa501bb", // primary
"54505a936a4a970e",
"326ef111425d14a5"};
rnp_key_store_t *ks = new rnp_key_store_t(global_ctx);
assert_rnp_success(init_file_src(&src, "data/keyrings/1/secring.gpg"));
assert_rnp_success(rnp_key_store_pgp_read_from_src(ks, &src));
src_close(&src);
// locate our key
assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0]));
assert_non_null(key);
// unlock the key
pgp_password_provider_t pprov(string_copy_password_callback, (void *) "password");
assert_true(key->unlock(pprov));
// save the counts for a few items
unsigned uidc = key->uid_count();
unsigned subsigc = key->sig_count();
// add first, non-primary userid
rnp_selfsig_cert_info_t selfsig0;
selfsig0.userid = "added0";
selfsig0.key_flags = 0x2;
selfsig0.key_expiration = base_expiry;
selfsig0.primary = false;
auto curtime = global_ctx.time();
global_ctx.set_time(curtime > SHA1_KEY_FROM ? SHA1_KEY_FROM - 100 : 0);
key->add_uid_cert(selfsig0, PGP_HASH_SHA1, global_ctx);
// attempt to add sha1-signed uid and make sure it succeeds now and fails after the cutoff
// date in 2024
assert_int_equal(base_expiry, key->expiration());
assert_int_equal(0x2, key->flags());
assert_true(key->get_uid(uidc).valid);
// delete new uid and add one in the future
key->del_uid(uidc);
global_ctx.set_time(SHA1_KEY_FROM + 2);
key->add_uid_cert(selfsig0, PGP_HASH_SHA1, global_ctx);
assert_int_equal(0, key->expiration());
assert_int_equal(0x3, key->flags());
assert_false(key->get_uid(uidc).valid);
global_ctx.set_time(0);
key->del_uid(uidc);
assert_int_equal(uidc, key->uid_count());
assert_int_equal(subsigc, key->sig_count());
key->add_uid_cert(selfsig0, PGP_HASH_SHA256, global_ctx);
// make sure this userid has not been marked as primary
assert_false(key->has_primary_uid());
// make sure key expiration and flags are set
assert_int_equal(base_expiry, key->expiration());
assert_int_equal(0x2, key->flags());
assert_true(key->get_uid(uidc).valid);
// add a primary userid
rnp_selfsig_cert_info_t selfsig1;
selfsig1.userid = "added1";
selfsig1.key_flags = 0xAB;
selfsig1.key_expiration = base_expiry + 1;
selfsig1.primary = 1;
key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx);
// make sure this userid has been marked as primary
assert_int_equal(key->uid_count() - 1, key->get_primary_uid());
// make sure key expiration and flags are set
assert_int_equal(base_expiry + 1, key->expiration());
assert_int_equal(0xAB, key->flags());
assert_true(key->get_uid(uidc + 1).valid);
// try to add the same userid (should fail)
rnp_selfsig_cert_info_t dup_selfsig;
dup_selfsig.userid = "added1";
assert_throw(key->add_uid_cert(dup_selfsig, PGP_HASH_SHA256, global_ctx));
// try to add another primary userid (should fail)
rnp_selfsig_cert_info_t selfsig2;
selfsig2.userid = "added2";
selfsig2.primary = 1;
assert_throw(key->add_uid_cert(selfsig2, PGP_HASH_SHA256, global_ctx));
selfsig2.userid = "added2";
selfsig2.key_flags = 0xCD;
selfsig2.primary = 0;
// actually add another userid
key->add_uid_cert(selfsig2, PGP_HASH_SHA256, global_ctx);
// confirm that the counts have increased as expected
assert_int_equal(key->uid_count(), uidc + 3);
assert_int_equal(key->sig_count(), subsigc + 3);
assert_true(key->get_uid(uidc + 2).valid);
// make sure key expiration and flags are not updated as they are picked from the primary
assert_int_equal(base_expiry + 1, key->expiration());
assert_int_equal(0xAB, key->flags());
// check the userids array
// added0
assert_string_equal(key->get_uid(uidc).str.c_str(), "added0");
assert_int_equal(uidc, key->get_sig(subsigc).uid);
assert_int_equal(0x2, key->get_sig(subsigc).key_flags);
// added1
assert_string_equal(key->get_uid(uidc + 1).str.c_str(), "added1");
assert_int_equal(uidc + 1, key->get_sig(subsigc + 1).uid);
assert_int_equal(0xAB, key->get_sig(subsigc + 1).key_flags);
// added2
assert_string_equal(key->get_uid(uidc + 2).str.c_str(), "added2");
assert_int_equal(uidc + 2, key->get_sig(subsigc + 2).uid);
assert_int_equal(0xCD, key->get_sig(subsigc + 2).key_flags);
// save the raw packets for the key (to reload later)
assert_rnp_success(init_mem_dest(&dst, NULL, 0));
key->write(dst);
// cleanup
delete ks;
key = NULL;
// start over
ks = new rnp_key_store_t(global_ctx);
assert_non_null(ks);
// read from the saved packets
assert_rnp_success(init_mem_src(&src, mem_dest_get_memory(&dst), dst.writeb, false));
assert_rnp_success(rnp_key_store_pgp_read_from_src(ks, &src));
src_close(&src);
dst_close(&dst, true);
assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0]));
// confirm that the counts have increased as expected
assert_int_equal(key->uid_count(), uidc + 3);
assert_int_equal(key->sig_count(), subsigc + 3);
// make sure correct key expiration and flags are set
assert_int_equal(base_expiry + 1, key->expiration());
assert_int_equal(0xAB, key->flags());
// check the userids array
// added0
assert_string_equal(key->get_uid(uidc).str.c_str(), "added0");
assert_int_equal(uidc, key->get_sig(subsigc).uid);
assert_int_equal(0x2, key->get_sig(subsigc).key_flags);
assert_true(key->get_uid(uidc).valid);
// added1
assert_string_equal(key->get_uid(uidc + 1).str.c_str(), "added1");
assert_int_equal(uidc + 1, key->get_sig(subsigc + 1).uid);
assert_int_equal(0xAB, key->get_sig(subsigc + 1).key_flags);
assert_true(key->get_uid(uidc + 1).valid);
// added2
assert_string_equal(key->get_uid(uidc + 2).str.c_str(), "added2");
assert_int_equal(uidc + 2, key->get_sig(subsigc + 2).uid);
assert_int_equal(0xCD, key->get_sig(subsigc + 2).key_flags);
assert_true(key->get_uid(uidc + 2).valid);
// delete primary userid and see how flags/expiration changes
key->del_uid(uidc + 1);
key->revalidate(*ks);
assert_string_equal(key->get_uid(uidc + 1).str.c_str(), "added2");
assert_int_equal(uidc + 1, key->get_sig(subsigc + 1).uid);
assert_int_equal(0xCD, key->get_sig(subsigc + 1).key_flags);
assert_int_equal(key->expiration(), 0);
assert_int_equal(key->flags(), 0xCD);
// delete first uid
key->del_uid(0);
key->revalidate(*ks);
assert_string_equal(key->get_uid(uidc).str.c_str(), "added2");
assert_int_equal(uidc, key->get_sig(subsigc).uid);
assert_int_equal(0xCD, key->get_sig(subsigc).key_flags);
assert_int_equal(key->expiration(), 0);
assert_int_equal(key->flags(), 0xCD);
// delete last uid, leaving added0 only
key->del_uid(uidc);
key->revalidate(*ks);
assert_string_equal(key->get_uid(uidc - 1).str.c_str(), "added0");
assert_int_equal(uidc - 1, key->get_sig(subsigc - 1).uid);
assert_int_equal(0x2, key->get_sig(subsigc - 1).key_flags);
assert_int_equal(key->expiration(), base_expiry);
assert_int_equal(key->flags(), 0x2);
// delete added0
key->del_uid(0);
key->revalidate(*ks);
// cleanup
delete ks;
}