mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-11 22:52:47 +01:00
gpg: Implemented latest rfc4880bis version 5 packet hashing.
* configure.ac (AC_CHECK_SIZEOF): Test size_t. * g10/sig-check.c (check_signature_end_simple): Support v5 signatures as per current rfc4880bis. For correctness also allow for N > 2^32. * g10/sign.c (pt_extra_hash_data_t): New. (hash_sigversion_to_magic): New arg EXTRAHASH. (write_plaintext_packet): New arg R_EXTRAHASH. (write_signature_packets): Pass EXTRAHASH. (sign_file): Ditto. (sign_symencrypt_file): Ditto. -- Take care: The code path for v5 sigs has not yet been tested. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
f199b627ce
commit
a21ca3a1ef
@ -1367,6 +1367,7 @@ AC_CHECK_SIZEOF(unsigned short)
|
|||||||
AC_CHECK_SIZEOF(unsigned int)
|
AC_CHECK_SIZEOF(unsigned int)
|
||||||
AC_CHECK_SIZEOF(unsigned long)
|
AC_CHECK_SIZEOF(unsigned long)
|
||||||
AC_CHECK_SIZEOF(unsigned long long)
|
AC_CHECK_SIZEOF(unsigned long long)
|
||||||
|
AC_CHECK_SIZEOF(size_t)
|
||||||
AC_HEADER_TIME
|
AC_HEADER_TIME
|
||||||
AC_CHECK_SIZEOF(time_t,,[[
|
AC_CHECK_SIZEOF(time_t,,[[
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -513,6 +513,7 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
|
|||||||
byte buf[10];
|
byte buf[10];
|
||||||
int i;
|
int i;
|
||||||
size_t n;
|
size_t n;
|
||||||
|
|
||||||
gcry_md_putc (digest, sig->pubkey_algo);
|
gcry_md_putc (digest, sig->pubkey_algo);
|
||||||
gcry_md_putc (digest, sig->digest_algo);
|
gcry_md_putc (digest, sig->digest_algo);
|
||||||
if (sig->hashed)
|
if (sig->hashed)
|
||||||
@ -531,16 +532,33 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
|
|||||||
gcry_md_putc (digest, 0);
|
gcry_md_putc (digest, 0);
|
||||||
n = 6;
|
n = 6;
|
||||||
}
|
}
|
||||||
/* add some magic per Section 5.2.4 of RFC 4880. */
|
/* Hash data from the literal data packet. */
|
||||||
|
if (sig->version >= 5
|
||||||
|
&& (sig->sig_class == 0x00 || sig->sig_class == 0x01))
|
||||||
|
{
|
||||||
|
/* - One octet content format
|
||||||
|
* - File name (one octet length followed by the name)
|
||||||
|
* - Four octet timestamp */
|
||||||
|
memset (buf, 0, 6);
|
||||||
|
gcry_md_write (digest, buf, 6);
|
||||||
|
}
|
||||||
|
/* Add some magic per Section 5.2.4 of RFC 4880. */
|
||||||
i = 0;
|
i = 0;
|
||||||
buf[i++] = sig->version;
|
buf[i++] = sig->version;
|
||||||
buf[i++] = 0xff;
|
buf[i++] = 0xff;
|
||||||
if (sig->version >= 5)
|
if (sig->version >= 5)
|
||||||
{
|
{
|
||||||
|
#if SIZEOF_SIZE_T > 4
|
||||||
|
buf[i++] = n >> 56;
|
||||||
|
buf[i++] = n >> 48;
|
||||||
|
buf[i++] = n >> 40;
|
||||||
|
buf[i++] = n >> 32;
|
||||||
|
#else
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
buf[i++] = n >> 24;
|
buf[i++] = n >> 24;
|
||||||
buf[i++] = n >> 16;
|
buf[i++] = n >> 16;
|
||||||
|
111
g10/sign.c
111
g10/sign.c
@ -49,7 +49,19 @@
|
|||||||
#define LF "\n"
|
#define LF "\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int recipient_digest_algo=0;
|
/* A type for the extra data we hash into v5 signature packets. */
|
||||||
|
struct pt_extra_hash_data_s
|
||||||
|
{
|
||||||
|
unsigned char mode;
|
||||||
|
u32 timestamp;
|
||||||
|
unsigned char namelen;
|
||||||
|
char name[1];
|
||||||
|
};
|
||||||
|
typedef struct pt_extra_hash_data_s *pt_extra_hash_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Hack */
|
||||||
|
static int recipient_digest_algo;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -216,10 +228,13 @@ hash_uid (gcry_md_hd_t md, int sigversion, const PKT_user_id *uid)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper to hash some parts from the signature
|
* Helper to hash some parts from the signature. EXTRAHASH gives the
|
||||||
|
* extra data to be hashed into v5 signatures; it may by NULL for
|
||||||
|
* detached signatures.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
|
hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig,
|
||||||
|
pt_extra_hash_data_t extrahash)
|
||||||
{
|
{
|
||||||
byte buf[10];
|
byte buf[10];
|
||||||
int i;
|
int i;
|
||||||
@ -243,12 +258,39 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
|
|||||||
gcry_md_putc (md, 0);
|
gcry_md_putc (md, 0);
|
||||||
n = 6;
|
n = 6;
|
||||||
}
|
}
|
||||||
|
/* Hash data from the literal data packet. */
|
||||||
|
if (sig->version >= 5 && (sig->sig_class == 0x00 || sig->sig_class == 0x01))
|
||||||
|
{
|
||||||
|
/* - One octet content format
|
||||||
|
* - File name (one octet length followed by the name)
|
||||||
|
* - Four octet timestamp */
|
||||||
|
if (extrahash)
|
||||||
|
{
|
||||||
|
buf[0] = extrahash->mode;
|
||||||
|
buf[1] = extrahash->namelen;
|
||||||
|
gcry_md_write (md, buf, 2);
|
||||||
|
if (extrahash->namelen)
|
||||||
|
gcry_md_write (md, extrahash->name, extrahash->namelen);
|
||||||
|
buf[0] = extrahash->timestamp >> 24;
|
||||||
|
buf[1] = extrahash->timestamp >> 16;
|
||||||
|
buf[2] = extrahash->timestamp >> 8;
|
||||||
|
buf[3] = extrahash->timestamp;
|
||||||
|
gcry_md_write (md, buf, 4);
|
||||||
|
}
|
||||||
|
else /* Detached signatures */
|
||||||
|
{
|
||||||
|
memset (buf, 0, 6);
|
||||||
|
gcry_md_write (md, buf, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Add some magic. */
|
/* Add some magic. */
|
||||||
i = 0;
|
i = 0;
|
||||||
buf[i++] = sig->version;
|
buf[i++] = sig->version;
|
||||||
buf[i++] = 0xff;
|
buf[i++] = 0xff;
|
||||||
if (sig->version >= 5)
|
if (sig->version >= 5)
|
||||||
{
|
{
|
||||||
|
/* Note: We don't hashed any data larger than 2^32 and thus we
|
||||||
|
* can always use 0 here. See also note below. */
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
buf[i++] = 0;
|
buf[i++] = 0;
|
||||||
@ -633,10 +675,14 @@ write_onepass_sig_packets (SK_LIST sk_list, IOBUF out, int sigclass )
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper to write the plaintext (literal data) packet
|
* Helper to write the plaintext (literal data) packet. At
|
||||||
|
* R_EXTRAHASH a malloced object with the with the extra data hashed
|
||||||
|
* into v5 signatures is stored.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
write_plaintext_packet (iobuf_t out, iobuf_t inp,
|
||||||
|
const char *fname, int ptmode,
|
||||||
|
pt_extra_hash_data_t *r_extrahash)
|
||||||
{
|
{
|
||||||
PKT_plaintext *pt = NULL;
|
PKT_plaintext *pt = NULL;
|
||||||
u32 filesize;
|
u32 filesize;
|
||||||
@ -691,6 +737,19 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
|||||||
if ((rc = build_packet (out, &pkt)))
|
if ((rc = build_packet (out, &pkt)))
|
||||||
log_error ("build_packet(PLAINTEXT) failed: %s\n",
|
log_error ("build_packet(PLAINTEXT) failed: %s\n",
|
||||||
gpg_strerror (rc) );
|
gpg_strerror (rc) );
|
||||||
|
|
||||||
|
*r_extrahash = xtrymalloc (sizeof **r_extrahash + pt->namelen);
|
||||||
|
if (!*r_extrahash)
|
||||||
|
rc = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*r_extrahash)->mode = pt->mode;
|
||||||
|
(*r_extrahash)->timestamp = pt->timestamp;
|
||||||
|
(*r_extrahash)->namelen = pt->namelen;
|
||||||
|
/* Note that the last byte or NAME won't be initialized
|
||||||
|
* becuase we don't need it. */
|
||||||
|
memcpy ((*r_extrahash)->name, pt->name, pt->namelen);
|
||||||
|
}
|
||||||
pt->buf = NULL;
|
pt->buf = NULL;
|
||||||
free_packet (&pkt, NULL);
|
free_packet (&pkt, NULL);
|
||||||
}
|
}
|
||||||
@ -699,6 +758,18 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
|||||||
byte copy_buffer[4096];
|
byte copy_buffer[4096];
|
||||||
int bytes_copied;
|
int bytes_copied;
|
||||||
|
|
||||||
|
*r_extrahash = xtrymalloc (sizeof **r_extrahash);
|
||||||
|
if (!*r_extrahash)
|
||||||
|
{
|
||||||
|
rc = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* FIXME: We need to parse INP to get the to be hashed data from
|
||||||
|
* it. */
|
||||||
|
(*r_extrahash)->mode = 0;
|
||||||
|
(*r_extrahash)->timestamp = 0;
|
||||||
|
(*r_extrahash)->namelen = 0;
|
||||||
|
|
||||||
while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
|
while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
|
||||||
if ((rc = iobuf_write (out, copy_buffer, bytes_copied)))
|
if ((rc = iobuf_write (out, copy_buffer, bytes_copied)))
|
||||||
{
|
{
|
||||||
@ -708,19 +779,21 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
|||||||
}
|
}
|
||||||
wipememory (copy_buffer, 4096); /* burn buffer */
|
wipememory (copy_buffer, 4096); /* burn buffer */
|
||||||
}
|
}
|
||||||
/* fixme: it seems that we never freed pt/pkt */
|
|
||||||
|
|
||||||
|
leave:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write the signatures from the SK_LIST to OUT. HASH must be a non-finalized
|
* Write the signatures from the SK_LIST to OUT. HASH must be a
|
||||||
* hash which will not be changes here.
|
* non-finalized hash which will not be changes here. EXTRAHASH is
|
||||||
|
* either NULL or the extra data tro be hashed into v5 signatures.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
write_signature_packets (ctrl_t ctrl,
|
write_signature_packets (ctrl_t ctrl,
|
||||||
SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
|
SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
|
||||||
|
pt_extra_hash_data_t extrahash,
|
||||||
int sigclass, u32 timestamp, u32 duration,
|
int sigclass, u32 timestamp, u32 duration,
|
||||||
int status_letter, const char *cache_nonce)
|
int status_letter, const char *cache_nonce)
|
||||||
{
|
{
|
||||||
@ -762,7 +835,7 @@ write_signature_packets (ctrl_t ctrl,
|
|||||||
|
|
||||||
build_sig_subpkt_from_sig (sig, pk);
|
build_sig_subpkt_from_sig (sig, pk);
|
||||||
mk_notation_policy_etc (sig, NULL, pk);
|
mk_notation_policy_etc (sig, NULL, pk);
|
||||||
hash_sigversion_to_magic (md, sig);
|
hash_sigversion_to_magic (md, sig, extrahash);
|
||||||
gcry_md_final (md);
|
gcry_md_final (md);
|
||||||
|
|
||||||
rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce);
|
rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce);
|
||||||
@ -826,6 +899,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
|
|||||||
SK_LIST sk_rover = NULL;
|
SK_LIST sk_rover = NULL;
|
||||||
int multifile = 0;
|
int multifile = 0;
|
||||||
u32 duration=0;
|
u32 duration=0;
|
||||||
|
pt_extra_hash_data_t extrahash = NULL;
|
||||||
|
|
||||||
pfx = new_progress_context ();
|
pfx = new_progress_context ();
|
||||||
afx = new_armor_context ();
|
afx = new_armor_context ();
|
||||||
@ -1125,7 +1199,8 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
|
|||||||
{
|
{
|
||||||
rc = write_plaintext_packet (out, inp, fname,
|
rc = write_plaintext_packet (out, inp, fname,
|
||||||
(opt.textmode && !outfile) ?
|
(opt.textmode && !outfile) ?
|
||||||
(opt.mimemode? 'm' : 't') : 'b');
|
(opt.mimemode? 'm' : 't') : 'b',
|
||||||
|
&extrahash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Catch errors from above. */
|
/* Catch errors from above. */
|
||||||
@ -1133,7 +1208,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
|
|||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Write the signatures. */
|
/* Write the signatures. */
|
||||||
rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
|
rc = write_signature_packets (ctrl, sk_list, out, mfx.md, extrahash,
|
||||||
opt.textmode && !outfile? 0x01 : 0x00,
|
opt.textmode && !outfile? 0x01 : 0x00,
|
||||||
0, duration, detached ? 'D':'S', NULL);
|
0, duration, detached ? 'D':'S', NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1156,6 +1231,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
|
|||||||
recipient_digest_algo = 0;
|
recipient_digest_algo = 0;
|
||||||
release_progress_context (pfx);
|
release_progress_context (pfx);
|
||||||
release_armor_context (afx);
|
release_armor_context (afx);
|
||||||
|
xfree (extrahash);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1286,7 +1362,7 @@ clearsign_file (ctrl_t ctrl,
|
|||||||
push_armor_filter (afx, out);
|
push_armor_filter (afx, out);
|
||||||
|
|
||||||
/* Write the signatures. */
|
/* Write the signatures. */
|
||||||
rc = write_signature_packets (ctrl, sk_list, out, textmd, 0x01, 0,
|
rc = write_signature_packets (ctrl, sk_list, out, textmd, NULL, 0x01, 0,
|
||||||
duration, 'C', NULL);
|
duration, 'C', NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -1328,6 +1404,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
|
|||||||
int algo;
|
int algo;
|
||||||
u32 duration = 0;
|
u32 duration = 0;
|
||||||
int canceled;
|
int canceled;
|
||||||
|
pt_extra_hash_data_t extrahash = NULL;
|
||||||
|
|
||||||
pfx = new_progress_context ();
|
pfx = new_progress_context ();
|
||||||
afx = new_armor_context ();
|
afx = new_armor_context ();
|
||||||
@ -1452,13 +1529,14 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
|
|||||||
/* Pipe data through all filters; i.e. write the signed stuff. */
|
/* Pipe data through all filters; i.e. write the signed stuff. */
|
||||||
/* (current filters: zip - encrypt - armor) */
|
/* (current filters: zip - encrypt - armor) */
|
||||||
rc = write_plaintext_packet (out, inp, fname,
|
rc = write_plaintext_packet (out, inp, fname,
|
||||||
opt.textmode ? (opt.mimemode?'m':'t'):'b');
|
opt.textmode ? (opt.mimemode?'m':'t'):'b',
|
||||||
|
&extrahash);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
/* Write the signatures. */
|
/* Write the signatures. */
|
||||||
/* (current filters: zip - encrypt - armor) */
|
/* (current filters: zip - encrypt - armor) */
|
||||||
rc = write_signature_packets (ctrl, sk_list, out, mfx.md,
|
rc = write_signature_packets (ctrl, sk_list, out, mfx.md, extrahash,
|
||||||
opt.textmode? 0x01 : 0x00,
|
opt.textmode? 0x01 : 0x00,
|
||||||
0, duration, 'S', NULL);
|
0, duration, 'S', NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1480,6 +1558,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
|
|||||||
xfree (s2k);
|
xfree (s2k);
|
||||||
release_progress_context (pfx);
|
release_progress_context (pfx);
|
||||||
release_armor_context (afx);
|
release_armor_context (afx);
|
||||||
|
xfree (extrahash);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1599,7 +1678,7 @@ make_keysig_packet (ctrl_t ctrl,
|
|||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
hash_sigversion_to_magic (md, sig);
|
hash_sigversion_to_magic (md, sig, NULL);
|
||||||
gcry_md_final (md);
|
gcry_md_final (md);
|
||||||
rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
|
rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
|
||||||
}
|
}
|
||||||
@ -1699,7 +1778,7 @@ update_keysig_packet (ctrl_t ctrl,
|
|||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
hash_sigversion_to_magic (md, sig);
|
hash_sigversion_to_magic (md, sig, NULL);
|
||||||
gcry_md_final (md);
|
gcry_md_final (md);
|
||||||
rc = complete_sig (ctrl, sig, pksk, md, NULL);
|
rc = complete_sig (ctrl, sig, pksk, md, NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user