gpg-interface: prefer check_signature() for GPG verification
This commit refactors the use of verify_signed_buffer() outside of gpg-interface.c to use check_signature() instead. It also turns verify_signed_buffer() into a file-local function since it's now only invoked internally by check_signature(). There were previously two globally scoped functions used in different parts of Git to perform GPG signature verification: verify_signed_buffer() and check_signature(). Now only check_signature() is used. The verify_signed_buffer() function doesn't guard against duplicate signatures as described by Michał Górny [1]. Instead it only ensures a non-erroneous exit code from GPG and the presence of at least one GOODSIG status field. This stands in contrast with check_signature() that returns an error if more than one signature is encountered. The lower degree of verification makes the use of verify_signed_buffer() problematic if callers don't parse and validate the various parts of the GPG status message themselves. And processing these messages seems like a task that should be reserved to gpg-interface.c with the function check_signature(). Furthermore, the use of verify_signed_buffer() makes it difficult to introduce new functionality that relies on the content of the GPG status lines. Now all operations that does signature verification share a single entry point to gpg-interface.c. This makes it easier to propagate changed or additional functionality in GPG signature verification to all parts of Git, without having odd edge-cases that don't perform the same degree of verification. [1] https://dev.gentoo.org/~mgorny/articles/attack-on-git-signature-verification.html Signed-off-by: Hans Jerry Illikainen <hji@dyntopia.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
67a6ea6300
commit
72b006f4bf
30
log-tree.c
30
log-tree.c
@ -448,22 +448,22 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
|
||||
{
|
||||
struct strbuf payload = STRBUF_INIT;
|
||||
struct strbuf signature = STRBUF_INIT;
|
||||
struct strbuf gpg_output = STRBUF_INIT;
|
||||
struct signature_check sigc = { 0 };
|
||||
int status;
|
||||
|
||||
if (parse_signed_commit(commit, &payload, &signature) <= 0)
|
||||
goto out;
|
||||
|
||||
status = verify_signed_buffer(payload.buf, payload.len,
|
||||
signature.buf, signature.len,
|
||||
&gpg_output, NULL);
|
||||
if (status && !gpg_output.len)
|
||||
strbuf_addstr(&gpg_output, "No signature\n");
|
||||
|
||||
show_sig_lines(opt, status, gpg_output.buf);
|
||||
status = check_signature(payload.buf, payload.len, signature.buf,
|
||||
signature.len, &sigc);
|
||||
if (status && sigc.result == 'N')
|
||||
show_sig_lines(opt, status, "No signature\n");
|
||||
else {
|
||||
show_sig_lines(opt, status, sigc.gpg_output);
|
||||
signature_check_clear(&sigc);
|
||||
}
|
||||
|
||||
out:
|
||||
strbuf_release(&gpg_output);
|
||||
strbuf_release(&payload);
|
||||
strbuf_release(&signature);
|
||||
}
|
||||
@ -496,6 +496,7 @@ static int show_one_mergetag(struct commit *commit,
|
||||
struct object_id oid;
|
||||
struct tag *tag;
|
||||
struct strbuf verify_message;
|
||||
struct signature_check sigc = { 0 };
|
||||
int status, nth;
|
||||
size_t payload_size, gpg_message_offset;
|
||||
|
||||
@ -524,12 +525,13 @@ static int show_one_mergetag(struct commit *commit,
|
||||
status = -1;
|
||||
if (extra->len > payload_size) {
|
||||
/* could have a good signature */
|
||||
if (!verify_signed_buffer(extra->value, payload_size,
|
||||
extra->value + payload_size,
|
||||
extra->len - payload_size,
|
||||
&verify_message, NULL))
|
||||
if (!check_signature(extra->value, payload_size,
|
||||
extra->value + payload_size,
|
||||
extra->len - payload_size, &sigc)) {
|
||||
strbuf_addstr(&verify_message, sigc.gpg_output);
|
||||
signature_check_clear(&sigc);
|
||||
status = 0; /* good */
|
||||
else if (verify_message.len <= gpg_message_offset)
|
||||
} else if (verify_message.len <= gpg_message_offset)
|
||||
strbuf_addstr(&verify_message, "No signature\n");
|
||||
/* otherwise we couldn't verify, which is shown as bad */
|
||||
}
|
||||
|
Reference in New Issue
Block a user