From aa9da2b07e9bae6e5de9659122e02175a26a1253 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 9 Aug 2001 09:34:25 +0000 Subject: [PATCH] reworked the way hased data is stored and added a "primary" command DCVS: ---------------------------------------------------------------------- --- NEWS | 3 + g10/ChangeLog | 17 ++++ g10/build-packet.c | 226 +++++++++++++++++++++------------------------ g10/export.c | 4 +- g10/free-packet.c | 22 ++--- g10/getkey.c | 23 +++-- g10/import.c | 2 +- g10/keyedit.c | 8 +- g10/mainproc.c | 5 +- g10/packet.h | 30 ++++-- g10/parse-packet.c | 65 +++++++------ g10/pkclist.c | 2 +- g10/sig-check.c | 18 ++-- g10/sign.c | 32 ++++--- 14 files changed, 244 insertions(+), 213 deletions(-) diff --git a/NEWS b/NEWS index 4d073eff7..c701794ce 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ * There is no default comment string with ascii armors anymore except for revocation certificates and --enarmor mode. + * The command "primary" in the edit menu can be used to change the + primary UID. + Noteworthy changes in version 1.0.6 (2001-05-29) ------------------------------------------------ diff --git a/g10/ChangeLog b/g10/ChangeLog index f1b5f9f46..5a29b0cfd 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,22 @@ 2001-08-08 Werner Koch + * packet.h (subpktarea_t): New. + (PKT_signature): Use that type for hashed_data and unhashed_data and + removed the _data prefix from those fields. Changed all users. + * parse-packet.c (parse_signature): Changed allocation for that. + (parse_sig_subpkt): Changed declaration + (enum_sig_subpkt): Ditto and changed implementation accordingly. + * free-packet.c (cp_subpktarea): Renamed from cp_data_block and + adjusted implementation. Changed caller. + * sig-check.c (mdc_kludge_check): Adjusted the hashing. + (do_check): Ditto. + * sign.c (sign_file, clearsign_file, make_keysig_packet, + update_keysig_packet): Ditto. + * build-packet.c (build_sig_subpkt): Partial rewrite. + (find_subpkt): Adjusted and made static. + (delete_sig_subpkt): Adjusted. + (do_signature): Ditto. + * keygen.c (ask_keysize): Do not print the notes about suggested key sizes if just a DSA key is generated. diff --git a/g10/build-packet.c b/g10/build-packet.c index 3a981ca5c..ac21f8896 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -589,24 +589,25 @@ do_compressed( IOBUF out, int ctb, PKT_compressed *cd ) /**************** - * Find a subpacket of type REQTYPE in BUFFER and a return a pointer + * Find a subpacket of type REQTYPE in AREA and a return a pointer * to the first byte of that subpacket data. * And return the length of the packet in RET_N and the number of * header bytes in RET_HLEN (length header and type byte). */ -byte * -find_subpkt( byte *buffer, sigsubpkttype_t reqtype, +static byte * +find_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype, size_t *ret_hlen, size_t *ret_n ) { + byte *buffer; int buflen; sigsubpkttype_t type; byte *bufstart; size_t n; - if( !buffer ) + if( !area ) return NULL; - buflen = (*buffer << 8) | buffer[1]; - buffer += 2; + buflen = area->len; + buffer = area->data; for(;;) { if( !buflen ) return NULL; /* end of packets; not found */ @@ -616,7 +617,7 @@ find_subpkt( byte *buffer, sigsubpkttype_t reqtype, if( buflen < 4 ) break; n = (buffer[0] << 24) | (buffer[1] << 16) - | (buffer[2] << 8) | buffer[3]; + | (buffer[2] << 8) | buffer[3]; buffer += 4; buflen -= 4; } @@ -649,25 +650,23 @@ find_subpkt( byte *buffer, sigsubpkttype_t reqtype, } /**************** - * Delete all subpackets of type REQTYPE and return the number of bytes - * which are now unused at the end of the buffer. + * Delete all subpackets of type REQTYPE and return a bool whether a packet + * was deleted. */ -size_t -delete_sig_subpkt( byte *buffer, sigsubpkttype_t reqtype ) +int +delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype ) { - int buflen, orig_buflen; + int buflen; sigsubpkttype_t type; - byte *bufstart, *orig_buffer; + byte *buffer, *bufstart; size_t n; size_t unused = 0; int okay = 0; - if( !buffer ) + if( !area ) return 0; - orig_buffer = buffer; - buflen = (*buffer << 8) | buffer[1]; - buffer += 2; - orig_buflen = buflen; + buflen = area->len; + buffer = area->data; for(;;) { if( !buflen ) { okay = 1; @@ -679,7 +678,7 @@ delete_sig_subpkt( byte *buffer, sigsubpkttype_t reqtype ) if( buflen < 4 ) break; n = (buffer[0] << 24) | (buffer[1] << 16) - | (buffer[2] << 8) | buffer[3]; + | (buffer[2] << 8) | buffer[3]; buffer += 4; buflen -= 4; } @@ -692,6 +691,7 @@ delete_sig_subpkt( byte *buffer, sigsubpkttype_t reqtype ) } if( buflen < n ) break; + type = *buffer & 0x7f; if( type == reqtype ) { buffer++; @@ -699,10 +699,11 @@ delete_sig_subpkt( byte *buffer, sigsubpkttype_t reqtype ) n--; if( n > buflen ) break; - memmove (bufstart, buffer + n, n + (buffer-bufstart)); /* shift */ - unused += n + (buffer-bufstart); - buffer = bufstart; + buffer += n; /* point to next subpkt */ buflen -= n; + memmove (bufstart, buffer, buflen); /* shift */ + unused += buffer - bufstart; + buffer = bufstart; } else { buffer += n; buflen -=n; @@ -710,65 +711,62 @@ delete_sig_subpkt( byte *buffer, sigsubpkttype_t reqtype ) } if (!okay) - log_error("delete_subpkt: buffer shorter than subpacket\n"); - assert (unused <= orig_buflen); - orig_buflen -= unused; - orig_buffer[0] = (orig_buflen >> 8) & 0xff; - orig_buffer[1] = orig_buflen & 0xff; - return unused; + log_error ("delete_subpkt: buffer shorter than subpacket\n"); + assert (unused <= area->len); + area->len -= unused; + return !!unused; } /**************** - * Create or update a signature subpacket for SIG of TYPE. - * This functions knows where to put the data (hashed or unhashed). - * The function may move data from the unhashed part to the hashed one. - * Note: All pointers into sig->[un]hashed are not valid after a call - * to this function. The data to put into the subpaket should be - * in buffer with a length of buflen. + * Create or update a signature subpacket for SIG of TYPE. This + * functions knows where to put the data (hashed or unhashed). The + * function may move data from the unhashed part to the hashed one. + * Note: All pointers into sig->[un]hashed (e.g. returned by + * parse_sig_subpkt) are not valid after a call to this function. The + * data to put into the subpaket should be in a buffer with a length + * of buflen. */ void -build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, +build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ) { - byte *data; - size_t hlen, dlen, nlen; - int found=0; - int critical, hashed, realloced; - size_t n, n0; - size_t unused = 0; + byte *p; + int critical, hashed; + subpktarea_t *oldarea, *newarea; + size_t nlen, n, n0; critical = (type & SIGSUBPKT_FLAG_CRITICAL); type &= ~SIGSUBPKT_FLAG_CRITICAL; - + if( type == SIGSUBPKT_NOTATION ) ; /* we allow multiple packets */ - else if( (data = find_subpkt( sig->hashed_data, type, &hlen, &dlen )) ) - found = 1; - else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen ))) - found = 2; - - if (found==1 && (type == SIGSUBPKT_SIG_CREATED) ) { - unused = delete_sig_subpkt (sig->hashed_data, type); - assert (unused); - found = 0; + else if (find_subpkt (sig->hashed, type, NULL, NULL) ) { + switch (type) { + case SIGSUBPKT_SIG_CREATED: + delete_sig_subpkt (sig->hashed, type); + break; + default: + log_bug("build_sig_packet: update of hashed type %d nyi\n", type); + } } - else if (found==2 && ( type == SIGSUBPKT_PRIV_VERIFY_CACHE - || type == SIGSUBPKT_ISSUER - ) ) { - unused = delete_sig_subpkt (sig->unhashed_data, type); - assert (unused); - found = 0; + else if (find_subpkt (sig->unhashed, type, NULL, NULL)) { + switch (type) { + case SIGSUBPKT_PRIV_VERIFY_CACHE: + case SIGSUBPKT_ISSUER: + delete_sig_subpkt (sig->unhashed, type); + break; + default: + log_bug("build_sig_packet: update of unhashed type %d nyi\n",type); + } } - if( found ) - log_bug("build_sig_packet: update nyi\n"); if( (buflen+1) >= 8384 ) - nlen = 5; + nlen = 5; /* write 5 byte length header */ else if( (buflen+1) >= 192 ) - nlen = 2; + nlen = 2; /* write 2 byte length header */ else - nlen = 1; + nlen = 1; /* just a 1 byte length header */ switch( type ) { case SIGSUBPKT_SIG_CREATED: @@ -785,67 +783,55 @@ build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, default: hashed = 0; break; } - if( hashed ) { - n0 = sig->hashed_data ? ((*sig->hashed_data << 8) - | sig->hashed_data[1]) : 0; - n = n0 + nlen + 1 + buflen; /* length, type, buffer */ - realloced = !!sig->hashed_data; - data = sig->hashed_data ? m_realloc( sig->hashed_data, n+2 ) - : m_alloc( n+2 ); - } - else { - n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8) - | sig->unhashed_data[1]) : 0; - n = n0 + nlen + 1 + buflen; /* length, type, buffer */ - if ( sig->unhashed_data && (nlen + 1 + buflen) <= unused ) { - /* does fit into the freed area */ - data = sig->unhashed_data; - realloced = 1; - log_debug ("updating area of type %d\n", type ); - } - else { - realloced = !!sig->unhashed_data; - data = sig->unhashed_data ? m_realloc( sig->unhashed_data, n+2 ) - : m_alloc( n+2 ); - } - } - if( critical ) type |= SIGSUBPKT_FLAG_CRITICAL; - data[0] = (n >> 8) & 0xff; - data[1] = n & 0xff; - if( nlen == 5 ) { - data[n0+2] = 255; - data[n0+3] = (buflen+1) >> 24; - data[n0+4] = (buflen+1) >> 16; - data[n0+5] = (buflen+1) >> 8; - data[n0+6] = (buflen+1); - data[n0+7] = type; - memcpy(data+n0+8, buffer, buflen ); + oldarea = hashed? sig->hashed : sig->unhashed; + + /* Calculate new size of the area and allocate */ + n0 = oldarea? oldarea->len : 0; + n = n0 + nlen + 1 + buflen; /* length, type, buffer */ + if (oldarea && n <= oldarea->size) { /* fits into the unused space */ + newarea = oldarea; + /*log_debug ("updating area for type %d\n", type );*/ } - else if( nlen == 2 ) { - data[n0+2] = (buflen+1-192) / 256 + 192; - data[n0+3] = (buflen+1-192) % 256; - data[n0+4] = type; - memcpy(data+n0+5, buffer, buflen ); + else if (oldarea) { + newarea = m_realloc (oldarea, sizeof (*newarea) + n - 1); + newarea->size = sizeof (*newarea) + n - 1; + /*log_debug ("reallocating area for type %d\n", type );*/ } else { - data[n0+2] = buflen+1; - data[n0+3] = type; - memcpy(data+n0+4, buffer, buflen ); + newarea = m_alloc (sizeof (*newarea) + n - 1); + /*log_debug ("allocating area for type %d\n", type );*/ + } + newarea->len = n; + + p = newarea->data + n0; + if (nlen == 5) { + *p++ = 255; + *p++ = (buflen+1) >> 24; + *p++ = (buflen+1) >> 16; + *p++ = (buflen+1) >> 8; + *p++ = (buflen+1); + *p++ = type; + memcpy (p, buffer, buflen); + } + else if (nlen == 2) { + *p++ = (buflen+1-192) / 256 + 192; + *p++ = (buflen+1-192) % 256; + *p++ = type; + memcpy (p, buffer, buflen); + } + else { + *p++ = buflen+1; + *p++ = type; + memcpy (p, buffer, buflen); } - if( hashed ) { - if( !realloced ) - m_free(sig->hashed_data); - sig->hashed_data = data; - } - else { - if( !realloced ) - m_free(sig->unhashed_data); - sig->unhashed_data = data; - } + if (hashed) + sig->hashed = newarea; + else + sig->unhashed = newarea; } /**************** @@ -905,16 +891,14 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) /* timestamp and keyid must have been packed into the * subpackets prior to the call of this function, because * these subpackets are hashed */ - nn = sig->hashed_data?((sig->hashed_data[0]<<8) - |sig->hashed_data[1]) :0; + nn = sig->hashed? sig->hashed->len : 0; write_16(a, nn); if( nn ) - iobuf_write( a, sig->hashed_data+2, nn ); - nn = sig->unhashed_data?((sig->unhashed_data[0]<<8) - |sig->unhashed_data[1]) :0; + iobuf_write( a, sig->hashed->data, nn ); + nn = sig->unhashed? sig->unhashed->len : 0; write_16(a, nn); if( nn ) - iobuf_write( a, sig->unhashed_data+2, nn ); + iobuf_write( a, sig->unhashed->data, nn ); } iobuf_put(a, sig->digest_start[0] ); iobuf_put(a, sig->digest_start[1] ); diff --git a/g10/export.c b/g10/export.c index d156d1ccd..05efef0d0 100644 --- a/g10/export.c +++ b/g10/export.c @@ -199,8 +199,8 @@ do_export_stream( IOBUF out, STRLIST users, int secret, int onlyrfc, int *any ) continue; /* not exportable */ /* delete our verification cache */ - delete_sig_subpkt (node->pkt->pkt.signature->unhashed_data, - SIGSUBPKT_PRIV_VERIFY_CACHE); + delete_sig_subpkt (node->pkt->pkt.signature->unhashed, + SIGSUBPKT_PRIV_VERIFY_CACHE); } if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY ) { diff --git a/g10/free-packet.c b/g10/free-packet.c index 09e3de15f..de3568825 100644 --- a/g10/free-packet.c +++ b/g10/free-packet.c @@ -59,8 +59,8 @@ free_seckey_enc( PKT_signature *sig ) mpi_free(sig->data[0]); for(i=0; i < n; i++ ) mpi_free( sig->data[i] ); - m_free(sig->hashed_data); - m_free(sig->unhashed_data); + m_free(sig->hashed); + m_free(sig->unhashed); m_free(sig); } @@ -92,17 +92,17 @@ free_public_key( PKT_public_key *pk ) } -static void * -cp_data_block( byte *s ) +static subpktarea_t * +cp_subpktarea (subpktarea_t *s ) { - byte *d; - u16 len; + subpktarea_t *d; if( !s ) return NULL; - len = (s[0] << 8) | s[1]; - d = m_alloc( len+2 ); - memcpy(d, s, len+2); + d = m_alloc (sizeof (*d) + s->size - 1 ); + d->size = s->size; + d->len = s->len; + memcpy (d->data, s->data, s->len); return d; } @@ -177,8 +177,8 @@ copy_signature( PKT_signature *d, PKT_signature *s ) for(i=0; i < n; i++ ) d->data[i] = mpi_copy( s->data[i] ); } - d->hashed_data = cp_data_block(s->hashed_data); - d->unhashed_data = cp_data_block(s->unhashed_data); + d->hashed = cp_subpktarea (s->hashed); + d->unhashed = cp_subpktarea (s->unhashed); return d; } diff --git a/g10/getkey.c b/g10/getkey.c index bb16f91bc..598b33b26 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1380,7 +1380,7 @@ merge_keys_and_selfsig( KBNODE keyblock ) const byte *p; u32 ed; - p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL ); + p = parse_sig_subpkt( sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL ); if( pk ) { ed = p? pk->timestamp + buffer_to_u32(p):0; if( sig->timestamp > sigdate ) { @@ -1418,7 +1418,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) /* store the key flags in the helper variable for later processing */ uid->help_key_usage = 0; - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_KEY_FLAGS, &n ); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); if ( p && n ) { /* first octet of the keyflags */ if ( (*p & 3) ) @@ -1429,7 +1429,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) /* ditto or the key expiration */ uid->help_key_expire = 0; - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); if ( p ) { uid->help_key_expire = keycreated + buffer_to_u32(p); } @@ -1437,7 +1437,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated ) /* Set the primary user ID flag - we will later wipe out some * of them to only have one in out keyblock */ uid->is_primary = 0; - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_PRIMARY_UID, NULL ); + p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL ); if ( p && *p ) uid->is_primary = 1; /* We could also query this from the unhashed area if it is not in @@ -1505,7 +1505,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) else if ( IS_KEY_SIG (sig) && sig->timestamp >= sigdate ) { const byte *p; - p = parse_sig_subpkt( sig->hashed_data, + p = parse_sig_subpkt( sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL ); if ( p && (sig->timestamp + buffer_to_u32(p)) >= curtime ) ; /* signature has expired - ignore it */ @@ -1526,7 +1526,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) const byte *p; size_t n; - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_KEY_FLAGS, &n ); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); if ( p && n ) { /* first octet of the keyflags */ if ( (*p & 3) ) @@ -1536,8 +1536,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) } if ( pk->version > 3 ) { - p = parse_sig_subpkt ( sig->hashed_data, - SIGSUBPKT_KEY_EXPIRE, NULL); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); if ( p ) { key_expire = keytimestamp + buffer_to_u32(p); key_expire_seen = 1; @@ -1580,7 +1579,7 @@ merge_selfsigs_main( KBNODE keyblock, int *r_revoked ) */ const byte *p; - p = parse_sig_subpkt( sig->hashed_data, + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL ); if ( p && (sig->timestamp + buffer_to_u32(p)) >= curtime ) ; /* signature/revocation has expired - ignore it */ @@ -1733,7 +1732,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) * time */ } else if ( IS_SUBKEY_SIG (sig) && sig->timestamp >= sigdate ) { - p = parse_sig_subpkt( sig->hashed_data, + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_EXPIRE, NULL ); if ( p && (sig->timestamp + buffer_to_u32(p)) >= curtime ) ; /* signature has expired - ignore it */ @@ -1753,7 +1752,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) subpk->is_valid = 1; sig = signode->pkt->pkt.signature; - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_KEY_FLAGS, &n ); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_FLAGS, &n ); if ( p && n ) { /* first octet of the keyflags */ if ( (*p & 3) ) @@ -1771,7 +1770,7 @@ merge_selfsigs_subkey( KBNODE keyblock, KBNODE subnode ) } subpk->pubkey_usage = key_usage; - p = parse_sig_subpkt ( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL); if ( p ) key_expire = keytimestamp + buffer_to_u32(p); diff --git a/g10/import.c b/g10/import.c index 4fd82ff7c..c3a35aa8a 100644 --- a/g10/import.c +++ b/g10/import.c @@ -359,7 +359,7 @@ remove_bad_stuff (KBNODE keyblock) for (node=keyblock; node; node = node->next ) { if( node->pkt->pkttype == PKT_SIGNATURE ) { /* delete the subpackets we use for the verification cache */ - delete_sig_subpkt (node->pkt->pkt.signature->unhashed_data, + delete_sig_subpkt (node->pkt->pkt.signature->unhashed, SIGSUBPKT_PRIV_VERIFY_CACHE); } } diff --git a/g10/keyedit.c b/g10/keyedit.c index 4f8aa0871..b388f7f5a 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1653,8 +1653,8 @@ change_primary_uid_cb ( PKT_signature *sig, void *opaque ) /* first clear all primary uid flags so that we are sure none are * lingering around */ - delete_sig_subpkt (sig->hashed_data, SIGSUBPKT_PRIMARY_UID); - delete_sig_subpkt (sig->unhashed_data, SIGSUBPKT_PRIMARY_UID); + delete_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID); + delete_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID); /* if opaque is set,we want to set the primary id */ if (opaque) { @@ -1725,10 +1725,10 @@ menu_set_primary_uid ( KBNODE pub_keyblock, KBNODE sec_keyblock ) int action; /* see whether this signature has the primary UID flag */ - p = parse_sig_subpkt (sig->hashed_data, + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL ); if ( !p ) - p = parse_sig_subpkt (sig->unhashed_data, + p = parse_sig_subpkt (sig->unhashed, SIGSUBPKT_PRIMARY_UID, NULL ); if ( p && *p ) /* yes */ action = selected? 0 : -1; diff --git a/g10/mainproc.c b/g10/mainproc.c index 4609d56f0..af50f6a58 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -715,8 +715,7 @@ print_notation_data( PKT_signature *sig ) const byte *p; int seq = 0; - while( (p = enum_sig_subpkt( sig->hashed_data, SIGSUBPKT_NOTATION, - &n, &seq )) ) { + while( (p = enum_sig_subpkt (sig->hashed, SIGSUBPKT_NOTATION, &n, &seq))) { if( n < 8 ) { log_info(_("WARNING: invalid notation data found\n")); return; @@ -738,7 +737,7 @@ print_notation_data( PKT_signature *sig ) write_status_buffer ( STATUS_NOTATION_NAME, p , n1, 0 ); write_status_buffer ( STATUS_NOTATION_DATA, p+n1, n2, 20 ); } - if( (p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_POLICY, &n ) )) { + if( (p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_POLICY, &n ) )) { log_info(_("Policy: ") ); print_string( log_stream(), p, n, 0 ); putc( '\n', log_stream() ); diff --git a/g10/packet.h b/g10/packet.h index 3258593d8..737c4a586 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -96,6 +96,12 @@ typedef struct { } PKT_onepass_sig; +typedef struct { + size_t size; /* allocated */ + size_t len; /* used */ + byte data[1]; +} subpktarea_t; + typedef struct { ulong local_id; /* internal use, valid if > 0 */ struct { @@ -110,8 +116,8 @@ typedef struct { byte pubkey_algo; /* algorithm used for public key scheme */ /* (PUBKEY_ALGO_xxx) */ byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */ - byte *hashed_data; /* all subpackets with hashed data (v4 only) */ - byte *unhashed_data; /* ditto for unhashed data */ + subpktarea_t *hashed; /* all subpackets with hashed data (v4 only) */ + subpktarea_t *unhashed; /* ditto for unhashed data */ byte digest_start[2]; /* first 2 bytes of the digest */ MPI data[PUBKEY_MAX_NSIG]; } PKT_signature; @@ -325,14 +331,18 @@ int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ); int skip_some_packets( IOBUF inp, unsigned n ); #endif -const byte *enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, - size_t *ret_n, int *start ); -const byte *parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, - size_t *ret_n ); -const byte *parse_sig_subpkt2( PKT_signature *sig, - sigsubpkttype_t reqtype, size_t *ret_n ); +const byte *enum_sig_subpkt ( const subpktarea_t *subpkts, + sigsubpkttype_t reqtype, + size_t *ret_n, int *start ); +const byte *parse_sig_subpkt ( const subpktarea_t *buffer, + sigsubpkttype_t reqtype, + size_t *ret_n ); +const byte *parse_sig_subpkt2 ( PKT_signature *sig, + sigsubpkttype_t reqtype, + size_t *ret_n ); PACKET *create_gpg_control ( ctrlpkttype_t type, - const byte *data, size_t datalen ); + const byte *data, + size_t datalen ); /*-- build-packet.c --*/ int build_packet( IOBUF inp, PACKET *pkt ); @@ -341,7 +351,7 @@ void hash_public_key( MD_HANDLE md, PKT_public_key *pk ); void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ); void build_sig_subpkt_from_sig( PKT_signature *sig ); -size_t delete_sig_subpkt( byte *buffer, sigsubpkttype_t type ); +int delete_sig_subpkt(subpktarea_t *buffer, sigsubpkttype_t type ); /*-- free-packet.c --*/ void free_symkey_enc( PKT_symkey_enc *enc ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 15487572e..f2f35afc2 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -954,9 +954,10 @@ can_handle_critical( const byte *buffer, size_t n, int type ) const byte * -enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, +enum_sig_subpkt( const subpktarea_t *pktbuf, sigsubpkttype_t reqtype, size_t *ret_n, int *start ) { + const byte *buffer; int buflen; int type; int critical; @@ -965,26 +966,25 @@ enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, int seq = 0; int reqseq = start? *start: 0; - if( !buffer || reqseq == -1 ) { + if( !pktbuf || reqseq == -1 ) { /* return some value different from NULL to indicate that - * there is no crtitical bit we do not understand. The caller + * there is no critical bit we do not understand. The caller * will never use the value. Yes I know, it is an ugly hack */ - return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&buffer : NULL; + return reqtype == SIGSUBPKT_TEST_CRITICAL? (const byte*)&pktbuf : NULL; } - buflen = (*buffer << 8) | buffer[1]; - buffer += 2; + buffer = pktbuf->data; + buflen = pktbuf->len; while( buflen ) { n = *buffer++; buflen--; - if( n == 255 ) { + if( n == 255 ) { /* 4 byte length header */ if( buflen < 4 ) goto too_short; n = (buffer[0] << 24) | (buffer[1] << 16) - | (buffer[2] << 8) | buffer[3]; + | (buffer[2] << 8) | buffer[3]; buffer += 4; buflen -= 4; - } - else if( n >= 192 ) { + else if( n >= 192 ) { /* 2 byte special encoded length header */ if( buflen < 2 ) goto too_short; n = (( n - 192 ) << 8) + *buffer + 192; @@ -1059,19 +1059,21 @@ enum_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, const byte * -parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n ) +parse_sig_subpkt (const subpktarea_t *buffer, sigsubpkttype_t reqtype, + size_t *ret_n) { return enum_sig_subpkt( buffer, reqtype, ret_n, NULL ); } const byte * -parse_sig_subpkt2( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n ) +parse_sig_subpkt2 (PKT_signature *sig, sigsubpkttype_t reqtype, + size_t *ret_n ) { const byte *p; - p = parse_sig_subpkt( sig->hashed_data, reqtype, ret_n ); + p = parse_sig_subpkt (sig->hashed, reqtype, ret_n ); if( !p ) - p = parse_sig_subpkt( sig->unhashed_data, reqtype, ret_n ); + p = parse_sig_subpkt (sig->unhashed, reqtype, ret_n ); return p; } @@ -1119,11 +1121,12 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, goto leave; } if( n ) { - sig->hashed_data = m_alloc( n + 2 ); - sig->hashed_data[0] = n >> 8; - sig->hashed_data[1] = n; - if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) { - log_error("premature eof while reading hashed signature data\n"); + sig->hashed = m_alloc (sizeof (*sig->hashed) + n - 1 ); + sig->hashed->size = n; + sig->hashed->len = n; + if( iobuf_read (inp, sig->hashed->data, n ) != n ) { + log_error ("premature eof while reading " + "hashed signature data\n"); rc = -1; goto leave; } @@ -1136,11 +1139,15 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, goto leave; } if( n ) { - sig->unhashed_data = m_alloc( n + 2 ); - sig->unhashed_data[0] = n >> 8; - sig->unhashed_data[1] = n; - if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) { - log_error("premature eof while reading unhashed signature data\n"); + /* we add 6 extra bytes so that we have space for the signature + * status cache. Well we are wastin this if there is a cache + * packet already, but in the other case it avoids an realloc */ + sig->unhashed = m_alloc (sizeof(*sig->unhashed) + n + 8 - 1 ); + sig->unhashed->size = n + 8; + sig->unhashed->len = n; + if( iobuf_read(inp, sig->unhashed->data, n ) != n ) { + log_error("premature eof while reading " + "unhashed signature data\n"); rc = -1; goto leave; } @@ -1162,14 +1169,14 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, /* set sig->flags.unknown_critical if there is a * critical bit set for packets which we do not understand */ - if( !parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_TEST_CRITICAL, NULL) - || !parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_TEST_CRITICAL, + if( !parse_sig_subpkt (sig->hashed, SIGSUBPKT_TEST_CRITICAL, NULL) + || !parse_sig_subpkt (sig->unhashed, SIGSUBPKT_TEST_CRITICAL, NULL) ) { sig->flags.unknown_critical = 1; } - p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL ); + p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_SIG_CREATED, NULL ); if( !p ) log_error("signature packet without timestamp\n"); else @@ -1193,8 +1200,8 @@ parse_signature( IOBUF inp, int pkttype, unsigned long pktlen, sig->digest_algo, sig->digest_start[0], sig->digest_start[1] ); if( is_v4 ) { - parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_LIST_HASHED, NULL ); - parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL); + parse_sig_subpkt (sig->hashed, SIGSUBPKT_LIST_HASHED, NULL ); + parse_sig_subpkt (sig->unhashed, SIGSUBPKT_LIST_UNHASHED, NULL); } } diff --git a/g10/pkclist.c b/g10/pkclist.c index a80c4c680..45a40fe37 100644 --- a/g10/pkclist.c +++ b/g10/pkclist.c @@ -107,7 +107,7 @@ do_show_revocation_reason( PKT_signature *sig ) int seq = 0; const char *text; - while( (p = enum_sig_subpkt( sig->hashed_data, SIGSUBPKT_REVOC_REASON, + while( (p = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REVOC_REASON, &n, &seq )) ) { if( !n ) continue; /* invalid - just skip it */ diff --git a/g10/sig-check.c b/g10/sig-check.c index fe3f1c020..e517e6478 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -153,9 +153,11 @@ mdc_kludge_check( PKT_signature *sig, MD_HANDLE digest ) size_t n; md_putc( digest, sig->pubkey_algo ); md_putc( digest, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( digest, sig->hashed_data, n+2 ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (digest, (n >> 8) ); + md_putc (digest, n ); + md_write (digest, sig->hashed->data, n); n += 6; } else @@ -357,9 +359,11 @@ do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest, size_t n; md_putc( digest, sig->pubkey_algo ); md_putc( digest, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( digest, sig->hashed_data, n+2 ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (digest, (n >> 8) ); + md_putc (digest, n ); + md_write (digest, sig->hashed->data, n); n += 6; } else @@ -510,7 +514,7 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig, const byte *p; size_t len; - p = parse_sig_subpkt( sig->unhashed_data, + p = parse_sig_subpkt( sig->unhashed, SIGSUBPKT_PRIV_VERIFY_CACHE, &len ); if ( p && len >= 2 && p[0] == 1 ) { /* cache hit */ if( is_selfsig ) { diff --git a/g10/sign.c b/g10/sign.c index e54fdf4b8..f36838b4a 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -536,9 +536,11 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr, md_putc( md, sig->pubkey_algo ); md_putc( md, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( md, sig->hashed_data, n+2 ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (md, (n >> 8) ); + md_putc (md, n ); + md_write (md, sig->hashed->data, n ); n += 6; } else { @@ -740,9 +742,11 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile ) md_putc( md, sig->pubkey_algo ); md_putc( md, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( md, sig->hashed_data, n+2 ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (md, (n >> 8) ); + md_putc (md, n ); + md_write (md, sig->hashed->data, n); n += 6; } else { @@ -882,9 +886,11 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, md_putc( md, sig->pubkey_algo ); md_putc( md, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( md, sig->hashed_data, n+2 ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (md, (n >> 8) ); + md_putc (md, n ); + md_write (md, sig->hashed->data, n ); n += 6; } else { @@ -988,9 +994,11 @@ update_keysig_packet( PKT_signature **ret_sig, md_putc( md, sig->pubkey_algo ); md_putc( md, sig->digest_algo ); - if( sig->hashed_data ) { - n = (sig->hashed_data[0] << 8) | sig->hashed_data[1]; - md_write( md, sig->hashed_data, n+2 ); + if( sig->hashed ) { + n = sig->hashed->len; + md_putc (md, (n >> 8) ); + md_putc (md, n ); + md_write (md, sig->hashed->data, n ); n += 6; } else {