Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor rnp_key_store_t to rnp::KeyStore. #2122

Merged
merged 28 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1797f04
Refactor pgp_sig_get_signer and duplicate rnp_key_store_get_signer_ke…
ni4 Aug 25, 2023
492cdf8
Refactor rnp_key_store_clear() to rnp_key_store_t::clear().
ni4 Aug 25, 2023
b5b4dc9
Refactor rnp_key_store_get_key_count to rnp_key_store_t::key_count().
ni4 Aug 25, 2023
4495777
Refactor rnp_key_store_get_key_by_fpr() to rnp_key_store_t::get_key().
ni4 Aug 25, 2023
5f4cec5
Refactor rnp_key_store_load_* functions to rnp_key_store_t::load()
ni4 Aug 25, 2023
4be0ad8
Refactor rnp_key_store_write_to_* to rnp_key_store_t::write()
ni4 Aug 25, 2023
aeaf2b7
Refactor rnp_key_store_add_key to rnp_key_store_t::add_key().
ni4 Aug 25, 2023
0a937c4
Refactor rnp_key_store_import_* methods to rnp_key_store_t::import_*.
ni4 Aug 25, 2023
fa8fd23
Move away key grip calculations from the rnp_key_store.cpp.
ni4 Aug 25, 2023
ac023d5
Refactor rnp_key_store_remove_key to rnp_key_store_t::remove_key.
ni4 Aug 25, 2023
db3c872
Refactor rnp_key_store_get_primary_key to rnp_key_store_t::primary_ke…
ni4 Aug 25, 2023
1020228
Refactor rnp_key_store_search to rnp_key_store_t::search().
ni4 Aug 25, 2023
2736411
Refactor rnp_key_to_vec -> pgp_key_t::write_vec.
ni4 Aug 26, 2023
7ad9f06
Refactor rnp_key_store_pgp_read_from_src to rnp_key_store_t::load_pgp.
ni4 Aug 26, 2023
490445b
Refactor rnp_key_store_pgp_read_key_from_src to rnp_key_store_t::load…
ni4 Aug 26, 2023
5599a1d
Refactor rnp_key_store_pgp_write_to_dst to rnp_key_store_t::write_pgp
ni4 Aug 26, 2023
e101767
Refactor rnp_key_store_add_transferable_* to rnp_key_store_t::add_ts_…
ni4 Aug 26, 2023
67ecb25
Remove now empty key_store_pgp.h header.
ni4 Aug 26, 2023
f2f7873
Refactor out key_store_kbx.h and update corresponding functions.
ni4 Aug 26, 2023
5f22ee6
Refactor rnp_key_store_g10_from_src to rnp_key_store_t::load_g10().
ni4 Aug 26, 2023
fe6ba81
Refactor pgp_key_get_subkey to rnp_key_store_t::get_subkey.
ni4 Aug 26, 2023
ce78821
Use auto instead of rnp_key_store_t *, where applicable.
ni4 Aug 26, 2023
b4d70d6
Rename rnp_key_store_t to rnp::KeyStore.
ni4 Aug 26, 2023
a5e16ed
Refactor pgp_request_key to pgp_key_provider_t::request_key().
ni4 Aug 28, 2023
0460f2b
Refactor rnp_key_matches_search to pgp_key_t->matches().
ni4 Aug 28, 2023
8e1b013
Fix boolean expression in pgp_key_provider_t::request_key().
ni4 Aug 28, 2023
fcfe55e
Rename pgp_key_provider_t to rnp::KeyProvider
ni4 Aug 28, 2023
31e2e52
Refactor rnp_key_store_refresh_subkey_grips to rnp::KeyStore->refresh…
ni4 Aug 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 186 additions & 95 deletions include/rekey/rnp_key_store.h
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
/*
* Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
* Copyright (c) 2017-2023 [Ribose Inc](https://www.ribose.com).
* All rights reserved.
*
* This code is originally derived from software contributed to
* The NetBSD Foundation by Alistair Crooks ([email protected]), and
* carried further by Ribose Inc (https://www.ribose.com).
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 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.
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 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 HOLDERS 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.
* 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.
*/

#ifndef KEY_STORE_H_
Expand Down Expand Up @@ -61,7 +57,15 @@ typedef enum pgp_sig_import_status_t {

typedef std::unordered_map<pgp_fingerprint_t, std::list<pgp_key_t>::iterator> pgp_key_fp_map_t;

typedef struct rnp_key_store_t {
namespace rnp {
class KeyStore {
private:
pgp_key_t * add_subkey(pgp_key_t &srckey, pgp_key_t *oldkey);
pgp_sig_import_status_t import_subkey_signature(pgp_key_t & key,
const pgp_signature_t &sig);
bool refresh_subkey_grips(pgp_key_t &key);

public:
std::string path;
pgp_key_store_format_t format;
rnp::SecurityContext & secctx;
Expand All @@ -72,78 +76,165 @@ typedef struct rnp_key_store_t {
pgp_key_fp_map_t keybyfp;
std::vector<std::unique_ptr<kbx_blob_t>> blobs;

~rnp_key_store_t();
rnp_key_store_t(rnp::SecurityContext &ctx)
~KeyStore();
KeyStore(rnp::SecurityContext &ctx)
: path(""), format(PGP_KEY_STORE_UNKNOWN), secctx(ctx){};
rnp_key_store_t(pgp_key_store_format_t format,
const std::string & path,
rnp::SecurityContext & ctx);
KeyStore(pgp_key_store_format_t format,
const std::string & path,
rnp::SecurityContext & ctx);
/* make sure we use only empty constructor */
rnp_key_store_t(rnp_key_store_t &&src) = delete;
rnp_key_store_t &operator=(rnp_key_store_t &&) = delete;
rnp_key_store_t(const rnp_key_store_t &src) = delete;
rnp_key_store_t &operator=(const rnp_key_store_t &) = delete;
} rnp_key_store_t;

bool rnp_key_store_load_from_path(rnp_key_store_t *, const pgp_key_provider_t *key_provider);
bool rnp_key_store_load_from_src(rnp_key_store_t *,
pgp_source_t *,
const pgp_key_provider_t *key_provider);

bool rnp_key_store_write_to_path(rnp_key_store_t *);
bool rnp_key_store_write_to_dst(rnp_key_store_t *, pgp_dest_t *);

void rnp_key_store_clear(rnp_key_store_t *);

size_t rnp_key_store_get_key_count(const rnp_key_store_t *);

/**
* @brief Add key to the keystore, copying it.
*
* @param keyring allocated keyring, cannot be NULL.
* @param key key to be added, cannot be NULL.
* @return pointer to the added key or NULL if failed.
*/
pgp_key_t *rnp_key_store_add_key(rnp_key_store_t *keyring, pgp_key_t *key);

pgp_key_t *rnp_key_store_import_key(rnp_key_store_t *,
pgp_key_t *,
bool,
pgp_key_import_status_t *);

/**
* @brief Get signer's key from key store.
*
* @param store populated key store, cannot be NULL.
* @param sig signature, cannot be NULL.
* @return pointer to pgp_key_t structure if key was found or NULL otherwise.
*/
pgp_key_t *rnp_key_store_get_signer_key(rnp_key_store_t *store, const pgp_signature_t *sig);

pgp_sig_import_status_t rnp_key_store_import_key_signature(rnp_key_store_t * keyring,
pgp_key_t * key,
const pgp_signature_t *sig);

/**
* @brief Import revocation or direct-key signature to the keyring.
*
* @param keyring populated keyring, cannot be NULL.
* @param sig signature to import.
* @param status signature import status will be put here, if not NULL.
* @return pointer to the key to which this signature belongs (or NULL if key was not found)
*/
pgp_key_t *rnp_key_store_import_signature(rnp_key_store_t * keyring,
const pgp_signature_t * sig,
pgp_sig_import_status_t *status);

bool rnp_key_store_remove_key(rnp_key_store_t *, const pgp_key_t *, bool);

bool rnp_key_store_get_key_grip(const pgp_key_material_t *, pgp_key_grip_t &grip);

const pgp_key_t *rnp_key_store_get_key_by_fpr(const rnp_key_store_t *,
const pgp_fingerprint_t &fpr);
pgp_key_t * rnp_key_store_get_key_by_fpr(rnp_key_store_t *, const pgp_fingerprint_t &fpr);
pgp_key_t * rnp_key_store_get_primary_key(rnp_key_store_t *, const pgp_key_t *);
pgp_key_t *rnp_key_store_search(rnp_key_store_t *, const pgp_key_search_t *, pgp_key_t *);
KeyStore(KeyStore &&src) = delete;
KeyStore &operator=(KeyStore &&) = delete;
KeyStore(const KeyStore &src) = delete;
KeyStore &operator=(const KeyStore &) = delete;

/**
* @brief Try to load key store from path.
*/
bool load(const KeyProvider *key_provider = nullptr);

/**
* @brief Try to load key store from source.
*/
bool load(pgp_source_t &src, const KeyProvider *key_provider = nullptr);

/**
* @brief Load all keys from the source, assuming openpgp format.
*
* @param src source to load the keys from.
* @param skiperrors ignore key parsing errors, allowing to skip malformed/unsupported
* keys.
*/
rnp_result_t load_pgp(pgp_source_t &src, bool skiperrors = false);

/**
* @brief Load single key (including subkeys) from the source, assuming openpgp format.
*
* @param src source to load the key from.
* @param skiperrors ignore key parsing errors, allowing to skip malformed/unknown subkeys.
*/
rnp_result_t load_pgp_key(pgp_source_t &src, bool skiperrors = false);

/**
* @brief Load keystore in kbx format.
*/
bool load_kbx(pgp_source_t &src, const KeyProvider *key_provider = nullptr);

/**
* @brief Load keystore in g10 format.
*/
bool load_g10(pgp_source_t &src, const KeyProvider *key_provider = nullptr);

/**
* @brief Write keystore to the path.
*/
bool write();

/**
* @brief Write keystore to the dest.
*/
bool write(pgp_dest_t &dst);

/**
* @brief Write keystore to the dest in pgp format.
*/
bool write_pgp(pgp_dest_t &dst);

/**
* @brief Write keystore to the dest in kbx format.
*
*/
bool write_kbx(pgp_dest_t &dst);

void clear();

size_t key_count() const;

pgp_key_t * get_key(const pgp_fingerprint_t &fpr);
const pgp_key_t *get_key(const pgp_fingerprint_t &fpr) const;

/**
* @brief Get the key's subkey by its index
*
* @param key primary key
* @param idx index of the subkey
* @return pointer to the subkey or nullptr if subkey was found
*/
pgp_key_t *get_subkey(const pgp_key_t &key, size_t idx);

/**
* @brief Get the signer's key for signature
*
* @param sig signature
* @param prov key provider to request needed key.
* @return pointer to the key or nullptr if signer's key was not found.
*/
pgp_key_t *get_signer(const pgp_signature_t &sig, const KeyProvider *prov = nullptr);

/**
* @brief Add key to the keystore, copying it.
* @return pointer to the added key or nullptr if failed.
*/
pgp_key_t *add_key(pgp_key_t &key);

/**
* @brief Add transferable key to the keystore.
*
* @param tkey parsed key.
*/
bool add_ts_key(pgp_transferable_key_t &tkey);

/**
* @brief Add transferable subkey to the keystore.
*
* @param tskey parsed subkey.
* @param pkey primary key, may be nullptr.
*/
bool add_ts_subkey(const pgp_transferable_subkey_t &tskey, pgp_key_t *pkey = nullptr);

/**
* @brief Import key to the keystore.
*
* @param srckey source key.
* @param pubkey import just public key part.
* @param status if not nullptr then import status will be stored here.
* @return pgp_key_t*
*/
pgp_key_t *import_key(pgp_key_t & srckey,
bool pubkey,
pgp_key_import_status_t *status = nullptr);

/**
* @brief Import signature for the specified key.
*/
pgp_sig_import_status_t import_signature(pgp_key_t &key, const pgp_signature_t &sig);

/**
* @brief Import revocation or direct-key signature to the keystore.
*
* @param sig signature to import.
* @param status signature import status will be put here, if not nullptr.
* @return pointer to the key to which this signature belongs (or nullptr if key was not
* found)
*/
pgp_key_t *import_signature(const pgp_signature_t &sig, pgp_sig_import_status_t *status);

/**
* @brief Remove key from the keystore.
*
* @param key key to remove. Must be from this keystore.
* @param subkeys remove subkeys or not.
* @return true if key was succesfully removed, or false if key was not found in keystore.
*/
bool remove_key(const pgp_key_t &key, bool subkeys = false);

/**
* @brief Get primary key for the subkey, if any.
*/
pgp_key_t *primary_key(const pgp_key_t &subkey);

pgp_key_t *search(const pgp_key_search_t &search, pgp_key_t *after = nullptr);
};
} // namespace rnp

#endif /* KEY_STORE_H_ */
5 changes: 3 additions & 2 deletions src/fuzzing/keyring_g10.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "../lib/pgp-key.h"
#include "../librekey/key_store_g10.h"
#include "../librepgp/stream-common.h"
#include "../include/rekey/rnp_key_store.h"
#include "../lib/sec_profile.hpp"

#ifdef RNP_RUN_TESTS
Expand All @@ -40,11 +41,11 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
#endif
{
rnp::SecurityContext ctx;
rnp_key_store_t ks(ctx);
rnp::KeyStore ks(ctx);
pgp_source_t memsrc = {};

init_mem_src(&memsrc, data, size, false);
rnp_key_store_g10_from_src(&ks, &memsrc, NULL);
ks.load_g10(memsrc);
src_close(&memsrc);

return 0;
Expand Down
8 changes: 4 additions & 4 deletions src/lib/ffi-priv-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ struct rnp_symenc_handle_st {

struct rnp_ffi_st {
FILE * errs;
rnp_key_store_t * pubring;
rnp_key_store_t * secring;
rnp::KeyStore * pubring;
rnp::KeyStore * secring;
rnp_get_key_cb getkeycb;
void * getkeycb_ctx;
rnp_password_cb getpasscb;
void * getpasscb_ctx;
pgp_key_provider_t key_provider;
rnp::KeyProvider key_provider;
pgp_password_provider_t pass_provider;
rnp::SecurityContext context;

Expand Down Expand Up @@ -205,7 +205,7 @@ static_assert(RNP_LOCATOR_MAX_SIZE > MAX_ID_LENGTH, "Locator size mismatch.");
struct rnp_identifier_iterator_st {
rnp_ffi_t ffi;
pgp_key_search_type_t type;
rnp_key_store_t * store;
rnp::KeyStore * store;
std::list<pgp_key_t>::iterator *keyp;
unsigned uididx;
json_object * tbl;
Expand Down
11 changes: 5 additions & 6 deletions src/lib/generate-key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <string.h>

#include <rekey/rnp_key_store.h>
#include <librekey/key_store_pgp.h>
#include <librekey/key_store_g10.h>
#include <librepgp/stream-packet.h>
#include "crypto.h"
Expand Down Expand Up @@ -105,7 +104,7 @@ load_generated_g10_key(pgp_key_t * dst,
assert(pubkey);

// this would be better on the stack but the key store does not allow it
std::unique_ptr<rnp_key_store_t> key_store(new (std::nothrow) rnp_key_store_t(ctx));
std::unique_ptr<rnp::KeyStore> key_store(new (std::nothrow) rnp::KeyStore(ctx));
if (!key_store) {
return false;
}
Expand All @@ -124,12 +123,12 @@ load_generated_g10_key(pgp_key_t * dst,
// G10 needs the pubkey for copying some attributes (key version, creation time, etc)
key_ptrs.push_back(pubkey);

rnp::MemorySource memsrc(memdst.memory(), memdst.writeb(), false);
pgp_key_provider_t prov(rnp_key_provider_key_ptr_list, &key_ptrs);
if (!rnp_key_store_g10_from_src(key_store.get(), &memsrc.src(), &prov)) {
rnp::MemorySource memsrc(memdst.memory(), memdst.writeb(), false);
rnp::KeyProvider prov(rnp_key_provider_key_ptr_list, &key_ptrs);
if (!key_store.get()->load_g10(memsrc.src(), &prov)) {
return false;
}
if (rnp_key_store_get_key_count(key_store.get()) != 1) {
if (key_store.get()->key_count() != 1) {
return false;
}
// if a primary key is provided, it should match the sub with regards to type
Expand Down
Loading