mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +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 long)
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
AC_CHECK_SIZEOF(size_t)
|
||||
AC_HEADER_TIME
|
||||
AC_CHECK_SIZEOF(time_t,,[[
|
||||
#include <stdio.h>
|
||||
|
@ -513,6 +513,7 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
|
||||
byte buf[10];
|
||||
int i;
|
||||
size_t n;
|
||||
|
||||
gcry_md_putc (digest, sig->pubkey_algo);
|
||||
gcry_md_putc (digest, sig->digest_algo);
|
||||
if (sig->hashed)
|
||||
@ -531,22 +532,39 @@ check_signature_end_simple (PKT_public_key *pk, PKT_signature *sig,
|
||||
gcry_md_putc (digest, 0);
|
||||
n = 6;
|
||||
}
|
||||
/* add some magic per Section 5.2.4 of RFC 4880. */
|
||||
i = 0;
|
||||
buf[i++] = sig->version;
|
||||
buf[i++] = 0xff;
|
||||
if (sig->version >= 5)
|
||||
{
|
||||
buf[i++] = 0;
|
||||
buf[i++] = 0;
|
||||
buf[i++] = 0;
|
||||
buf[i++] = 0;
|
||||
}
|
||||
buf[i++] = n >> 24;
|
||||
buf[i++] = n >> 16;
|
||||
buf[i++] = n >> 8;
|
||||
buf[i++] = n;
|
||||
gcry_md_write (digest, buf, i);
|
||||
/* 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;
|
||||
buf[i++] = sig->version;
|
||||
buf[i++] = 0xff;
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
buf[i++] = n >> 24;
|
||||
buf[i++] = n >> 16;
|
||||
buf[i++] = n >> 8;
|
||||
buf[i++] = n;
|
||||
gcry_md_write (digest, buf, i);
|
||||
}
|
||||
gcry_md_final( digest );
|
||||
|
||||
|
113
g10/sign.c
113
g10/sign.c
@ -49,7 +49,19 @@
|
||||
#define LF "\n"
|
||||
#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
|
||||
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];
|
||||
int i;
|
||||
@ -243,12 +258,39 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig)
|
||||
gcry_md_putc (md, 0);
|
||||
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. */
|
||||
i = 0;
|
||||
buf[i++] = sig->version;
|
||||
buf[i++] = 0xff;
|
||||
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;
|
||||
@ -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
|
||||
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;
|
||||
u32 filesize;
|
||||
@ -691,6 +737,19 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
||||
if ((rc = build_packet (out, &pkt)))
|
||||
log_error ("build_packet(PLAINTEXT) failed: %s\n",
|
||||
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;
|
||||
free_packet (&pkt, NULL);
|
||||
}
|
||||
@ -699,6 +758,18 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
|
||||
byte copy_buffer[4096];
|
||||
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)
|
||||
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 */
|
||||
}
|
||||
/* fixme: it seems that we never freed pt/pkt */
|
||||
|
||||
leave:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write the signatures from the SK_LIST to OUT. HASH must be a non-finalized
|
||||
* hash which will not be changes here.
|
||||
* Write the signatures from the SK_LIST to OUT. HASH must be a
|
||||
* 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
|
||||
write_signature_packets (ctrl_t ctrl,
|
||||
SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
|
||||
pt_extra_hash_data_t extrahash,
|
||||
int sigclass, u32 timestamp, u32 duration,
|
||||
int status_letter, const char *cache_nonce)
|
||||
{
|
||||
@ -744,7 +817,7 @@ write_signature_packets (ctrl_t ctrl,
|
||||
if (pk->version >= 5)
|
||||
sig->version = 5; /* Required for v5 keys. */
|
||||
else
|
||||
sig->version = 4; /*Required. */
|
||||
sig->version = 4; /* Required. */
|
||||
|
||||
keyid_from_pk (pk, sig->keyid);
|
||||
sig->digest_algo = hash_for (pk);
|
||||
@ -762,7 +835,7 @@ write_signature_packets (ctrl_t ctrl,
|
||||
|
||||
build_sig_subpkt_from_sig (sig, 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);
|
||||
|
||||
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;
|
||||
int multifile = 0;
|
||||
u32 duration=0;
|
||||
pt_extra_hash_data_t extrahash = NULL;
|
||||
|
||||
pfx = new_progress_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,
|
||||
(opt.textmode && !outfile) ?
|
||||
(opt.mimemode? 'm' : 't') : 'b');
|
||||
(opt.mimemode? 'm' : 't') : 'b',
|
||||
&extrahash);
|
||||
}
|
||||
|
||||
/* Catch errors from above. */
|
||||
@ -1133,7 +1208,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
|
||||
goto leave;
|
||||
|
||||
/* 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,
|
||||
0, duration, detached ? 'D':'S', NULL);
|
||||
if (rc)
|
||||
@ -1156,6 +1231,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
|
||||
recipient_digest_algo = 0;
|
||||
release_progress_context (pfx);
|
||||
release_armor_context (afx);
|
||||
xfree (extrahash);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1286,7 +1362,7 @@ clearsign_file (ctrl_t ctrl,
|
||||
push_armor_filter (afx, out);
|
||||
|
||||
/* 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);
|
||||
if (rc)
|
||||
goto leave;
|
||||
@ -1328,6 +1404,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
|
||||
int algo;
|
||||
u32 duration = 0;
|
||||
int canceled;
|
||||
pt_extra_hash_data_t extrahash = NULL;
|
||||
|
||||
pfx = new_progress_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. */
|
||||
/* (current filters: zip - encrypt - armor) */
|
||||
rc = write_plaintext_packet (out, inp, fname,
|
||||
opt.textmode ? (opt.mimemode?'m':'t'):'b');
|
||||
opt.textmode ? (opt.mimemode?'m':'t'):'b',
|
||||
&extrahash);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
/* Write the signatures. */
|
||||
/* (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,
|
||||
0, duration, 'S', NULL);
|
||||
if (rc)
|
||||
@ -1480,6 +1558,7 @@ sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
|
||||
xfree (s2k);
|
||||
release_progress_context (pfx);
|
||||
release_armor_context (afx);
|
||||
xfree (extrahash);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1599,7 +1678,7 @@ make_keysig_packet (ctrl_t ctrl,
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
hash_sigversion_to_magic (md, sig);
|
||||
hash_sigversion_to_magic (md, sig, NULL);
|
||||
gcry_md_final (md);
|
||||
rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
|
||||
}
|
||||
@ -1699,7 +1778,7 @@ update_keysig_packet (ctrl_t ctrl,
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
hash_sigversion_to_magic (md, sig);
|
||||
hash_sigversion_to_magic (md, sig, NULL);
|
||||
gcry_md_final (md);
|
||||
rc = complete_sig (ctrl, sig, pksk, md, NULL);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user