diff --git a/include/rekey/rnp_key_store.h b/include/rekey/rnp_key_store.h index 04faabf75f..e6198d4661 100644 --- a/include/rekey/rnp_key_store.h +++ b/include/rekey/rnp_key_store.h @@ -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 (agc@netbsd.org), 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_ @@ -61,7 +57,15 @@ typedef enum pgp_sig_import_status_t { typedef std::unordered_map::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; @@ -72,78 +76,165 @@ typedef struct rnp_key_store_t { pgp_key_fp_map_t keybyfp; std::vector> 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_ */ diff --git a/src/fuzzing/keyring_g10.cpp b/src/fuzzing/keyring_g10.cpp index f2495a591d..58431a07e0 100644 --- a/src/fuzzing/keyring_g10.cpp +++ b/src/fuzzing/keyring_g10.cpp @@ -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 @@ -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; diff --git a/src/lib/ffi-priv-types.h b/src/lib/ffi-priv-types.h index 924343d744..87e536908e 100644 --- a/src/lib/ffi-priv-types.h +++ b/src/lib/ffi-priv-types.h @@ -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; @@ -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::iterator *keyp; unsigned uididx; json_object * tbl; diff --git a/src/lib/generate-key.cpp b/src/lib/generate-key.cpp index 52481f971b..c58629a6ee 100644 --- a/src/lib/generate-key.cpp +++ b/src/lib/generate-key.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include #include "crypto.h" @@ -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 key_store(new (std::nothrow) rnp_key_store_t(ctx)); + std::unique_ptr key_store(new (std::nothrow) rnp::KeyStore(ctx)); if (!key_store) { return false; } @@ -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 diff --git a/src/lib/key-provider.cpp b/src/lib/key-provider.cpp index 2a64b63329..dbc49be282 100644 --- a/src/lib/key-provider.cpp +++ b/src/lib/key-provider.cpp @@ -33,54 +33,31 @@ #include "utils.h" #include -bool -rnp_key_matches_search(const pgp_key_t *key, const pgp_key_search_t *search) -{ - if (!key) { - return false; - } - switch (search->type) { - case PGP_KEY_SEARCH_KEYID: - return (key->keyid() == search->by.keyid) || (search->by.keyid == pgp_key_id_t({})); - case PGP_KEY_SEARCH_FINGERPRINT: - return key->fp() == search->by.fingerprint; - case PGP_KEY_SEARCH_GRIP: - return key->grip() == search->by.grip; - case PGP_KEY_SEARCH_USERID: - if (key->has_uid(search->by.userid)) { - return true; - } - break; - default: - assert(false); - break; - } - return false; -} - +namespace rnp { pgp_key_t * -pgp_request_key(const pgp_key_provider_t *provider, const pgp_key_request_ctx_t *ctx) +KeyProvider::request_key(const pgp_key_request_ctx_t &ctx) const { - pgp_key_t *key = NULL; - if (!provider || !provider->callback || !ctx) { - return NULL; + pgp_key_t *key = nullptr; + if (!callback) { + return key; } - if (!(key = provider->callback(ctx, provider->userdata))) { - return NULL; + if (!(key = callback(&ctx, userdata))) { + return nullptr; } // confirm that the key actually matches the search criteria - if (!rnp_key_matches_search(key, &ctx->search) && key->is_secret() == ctx->secret) { - return NULL; + if (!key->matches(ctx.search) || (key->is_secret() != ctx.secret)) { + return nullptr; } return key; } +} // namespace rnp pgp_key_t * rnp_key_provider_key_ptr_list(const pgp_key_request_ctx_t *ctx, void *userdata) { std::vector *key_list = (std::vector *) userdata; for (auto key : *key_list) { - if (rnp_key_matches_search(key, &ctx->search) && (key->is_secret() == ctx->secret)) { + if (key->matches(ctx->search) && (key->is_secret() == ctx->secret)) { return key; } } @@ -90,11 +67,11 @@ rnp_key_provider_key_ptr_list(const pgp_key_request_ctx_t *ctx, void *userdata) pgp_key_t * rnp_key_provider_chained(const pgp_key_request_ctx_t *ctx, void *userdata) { - for (pgp_key_provider_t **pprovider = (pgp_key_provider_t **) userdata; + for (rnp::KeyProvider **pprovider = (rnp::KeyProvider **) userdata; pprovider && *pprovider; pprovider++) { - pgp_key_provider_t *provider = *pprovider; - pgp_key_t * key = NULL; + auto provider = *pprovider; + pgp_key_t *key = nullptr; if ((key = provider->callback(ctx, provider->userdata))) { return key; } @@ -105,10 +82,9 @@ rnp_key_provider_chained(const pgp_key_request_ctx_t *ctx, void *userdata) pgp_key_t * rnp_key_provider_store(const pgp_key_request_ctx_t *ctx, void *userdata) { - rnp_key_store_t *ks = (rnp_key_store_t *) userdata; + auto ks = (rnp::KeyStore *) userdata; - for (pgp_key_t *key = rnp_key_store_search(ks, &ctx->search, NULL); key; - key = rnp_key_store_search(ks, &ctx->search, key)) { + for (pgp_key_t *key = ks->search(ctx->search); key; key = ks->search(ctx->search, key)) { if (key->is_secret() == ctx->secret) { return key; } diff --git a/src/lib/key-provider.h b/src/lib/key-provider.h index 4d09e2f825..9ef96fb4b5 100644 --- a/src/lib/key-provider.h +++ b/src/lib/key-provider.h @@ -67,33 +67,23 @@ typedef struct pgp_key_request_ctx_t { typedef pgp_key_t *pgp_key_callback_t(const pgp_key_request_ctx_t *ctx, void *userdata); -typedef struct pgp_key_provider_t { +namespace rnp { +class KeyProvider { + public: pgp_key_callback_t *callback; void * userdata; - pgp_key_provider_t(pgp_key_callback_t *cb = NULL, void *ud = NULL) + KeyProvider(pgp_key_callback_t *cb = nullptr, void *ud = nullptr) : callback(cb), userdata(ud){}; -} pgp_key_provider_t; -/** checks if a key matches search criteria - * - * Note that this does not do any check on the type of key (public/secret), - * that is left up to the caller. - * - * @param key the key to check - * @param search the search criteria to check against - * @return true if the key satisfies the search criteria, false otherwise - **/ -bool rnp_key_matches_search(const pgp_key_t *key, const pgp_key_search_t *search); - -/** @brief request public or secret pgp key, according to information stored in ctx - * @param ctx information about the request - which operation requested the key, which search - * criteria should be used and whether secret or public key is needed - * @param key pointer to the key structure will be stored here on success - * @return a key pointer on success, or NULL if key was not found otherwise - **/ -pgp_key_t *pgp_request_key(const pgp_key_provider_t * provider, - const pgp_key_request_ctx_t *ctx); + /** @brief request public or secret pgp key, according to information stored in ctx + * @param ctx information about the request - which operation requested the key, which + *search criteria should be used and whether secret or public key is needed + * @return a key pointer on success, or nullptr if key was not found otherwise + **/ + pgp_key_t *request_key(const pgp_key_request_ctx_t &ctx) const; +}; +} // namespace rnp /** key provider callback that searches a list of pgp_key_t pointers * @@ -105,15 +95,15 @@ pgp_key_t *rnp_key_provider_key_ptr_list(const pgp_key_request_ctx_t *ctx, void /** key provider callback that searches a given store * * @param ctx - * @param userdata must be a pointer to rnp_key_store_t + * @param userdata must be a pointer to rnp::KeyStore */ pgp_key_t *rnp_key_provider_store(const pgp_key_request_ctx_t *ctx, void *userdata); /** key provider that calls other key providers * * @param ctx - * @param userdata must be an array pgp_key_provider_t pointers, - * ending with a NULL. + * @param userdata must be an array rnp::KeyProvider pointers, + * ending with a nullptr. */ pgp_key_t *rnp_key_provider_chained(const pgp_key_request_ctx_t *ctx, void *userdata); diff --git a/src/lib/logging.h b/src/lib/logging.h index 7335e57483..c0752c90db 100644 --- a/src/lib/logging.h +++ b/src/lib/logging.h @@ -76,7 +76,7 @@ class LogStop { break; \ } \ char keyid[PGP_KEY_ID_SIZE * 2 + 1] = {0}; \ - const pgp_key_id_t &id = key->keyid(); \ + const pgp_key_id_t &id = (key)->keyid(); \ rnp::hex_encode(id.data(), id.size(), keyid, sizeof(keyid), rnp::HEX_LOWERCASE); \ RNP_LOG(msg, keyid); \ } while (0) diff --git a/src/lib/pgp-key.cpp b/src/lib/pgp-key.cpp index aadd1054a4..4af79a2100 100644 --- a/src/lib/pgp-key.cpp +++ b/src/lib/pgp-key.cpp @@ -51,7 +51,6 @@ #include "pgp-key.h" #include "utils.h" -#include #include #include "crypto.h" #include "crypto/s2k.h" @@ -126,29 +125,6 @@ pgp_decrypt_seckey(const pgp_key_t & key, } } -pgp_key_t * -pgp_sig_get_signer(const pgp_subsig_t &sig, rnp_key_store_t *keyring, pgp_key_provider_t *prov) -{ - pgp_key_request_ctx_t ctx(PGP_OP_VERIFY, false, PGP_KEY_SEARCH_UNKNOWN); - /* if we have fingerprint let's check it */ - if (sig.sig.has_keyfp()) { - ctx.search.by.fingerprint = sig.sig.keyfp(); - ctx.search.type = PGP_KEY_SEARCH_FINGERPRINT; - } else if (sig.sig.has_keyid()) { - ctx.search.by.keyid = sig.sig.keyid(); - ctx.search.type = PGP_KEY_SEARCH_KEYID; - } else { - RNP_LOG("No way to search for the signer."); - return NULL; - } - - pgp_key_t *key = rnp_key_store_search(keyring, &ctx.search, NULL); - if (key || !prov) { - return key; - } - return pgp_request_key(prov, &ctx); -} - static const id_str_pair ss_rr_code_map[] = { {PGP_REVOCATION_NO_REASON, "No reason specified"}, {PGP_REVOCATION_SUPERSEDED, "Key is superseded"}, @@ -158,17 +134,6 @@ static const id_str_pair ss_rr_code_map[] = { {0x00, NULL}, }; -pgp_key_t * -pgp_key_get_subkey(const pgp_key_t *key, rnp_key_store_t *store, size_t idx) -{ - try { - return rnp_key_store_get_key_by_fpr(store, key->get_subkey_fp(idx)); - } catch (const std::exception &e) { - RNP_LOG("%s", e.what()); - return NULL; - } -} - pgp_key_flags_t pgp_pk_alg_capabilities(pgp_pubkey_alg_t alg) { @@ -469,12 +434,9 @@ pgp_subkey_set_expiration(pgp_key_t * sub, } pgp_key_t * -find_suitable_key(pgp_op_t op, - pgp_key_t * key, - pgp_key_provider_t *key_provider, - bool no_primary) +find_suitable_key(pgp_op_t op, pgp_key_t *key, rnp::KeyProvider *key_provider, bool no_primary) { - if (!key) { + if (!key || !key_provider) { return NULL; } bool secret = false; @@ -497,7 +459,7 @@ find_suitable_key(pgp_op_t op, pgp_key_request_ctx_t ctx(op, secret, PGP_KEY_SEARCH_FINGERPRINT); if (!no_primary && secret && key->is_public() && key->usable_for(op, true)) { ctx.search.by.fingerprint = key->fp(); - pgp_key_t *sec = pgp_request_key(key_provider, &ctx); + pgp_key_t *sec = key_provider->request_key(ctx); if (sec && sec->usable_for(op)) { return sec; } @@ -506,7 +468,7 @@ find_suitable_key(pgp_op_t op, pgp_key_t *subkey = NULL; for (auto &fp : key->subkey_fps()) { ctx.search.by.fingerprint = fp; - pgp_key_t *cur = pgp_request_key(key_provider, &ctx); + pgp_key_t *cur = key_provider->request_key(ctx); if (!cur || !cur->usable_for(op)) { continue; } @@ -806,7 +768,7 @@ pgp_key_t::pgp_key_t(const pgp_key_pkt_t &keypkt) : pkt_(keypkt) throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); } if (pgp_keyid(keyid_, pkt_) || pgp_fingerprint(fingerprint_, pkt_) || - !rnp_key_store_get_key_grip(&pkt_.material, grip_)) { + !pkt_.material.get_grip(grip_)) { throw rnp::rnp_exception(RNP_ERROR_GENERIC); } @@ -1716,7 +1678,7 @@ pgp_key_t::write(pgp_dest_t &dst) const } void -pgp_key_t::write_xfer(pgp_dest_t &dst, const rnp_key_store_t *keyring) const +pgp_key_t::write_xfer(pgp_dest_t &dst, const rnp::KeyStore *keyring) const { write(dst); if (dst.werr) { @@ -1730,7 +1692,7 @@ pgp_key_t::write_xfer(pgp_dest_t &dst, const rnp_key_store_t *keyring) const // Export subkeys for (auto &fp : subkey_fps_) { - const pgp_key_t *subkey = rnp_key_store_get_key_by_fpr(keyring, fp); + const pgp_key_t *subkey = keyring->get_key(fp); if (!subkey) { char fphex[PGP_MAX_FINGERPRINT_SIZE * 2 + 1] = {0}; rnp::hex_encode( @@ -1780,6 +1742,36 @@ pgp_key_t::write_autocrypt(pgp_dest_t &dst, pgp_key_t &sub, uint32_t uid) } } +std::vector +pgp_key_t::write_vec() const +{ + rnp::MemoryDest dst; + write(dst.dst()); + return dst.to_vector(); +} + +bool +pgp_key_t::matches(const pgp_key_search_t &search) const +{ + switch (search.type) { + case PGP_KEY_SEARCH_KEYID: + return (keyid() == search.by.keyid) || (search.by.keyid == pgp_key_id_t({})); + case PGP_KEY_SEARCH_FINGERPRINT: + return fp() == search.by.fingerprint; + case PGP_KEY_SEARCH_GRIP: + return grip() == search.by.grip; + case PGP_KEY_SEARCH_USERID: + if (has_uid(search.by.userid)) { + return true; + } + break; + default: + assert(false); + break; + } + return false; +} + /* look only for primary userids */ #define PGP_UID_PRIMARY ((uint32_t) -2) /* look for any uid, except PGP_UID_NONE) */ @@ -2177,7 +2169,7 @@ pgp_key_t::validate_self_signatures(pgp_key_t &primary, const rnp::SecurityConte } void -pgp_key_t::validate_primary(rnp_key_store_t &keyring) +pgp_key_t::validate_primary(rnp::KeyStore &keyring) { /* validate signatures if needed */ validate_self_signatures(keyring.secctx); @@ -2231,7 +2223,7 @@ pgp_key_t::validate_primary(rnp_key_store_t &keyring) /* let's check whether key has at least one valid subkey binding */ for (size_t i = 0; i < subkey_count(); i++) { - pgp_key_t *sub = pgp_key_get_subkey(this, &keyring, i); + pgp_key_t *sub = keyring.get_subkey(*this, i); if (!sub) { continue; } @@ -2288,7 +2280,7 @@ pgp_key_t::validate_subkey(pgp_key_t *primary, const rnp::SecurityContext &ctx) } void -pgp_key_t::validate(rnp_key_store_t &keyring) +pgp_key_t::validate(rnp::KeyStore &keyring) { validity_.reset(); if (!is_subkey()) { @@ -2296,17 +2288,17 @@ pgp_key_t::validate(rnp_key_store_t &keyring) } else { pgp_key_t *primary = NULL; if (has_primary_fp()) { - primary = rnp_key_store_get_key_by_fpr(&keyring, primary_fp()); + primary = keyring.get_key(primary_fp()); } validate_subkey(primary, keyring.secctx); } } void -pgp_key_t::revalidate(rnp_key_store_t &keyring) +pgp_key_t::revalidate(rnp::KeyStore &keyring) { if (is_subkey()) { - pgp_key_t *primary = rnp_key_store_get_primary_key(&keyring, this); + pgp_key_t *primary = keyring.primary_key(*this); if (primary) { primary->revalidate(keyring); } else { @@ -2321,7 +2313,7 @@ pgp_key_t::revalidate(rnp_key_store_t &keyring) } /* validate/re-validate all subkeys as well */ for (auto &fp : subkey_fps_) { - pgp_key_t *subkey = rnp_key_store_get_key_by_fpr(&keyring, fp); + pgp_key_t *subkey = keyring.get_key(fp); if (subkey) { subkey->validate_subkey(this, keyring.secctx); if (!subkey->refresh_data(this, keyring.secctx)) { @@ -2912,3 +2904,178 @@ pgp_key_material_t::valid() const { return validity.validated && validity.valid; } + +namespace { +void +grip_hash_mpi(rnp::Hash &hash, const pgp_mpi_t &val, const char name, bool lzero = true) +{ + size_t len = mpi_bytes(&val); + size_t idx = 0; + for (idx = 0; (idx < len) && !val.mpi[idx]; idx++) + ; + + if (name) { + size_t hlen = idx >= len ? 0 : len - idx; + if ((len > idx) && lzero && (val.mpi[idx] & 0x80)) { + hlen++; + } + + char buf[20] = {0}; + snprintf(buf, sizeof(buf), "(1:%c%zu:", name, hlen); + hash.add(buf, strlen(buf)); + } + + if (idx < len) { + /* gcrypt prepends mpis with zero if higher bit is set */ + if (lzero && (val.mpi[idx] & 0x80)) { + uint8_t zero = 0; + hash.add(&zero, 1); + } + hash.add(val.mpi + idx, len - idx); + } + if (name) { + hash.add(")", 1); + } +} + +void +grip_hash_ecc_hex(rnp::Hash &hash, const char *hex, char name) +{ + pgp_mpi_t mpi = {}; + mpi.len = rnp::hex_decode(hex, mpi.mpi, sizeof(mpi.mpi)); + if (!mpi.len) { + RNP_LOG("wrong hex mpi"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + + /* libgcrypt doesn't add leading zero when hashes ecc mpis */ + return grip_hash_mpi(hash, mpi, name, false); +} + +void +grip_hash_ec(rnp::Hash &hash, const pgp_ec_key_t &key) +{ + const ec_curve_desc_t *desc = get_curve_desc(key.curve); + if (!desc) { + RNP_LOG("unknown curve %d", (int) key.curve); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + + /* build uncompressed point from gx and gy */ + pgp_mpi_t g = {}; + g.mpi[0] = 0x04; + g.len = 1; + size_t len = rnp::hex_decode(desc->gx, g.mpi + g.len, sizeof(g.mpi) - g.len); + if (!len) { + RNP_LOG("wrong x mpi"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + g.len += len; + len = rnp::hex_decode(desc->gy, g.mpi + g.len, sizeof(g.mpi) - g.len); + if (!len) { + RNP_LOG("wrong y mpi"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + g.len += len; + + /* p, a, b, g, n, q */ + grip_hash_ecc_hex(hash, desc->p, 'p'); + grip_hash_ecc_hex(hash, desc->a, 'a'); + grip_hash_ecc_hex(hash, desc->b, 'b'); + grip_hash_mpi(hash, g, 'g', false); + grip_hash_ecc_hex(hash, desc->n, 'n'); + + if ((key.curve == PGP_CURVE_ED25519) || (key.curve == PGP_CURVE_25519)) { + if (g.len < 1) { + RNP_LOG("wrong 25519 p"); + throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } + g.len = key.p.len - 1; + memcpy(g.mpi, key.p.mpi + 1, g.len); + grip_hash_mpi(hash, g, 'q', false); + } else { + grip_hash_mpi(hash, key.p, 'q', false); + } +} +} // namespace + +/* keygrip is subjectKeyHash from pkcs#15 for RSA. */ +bool +pgp_key_material_t::get_grip(pgp_key_grip_t &grip) const +{ + try { + auto hash = rnp::Hash::create(PGP_HASH_SHA1); + switch (alg) { + case PGP_PKA_RSA: + case PGP_PKA_RSA_SIGN_ONLY: + case PGP_PKA_RSA_ENCRYPT_ONLY: + grip_hash_mpi(*hash, rsa.n, '\0'); + break; + case PGP_PKA_DSA: + grip_hash_mpi(*hash, dsa.p, 'p'); + grip_hash_mpi(*hash, dsa.q, 'q'); + grip_hash_mpi(*hash, dsa.g, 'g'); + grip_hash_mpi(*hash, dsa.y, 'y'); + break; + case PGP_PKA_ELGAMAL: + case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: + grip_hash_mpi(*hash, eg.p, 'p'); + grip_hash_mpi(*hash, eg.g, 'g'); + grip_hash_mpi(*hash, eg.y, 'y'); + break; + case PGP_PKA_ECDH: + case PGP_PKA_ECDSA: + case PGP_PKA_EDDSA: + case PGP_PKA_SM2: + grip_hash_ec(*hash, ec); + break; +#if defined(ENABLE_CRYPTO_REFRESH) + // TODO: if GnuPG would ever support v6, check whether this works correctly. + case PGP_PKA_ED25519: + hash->add(key->ed25519.pub); + break; + case PGP_PKA_X25519: + hash->add(key->x25519.pub); + break; +#endif +#if defined(ENABLE_PQC) + case PGP_PKA_KYBER768_X25519: + FALLTHROUGH_STATEMENT; + // TODO add case PGP_PKA_KYBER1024_X448: FALLTHROUGH_STATEMENT; + case PGP_PKA_KYBER768_P256: + FALLTHROUGH_STATEMENT; + case PGP_PKA_KYBER1024_P384: + FALLTHROUGH_STATEMENT; + case PGP_PKA_KYBER768_BP256: + FALLTHROUGH_STATEMENT; + case PGP_PKA_KYBER1024_BP384: + hash->add(key->kyber_ecdh.pub.get_encoded()); + break; + case PGP_PKA_DILITHIUM3_ED25519: + FALLTHROUGH_STATEMENT; + // TODO: add case PGP_PKA_DILITHIUM5_ED448: FALLTHROUGH_STATEMENT; + case PGP_PKA_DILITHIUM3_P256: + FALLTHROUGH_STATEMENT; + case PGP_PKA_DILITHIUM5_P384: + FALLTHROUGH_STATEMENT; + case PGP_PKA_DILITHIUM3_BP256: + FALLTHROUGH_STATEMENT; + case PGP_PKA_DILITHIUM5_BP384: + hash->add(key->dilithium_exdsa.pub.get_encoded()); + break; + case PGP_PKA_SPHINCSPLUS_SHA2: + FALLTHROUGH_STATEMENT; + case PGP_PKA_SPHINCSPLUS_SHAKE: + hash->add(key->sphincsplus.pub.get_encoded()); + break; +#endif + default: + RNP_LOG("unsupported public-key algorithm %d", (int) alg); + return false; + } + return hash->finish(grip.data()) == grip.size(); + } catch (const std::exception &e) { + RNP_LOG("Grip calculation failed: %s", e.what()); + return false; + } +} diff --git a/src/lib/pgp-key.h b/src/lib/pgp-key.h index 6e82d963bf..c65d7b5d19 100644 --- a/src/lib/pgp-key.h +++ b/src/lib/pgp-key.h @@ -130,7 +130,9 @@ typedef struct pgp_userid_t { #define PGP_UID_NONE ((uint32_t) -1) -typedef struct rnp_key_store_t rnp_key_store_t; +namespace rnp { +class KeyStore; +} /* describes a user's key */ struct pgp_key_t { @@ -158,7 +160,7 @@ struct pgp_key_t { uint64_t valid_till_{}; /* date till which key is/was valid */ pgp_subsig_t *latest_uid_selfcert(uint32_t uid); - void validate_primary(rnp_key_store_t &keyring); + void validate_primary(rnp::KeyStore &keyring); void merge_validity(const pgp_validity_t &src); uint64_t valid_till_common(bool expiry) const; bool write_sec_pgp(pgp_dest_t & dst, @@ -331,7 +333,7 @@ struct pgp_key_t { * @param keyring keyring, which will be searched for subkeys. Pass NULL to skip subkeys. * @return void, but error may be checked via dst.werr */ - void write_xfer(pgp_dest_t &dst, const rnp_key_store_t *keyring = NULL) const; + void write_xfer(pgp_dest_t &dst, const rnp::KeyStore *keyring = NULL) const; /** * @brief Export key with subkey as it is required by Autocrypt (5-packet sequence: key, * uid, sig, subkey, sig). @@ -342,7 +344,19 @@ struct pgp_key_t { * @return true on success or false otherwise */ bool write_autocrypt(pgp_dest_t &dst, pgp_key_t &sub, uint32_t uid); - + /** + * @brief Write key to vector. + */ + std::vector write_vec() const; + /** checks if a key matches search criteria + * + * Note that this does not do any check on the type of key (public/secret), + * that is left up to the caller. + * + * @param search the search criteria to check against + * @return true if the key satisfies the search criteria, false otherwise + **/ + bool matches(const pgp_key_search_t &search) const; /** * @brief Get the latest valid self-signature with information about the primary key for * the specified uid (including the special cases). It could be userid certification @@ -448,9 +462,9 @@ struct pgp_key_t { void validate_self_signatures(const rnp::SecurityContext &ctx); void validate_self_signatures(pgp_key_t &primary, const rnp::SecurityContext &ctx); - void validate(rnp_key_store_t &keyring); + void validate(rnp::KeyStore &keyring); void validate_subkey(pgp_key_t *primary, const rnp::SecurityContext &ctx); - void revalidate(rnp_key_store_t &keyring); + void revalidate(rnp::KeyStore &keyring); void mark_valid(); /** * @brief Fill common signature parameters, assuming that current key is a signing one. @@ -604,28 +618,6 @@ pgp_key_pkt_t *pgp_decrypt_seckey(const pgp_key_t &, const pgp_password_provider_t &, const pgp_password_ctx_t &); -/** - * @brief Get the signer's key for signature - * - * @param sig signature - * @param keyring keyring to search for the key. May be NULL. - * @param prov key provider to request needed key, may be NULL. - * @return pointer to the key or NULL if key is not found. - */ -pgp_key_t *pgp_sig_get_signer(const pgp_subsig_t &sig, - rnp_key_store_t * keyring, - pgp_key_provider_t *prov); - -/** - * @brief Get the key's subkey by its index - * - * @param key primary key - * @param store key store which will be searched for subkeys - * @param idx index of the subkey - * @return pointer to the subkey or NULL if subkey not found - */ -pgp_key_t *pgp_key_get_subkey(const pgp_key_t *key, rnp_key_store_t *store, size_t idx); - pgp_key_flags_t pgp_pk_alg_capabilities(pgp_pubkey_alg_t alg); bool pgp_key_set_expiration(pgp_key_t * key, @@ -657,10 +649,10 @@ bool pgp_subkey_set_expiration(pgp_key_t * sub, * @returns key or last created subkey with desired usage flag * set or NULL if not found */ -pgp_key_t *find_suitable_key(pgp_op_t op, - pgp_key_t * key, - pgp_key_provider_t *key_provider, - bool no_primary = false); +pgp_key_t *find_suitable_key(pgp_op_t op, + pgp_key_t * key, + rnp::KeyProvider *key_provider, + bool no_primary = false); /* * Picks up hash algorithm according to domain parameters set diff --git a/src/lib/rnp.cpp b/src/lib/rnp.cpp index 11ea7ec52e..9b90a61636 100644 --- a/src/lib/rnp.cpp +++ b/src/lib/rnp.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -109,8 +108,8 @@ find_key(rnp_ffi_t ffi, bool try_key_provider, pgp_key_t * after = NULL) { - pgp_key_t *key = - rnp_key_store_search(secret ? ffi->secring : ffi->pubring, &search, after); + auto ks = secret ? ffi->secring : ffi->pubring; + pgp_key_t *key = ks->search(search, after); if (!key && try_key_provider && call_key_callback(ffi, search, secret)) { // recurse and try the store search above once more return find_key(ffi, search, secret, false, after); @@ -587,8 +586,8 @@ ffi_exception(FILE *fp, const char *func, const char *msg, uint32_t ret = RNP_ER rnp_ffi_st::rnp_ffi_st(pgp_key_store_format_t pub_fmt, pgp_key_store_format_t sec_fmt) { errs = stderr; - pubring = new rnp_key_store_t(pub_fmt, "", context); - secring = new rnp_key_store_t(sec_fmt, "", context); + pubring = new rnp::KeyStore(pub_fmt, "", context); + secring = new rnp::KeyStore(sec_fmt, "", context); getkeycb = NULL; getkeycb_ctx = NULL; getpasscb = NULL; @@ -1407,30 +1406,30 @@ try { FFI_GUARD static rnp_result_t -load_keys_from_input(rnp_ffi_t ffi, rnp_input_t input, rnp_key_store_t *store) +load_keys_from_input(rnp_ffi_t ffi, rnp_input_t input, rnp::KeyStore *store) { - pgp_key_provider_t chained(rnp_key_provider_store, store); - const pgp_key_provider_t *key_providers[] = {&chained, &ffi->key_provider, NULL}; - const pgp_key_provider_t key_provider(rnp_key_provider_chained, key_providers); + rnp::KeyProvider chained(rnp_key_provider_store, store); + const rnp::KeyProvider *key_providers[] = {&chained, &ffi->key_provider, NULL}; + const rnp::KeyProvider key_provider(rnp_key_provider_chained, key_providers); if (!input->src_directory.empty()) { // load the keys store->path = input->src_directory; - if (!rnp_key_store_load_from_path(store, &key_provider)) { + if (!store->load(&key_provider)) { return RNP_ERROR_BAD_FORMAT; } return RNP_SUCCESS; } // load the keys - if (!rnp_key_store_load_from_src(store, &input->src, &key_provider)) { + if (!store->load(input->src, &key_provider)) { return RNP_ERROR_BAD_FORMAT; } return RNP_SUCCESS; } static bool -key_needs_conversion(const pgp_key_t *key, const rnp_key_store_t *store) +key_needs_conversion(const pgp_key_t *key, const rnp::KeyStore *store) { pgp_key_store_format_t key_format = key->format; pgp_key_store_format_t store_format = store->format; @@ -1457,10 +1456,10 @@ do_load_keys(rnp_ffi_t ffi, key_type_t key_type) { // create a temporary key store to hold the keys - std::unique_ptr tmp_store; + std::unique_ptr tmp_store; try { tmp_store = - std::unique_ptr(new rnp_key_store_t(format, "", ffi->context)); + std::unique_ptr(new rnp::KeyStore(format, "", ffi->context)); } catch (const std::invalid_argument &e) { FFI_LOG(ffi, "Failed to create key store of format: %d", (int) format); return RNP_ERROR_BAD_PARAMETERS; @@ -1481,7 +1480,7 @@ do_load_keys(rnp_ffi_t ffi, return RNP_ERROR_NOT_IMPLEMENTED; } - if (!rnp_key_store_add_key(ffi->secring, &key)) { + if (!ffi->secring->add_key(key)) { FFI_LOG(ffi, "Failed to add secret key"); return RNP_ERROR_GENERIC; } @@ -1512,7 +1511,7 @@ do_load_keys(rnp_ffi_t ffi, return RNP_ERROR_NOT_IMPLEMENTED; } - if (!rnp_key_store_add_key(ffi->pubring, &keycp)) { + if (!ffi->pubring->add_key(keycp)) { FFI_LOG(ffi, "Failed to add public key"); return RNP_ERROR_GENERIC; } @@ -1578,10 +1577,10 @@ try { } if (flags & RNP_KEY_UNLOAD_PUBLIC) { - rnp_key_store_clear(ffi->pubring); + ffi->pubring->clear(); } if (flags & RNP_KEY_UNLOAD_SECRET) { - rnp_key_store_clear(ffi->secring); + ffi->secring->clear(); } return RNP_SUCCESS; @@ -1685,8 +1684,8 @@ try { return RNP_ERROR_BAD_PARAMETERS; } - rnp_result_t ret = RNP_ERROR_GENERIC; - rnp_key_store_t tmp_store(PGP_KEY_STORE_GPG, "", ffi->context); + rnp_result_t ret = RNP_ERROR_GENERIC; + rnp::KeyStore tmp_store(PGP_KEY_STORE_GPG, "", ffi->context); /* check whether input is base64 */ if (base64 && is_base64_source(input->src)) { @@ -1708,12 +1707,12 @@ try { FFI_LOG(ffi, "Failed to init/check dearmor."); return ret; } - ret = rnp_key_store_pgp_read_key_from_src(tmp_store, input->src, skipbad); + ret = tmp_store.load_pgp_key(input->src, skipbad); if (ret) { return ret; } } else { - ret = rnp_key_store_pgp_read_from_src(&tmp_store, &input->src, skipbad); + ret = tmp_store.load_pgp(input->src, skipbad); if (ret) { return ret; } @@ -1737,17 +1736,17 @@ try { continue; } // if we got here then we add public key itself or public part of the secret key - if (!rnp_key_store_import_key(ffi->pubring, &key, true, &pub_status)) { + if (!ffi->pubring->import_key(key, true, &pub_status)) { return RNP_ERROR_BAD_PARAMETERS; } // import secret key part if available and requested if (sec && key.is_secret()) { - if (!rnp_key_store_import_key(ffi->secring, &key, false, &sec_status)) { + if (!ffi->secring->import_key(key, false, &sec_status)) { return RNP_ERROR_BAD_PARAMETERS; } // add uids, certifications and other stuff from the public key if any - pgp_key_t *expub = rnp_key_store_get_key_by_fpr(ffi->pubring, key.fp()); - if (expub && !rnp_key_store_import_key(ffi->secring, expub, true, NULL)) { + pgp_key_t *expub = ffi->pubring->get_key(key.fp()); + if (expub && !ffi->secring->import_key(*expub, true)) { return RNP_ERROR_BAD_PARAMETERS; } } @@ -1845,8 +1844,8 @@ try { for (auto &sig : sigs) { pgp_sig_import_status_t pub_status = PGP_SIG_IMPORT_STATUS_UNKNOWN; pgp_sig_import_status_t sec_status = PGP_SIG_IMPORT_STATUS_UNKNOWN; - pgp_key_t *pkey = rnp_key_store_import_signature(ffi->pubring, &sig, &pub_status); - pgp_key_t *skey = rnp_key_store_import_signature(ffi->secring, &sig, &sec_status); + pgp_key_t * pkey = ffi->pubring->import_signature(sig, &pub_status); + pgp_key_t * skey = ffi->secring->import_signature(sig, &sec_status); sigret = add_sig_status(jsosigs, pkey ? pkey : skey, pub_status, sec_status); if (sigret) { return sigret; @@ -1868,10 +1867,10 @@ try { FFI_GUARD static bool -copy_store_keys(rnp_ffi_t ffi, rnp_key_store_t *dest, rnp_key_store_t *src) +copy_store_keys(rnp_ffi_t ffi, rnp::KeyStore *dest, rnp::KeyStore *src) { for (auto &key : src->keys) { - if (!rnp_key_store_add_key(dest, &key)) { + if (!dest->add_key(key)) { FFI_LOG(ffi, "failed to add key to the store"); return false; } @@ -1886,9 +1885,9 @@ do_save_keys(rnp_ffi_t ffi, key_type_t key_type) { // create a temporary key store to hold the keys - rnp_key_store_t *tmp_store = NULL; + rnp::KeyStore *tmp_store = nullptr; try { - tmp_store = new rnp_key_store_t(format, "", ffi->context); + tmp_store = new rnp::KeyStore(format, "", ffi->context); } catch (const std::invalid_argument &e) { FFI_LOG(ffi, "Failed to create key store of format: %d", (int) format); return RNP_ERROR_BAD_PARAMETERS; @@ -1896,7 +1895,7 @@ do_save_keys(rnp_ffi_t ffi, FFI_LOG(ffi, "%s", e.what()); return RNP_ERROR_OUT_OF_MEMORY; } - std::unique_ptr tmp_store_ptr(tmp_store); + std::unique_ptr tmp_store_ptr(tmp_store); // include the public keys, if desired if (key_type == KEY_TYPE_PUBLIC || key_type == KEY_TYPE_ANY) { if (!copy_store_keys(ffi, tmp_store, ffi->pubring)) { @@ -1919,12 +1918,12 @@ do_save_keys(rnp_ffi_t ffi, // write if (output->dst_directory) { tmp_store->path = output->dst_directory; - if (!rnp_key_store_write_to_path(tmp_store)) { + if (!tmp_store->write()) { return RNP_ERROR_WRITE; } return RNP_SUCCESS; } else { - if (!rnp_key_store_write_to_dst(tmp_store, &output->dst)) { + if (!tmp_store->write(output->dst)) { return RNP_ERROR_WRITE; } dst_flush(&output->dst); @@ -1965,7 +1964,7 @@ try { if (!ffi || !count) { return RNP_ERROR_NULL_POINTER; } - *count = rnp_key_store_get_key_count(ffi->pubring); + *count = ffi->pubring->key_count(); return RNP_SUCCESS; } FFI_GUARD @@ -1976,7 +1975,7 @@ try { if (!ffi || !count) { return RNP_ERROR_NULL_POINTER; } - *count = rnp_key_store_get_key_count(ffi->secring); + *count = ffi->secring->key_count(); return RNP_SUCCESS; } FFI_GUARD @@ -2791,10 +2790,9 @@ static pgp_write_handler_t pgp_write_handler(pgp_password_provider_t *pass_provider, rnp_ctx_t * rnpctx, void * param, - pgp_key_provider_t * key_provider) + rnp::KeyProvider * key_provider) { - pgp_write_handler_t handler; - memset(&handler, 0, sizeof(handler)); + pgp_write_handler_t handler{}; handler.password_provider = pass_provider; handler.ctx = rnpctx; handler.param = param; @@ -3344,7 +3342,7 @@ try { handler.password_provider = &op->ffi->pass_provider; rnp_decryption_kp_param_t kparam(op); - pgp_key_provider_t kprov = {ffi_decrypt_key_provider, &kparam}; + rnp::KeyProvider kprov(ffi_decrypt_key_provider, &kparam); handler.key_provider = &kprov; handler.on_signatures = rnp_op_verify_on_signatures; @@ -3707,8 +3705,8 @@ try { search.by.keyid = sig->sig_pkt.keyid(); // search the stores - pgp_key_t *pub = rnp_key_store_search(ffi->pubring, &search, NULL); - pgp_key_t *sec = rnp_key_store_search(ffi->secring, &search, NULL); + pgp_key_t *pub = ffi->pubring->search(search); + pgp_key_t *sec = ffi->secring->search(search); if (!pub && !sec) { return RNP_ERROR_KEY_NOT_FOUND; } @@ -3878,9 +3876,9 @@ rnp_locate_key_int(rnp_ffi_t ffi, bool require_secret = false) { // search pubring - pgp_key_t *pub = rnp_key_store_search(ffi->pubring, &locator, NULL); + pgp_key_t *pub = ffi->pubring->search(locator); // search secring - pgp_key_t *sec = rnp_key_store_search(ffi->secring, &locator, NULL); + pgp_key_t *sec = ffi->secring->search(locator); if (require_secret && !sec) { *handle = NULL; @@ -3941,9 +3939,9 @@ try { } // handle flags - bool armored = extract_flag(flags, RNP_KEY_EXPORT_ARMORED); - pgp_key_t * key = NULL; - rnp_key_store_t *store = NULL; + bool armored = extract_flag(flags, RNP_KEY_EXPORT_ARMORED); + pgp_key_t * key = NULL; + rnp::KeyStore *store = nullptr; if (flags & RNP_KEY_EXPORT_PUBLIC) { extract_flag(flags, RNP_KEY_EXPORT_PUBLIC); key = get_key_require_public(handle); @@ -3993,7 +3991,7 @@ try { return RNP_ERROR_BAD_PARAMETERS; } // subkey, write the primary + this subkey only - pgp_key_t *primary = rnp_key_store_get_primary_key(store, key); + pgp_key_t *primary = store->primary_key(*key); if (!primary) { // shouldn't happen return RNP_ERROR_GENERIC; @@ -4086,7 +4084,7 @@ rnp_key_get_revoker(rnp_key_handle_t key) return NULL; } if (exkey->is_subkey()) { - return rnp_key_store_get_primary_key(key->ffi->secring, exkey); + return key->ffi->secring->primary_key(*exkey); } // TODO: search through revocation key subpackets as well return get_key_require_secret(key); @@ -4219,10 +4217,10 @@ try { pgp_sig_import_status_t pub_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY; pgp_sig_import_status_t sec_status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY; if (key->pub) { - pub_status = rnp_key_store_import_key_signature(key->ffi->pubring, key->pub, &sig); + pub_status = key->ffi->pubring->import_signature(*key->pub, sig); } if (key->sec) { - sec_status = rnp_key_store_import_key_signature(key->ffi->secring, key->sec, &sig); + sec_status = key->ffi->secring->import_signature(*key->sec, sig); } if ((pub_status == PGP_SIG_IMPORT_STATUS_UNKNOWN) || @@ -4296,7 +4294,7 @@ try { if (!key->ffi->pubring || !key->pub) { return RNP_ERROR_BAD_PARAMETERS; } - if (!rnp_key_store_remove_key(key->ffi->pubring, key->pub, sub)) { + if (!key->ffi->pubring->remove_key(*key->pub, sub)) { return RNP_ERROR_KEY_NOT_FOUND; } key->pub = NULL; @@ -4305,7 +4303,7 @@ try { if (!key->ffi->secring || !key->sec) { return RNP_ERROR_BAD_PARAMETERS; } - if (!rnp_key_store_remove_key(key->ffi->secring, key->sec, sub)) { + if (!key->ffi->secring->remove_key(*key->sec, sub)) { return RNP_ERROR_KEY_NOT_FOUND; } key->sec = NULL; @@ -4359,13 +4357,13 @@ signature_needs_removal(rnp_ffi_t ffi, const pgp_key_t &key, pgp_subsig_t &sig, return true; } if (nonself && key.is_subkey()) { - pgp_key_t *primary = rnp_key_store_get_primary_key(ffi->pubring, &key); + pgp_key_t *primary = ffi->pubring->primary_key(key); if (primary && !primary->is_signer(sig)) { return true; } } /* unknown signer */ - pgp_key_t *signer = pgp_sig_get_signer(sig, ffi->pubring, &ffi->key_provider); + pgp_key_t *signer = ffi->pubring->get_signer(sig.sig, &ffi->key_provider); if (!signer && (flags & RNP_KEY_SIGNATURE_UNKNOWN_KEY)) { return true; } @@ -4444,12 +4442,12 @@ try { /* process subkeys */ for (size_t idx = 0; key->is_primary() && (idx < key->subkey_count()); idx++) { - pgp_key_t *sub = pgp_key_get_subkey(key, handle->ffi->pubring, idx); + pgp_key_t *sub = handle->ffi->pubring->get_subkey(*key, idx); if (!sub) { FFI_LOG(handle->ffi, "Failed to get subkey at idx %zu.", idx); continue; } - pgp_key_t *subsec = rnp_key_store_get_key_by_fpr(handle->ffi->secring, sub->fp()); + pgp_key_t *subsec = handle->ffi->secring->get_key(sub->fp()); remove_key_signatures(handle->ffi, *sub, subsec, flags, sigcb, app_ctx); } /* revalidate key/subkey */ @@ -4876,14 +4874,14 @@ gen_json_primary_key(rnp_ffi_t ffi, if (!pgp_generate_primary_key(desc, true, sec, pub, ffi->secring->format)) { return RNP_ERROR_GENERIC; } - if (!rnp_key_store_add_key(ffi->pubring, &pub)) { + if (!ffi->pubring->add_key(pub)) { return RNP_ERROR_OUT_OF_MEMORY; } /* encrypt secret key if specified */ if (protect && prot.symm_alg && !sec.protect(prot, ffi->pass_provider, ffi->context)) { return RNP_ERROR_BAD_PARAMETERS; } - if (!rnp_key_store_add_key(ffi->secring, &sec)) { + if (!ffi->secring->add_key(sec)) { return RNP_ERROR_OUT_OF_MEMORY; } fp = pub.fp(); @@ -4921,14 +4919,14 @@ gen_json_subkey(rnp_ffi_t ffi, ffi->secring->format)) { return RNP_ERROR_GENERIC; } - if (!rnp_key_store_add_key(ffi->pubring, &pub)) { + if (!ffi->pubring->add_key(pub)) { return RNP_ERROR_OUT_OF_MEMORY; } /* encrypt subkey if specified */ if (prot.symm_alg && !sec.protect(prot, ffi->pass_provider, ffi->context)) { return RNP_ERROR_BAD_PARAMETERS; } - if (!rnp_key_store_add_key(ffi->secring, &sec)) { + if (!ffi->secring->add_key(sec)) { return RNP_ERROR_OUT_OF_MEMORY; } fp = pub.fp(); @@ -4994,14 +4992,14 @@ try { if (ret) { return ret; } - prim_pub = rnp_key_store_get_key_by_fpr(ffi->pubring, fp); + prim_pub = ffi->pubring->get_key(fp); if (!jsosub) { if (!gen_json_grips(results, prim_pub, NULL)) { return RNP_ERROR_OUT_OF_MEMORY; } return RNP_SUCCESS; } - prim_sec = rnp_key_store_get_key_by_fpr(ffi->secring, fp); + prim_sec = ffi->secring->get_key(fp); } else { /* generate subkey only - find primary key via JSON params */ json_object *jsoparent = NULL; @@ -5029,8 +5027,8 @@ try { return tmpret; } - prim_pub = rnp_key_store_search(ffi->pubring, &locator, NULL); - prim_sec = rnp_key_store_search(ffi->secring, &locator, NULL); + prim_pub = ffi->pubring->search(locator); + prim_sec = ffi->secring->search(locator); if (!prim_sec || !prim_pub) { return RNP_ERROR_KEY_NOT_FOUND; } @@ -5042,20 +5040,20 @@ try { if (ret) { if (jsoprimary) { /* do not leave generated primary key in keyring */ - rnp_key_store_remove_key(ffi->pubring, prim_pub, false); - rnp_key_store_remove_key(ffi->secring, prim_sec, false); + ffi->pubring->remove_key(*prim_pub); + ffi->secring->remove_key(*prim_sec); } return ret; } /* Protect the primary key now */ if (prim_prot.symm_alg && !prim_sec->protect(prim_prot, ffi->pass_provider, ffi->context)) { - rnp_key_store_remove_key(ffi->pubring, prim_pub, true); - rnp_key_store_remove_key(ffi->secring, prim_sec, true); + ffi->pubring->remove_key(*prim_pub); + ffi->secring->remove_key(*prim_sec); return RNP_ERROR_BAD_PARAMETERS; } - pgp_key_t *sub_pub = rnp_key_store_get_key_by_fpr(ffi->pubring, fp); + pgp_key_t *sub_pub = ffi->pubring->get_key(fp); bool res = gen_json_grips(results, jsoprimary ? prim_pub : NULL, sub_pub); return res ? RNP_SUCCESS : RNP_ERROR_OUT_OF_MEMORY; } @@ -5781,7 +5779,7 @@ try { } /* add public key part to the keyring */ - if (!(op->gen_pub = rnp_key_store_add_key(op->ffi->pubring, &pub))) { + if (!(op->gen_pub = op->ffi->pubring->add_key(pub))) { ret = RNP_ERROR_OUT_OF_MEMORY; goto done; } @@ -5799,7 +5797,7 @@ try { } /* add secret key to the keyring */ - if (!(op->gen_sec = rnp_key_store_add_key(op->ffi->secring, &sec))) { + if (!(op->gen_sec = op->ffi->secring->add_key(sec))) { ret = RNP_ERROR_OUT_OF_MEMORY; goto done; } @@ -5807,11 +5805,11 @@ try { done: op->password.clear(); if (ret && op->gen_pub) { - rnp_key_store_remove_key(op->ffi->pubring, op->gen_pub, false); + op->ffi->pubring->remove_key(*op->gen_pub); op->gen_pub = NULL; } if (ret && op->gen_sec) { - rnp_key_store_remove_key(op->ffi->secring, op->gen_sec, false); + op->ffi->secring->remove_key(*op->gen_sec); op->gen_sec = NULL; } return ret; @@ -5880,7 +5878,7 @@ get_key_require_public(rnp_key_handle_t handle) // try fingerprint request.search.type = PGP_KEY_SEARCH_FINGERPRINT; request.search.by.fingerprint = handle->sec->fp(); - handle->pub = pgp_request_key(&handle->ffi->key_provider, &request); + handle->pub = handle->ffi->key_provider.request_key(request); if (handle->pub) { return handle->pub; } @@ -5888,7 +5886,7 @@ get_key_require_public(rnp_key_handle_t handle) // try keyid request.search.type = PGP_KEY_SEARCH_KEYID; request.search.by.keyid = handle->sec->keyid(); - handle->pub = pgp_request_key(&handle->ffi->key_provider, &request); + handle->pub = handle->ffi->key_provider.request_key(request); } return handle->pub; } @@ -5910,7 +5908,7 @@ get_key_require_secret(rnp_key_handle_t handle) // try fingerprint request.search.type = PGP_KEY_SEARCH_FINGERPRINT; request.search.by.fingerprint = handle->pub->fp(); - handle->sec = pgp_request_key(&handle->ffi->key_provider, &request); + handle->sec = handle->ffi->key_provider.request_key(request); if (handle->sec) { return handle->sec; } @@ -5918,7 +5916,7 @@ get_key_require_secret(rnp_key_handle_t handle) // try keyid request.search.type = PGP_KEY_SEARCH_KEYID; request.search.by.keyid = handle->pub->keyid(); - handle->sec = pgp_request_key(&handle->ffi->key_provider, &request); + handle->sec = handle->ffi->key_provider.request_key(request); } return handle->sec; } @@ -6378,22 +6376,22 @@ try { return RNP_ERROR_BAD_PARAMETERS; } - if (!sig->sig->validity.validated) { - pgp_key_t *signer = - pgp_sig_get_signer(*sig->sig, sig->ffi->pubring, &sig->ffi->key_provider); + auto ssig = sig->sig; + if (!ssig->validity.validated) { + pgp_key_t *signer = sig->ffi->pubring->get_signer(ssig->sig, &sig->ffi->key_provider); if (!signer) { return RNP_ERROR_KEY_NOT_FOUND; } - signer->validate_sig(*sig->key, *sig->sig, sig->ffi->context); + signer->validate_sig(*sig->key, *ssig, sig->ffi->context); } - if (!sig->sig->validity.validated) { + if (!ssig->validity.validated) { return RNP_ERROR_VERIFICATION_FAILED; } - if (sig->sig->validity.expired) { + if (ssig->validity.expired) { return RNP_ERROR_SIGNATURE_EXPIRED; } - return sig->sig->valid() ? RNP_SUCCESS : RNP_ERROR_SIGNATURE_INVALID; + return ssig->valid() ? RNP_SUCCESS : RNP_ERROR_SIGNATURE_INVALID; } FFI_GUARD @@ -6767,14 +6765,11 @@ FFI_GUARD static const pgp_key_grip_t * rnp_get_grip_by_fp(rnp_ffi_t ffi, const pgp_fingerprint_t &fp) { - pgp_key_t *key = NULL; - if (ffi->pubring) { - key = rnp_key_store_get_key_by_fpr(ffi->pubring, fp); - } - if (!key && ffi->secring) { - key = rnp_key_store_get_key_by_fpr(ffi->secring, fp); + const pgp_key_t *key = ffi->pubring->get_key(fp); + if (!key) { + key = ffi->secring->get_key(fp); } - return key ? &key->grip() : NULL; + return key ? &key->grip() : nullptr; } rnp_result_t @@ -6933,7 +6928,7 @@ try { if (key->is_subkey()) { /* check validity time of the primary key as well */ - pgp_key_t *primary = rnp_key_store_get_primary_key(handle->ffi->pubring, key); + pgp_key_t *primary = handle->ffi->pubring->primary_key(*key); if (!primary) { /* no primary key - subkey considered as never valid */ *result = 0; @@ -7420,7 +7415,7 @@ FFI_GUARD static rnp_result_t key_to_bytes(pgp_key_t *key, uint8_t **buf, size_t *buf_len) { - auto vec = rnp_key_to_vec(*key); + auto vec = key->write_vec(); *buf = (uint8_t *) calloc(1, vec.size()); if (!*buf) { return RNP_ERROR_OUT_OF_MEMORY; @@ -8151,7 +8146,7 @@ try { return RNP_ERROR_BAD_PARAMETERS; } - auto vec = rnp_key_to_vec(*key); + auto vec = key->write_vec(); rnp::MemorySource mem(vec); return rnp_dump_src_to_json(&mem.src(), flags, result); } @@ -8239,9 +8234,9 @@ key_iter_next_item(rnp_identifier_iterator_t it) static bool key_iter_first_key(rnp_identifier_iterator_t it) { - if (rnp_key_store_get_key_count(it->ffi->pubring)) { + if (it->ffi->pubring->key_count()) { it->store = it->ffi->pubring; - } else if (rnp_key_store_get_key_count(it->ffi->secring)) { + } else if (it->ffi->secring->key_count()) { it->store = it->ffi->secring; } else { it->store = NULL; diff --git a/src/lib/types.h b/src/lib/types.h index 3495681458..850c4b0e91 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -204,6 +204,8 @@ typedef struct pgp_key_material_t { size_t qbits() const; void validate(rnp::SecurityContext &ctx, bool reset = true); bool valid() const; + + bool get_grip(pgp_key_grip_t &grip) const; } pgp_key_material_t; /** diff --git a/src/librekey/kbx_blob.hpp b/src/librekey/kbx_blob.hpp index 5c6b3ee733..a9434e44b1 100644 --- a/src/librekey/kbx_blob.hpp +++ b/src/librekey/kbx_blob.hpp @@ -27,6 +27,9 @@ #ifndef RNP_KBX_BLOB_HPP #define RNP_KBX_BLOB_HPP +#include +#include "repgp/repgp_def.h" + typedef enum : uint8_t { KBX_EMPTY_BLOB = 0, KBX_HEADER_BLOB = 1, diff --git a/src/librekey/key_store_g10.cpp b/src/librekey/key_store_g10.cpp index dcf3fe112a..310c810580 100644 --- a/src/librekey/key_store_g10.cpp +++ b/src/librekey/key_store_g10.cpp @@ -33,7 +33,6 @@ #include "config.h" #include -#include "key_store_pgp.h" #include "key_store_g10.h" #include "crypto/common.h" @@ -894,14 +893,13 @@ copy_secret_fields(pgp_key_pkt_t &dst, const pgp_key_pkt_t &src) return true; } +namespace rnp { bool -rnp_key_store_g10_from_src(rnp_key_store_t * key_store, - pgp_source_t * src, - const pgp_key_provider_t *key_provider) +KeyStore::load_g10(pgp_source_t &src, const KeyProvider *key_provider) { try { /* read src to the memory */ - rnp::MemorySource memsrc(*src); + MemorySource memsrc(src); /* parse secret key: fills material and sec_protection only */ pgp_key_pkt_t seckey; if (!g23_parse_seckey(seckey, (uint8_t *) memsrc.memory(), memsrc.size(), NULL)) { @@ -911,11 +909,11 @@ rnp_key_store_g10_from_src(rnp_key_store_t * key_store, pgp_key_t key; if (key_provider) { pgp_key_request_ctx_t req_ctx(PGP_OP_MERGE_INFO, false, PGP_KEY_SEARCH_GRIP); - if (!rnp_key_store_get_key_grip(&seckey.material, req_ctx.search.by.grip)) { + if (!seckey.material.get_grip(req_ctx.search.by.grip)) { return false; } - const pgp_key_t *pubkey = pgp_request_key(key_provider, &req_ctx); + const pgp_key_t *pubkey = key_provider->request_key(req_ctx); if (!pubkey) { return false; } @@ -932,7 +930,7 @@ rnp_key_store_g10_from_src(rnp_key_store_t * key_store, key.set_rawpkt( pgp_rawpacket_t((uint8_t *) memsrc.memory(), memsrc.size(), PGP_PKT_RESERVED)); key.format = PGP_KEY_STORE_G10; - if (!rnp_key_store_add_key(key_store, &key)) { + if (!add_key(key)) { return false; } return true; @@ -941,6 +939,7 @@ rnp_key_store_g10_from_src(rnp_key_store_t * key_store, return false; } } +} // namespace rnp /* * Write G10 S-exp to buffer diff --git a/src/librekey/key_store_g10.h b/src/librekey/key_store_g10.h index f770628c7c..9dd561e4a3 100644 --- a/src/librekey/key_store_g10.h +++ b/src/librekey/key_store_g10.h @@ -29,12 +29,11 @@ #include -bool rnp_key_store_g10_from_src(rnp_key_store_t *, pgp_source_t *, const pgp_key_provider_t *); -bool rnp_key_store_gnupg_sexp_to_dst(pgp_key_t *, pgp_dest_t *); -bool g10_write_seckey(pgp_dest_t * dst, - pgp_key_pkt_t * seckey, - const char * password, - rnp::SecurityContext &ctx); +bool rnp_key_store_gnupg_sexp_to_dst(pgp_key_t *, pgp_dest_t *); +bool g10_write_seckey(pgp_dest_t * dst, + pgp_key_pkt_t * seckey, + const char * password, + rnp::SecurityContext &ctx); pgp_key_pkt_t *g10_decrypt_seckey(const pgp_rawpacket_t &raw, const pgp_key_pkt_t & pubkey, const char * password); diff --git a/src/librekey/key_store_kbx.cpp b/src/librekey/key_store_kbx.cpp index 954e49df5e..0828ae8595 100644 --- a/src/librekey/key_store_kbx.cpp +++ b/src/librekey/key_store_kbx.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2022, [Ribose Inc](https://www.ribose.com). + * Copyright (c) 2017-2023, [Ribose Inc](https://www.ribose.com). * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,8 +36,6 @@ #include #include -#include "key_store_pgp.h" -#include "key_store_kbx.h" #include "pgp-key.h" #include @@ -334,8 +332,10 @@ kbx_pgp_blob_t::parse() return true; } -static std::unique_ptr -rnp_key_store_kbx_parse_blob(const uint8_t *image, size_t image_len) +namespace rnp { +namespace { +std::unique_ptr +kbx_parse_blob(const uint8_t *image, size_t image_len) { std::unique_ptr blob; // a blob shouldn't be less of length + type @@ -377,16 +377,15 @@ rnp_key_store_kbx_parse_blob(const uint8_t *image, size_t image_len) } return blob; } +} // namespace bool -rnp_key_store_kbx_from_src(rnp_key_store_t * key_store, - pgp_source_t * src, - const pgp_key_provider_t *key_provider) +KeyStore::load_kbx(pgp_source_t &src, const KeyProvider *key_provider) { try { - rnp::MemorySource mem(*src); - size_t has_bytes = mem.size(); - uint8_t * buf = (uint8_t *) mem.memory(); + MemorySource mem(src); + size_t has_bytes = mem.size(); + uint8_t * buf = (uint8_t *) mem.memory(); if (has_bytes < BLOB_FIRST_SIZE) { RNP_LOG("Too few bytes for valid KBX"); @@ -410,13 +409,13 @@ rnp_key_store_kbx_from_src(rnp_key_store_t * key_store, has_bytes); return false; } - auto blob = rnp_key_store_kbx_parse_blob(buf, blob_length); + auto blob = kbx_parse_blob(buf, blob_length); if (!blob.get()) { RNP_LOG("Failed to parse blob"); return false; } kbx_blob_t *pblob = blob.get(); - key_store->blobs.push_back(std::move(blob)); + blobs.push_back(std::move(blob)); if (pblob->type() == KBX_PGP_BLOB) { // parse keyblock if it existed @@ -426,10 +425,10 @@ rnp_key_store_kbx_from_src(rnp_key_store_t * key_store, return false; } - rnp::MemorySource blsrc(pgp_blob.image().data() + pgp_blob.keyblock_offset(), - pgp_blob.keyblock_length(), - false); - if (rnp_key_store_pgp_read_from_src(key_store, &blsrc.src())) { + MemorySource blsrc(pgp_blob.image().data() + pgp_blob.keyblock_offset(), + pgp_blob.keyblock_length(), + false); + if (load_pgp(blsrc.src())) { return false; } } @@ -447,21 +446,22 @@ rnp_key_store_kbx_from_src(rnp_key_store_t * key_store, } } -static bool -pbuf(pgp_dest_t *dst, const void *buf, size_t len) +namespace { +bool +pbuf(pgp_dest_t &dst, const void *buf, size_t len) { - dst_write(dst, buf, len); - return dst->werr == RNP_SUCCESS; + dst_write(&dst, buf, len); + return dst.werr == RNP_SUCCESS; } -static bool -pu8(pgp_dest_t *dst, uint8_t p) +bool +pu8(pgp_dest_t &dst, uint8_t p) { return pbuf(dst, &p, 1); } -static bool -pu16(pgp_dest_t *dst, uint16_t f) +bool +pu16(pgp_dest_t &dst, uint16_t f) { uint8_t p[2]; p[0] = (uint8_t)(f >> 8); @@ -469,22 +469,22 @@ pu16(pgp_dest_t *dst, uint16_t f) return pbuf(dst, p, 2); } -static bool -pu32(pgp_dest_t *dst, uint32_t f) +bool +pu32(pgp_dest_t &dst, uint32_t f) { uint8_t p[4]; write_uint32(p, f); return pbuf(dst, p, 4); } -static bool -rnp_key_store_kbx_write_header(rnp_key_store_t *key_store, pgp_dest_t *dst) +bool +kbx_write_header(const KeyStore &key_store, pgp_dest_t &dst) { uint16_t flags = 0; - uint32_t file_created_at = key_store->secctx.time(); + uint32_t file_created_at = key_store.secctx.time(); - if (!key_store->blobs.empty() && (key_store->blobs[0]->type() == KBX_HEADER_BLOB)) { - kbx_header_blob_t &blob = dynamic_cast(*key_store->blobs[0]); + if (!key_store.blobs.empty() && (key_store.blobs[0]->type() == KBX_HEADER_BLOB)) { + kbx_header_blob_t &blob = dynamic_cast(*key_store.blobs[0]); file_created_at = blob.file_created_at(); } @@ -492,56 +492,54 @@ rnp_key_store_kbx_write_header(rnp_key_store_t *key_store, pgp_dest_t *dst) !pu8(dst, 1) // version || !pu16(dst, flags) || !pbuf(dst, "KBXf", 4) || !pu32(dst, 0) // RFU || !pu32(dst, 0) // RFU - || !pu32(dst, file_created_at) || !pu32(dst, key_store->secctx.time()) || + || !pu32(dst, file_created_at) || !pu32(dst, key_store.secctx.time()) || !pu32(dst, 0)); // RFU } -static bool -rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest_t *dst) +bool +kbx_write_pgp(const KeyStore &key_store, const pgp_key_t &key, pgp_dest_t &dst) { - rnp::MemoryDest mem(NULL, BLOB_SIZE_LIMIT); + MemoryDest mem(NULL, BLOB_SIZE_LIMIT); - if (!pu32(&mem.dst(), 0)) { // length, we don't know length of blob yet, so it's 0 + if (!pu32(mem.dst(), 0)) { // length, we don't know length of blob yet, so it's 0 return false; } - if (!pu8(&mem.dst(), KBX_PGP_BLOB) || !pu8(&mem.dst(), 1)) { // type, version + if (!pu8(mem.dst(), KBX_PGP_BLOB) || !pu8(mem.dst(), 1)) { // type, version return false; } - if (!pu16(&mem.dst(), 0)) { // flags, not used by GnuPG + if (!pu16(mem.dst(), 0)) { // flags, not used by GnuPG return false; } - if (!pu32(&mem.dst(), 0) || - !pu32(&mem.dst(), 0)) { // offset and length of keyblock, update later + if (!pu32(mem.dst(), 0) || + !pu32(mem.dst(), 0)) { // offset and length of keyblock, update later return false; } - if (!pu16(&mem.dst(), 1 + key->subkey_count())) { // number of keys in keyblock + if (!pu16(mem.dst(), 1 + key.subkey_count())) { // number of keys in keyblock return false; } - if (!pu16(&mem.dst(), 28)) { // size of key info structure) + if (!pu16(mem.dst(), 28)) { // size of key info structure) return false; } - if (!pbuf(&mem.dst(), key->fp().fingerprint, key->fp().length) || - !pu32(&mem.dst(), mem.writeb() - 8) || // offset to keyid (part of fpr for V4) - !pu16(&mem.dst(), 0) || // flags, not used by GnuPG - !pu16(&mem.dst(), 0)) { // RFU + if (!pbuf(mem.dst(), key.fp().fingerprint, key.fp().length) || + !pu32(mem.dst(), mem.writeb() - 8) || // offset to keyid (part of fpr for V4) + !pu16(mem.dst(), 0) || // flags, not used by GnuPG + !pu16(mem.dst(), 0)) { // RFU return false; } // same as above, for each subkey std::vector subkey_sig_expirations; - for (auto &sfp : key->subkey_fps()) { - pgp_key_t *subkey = rnp_key_store_get_key_by_fpr(key_store, sfp); - if (!subkey || !pbuf(&mem.dst(), subkey->fp().fingerprint, key->fp().length) || - // if (!subkey || !pbuf(&mem.dst(), subkey->fp().fingerprint, PGP_FINGERPRINT_SIZE) - // || // from upstream during merge 2023-03-20 - !pu32(&mem.dst(), mem.writeb() - 8) || // offset to keyid (part of fpr for V4) - !pu16(&mem.dst(), 0) || // flags, not used by GnuPG - !pu16(&mem.dst(), 0)) { // RFU + for (auto &sfp : key.subkey_fps()) { + auto *subkey = key_store.get_key(sfp); + if (!subkey || !pbuf(mem.dst(), subkey->fp().fingerprint, subkey->fp().length) || + !pu32(mem.dst(), mem.writeb() - 8) || // offset to keyid (part of fpr for V4) + !pu16(mem.dst(), 0) || // flags, not used by GnuPG + !pu16(mem.dst(), 0)) { // RFU return false; } // load signature expirations while we're at it @@ -551,77 +549,77 @@ rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest } } - if (!pu16(&mem.dst(), 0)) { // Zero size of serial number + if (!pu16(mem.dst(), 0)) { // Zero size of serial number return false; } // skip serial number - if (!pu16(&mem.dst(), key->uid_count()) || !pu16(&mem.dst(), 12)) { + if (!pu16(mem.dst(), key.uid_count()) || !pu16(mem.dst(), 12)) { return false; } size_t uid_start = mem.writeb(); - for (size_t i = 0; i < key->uid_count(); i++) { - if (!pu32(&mem.dst(), 0) || - !pu32(&mem.dst(), 0)) { // UID offset and length, update when blob has done + for (size_t i = 0; i < key.uid_count(); i++) { + if (!pu32(mem.dst(), 0) || + !pu32(mem.dst(), 0)) { // UID offset and length, update when blob has done return false; } - if (!pu16(&mem.dst(), 0)) { // flags, (not yet used) + if (!pu16(mem.dst(), 0)) { // flags, (not yet used) return false; } - if (!pu8(&mem.dst(), 0) || !pu8(&mem.dst(), 0)) { // Validity & RFU + if (!pu8(mem.dst(), 0) || !pu8(mem.dst(), 0)) { // Validity & RFU return false; } } - if (!pu16(&mem.dst(), key->sig_count() + subkey_sig_expirations.size()) || - !pu16(&mem.dst(), 4)) { + if (!pu16(mem.dst(), key.sig_count() + subkey_sig_expirations.size()) || + !pu16(mem.dst(), 4)) { return false; } - for (size_t i = 0; i < key->sig_count(); i++) { - if (!pu32(&mem.dst(), key->get_sig(i).sig.key_expiration())) { + for (size_t i = 0; i < key.sig_count(); i++) { + if (!pu32(mem.dst(), key.get_sig(i).sig.key_expiration())) { return false; } } for (auto &expiration : subkey_sig_expirations) { - if (!pu32(&mem.dst(), expiration)) { + if (!pu32(mem.dst(), expiration)) { return false; } } - if (!pu8(&mem.dst(), 0) || - !pu8(&mem.dst(), 0)) { // Assigned ownertrust & All_Validity (not yet used) + if (!pu8(mem.dst(), 0) || + !pu8(mem.dst(), 0)) { // Assigned ownertrust & All_Validity (not yet used) return false; } - if (!pu16(&mem.dst(), 0) || !pu32(&mem.dst(), 0)) { // RFU & Recheck_after + if (!pu16(mem.dst(), 0) || !pu32(mem.dst(), 0)) { // RFU & Recheck_after return false; } - if (!pu32(&mem.dst(), key_store->secctx.time()) || - !pu32(&mem.dst(), key_store->secctx.time())) { // Latest timestamp && created + if (!pu32(mem.dst(), key_store.secctx.time()) || + !pu32(mem.dst(), key_store.secctx.time())) { // Latest timestamp && created return false; } - if (!pu32(&mem.dst(), 0)) { // Size of reserved space + if (!pu32(mem.dst(), 0)) { // Size of reserved space return false; } // wrtite UID, we might redesign PGP write and use this information from keyblob - for (size_t i = 0; i < key->uid_count(); i++) { - const pgp_userid_t &uid = key->get_uid(i); + for (size_t i = 0; i < key.uid_count(); i++) { + const pgp_userid_t &uid = key.get_uid(i); uint8_t * p = (uint8_t *) mem.memory() + uid_start + (12 * i); /* store absolute uid offset in the output stream */ - uint32_t pt = mem.writeb() + dst->writeb; + uint32_t pt = mem.writeb() + dst.writeb; write_uint32(p, pt); /* and uid length */ pt = uid.str.size(); write_uint32(p + 4, pt); /* uid data itself */ - if (!pbuf(&mem.dst(), uid.str.c_str(), pt)) { + if (!pbuf(mem.dst(), uid.str.c_str(), pt)) { return false; } } @@ -632,13 +630,13 @@ rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest uint8_t *p = (uint8_t *) mem.memory() + 8; write_uint32(p, pt); - key->write(mem.dst()); + key.write(mem.dst()); if (mem.werr()) { return false; } - for (auto &sfp : key->subkey_fps()) { - const pgp_key_t *subkey = rnp_key_store_get_key_by_fpr(key_store, sfp); + for (auto &sfp : key.subkey_fps()) { + const pgp_key_t *subkey = key_store.get_key(sfp); if (!subkey) { return false; } @@ -665,19 +663,19 @@ rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest assert(hash->size() == sizeof(checksum)); hash->finish(checksum); - if (!(pbuf(&mem.dst(), checksum, PGP_SHA1_HASH_SIZE))) { + if (!(pbuf(mem.dst(), checksum, PGP_SHA1_HASH_SIZE))) { return false; } /* finally write to the output */ - dst_write(dst, mem.memory(), mem.writeb()); - return !dst->werr; + dst_write(&dst, mem.memory(), mem.writeb()); + return !dst.werr; } -static bool -rnp_key_store_kbx_write_x509(rnp_key_store_t *key_store, pgp_dest_t *dst) +bool +kbx_write_x509(const KeyStore &key_store, pgp_dest_t &dst) { - for (auto &blob : key_store->blobs) { + for (auto &blob : key_store.blobs) { if (blob->type() != KBX_X509_BLOB) { continue; } @@ -687,27 +685,28 @@ rnp_key_store_kbx_write_x509(rnp_key_store_t *key_store, pgp_dest_t *dst) } return true; } +} // namespace bool -rnp_key_store_kbx_to_dst(rnp_key_store_t *key_store, pgp_dest_t *dst) +KeyStore::write_kbx(pgp_dest_t &dst) { try { - if (!rnp_key_store_kbx_write_header(key_store, dst)) { + if (!kbx_write_header(*this, dst)) { RNP_LOG("Can't write KBX header"); return false; } - for (auto &key : key_store->keys) { + for (auto &key : keys) { if (!key.is_primary()) { continue; } - if (!rnp_key_store_kbx_write_pgp(key_store, &key, dst)) { + if (!kbx_write_pgp(*this, key, dst)) { RNP_LOG("Can't write PGP blobs for key %p", &key); return false; } } - if (!rnp_key_store_kbx_write_x509(key_store, dst)) { + if (!kbx_write_x509(*this, dst)) { RNP_LOG("Can't write X509 blobs"); return false; } @@ -717,3 +716,4 @@ rnp_key_store_kbx_to_dst(rnp_key_store_t *key_store, pgp_dest_t *dst) return false; } } +} // namespace rnp diff --git a/src/librekey/key_store_kbx.h b/src/librekey/key_store_kbx.h deleted file mode 100644 index 68d725d4cf..0000000000 --- a/src/librekey/key_store_kbx.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2017, [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 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. - */ - -#ifndef RNP_KEY_STORE_KBX_H -#define RNP_KEY_STORE_KBX_H - -#include -#include "sec_profile.hpp" - -bool rnp_key_store_kbx_from_src(rnp_key_store_t *, pgp_source_t *, const pgp_key_provider_t *); -bool rnp_key_store_kbx_to_dst(rnp_key_store_t *, pgp_dest_t *); - -#endif // RNP_KEY_STORE_KBX_H diff --git a/src/librekey/key_store_pgp.cpp b/src/librekey/key_store_pgp.cpp index 6edc099b2e..94c82f5caf 100644 --- a/src/librekey/key_store_pgp.cpp +++ b/src/librekey/key_store_pgp.cpp @@ -1,59 +1,29 @@ /* - * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com). - * Copyright (c) 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2017-2020, 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 (agc@netbsd.org), 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. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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. * - * See the License for the specific language governing permissions and - * limitations under the License. + * 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. */ -#if defined(__NetBSD__) -__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: keyring.c,v 1.50 2011/06/25 00:37:44 agc Exp $"); -#endif - #include #include @@ -64,74 +34,68 @@ __RCSID("$NetBSD: keyring.c,v 1.50 2011/06/25 00:37:44 agc Exp $"); #include "crypto/mem.h" #include "types.h" -#include "key_store_pgp.h" #include "pgp-key.h" +namespace rnp { bool -rnp_key_store_add_transferable_subkey(rnp_key_store_t * keyring, - pgp_transferable_subkey_t *tskey, - pgp_key_t * pkey) +KeyStore::add_ts_subkey(const pgp_transferable_subkey_t &tskey, pgp_key_t *pkey) { try { /* create subkey */ - pgp_key_t skey(*tskey, pkey); + pgp_key_t skey(tskey, pkey); /* add it to the storage */ - return rnp_key_store_add_key(keyring, &skey); + return add_key(skey); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); - RNP_LOG_KEY_PKT("failed to create subkey %s", tskey->subkey); + RNP_LOG_KEY_PKT("failed to create subkey %s", tskey.subkey); RNP_LOG_KEY("primary key is %s", pkey); return false; } } bool -rnp_key_store_add_transferable_key(rnp_key_store_t *keyring, pgp_transferable_key_t *tkey) +KeyStore::add_ts_key(pgp_transferable_key_t &tkey) { - pgp_key_t *addkey = NULL; + pgp_key_t *addkey = nullptr; /* create key from transferable key */ try { - pgp_key_t key(*tkey); + pgp_key_t key(tkey); /* temporary disable key validation */ - keyring->disable_validation = true; + disable_validation = true; /* add key to the storage before subkeys */ - addkey = rnp_key_store_add_key(keyring, &key); + addkey = add_key(key); } catch (const std::exception &e) { - keyring->disable_validation = false; - RNP_LOG_KEY_PKT("failed to add key %s", tkey->key); + disable_validation = false; + RNP_LOG_KEY_PKT("failed to add key %s", tkey.key); return false; } if (!addkey) { - keyring->disable_validation = false; + disable_validation = false; RNP_LOG("Failed to add key to key store."); return false; } /* add subkeys */ - for (auto &subkey : tkey->subkeys) { - if (!rnp_key_store_add_transferable_subkey(keyring, &subkey, addkey)) { + for (auto &subkey : tkey.subkeys) { + if (!add_ts_subkey(subkey, addkey)) { RNP_LOG("Failed to add subkey to key store."); - keyring->disable_validation = false; - goto error; + disable_validation = false; + /* during key addition all fields are copied so will be cleaned below */ + remove_key(*addkey, false); + return false; } } /* now validate/refresh the whole key with subkeys */ - keyring->disable_validation = false; - addkey->revalidate(*keyring); + disable_validation = false; + addkey->revalidate(*this); return true; -error: - /* during key addition all fields are copied so will be cleaned below */ - rnp_key_store_remove_key(keyring, addkey, false); - return false; } rnp_result_t -rnp_key_store_pgp_read_key_from_src(rnp_key_store_t &keyring, - pgp_source_t & src, - bool skiperrors) +KeyStore::load_pgp_key(pgp_source_t &src, bool skiperrors) { pgp_transferable_key_t key; rnp_result_t ret = process_pgp_key_auto(src, key, true, skiperrors); @@ -142,8 +106,7 @@ rnp_key_store_pgp_read_key_from_src(rnp_key_store_t &keyring, /* check whether we have primary key */ if (key.key.tag != PGP_PKT_RESERVED) { - return rnp_key_store_add_transferable_key(&keyring, &key) ? RNP_SUCCESS : - RNP_ERROR_BAD_STATE; + return add_ts_key(key) ? RNP_SUCCESS : RNP_ERROR_BAD_STATE; } /* we just skipped some unexpected packets and read nothing */ @@ -151,35 +114,31 @@ rnp_key_store_pgp_read_key_from_src(rnp_key_store_t &keyring, return RNP_SUCCESS; } - return rnp_key_store_add_transferable_subkey(&keyring, &key.subkeys.front(), NULL) ? - RNP_SUCCESS : - RNP_ERROR_BAD_STATE; + return add_ts_subkey(key.subkeys.front()) ? RNP_SUCCESS : RNP_ERROR_BAD_STATE; } rnp_result_t -rnp_key_store_pgp_read_from_src(rnp_key_store_t *keyring, pgp_source_t *src, bool skiperrors) +KeyStore::load_pgp(pgp_source_t &src, bool skiperrors) { /* check whether we have transferable subkey in source */ - if (is_subkey_pkt(stream_pkt_type(*src))) { + if (is_subkey_pkt(stream_pkt_type(src))) { pgp_transferable_subkey_t tskey; - rnp_result_t ret = process_pgp_subkey(*src, tskey, skiperrors); + rnp_result_t ret = process_pgp_subkey(src, tskey, skiperrors); if (ret) { return ret; } - return rnp_key_store_add_transferable_subkey(keyring, &tskey, NULL) ? - RNP_SUCCESS : - RNP_ERROR_BAD_STATE; + return add_ts_subkey(tskey) ? RNP_SUCCESS : RNP_ERROR_BAD_STATE; } /* process armored or raw transferable key packets sequence(s) */ try { pgp_key_sequence_t keys; - rnp_result_t ret = process_pgp_keys(*src, keys, skiperrors); + rnp_result_t ret = process_pgp_keys(src, keys, skiperrors); if (ret) { return ret; } for (auto &key : keys.keys) { - if (!rnp_key_store_add_transferable_key(keyring, &key)) { + if (!add_ts_key(key)) { return RNP_ERROR_BAD_STATE; } } @@ -189,19 +148,13 @@ rnp_key_store_pgp_read_from_src(rnp_key_store_t *keyring, pgp_source_t *src, boo return RNP_ERROR_BAD_PARAMETERS; } } +} // namespace rnp -std::vector -rnp_key_to_vec(const pgp_key_t &key) -{ - rnp::MemoryDest dst; - key.write(dst.dst()); - return dst.to_vector(); -} - -static bool -do_write(rnp_key_store_t *key_store, pgp_dest_t *dst, bool secret) +namespace { +bool +do_write(rnp::KeyStore &key_store, pgp_dest_t &dst, bool secret) { - for (auto &key : key_store->keys) { + for (auto &key : key_store.keys) { if (key.is_secret() != secret) { continue; } @@ -214,28 +167,31 @@ do_write(rnp_key_store_t *key_store, pgp_dest_t *dst, bool secret) RNP_LOG("incorrect format (conversions not supported): %d", key.format); return false; } - key.write(*dst); - if (dst->werr) { + key.write(dst); + if (dst.werr) { return false; } for (auto &sfp : key.subkey_fps()) { - pgp_key_t *subkey = rnp_key_store_get_key_by_fpr(key_store, sfp); + pgp_key_t *subkey = key_store.get_key(sfp); if (!subkey) { RNP_LOG("Missing subkey"); continue; } - subkey->write(*dst); - if (dst->werr) { + subkey->write(dst); + if (dst.werr) { return false; } } } return true; } +} // namespace +namespace rnp { bool -rnp_key_store_pgp_write_to_dst(rnp_key_store_t *key_store, pgp_dest_t *dst) +KeyStore::write_pgp(pgp_dest_t &dst) { // two separate passes (public keys, then secret keys) - return do_write(key_store, dst, false) && do_write(key_store, dst, true); + return do_write(*this, dst, false) && do_write(*this, dst, true); } +} // namespace rnp diff --git a/src/librekey/key_store_pgp.h b/src/librekey/key_store_pgp.h deleted file mode 100644 index d3dcd06250..0000000000 --- a/src/librekey/key_store_pgp.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2017-2020, [Ribose Inc](https://www.ribose.com). - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is originally derived from software contributed to - * The NetBSD Foundation by Alistair Crooks (agc@netbsd.org), 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: - * 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 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. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef KEY_STORE_PGP_H_ -#define KEY_STORE_PGP_H_ - -#include -#include -#include - -/* Read the whole keyring from the src, processing all available keys or subkeys */ -rnp_result_t rnp_key_store_pgp_read_from_src(rnp_key_store_t *keyring, - pgp_source_t * src, - bool skiperrors = false); - -/* Read the first key or subkey from the src */ -rnp_result_t rnp_key_store_pgp_read_key_from_src(rnp_key_store_t &keyring, - pgp_source_t & src, - bool skiperrors = false); - -bool rnp_key_store_pgp_write_to_dst(rnp_key_store_t *key_store, pgp_dest_t *dst); - -bool rnp_key_store_add_transferable_subkey(rnp_key_store_t * keyring, - pgp_transferable_subkey_t *tskey, - pgp_key_t * pkey); - -bool rnp_key_store_add_transferable_key(rnp_key_store_t * keyring, - pgp_transferable_key_t *tkey); - -std::vector rnp_key_to_vec(const pgp_key_t &key); - -#endif /* KEY_STORE_PGP_H_ */ diff --git a/src/librekey/rnp_key_store.cpp b/src/librekey/rnp_key_store.cpp index 0918d155c1..023d383756 100644 --- a/src/librekey/rnp_key_store.cpp +++ b/src/librekey/rnp_key_store.cpp @@ -1,31 +1,27 @@ /* - * Copyright (c) 2017-2022 [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 (agc@netbsd.org), 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. */ #include "config.h" @@ -50,8 +46,6 @@ #include #include -#include "key_store_pgp.h" -#include "key_store_kbx.h" #include "key_store_g10.h" #include "kbx_blob.hpp" @@ -64,31 +58,30 @@ #include "str-utils.h" #endif +namespace rnp { bool -rnp_key_store_load_from_path(rnp_key_store_t * key_store, - const pgp_key_provider_t *key_provider) +KeyStore::load(const KeyProvider *key_provider) { pgp_source_t src = {}; - if (key_store->format == PGP_KEY_STORE_G10) { - auto dir = rnp_opendir(key_store->path.c_str()); + if (format == PGP_KEY_STORE_G10) { + auto dir = rnp_opendir(path.c_str()); if (!dir) { - RNP_LOG( - "Can't open G10 directory %s: %s", key_store->path.c_str(), strerror(errno)); + RNP_LOG("Can't open G10 directory %s: %s", path.c_str(), strerror(errno)); return false; } std::string dirname; while (!((dirname = rnp_readdir_name(dir)).empty())) { - std::string path = rnp::path::append(key_store->path, dirname); + std::string apath = rnp::path::append(path, dirname); - if (init_file_src(&src, path.c_str())) { - RNP_LOG("failed to read file %s", path.c_str()); + if (init_file_src(&src, apath.c_str())) { + RNP_LOG("failed to read file %s", apath.c_str()); continue; } // G10 may fail to read one file, so ignore it! - if (!rnp_key_store_g10_from_src(key_store, &src, key_provider)) { - RNP_LOG("Can't parse file: %s", path.c_str()); // TODO: %S ? + if (!load_g10(src, key_provider)) { + RNP_LOG("Can't parse file: %s", apath.c_str()); // TODO: %S ? } src_close(&src); } @@ -97,68 +90,66 @@ rnp_key_store_load_from_path(rnp_key_store_t * key_store, } /* init file source and load from it */ - if (init_file_src(&src, key_store->path.c_str())) { - RNP_LOG("failed to read file %s", key_store->path.c_str()); + if (init_file_src(&src, path.c_str())) { + RNP_LOG("failed to read file %s", path.c_str()); return false; } - bool rc = rnp_key_store_load_from_src(key_store, &src, key_provider); + bool rc = load(src, key_provider); src_close(&src); return rc; } bool -rnp_key_store_load_from_src(rnp_key_store_t * key_store, - pgp_source_t * src, - const pgp_key_provider_t *key_provider) +KeyStore::load(pgp_source_t &src, const KeyProvider *key_provider) { - switch (key_store->format) { + switch (format) { case PGP_KEY_STORE_GPG: - return rnp_key_store_pgp_read_from_src(key_store, src) == RNP_SUCCESS; + return !load_pgp(src); case PGP_KEY_STORE_KBX: - return rnp_key_store_kbx_from_src(key_store, src, key_provider); + return load_kbx(src, key_provider); case PGP_KEY_STORE_G10: - return rnp_key_store_g10_from_src(key_store, src, key_provider); + return load_g10(src, key_provider); default: - RNP_LOG("Unsupported load from memory for key-store format: %d", key_store->format); + RNP_LOG("Unsupported load from memory for key-store format: %d", format); } return false; } bool -rnp_key_store_write_to_path(rnp_key_store_t *key_store) +KeyStore::write() { bool rc; pgp_dest_t keydst = {}; /* write g10 key store to the directory */ - if (key_store->format == PGP_KEY_STORE_G10) { - char path[MAXPATHLEN]; + if (format == PGP_KEY_STORE_G10) { + char chpath[MAXPATHLEN]; struct stat path_stat; - if (rnp_stat(key_store->path.c_str(), &path_stat) != -1) { + if (rnp_stat(path.c_str(), &path_stat) != -1) { if (!S_ISDIR(path_stat.st_mode)) { - RNP_LOG("G10 keystore should be a directory: %s", key_store->path.c_str()); + RNP_LOG("G10 keystore should be a directory: %s", path.c_str()); return false; } } else { if (errno != ENOENT) { - RNP_LOG("stat(%s): %s", key_store->path.c_str(), strerror(errno)); + RNP_LOG("stat(%s): %s", path.c_str(), strerror(errno)); return false; } - if (RNP_MKDIR(key_store->path.c_str(), S_IRWXU) != 0) { - RNP_LOG("mkdir(%s, S_IRWXU): %s", key_store->path.c_str(), strerror(errno)); + if (RNP_MKDIR(path.c_str(), S_IRWXU) != 0) { + RNP_LOG("mkdir(%s, S_IRWXU): %s", path.c_str(), strerror(errno)); return false; } } - for (auto &key : key_store->keys) { + for (auto &key : keys) { char grip[PGP_MAX_FINGERPRINT_HEX_SIZE] = {0}; rnp::hex_encode(key.grip().data(), key.grip().size(), grip, sizeof(grip)); - snprintf(path, sizeof(path), "%s/%s.key", key_store->path.c_str(), grip); + snprintf(chpath, sizeof(chpath), "%s/%s.key", path.c_str(), grip); - if (init_tmpfile_dest(&keydst, path, true)) { + if (init_tmpfile_dest(&keydst, chpath, true)) { RNP_LOG("failed to create file"); return false; } @@ -181,12 +172,12 @@ rnp_key_store_write_to_path(rnp_key_store_t *key_store) } /* write kbx/gpg store to the single file */ - if (init_tmpfile_dest(&keydst, key_store->path.c_str(), true)) { + if (init_tmpfile_dest(&keydst, path.c_str(), true)) { RNP_LOG("failed to create keystore file"); return false; } - if (!rnp_key_store_write_to_dst(key_store, &keydst)) { + if (!write(keydst)) { RNP_LOG("failed to write keys to file"); dst_close(&keydst, true); return false; @@ -198,43 +189,43 @@ rnp_key_store_write_to_path(rnp_key_store_t *key_store) } bool -rnp_key_store_write_to_dst(rnp_key_store_t *key_store, pgp_dest_t *dst) +KeyStore::write(pgp_dest_t &dst) { - switch (key_store->format) { + switch (format) { case PGP_KEY_STORE_GPG: - return rnp_key_store_pgp_write_to_dst(key_store, dst); + return write_pgp(dst); case PGP_KEY_STORE_KBX: - return rnp_key_store_kbx_to_dst(key_store, dst); + return write_kbx(dst); default: - RNP_LOG("Unsupported write to memory for key-store format: %d", key_store->format); + RNP_LOG("Unsupported write to memory for key-store format: %d", format); } return false; } void -rnp_key_store_clear(rnp_key_store_t *keyring) +KeyStore::clear() { - keyring->keybyfp.clear(); - keyring->keys.clear(); - keyring->blobs.clear(); + keybyfp.clear(); + keys.clear(); + blobs.clear(); } size_t -rnp_key_store_get_key_count(const rnp_key_store_t *keyring) +KeyStore::key_count() const { - return keyring->keys.size(); + return keys.size(); } -static bool -rnp_key_store_refresh_subkey_grips(rnp_key_store_t *keyring, pgp_key_t *key) +bool +KeyStore::refresh_subkey_grips(pgp_key_t &key) { - if (key->is_subkey()) { + if (key.is_subkey()) { RNP_LOG("wrong argument"); return false; } - for (auto &skey : keyring->keys) { + for (auto &skey : keys) { bool found = false; /* if we have primary_grip then we also added to subkey_grips */ @@ -248,11 +239,11 @@ rnp_key_store_refresh_subkey_grips(rnp_key_store_t *keyring, pgp_key_t *key) if (subsig.sig.type() != PGP_SIG_SUBKEY) { continue; } - if (subsig.sig.has_keyfp() && (key->fp() == subsig.sig.keyfp())) { + if (subsig.sig.has_keyfp() && (key.fp() == subsig.sig.keyfp())) { found = true; break; } - if (subsig.sig.has_keyid() && (key->keyid() == subsig.sig.keyid())) { + if (subsig.sig.has_keyid() && (key.keyid() == subsig.sig.keyid())) { found = true; break; } @@ -260,7 +251,7 @@ rnp_key_store_refresh_subkey_grips(rnp_key_store_t *keyring, pgp_key_t *key) if (found) { try { - key->link_subkey_fp(skey); + key.link_subkey_fp(skey); } catch (const std::exception &e) { RNP_LOG("%s", e.what()); return false; @@ -271,60 +262,60 @@ rnp_key_store_refresh_subkey_grips(rnp_key_store_t *keyring, pgp_key_t *key) return true; } -static pgp_key_t * -rnp_key_store_add_subkey(rnp_key_store_t *keyring, pgp_key_t *srckey, pgp_key_t *oldkey) +pgp_key_t * +KeyStore::add_subkey(pgp_key_t &srckey, pgp_key_t *oldkey) { pgp_key_t *primary = NULL; if (oldkey) { - primary = rnp_key_store_get_primary_key(keyring, oldkey); + primary = primary_key(*oldkey); } if (!primary) { - primary = rnp_key_store_get_primary_key(keyring, srckey); + primary = primary_key(srckey); } if (oldkey) { /* check for the weird case when same subkey has different primary keys */ - if (srckey->has_primary_fp() && oldkey->has_primary_fp() && - (srckey->primary_fp() != oldkey->primary_fp())) { - RNP_LOG_KEY("Warning: different primary keys for subkey %s", srckey); - pgp_key_t *srcprim = rnp_key_store_get_key_by_fpr(keyring, srckey->primary_fp()); + if (srckey.has_primary_fp() && oldkey->has_primary_fp() && + (srckey.primary_fp() != oldkey->primary_fp())) { + RNP_LOG_KEY("Warning: different primary keys for subkey %s", &srckey); + pgp_key_t *srcprim = get_key(srckey.primary_fp()); if (srcprim && (srcprim != primary)) { - srcprim->remove_subkey_fp(srckey->fp()); + srcprim->remove_subkey_fp(srckey.fp()); } } /* in case we already have key let's merge it in */ - if (!oldkey->merge(*srckey, primary)) { - RNP_LOG_KEY("failed to merge subkey %s", srckey); + if (!oldkey->merge(srckey, primary)) { + RNP_LOG_KEY("failed to merge subkey %s", &srckey); RNP_LOG_KEY("primary key is %s", primary); return NULL; } } else { try { - keyring->keys.emplace_back(); - oldkey = &keyring->keys.back(); - keyring->keybyfp[srckey->fp()] = std::prev(keyring->keys.end()); - *oldkey = pgp_key_t(*srckey); + keys.emplace_back(); + oldkey = &keys.back(); + keybyfp[srckey.fp()] = std::prev(keys.end()); + *oldkey = pgp_key_t(srckey); if (primary) { primary->link_subkey_fp(*oldkey); } } catch (const std::exception &e) { - RNP_LOG_KEY("key %s copying failed", srckey); + RNP_LOG_KEY("key %s copying failed", &srckey); RNP_LOG_KEY("primary key is %s", primary); RNP_LOG("%s", e.what()); if (oldkey) { - keyring->keys.pop_back(); - keyring->keybyfp.erase(srckey->fp()); + keys.pop_back(); + keybyfp.erase(srckey.fp()); } - return NULL; + return nullptr; } } /* validate all added keys if not disabled */ - if (!keyring->disable_validation && !oldkey->validated()) { - oldkey->validate_subkey(primary, keyring->secctx); + if (!disable_validation && !oldkey->validated()) { + oldkey->validate_subkey(primary, secctx); } - if (!oldkey->refresh_data(primary, keyring->secctx)) { - RNP_LOG_KEY("Failed to refresh subkey %s data", srckey); + if (!oldkey->refresh_data(primary, secctx)) { + RNP_LOG_KEY("Failed to refresh subkey %s data", &srckey); RNP_LOG_KEY("primary key is %s", primary); } return oldkey; @@ -332,76 +323,73 @@ rnp_key_store_add_subkey(rnp_key_store_t *keyring, pgp_key_t *srckey, pgp_key_t /* add a key to keyring */ pgp_key_t * -rnp_key_store_add_key(rnp_key_store_t *keyring, pgp_key_t *srckey) +KeyStore::add_key(pgp_key_t &srckey) { - assert(srckey->type() && srckey->version()); - pgp_key_t *added_key = rnp_key_store_get_key_by_fpr(keyring, srckey->fp()); + assert(srckey.type() && srckey.version()); + pgp_key_t *added_key = get_key(srckey.fp()); /* we cannot merge G10 keys - so just return it */ - if (added_key && (srckey->format == PGP_KEY_STORE_G10)) { + if (added_key && (srckey.format == PGP_KEY_STORE_G10)) { return added_key; } /* different processing for subkeys */ - if (srckey->is_subkey()) { - return rnp_key_store_add_subkey(keyring, srckey, added_key); + if (srckey.is_subkey()) { + return add_subkey(srckey, added_key); } if (added_key) { - if (!added_key->merge(*srckey)) { - RNP_LOG_KEY("failed to merge key %s", srckey); + if (!added_key->merge(srckey)) { + RNP_LOG_KEY("failed to merge key %s", &srckey); return NULL; } } else { try { - keyring->keys.emplace_back(); - added_key = &keyring->keys.back(); - keyring->keybyfp[srckey->fp()] = std::prev(keyring->keys.end()); - *added_key = pgp_key_t(*srckey); + keys.emplace_back(); + added_key = &keys.back(); + keybyfp[srckey.fp()] = std::prev(keys.end()); + *added_key = pgp_key_t(srckey); /* primary key may be added after subkeys, so let's handle this case correctly */ - if (!rnp_key_store_refresh_subkey_grips(keyring, added_key)) { + if (!refresh_subkey_grips(*added_key)) { RNP_LOG_KEY("failed to refresh subkey grips for %s", added_key); } } catch (const std::exception &e) { - RNP_LOG_KEY("key %s copying failed", srckey); + RNP_LOG_KEY("key %s copying failed", &srckey); RNP_LOG("%s", e.what()); if (added_key) { - keyring->keys.pop_back(); - keyring->keybyfp.erase(srckey->fp()); + keys.pop_back(); + keybyfp.erase(srckey.fp()); } return NULL; } } /* validate all added keys if not disabled or already validated */ - if (!keyring->disable_validation && !added_key->validated()) { - added_key->revalidate(*keyring); - } else if (!added_key->refresh_data(keyring->secctx)) { - RNP_LOG_KEY("Failed to refresh key %s data", srckey); + if (!disable_validation && !added_key->validated()) { + added_key->revalidate(*this); + } else if (!added_key->refresh_data(secctx)) { + RNP_LOG_KEY("Failed to refresh key %s data", &srckey); } return added_key; } pgp_key_t * -rnp_key_store_import_key(rnp_key_store_t * keyring, - pgp_key_t * srckey, - bool pubkey, - pgp_key_import_status_t *status) +KeyStore::import_key(pgp_key_t &srckey, bool pubkey, pgp_key_import_status_t *status) { /* add public key */ - pgp_key_t *exkey = rnp_key_store_get_key_by_fpr(keyring, srckey->fp()); + pgp_key_t *exkey = get_key(srckey.fp()); size_t expackets = exkey ? exkey->rawpkt_count() : 0; try { - pgp_key_t keycp(*srckey, pubkey); - keyring->disable_validation = true; - exkey = rnp_key_store_add_key(keyring, &keycp); - keyring->disable_validation = false; + pgp_key_t keycp(srckey, pubkey); + disable_validation = true; + exkey = add_key(keycp); + disable_validation = false; if (!exkey) { RNP_LOG("failed to add key to the keyring"); - return NULL; + return nullptr; } bool changed = exkey->rawpkt_count() > expackets; if (changed || !exkey->validated()) { /* this will revalidated primary key with all subkeys */ - exkey->revalidate(*keyring); + exkey->revalidate(*this); } if (status) { *status = changed ? (expackets ? PGP_KEY_IMPORT_STATUS_UPDATED : @@ -411,64 +399,43 @@ rnp_key_store_import_key(rnp_key_store_t * keyring, return exkey; } catch (const std::exception &e) { RNP_LOG("%s", e.what()); - keyring->disable_validation = false; - return NULL; + disable_validation = false; + return nullptr; } } -pgp_key_t * -rnp_key_store_get_signer_key(rnp_key_store_t *store, const pgp_signature_t *sig) -{ - pgp_key_search_t search; - // prefer using the issuer fingerprint when available - if (sig->has_keyfp()) { - search.by.fingerprint = sig->keyfp(); - search.type = PGP_KEY_SEARCH_FINGERPRINT; - return rnp_key_store_search(store, &search, NULL); - } - // fall back to key id search - if (sig->has_keyid()) { - search.by.keyid = sig->keyid(); - search.type = PGP_KEY_SEARCH_KEYID; - return rnp_key_store_search(store, &search, NULL); - } - return NULL; -} - -static pgp_sig_import_status_t -rnp_key_store_import_subkey_signature(rnp_key_store_t * keyring, - pgp_key_t * key, - const pgp_signature_t *sig) +pgp_sig_import_status_t +KeyStore::import_subkey_signature(pgp_key_t &key, const pgp_signature_t &sig) { - if ((sig->type() != PGP_SIG_SUBKEY) && (sig->type() != PGP_SIG_REV_SUBKEY)) { + if ((sig.type() != PGP_SIG_SUBKEY) && (sig.type() != PGP_SIG_REV_SUBKEY)) { return PGP_SIG_IMPORT_STATUS_UNKNOWN; } - pgp_key_t *primary = rnp_key_store_get_signer_key(keyring, sig); - if (!primary || !key->has_primary_fp()) { + pgp_key_t *primary = get_signer(sig); + if (!primary || !key.has_primary_fp()) { RNP_LOG("No primary grip or primary key"); return PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY; } - if (primary->fp() != key->primary_fp()) { + if (primary->fp() != key.primary_fp()) { RNP_LOG("Wrong subkey signature's signer."); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } try { - pgp_key_t tmpkey(key->pkt()); - tmpkey.add_sig(*sig); - if (!tmpkey.refresh_data(primary, keyring->secctx)) { + pgp_key_t tmpkey(key.pkt()); + tmpkey.add_sig(sig); + if (!tmpkey.refresh_data(primary, secctx)) { RNP_LOG("Failed to add signature to the key."); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } - size_t expackets = key->rawpkt_count(); - key = rnp_key_store_add_key(keyring, &tmpkey); - if (!key) { + size_t expackets = key.rawpkt_count(); + auto nkey = add_key(tmpkey); + if (!nkey) { RNP_LOG("Failed to add key with imported sig to the keyring"); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } - return (key->rawpkt_count() > expackets) ? PGP_SIG_IMPORT_STATUS_NEW : - PGP_SIG_IMPORT_STATUS_UNCHANGED; + return (nkey->rawpkt_count() > expackets) ? PGP_SIG_IMPORT_STATUS_NEW : + PGP_SIG_IMPORT_STATUS_UNCHANGED; } catch (const std::exception &e) { RNP_LOG("%s", e.what()); return PGP_SIG_IMPORT_STATUS_UNKNOWN; @@ -476,34 +443,32 @@ rnp_key_store_import_subkey_signature(rnp_key_store_t * keyring, } 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) +KeyStore::import_signature(pgp_key_t &key, const pgp_signature_t &sig) { - if (key->is_subkey()) { - return rnp_key_store_import_subkey_signature(keyring, key, sig); + if (key.is_subkey()) { + return import_subkey_signature(key, sig); } - if ((sig->type() != PGP_SIG_DIRECT) && (sig->type() != PGP_SIG_REV_KEY)) { - RNP_LOG("Wrong signature type: %d", (int) sig->type()); + if ((sig.type() != PGP_SIG_DIRECT) && (sig.type() != PGP_SIG_REV_KEY)) { + RNP_LOG("Wrong signature type: %d", (int) sig.type()); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } try { - pgp_key_t tmpkey(key->pkt()); - tmpkey.add_sig(*sig); - if (!tmpkey.refresh_data(keyring->secctx)) { + pgp_key_t tmpkey(key.pkt()); + tmpkey.add_sig(sig); + if (!tmpkey.refresh_data(secctx)) { RNP_LOG("Failed to add signature to the key."); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } - size_t expackets = key->rawpkt_count(); - key = rnp_key_store_add_key(keyring, &tmpkey); - if (!key) { + size_t expackets = key.rawpkt_count(); + auto nkey = add_key(tmpkey); + if (!nkey) { RNP_LOG("Failed to add key with imported sig to the keyring"); return PGP_SIG_IMPORT_STATUS_UNKNOWN; } - return (key->rawpkt_count() > expackets) ? PGP_SIG_IMPORT_STATUS_NEW : - PGP_SIG_IMPORT_STATUS_UNCHANGED; + return (nkey->rawpkt_count() > expackets) ? PGP_SIG_IMPORT_STATUS_NEW : + PGP_SIG_IMPORT_STATUS_UNCHANGED; } catch (const std::exception &e) { RNP_LOG("%s", e.what()); return PGP_SIG_IMPORT_STATUS_UNKNOWN; @@ -511,9 +476,7 @@ rnp_key_store_import_key_signature(rnp_key_store_t * keyring, } pgp_key_t * -rnp_key_store_import_signature(rnp_key_store_t * keyring, - const pgp_signature_t * sig, - pgp_sig_import_status_t *status) +KeyStore::import_signature(const pgp_signature_t &sig, pgp_sig_import_status_t *status) { pgp_sig_import_status_t tmp_status = PGP_SIG_IMPORT_STATUS_UNKNOWN; if (!status) { @@ -522,310 +485,166 @@ rnp_key_store_import_signature(rnp_key_store_t * keyring, *status = PGP_SIG_IMPORT_STATUS_UNKNOWN; /* we support only direct-key and key revocation signatures here */ - if ((sig->type() != PGP_SIG_DIRECT) && (sig->type() != PGP_SIG_REV_KEY)) { - return NULL; + if ((sig.type() != PGP_SIG_DIRECT) && (sig.type() != PGP_SIG_REV_KEY)) { + return nullptr; } - pgp_key_t *res_key = rnp_key_store_get_signer_key(keyring, sig); + pgp_key_t *res_key = get_signer(sig); if (!res_key || !res_key->is_primary()) { *status = PGP_SIG_IMPORT_STATUS_UNKNOWN_KEY; - return NULL; + return nullptr; } - *status = rnp_key_store_import_key_signature(keyring, res_key, sig); + *status = import_signature(*res_key, sig); return res_key; } bool -rnp_key_store_remove_key(rnp_key_store_t *keyring, const pgp_key_t *key, bool subkeys) +KeyStore::remove_key(const pgp_key_t &key, bool subkeys) { - auto it = keyring->keybyfp.find(key->fp()); - if (it == keyring->keybyfp.end()) { + auto it = keybyfp.find(key.fp()); + if (it == keybyfp.end()) { return false; } /* cleanup primary_grip (or subkey)/subkey_grips */ - if (key->is_primary() && key->subkey_count()) { - for (size_t i = 0; i < key->subkey_count(); i++) { - auto it = keyring->keybyfp.find(key->get_subkey_fp(i)); - if (it == keyring->keybyfp.end()) { + if (key.is_primary() && key.subkey_count()) { + for (size_t i = 0; i < key.subkey_count(); i++) { + auto its = keybyfp.find(key.get_subkey_fp(i)); + if (its == keybyfp.end()) { continue; } /* if subkeys are deleted then no need to update grips */ if (subkeys) { - keyring->keys.erase(it->second); - keyring->keybyfp.erase(it); + keys.erase(its->second); + keybyfp.erase(its); continue; } - it->second->unset_primary_fp(); + its->second->unset_primary_fp(); } } - if (key->is_subkey() && key->has_primary_fp()) { - pgp_key_t *primary = rnp_key_store_get_primary_key(keyring, key); + if (key.is_subkey() && key.has_primary_fp()) { + pgp_key_t *primary = primary_key(key); if (primary) { - primary->remove_subkey_fp(key->fp()); + primary->remove_subkey_fp(key.fp()); } } - keyring->keys.erase(it->second); - keyring->keybyfp.erase(it); + keys.erase(it->second); + keybyfp.erase(it); return true; } const pgp_key_t * -rnp_key_store_get_key_by_fpr(const rnp_key_store_t *keyring, const pgp_fingerprint_t &fpr) +KeyStore::get_key(const pgp_fingerprint_t &fpr) const { - auto it = keyring->keybyfp.find(fpr); - if (it == keyring->keybyfp.end()) { - return NULL; + auto it = keybyfp.find(fpr); + if (it == keybyfp.end()) { + return nullptr; } return &*it->second; } pgp_key_t * -rnp_key_store_get_key_by_fpr(rnp_key_store_t *keyring, const pgp_fingerprint_t &fpr) +KeyStore::get_key(const pgp_fingerprint_t &fpr) { - auto it = keyring->keybyfp.find(fpr); - if (it == keyring->keybyfp.end()) { - return NULL; + auto it = keybyfp.find(fpr); + if (it == keybyfp.end()) { + return nullptr; } return &*it->second; } pgp_key_t * -rnp_key_store_get_primary_key(rnp_key_store_t *keyring, const pgp_key_t *subkey) +KeyStore::get_subkey(const pgp_key_t &key, size_t idx) { - if (!subkey->is_subkey()) { - return NULL; - } - - if (subkey->has_primary_fp()) { - pgp_key_t *primary = rnp_key_store_get_key_by_fpr(keyring, subkey->primary_fp()); - return primary && primary->is_primary() ? primary : NULL; - } - - for (size_t i = 0; i < subkey->sig_count(); i++) { - const pgp_subsig_t &subsig = subkey->get_sig(i); - if (subsig.sig.type() != PGP_SIG_SUBKEY) { - continue; - } - - pgp_key_t *primary = rnp_key_store_get_signer_key(keyring, &subsig.sig); - if (primary && primary->is_primary()) { - return primary; - } + if (idx >= key.subkey_count()) { + return nullptr; } - return NULL; + return get_key(key.get_subkey_fp(idx)); } -static void -grip_hash_mpi(rnp::Hash &hash, const pgp_mpi_t &val, const char name, bool lzero = true) +pgp_key_t * +KeyStore::primary_key(const pgp_key_t &subkey) { - size_t len = mpi_bytes(&val); - size_t idx = 0; - for (idx = 0; (idx < len) && !val.mpi[idx]; idx++) - ; - - if (name) { - size_t hlen = idx >= len ? 0 : len - idx; - if ((len > idx) && lzero && (val.mpi[idx] & 0x80)) { - hlen++; - } - - char buf[20] = {0}; - snprintf(buf, sizeof(buf), "(1:%c%zu:", name, hlen); - hash.add(buf, strlen(buf)); + if (!subkey.is_subkey()) { + return nullptr; } - if (idx < len) { - /* gcrypt prepends mpis with zero if higher bit is set */ - if (lzero && (val.mpi[idx] & 0x80)) { - uint8_t zero = 0; - hash.add(&zero, 1); - } - hash.add(val.mpi + idx, len - idx); - } - if (name) { - hash.add(")", 1); - } -} - -static void -grip_hash_ecc_hex(rnp::Hash &hash, const char *hex, char name) -{ - pgp_mpi_t mpi = {}; - mpi.len = rnp::hex_decode(hex, mpi.mpi, sizeof(mpi.mpi)); - if (!mpi.len) { - RNP_LOG("wrong hex mpi"); - throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + if (subkey.has_primary_fp()) { + pgp_key_t *primary = get_key(subkey.primary_fp()); + return primary && primary->is_primary() ? primary : nullptr; } - /* libgcrypt doesn't add leading zero when hashes ecc mpis */ - return grip_hash_mpi(hash, mpi, name, false); -} - -static void -grip_hash_ec(rnp::Hash &hash, const pgp_ec_key_t &key) -{ - const ec_curve_desc_t *desc = get_curve_desc(key.curve); - if (!desc) { - RNP_LOG("unknown curve %d", (int) key.curve); - throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); - } - - /* build uncompressed point from gx and gy */ - pgp_mpi_t g = {}; - g.mpi[0] = 0x04; - g.len = 1; - size_t len = rnp::hex_decode(desc->gx, g.mpi + g.len, sizeof(g.mpi) - g.len); - if (!len) { - RNP_LOG("wrong x mpi"); - throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); - } - g.len += len; - len = rnp::hex_decode(desc->gy, g.mpi + g.len, sizeof(g.mpi) - g.len); - if (!len) { - RNP_LOG("wrong y mpi"); - throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); - } - g.len += len; - - /* p, a, b, g, n, q */ - grip_hash_ecc_hex(hash, desc->p, 'p'); - grip_hash_ecc_hex(hash, desc->a, 'a'); - grip_hash_ecc_hex(hash, desc->b, 'b'); - grip_hash_mpi(hash, g, 'g', false); - grip_hash_ecc_hex(hash, desc->n, 'n'); - - if ((key.curve == PGP_CURVE_ED25519) || (key.curve == PGP_CURVE_25519)) { - if (g.len < 1) { - RNP_LOG("wrong 25519 p"); - throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); + for (size_t i = 0; i < subkey.sig_count(); i++) { + auto &subsig = subkey.get_sig(i); + if (subsig.sig.type() != PGP_SIG_SUBKEY) { + continue; } - g.len = key.p.len - 1; - memcpy(g.mpi, key.p.mpi + 1, g.len); - grip_hash_mpi(hash, g, 'q', false); - } else { - grip_hash_mpi(hash, key.p, 'q', false); - } -} -/* keygrip is subjectKeyHash from pkcs#15 for RSA. */ -bool -rnp_key_store_get_key_grip(const pgp_key_material_t *key, pgp_key_grip_t &grip) -{ - try { - auto hash = rnp::Hash::create(PGP_HASH_SHA1); - switch (key->alg) { - case PGP_PKA_RSA: - case PGP_PKA_RSA_SIGN_ONLY: - case PGP_PKA_RSA_ENCRYPT_ONLY: - grip_hash_mpi(*hash, key->rsa.n, '\0'); - break; - case PGP_PKA_DSA: - grip_hash_mpi(*hash, key->dsa.p, 'p'); - grip_hash_mpi(*hash, key->dsa.q, 'q'); - grip_hash_mpi(*hash, key->dsa.g, 'g'); - grip_hash_mpi(*hash, key->dsa.y, 'y'); - break; - case PGP_PKA_ELGAMAL: - case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - grip_hash_mpi(*hash, key->eg.p, 'p'); - grip_hash_mpi(*hash, key->eg.g, 'g'); - grip_hash_mpi(*hash, key->eg.y, 'y'); - break; - case PGP_PKA_ECDH: - case PGP_PKA_ECDSA: - case PGP_PKA_EDDSA: - case PGP_PKA_SM2: - grip_hash_ec(*hash, key->ec); - break; -#if defined(ENABLE_CRYPTO_REFRESH) - case PGP_PKA_ED25519: - hash->add(key->ed25519.pub); - break; - case PGP_PKA_X25519: - hash->add(key->x25519.pub); - break; -#endif -#if defined(ENABLE_PQC) - case PGP_PKA_KYBER768_X25519: - FALLTHROUGH_STATEMENT; - // TODO add case PGP_PKA_KYBER1024_X448: FALLTHROUGH_STATEMENT; - case PGP_PKA_KYBER768_P256: - FALLTHROUGH_STATEMENT; - case PGP_PKA_KYBER1024_P384: - FALLTHROUGH_STATEMENT; - case PGP_PKA_KYBER768_BP256: - FALLTHROUGH_STATEMENT; - case PGP_PKA_KYBER1024_BP384: - hash->add(key->kyber_ecdh.pub.get_encoded()); - break; - case PGP_PKA_DILITHIUM3_ED25519: - FALLTHROUGH_STATEMENT; - // TODO: add case PGP_PKA_DILITHIUM5_ED448: FALLTHROUGH_STATEMENT; - case PGP_PKA_DILITHIUM3_P256: - FALLTHROUGH_STATEMENT; - case PGP_PKA_DILITHIUM5_P384: - FALLTHROUGH_STATEMENT; - case PGP_PKA_DILITHIUM3_BP256: - FALLTHROUGH_STATEMENT; - case PGP_PKA_DILITHIUM5_BP384: - hash->add(key->dilithium_exdsa.pub.get_encoded()); - break; - case PGP_PKA_SPHINCSPLUS_SHA2: - FALLTHROUGH_STATEMENT; - case PGP_PKA_SPHINCSPLUS_SHAKE: - hash->add(key->sphincsplus.pub.get_encoded()); - break; -#endif - default: - RNP_LOG("unsupported public-key algorithm %d", (int) key->alg); - return false; + pgp_key_t *primary = get_signer(subsig.sig); + if (primary && primary->is_primary()) { + return primary; } - return hash->finish(grip.data()) == grip.size(); - } catch (const std::exception &e) { - RNP_LOG("Grip calculation failed: %s", e.what()); - return false; } + return nullptr; } pgp_key_t * -rnp_key_store_search(rnp_key_store_t * keyring, - const pgp_key_search_t *search, - pgp_key_t * after) +KeyStore::search(const pgp_key_search_t &search, pgp_key_t *after) { // since keys are distinguished by fingerprint then just do map lookup - if (search->type == PGP_KEY_SEARCH_FINGERPRINT) { - pgp_key_t *key = rnp_key_store_get_key_by_fpr(keyring, search->by.fingerprint); + if (search.type == PGP_KEY_SEARCH_FINGERPRINT) { + pgp_key_t *key = get_key(search.by.fingerprint); if (after && (after != key)) { RNP_LOG("searching with invalid after param"); - return NULL; + return nullptr; } // return NULL if after is specified - return after ? NULL : key; + return after ? nullptr : key; } // if after is provided, make sure it is a member of the appropriate list - auto it = - std::find_if(keyring->keys.begin(), keyring->keys.end(), [after](const pgp_key_t &key) { - return !after || (after == &key); - }); - if (after && (it == keyring->keys.end())) { + auto it = std::find_if(keys.begin(), keys.end(), [after](const pgp_key_t &key) { + return !after || (after == &key); + }); + if (after && (it == keys.end())) { RNP_LOG("searching with non-keyrings after param"); - return NULL; + return nullptr; } if (after) { it = std::next(it); } - it = std::find_if(it, keyring->keys.end(), [search](const pgp_key_t &key) { - return rnp_key_matches_search(&key, search); - }); - return (it == keyring->keys.end()) ? NULL : &(*it); + it = std::find_if( + it, keys.end(), [search](const pgp_key_t &key) { return key.matches(search); }); + return (it == keys.end()) ? nullptr : &(*it); +} + +pgp_key_t * +KeyStore::get_signer(const pgp_signature_t &sig, const KeyProvider *prov) +{ + pgp_key_request_ctx_t ctx(PGP_OP_VERIFY, false, PGP_KEY_SEARCH_UNKNOWN); + /* if we have fingerprint let's check it */ + if (sig.has_keyfp()) { + ctx.search.by.fingerprint = sig.keyfp(); + ctx.search.type = PGP_KEY_SEARCH_FINGERPRINT; + } else if (sig.has_keyid()) { + ctx.search.by.keyid = sig.keyid(); + ctx.search.type = PGP_KEY_SEARCH_KEYID; + } else { + RNP_LOG("No way to search for the signer."); + return nullptr; + } + + pgp_key_t *key = search(ctx.search); + if (key || !prov) { + return key; + } + return prov->request_key(ctx); } -rnp_key_store_t::rnp_key_store_t(pgp_key_store_format_t _format, - const std::string & _path, - rnp::SecurityContext & ctx) +KeyStore::KeyStore(pgp_key_store_format_t _format, + const std::string & _path, + rnp::SecurityContext & ctx) : secctx(ctx) { if (_format == PGP_KEY_STORE_UNKNOWN) { @@ -836,7 +655,8 @@ rnp_key_store_t::rnp_key_store_t(pgp_key_store_format_t _format, path = _path; } -rnp_key_store_t::~rnp_key_store_t() +KeyStore::~KeyStore() { - rnp_key_store_clear(this); + clear(); } +} // namespace rnp diff --git a/src/librepgp/stream-dump.cpp b/src/librepgp/stream-dump.cpp index 644af5b61f..bc33b68156 100644 --- a/src/librepgp/stream-dump.cpp +++ b/src/librepgp/stream-dump.cpp @@ -1036,7 +1036,7 @@ stream_dump_key(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst) if (ctx->dump_grips) { pgp_key_grip_t grip; - if (rnp_key_store_get_key_grip(&key.material, grip)) { + if (key.material.get_grip(grip)) { dst_print_hex(dst, "grip", grip.data(), grip.size(), false); } else { dst_printf(dst, "grip: failed to calculate"); @@ -2185,7 +2185,7 @@ stream_dump_key_json(rnp_dump_ctx_t *ctx, pgp_source_t *src, json_object *pkt) } pgp_key_grip_t grip; - if (!rnp_key_store_get_key_grip(&key.material, grip) || + if (!key.material.get_grip(grip) || !json_add_hex(pkt, "grip", grip.data(), grip.size())) { return RNP_ERROR_OUT_OF_MEMORY; } diff --git a/src/librepgp/stream-key.cpp b/src/librepgp/stream-key.cpp index 7c9a5c4e29..412855c79e 100644 --- a/src/librepgp/stream-key.cpp +++ b/src/librepgp/stream-key.cpp @@ -47,7 +47,6 @@ #include "crypto.h" #include "crypto/signatures.h" #include "crypto/mem.h" -#include "../librekey/key_store_pgp.h" #include "str-utils.h" #include #include @@ -91,7 +90,7 @@ rnp_result_t transferable_subkey_from_key(pgp_transferable_subkey_t &dst, const pgp_key_t &key) { try { - auto vec = rnp_key_to_vec(key); + auto vec = key.write_vec(); rnp::MemorySource mem(vec); return process_pgp_subkey(mem.src(), dst, false); } catch (const std::exception &e) { @@ -119,7 +118,7 @@ rnp_result_t transferable_key_from_key(pgp_transferable_key_t &dst, const pgp_key_t &key) { try { - auto vec = rnp_key_to_vec(key); + auto vec = key.write_vec(); rnp::MemorySource mem(vec); return process_pgp_key(mem.src(), dst, false); } catch (const std::exception &e) { diff --git a/src/librepgp/stream-parse.cpp b/src/librepgp/stream-parse.cpp index aed70530bf..f80fe5d16d 100644 --- a/src/librepgp/stream-parse.cpp +++ b/src/librepgp/stream-parse.cpp @@ -874,11 +874,11 @@ signed_validate_signature(pgp_source_signed_param_t ¶m, pgp_signature_info_t return; } /* Get the public key */ - pgp_key_t *key = pgp_request_key(param.handler->key_provider, &keyctx); + pgp_key_t *key = param.handler->key_provider->request_key(keyctx); if (!key) { /* fallback to secret key */ keyctx.secret = true; - if (!(key = pgp_request_key(param.handler->key_provider, &keyctx))) { + if (!(key = param.handler->key_provider->request_key(keyctx))) { RNP_LOG("signer's key not found"); sinfo.no_signer = true; return; @@ -2408,7 +2408,7 @@ init_encrypted_src(pgp_parse_handler_t *handler, pgp_source_t *src, pgp_source_t #endif /* Get the key if any */ - pgp_key_t *seckey = pgp_request_key(handler->key_provider, &keyctx); + pgp_key_t *seckey = handler->key_provider->request_key(keyctx); if (!seckey) { pubidx++; continue; diff --git a/src/librepgp/stream-parse.h b/src/librepgp/stream-parse.h index 1bee9fd823..9ea1d56d7f 100644 --- a/src/librepgp/stream-parse.h +++ b/src/librepgp/stream-parse.h @@ -60,9 +60,9 @@ typedef void pgp_decryption_done_func_t(bool validated, void *param); /* handler used to return needed information during pgp source processing */ typedef struct pgp_parse_handler_t { pgp_password_provider_t *password_provider; /* if NULL then default will be used */ - pgp_key_provider_t * key_provider; /* must be set when key is required, i.e. during - signing/verification/public key encryption and - deryption */ + rnp::KeyProvider * key_provider; /* must be set when key is required, i.e. during + signing/verification/public key encryption and + deryption */ pgp_destination_func_t *dest_provider; /* called when destination stream is required */ pgp_source_func_t * src_provider; /* required to provider source during the detached signature verification */ diff --git a/src/librepgp/stream-write.h b/src/librepgp/stream-write.h index 49431f9152..d4b12ce8f6 100644 --- a/src/librepgp/stream-write.h +++ b/src/librepgp/stream-write.h @@ -35,11 +35,11 @@ #include "stream-ctx.h" typedef struct pgp_write_handler_t { - pgp_password_provider_t *password_provider; - pgp_key_provider_t * key_provider; - rnp_ctx_t * ctx; + pgp_password_provider_t *password_provider{}; + rnp::KeyProvider * key_provider{}; + rnp_ctx_t * ctx{}; - void *param; + void *param{}; } pgp_write_handler_t; /** @brief sign the input data, producing attached, detached or cleartext signature. diff --git a/src/tests/cli.cpp b/src/tests/cli.cpp index a96115cf06..d1552a1403 100644 --- a/src/tests/cli.cpp +++ b/src/tests/cli.cpp @@ -617,9 +617,7 @@ TEST_F(rnp_tests, test_cli_rnpkeys) // check both primary key and subkey for the given userid static int -key_expiration_check(rnp_key_store_t *keystore, - const char * userid, - uint32_t expectedExpiration) +key_expiration_check(rnp::KeyStore *keystore, const char *userid, uint32_t expectedExpiration) { int res = -1; // not found for (auto &key : keystore->keys) { @@ -630,7 +628,10 @@ key_expiration_check(rnp_key_store_t *keystore, if (!key.has_primary_fp()) { return 0; } - pk = rnp_key_store_get_key_by_fpr(keystore, key.primary_fp()); + pk = keystore->get_key(key.primary_fp()); + if (!pk) { + return 0; + } } if (pk->uid_count() != 1) { return 0; @@ -767,11 +768,11 @@ TEST_F(rnp_tests, test_cli_rnpkeys_genkey) assert_int_equal(key_generate(GENKEYS, "expiration_2months@rnp", "2m"), 0); assert_int_equal(key_generate(GENKEYS, "expiration_2years@rnp", "2y"), 0); - auto keystore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); + auto keystore = new rnp::KeyStore(PGP_KEY_STORE_GPG, "", global_ctx); pgp_source_t src = {}; assert_rnp_success(init_file_src(&src, GENKEYS "/pubring.gpg")); - assert_true(rnp_key_store_load_from_src(keystore, &src, NULL)); - assert_int_equal(rnp_key_store_get_key_count(keystore), 34); + assert_true(keystore->load(src)); + assert_int_equal(keystore->key_count(), 34); src_close(&src); assert_int_equal(key_expiration_check(keystore, "expiration_max_32bit@rnp", 4294967295), 1); diff --git a/src/tests/generatekey.cpp b/src/tests/generatekey.cpp index bf948b7bae..c89174315c 100644 --- a/src/tests/generatekey.cpp +++ b/src/tests/generatekey.cpp @@ -995,10 +995,10 @@ TEST_F(rnp_tests, generatekeyECDSA_explicitlySetUnknownDigest_ShouldFail) */ TEST_F(rnp_tests, test_generated_key_sigs) { - rnp_key_store_t *pubring = new rnp_key_store_t(global_ctx); - rnp_key_store_t *secring = new rnp_key_store_t(global_ctx); - pgp_key_t * primary_pub = NULL, *primary_sec = NULL; - pgp_key_t * sub_pub = NULL, *sub_sec = NULL; + auto pubring = new rnp::KeyStore(global_ctx); + auto secring = new rnp::KeyStore(global_ctx); + pgp_key_t *primary_pub = NULL, *primary_sec = NULL; + pgp_key_t *sub_pub = NULL, *sub_sec = NULL; // primary { @@ -1020,8 +1020,8 @@ TEST_F(rnp_tests, test_generated_key_sigs) assert_true(pgp_generate_primary_key(desc, true, sec, pub, PGP_KEY_STORE_GPG)); // add to our rings - assert_true(rnp_key_store_add_key(pubring, &pub)); - assert_true(rnp_key_store_add_key(secring, &sec)); + assert_true(pubring->add_key(pub)); + assert_true(secring->add_key(sec)); // retrieve back from our rings (for later) primary_pub = rnp_tests_get_key_by_grip(pubring, pub.grip()); primary_sec = rnp_tests_get_key_by_grip(secring, pub.grip()); @@ -1216,8 +1216,8 @@ TEST_F(rnp_tests, test_generated_key_sigs) ssig->hashed_data[10] ^= 0xff; // add to our rings - assert_true(rnp_key_store_add_key(pubring, &pub)); - assert_true(rnp_key_store_add_key(secring, &sec)); + assert_true(pubring->add_key(pub)); + assert_true(secring->add_key(sec)); // retrieve back from our rings sub_pub = rnp_tests_get_key_by_grip(pubring, pub.grip()); sub_sec = rnp_tests_get_key_by_grip(secring, pub.grip()); diff --git a/src/tests/kbx-nsigs-test.cpp b/src/tests/kbx-nsigs-test.cpp index 7b4b8b80a3..5ad338a6e9 100644 --- a/src/tests/kbx-nsigs-test.cpp +++ b/src/tests/kbx-nsigs-test.cpp @@ -25,7 +25,6 @@ */ #include -#include #include #include "rnp_tests.h" diff --git a/src/tests/key-add-userid.cpp b/src/tests/key-add-userid.cpp index b80dbb6cf0..e6686c51f9 100644 --- a/src/tests/key-add-userid.cpp +++ b/src/tests/key-add-userid.cpp @@ -24,7 +24,6 @@ * 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" @@ -45,10 +44,10 @@ TEST_F(rnp_tests, test_key_add_userid) "54505a936a4a970e", "326ef111425d14a5"}; - rnp_key_store_t *ks = new rnp_key_store_t(global_ctx); + auto ks = new rnp::KeyStore(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)); + assert_rnp_success(ks->load_pgp(src)); src_close(&src); // locate our key @@ -157,11 +156,11 @@ TEST_F(rnp_tests, test_key_add_userid) key = NULL; // start over - ks = new rnp_key_store_t(global_ctx); + ks = new rnp::KeyStore(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)); + assert_rnp_success(ks->load_pgp(src)); src_close(&src); dst_close(&dst, true); assert_non_null(key = rnp_tests_get_key_by_id(ks, keyids[0])); diff --git a/src/tests/key-grip.cpp b/src/tests/key-grip.cpp index 7e16e9f8df..79c97e7e1c 100644 --- a/src/tests/key-grip.cpp +++ b/src/tests/key-grip.cpp @@ -24,7 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../librekey/key_store_pgp.h" #include "../librepgp/stream-packet.h" #include "../librepgp/stream-sig.h" #include "pgp-key.h" @@ -34,14 +33,14 @@ TEST_F(rnp_tests, key_grip) { - rnp_key_store_t *pub_store = new rnp_key_store_t( + auto pub_store = new rnp::KeyStore( PGP_KEY_STORE_KBX, "data/test_stream_key_load/g10/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pub_store, NULL)); + assert_true(pub_store->load()); - rnp_key_store_t *sec_store = new rnp_key_store_t( + auto sec_store = new rnp::KeyStore( PGP_KEY_STORE_G10, "data/test_stream_key_load/g10/private-keys-v1.d", global_ctx); - pgp_key_provider_t key_provider(rnp_key_provider_store, pub_store); - assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + rnp::KeyProvider key_provider(rnp_key_provider_store, pub_store); + assert_true(sec_store->load(&key_provider)); const pgp_key_t *key = NULL; // dsa-eg public/secret key diff --git a/src/tests/key-protect.cpp b/src/tests/key-protect.cpp index c9acf382d2..74e800a6a3 100644 --- a/src/tests/key-protect.cpp +++ b/src/tests/key-protect.cpp @@ -24,7 +24,6 @@ * 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" @@ -48,11 +47,11 @@ TEST_F(rnp_tests, test_key_protect_load_pgp) // load our keyring and do some quick checks { - pgp_source_t src = {}; - rnp_key_store_t *ks = new rnp_key_store_t(global_ctx); + pgp_source_t src = {}; + auto ks = new rnp::KeyStore(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)); + assert_rnp_success(ks->load_pgp(src)); src_close(&src); for (size_t i = 0; i < ARRAY_SIZE(keyids); i++) { @@ -125,11 +124,11 @@ TEST_F(rnp_tests, test_key_protect_load_pgp) // confirm that packets[0] is no longer encrypted { pgp_source_t memsrc = {}; - rnp_key_store_t *ks = new rnp_key_store_t(global_ctx); + auto ks = new rnp::KeyStore(global_ctx); pgp_rawpacket_t &pkt = key->rawpkt(); assert_rnp_success(init_mem_src(&memsrc, pkt.raw.data(), pkt.raw.size(), false)); - assert_rnp_success(rnp_key_store_pgp_read_from_src(ks, &memsrc)); + assert_rnp_success(ks->load_pgp(memsrc)); src_close(&memsrc); // grab the first key diff --git a/src/tests/key-store-search.cpp b/src/tests/key-store-search.cpp index aabd4bd01c..af9a67cefb 100644 --- a/src/tests/key-store-search.cpp +++ b/src/tests/key-store-search.cpp @@ -26,7 +26,6 @@ #include #include -#include "../librekey/key_store_pgp.h" #include "pgp-key.h" #include "rnp_tests.h" @@ -38,7 +37,7 @@ TEST_F(rnp_tests, test_key_store_search) { // create our store - rnp_key_store_t *store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); + auto store = new rnp::KeyStore(PGP_KEY_STORE_GPG, "", global_ctx); store->disable_validation = true; // some fake key data @@ -62,7 +61,7 @@ TEST_F(rnp_tests, test_key_store_search) // set the keyid assert_true(rnp::hex_decode( testdata[i].keyid, (uint8_t *) key.keyid().data(), key.keyid().size())); - // keys should have different grips otherwise rnp_key_store_add_key will fail here + // keys should have different grips otherwise store->add_key will fail here pgp_key_grip_t &grip = (pgp_key_grip_t &) key.grip(); assert_true(rnp::hex_decode(testdata[i].keyid, grip.data(), grip.size())); grip[0] = (uint8_t) n; @@ -83,7 +82,7 @@ TEST_F(rnp_tests, test_key_store_search) key.add_uid(tuid); } // add to the store - assert_true(rnp_key_store_add_key(store, &key)); + assert_true(store->add_key(key)); } } @@ -165,14 +164,14 @@ TEST_F(rnp_tests, test_key_store_search_by_name) pgp_key_t * subpub; // load pubring - rnp_key_store_t *pub_store = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pub_store, NULL)); + auto pub_store = + new rnp::KeyStore(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); + assert_true(pub_store->load()); // load secring - rnp_key_store_t *sec_store = - new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); - pgp_key_provider_t key_provider(rnp_key_provider_store, pub_store); - assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + auto sec_store = + new rnp::KeyStore(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); + rnp::KeyProvider key_provider(rnp_key_provider_store, pub_store); + assert_true(sec_store->load(&key_provider)); /* Main key fingerprint and id: 4F2E62B74E6A4CD333BC19004BE147BB22DF1E60, 4BE147BB22DF1E60 diff --git a/src/tests/key-unlock.cpp b/src/tests/key-unlock.cpp index 445c70463c..53ccb94687 100644 --- a/src/tests/key-unlock.cpp +++ b/src/tests/key-unlock.cpp @@ -24,7 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../librekey/key_store_pgp.h" #include "../librepgp/stream-ctx.h" #include "pgp-key.h" #include "ffi-priv-types.h" diff --git a/src/tests/key-validate.cpp b/src/tests/key-validate.cpp index 928415bf46..a361cd6ac3 100644 --- a/src/tests/key-validate.cpp +++ b/src/tests/key-validate.cpp @@ -24,7 +24,6 @@ * 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" @@ -33,7 +32,7 @@ #include "../librepgp/stream-armor.h" static bool -all_keys_valid(const rnp_key_store_t *keyring, pgp_key_t *except = NULL) +all_keys_valid(const rnp::KeyStore *keyring, pgp_key_t *except = NULL) { char keyid[PGP_KEY_ID_SIZE * 2 + 3] = {0}; @@ -55,13 +54,11 @@ all_keys_valid(const rnp_key_store_t *keyring, pgp_key_t *except = NULL) TEST_F(rnp_tests, test_key_validate) { - rnp_key_store_t *pubring; - rnp_key_store_t *secring; - pgp_key_t * key = NULL; + pgp_key_t *key = NULL; - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + auto pubring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); + assert_true(pubring->load()); /* this keyring has one expired subkey */ assert_non_null(key = rnp_tests_get_key_by_id(pubring, "1d7e8a5393c997a8")); assert_false(key->valid()); @@ -70,82 +67,75 @@ TEST_F(rnp_tests, test_key_validate) delete pubring; /* secret key is marked is expired as well */ - secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/secring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); + auto secring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/1/secring.gpg", global_ctx); + assert_true(secring->load()); assert_non_null(key = rnp_tests_get_key_by_id(secring, "1d7e8a5393c997a8")); assert_false(key->valid()); assert_true(key->expired()); assert_true(all_keys_valid(secring, key)); delete secring; - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_true(all_keys_valid(pubring)); /* secret keyring doesn't have signatures - so keys are marked as invalid */ - secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/secring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); + secring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/2/secring.gpg", global_ctx); + assert_true(secring->load()); assert_false(all_keys_valid(secring)); /* but after adding signatures from public it is marked as valid */ assert_non_null(key = rnp_tests_get_key_by_id(pubring, "dc70c124a50283f1")); - assert_non_null(rnp_key_store_import_key(secring, key, true, NULL)); + assert_non_null(secring->import_key(*key, true)); assert_true(all_keys_valid(secring)); delete pubring; delete secring; - pubring = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + pubring = new rnp::KeyStore(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); + assert_true(pubring->load()); assert_true(all_keys_valid(pubring)); secring = - new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); - pgp_key_provider_t key_provider(rnp_key_provider_store, pubring); - assert_true(rnp_key_store_load_from_path(secring, &key_provider)); + new rnp::KeyStore(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); + rnp::KeyProvider key_provider(rnp_key_provider_store, pubring); + assert_true(secring->load(&key_provider)); assert_true(all_keys_valid(secring)); delete pubring; delete secring; - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/pubring.pgp", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/4/pubring.pgp", global_ctx); + assert_true(pubring->load()); /* certification has signature with MD5 hash algorithm */ assert_false(all_keys_valid(pubring)); - rnp_key_store_clear(pubring); + pubring->clear(); /* add rule which allows MD5 */ rnp::SecurityRule allow_md5( rnp::FeatureType::Hash, PGP_HASH_MD5, rnp::SecurityLevel::Default); allow_md5.override = true; global_ctx.profile.add_rule(allow_md5); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_true(all_keys_valid(pubring)); - rnp_key_store_clear(pubring); + pubring->clear(); /* remove rule */ assert_true(global_ctx.profile.del_rule(allow_md5)); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_false(all_keys_valid(pubring)); delete pubring; /* secret keyring doesn't have certifications - so marked as invalid */ - secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/secring.pgp", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); + secring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/4/secring.pgp", global_ctx); + assert_true(secring->load()); assert_false(all_keys_valid(secring)); delete secring; - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/5/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/5/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_true(all_keys_valid(pubring)); delete pubring; - secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/5/secring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); + secring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/5/secring.gpg", global_ctx); + assert_true(secring->load()); assert_true(all_keys_valid(secring)); delete secring; } @@ -153,19 +143,19 @@ TEST_F(rnp_tests, test_key_validate) #define DATA_PATH "data/test_forged_keys/" static void -key_store_add(rnp_key_store_t *keyring, const char *keypath) +key_store_add(rnp::KeyStore *keyring, const char *keypath) { pgp_source_t keysrc = {}; pgp_transferable_key_t tkey = {}; assert_rnp_success(init_file_src(&keysrc, keypath)); assert_rnp_success(process_pgp_key(keysrc, tkey, false)); - assert_true(rnp_key_store_add_transferable_key(keyring, &tkey)); + assert_true(keyring->add_ts_key(tkey)); src_close(&keysrc); } static bool -key_check(rnp_key_store_t *keyring, const std::string &keyid, bool valid, bool expired = false) +key_check(rnp::KeyStore *keyring, const std::string &keyid, bool valid, bool expired = false) { pgp_key_t *key = rnp_tests_get_key_by_id(keyring, keyid); return key && (key->validated()) && (key->valid() == valid) && (key->expired() == expired); @@ -173,49 +163,46 @@ key_check(rnp_key_store_t *keyring, const std::string &keyid, bool valid, bool e TEST_F(rnp_tests, test_forged_key_validate) { - rnp_key_store_t *pubring; - pgp_key_t * key = NULL; - - pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); + auto pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "", global_ctx); /* load valid dsa-eg key */ key_store_add(pubring, DATA_PATH "dsa-eg-pub.pgp"); assert_true(key_check(pubring, "C8A10A7D78273E10", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load dsa-eg key with forged self-signature and binding. Subkey will not be valid as * well. */ key_store_add(pubring, DATA_PATH "dsa-eg-pub-forged-key.pgp"); assert_true(key_check(pubring, "C8A10A7D78273E10", false)); assert_true(key_check(pubring, "02A5715C3537717E", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load dsa-eg key with forged key material */ key_store_add(pubring, DATA_PATH "dsa-eg-pub-forged-material.pgp"); - key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10"); + pgp_key_t *key = rnp_tests_get_key_by_id(pubring, "C8A10A7D78273E10"); assert_null(key); /* malformed key material causes keyid change */ key = rnp_tests_get_key_by_id(pubring, "C258AB3B54097B9B"); assert_non_null(key); assert_false(key->valid()); assert_false(key->expired()); - rnp_key_store_clear(pubring); + pubring->clear(); /* load dsa-eg keypair with forged subkey binding signature */ key_store_add(pubring, DATA_PATH "dsa-eg-pub-forged-subkey.pgp"); assert_true(key_check(pubring, "02A5715C3537717E", false)); assert_true(key_check(pubring, "C8A10A7D78273E10", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load valid eddsa key */ key_store_add(pubring, DATA_PATH "ecc-25519-pub.pgp"); assert_true(key_check(pubring, "CC786278981B0728", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load eddsa key with forged self-signature */ key_store_add(pubring, DATA_PATH "ecc-25519-pub-forged-key.pgp"); assert_true(key_check(pubring, "CC786278981B0728", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load eddsa key with forged key material */ key_store_add(pubring, DATA_PATH "ecc-25519-pub-forged-material.pgp"); @@ -223,20 +210,20 @@ TEST_F(rnp_tests, test_forged_key_validate) assert_non_null(key); assert_false(key->valid()); assert_false(key->expired()); - rnp_key_store_clear(pubring); + pubring->clear(); /* load valid ecdsa/ecdh p-256 keypair */ key_store_add(pubring, DATA_PATH "ecc-p256-pub.pgp"); assert_true(key_check(pubring, "23674F21B2441527", true)); assert_true(key_check(pubring, "37E285E9E9851491", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh key with forged self-signature. Both valid since there is valid binding. */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-forged-key.pgp"); assert_true(key_check(pubring, "23674F21B2441527", true)); assert_true(key_check(pubring, "37E285E9E9851491", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh key with forged key material. Subkey is not valid as well. */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-forged-material.pgp"); @@ -247,51 +234,51 @@ TEST_F(rnp_tests, test_forged_key_validate) assert_false(key->valid()); assert_false(key->expired()); assert_true(key_check(pubring, "37E285E9E9851491", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh keypair with forged subkey binding signature */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-forged-subkey.pgp"); assert_true(key_check(pubring, "37E285E9E9851491", false)); assert_true(key_check(pubring, "23674F21B2441527", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh keypair without certification: valid since have binding */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-no-certification.pgp"); assert_true(key_check(pubring, "23674F21B2441527", true)); assert_true(key_check(pubring, "37E285E9E9851491", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh keypair without certification and invalid binding */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-no-cert-malf-binding.pgp"); assert_true(key_check(pubring, "23674F21B2441527", false)); assert_true(key_check(pubring, "37E285E9E9851491", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh keypair without subkey binding */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-no-binding.pgp"); assert_true(key_check(pubring, "23674F21B2441527", true)); assert_true(key_check(pubring, "37E285E9E9851491", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load valid rsa/rsa keypair */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub.pgp"); /* it is valid only till year 2024 since SHA1 hash is used for signatures */ assert_true(key_check(pubring, "2FB9179118898E8B", true)); assert_true(key_check(pubring, "6E2F73008F8B8D6E", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load eddsa key which uses SHA1 signature and is created after the cutoff date */ global_ctx.set_time(SHA1_KEY_FROM + 10); key_store_add(pubring, DATA_PATH "eddsa-2024-pub.pgp"); assert_false(key_check(pubring, "980E3741F632212C", true)); assert_false(key_check(pubring, "6DA00BF7F8B59B53", true)); global_ctx.set_time(0); - rnp_key_store_clear(pubring); + pubring->clear(); /* load rsa/rsa key with forged self-signature. Valid because of valid binding. */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub-forged-key.pgp"); assert_true(key_check(pubring, "2FB9179118898E8B", true)); assert_true(key_check(pubring, "6E2F73008F8B8D6E", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load rsa/rsa key with forged key material. Subkey is not valid as well. */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub-forged-material.pgp"); @@ -302,45 +289,45 @@ TEST_F(rnp_tests, test_forged_key_validate) assert_false(key->valid()); assert_false(key->expired()); assert_true(key_check(pubring, "6E2F73008F8B8D6E", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load rsa/rsa keypair with forged subkey binding signature */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub-forged-subkey.pgp"); assert_true(key_check(pubring, "2FB9179118898E8B", true)); assert_true(key_check(pubring, "6E2F73008F8B8D6E", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load rsa/rsa keypair with future creation date */ key_store_add(pubring, DATA_PATH "rsa-rsa-pub-future-key.pgp"); assert_true(key_check(pubring, "3D032D00EE1EC3F5", false)); assert_true(key_check(pubring, "021085B640CE8DCE", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load eddsa/rsa keypair with certification with future creation date - valid because of * binding. */ key_store_add(pubring, DATA_PATH "ecc-25519-pub-future-cert.pgp"); assert_true(key_check(pubring, "D3B746FA852C2BE8", true)); assert_true(key_check(pubring, "EB8C21ACDC15CA14", true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load eddsa/rsa keypair with certification with future creation date - invalid because of * invalid binding. */ key_store_add(pubring, DATA_PATH "ecc-25519-pub-future-cert-malf-bind.pgp"); assert_true(key_check(pubring, "D3B746FA852C2BE8", false)); assert_true(key_check(pubring, "EB8C21ACDC15CA14", false)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/rsa keypair with expired subkey */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-expired-subkey.pgp"); assert_true(key_check(pubring, "23674F21B2441527", true)); assert_true(key_check(pubring, "37E285E9E9851491", false, true)); - rnp_key_store_clear(pubring); + pubring->clear(); /* load ecdsa/ecdh keypair with expired key */ key_store_add(pubring, DATA_PATH "ecc-p256-pub-expired-key.pgp"); assert_true(key_check(pubring, "23674F21B2441527", false, true)); assert_true(key_check(pubring, "37E285E9E9851491", false)); - rnp_key_store_clear(pubring); + pubring->clear(); delete pubring; } @@ -349,17 +336,15 @@ TEST_F(rnp_tests, test_forged_key_validate) TEST_F(rnp_tests, test_key_validity) { - rnp_key_store_t *pubring; - pgp_key_t * key = NULL; - /* Case1: * Keys: Alice [pub] * Alice is signed by Basil, but without the Basil's key. * Result: Alice [valid] */ - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case1/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + auto pubring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case1/pubring.gpg", global_ctx); + assert_true(pubring->load()); + pgp_key_t *key = NULL; assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); assert_false(key->expired()); @@ -372,8 +357,8 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [invalid], Basil [valid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case2/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case2/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_false(key->expired()); @@ -388,8 +373,8 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case3/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case3/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_false(key->expired()); @@ -404,14 +389,14 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [valid], Alice sub [invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case4/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case4/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); assert_false(key->expired()); assert_int_equal(key->subkey_count(), 1); pgp_key_t *subkey = NULL; - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -425,13 +410,13 @@ TEST_F(rnp_tests, test_key_validity) * To build it, feed -DBUILD_TESTING_GENERATORS=On to the cmake. */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case5/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case5/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); assert_false(key->expired()); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -442,14 +427,14 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [invalid], Alice sub [invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case6/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case6/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_false(key->valid()); assert_false(key->expired()); assert_true(key->revoked()); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); assert_false(subkey->revoked()); @@ -461,14 +446,14 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [valid], Alice sub [invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case7/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case7/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_key_search(pubring, "Alice ")); assert_true(key->valid()); assert_false(key->expired()); assert_false(key->revoked()); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); assert_true(subkey->revoked()); @@ -480,12 +465,12 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [valid], Alice sub[valid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case8/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case8/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_true(key->valid()); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_true(subkey->valid()); delete pubring; @@ -496,14 +481,14 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [valid], Alice sub[valid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case9/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case9/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_true(key->valid()); assert_false(key->expired()); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_true(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -514,14 +499,14 @@ TEST_F(rnp_tests, test_key_validity) * Result: Alice [invalid], Alice sub[invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case10/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case10/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -532,15 +517,15 @@ TEST_F(rnp_tests, test_key_validity) * expiring primary userid certification. Result: Alice [invalid], Alice sub[invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case11/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case11/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 100); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -551,15 +536,15 @@ TEST_F(rnp_tests, test_key_validity) * expiring primary userid certification. Result: Alice [invalid], Alice sub[invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case12/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case12/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 2000); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -570,15 +555,15 @@ TEST_F(rnp_tests, test_key_validity) * non-expiring primary userid certification. Result: Alice [invalid], Alice sub[invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case13/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case13/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 6); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -590,15 +575,15 @@ TEST_F(rnp_tests, test_key_validity) * Alice [invalid], Alice sub[invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case14/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case14/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "0451409669FFDE3C")); assert_false(key->valid()); assert_true(key->expired()); assert_int_equal(key->expiration(), 6); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -609,15 +594,15 @@ TEST_F(rnp_tests, test_key_validity) * Result: primary [valid], sub[invalid] */ pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "case15/pubring.gpg", global_ctx); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "case15/pubring.gpg", global_ctx); assert_non_null(pubring); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + assert_true(pubring->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubring, "E863072D3E9042EE")); assert_true(key->valid()); assert_false(key->expired()); assert_int_equal(key->expiration(), 0); assert_int_equal(key->subkey_count(), 1); - assert_non_null(subkey = pgp_key_get_subkey(key, pubring, 0)); + assert_non_null(subkey = pubring->get_subkey(*key, 0)); assert_false(subkey->valid()); assert_false(subkey->expired()); delete pubring; @@ -626,9 +611,9 @@ TEST_F(rnp_tests, test_key_validity) TEST_F(rnp_tests, test_key_expiry_direct_sig) { /* this test was mainly used to generate test data for cases 10-12 in test_key_validity */ - rnp_key_store_t *secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); + auto secring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp", global_ctx); + assert_true(secring->load()); pgp_key_t *key = NULL; assert_non_null(key = rnp_tests_key_search(secring, "Alice ")); assert_true(key->valid()); @@ -656,9 +641,9 @@ TEST_F(rnp_tests, test_key_expiry_direct_sig) assert_false(key->valid()); assert_true(key->expired()); - rnp_key_store_t *pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + auto pubring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp", global_ctx); + assert_true(pubring->load()); pgp_key_t *pubkey = NULL; assert_non_null(pubkey = rnp_tests_key_search(pubring, "Alice ")); assert_int_equal(pubkey->expiration(), 0); @@ -696,8 +681,8 @@ TEST_F(rnp_tests, test_key_expiry_direct_sig) delete pubring; secring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-sec.pgp", global_ctx); + assert_true(secring->load()); assert_non_null(key = rnp_tests_key_search(secring, "Alice ")); /* create direct-key signature */ sig = {}; @@ -725,8 +710,8 @@ TEST_F(rnp_tests, test_key_expiry_direct_sig) assert_int_equal(key->expiration(), 6); pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, KEYSIG_PATH "alice-sub-pub.pgp", global_ctx); + assert_true(pubring->load()); assert_non_null(pubkey = rnp_tests_key_search(pubring, "Alice ")); assert_non_null(subpub = rnp_tests_get_key_by_id(pubring, "dd23ceb7febeff17")); assert_int_equal(subpub->expiration(), 0); diff --git a/src/tests/load-g10.cpp b/src/tests/load-g10.cpp index 3e2c2c014e..8e3fed32a9 100644 --- a/src/tests/load-g10.cpp +++ b/src/tests/load-g10.cpp @@ -24,7 +24,6 @@ * 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" @@ -32,20 +31,18 @@ TEST_F(rnp_tests, test_invalid_g10) { - rnp_key_store_t * pub_store = NULL; - rnp_key_store_t * sec_store = NULL; - pgp_key_provider_t key_provider(rnp_key_provider_store); + rnp::KeyProvider key_provider(rnp_key_provider_store); // load pubring - pub_store = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pub_store, NULL)); + auto pub_store = + new rnp::KeyStore(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); + assert_true(pub_store->load()); // trigger "Unsupported public key algorithm:" error message - sec_store = new rnp_key_store_t( + auto sec_store = new rnp::KeyStore( PGP_KEY_STORE_G10, "data/test_invalid_g10/private-keys-v1.d", global_ctx); key_provider.userdata = pub_store; - assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + assert_true(sec_store->load(&key_provider)); // NULL key_provider - assert_true(rnp_key_store_load_from_path(sec_store, NULL)); + assert_true(sec_store->load()); delete pub_store; delete sec_store; @@ -56,19 +53,17 @@ TEST_F(rnp_tests, test_invalid_g10) */ TEST_F(rnp_tests, test_load_g10) { - rnp_key_store_t * pub_store = NULL; - rnp_key_store_t * sec_store = NULL; - pgp_key_provider_t key_provider(rnp_key_provider_store); + rnp::KeyProvider key_provider(rnp_key_provider_store); // load pubring - pub_store = - new rnp_key_store_t(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pub_store, NULL)); + auto pub_store = + new rnp::KeyStore(PGP_KEY_STORE_KBX, "data/keyrings/3/pubring.kbx", global_ctx); + assert_true(pub_store->load()); // load secring - sec_store = - new rnp_key_store_t(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); + auto sec_store = + new rnp::KeyStore(PGP_KEY_STORE_G10, "data/keyrings/3/private-keys-v1.d", global_ctx); key_provider.userdata = pub_store; - assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + assert_true(sec_store->load(&key_provider)); /* check primary key and subkey */ test_load_gpg_check_key(pub_store, sec_store, "4BE147BB22DF1E60"); @@ -79,13 +74,13 @@ TEST_F(rnp_tests, test_load_g10) delete sec_store; /* another store */ - pub_store = new rnp_key_store_t( + pub_store = new rnp::KeyStore( PGP_KEY_STORE_KBX, "data/test_stream_key_load/g10/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pub_store, NULL)); - sec_store = new rnp_key_store_t( + assert_true(pub_store->load()); + sec_store = new rnp::KeyStore( PGP_KEY_STORE_G10, "data/test_stream_key_load/g10/private-keys-v1.d", global_ctx); key_provider.userdata = pub_store; - assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + assert_true(sec_store->load(&key_provider)); /* dsa/eg key */ assert_true(test_load_gpg_check_key(pub_store, sec_store, "C8A10A7D78273E10")); diff --git a/src/tests/load-g23.cpp b/src/tests/load-g23.cpp index f9873448d8..f42e2b2313 100644 --- a/src/tests/load-g23.cpp +++ b/src/tests/load-g23.cpp @@ -24,7 +24,6 @@ * 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" @@ -35,18 +34,16 @@ */ TEST_F(rnp_tests, test_load_g23) { - rnp_key_store_t * pub_store = NULL; - rnp_key_store_t * sec_store = NULL; - pgp_key_provider_t key_provider(rnp_key_provider_store); + rnp::KeyProvider key_provider(rnp_key_provider_store); /* another store */ - pub_store = new rnp_key_store_t( + auto pub_store = new rnp::KeyStore( PGP_KEY_STORE_KBX, "data/test_stream_key_load/g23/pubring.kbx", global_ctx); - assert_true(rnp_key_store_load_from_path(pub_store, NULL)); - sec_store = new rnp_key_store_t( + assert_true(pub_store->load()); + auto sec_store = new rnp::KeyStore( PGP_KEY_STORE_G10, "data/test_stream_key_load/g23/private-keys-v1.d", global_ctx); key_provider.userdata = pub_store; - assert_true(rnp_key_store_load_from_path(sec_store, &key_provider)); + assert_true(sec_store->load(&key_provider)); #ifdef CRYPTO_BACKEND_BOTAN /* GnuPG extended key format requires AEAD support that is available for BOTAN backend diff --git a/src/tests/load-kbx.cpp b/src/tests/load-kbx.cpp index 7b0b107adf..f4de9b4da6 100644 --- a/src/tests/load-kbx.cpp +++ b/src/tests/load-kbx.cpp @@ -24,8 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../librekey/key_store_pgp.h" -#include "../librekey/key_store_kbx.h" #include "pgp-key.h" #include "rnp_tests.h" diff --git a/src/tests/load-pgp.cpp b/src/tests/load-pgp.cpp index 560ed3df2f..b594f63424 100644 --- a/src/tests/load-pgp.cpp +++ b/src/tests/load-pgp.cpp @@ -24,7 +24,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../librekey/key_store_pgp.h" #include "../librepgp/stream-packet.h" #include "../librepgp/stream-sig.h" #include "pgp-key.h" @@ -40,13 +39,13 @@ TEST_F(rnp_tests, test_load_v3_keyring_pgp) { pgp_source_t src = {}; - rnp_key_store_t *key_store = new rnp_key_store_t(global_ctx); + auto key_store = new rnp::KeyStore(global_ctx); // load pubring in to the key store assert_rnp_success(init_file_src(&src, "data/keyrings/2/pubring.gpg")); - assert_rnp_success(rnp_key_store_pgp_read_from_src(key_store, &src)); + assert_rnp_success(key_store->load_pgp(src)); src_close(&src); - assert_int_equal(1, rnp_key_store_get_key_count(key_store)); + assert_int_equal(1, key_store->key_count()); // find the key by keyid const pgp_key_t *key = rnp_tests_get_key_by_id(key_store, "DC70C124A50283F1"); @@ -63,12 +62,12 @@ TEST_F(rnp_tests, test_load_v3_keyring_pgp) delete key_store; // load secret keyring and decrypt the key - key_store = new rnp_key_store_t(global_ctx); + key_store = new rnp::KeyStore(global_ctx); assert_rnp_success(init_file_src(&src, "data/keyrings/4/secring.pgp")); - assert_rnp_success(rnp_key_store_pgp_read_from_src(key_store, &src)); + assert_rnp_success(key_store->load_pgp(src)); src_close(&src); - assert_int_equal(1, rnp_key_store_get_key_count(key_store)); + assert_int_equal(1, key_store->key_count()); key = rnp_tests_get_key_by_id(key_store, "7D0BC10E933404C9"); assert_non_null(key); @@ -102,13 +101,13 @@ TEST_F(rnp_tests, test_load_v4_keyring_pgp) { pgp_source_t src = {}; - rnp_key_store_t *key_store = new rnp_key_store_t(global_ctx); + auto key_store = new rnp::KeyStore(global_ctx); // load it in to the key store assert_rnp_success(init_file_src(&src, "data/keyrings/1/pubring.gpg")); - assert_rnp_success(rnp_key_store_pgp_read_from_src(key_store, &src)); + assert_rnp_success(key_store->load_pgp(src)); src_close(&src); - assert_int_equal(7, rnp_key_store_get_key_count(key_store)); + assert_int_equal(7, key_store->key_count()); // find the key by keyid static const std::string keyid = "8a05b89fad5aded1"; @@ -128,12 +127,12 @@ check_pgp_keyring_counts(const char * path, unsigned primary_count, const unsigned subkey_counts[]) { - pgp_source_t src = {}; - rnp_key_store_t *key_store = new rnp_key_store_t(global_ctx); + pgp_source_t src = {}; + auto key_store = new rnp::KeyStore(global_ctx); // load it in to the key store assert_rnp_success(init_file_src(&src, path)); - assert_rnp_success(rnp_key_store_pgp_read_from_src(key_store, &src)); + assert_rnp_success(key_store->load_pgp(src)); src_close(&src); // count primary keys first @@ -158,8 +157,7 @@ check_pgp_keyring_counts(const char * path, } // check the total (not really needed) - assert_int_equal(rnp_key_store_get_key_count(key_store), - total_primary_count + total_subkey_count); + assert_int_equal(key_store->key_count(), total_primary_count + total_subkey_count); // cleanup delete key_store; @@ -190,9 +188,9 @@ TEST_F(rnp_tests, test_load_check_bitfields_and_times) const pgp_signature_t *sig = NULL; // load keyring - rnp_key_store_t *key_store = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(key_store, NULL)); + auto key_store = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); + assert_true(key_store->load()); // find key = NULL; @@ -334,9 +332,9 @@ TEST_F(rnp_tests, test_load_check_bitfields_and_times_v3) const pgp_signature_t *sig = NULL; // load keyring - rnp_key_store_t *key_store = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(key_store, NULL)); + auto key_store = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/2/pubring.gpg", global_ctx); + assert_true(key_store->load()); // find key = NULL; @@ -370,12 +368,12 @@ TEST_F(rnp_tests, test_load_check_bitfields_and_times_v3) TEST_F(rnp_tests, test_load_armored_pub_sec) { - rnp_key_store_t *key_store = - new rnp_key_store_t(PGP_KEY_STORE_GPG, MERGE_PATH "key-both.asc", global_ctx); - assert_true(rnp_key_store_load_from_path(key_store, NULL)); + auto key_store = + new rnp::KeyStore(PGP_KEY_STORE_GPG, MERGE_PATH "key-both.asc", global_ctx); + assert_true(key_store->load()); /* we must have 1 main key and 2 subkeys */ - assert_int_equal(rnp_key_store_get_key_count(key_store), 3); + assert_int_equal(key_store->key_count(), 3); pgp_key_t *key = NULL; assert_non_null(key = rnp_tests_get_key_by_id(key_store, "9747D2A6B3A63124")); @@ -436,10 +434,10 @@ load_transferable_subkey(pgp_transferable_subkey_t *key, const char *fname) } static bool -load_keystore(rnp_key_store_t *keystore, const char *fname) +load_keystore(rnp::KeyStore *keystore, const char *fname) { pgp_source_t src = {}; - bool res = !init_file_src(&src, fname) && !rnp_key_store_pgp_read_from_src(keystore, &src); + bool res = !init_file_src(&src, fname) && !keystore->load_pgp(src); src_close(&src); return res; } @@ -465,15 +463,15 @@ TEST_F(rnp_tests, test_load_merge) provider.callback = string_copy_password_callback; provider.userdata = (void *) "password"; - rnp_key_store_t *key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); - std::string keyid = "9747D2A6B3A63124"; - std::string sub1id = "AF1114A47F5F5B28"; - std::string sub2id = "16CD16F267CCDD4F"; + auto key_store = new rnp::KeyStore(PGP_KEY_STORE_GPG, "", global_ctx); + std::string keyid = "9747D2A6B3A63124"; + std::string sub1id = "AF1114A47F5F5B28"; + std::string sub2id = "16CD16F267CCDD4F"; /* load just key packet */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-just-key.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 1); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 1); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_false(key->valid()); assert_int_equal(key->rawpkt_count(), 1); @@ -481,8 +479,8 @@ TEST_F(rnp_tests, test_load_merge) /* load key + user id 1 without sigs */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-uid-1-no-sigs.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 1); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 1); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_false(key->valid()); assert_int_equal(key->uid_count(), 1); @@ -494,8 +492,8 @@ TEST_F(rnp_tests, test_load_merge) /* load key + user id 1 with sigs */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-uid-1.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 1); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 1); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_true(key->valid()); assert_int_equal(key->uid_count(), 1); @@ -507,10 +505,10 @@ TEST_F(rnp_tests, test_load_merge) /* load key + user id 2 with sigs */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-uid-2.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); + assert_true(key_store->add_ts_key(tkey)); /* try to add it twice */ - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 1); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 1); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_true(key->valid()); assert_int_equal(key->uid_count(), 2); @@ -525,8 +523,8 @@ TEST_F(rnp_tests, test_load_merge) /* load key + subkey 1 without sigs */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-subkey-1-no-sigs.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 2); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 2); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_true(key->valid()); @@ -546,10 +544,10 @@ TEST_F(rnp_tests, test_load_merge) /* load just subkey 1 but with signature */ assert_true(load_transferable_subkey(&tskey, MERGE_PATH "key-pub-no-key-subkey-1.pgp")); - assert_true(rnp_key_store_add_transferable_subkey(key_store, &tskey, key)); + assert_true(key_store->add_ts_subkey(tskey, key)); /* try to add it twice */ - assert_true(rnp_key_store_add_transferable_subkey(key_store, &tskey, key)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 2); + assert_true(key_store->add_ts_subkey(tskey, key)); + assert_int_equal(key_store->key_count(), 2); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_true(key->valid()); @@ -570,10 +568,10 @@ TEST_F(rnp_tests, test_load_merge) /* load key + subkey 2 with signature */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub-subkey-2.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); + assert_true(key_store->add_ts_key(tkey)); /* try to add it twice */ - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 3); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 3); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); @@ -601,10 +599,10 @@ TEST_F(rnp_tests, test_load_merge) /* load secret key & subkeys */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-sec-no-uid-no-sigs.pgp")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); + assert_true(key_store->add_ts_key(tkey)); /* try to add it twice */ - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 3); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 3); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); @@ -636,10 +634,10 @@ TEST_F(rnp_tests, test_load_merge) /* load the whole public + secret key */ assert_true(load_transferable_key(&tkey, MERGE_PATH "key-pub.asc")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); + assert_true(key_store->add_ts_key(tkey)); assert_true(load_transferable_key(&tkey, MERGE_PATH "key-sec.asc")); - assert_true(rnp_key_store_add_transferable_key(key_store, &tkey)); - assert_int_equal(rnp_key_store_get_key_count(key_store), 3); + assert_true(key_store->add_ts_key(tkey)); + assert_int_equal(key_store->key_count(), 3); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); @@ -672,11 +670,9 @@ TEST_F(rnp_tests, test_load_merge) TEST_F(rnp_tests, test_load_public_from_secret) { - rnp_key_store_t *secstore = - new rnp_key_store_t(PGP_KEY_STORE_GPG, MERGE_PATH "key-sec.asc", global_ctx); - assert_true(rnp_key_store_load_from_path(secstore, NULL)); - rnp_key_store_t *pubstore = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "pubring.gpg", global_ctx); + auto secstore = new rnp::KeyStore(PGP_KEY_STORE_GPG, MERGE_PATH "key-sec.asc", global_ctx); + assert_true(secstore->load()); + auto pubstore = new rnp::KeyStore(PGP_KEY_STORE_GPG, "pubring.gpg", global_ctx); std::string keyid = "9747D2A6B3A63124"; std::string sub1id = "AF1114A47F5F5B28"; @@ -707,7 +703,7 @@ TEST_F(rnp_tests, test_load_public_from_secret) assert_null(keycp.pkt().sec_data); assert_int_equal(keycp.pkt().sec_len, 0); assert_false(keycp.pkt().material.secret); - rnp_key_store_add_key(pubstore, &keycp); + pubstore->add_key(keycp); /* subkey 1 */ keycp = pgp_key_t(*skey1, true); assert_false(keycp.is_secret()); @@ -719,7 +715,7 @@ TEST_F(rnp_tests, test_load_public_from_secret) assert_null(keycp.pkt().sec_data); assert_int_equal(keycp.pkt().sec_len, 0); assert_false(keycp.pkt().material.secret); - rnp_key_store_add_key(pubstore, &keycp); + pubstore->add_key(keycp); /* subkey 2 */ keycp = pgp_key_t(*skey2, true); assert_false(keycp.is_secret()); @@ -731,13 +727,13 @@ TEST_F(rnp_tests, test_load_public_from_secret) assert_null(keycp.pkt().sec_data); assert_int_equal(keycp.pkt().sec_len, 0); assert_false(keycp.pkt().material.secret); - rnp_key_store_add_key(pubstore, &keycp); + pubstore->add_key(keycp); /* save pubring */ - assert_true(rnp_key_store_write_to_path(pubstore)); + assert_true(pubstore->write()); delete pubstore; /* reload */ - pubstore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubstore, NULL)); + pubstore = new rnp::KeyStore(PGP_KEY_STORE_GPG, "pubring.gpg", global_ctx); + assert_true(pubstore->load()); assert_non_null(key = rnp_tests_get_key_by_id(pubstore, keyid)); assert_non_null(skey1 = rnp_tests_get_key_by_id(pubstore, sub1id)); assert_non_null(skey2 = rnp_tests_get_key_by_id(pubstore, sub2id)); @@ -927,15 +923,15 @@ TEST_F(rnp_tests, test_key_import) TEST_F(rnp_tests, test_load_subkey) { - rnp_key_store_t *key_store = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); - std::string keyid = "9747D2A6B3A63124"; - std::string sub1id = "AF1114A47F5F5B28"; - std::string sub2id = "16CD16F267CCDD4F"; + auto key_store = new rnp::KeyStore(PGP_KEY_STORE_GPG, "", global_ctx); + std::string keyid = "9747D2A6B3A63124"; + std::string sub1id = "AF1114A47F5F5B28"; + std::string sub2id = "16CD16F267CCDD4F"; /* load first subkey with signature */ pgp_key_t *key = NULL, *skey1 = NULL, *skey2 = NULL; assert_true(load_keystore(key_store, MERGE_PATH "key-pub-just-subkey-1.pgp")); - assert_int_equal(rnp_key_store_get_key_count(key_store), 1); + assert_int_equal(key_store->key_count(), 1); assert_non_null(skey1 = rnp_tests_get_key_by_id(key_store, sub1id)); assert_false(skey1->valid()); assert_int_equal(skey1->rawpkt_count(), 2); @@ -945,7 +941,7 @@ TEST_F(rnp_tests, test_load_subkey) /* load second subkey, without signature */ assert_true(load_keystore(key_store, MERGE_PATH "key-pub-just-subkey-2-no-sigs.pgp")); - assert_int_equal(rnp_key_store_get_key_count(key_store), 2); + assert_int_equal(key_store->key_count(), 2); assert_non_null(skey2 = rnp_tests_get_key_by_id(key_store, sub2id)); assert_false(skey2->valid()); assert_int_equal(skey2->rawpkt_count(), 1); @@ -955,7 +951,7 @@ TEST_F(rnp_tests, test_load_subkey) /* load primary key without subkey signatures */ assert_true(load_keystore(key_store, MERGE_PATH "key-pub-uid-1.pgp")); - assert_int_equal(rnp_key_store_get_key_count(key_store), 3); + assert_int_equal(key_store->key_count(), 3); assert_non_null(key = rnp_tests_get_key_by_id(key_store, keyid)); assert_true(key->valid()); assert_int_equal(key->rawpkt_count(), 3); @@ -972,7 +968,7 @@ TEST_F(rnp_tests, test_load_subkey) /* load second subkey with signature */ assert_true(load_keystore(key_store, MERGE_PATH "key-pub-just-subkey-2.pgp")); - assert_int_equal(rnp_key_store_get_key_count(key_store), 3); + assert_int_equal(key_store->key_count(), 3); assert_true(key == rnp_tests_get_key_by_id(key_store, keyid)); assert_true(skey1 == rnp_tests_get_key_by_id(key_store, sub1id)); assert_true(skey2 == rnp_tests_get_key_by_id(key_store, sub2id)); diff --git a/src/tests/streams.cpp b/src/tests/streams.cpp index c0bf698309..9ff5ee67fa 100644 --- a/src/tests/streams.cpp +++ b/src/tests/streams.cpp @@ -334,16 +334,14 @@ TEST_F(rnp_tests, test_stream_file) TEST_F(rnp_tests, test_stream_signatures) { - rnp_key_store_t *pubring; - rnp_key_store_t *secring; - pgp_signature_t sig; - pgp_source_t sigsrc; - pgp_key_t * key = NULL; + pgp_signature_t sig; + pgp_source_t sigsrc; + pgp_key_t * key = NULL; /* load keys */ - pubring = new rnp_key_store_t( - PGP_KEY_STORE_GPG, "data/test_stream_signatures/pub.asc", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + auto pubring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/test_stream_signatures/pub.asc", global_ctx); + assert_true(pubring->load()); /* load signature */ assert_rnp_success(init_file_src(&sigsrc, "data/test_stream_signatures/source.txt.sig")); assert_rnp_success(sig.parse(sigsrc)); @@ -357,7 +355,7 @@ TEST_F(rnp_tests, test_stream_signatures) assert_true( stream_hash_file(*hash_forged, "data/test_stream_signatures/source_forged.txt")); /* find signing key */ - assert_non_null(key = rnp_key_store_get_signer_key(pubring, &sig)); + assert_non_null(key = pubring->get_signer(sig)); /* validate signature and fields */ auto hash = hash_orig->clone(); assert_int_equal(sig.creation(), 1522241943); @@ -368,10 +366,10 @@ TEST_F(rnp_tests, test_stream_signatures) /* now let's create signature and sign file */ /* load secret key */ - secring = new rnp_key_store_t( - PGP_KEY_STORE_GPG, "data/test_stream_signatures/sec.asc", global_ctx); - assert_true(rnp_key_store_load_from_path(secring, NULL)); - assert_non_null(key = rnp_key_store_get_signer_key(secring, &sig)); + auto secring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/test_stream_signatures/sec.asc", global_ctx); + assert_true(secring->load()); + assert_non_null(key = secring->get_signer(sig)); assert_true(key->is_secret()); /* fill signature */ uint32_t create = time(NULL); @@ -1000,8 +998,8 @@ TEST_F(rnp_tests, test_stream_key_signatures) /* v3 public key */ auto pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc", global_ctx); + assert_true(pubring->load()); assert_rnp_success(init_file_src(&keysrc, "data/keyrings/4/rsav3-p.asc")); assert_rnp_success(process_pgp_keys(keysrc, keyseq, false)); src_close(&keysrc); @@ -1009,7 +1007,7 @@ TEST_F(rnp_tests, test_stream_key_signatures) auto &key = keyseq.keys.front(); auto &uid = key.userids.front(); auto &sig = uid.signatures.front(); - assert_non_null(pkey = rnp_key_store_get_signer_key(pubring, &sig)); + assert_non_null(pkey = pubring->get_signer(sig)); /* check certification signature */ auto hash = signature_hash_certification(sig, key.key, uid.uid); /* this signature uses MD5 hash after the allowed date */ @@ -1030,9 +1028,8 @@ TEST_F(rnp_tests, test_stream_key_signatures) delete pubring; /* keyring */ - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); + pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); + assert_true(pubring->load()); assert_rnp_success(init_file_src(&keysrc, "data/keyrings/1/pubring.gpg")); assert_rnp_success(process_pgp_keys(keysrc, keyseq, false)); src_close(&keysrc); @@ -1042,7 +1039,7 @@ TEST_F(rnp_tests, test_stream_key_signatures) for (auto &uid : keyref.userids) { /* userid certifications */ for (auto &sig : uid.signatures) { - assert_non_null(pkey = rnp_key_store_get_signer_key(pubring, &sig)); + assert_non_null(pkey = pubring->get_signer(sig)); /* high level interface */ sinfo.sig = &sig; pkey->validate_cert(sinfo, keyref.key, uid.uid, global_ctx); @@ -1064,7 +1061,7 @@ TEST_F(rnp_tests, test_stream_key_signatures) /* subkey binding signatures */ for (auto &subkey : keyref.subkeys) { auto &sig = subkey.signatures.front(); - assert_non_null(pkey = rnp_key_store_get_signer_key(pubring, &sig)); + assert_non_null(pkey = pubring->get_signer(sig)); /* high level interface */ sinfo.sig = &sig; pgp_key_id_t subid; @@ -1088,8 +1085,8 @@ TEST_F(rnp_tests, test_stream_key_signatures) static bool validate_key_sigs(const char *path) { - rnp_key_store_t *pubring = new rnp_key_store_t(PGP_KEY_STORE_GPG, path, global_ctx); - bool valid = rnp_key_store_load_from_path(pubring, NULL); + auto pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, path, global_ctx); + bool valid = pubring->load(); for (auto &key : pubring->keys) { key.validate(*pubring); valid = valid && key.valid(); @@ -1101,10 +1098,10 @@ validate_key_sigs(const char *path) TEST_F(rnp_tests, test_stream_key_signature_validate) { /* v3 public key */ - rnp_key_store_t *pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_int_equal(rnp_key_store_get_key_count(pubring), 1); + auto pubring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/4/rsav3-p.asc", global_ctx); + assert_true(pubring->load()); + assert_int_equal(pubring->key_count(), 1); pgp_key_t &pkey = pubring->keys.front(); pkey.validate(*pubring); /* MD5 signature is marked as invalid by default */ @@ -1126,10 +1123,9 @@ TEST_F(rnp_tests, test_stream_key_signature_validate) delete pubring; /* keyring */ - pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_true(rnp_key_store_get_key_count(pubring) > 0); + pubring = new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); + assert_true(pubring->load()); + assert_true(pubring->key_count() > 0); int i = 0; for (auto &key : pubring->keys) { key.validate(*pubring); @@ -1477,14 +1473,13 @@ TEST_F(rnp_tests, test_stream_814_dearmor_double_free) TEST_F(rnp_tests, test_stream_825_dearmor_blank_line) { - rnp_key_store_t *keystore = NULL; - pgp_source_t src = {}; + pgp_source_t src = {}; - keystore = new rnp_key_store_t(PGP_KEY_STORE_GPG, "", global_ctx); + auto keystore = new rnp::KeyStore(PGP_KEY_STORE_GPG, "", global_ctx); assert_rnp_success( init_file_src(&src, "data/test_stream_armor/extra_line_before_trailer.asc")); - assert_true(rnp_key_store_load_from_src(keystore, &src, NULL)); - assert_int_equal(rnp_key_store_get_key_count(keystore), 2); + assert_true(keystore->load(src)); + assert_int_equal(keystore->key_count(), 2); src_close(&src); delete keystore; } diff --git a/src/tests/support.cpp b/src/tests/support.cpp index 4b333c37e9..c19e56e333 100644 --- a/src/tests/support.cpp +++ b/src/tests/support.cpp @@ -761,7 +761,7 @@ check_json_pkt_type(json_object *pkt, int tag) } pgp_key_t * -rnp_tests_get_key_by_id(rnp_key_store_t *keyring, const std::string &keyid, pgp_key_t *after) +rnp_tests_get_key_by_id(rnp::KeyStore *keyring, const std::string &keyid, pgp_key_t *after) { if (!keyring || keyid.empty() || !rnp::is_hex(keyid)) { return NULL; @@ -773,11 +773,11 @@ rnp_tests_get_key_by_id(rnp_key_store_t *keyring, const std::string &keyid, pgp_ } pgp_key_search_t search(PGP_KEY_SEARCH_KEYID); search.by.keyid = keyid_bin; - return rnp_key_store_search(keyring, &search, after); + return keyring->search(search, after); } pgp_key_t * -rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const std::string &grip) +rnp_tests_get_key_by_grip(rnp::KeyStore *keyring, const std::string &grip) { if (!keyring || grip.empty() || !rnp::is_hex(grip)) { return NULL; @@ -791,18 +791,18 @@ rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const std::string &grip) } pgp_key_t * -rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const pgp_key_grip_t &grip) +rnp_tests_get_key_by_grip(rnp::KeyStore *keyring, const pgp_key_grip_t &grip) { if (!keyring) { return NULL; } pgp_key_search_t search(PGP_KEY_SEARCH_GRIP); search.by.grip = grip; - return rnp_key_store_search(keyring, &search, NULL); + return keyring->search(search); } pgp_key_t * -rnp_tests_get_key_by_fpr(rnp_key_store_t *keyring, const std::string &keyid) +rnp_tests_get_key_by_fpr(rnp::KeyStore *keyring, const std::string &keyid) { if (!keyring || keyid.empty() || !rnp::is_hex(keyid)) { return NULL; @@ -814,11 +814,11 @@ rnp_tests_get_key_by_fpr(rnp_key_store_t *keyring, const std::string &keyid) } pgp_fingerprint_t fp = {{}, static_cast(binlen)}; memcpy(fp.fingerprint, keyid_bin.data(), binlen); - return rnp_key_store_get_key_by_fpr(keyring, fp); + return keyring->get_key(fp); } pgp_key_t * -rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &uid) +rnp_tests_key_search(rnp::KeyStore *keyring, const std::string &uid) { if (!keyring || uid.empty()) { return NULL; @@ -827,7 +827,7 @@ rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &uid) pgp_key_search_t srch_userid(PGP_KEY_SEARCH_USERID); strncpy(srch_userid.by.userid, uid.c_str(), sizeof(srch_userid.by.userid)); srch_userid.by.userid[sizeof(srch_userid.by.userid) - 1] = '\0'; - return rnp_key_store_search(keyring, &srch_userid, NULL); + return keyring->search(srch_userid); } void @@ -1206,7 +1206,7 @@ ripemd160_enabled() } bool -test_load_gpg_check_key(rnp_key_store_t *pub, rnp_key_store_t *sec, const char *id) +test_load_gpg_check_key(rnp::KeyStore *pub, rnp::KeyStore *sec, const char *id) { pgp_key_t *key = rnp_tests_get_key_by_id(pub, id); if (!key) { diff --git a/src/tests/support.h b/src/tests/support.h index 6206924501..fa9ec02907 100644 --- a/src/tests/support.h +++ b/src/tests/support.h @@ -216,13 +216,13 @@ bool check_json_field_int(json_object *obj, const std::string &field, int value) bool check_json_field_bool(json_object *obj, const std::string &field, bool value); bool check_json_pkt_type(json_object *pkt, int tag); -pgp_key_t *rnp_tests_get_key_by_id(rnp_key_store_t * keyring, +pgp_key_t *rnp_tests_get_key_by_id(rnp::KeyStore * keyring, const std::string &keyid, pgp_key_t * after = NULL); -pgp_key_t *rnp_tests_get_key_by_fpr(rnp_key_store_t *keyring, const std::string &keyid); -pgp_key_t *rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const std::string &grip); -pgp_key_t *rnp_tests_get_key_by_grip(rnp_key_store_t *keyring, const pgp_key_grip_t &grip); -pgp_key_t *rnp_tests_key_search(rnp_key_store_t *keyring, const std::string &uid); +pgp_key_t *rnp_tests_get_key_by_fpr(rnp::KeyStore *keyring, const std::string &keyid); +pgp_key_t *rnp_tests_get_key_by_grip(rnp::KeyStore *keyring, const std::string &grip); +pgp_key_t *rnp_tests_get_key_by_grip(rnp::KeyStore *keyring, const pgp_key_grip_t &grip); +pgp_key_t *rnp_tests_key_search(rnp::KeyStore *keyring, const std::string &uid); /* key load/reload shortcuts */ void reload_pubring(rnp_ffi_t *ffi); @@ -289,7 +289,7 @@ rnp_round_up(size_t n, size_t align_to) /* load g10/g23 gpg key and verify that it can be unprotected/protected */ -bool test_load_gpg_check_key(rnp_key_store_t *pub, rnp_key_store_t *sec, const char *id); +bool test_load_gpg_check_key(rnp::KeyStore *pub, rnp::KeyStore *sec, const char *id); #define MD5_FROM 1325376000 #define SHA1_DATA_FROM 1547856000 diff --git a/src/tests/user-prefs.cpp b/src/tests/user-prefs.cpp index 96813070fa..8511045fb3 100644 --- a/src/tests/user-prefs.cpp +++ b/src/tests/user-prefs.cpp @@ -56,10 +56,10 @@ find_subsig(const pgp_key_t *key, const char *userid) TEST_F(rnp_tests, test_load_user_prefs) { - rnp_key_store_t *pubring = - new rnp_key_store_t(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); - assert_true(rnp_key_store_load_from_path(pubring, NULL)); - assert_int_equal(rnp_key_store_get_key_count(pubring), 7); + auto pubring = + new rnp::KeyStore(PGP_KEY_STORE_GPG, "data/keyrings/1/pubring.gpg", global_ctx); + assert_true(pubring->load()); + assert_int_equal(pubring->key_count(), 7); { const char *userid = "key1-uid0";