summaryrefslogtreecommitdiffstats
path: root/src/lib/pgp-key.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pgp-key.h')
-rw-r--r--src/lib/pgp-key.h671
1 files changed, 671 insertions, 0 deletions
diff --git a/src/lib/pgp-key.h b/src/lib/pgp-key.h
new file mode 100644
index 0000000..aa088bb
--- /dev/null
+++ b/src/lib/pgp-key.h
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2017-2021 [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.
+ */
+
+#ifndef RNP_PACKET_KEY_H
+#define RNP_PACKET_KEY_H
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <vector>
+#include <unordered_map>
+#include "pass-provider.h"
+#include "../librepgp/stream-key.h"
+#include <rekey/rnp_key_store.h>
+#include "../librepgp/stream-packet.h"
+#include "crypto/symmetric.h"
+#include "types.h"
+#include "sec_profile.hpp"
+
+/** pgp_rawpacket_t */
+typedef struct pgp_rawpacket_t {
+ pgp_pkt_type_t tag;
+ std::vector<uint8_t> raw;
+
+ pgp_rawpacket_t() = default;
+ pgp_rawpacket_t(const uint8_t *data, size_t len, pgp_pkt_type_t tag)
+ : tag(tag),
+ raw(data ? std::vector<uint8_t>(data, data + len) : std::vector<uint8_t>()){};
+ pgp_rawpacket_t(const pgp_signature_t &sig);
+ pgp_rawpacket_t(pgp_key_pkt_t &key);
+ pgp_rawpacket_t(const pgp_userid_pkt_t &uid);
+
+ void write(pgp_dest_t &dst) const;
+} pgp_rawpacket_t;
+
+/** information about the signature */
+typedef struct pgp_subsig_t {
+ uint32_t uid{}; /* index in userid array in key for certification sig */
+ pgp_signature_t sig{}; /* signature packet */
+ pgp_sig_id_t sigid{}; /* signature identifier */
+ pgp_rawpacket_t rawpkt{}; /* signature's rawpacket */
+ uint8_t trustlevel{}; /* level of trust */
+ uint8_t trustamount{}; /* amount of trust */
+ uint8_t key_flags{}; /* key flags for certification/direct key sig */
+ pgp_user_prefs_t prefs{}; /* user preferences for certification sig */
+ pgp_validity_t validity{}; /* signature validity information */
+
+ pgp_subsig_t() = delete;
+ pgp_subsig_t(const pgp_signature_t &sig);
+
+ bool validated() const;
+ bool valid() const;
+ /** @brief Returns true if signature is certification */
+ bool is_cert() const;
+ /** @brief Returns true if signature is expired */
+ bool expired(uint64_t at) const;
+} pgp_subsig_t;
+
+typedef std::unordered_map<pgp_sig_id_t, pgp_subsig_t> pgp_sig_map_t;
+
+/* userid, built on top of userid packet structure */
+typedef struct pgp_userid_t {
+ private:
+ std::vector<pgp_sig_id_t> sigs_{}; /* all signatures related to this userid */
+ public:
+ pgp_userid_pkt_t pkt{}; /* User ID or User Attribute packet as it was loaded */
+ pgp_rawpacket_t rawpkt{}; /* Raw packet contents */
+ std::string str{}; /* Human-readable representation of the userid */
+ bool valid{}; /* User ID is valid, i.e. has valid, non-expired self-signature */
+ bool revoked{};
+ pgp_revoke_t revocation{};
+
+ pgp_userid_t(const pgp_userid_pkt_t &pkt);
+
+ size_t sig_count() const;
+ const pgp_sig_id_t &get_sig(size_t idx) const;
+ bool has_sig(const pgp_sig_id_t &id) const;
+ void add_sig(const pgp_sig_id_t &sig);
+ void replace_sig(const pgp_sig_id_t &id, const pgp_sig_id_t &newsig);
+ bool del_sig(const pgp_sig_id_t &id);
+ void clear_sigs();
+} pgp_userid_t;
+
+#define PGP_UID_NONE ((uint32_t) -1)
+
+typedef struct rnp_key_store_t rnp_key_store_t;
+
+/* describes a user's key */
+struct pgp_key_t {
+ private:
+ pgp_sig_map_t sigs_map_{}; /* map with subsigs stored by their id */
+ std::vector<pgp_sig_id_t> sigs_{}; /* subsig ids to lookup actual sig in map */
+ std::vector<pgp_sig_id_t> keysigs_{}; /* direct-key signature ids in the original order */
+ std::vector<pgp_userid_t> uids_{}; /* array of user ids */
+ pgp_key_pkt_t pkt_{}; /* pubkey/seckey data packet */
+ uint8_t flags_{}; /* key flags */
+ uint32_t expiration_{}; /* key expiration time, if available */
+ pgp_key_id_t keyid_{};
+ pgp_fingerprint_t fingerprint_{};
+ pgp_key_grip_t grip_{};
+ pgp_fingerprint_t primary_fp_{}; /* fingerprint of the primary key (for subkeys) */
+ bool primary_fp_set_{};
+ std::vector<pgp_fingerprint_t>
+ subkey_fps_{}; /* array of subkey fingerprints (for primary keys) */
+ pgp_rawpacket_t rawpkt_{}; /* key raw packet */
+ uint32_t uid0_{}; /* primary uid index in uids array */
+ bool uid0_set_{}; /* flag for the above */
+ bool revoked_{}; /* key has been revoked */
+ pgp_revoke_t revocation_{}; /* revocation reason */
+ pgp_validity_t validity_{}; /* key's validity */
+ 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 merge_validity(const pgp_validity_t &src);
+ uint64_t valid_till_common(bool expiry) const;
+ bool write_sec_pgp(pgp_dest_t & dst,
+ pgp_key_pkt_t & seckey,
+ const std::string &password,
+ rnp::RNG & rng);
+
+ public:
+ pgp_key_store_format_t format{}; /* the format of the key in packets[0] */
+
+ pgp_key_t() = default;
+ pgp_key_t(const pgp_key_pkt_t &pkt);
+ pgp_key_t(const pgp_key_pkt_t &pkt, pgp_key_t &primary);
+ pgp_key_t(const pgp_key_t &src, bool pubonly = false);
+ pgp_key_t(const pgp_transferable_key_t &src);
+ pgp_key_t(const pgp_transferable_subkey_t &src, pgp_key_t *primary);
+ pgp_key_t &operator=(const pgp_key_t &) = default;
+ pgp_key_t &operator=(pgp_key_t &&) = default;
+
+ size_t sig_count() const;
+ pgp_subsig_t & get_sig(size_t idx);
+ const pgp_subsig_t &get_sig(size_t idx) const;
+ bool has_sig(const pgp_sig_id_t &id) const;
+ pgp_subsig_t & replace_sig(const pgp_sig_id_t &id, const pgp_signature_t &newsig);
+ pgp_subsig_t & get_sig(const pgp_sig_id_t &id);
+ const pgp_subsig_t &get_sig(const pgp_sig_id_t &id) const;
+ pgp_subsig_t & add_sig(const pgp_signature_t &sig, size_t uid = PGP_UID_NONE);
+ bool del_sig(const pgp_sig_id_t &sigid);
+ size_t del_sigs(const std::vector<pgp_sig_id_t> &sigs);
+ size_t keysig_count() const;
+ pgp_subsig_t & get_keysig(size_t idx);
+ size_t uid_count() const;
+ pgp_userid_t & get_uid(size_t idx);
+ const pgp_userid_t &get_uid(size_t idx) const;
+ pgp_userid_t & add_uid(const pgp_transferable_userid_t &uid);
+ bool has_uid(const std::string &uid) const;
+ void del_uid(size_t idx);
+ bool has_primary_uid() const;
+ uint32_t get_primary_uid() const;
+ bool revoked() const;
+ const pgp_revoke_t &revocation() const;
+ void clear_revokes();
+
+ const pgp_key_pkt_t &pkt() const;
+ pgp_key_pkt_t & pkt();
+ void set_pkt(const pgp_key_pkt_t &pkt);
+
+ pgp_key_material_t &material();
+
+ pgp_pubkey_alg_t alg() const;
+ pgp_curve_t curve() const;
+ pgp_version_t version() const;
+ pgp_pkt_type_t type() const;
+ bool encrypted() const;
+ uint8_t flags() const;
+ bool can_sign() const;
+ bool can_certify() const;
+ bool can_encrypt() const;
+ bool has_secret() const;
+ /**
+ * @brief Check whether key is usable for the specified operation.
+ *
+ * @param op operation to check.
+ * @param if_secret check whether secret part of this key could be usable for op.
+ * @return true if key (or corresponding secret key) is usable or false otherwise.
+ */
+ bool usable_for(pgp_op_t op, bool if_secret = false) const;
+ /** @brief Get key's expiration time in seconds. If 0 then it doesn't expire. */
+ uint32_t expiration() const;
+ /** @brief Check whether key is expired. Must be validated before that. */
+ bool expired() const;
+ /** @brief Get key's creation time in seconds since Jan, 1 1970. */
+ uint32_t creation() const;
+ bool is_public() const;
+ bool is_secret() const;
+ bool is_primary() const;
+ bool is_subkey() const;
+ /** @brief check if a key is currently locked, i.e. secret fields are not decrypted.
+ * Note: Key locking does not apply to unprotected keys.
+ */
+ bool is_locked() const;
+ /** @brief check if a key is currently protected, i.e. its secret data is encrypted */
+ bool is_protected() const;
+
+ bool valid() const;
+ bool validated() const;
+ /** @brief return time till which key is considered to be valid */
+ uint64_t valid_till() const;
+ /** @brief check whether key was/will be valid at the specified time */
+ bool valid_at(uint64_t timestamp) const;
+
+ /** @brief Get key's id */
+ const pgp_key_id_t &keyid() const;
+ /** @brief Get key's fingerprint */
+ const pgp_fingerprint_t &fp() const;
+ /** @brief Get key's grip */
+ const pgp_key_grip_t &grip() const;
+ /** @brief Get primary key's fingerprint for the subkey, if it is available.
+ * Note: will throw if it is not available, use has_primary_fp() to check.
+ */
+ const pgp_fingerprint_t &primary_fp() const;
+ /** @brief Check whether key has primary key's fingerprint */
+ bool has_primary_fp() const;
+ /** @brief Clean primary_fp */
+ void unset_primary_fp();
+ /** @brief Link key with subkey via primary_fp and subkey_fps list */
+ void link_subkey_fp(pgp_key_t &subkey);
+ /**
+ * @brief Add subkey fp to key's list.
+ * Note: this function will check for duplicates.
+ */
+ void add_subkey_fp(const pgp_fingerprint_t &fp);
+ /** @brief Get the number of pgp key's subkeys. */
+ size_t subkey_count() const;
+ /** @brief Remove subkey fingerprint from key's list. */
+ void remove_subkey_fp(const pgp_fingerprint_t &fp);
+ /**
+ * @brief Get the pgp key's subkey fingerprint
+ * @return fingerprint or throws std::out_of_range exception
+ */
+ const pgp_fingerprint_t & get_subkey_fp(size_t idx) const;
+ const std::vector<pgp_fingerprint_t> &subkey_fps() const;
+
+ size_t rawpkt_count() const;
+ pgp_rawpacket_t & rawpkt();
+ const pgp_rawpacket_t &rawpkt() const;
+ void set_rawpkt(const pgp_rawpacket_t &src);
+ /** @brief write secret key data to the rawpkt, optionally encrypting with password */
+ bool write_sec_rawpkt(pgp_key_pkt_t & seckey,
+ const std::string & password,
+ rnp::SecurityContext &ctx);
+
+ /** @brief Unlock a key, i.e. decrypt its secret data so it can be used for
+ * signing/decryption.
+ * Note: Key locking does not apply to unprotected keys.
+ *
+ * @param pass_provider the password provider that may be used to unlock the key
+ * @param op operation for which secret key should be unloacked
+ * @return true if the key was unlocked, false otherwise
+ **/
+ bool unlock(const pgp_password_provider_t &provider, pgp_op_t op = PGP_OP_UNLOCK);
+ /** @brief Lock a key, i.e. cleanup decrypted secret data.
+ * Note: Key locking does not apply to unprotected keys.
+ *
+ * @param key the key
+ * @return true if the key was locked, false otherwise
+ **/
+ bool lock();
+ /** @brief Add protection to an unlocked key, i.e. encrypt its secret data with specified
+ * parameters. */
+ bool protect(const rnp_key_protection_params_t &protection,
+ const pgp_password_provider_t & password_provider,
+ rnp::SecurityContext & ctx);
+ /** @brief Add/change protection of a key */
+ bool protect(pgp_key_pkt_t & decrypted,
+ const rnp_key_protection_params_t &protection,
+ const std::string & new_password,
+ rnp::SecurityContext & ctx);
+ /** @brief Remove protection from a key, i.e. leave secret fields unencrypted */
+ bool unprotect(const pgp_password_provider_t &password_provider,
+ rnp::SecurityContext & ctx);
+
+ /** @brief Write key's packets to the output. */
+ void write(pgp_dest_t &dst) const;
+ /**
+ * @brief Write OpenPGP key packets (including subkeys) to the specified stream
+ *
+ * @param dst stream to write packets
+ * @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;
+ /**
+ * @brief Export key with subkey as it is required by Autocrypt (5-packet sequence: key,
+ * uid, sig, subkey, sig).
+ *
+ * @param dst stream to write packets
+ * @param sub subkey
+ * @param uid index of uid to export
+ * @return true on success or false otherwise
+ */
+ bool write_autocrypt(pgp_dest_t &dst, pgp_key_t &sub, uint32_t uid);
+
+ /**
+ * @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
+ * or direct-key signature.
+ *
+ * @param uid uid for which latest self-signature should be returned,
+ * PGP_UID_NONE for direct-key signature,
+ * PGP_UID_PRIMARY for any primary key,
+ * PGP_UID_ANY for any uid.
+ * @return pointer to signature object or NULL if failed/not found.
+ */
+ pgp_subsig_t *latest_selfsig(uint32_t uid);
+
+ /**
+ * @brief Get the latest valid subkey binding. Should be called on subkey.
+ *
+ * @param validated set to true whether binding signature must be validated
+ * @return pointer to signature object or NULL if failed/not found.
+ */
+ pgp_subsig_t *latest_binding(bool validated = true);
+
+ /** @brief Returns true if signature is produced by the key itself. */
+ bool is_signer(const pgp_subsig_t &sig) const;
+
+ /** @brief Returns true if key is expired according to sig. */
+ bool expired_with(const pgp_subsig_t &sig, uint64_t at) const;
+
+ /** @brief Check whether signature is key's self certification. */
+ bool is_self_cert(const pgp_subsig_t &sig) const;
+
+ /** @brief Check whether signature is key's direct-key self-signature */
+ bool is_direct_self(const pgp_subsig_t &sig) const;
+
+ /** @brief Check whether signature is key's/subkey's revocation */
+ bool is_revocation(const pgp_subsig_t &sig) const;
+
+ /** @brief Check whether signature is userid revocation */
+ bool is_uid_revocation(const pgp_subsig_t &sig) const;
+
+ /** @brief Check whether signature is subkey binding */
+ bool is_binding(const pgp_subsig_t &sig) const;
+
+ /**
+ * @brief Validate key's signature, assuming that 'this' is a signing key.
+ *
+ * @param key key or subkey to which signature belongs.
+ * @param sig signature to validate.
+ * @param ctx Populated security context.
+ */
+ void validate_sig(const pgp_key_t & key,
+ pgp_subsig_t & sig,
+ const rnp::SecurityContext &ctx) const noexcept;
+
+ /**
+ * @brief Validate signature, assuming that 'this' is a signing key.
+ *
+ * @param sinfo populated signature info. Validation results will be stored here.
+ * @param hash hash, feed with all signed data except signature trailer.
+ * @param ctx Populated security context.
+ */
+ void validate_sig(pgp_signature_info_t & sinfo,
+ rnp::Hash & hash,
+ const rnp::SecurityContext &ctx) const noexcept;
+
+ /**
+ * @brief Validate certification.
+ *
+ * @param sinfo populated signature info. Validation results will be stored here.
+ * @param key key packet to which certification belongs.
+ * @param uid userid which is bound by certification to the key packet.
+ */
+ void validate_cert(pgp_signature_info_t & sinfo,
+ const pgp_key_pkt_t & key,
+ const pgp_userid_pkt_t & uid,
+ const rnp::SecurityContext &ctx) const;
+
+ /**
+ * @brief Validate subkey binding.
+ *
+ * @param sinfo populated signature info. Validation results will be stored here.
+ * @param subkey subkey packet.
+ */
+ void validate_binding(pgp_signature_info_t & sinfo,
+ const pgp_key_t & subkey,
+ const rnp::SecurityContext &ctx) const;
+
+ /**
+ * @brief Validate subkey revocation.
+ *
+ * @param sinfo populated signature info. Validation results will be stored here.
+ * @param subkey subkey packet.
+ */
+ void validate_sub_rev(pgp_signature_info_t & sinfo,
+ const pgp_key_pkt_t & subkey,
+ const rnp::SecurityContext &ctx) const;
+
+ /**
+ * @brief Validate direct-key signature.
+ *
+ * @param sinfo populated signature info. Validation results will be stored here.
+ */
+ void validate_direct(pgp_signature_info_t &sinfo, const rnp::SecurityContext &ctx) const;
+
+ 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_subkey(pgp_key_t *primary, const rnp::SecurityContext &ctx);
+ void revalidate(rnp_key_store_t &keyring);
+ void mark_valid();
+ /**
+ * @brief Fill common signature parameters, assuming that current key is a signing one.
+ * @param sig signature to init.
+ * @param hash hash algorithm to use (may be changed if it is not suitable for public key
+ * algorithm).
+ * @param creation signature's creation time.
+ */
+ void sign_init(pgp_signature_t &sig, pgp_hash_alg_t hash, uint64_t creation) const;
+ /**
+ * @brief Calculate a certification and fill signature material.
+ * Note: secret key must be unlocked before calling this function.
+ *
+ * @param key key packet to sign. May be both public and secret. Could be signing key's
+ * packet for self-signature, or any other one for cross-key certification.
+ * @param uid uid to certify.
+ * @param sig signature, pre-populated with all of the required data, except the
+ * signature material.
+ */
+ void sign_cert(const pgp_key_pkt_t & key,
+ const pgp_userid_pkt_t &uid,
+ pgp_signature_t & sig,
+ rnp::SecurityContext & ctx);
+
+ /**
+ * @brief Calculate direct-key signature.
+ * Note: secret key must be unlocked before calling this function.
+ *
+ * @param key key packet to sign. May be both public and secret.
+ * @param sig signature, pre-populated with all of the required data, except the
+ * signature material.
+ */
+ void sign_direct(const pgp_key_pkt_t & key,
+ pgp_signature_t & sig,
+ rnp::SecurityContext &ctx);
+
+ /**
+ * @brief Calculate subkey or primary key binding.
+ * Note: this will not embed primary key binding for the signing subkey, it should
+ * be added by the caller.
+ *
+ * @param key subkey or primary key packet, may be both public or secret.
+ * @param sig signature, pre-populated with all of the required data, except the
+ * signature material.
+ */
+ void sign_binding(const pgp_key_pkt_t & key,
+ pgp_signature_t & sig,
+ rnp::SecurityContext &ctx);
+
+ /**
+ * @brief Calculate subkey binding.
+ * Note: secret key must be unlocked before calling this function. If subsign is
+ * true then subkey must be secret and unlocked as well so function can calculate
+ * primary key binding.
+ *
+ * @param sub subkey to bind to the primary key. If subsign is true then must be unlocked
+ * secret key.
+ * @param sig signature, pre-populated with all of the required data, except the
+ * signature material.
+ */
+ void sign_subkey_binding(pgp_key_t & sub,
+ pgp_signature_t & sig,
+ rnp::SecurityContext &ctx,
+ bool subsign = false);
+
+ /**
+ * @brief Generate key or subkey revocation signature.
+ *
+ * @param revoke revocation information.
+ * @param key key or subkey packet to revoke.
+ * @param sig object to store revocation signature. Will be populated in method call.
+ */
+ void gen_revocation(const pgp_revoke_t & revoke,
+ pgp_hash_alg_t hash,
+ const pgp_key_pkt_t & key,
+ pgp_signature_t & sig,
+ rnp::SecurityContext &ctx);
+
+ /**
+ * @brief Add and certify userid.
+ * Note: secret key must be unlocked before calling this function.
+ *
+ * @param cert certification and userid parameters.
+ * @param hash hash algorithm to use during signing. See sign_init() for more details.
+ * @param ctx security context.
+ * @param pubkey if non-NULL then userid and certification will be added to this key as
+ * well.
+ */
+ void add_uid_cert(rnp_selfsig_cert_info_t &cert,
+ pgp_hash_alg_t hash,
+ rnp::SecurityContext & ctx,
+ pgp_key_t * pubkey = nullptr);
+
+ /**
+ * @brief Calculate and add subkey binding signature.
+ * Note: must be called on the unlocked secret primary key. Calculated signature is
+ * added to the subkey.
+ *
+ * @param subsec secret subkey.
+ * @param subpub subkey's public part (so signature is added to both).
+ * @param binding information about subkey to put to the signature.
+ * @param hash hash algorithm to use (may be adjusted according to key and subkey
+ * algorithms)
+ */
+ void add_sub_binding(pgp_key_t & subsec,
+ pgp_key_t & subpub,
+ const rnp_selfsig_binding_info_t &binding,
+ pgp_hash_alg_t hash,
+ rnp::SecurityContext & ctx);
+
+ /** @brief Refresh internal fields after primary key is updated */
+ bool refresh_data(const rnp::SecurityContext &ctx);
+ /** @brief Refresh internal fields after subkey is updated */
+ bool refresh_data(pgp_key_t *primary, const rnp::SecurityContext &ctx);
+ /** @brief Merge primary key with the src, i.e. add all new userids/signatures/subkeys */
+ bool merge(const pgp_key_t &src);
+ /** @brief Merge subkey with the source, i.e. add all new signatures */
+ bool merge(const pgp_key_t &src, pgp_key_t *primary);
+};
+
+namespace rnp {
+class KeyLocker {
+ bool lock_;
+ pgp_key_t &key_;
+
+ public:
+ KeyLocker(pgp_key_t &key) : lock_(key.is_locked()), key_(key)
+ {
+ }
+
+ ~KeyLocker()
+ {
+ if (lock_ && !key_.is_locked()) {
+ key_.lock();
+ }
+ }
+};
+}; // namespace rnp
+
+pgp_key_pkt_t *pgp_decrypt_seckey_pgp(const pgp_rawpacket_t &raw,
+ const pgp_key_pkt_t & key,
+ const char * password);
+
+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,
+ pgp_key_t * signer,
+ uint32_t expiry,
+ const pgp_password_provider_t &prov,
+ rnp::SecurityContext & ctx);
+
+bool pgp_subkey_set_expiration(pgp_key_t * sub,
+ pgp_key_t * primsec,
+ pgp_key_t * secsub,
+ uint32_t expiry,
+ const pgp_password_provider_t &prov,
+ rnp::SecurityContext & ctx);
+
+/** Find a key or it's subkey, suitable for a particular operation
+ *
+ * If the key passed is suitable, it will be returned.
+ * Otherwise, its subkeys (if it is a primary w/subs)
+ * will be checked. NULL will be returned if no suitable
+ * key is found.
+ *
+ * @param op the operation for which the key should be suitable
+ * @param key the key
+ * @param key_provider the key provider. This will be used
+ * if/when subkeys are checked.
+ * @param no_primary set true if only subkeys must be returned
+ *
+ * @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);
+
+/*
+ * Picks up hash algorithm according to domain parameters set
+ * in `pubkey' and user provided hash. That's mostly because DSA
+ * and ECDSA needs special treatment.
+ *
+ * @param hash set by the caller
+ * @param pubkey initialized public key
+ *
+ * @returns hash algorithm that must be use for operation (mostly
+ signing with secure key which corresponds to 'pubkey')
+ */
+pgp_hash_alg_t pgp_hash_adjust_alg_to_key(pgp_hash_alg_t hash, const pgp_key_pkt_t *pubkey);
+
+#endif // RNP_PACKET_KEY_H