diff --git a/src/lib/ffi-priv-types.h b/src/lib/ffi-priv-types.h index 0b18ef051..a9379f66a 100644 --- a/src/lib/ffi-priv-types.h +++ b/src/lib/ffi-priv-types.h @@ -156,13 +156,13 @@ struct rnp_op_generate_st { rnp::secure_vector password; /* request password for key encryption via ffi's password provider */ bool request_password{}; - rnp::KeygenParams keygen_params; + rnp::KeygenParams keygen; rnp_key_protection_params_t protection{}; - rnp_selfsig_cert_info_t cert{}; - rnp_selfsig_binding_info_t binding{}; + rnp::CertParams cert; + rnp::BindingParams binding; rnp_op_generate_st(rnp_ffi_t affi, pgp_pubkey_alg_t alg) - : ffi(affi), keygen_params(alg, affi->context) + : ffi(affi), keygen(alg, affi->context) { } }; diff --git a/src/lib/keygen.cpp b/src/lib/keygen.cpp index 9bef2b62e..9e814299b 100644 --- a/src/lib/keygen.cpp +++ b/src/lib/keygen.cpp @@ -42,12 +42,95 @@ KeygenParams::check_defaults() noexcept hash_ = alg_ == PGP_PKA_SM2 ? PGP_HASH_SM3 : DEFAULT_PGP_HASH_ALG; } pgp_hash_alg_t min_hash = key_params_->min_hash(); - if (rnp::Hash::size(hash_) < rnp::Hash::size(min_hash)) { + if (Hash::size(hash_) < Hash::size(min_hash)) { hash_ = min_hash; } key_params_->check_defaults(); } +bool +KeygenParams::validate() const noexcept +{ +#if defined(ENABLE_PQC) + switch (alg()) { + case PGP_PKA_SPHINCSPLUS_SHA2: + FALLTHROUGH_STATEMENT; + case PGP_PKA_SPHINCSPLUS_SHAKE: { + auto &slhdsa = dynamic_cast(key_params()); + if (!sphincsplus_hash_allowed(alg(), slhdsa.param(), hash())) { + RNP_LOG("invalid hash algorithm for the slhdsa key"); + return false; + } + 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: + if (!dilithium_hash_allowed(hash())) { + RNP_LOG("invalid hash algorithm for the dilithium key"); + return false; + } + break; + default: + break; + } +#endif + return true; +} + +bool +KeygenParams::validate(const CertParams &cert) const noexcept +{ + /* Confirm that the specified pk alg can certify. + * gpg requires this, though the RFC only says that a V4 primary + * key SHOULD be a key capable of certification. + */ + if (!(pgp_pk_alg_capabilities(alg()) & PGP_KF_CERTIFY)) { + RNP_LOG("primary key alg (%d) must be able to sign", alg()); + return false; + } + + // check key flags + if (!cert.flags) { + // these are probably not *technically* required + RNP_LOG("key flags are required"); + return false; + } + if (cert.flags & ~pgp_pk_alg_capabilities(alg())) { + // check the flags against the alg capabilities + RNP_LOG("usage not permitted for pk algorithm"); + return false; + } + // require a userid + if (cert.userid.empty()) { + RNP_LOG("userid is required for primary key"); + return false; + } + return validate(); +} + +bool +KeygenParams::validate(const BindingParams &binding) const noexcept +{ + if (!binding.flags) { + RNP_LOG("key flags are required"); + return false; + } + if (binding.flags & ~pgp_pk_alg_capabilities(alg())) { + // check the flags against the alg capabilities + RNP_LOG("usage not permitted for pk algorithm"); + return false; + } + return validate(); +} + static const id_str_pair pubkey_alg_map[] = {{PGP_PKA_RSA, "RSA (Encrypt or Sign)"}, {PGP_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only"}, {PGP_PKA_RSA_SIGN_ONLY, "RSA Sign-Only"}, @@ -79,13 +162,6 @@ static const id_str_pair pubkey_alg_map[] = {{PGP_PKA_RSA, "RSA (Encrypt or Sign #endif {0, NULL}}; -static uint8_t -pk_alg_default_flags(pgp_pubkey_alg_t alg) -{ - // just use the full capabilities as the ultimate fallback - return pgp_pk_alg_capabilities(alg); -} - bool KeygenParams::generate(pgp_key_pkt_t &seckey, bool primary) { @@ -115,11 +191,11 @@ KeygenParams::generate(pgp_key_pkt_t &seckey, bool primary) } static bool -load_generated_g10_key(pgp_key_t * dst, - pgp_key_pkt_t * newkey, - pgp_key_t * primary_key, - pgp_key_t * pubkey, - rnp::SecurityContext &ctx) +load_generated_g10_key(pgp_key_t * dst, + pgp_key_pkt_t * newkey, + pgp_key_t * primary_key, + pgp_key_t * pubkey, + SecurityContext &ctx) { // this should generally be zeroed assert(dst->type() == 0); @@ -131,12 +207,12 @@ 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::KeyStore(ctx)); + std::unique_ptr key_store(new (std::nothrow) KeyStore(ctx)); if (!key_store) { return false; } /* Write g10 seckey */ - rnp::MemoryDest memdst(NULL, 0); + MemoryDest memdst(NULL, 0); if (!g10_write_seckey(&memdst.dst(), newkey, NULL, ctx)) { RNP_LOG("failed to write generated seckey"); return false; @@ -150,8 +226,8 @@ 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); - rnp::KeyProvider prov(rnp_key_provider_key_ptr_list, &key_ptrs); + MemorySource memsrc(memdst.memory(), memdst.writeb(), false); + KeyProvider prov(rnp_key_provider_key_ptr_list, &key_ptrs); if (!key_store.get()->load_g10(memsrc.src(), &prov)) { return false; } @@ -164,147 +240,23 @@ load_generated_g10_key(pgp_key_t * dst, return true; } -static std::string -default_uid(const KeygenParams ¶ms) -{ - char uid[MAX_ID_LENGTH] = {0}; - snprintf(uid, - sizeof(uid), - "%s %zu-bit key <%s@localhost>", - id_str_pair::lookup(pubkey_alg_map, params.alg()), - params.key_params().bits(), - getenv_logname()); - return uid; -} - -static bool -validate_keygen_primary(const KeygenParams ¶ms, const rnp_selfsig_cert_info_t &cert) -{ - /* Confirm that the specified pk alg can certify. - * gpg requires this, though the RFC only says that a V4 primary - * key SHOULD be a key capable of certification. - */ - if (!(pgp_pk_alg_capabilities(params.alg()) & PGP_KF_CERTIFY)) { - RNP_LOG("primary key alg (%d) must be able to sign", params.alg()); - return false; - } - - // check key flags - if (!cert.key_flags) { - // these are probably not *technically* required - RNP_LOG("key flags are required"); - return false; - } else if (cert.key_flags & ~pgp_pk_alg_capabilities(params.alg())) { - // check the flags against the alg capabilities - RNP_LOG("usage not permitted for pk algorithm"); - return false; - } - // require a userid - if (cert.userid.empty()) { - RNP_LOG("userid is required for primary key"); - return false; - } - return true; -} - -static void -keygen_primary_merge_defaults(KeygenParams ¶ms, rnp_selfsig_cert_info_t &cert) -{ - params.check_defaults(); - cert.prefs.merge_defaults(params.version()); - - if (!cert.key_flags) { - // set some default key flags if none are provided - cert.key_flags = pk_alg_default_flags(params.alg()); - } - if (cert.userid.empty()) { - cert.userid = default_uid(params); - } -} - -#if defined(ENABLE_PQC) -static bool -pgp_check_key_hash_requirements(KeygenParams ¶ms) -{ - switch (params.alg()) { - case PGP_PKA_SPHINCSPLUS_SHA2: - FALLTHROUGH_STATEMENT; - case PGP_PKA_SPHINCSPLUS_SHAKE: { - auto &slhdsa = dynamic_cast(params.key_params()); - if (!sphincsplus_hash_allowed(params.alg(), slhdsa.param(), params.hash())) { - return false; - } - 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: - if (!dilithium_hash_allowed(params.hash())) { - return false; - } - break; - default: - break; - } - return true; -} -#endif - -static bool -validate_keygen_subkey(const KeygenParams ¶ms, const rnp_selfsig_binding_info_t &binding) -{ - if (!binding.key_flags) { - RNP_LOG("key flags are required"); - return false; - } else if (binding.key_flags & ~pgp_pk_alg_capabilities(params.alg())) { - // check the flags against the alg capabilities - RNP_LOG("usage not permitted for pk algorithm"); - return false; - } - return true; -} - -static void -keygen_subkey_merge_defaults(KeygenParams ¶ms, rnp_selfsig_binding_info_t &binding) -{ - params.check_defaults(); - if (!binding.key_flags) { - // set some default key flags if none are provided - binding.key_flags = pk_alg_default_flags(params.alg()); - } -} - bool -KeygenParams::generate(rnp_selfsig_cert_info_t &cert, - pgp_key_t & primary_sec, - pgp_key_t & primary_pub, - pgp_key_store_format_t secformat) +KeygenParams::generate(CertParams & cert, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, + pgp_key_store_format_t secformat) { primary_sec = {}; primary_pub = {}; // merge some defaults in - keygen_primary_merge_defaults(*this, cert); + check_defaults(); + cert.check_defaults(*this); // now validate the keygen fields - if (!validate_keygen_primary(*this, cert)) { + if (!validate(cert)) { return false; } -#if defined(ENABLE_PQC) - // check hash requirements - if (!pgp_check_key_hash_requirements(*this)) { - RNP_LOG("invalid hash algorithm for the chosen key"); - return false; - } -#endif - // generate the raw key and fill tag/secret fields pgp_key_pkt_t secpkt; if (!generate(secpkt, true)) { @@ -347,7 +299,7 @@ KeygenParams::generate(rnp_selfsig_cert_info_t &cert, } bool -KeygenParams::generate(rnp_selfsig_binding_info_t & binding, +KeygenParams::generate(BindingParams & binding, pgp_key_t & primary_sec, pgp_key_t & primary_pub, pgp_key_t & subkey_sec, @@ -365,23 +317,16 @@ KeygenParams::generate(rnp_selfsig_binding_info_t & binding, subkey_pub = {}; // merge some defaults in - keygen_subkey_merge_defaults(*this, binding); + check_defaults(); + binding.check_defaults(*this); // now validate the keygen fields - if (!validate_keygen_subkey(*this, binding)) { + if (!validate(binding)) { return false; } -#if defined(ENABLE_PQC) - // check hash requirements - if (!pgp_check_key_hash_requirements(*this)) { - RNP_LOG("invalid hash algorithm for the chosen key"); - return false; - } -#endif - /* decrypt the primary seckey if needed (for signatures) */ - rnp::KeyLocker primlock(primary_sec); + KeyLocker primlock(primary_sec); if (primary_sec.encrypted() && !primary_sec.unlock(password_provider, PGP_OP_ADD_SUBKEY)) { RNP_LOG("Failed to unlock primary key."); return false; @@ -420,4 +365,99 @@ KeygenParams::generate(rnp_selfsig_binding_info_t & binding, subkey_sec.refresh_data(&primary_sec, ctx()); } +void +CertParams::check_defaults(const KeygenParams ¶ms) +{ + prefs.merge_defaults(params.version()); + + if (!flags) { + // set some default key flags if none are provided + flags = pgp_pk_alg_capabilities(params.alg()); + } + if (userid.empty()) { + std::string alg = id_str_pair::lookup(pubkey_alg_map, params.alg()); + std::string bits = std::to_string(params.key_params().bits()); + std::string name = getenv_logname() ? getenv_logname() : ""; + /* Awkward but better then sprintf */ + userid = alg + " " + bits + "-bit key <" + name + "@localhost>"; + } +} + +void +CertParams::populate(pgp_userid_pkt_t &uid) const +{ + uid.tag = PGP_PKT_USER_ID; + uid.uid_len = userid.size(); + if (!(uid.uid = (uint8_t *) malloc(uid.uid_len))) { + RNP_LOG("alloc failed"); + throw rnp_exception(RNP_ERROR_OUT_OF_MEMORY); + } + memcpy(uid.uid, userid.data(), uid.uid_len); +} + +void +CertParams::populate(pgp_signature_t &sig) const +{ + if (expiration) { + sig.set_key_expiration(expiration); + } + if (primary) { + sig.set_primary_uid(true); + } +#if defined(ENABLE_CRYPTO_REFRESH) + if ((sig.version == PGP_V6) && (sig.type() != PGP_SIG_DIRECT)) { + /* only set key expiraton and primary uid for v6 self-signatures + * since most information is stored in the direct-key signature of the primary key. + */ + + if (flags && (sig.type() == PGP_SIG_SUBKEY)) { + /* for v6 subkeys signatures we also add the key flags */ + sig.set_key_flags(flags); + } + return; + } else if ((sig.version == PGP_V6) && (sig.type() == PGP_SIG_DIRECT)) { + /* set some additional packets for v6 direct-key self signatures */ + sig.set_key_features(PGP_KEY_FEATURE_MDC | PGP_KEY_FEATURE_SEIPDV2); + if (!prefs.aead_prefs.empty()) { + sig.set_preferred_aead_algs(prefs.aead_prefs); + } + } +#endif + if (flags) { + sig.set_key_flags(flags); + } + if (!prefs.symm_algs.empty()) { + sig.set_preferred_symm_algs(prefs.symm_algs); + } + if (!prefs.hash_algs.empty()) { + sig.set_preferred_hash_algs(prefs.hash_algs); + } + if (!prefs.z_algs.empty()) { + sig.set_preferred_z_algs(prefs.z_algs); + } + if (!prefs.ks_prefs.empty()) { + sig.set_key_server_prefs(prefs.ks_prefs[0]); + } + if (!prefs.key_server.empty()) { + sig.set_key_server(prefs.key_server); + } +} + +void +CertParams::populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig) const +{ + sig.set_type(PGP_CERT_POSITIVE); + populate(sig); + populate(uid); +} + +void +BindingParams::check_defaults(const KeygenParams ¶ms) +{ + if (!flags) { + // set some default key flags if none are provided + flags = pgp_pk_alg_capabilities(params.alg()); + } +} + } // namespace rnp diff --git a/src/lib/keygen.hpp b/src/lib/keygen.hpp index b75e35031..581d5cbd1 100644 --- a/src/lib/keygen.hpp +++ b/src/lib/keygen.hpp @@ -66,6 +66,12 @@ class KeygenParams { void check_defaults() noexcept; + bool validate() const noexcept; + + bool validate(const CertParams &cert) const noexcept; + + bool validate(const BindingParams &binding) const noexcept; + pgp_version_t version() const noexcept { @@ -100,13 +106,13 @@ class KeygenParams { bool generate(pgp_key_pkt_t &seckey, bool primary); /* Generate primary key with self-certification */ - bool generate(rnp_selfsig_cert_info_t &cert, - pgp_key_t & primary_sec, - pgp_key_t & primary_pub, - pgp_key_store_format_t secformat); + bool generate(CertParams & cert, + pgp_key_t & primary_sec, + pgp_key_t & primary_pub, + pgp_key_store_format_t secformat); /* Generate a subkey for already existing primary key*/ - bool generate(rnp_selfsig_binding_info_t & binding, + bool generate(BindingParams & binding, pgp_key_t & primary_sec, pgp_key_t & primary_pub, pgp_key_t & subkey_sec, @@ -115,6 +121,33 @@ class KeygenParams { pgp_key_store_format_t secformat); }; +class CertParams { + public: + std::string userid; /* userid, required */ + uint8_t flags{}; /* key flags */ + uint32_t expiration{}; /* key expiration time (sec), 0 = no expiration */ + pgp_user_prefs_t prefs{}; /* user preferences, optional */ + bool primary; /* mark this as the primary user id */ + + void check_defaults(const KeygenParams ¶ms); + + /** + * @brief Populate uid and sig packet with data stored in this struct. + * At some point we should get rid of it. + */ + void populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig) const; + void populate(pgp_signature_t &sig) const; + void populate(pgp_userid_pkt_t &uid) const; +}; + +class BindingParams { + public: + uint8_t flags{}; + uint32_t expiration{}; + + void check_defaults(const KeygenParams ¶ms); +}; + } // namespace rnp #endif // RNP_KEYGEN_HPP_ \ No newline at end of file diff --git a/src/lib/pgp-key.cpp b/src/lib/pgp-key.cpp index 72e5b710f..3f3171eef 100644 --- a/src/lib/pgp-key.cpp +++ b/src/lib/pgp-key.cpp @@ -56,6 +56,7 @@ #include "crypto/mem.h" #include "crypto/signatures.h" #include "fingerprint.h" +#include "keygen.hpp" #include #include @@ -2538,10 +2539,10 @@ pgp_key_t::sign_subkey_binding(pgp_key_t & sub, #if defined(ENABLE_CRYPTO_REFRESH) void -pgp_key_t::add_direct_sig(rnp_selfsig_cert_info_t &cert, - pgp_hash_alg_t hash, - rnp::SecurityContext & ctx, - pgp_key_t * pubkey) +pgp_key_t::add_direct_sig(rnp::CertParams & cert, + pgp_hash_alg_t hash, + rnp::SecurityContext &ctx, + pgp_key_t * pubkey) { // We only support modifying v4 and newer keys if (pkt().version < PGP_V4) { @@ -2566,10 +2567,10 @@ pgp_key_t::add_direct_sig(rnp_selfsig_cert_info_t &cert, #endif void -pgp_key_t::add_uid_cert(rnp_selfsig_cert_info_t &cert, - pgp_hash_alg_t hash, - rnp::SecurityContext & ctx, - pgp_key_t * pubkey) +pgp_key_t::add_uid_cert(rnp::CertParams & cert, + pgp_hash_alg_t hash, + rnp::SecurityContext &ctx, + pgp_key_t * pubkey) { if (cert.userid.empty()) { /* todo: why not to allow empty uid? */ @@ -2626,11 +2627,11 @@ pgp_key_t::add_uid_cert(rnp_selfsig_cert_info_t &cert, } void -pgp_key_t::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) +pgp_key_t::add_sub_binding(pgp_key_t & subsec, + pgp_key_t & subpub, + const rnp::BindingParams &binding, + pgp_hash_alg_t hash, + rnp::SecurityContext & ctx) { if (!is_primary()) { RNP_LOG("must be called on primary key"); @@ -2641,14 +2642,14 @@ pgp_key_t::add_sub_binding(pgp_key_t & subsec, pgp_signature_t sig; sign_init(ctx.rng, sig, hash, ctx.time(), version()); sig.set_type(PGP_SIG_SUBKEY); - if (binding.key_expiration) { - sig.set_key_expiration(binding.key_expiration); + if (binding.expiration) { + sig.set_key_expiration(binding.expiration); } - if (binding.key_flags) { - sig.set_key_flags(binding.key_flags); + if (binding.flags) { + sig.set_key_flags(binding.flags); } /* calculate binding */ - pgp_key_flags_t realkf = (pgp_key_flags_t) binding.key_flags; + pgp_key_flags_t realkf = (pgp_key_flags_t) binding.flags; if (!realkf) { realkf = pgp_pk_alg_capabilities(subsec.alg()); } diff --git a/src/lib/pgp-key.h b/src/lib/pgp-key.h index 5bac8acaf..3272be26e 100644 --- a/src/lib/pgp-key.h +++ b/src/lib/pgp-key.h @@ -132,7 +132,9 @@ typedef struct pgp_userid_t { namespace rnp { class KeyStore; -} +class CertParams; +class BindingParams; +} // namespace rnp /* describes a user's key */ struct pgp_key_t { @@ -577,10 +579,10 @@ struct pgp_key_t { * @param pubkey if non-NULL then the direct-key signature will be added to this key as * well. */ - void add_direct_sig(rnp_selfsig_cert_info_t &cert, - pgp_hash_alg_t hash, - rnp::SecurityContext & ctx, - pgp_key_t * pubkey = nullptr); + void add_direct_sig(rnp::CertParams & cert, + pgp_hash_alg_t hash, + rnp::SecurityContext &ctx, + pgp_key_t * pubkey = nullptr); #endif /** @@ -593,10 +595,10 @@ struct pgp_key_t { * @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); + void add_uid_cert(rnp::CertParams & cert, + pgp_hash_alg_t hash, + rnp::SecurityContext &ctx, + pgp_key_t * pubkey = nullptr); /** * @brief Calculate and add subkey binding signature. @@ -609,11 +611,11 @@ struct pgp_key_t { * @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); + void add_sub_binding(pgp_key_t & subsec, + pgp_key_t & subpub, + const rnp::BindingParams &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); diff --git a/src/lib/rnp.cpp b/src/lib/rnp.cpp index 1f6e3d56f..fd6ce1e89 100644 --- a/src/lib/rnp.cpp +++ b/src/lib/rnp.cpp @@ -4531,7 +4531,7 @@ parse_keygen_common_fields(json_object * jso, static std::unique_ptr parse_keygen_primary(rnp_ffi_t ffi, json_object * jso, - rnp_selfsig_cert_info_t & cert, + rnp::CertParams & cert, rnp_key_protection_params_t &prot) { /* Parse keygen params first */ @@ -4540,7 +4540,7 @@ parse_keygen_primary(rnp_ffi_t ffi, return nullptr; } /* Parse common key/subkey fields */ - if (!parse_keygen_common_fields(jso, cert.key_flags, cert.key_expiration, prot)) { + if (!parse_keygen_common_fields(jso, cert.flags, cert.expiration, prot)) { return nullptr; } /* UserID */ @@ -4566,7 +4566,7 @@ parse_keygen_primary(rnp_ffi_t ffi, static std::unique_ptr parse_keygen_sub(rnp_ffi_t ffi, json_object * jso, - rnp_selfsig_binding_info_t & binding, + rnp::BindingParams & binding, rnp_key_protection_params_t &prot) { /* Parse keygen params first */ @@ -4575,7 +4575,7 @@ parse_keygen_sub(rnp_ffi_t ffi, return nullptr; } /* Parse common with primary key fields */ - if (!parse_keygen_common_fields(jso, binding.key_flags, binding.key_expiration, prot)) { + if (!parse_keygen_common_fields(jso, binding.flags, binding.expiration, prot)) { return nullptr; } /* Do not allow unknown extra fields */ @@ -4627,8 +4627,8 @@ gen_json_primary_key(rnp_ffi_t ffi, pgp_fingerprint_t & fp, bool protect) { - rnp_selfsig_cert_info_t cert = {}; - cert.key_expiration = DEFAULT_KEY_EXPIRATION; + rnp::CertParams cert; + cert.expiration = DEFAULT_KEY_EXPIRATION; auto keygen = parse_keygen_primary(ffi, jsoparams, cert, prot); if (!keygen) { @@ -4662,17 +4662,17 @@ gen_json_subkey(rnp_ffi_t ffi, pgp_key_t & prim_sec, pgp_fingerprint_t &fp) { - rnp_selfsig_binding_info_t binding = {}; + rnp::BindingParams binding; rnp_key_protection_params_t prot = {}; - binding.key_expiration = DEFAULT_KEY_EXPIRATION; + binding.expiration = DEFAULT_KEY_EXPIRATION; auto keygen = parse_keygen_sub(ffi, jsoparams, binding, prot); if (!keygen) { return RNP_ERROR_BAD_PARAMETERS; } - if (!binding.key_flags) { + if (!binding.flags) { /* Generate encrypt-only subkeys by default */ - binding.key_flags = PGP_KF_ENCRYPT; + binding.flags = PGP_KF_ENCRYPT; } pgp_key_t pub; pgp_key_t sec; @@ -4878,7 +4878,7 @@ try { if (password && (ret = rnp_op_generate_set_protection_password(subop, password))) { goto done; } - if (pgp_pk_alg_capabilities(subop->keygen_params.alg()) & PGP_KF_ENCRYPT) { + if (pgp_pk_alg_capabilities(subop->keygen.alg()) & PGP_KF_ENCRYPT) { if ((ret = rnp_op_generate_add_usage(subop, "encrypt"))) { goto done; } @@ -5078,8 +5078,8 @@ try { *op = new rnp_op_generate_st(ffi, key_alg); (*op)->primary = true; - (*op)->cert.key_flags = default_key_flags(key_alg, false); - (*op)->cert.key_expiration = DEFAULT_KEY_EXPIRATION; + (*op)->cert.flags = default_key_flags(key_alg, false); + (*op)->cert.expiration = DEFAULT_KEY_EXPIRATION; return RNP_SUCCESS; } @@ -5111,8 +5111,8 @@ try { *op = new rnp_op_generate_st(ffi, key_alg); (*op)->primary = false; - (*op)->binding.key_flags = default_key_flags(key_alg, true); - (*op)->binding.key_expiration = DEFAULT_KEY_EXPIRATION; + (*op)->binding.flags = default_key_flags(key_alg, true); + (*op)->binding.expiration = DEFAULT_KEY_EXPIRATION; (*op)->primary_sec = primary->sec; (*op)->primary_pub = primary->pub; @@ -5127,7 +5127,7 @@ try { return RNP_ERROR_NULL_POINTER; } - auto bitkeygen = dynamic_cast(&op->keygen_params.key_params()); + auto bitkeygen = dynamic_cast(&op->keygen.key_params()); if (!bitkeygen) { return RNP_ERROR_BAD_PARAMETERS; } @@ -5147,7 +5147,7 @@ try { FFI_LOG(op->ffi, "Invalid hash: %s", hash); return RNP_ERROR_BAD_PARAMETERS; } - op->keygen_params.set_hash(halg); + op->keygen.set_hash(halg); return RNP_SUCCESS; } FFI_GUARD @@ -5158,10 +5158,10 @@ try { if (!op) { return RNP_ERROR_NULL_POINTER; } - if (op->keygen_params.alg() != PGP_PKA_DSA) { + if (op->keygen.alg() != PGP_PKA_DSA) { return RNP_ERROR_BAD_PARAMETERS; } - auto &dsa = dynamic_cast(op->keygen_params.key_params()); + auto &dsa = dynamic_cast(op->keygen.key_params()); dsa.set_qbits(qbits); return RNP_SUCCESS; } @@ -5173,14 +5173,14 @@ try { if (!op || !curve) { return RNP_ERROR_NULL_POINTER; } - if (!pk_alg_allows_custom_curve(op->keygen_params.alg())) { + if (!pk_alg_allows_custom_curve(op->keygen.alg())) { return RNP_ERROR_BAD_PARAMETERS; } pgp_curve_t eccurve = PGP_CURVE_UNKNOWN; if (!curve_str_to_type(curve, &eccurve)) { return RNP_ERROR_BAD_PARAMETERS; } - auto &ecc = dynamic_cast(op->keygen_params.key_params()); + auto &ecc = dynamic_cast(op->keygen.key_params()); ecc.set_curve(eccurve); return RNP_SUCCESS; } @@ -5268,13 +5268,13 @@ try { if (!str_to_key_flag(usage, &flag)) { return RNP_ERROR_BAD_PARAMETERS; } - if (!(pgp_pk_alg_capabilities(op->keygen_params.alg()) & flag)) { + if (!(pgp_pk_alg_capabilities(op->keygen.alg()) & flag)) { return RNP_ERROR_NOT_SUPPORTED; } if (op->primary) { - op->cert.key_flags |= flag; + op->cert.flags |= flag; } else { - op->binding.key_flags |= flag; + op->binding.flags |= flag; } return RNP_SUCCESS; } @@ -5287,9 +5287,9 @@ try { return RNP_ERROR_NULL_POINTER; } if (op->primary) { - op->cert.key_flags = 0; + op->cert.flags = 0; } else { - op->binding.key_flags = 0; + op->binding.flags = 0; } return RNP_SUCCESS; } @@ -5319,9 +5319,9 @@ try { return RNP_ERROR_NULL_POINTER; } if (op->primary) { - op->cert.key_expiration = expiration; + op->cert.expiration = expiration; } else { - op->binding.key_expiration = expiration; + op->binding.expiration = expiration; } return RNP_SUCCESS; } @@ -5444,7 +5444,7 @@ try { if (!op) { return RNP_ERROR_NULL_POINTER; } - op->keygen_params.set_version(PGP_V6); + op->keygen.set_version(PGP_V6); return RNP_SUCCESS; } FFI_GUARD @@ -5457,7 +5457,7 @@ try { if (!op || !param_cstr) { return RNP_ERROR_NULL_POINTER; } - auto slhdsa = dynamic_cast(&op->keygen_params.key_params()); + auto slhdsa = dynamic_cast(&op->keygen.key_params()); if (!slhdsa) { return RNP_ERROR_BAD_PARAMETERS; } @@ -5500,18 +5500,18 @@ try { pgp_password_provider_t prov; if (op->primary) { - if (!op->keygen_params.generate(op->cert, sec, pub, op->ffi->secring->format)) { + if (!op->keygen.generate(op->cert, sec, pub, op->ffi->secring->format)) { return RNP_ERROR_KEY_GENERATION; } } else { /* subkey generation */ - if (!op->keygen_params.generate(op->binding, - *op->primary_sec, - *op->primary_pub, - sec, - pub, - op->ffi->pass_provider, - op->ffi->secring->format)) { + if (!op->keygen.generate(op->binding, + *op->primary_sec, + *op->primary_pub, + sec, + pub, + op->ffi->pass_provider, + op->ffi->secring->format)) { return RNP_ERROR_KEY_GENERATION; } } @@ -5679,10 +5679,10 @@ try { FFI_LOG(handle->ffi, "UserID too long"); return RNP_ERROR_BAD_PARAMETERS; } - rnp_selfsig_cert_info_t info; + rnp::CertParams info; info.userid = uid; - info.key_flags = key_flags; - info.key_expiration = expiration; + info.flags = key_flags; + info.expiration = expiration; info.primary = primary; /* obtain and unlok secret key */ diff --git a/src/lib/types.h b/src/lib/types.h index 056e76485..7050aa069 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -319,27 +319,6 @@ typedef struct pgp_user_prefs_t { void merge_defaults(pgp_version_t version = PGP_V4); } pgp_user_prefs_t; -typedef struct rnp_selfsig_cert_info_t { - std::string userid; /* userid, required */ - uint8_t key_flags{}; /* key flags */ - uint32_t key_expiration{}; /* key expiration time (sec), 0 = no expiration */ - pgp_user_prefs_t prefs{}; /* user preferences, optional */ - bool primary; /* mark this as the primary user id */ - - /** - * @brief Populate uid and sig packet with data stored in this struct. - * At some point we should get rid of it. - */ - void populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig); - void populate(pgp_signature_t &sig); - void populate(pgp_userid_pkt_t &uid); -} rnp_selfsig_cert_info_t; - -typedef struct rnp_selfsig_binding_info_t { - uint8_t key_flags; - uint32_t key_expiration; -} rnp_selfsig_binding_info_t; - typedef struct rnp_key_protection_params_t { pgp_symm_alg_t symm_alg; pgp_cipher_mode_t cipher_mode; diff --git a/src/librepgp/stream-sig.cpp b/src/librepgp/stream-sig.cpp index b91cd67f8..4ff5ac4f1 100644 --- a/src/librepgp/stream-sig.cpp +++ b/src/librepgp/stream-sig.cpp @@ -1245,71 +1245,3 @@ pgp_signature_t::fill_hashed_data() } hashed_data.assign(hbody.data(), hbody.data() + hbody.size()); } - -void -rnp_selfsig_cert_info_t::populate(pgp_userid_pkt_t &uid) -{ - uid.tag = PGP_PKT_USER_ID; - uid.uid_len = userid.size(); - if (!(uid.uid = (uint8_t *) malloc(uid.uid_len))) { - RNP_LOG("alloc failed"); - throw rnp::rnp_exception(RNP_ERROR_OUT_OF_MEMORY); - } - memcpy(uid.uid, userid.data(), uid.uid_len); -} - -void -rnp_selfsig_cert_info_t::populate(pgp_signature_t &sig) -{ - if (key_expiration) { - sig.set_key_expiration(key_expiration); - } - if (primary) { - sig.set_primary_uid(true); - } -#if defined(ENABLE_CRYPTO_REFRESH) - if ((sig.version == PGP_V6) && (sig.type() != PGP_SIG_DIRECT)) { - /* only set key expiraton and primary uid for v6 self-signatures - * since most information is stored in the direct-key signature of the primary key. - */ - - if (key_flags && (sig.type() == PGP_SIG_SUBKEY)) { - /* for v6 subkeys signatures we also add the key flags */ - sig.set_key_flags(key_flags); - } - return; - } else if ((sig.version == PGP_V6) && (sig.type() == PGP_SIG_DIRECT)) { - /* set some additional packets for v6 direct-key self signatures */ - sig.set_key_features(PGP_KEY_FEATURE_MDC | PGP_KEY_FEATURE_SEIPDV2); - if (!prefs.aead_prefs.empty()) { - sig.set_preferred_aead_algs(prefs.aead_prefs); - } - } -#endif - if (key_flags) { - sig.set_key_flags(key_flags); - } - if (!prefs.symm_algs.empty()) { - sig.set_preferred_symm_algs(prefs.symm_algs); - } - if (!prefs.hash_algs.empty()) { - sig.set_preferred_hash_algs(prefs.hash_algs); - } - if (!prefs.z_algs.empty()) { - sig.set_preferred_z_algs(prefs.z_algs); - } - if (!prefs.ks_prefs.empty()) { - sig.set_key_server_prefs(prefs.ks_prefs[0]); - } - if (!prefs.key_server.empty()) { - sig.set_key_server(prefs.key_server); - } -} - -void -rnp_selfsig_cert_info_t::populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig) -{ - sig.set_type(PGP_CERT_POSITIVE); - populate(sig); - populate(uid); -} diff --git a/src/tests/generatekey.cpp b/src/tests/generatekey.cpp index 30f54157c..14f8e8038 100644 --- a/src/tests/generatekey.cpp +++ b/src/tests/generatekey.cpp @@ -1012,7 +1012,7 @@ TEST_F(rnp_tests, test_generated_key_sigs) auto & rsa = dynamic_cast(keygen.key_params()); rsa.set_bits(1024); - rnp_selfsig_cert_info_t cert{}; + rnp::CertParams cert; cert.userid = "test"; // generate @@ -1149,8 +1149,8 @@ TEST_F(rnp_tests, test_generated_key_sigs) rsa.set_bits(1024); // generate - pgp_password_provider_t prov = {}; - rnp_selfsig_binding_info_t binding{}; + pgp_password_provider_t prov = {}; + rnp::BindingParams binding; assert_true(keygen.generate( binding, *primary_sec, *primary_pub, sec, pub, prov, PGP_KEY_STORE_GPG)); assert_true(pub.valid()); diff --git a/src/tests/key-add-userid.cpp b/src/tests/key-add-userid.cpp index edd420573..fa383555f 100644 --- a/src/tests/key-add-userid.cpp +++ b/src/tests/key-add-userid.cpp @@ -27,6 +27,7 @@ #include "pgp-key.h" #include "rnp_tests.h" #include "support.h" +#include "keygen.hpp" /* This test loads a pgp keyring and adds a few userids to the key. */ @@ -63,10 +64,10 @@ TEST_F(rnp_tests, test_key_add_userid) unsigned subsigc = key->sig_count(); // add first, non-primary userid - rnp_selfsig_cert_info_t selfsig0; + rnp::CertParams selfsig0; selfsig0.userid = "added0"; - selfsig0.key_flags = 0x2; - selfsig0.key_expiration = base_expiry; + selfsig0.flags = 0x2; + selfsig0.expiration = base_expiry; selfsig0.primary = false; auto curtime = global_ctx.time(); global_ctx.set_time(curtime > SHA1_KEY_FROM ? SHA1_KEY_FROM - 100 : 0); @@ -96,10 +97,10 @@ TEST_F(rnp_tests, test_key_add_userid) assert_true(key->get_uid(uidc).valid); // add a primary userid - rnp_selfsig_cert_info_t selfsig1; + rnp::CertParams selfsig1; selfsig1.userid = "added1"; - selfsig1.key_flags = 0xAB; - selfsig1.key_expiration = base_expiry + 1; + selfsig1.flags = 0xAB; + selfsig1.expiration = base_expiry + 1; selfsig1.primary = 1; key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx); @@ -111,18 +112,18 @@ TEST_F(rnp_tests, test_key_add_userid) assert_true(key->get_uid(uidc + 1).valid); // try to add the same userid (should fail) - rnp_selfsig_cert_info_t dup_selfsig; + rnp::CertParams dup_selfsig; dup_selfsig.userid = "added1"; assert_throw(key->add_uid_cert(dup_selfsig, PGP_HASH_SHA256, global_ctx)); // try to add another primary userid (should fail) - rnp_selfsig_cert_info_t selfsig2; + rnp::CertParams selfsig2; selfsig2.userid = "added2"; selfsig2.primary = 1; assert_throw(key->add_uid_cert(selfsig2, PGP_HASH_SHA256, global_ctx)); selfsig2.userid = "added2"; - selfsig2.key_flags = 0xCD; + selfsig2.flags = 0xCD; selfsig2.primary = 0; // actually add another userid diff --git a/src/tests/key-protect.cpp b/src/tests/key-protect.cpp index 16c488837..740abffd8 100644 --- a/src/tests/key-protect.cpp +++ b/src/tests/key-protect.cpp @@ -235,10 +235,10 @@ TEST_F(rnp_tests, test_key_protect_sec_data) auto & rsa = dynamic_cast(keygen.key_params()); rsa.set_bits(1024); - rnp_selfsig_cert_info_t cert{}; + rnp::CertParams cert; cert.userid = "test"; - rnp_selfsig_binding_info_t binding{}; + rnp::BindingParams binding; /* generate raw unprotected keypair */ pgp_key_t skey, pkey, ssub, psub; diff --git a/src/tests/key-validate.cpp b/src/tests/key-validate.cpp index 0a5c924ed..aece4bba9 100644 --- a/src/tests/key-validate.cpp +++ b/src/tests/key-validate.cpp @@ -30,6 +30,7 @@ #include "support.h" #include "../librepgp/stream-packet.h" #include "../librepgp/stream-armor.h" +#include "keygen.hpp" static bool all_keys_valid(const rnp::KeyStore *keyring, pgp_key_t *except = NULL) @@ -665,10 +666,10 @@ TEST_F(rnp_tests, test_key_expiry_direct_sig) assert_false(subpub->expired()); /* add primary userid with smaller expiration date */ - rnp_selfsig_cert_info_t selfsig1 = {}; - const char * boris = "Boris "; + rnp::CertParams selfsig1 = {}; + const char * boris = "Boris "; selfsig1.userid = boris; - selfsig1.key_expiration = 100; + selfsig1.expiration = 100; selfsig1.primary = true; key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx); key->revalidate(*secring); @@ -703,7 +704,7 @@ TEST_F(rnp_tests, test_key_expiry_direct_sig) /* add primary userid with 0 expiration */ selfsig1 = {}; selfsig1.userid = boris; - selfsig1.key_expiration = 0; + selfsig1.expiration = 0; selfsig1.primary = true; key->add_uid_cert(selfsig1, PGP_HASH_SHA256, global_ctx); key->revalidate(*secring);