Skip to content

Commit

Permalink
add mandatory direct-key signature for v6 certificates
Browse files Browse the repository at this point in the history
  • Loading branch information
TJ-91 committed Nov 16, 2023
1 parent bcc9257 commit 432e453
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 14 deletions.
6 changes: 6 additions & 0 deletions src/lib/generate-key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,12 @@ pgp_generate_primary_key(rnp_keygen_primary_desc_t &desc,

pgp_key_t sec(secpkt);
pgp_key_t pub(secpkt, true);
#if defined(ENABLE_CRYPTO_REFRESH)
// for v6 packets, a direct-key sig is mandatory.
if (sec.version() == PGP_V6) {
sec.add_direct_sig(desc.cert, desc.crypto.hash_alg, *desc.crypto.ctx, &pub);
}
#endif
sec.add_uid_cert(desc.cert, desc.crypto.hash_alg, *desc.crypto.ctx, &pub);

switch (secformat) {
Expand Down
29 changes: 29 additions & 0 deletions src/lib/pgp-key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2426,6 +2426,35 @@ 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)
{
// We only support modifying v4 and newer keys
if (pkt().version < PGP_V4) {
RNP_LOG("adding a direct-key sig to V2/V3 key is not supported");
throw rnp::rnp_exception(RNP_ERROR_BAD_STATE);
}

pgp_signature_t sig;
sign_init(ctx.rng, sig, hash, ctx.time(), pkt().version);
sig.set_type(PGP_SIG_DIRECT);
cert.populate(sig);
sign_direct(pkt_, sig, ctx);

add_sig(sig, PGP_UID_NONE);
refresh_data(ctx);
if (!pubkey) {
return;
}
pubkey->add_sig(sig, PGP_UID_NONE);
pubkey->refresh_data(ctx);
}
#endif

void
pgp_key_t::add_uid_cert(rnp_selfsig_cert_info_t &cert,
pgp_hash_alg_t hash,
Expand Down
17 changes: 17 additions & 0 deletions src/lib/pgp-key.h
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,23 @@ struct pgp_key_t {
pgp_signature_t & sig,
rnp::SecurityContext &ctx);

#if defined(ENABLE_CRYPTO_REFRESH)
/**
* @brief Add a direct-key self signature
* Note: secret key must be unlocked before calling this function.
*
* @param cert certification 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 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);
#endif

/**
* @brief Add and certify userid.
* Note: secret key must be unlocked before calling this function.
Expand Down
2 changes: 2 additions & 0 deletions src/lib/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ typedef struct rnp_selfsig_cert_info_t {
* 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 {
Expand Down
51 changes: 37 additions & 14 deletions src/librepgp/stream-sig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1769,19 +1769,42 @@ pgp_signature_t::fill_hashed_data()
}

void
rnp_selfsig_cert_info_t::populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig)
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)
{
/* populate signature */
sig.set_type(PGP_CERT_POSITIVE);
if (key_expiration) {
sig.set_key_expiration(key_expiration);
}
if (key_flags) {
sig.set_key_flags(key_flags);
}
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;
}
#endif
if (key_flags) {
sig.set_key_flags(key_flags);
}
if (!prefs.symm_algs.empty()) {
sig.set_preferred_symm_algs(prefs.symm_algs);
}
Expand All @@ -1797,12 +1820,12 @@ rnp_selfsig_cert_info_t::populate(pgp_userid_pkt_t &uid, pgp_signature_t &sig)
if (!prefs.key_server.empty()) {
sig.set_key_server(prefs.key_server);
}
/* populate 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_userid_pkt_t &uid, pgp_signature_t &sig)
{
sig.set_type(PGP_CERT_POSITIVE);
populate(sig);
populate(uid);
}

0 comments on commit 432e453

Please sign in to comment.