See ChangeLog: Mon Mar 13 19:22:46 CET 2000 Werner Koch
[gnupg.git] / g10 / build-packet.c
1 /* build-packet.c - assemble packets and write them
2  *      Copyright (C) 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "packet.h"
28 #include "errors.h"
29 #include "iobuf.h"
30 #include "util.h"
31 #include <gcrypt.h>
32 #include "options.h"
33 #include "main.h"
34
35
36 static int do_comment( IOBUF out, int ctb, PKT_comment *rem );
37 static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
38 static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk );
39 static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk );
40 static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
41 static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc );
42 static u32 calc_plaintext( PKT_plaintext *pt );
43 static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
44 static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
45 static int do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed );
46 static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
47 static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
48 static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
49
50 static int calc_header_length( u32 len, int new_ctb );
51 static int write_16(IOBUF inp, u16 a);
52 static int write_32(IOBUF inp, u32 a);
53 static int write_header( IOBUF out, int ctb, u32 len );
54 static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
55 static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode );
56 static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
57 static int write_version( IOBUF out, int ctb );
58
59 /****************
60  * Build a packet and write it to INP
61  * Returns: 0 := okay
62  *         >0 := error
63  * Note: Caller must free the packet
64  */
65 int
66 build_packet( IOBUF out, PACKET *pkt )
67 {
68     int new_ctb=0, rc=0, ctb;
69
70     if( DBG_PACKET )
71         log_debug("build_packet() type=%d\n", pkt->pkttype );
72     assert( pkt->pkt.generic );
73
74     switch( pkt->pkttype ) {
75       case PKT_OLD_COMMENT: pkt->pkttype = PKT_COMMENT; break;
76       case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
77       case PKT_ENCRYPTED:
78       case PKT_ENCRYPTED_MDC: new_ctb = pkt->pkt.encrypted->new_ctb; break;
79       case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
80       default: break;
81     }
82
83     if( new_ctb || pkt->pkttype > 15 ) /* new format */
84         ctb = 0xc0 | (pkt->pkttype & 0x3f);
85     else
86         ctb = 0x80 | ((pkt->pkttype & 15)<<2);
87     switch( pkt->pkttype ) {
88       case PKT_USER_ID:
89         rc = do_user_id( out, ctb, pkt->pkt.user_id );
90         break;
91       case PKT_COMMENT:
92         rc = do_comment( out, ctb, pkt->pkt.comment );
93         break;
94       case PKT_PUBLIC_SUBKEY:
95       case PKT_PUBLIC_KEY:
96         rc = do_public_key( out, ctb, pkt->pkt.public_key );
97         break;
98       case PKT_SECRET_SUBKEY:
99       case PKT_SECRET_KEY:
100         rc = do_secret_key( out, ctb, pkt->pkt.secret_key );
101         break;
102       case PKT_SYMKEY_ENC:
103         rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc );
104         break;
105       case PKT_PUBKEY_ENC:
106         rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc );
107         break;
108       case PKT_PLAINTEXT:
109         rc = do_plaintext( out, ctb, pkt->pkt.plaintext );
110         break;
111       case PKT_ENCRYPTED:
112         rc = do_encrypted( out, ctb, pkt->pkt.encrypted );
113         break;
114       case PKT_ENCRYPTED_MDC:
115         rc = do_encrypted_mdc( out, ctb, pkt->pkt.encrypted );
116         break;
117       case PKT_COMPRESSED:
118         rc = do_compressed( out, ctb, pkt->pkt.compressed );
119         break;
120       case PKT_SIGNATURE:
121         rc = do_signature( out, ctb, pkt->pkt.signature );
122         break;
123       case PKT_ONEPASS_SIG:
124         rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
125         break;
126       case PKT_RING_TRUST:
127         break; /* ignore it */
128       default:
129         log_bug("invalid packet type in build_packet()\n");
130         break;
131     }
132
133     return rc;
134 }
135
136 /****************
137  * calculate the length of a packet described by PKT
138  */
139 u32
140 calc_packet_length( PACKET *pkt )
141 {
142     u32 n=0;
143     int new_ctb = 0;
144
145     assert( pkt->pkt.generic );
146     switch( pkt->pkttype ) {
147       case PKT_PLAINTEXT:
148         n = calc_plaintext( pkt->pkt.plaintext );
149         new_ctb = pkt->pkt.plaintext->new_ctb;
150         break;
151       case PKT_USER_ID:
152       case PKT_COMMENT:
153       case PKT_PUBLIC_KEY:
154       case PKT_SECRET_KEY:
155       case PKT_SYMKEY_ENC:
156       case PKT_PUBKEY_ENC:
157       case PKT_ENCRYPTED:
158       case PKT_SIGNATURE:
159       case PKT_ONEPASS_SIG:
160       case PKT_RING_TRUST:
161       case PKT_COMPRESSED:
162       default:
163         log_bug("invalid packet type in calc_packet_length()");
164         break;
165     }
166
167     n += calc_header_length(n, new_ctb);
168     return n;
169 }
170
171 static void
172 write_fake_data( IOBUF out, MPI a )
173 {
174     if( a ) {
175         size_t i;
176         void *p;
177
178         p = gcry_mpi_get_opaque( a, &i );
179         iobuf_write( out, p, (i+7)/8 );
180     }
181 }
182
183
184 static int
185 do_comment( IOBUF out, int ctb, PKT_comment *rem )
186 {
187     if( !opt.no_comment ) {
188         write_header(out, ctb, rem->len);
189         if( iobuf_write( out, rem->data, rem->len ) )
190             return GPGERR_WRITE_FILE;
191     }
192     return 0;
193 }
194
195 static int
196 do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
197 {
198     write_header(out, ctb, uid->len);
199     uid->stored_at = iobuf_tell( out ); /* what a hack */
200     if( iobuf_write( out, uid->name, uid->len ) )
201         return GPGERR_WRITE_FILE;
202     return 0;
203 }
204
205 static int
206 do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
207 {
208     int rc = 0;
209     int n, i;
210     IOBUF a = iobuf_temp();
211
212     if( !pk->version )
213         iobuf_put( a, 3 );
214     else
215         iobuf_put( a, pk->version );
216     write_32(a, pk->timestamp );
217     if( pk->version < 4 ) {
218         u16 ndays;
219         if( pk->expiredate )
220             ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
221         else
222             ndays = 0;
223         write_16(a, ndays );
224     }
225     iobuf_put(a, pk->pubkey_algo );
226     n = pubkey_get_npkey( pk->pubkey_algo );
227     if( !n )
228         write_fake_data( a, pk->pkey[0] );
229     for(i=0; i < n; i++ )
230         mpi_write(a, pk->pkey[i] );
231
232     write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 );
233     if( iobuf_write_temp( out, a ) )
234         rc = GPGERR_WRITE_FILE;
235
236     iobuf_close(a);
237     return rc;
238 }
239
240
241 /****************
242  * Make a hash value from the public key certificate
243  */
244 void
245 hash_public_key( GCRY_MD_HD md, PKT_public_key *pk )
246 {
247     PACKET pkt;
248     int rc = 0;
249     int ctb;
250     ulong pktlen;
251     int c;
252     IOBUF a = iobuf_temp();
253   #if 0
254     FILE *fp = fopen("dump.pk", "a");
255     int i=0;
256
257     fprintf(fp, "\nHashing PK (v%d):\n", pk->version);
258   #endif
259
260     /* build the packet */
261     init_packet(&pkt);
262     pkt.pkttype = PKT_PUBLIC_KEY;
263     pkt.pkt.public_key = pk;
264     if( (rc = build_packet( a, &pkt )) )
265         log_fatal("build public_key for hashing failed: %s\n", gpg_errstr(rc));
266
267     if( !(pk->version == 3 && pk->pubkey_algo == 16) ) {
268         /* skip the constructed header but don't do this for our very old
269          * v3 ElG keys */
270         ctb = iobuf_get_noeof(a);
271         pktlen = 0;
272         if( (ctb & 0x40) ) {
273             c = iobuf_get_noeof(a);
274             if( c < 192 )
275                 pktlen = c;
276             else if( c < 224 ) {
277                 pktlen = (c - 192) * 256;
278                 c = iobuf_get_noeof(a);
279                 pktlen += c + 192;
280             }
281             else if( c == 255 ) {
282                 pktlen  = iobuf_get_noeof(a) << 24;
283                 pktlen |= iobuf_get_noeof(a) << 16;
284                 pktlen |= iobuf_get_noeof(a) << 8;
285                 pktlen |= iobuf_get_noeof(a);
286             }
287         }
288         else {
289             int lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
290             for( ; lenbytes; lenbytes-- ) {
291                 pktlen <<= 8;
292                 pktlen |= iobuf_get_noeof(a);
293             }
294         }
295         /* hash a header */
296         gcry_md_putc( md, 0x99 );
297         pktlen &= 0xffff; /* can't handle longer packets */
298         gcry_md_putc( md, pktlen >> 8 );
299         gcry_md_putc( md, pktlen & 0xff );
300     }
301     /* hash the packet body */
302     while( (c=iobuf_get(a)) != -1 ) {
303       #if 0
304         fprintf( fp," %02x", c );
305         if( (++i == 24) ) {
306             putc('\n', fp);
307             i=0;
308         }
309       #endif
310         gcry_md_putc( md, c );
311     }
312   #if 0
313     putc('\n', fp);
314     fclose(fp);
315   #endif
316     iobuf_cancel(a);
317 }
318
319
320 static int
321 do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
322 {
323     int rc = 0;
324     int i, nskey, npkey;
325     IOBUF a = iobuf_temp();
326
327     if( !sk->version )
328         iobuf_put( a, 3 );
329     else
330         iobuf_put( a, sk->version );
331     write_32(a, sk->timestamp );
332     if( sk->version < 4 ) {
333         u16 ndays;
334         if( sk->expiredate )
335             ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
336         else
337             ndays = 0;
338         write_16(a, 0 );
339     }
340     iobuf_put(a, sk->pubkey_algo );
341     nskey = pubkey_get_nskey( sk->pubkey_algo );
342     npkey = pubkey_get_npkey( sk->pubkey_algo );
343     if( !npkey ) {
344         write_fake_data( a, sk->skey[0] );
345         goto leave;
346     }
347     assert( npkey < nskey );
348
349     for(i=0; i < npkey; i++ )
350         mpi_write(a, sk->skey[i] );
351     if( sk->is_protected ) {
352         if( is_RSA(sk->pubkey_algo) && sk->version < 4
353                                     && !sk->protect.s2k.mode ) {
354             iobuf_put(a, sk->protect.algo );
355             iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
356         }
357         else {
358             iobuf_put(a, 0xff );
359             iobuf_put(a, sk->protect.algo );
360             iobuf_put(a, sk->protect.s2k.mode );
361             iobuf_put(a, sk->protect.s2k.hash_algo );
362             if( sk->protect.s2k.mode == 1
363                 || sk->protect.s2k.mode == 3 )
364                 iobuf_write(a, sk->protect.s2k.salt, 8 );
365             if( sk->protect.s2k.mode == 3 )
366                 iobuf_put(a, sk->protect.s2k.count );
367             iobuf_write(a, sk->protect.iv, sk->protect.ivlen );
368         }
369     }
370     else
371         iobuf_put(a, 0 );
372     if( sk->is_protected && sk->version >= 4 ) {
373         byte *p;
374         size_t n;
375         assert( gcry_mpi_get_flag( sk->skey[i], GCRYMPI_FLAG_OPAQUE ) );
376         p = gcry_mpi_get_opaque( sk->skey[i], &n );
377         iobuf_write(a, p, (n+7)/8 );
378     }
379     else {
380         for(   ; i < nskey; i++ )
381             mpi_write_opaque(a, sk->skey[i] );
382         write_16(a, sk->csum );
383     }
384
385   leave:
386     write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 );
387     if( iobuf_write_temp( out, a ) )
388         rc = GPGERR_WRITE_FILE;
389
390     iobuf_close(a);
391     return rc;
392 }
393
394 static int
395 do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
396 {
397     int rc = 0;
398     IOBUF a = iobuf_temp();
399
400     assert( enc->version == 4 );
401     switch( enc->s2k.mode ) {
402       case 0: case 1: case 3: break;
403       default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode );
404     }
405     iobuf_put( a, enc->version );
406     iobuf_put( a, enc->cipher_algo );
407     iobuf_put( a, enc->s2k.mode );
408     iobuf_put( a, enc->s2k.hash_algo );
409     if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) {
410         iobuf_write(a, enc->s2k.salt, 8 );
411         if( enc->s2k.mode == 3 )
412             iobuf_put(a, enc->s2k.count);
413     }
414     if( enc->seskeylen )
415         iobuf_write(a, enc->seskey, enc->seskeylen );
416
417     write_header(out, ctb, iobuf_get_temp_length(a) );
418     if( iobuf_write_temp( out, a ) )
419         rc = GPGERR_WRITE_FILE;
420
421     iobuf_close(a);
422     return rc;
423 }
424
425
426
427
428 static int
429 do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
430 {
431     int rc = 0;
432     int n, i;
433     IOBUF a = iobuf_temp();
434
435     write_version( a, ctb );
436     if( enc->throw_keyid ) {
437         write_32(a, 0 );  /* don't tell Eve who can decrypt the message */
438         write_32(a, 0 );
439     }
440     else {
441         write_32(a, enc->keyid[0] );
442         write_32(a, enc->keyid[1] );
443     }
444     iobuf_put(a,enc->pubkey_algo );
445     n = pubkey_get_nenc( enc->pubkey_algo );
446     if( !n )
447         write_fake_data( a, enc->data[0] );
448     for(i=0; i < n; i++ )
449         mpi_write(a, enc->data[i] );
450
451     write_header(out, ctb, iobuf_get_temp_length(a) );
452     if( iobuf_write_temp( out, a ) )
453         rc = GPGERR_WRITE_FILE;
454
455     iobuf_close(a);
456     return rc;
457 }
458
459
460
461
462 static u32
463 calc_plaintext( PKT_plaintext *pt )
464 {
465     return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0;
466 }
467
468 static int
469 do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
470 {
471     int i, rc = 0;
472     u32 n;
473     byte buf[1000]; /* this buffer has the plaintext! */
474     int nbytes;
475
476     write_header(out, ctb, calc_plaintext( pt ) );
477     iobuf_put(out, pt->mode );
478     iobuf_put(out, pt->namelen );
479     for(i=0; i < pt->namelen; i++ )
480         iobuf_put(out, pt->name[i] );
481     if( write_32(out, pt->timestamp ) )
482         rc = GPGERR_WRITE_FILE;
483
484     n = 0;
485     while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) {
486         if( iobuf_write(out, buf, nbytes) == -1 ) {
487             rc = GPGERR_WRITE_FILE;
488             break;
489         }
490         n += nbytes;
491     }
492     memset(buf,0,1000); /* at least burn the buffer */
493     if( !pt->len )
494         iobuf_set_block_mode(out, 0 ); /* write end marker */
495     else if( n != pt->len )
496         log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n",
497                         (ulong)n, (ulong)pt->len );
498
499     return rc;
500 }
501
502
503
504 static int
505 do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
506 {
507     int rc = 0;
508     u32 n;
509
510     n = ed->len ? (ed->len + 10) : 0;
511     write_header(out, ctb, n );
512
513     /* This is all. The caller has to write the real data */
514
515     return rc;
516 }
517
518 static int
519 do_encrypted_mdc( IOBUF out, int ctb, PKT_encrypted *ed )
520 {
521     int rc = 0;
522     u32 n;
523
524     assert( ed->mdc_method );
525
526     n = ed->len ? (ed->len + 10) : 0;
527     write_header(out, ctb, n );
528     iobuf_put(out, 1 );  /* version */
529     iobuf_put(out, ed->mdc_method );
530
531     /* This is all. The caller has to write the real data */
532
533     return rc;
534 }
535
536 static int
537 do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
538 {
539     int rc = 0;
540
541     /* we must use the old convention and don't use blockmode */
542     write_header2(out, ctb, 0, 0, 0 );
543     iobuf_put(out, cd->algorithm );
544
545     /* This is all. The caller has to write the real data */
546
547     return rc;
548 }
549
550
551
552 /****************
553  * Find a subpacket of type REQTYPE in BUFFER and a return a pointer
554  * to the first byte of that subpacket data.
555  * And return the length of the packet in RET_N and the number of
556  * header bytes in RET_HLEN (length header and type byte).
557  */
558 byte *
559 find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
560              size_t *ret_hlen, size_t *ret_n )
561 {
562     int buflen;
563     sigsubpkttype_t type;
564     byte *bufstart;
565     size_t n;
566
567     if( !buffer )
568         return NULL;
569     buflen = (*buffer << 8) | buffer[1];
570     buffer += 2;
571     for(;;) {
572         if( !buflen )
573             return NULL; /* end of packets; not found */
574         bufstart = buffer;
575         n = *buffer++; buflen--;
576         if( n == 255 ) {
577             if( buflen < 4 )
578                 break;
579             n = (buffer[0] << 24) | (buffer[1] << 16)
580                                   | (buffer[2] << 8) | buffer[3];
581             buffer += 4;
582             buflen -= 4;
583         }
584         else if( n >= 192 ) {
585             if( buflen < 2 )
586                 break;
587             n = (( n - 192 ) << 8) + *buffer + 192;
588             buffer++;
589             buflen--;
590         }
591         if( buflen < n )
592             break;
593         type = *buffer & 0x7f;
594         if( type == reqtype ) {
595             buffer++;
596             n--;
597             if( n > buflen )
598                 break;
599             if( ret_hlen )
600                 *ret_hlen = buffer - bufstart;
601             if( ret_n )
602                 *ret_n = n;
603             return buffer;
604         }
605         buffer += n; buflen -=n;
606     }
607
608     log_error("find_subpkt: buffer shorter than subpacket\n");
609     return NULL;
610 }
611
612
613 /****************
614  * Create or update a signature subpacket for SIG of TYPE.
615  * This functions knows where to put the data (hashed or unhashed).
616  * The function may move data from the unhased part to the hashed one.
617  * Note: All pointers into sig->[un]hashed are not valid after a call
618  * to this function.  The data to but into the subpaket should be
619  * in buffer with a length of buflen.
620  */
621 void
622 build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
623                   const byte *buffer, size_t buflen )
624 {
625
626     byte *data;
627     size_t hlen, dlen, nlen;
628     int found=0;
629     int critical, hashed, realloced;
630     size_t n, n0;
631
632     critical = (type & SIGSUBPKT_FLAG_CRITICAL);
633     type &= ~SIGSUBPKT_FLAG_CRITICAL;
634
635     if( type == SIGSUBPKT_NOTATION )
636         ; /* we allow multiple packets */
637     else if( (data = find_subpkt( sig->hashed_data, type, &hlen, &dlen )) )
638         found = 1;
639     else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen )))
640         found = 2;
641
642     if( found )
643         log_bug("build_sig_packet: update nyi\n");
644     if( (buflen+1) >= 8384 )
645         nlen = 5;
646     else if( (buflen+1) >= 192 )
647         nlen = 2;
648     else
649         nlen = 1;
650
651     switch( type ) {
652       case SIGSUBPKT_SIG_CREATED:
653       case SIGSUBPKT_PRIV_ADD_SIG:
654       case SIGSUBPKT_PREF_SYM:
655       case SIGSUBPKT_PREF_HASH:
656       case SIGSUBPKT_PREF_COMPR:
657       case SIGSUBPKT_KS_FLAGS:
658       case SIGSUBPKT_KEY_EXPIRE:
659       case SIGSUBPKT_NOTATION:
660       case SIGSUBPKT_POLICY:
661                hashed = 1; break;
662       default: hashed = 0; break;
663     }
664
665     if( hashed ) {
666         n0 = sig->hashed_data ? ((*sig->hashed_data << 8)
667                                     | sig->hashed_data[1]) : 0;
668         n = n0 + nlen + 1 + buflen; /* length, type, buffer */
669         realloced = !!sig->hashed_data;
670         data = sig->hashed_data ? gcry_xrealloc( sig->hashed_data, n+2 )
671                                 : gcry_xmalloc( n+2 );
672     }
673     else {
674         n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8)
675                                       | sig->unhashed_data[1]) : 0;
676         n = n0 + nlen + 1 + buflen; /* length, type, buffer */
677         realloced = !!sig->unhashed_data;
678         data = sig->unhashed_data ? gcry_xrealloc( sig->unhashed_data, n+2 )
679                                   : gcry_xmalloc( n+2 );
680     }
681
682     if( critical )
683         type |= SIGSUBPKT_FLAG_CRITICAL;
684
685     data[0] = (n >> 8) & 0xff;
686     data[1] = n & 0xff;
687     if( nlen == 5 ) {
688         data[n0+2] = 255;
689         data[n0+3] = (buflen+1) >> 24;
690         data[n0+4] = (buflen+1) >> 16;
691         data[n0+5] = (buflen+1) >>  8;
692         data[n0+6] = (buflen+1);
693         data[n0+7] = type;
694         memcpy(data+n0+8, buffer, buflen );
695     }
696     else if( nlen == 2 ) {
697         data[n0+2] = (buflen+1-192) / 256 + 192;
698         data[n0+3] = (buflen+1-192) & 256;
699         data[n0+4] = type;
700         memcpy(data+n0+5, buffer, buflen );
701     }
702     else {
703         data[n0+2] = buflen+1;
704         data[n0+3] = type;
705         memcpy(data+n0+4, buffer, buflen );
706     }
707
708     if( hashed ) {
709         if( !realloced )
710             gcry_free(sig->hashed_data);
711         sig->hashed_data = data;
712     }
713     else {
714         if( !realloced )
715             gcry_free(sig->unhashed_data);
716         sig->unhashed_data = data;
717     }
718 }
719
720 /****************
721  * Put all the required stuff from SIG into subpackets of sig.
722  */
723 void
724 build_sig_subpkt_from_sig( PKT_signature *sig )
725 {
726     u32  u;
727     byte buf[8];
728
729     u = sig->keyid[0];
730     buf[0] = (u >> 24) & 0xff;
731     buf[1] = (u >> 16) & 0xff;
732     buf[2] = (u >>  8) & 0xff;
733     buf[3] = u & 0xff;
734     u = sig->keyid[1];
735     buf[4] = (u >> 24) & 0xff;
736     buf[5] = (u >> 16) & 0xff;
737     buf[6] = (u >>  8) & 0xff;
738     buf[7] = u & 0xff;
739     build_sig_subpkt( sig, SIGSUBPKT_ISSUER, buf, 8 );
740
741     u = sig->timestamp;
742     buf[0] = (u >> 24) & 0xff;
743     buf[1] = (u >> 16) & 0xff;
744     buf[2] = (u >>  8) & 0xff;
745     buf[3] = u & 0xff;
746     build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 );
747 }
748
749
750 static int
751 do_signature( IOBUF out, int ctb, PKT_signature *sig )
752 {
753     int rc = 0;
754     int n, i;
755     IOBUF a = iobuf_temp();
756
757     if( !sig->version )
758         iobuf_put( a, 3 );
759     else
760         iobuf_put( a, sig->version );
761     if( sig->version < 4 )
762         iobuf_put(a, 5 ); /* constant */
763     iobuf_put(a, sig->sig_class );
764     if( sig->version < 4 ) {
765         write_32(a, sig->timestamp );
766         write_32(a, sig->keyid[0] );
767         write_32(a, sig->keyid[1] );
768     }
769     iobuf_put(a, sig->pubkey_algo );
770     iobuf_put(a, sig->digest_algo );
771     if( sig->version >= 4 ) {
772         size_t nn;
773         /* timestamp and keyid must have been packed into the
774          * subpackets prior to the call of this function, because
775          * these subpackets are hashed */
776         nn = sig->hashed_data?((sig->hashed_data[0]<<8)
777                                 |sig->hashed_data[1])   :0;
778         write_16(a, nn);
779         if( nn )
780             iobuf_write( a, sig->hashed_data+2, nn );
781         nn = sig->unhashed_data?((sig->unhashed_data[0]<<8)
782                                   |sig->unhashed_data[1])   :0;
783         write_16(a, nn);
784         if( nn )
785             iobuf_write( a, sig->unhashed_data+2, nn );
786     }
787     iobuf_put(a, sig->digest_start[0] );
788     iobuf_put(a, sig->digest_start[1] );
789     n = pubkey_get_nsig( sig->pubkey_algo );
790     if( !n )
791         write_fake_data( a, sig->data[0] );
792     for(i=0; i < n; i++ )
793         mpi_write(a, sig->data[i] );
794
795     if( is_RSA(sig->pubkey_algo) && sig->version < 4 )
796         write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
797     else
798         write_header(out, ctb, iobuf_get_temp_length(a) );
799     if( iobuf_write_temp( out, a ) )
800         rc = GPGERR_WRITE_FILE;
801
802     iobuf_close(a);
803     return rc;
804 }
805
806
807 static int
808 do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
809 {
810     int rc = 0;
811     IOBUF a = iobuf_temp();
812
813     write_version( a, ctb );
814     iobuf_put(a, ops->sig_class );
815     iobuf_put(a, ops->digest_algo );
816     iobuf_put(a, ops->pubkey_algo );
817     write_32(a, ops->keyid[0] );
818     write_32(a, ops->keyid[1] );
819     iobuf_put(a, ops->last );
820
821     write_header(out, ctb, iobuf_get_temp_length(a) );
822     if( iobuf_write_temp( out, a ) )
823         rc = GPGERR_WRITE_FILE;
824
825     iobuf_close(a);
826     return rc;
827 }
828
829
830 static int
831 write_16(IOBUF out, u16 a)
832 {
833     iobuf_put(out, a>>8);
834     if( iobuf_put(out,a) )
835         return -1;
836     return 0;
837 }
838
839 static int
840 write_32(IOBUF out, u32 a)
841 {
842     iobuf_put(out, a>> 24);
843     iobuf_put(out, a>> 16);
844     iobuf_put(out, a>> 8);
845     if( iobuf_put(out, a) )
846         return -1;
847     return 0;
848 }
849
850
851 /****************
852  * calculate the length of a header
853  */
854 static int
855 calc_header_length( u32 len, int new_ctb )
856 {
857     if( !len )
858         return 1; /* only the ctb */
859
860     if( new_ctb ) {
861         if( len < 192 )
862             return 2;
863         if( len < 8384 )
864             return 3;
865         else
866             return 6;
867     }
868     if( len < 256 )
869         return 2;
870     if( len < 65536 )
871         return 3;
872
873     return 5;
874 }
875
876 /****************
877  * Write the CTB and the packet length
878  */
879 static int
880 write_header( IOBUF out, int ctb, u32 len )
881 {
882     return write_header2( out, ctb, len, 0, 1 );
883 }
884
885
886 static int
887 write_sign_packet_header( IOBUF out, int ctb, u32 len )
888 {
889     /* work around a bug in the pgp read function for signature packets,
890      * which are not correctly coded and silently assume at some
891      * point 2 byte length headers.*/
892     iobuf_put(out, 0x89 );
893     iobuf_put(out, len >> 8 );
894     return iobuf_put(out, len ) == -1 ? -1:0;
895 }
896
897 /****************
898  * if HDRLEN is > 0, try to build a header of this length.
899  * we need this, so that we can hash packets without reading them again.
900  */
901 static int
902 write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode )
903 {
904     if( ctb & 0x40 )
905         return write_new_header( out, ctb, len, hdrlen );
906
907     if( hdrlen ) {
908         if( !len )
909             ctb |= 3;
910         else if( hdrlen == 2 && len < 256 )
911             ;
912         else if( hdrlen == 3 && len < 65536 )
913             ctb |= 1;
914         else
915             ctb |= 2;
916     }
917     else {
918         if( !len )
919             ctb |= 3;
920         else if( len < 256 )
921             ;
922         else if( len < 65536 )
923             ctb |= 1;
924         else
925             ctb |= 2;
926     }
927     if( iobuf_put(out, ctb ) )
928         return -1;
929     if( !len ) {
930         if( blkmode )
931             iobuf_set_block_mode(out, 8196 );
932     }
933     else {
934         if( ctb & 2 ) {
935             iobuf_put(out, len >> 24 );
936             iobuf_put(out, len >> 16 );
937         }
938         if( ctb & 3 )
939             iobuf_put(out, len >> 8 );
940         if( iobuf_put(out, len ) )
941             return -1;
942     }
943     return 0;
944 }
945
946
947 static int
948 write_new_header( IOBUF out, int ctb, u32 len, int hdrlen )
949 {
950     if( hdrlen )
951         log_bug("can't cope with hdrlen yet\n");
952
953     if( iobuf_put(out, ctb ) )
954         return -1;
955     if( !len ) {
956         iobuf_set_partial_block_mode(out, 512 );
957     }
958     else {
959         if( len < 192 ) {
960             if( iobuf_put(out, len ) )
961                 return -1;
962         }
963         else if( len < 8384 ) {
964             len -= 192;
965             if( iobuf_put( out, (len / 256) + 192) )
966                 return -1;
967             if( iobuf_put( out, (len % 256) )  )
968                 return -1;
969         }
970         else {
971             if( iobuf_put( out, 0xff ) )
972                 return -1;
973             if( iobuf_put( out, (len >> 24)&0xff ) )
974                 return -1;
975             if( iobuf_put( out, (len >> 16)&0xff ) )
976                 return -1;
977             if( iobuf_put( out, (len >> 8)&0xff )  )
978                 return -1;
979             if( iobuf_put( out, len & 0xff ) )
980                 return -1;
981         }
982     }
983     return 0;
984 }
985
986 static int
987 write_version( IOBUF out, int ctb )
988 {
989     if( iobuf_put( out, 3 ) )
990         return -1;
991     return 0;
992 }
993