Tizen 2.0 Release
[external/libgnutls26.git] / lib / opencdk / read-packet.c
1 /* read-packet.c - Read OpenPGP packets
2  * Copyright (C) 2001, 2002, 2003, 2007, 2008, 2010 Free Software
3  * Foundation, Inc.
4  *
5  * Author: Timo Schulz
6  *
7  * This file is part of OpenCDK.
8  *
9  * The OpenCDK library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1 of
12  * the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA
23  *
24  */
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <string.h>
29 #include <stdio.h>
30 #include <time.h>
31 #include <assert.h>
32
33 #include "opencdk.h"
34 #include "main.h"
35 #include "packet.h"
36 #include "types.h"
37 #include <gnutls_algorithms.h>
38
39 /* The version of the MDC packet considering the lastest OpenPGP draft. */
40 #define MDC_PKT_VER 1
41
42 static int
43 stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread)
44 {
45   *r_nread = cdk_stream_read (s, buf, buflen);
46   return *r_nread > 0 ? 0 : _cdk_stream_get_errno (s);
47 }
48
49
50 /* Try to read 4 octets from the stream. */
51 static u32
52 read_32 (cdk_stream_t s)
53 {
54   byte buf[4];
55   size_t nread;
56
57   assert (s != NULL);
58
59   stream_read (s, buf, 4, &nread);
60   if (nread != 4)
61     return (u32) - 1;
62   return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
63 }
64
65
66 /* Try to read 2 octets from a stream. */
67 static u16
68 read_16 (cdk_stream_t s)
69 {
70   byte buf[2];
71   size_t nread;
72
73   assert (s != NULL);
74
75   stream_read (s, buf, 2, &nread);
76   if (nread != 2)
77     return (u16) - 1;
78   return buf[0] << 8 | buf[1];
79 }
80
81
82 /* read about S2K at http://tools.ietf.org/html/rfc4880#section-3.7.1 */
83 static cdk_error_t
84 read_s2k (cdk_stream_t inp, cdk_s2k_t s2k)
85 {
86   size_t nread;
87
88   s2k->mode = cdk_stream_getc (inp);
89   s2k->hash_algo = cdk_stream_getc (inp);
90   if (s2k->mode == CDK_S2K_SIMPLE)
91     return 0;
92   else if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED)
93     {
94       if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread))
95         return CDK_Inv_Packet;
96       if (nread != DIM (s2k->salt))
97         return CDK_Inv_Packet;
98
99       if (s2k->mode == CDK_S2K_ITERSALTED)
100         s2k->count = cdk_stream_getc (inp);
101     }
102   else if (s2k->mode == CDK_S2K_GNU_EXT)
103     {
104       /* GNU extensions to the S2K : read DETAILS from gnupg */
105       return 0;
106     }
107   else
108     return CDK_Not_Implemented;
109
110   return 0;
111 }
112
113
114 static cdk_error_t
115 read_mpi (cdk_stream_t inp, bigint_t * ret_m, int secure)
116 {
117   bigint_t m;
118   int err;
119   byte buf[MAX_MPI_BYTES + 2];
120   size_t nread, nbits;
121   cdk_error_t rc;
122
123   if (!inp || !ret_m)
124     return CDK_Inv_Value;
125
126   *ret_m = NULL;
127   nbits = read_16 (inp);
128   nread = (nbits + 7) / 8;
129
130   if (nbits > MAX_MPI_BITS || nbits == 0)
131     {
132       _gnutls_write_log ("read_mpi: too large %d bits\n", (int) nbits);
133       return CDK_MPI_Error;     /* Sanity check */
134     }
135
136   rc = stream_read (inp, buf + 2, nread, &nread);
137   if (!rc && nread != ((nbits + 7) / 8))
138     {
139       _gnutls_write_log ("read_mpi: too short %d < %d\n", (int) nread,
140                          (int) ((nbits + 7) / 8));
141       return CDK_MPI_Error;
142     }
143
144   buf[0] = nbits >> 8;
145   buf[1] = nbits >> 0;
146   nread += 2;
147   err = _gnutls_mpi_scan_pgp (&m, buf, nread);
148   if (err < 0)
149     return map_gnutls_error (err);
150
151   *ret_m = m;
152   return rc;
153 }
154
155
156 /* Read the encoded packet length directly from the file 
157    object INP and return it. Reset RET_PARTIAL if this is
158    the last packet in block mode. */
159 size_t
160 _cdk_pkt_read_len (FILE * inp, size_t * ret_partial)
161 {
162   int c1, c2;
163   size_t pktlen;
164
165   c1 = fgetc (inp);
166   if (c1 == EOF)
167     return (size_t) EOF;
168   if (c1 < 224 || c1 == 255)
169     *ret_partial = 0;           /* End of partial data */
170   if (c1 < 192)
171     pktlen = c1;
172   else if (c1 >= 192 && c1 <= 223)
173     {
174       c2 = fgetc (inp);
175       if (c2 == EOF)
176         return (size_t) EOF;
177       pktlen = ((c1 - 192) << 8) + c2 + 192;
178     }
179   else if (c1 == 255)
180     {
181       pktlen = fgetc (inp) << 24;
182       pktlen |= fgetc (inp) << 16;
183       pktlen |= fgetc (inp) << 8;
184       pktlen |= fgetc (inp) << 0;
185     }
186   else
187     pktlen = 1 << (c1 & 0x1f);
188   return pktlen;
189 }
190
191
192 static cdk_error_t
193 read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke)
194 {
195   size_t i, nenc;
196
197   if (!inp || !pke)
198     return CDK_Inv_Value;
199
200   if (DEBUG_PKT)
201     _gnutls_write_log ("read_pubkey_enc: %d octets\n", (int) pktlen);
202
203   if (pktlen < 12)
204     return CDK_Inv_Packet;
205   pke->version = cdk_stream_getc (inp);
206   if (pke->version < 2 || pke->version > 3)
207     return CDK_Inv_Packet;
208   pke->keyid[0] = read_32 (inp);
209   pke->keyid[1] = read_32 (inp);
210   if (!pke->keyid[0] && !pke->keyid[1])
211     pke->throw_keyid = 1;       /* RFC2440 "speculative" keyID */
212   pke->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
213   nenc = cdk_pk_get_nenc (pke->pubkey_algo);
214   if (!nenc)
215     return CDK_Inv_Algo;
216   for (i = 0; i < nenc; i++)
217     {
218       cdk_error_t rc = read_mpi (inp, &pke->mpi[i], 0);
219       if (rc)
220         return rc;
221     }
222
223   return 0;
224 }
225
226
227
228 static cdk_error_t
229 read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc)
230 {
231   size_t n;
232   cdk_error_t rc;
233
234   if (!inp || !mdc)
235     return CDK_Inv_Value;
236
237   if (DEBUG_PKT)
238     _gnutls_write_log ("read_mdc:\n");
239
240   rc = stream_read (inp, mdc->hash, DIM (mdc->hash), &n);
241   if (rc)
242     return rc;
243
244   return n != DIM (mdc->hash) ? CDK_Inv_Packet : 0;
245 }
246
247
248 static cdk_error_t
249 read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c)
250 {
251   if (!inp || !c)
252     return CDK_Inv_Value;
253
254   if (DEBUG_PKT)
255     _gnutls_write_log ("read_compressed: %d octets\n", (int) pktlen);
256
257   c->algorithm = cdk_stream_getc (inp);
258   if (c->algorithm > 3)
259     return CDK_Inv_Packet;
260
261   /* don't know the size, so we read until EOF */
262   if (!pktlen)
263     {
264       c->len = 0;
265       c->buf = inp;
266     }
267
268   /* FIXME: Support partial bodies. */
269   return 0;
270 }
271
272
273 static cdk_error_t
274 read_public_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
275 {
276   size_t i, ndays, npkey;
277
278   if (!inp || !pk)
279     return CDK_Inv_Value;
280
281   if (DEBUG_PKT)
282     _gnutls_write_log ("read_public_key: %d octets\n", (int) pktlen);
283
284   pk->is_invalid = 1;           /* default to detect missing self signatures */
285   pk->is_revoked = 0;
286   pk->has_expired = 0;
287
288   pk->version = cdk_stream_getc (inp);
289   if (pk->version < 2 || pk->version > 4)
290     return CDK_Inv_Packet_Ver;
291   pk->timestamp = read_32 (inp);
292   if (pk->version < 4)
293     {
294       ndays = read_16 (inp);
295       if (ndays)
296         pk->expiredate = pk->timestamp + ndays * 86400L;
297     }
298
299   pk->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
300   npkey = cdk_pk_get_npkey (pk->pubkey_algo);
301   if (!npkey)
302     {
303       gnutls_assert ();
304       _gnutls_write_log ("invalid public key algorithm %d\n",
305                          pk->pubkey_algo);
306       return CDK_Inv_Algo;
307     }
308   for (i = 0; i < npkey; i++)
309     {
310       cdk_error_t rc = read_mpi (inp, &pk->mpi[i], 0);
311       if (rc)
312         return rc;
313     }
314
315   /* This value is just for the first run and will be
316      replaced with the actual key flags from the self signature. */
317   pk->pubkey_usage = 0;
318   return 0;
319 }
320
321
322 static cdk_error_t
323 read_public_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
324 {
325   if (!inp || !pk)
326     return CDK_Inv_Value;
327   return read_public_key (inp, pktlen, pk);
328 }
329
330 static cdk_error_t
331 read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
332 {
333   size_t p1, p2, nread;
334   int i, nskey;
335   int rc;
336
337   if (!inp || !sk || !sk->pk)
338     return CDK_Inv_Value;
339
340   if (DEBUG_PKT)
341     _gnutls_write_log ("read_secret_key: %d octets\n", (int) pktlen);
342
343   p1 = cdk_stream_tell (inp);
344   rc = read_public_key (inp, pktlen, sk->pk);
345   if (rc)
346     return rc;
347
348   sk->s2k_usage = cdk_stream_getc (inp);
349   sk->protect.sha1chk = 0;
350   if (sk->s2k_usage == 254 || sk->s2k_usage == 255)
351     {
352       sk->protect.sha1chk = (sk->s2k_usage == 254);
353       sk->protect.algo = _pgp_cipher_to_gnutls (cdk_stream_getc (inp));
354       sk->protect.s2k = cdk_calloc (1, sizeof *sk->protect.s2k);
355       if (!sk->protect.s2k)
356         return CDK_Out_Of_Core;
357       rc = read_s2k (inp, sk->protect.s2k);
358       if (rc)
359         return rc;
360       /* refer to --export-secret-subkeys in gpg(1) */
361       if (sk->protect.s2k->mode == CDK_S2K_GNU_EXT)
362         sk->protect.ivlen = 0;
363       else
364         {
365           sk->protect.ivlen = gnutls_cipher_get_block_size (sk->protect.algo);
366           if (!sk->protect.ivlen)
367             return CDK_Inv_Packet;
368           rc = stream_read (inp, sk->protect.iv, sk->protect.ivlen, &nread);
369           if (rc)
370             return rc;
371           if (nread != sk->protect.ivlen)
372             return CDK_Inv_Packet;
373         }
374     }
375   else
376     sk->protect.algo = _pgp_cipher_to_gnutls (sk->s2k_usage);
377   if (sk->protect.algo == GNUTLS_CIPHER_NULL)
378     {
379       sk->csum = 0;
380       nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
381       if (!nskey)
382         {
383           gnutls_assert ();
384           return CDK_Inv_Algo;
385         }
386       for (i = 0; i < nskey; i++)
387         {
388           rc = read_mpi (inp, &sk->mpi[i], 1);
389           if (rc)
390             return rc;
391         }
392       sk->csum = read_16 (inp);
393       sk->is_protected = 0;
394     }
395   else if (sk->pk->version < 4)
396     {
397       /* The length of each multiprecision integer is stored in plaintext. */
398       nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
399       if (!nskey)
400         {
401           gnutls_assert ();
402           return CDK_Inv_Algo;
403         }
404       for (i = 0; i < nskey; i++)
405         {
406           rc = read_mpi (inp, &sk->mpi[i], 1);
407           if (rc)
408             return rc;
409         }
410       sk->csum = read_16 (inp);
411       sk->is_protected = 1;
412     }
413   else
414     {
415       /* We need to read the rest of the packet because we do not
416          have any information how long the encrypted mpi's are */
417       p2 = cdk_stream_tell (inp);
418       p2 -= p1;
419       sk->enclen = pktlen - p2;
420       if (sk->enclen < 2)
421         return CDK_Inv_Packet;  /* at least 16 bits for the checksum! */
422       sk->encdata = cdk_calloc (1, sk->enclen + 1);
423       if (!sk->encdata)
424         return CDK_Out_Of_Core;
425       if (stream_read (inp, sk->encdata, sk->enclen, &nread))
426         return CDK_Inv_Packet;
427       /* Handle the GNU S2K extensions we know (just gnu-dummy right now): */
428       if (sk->protect.s2k->mode == CDK_S2K_GNU_EXT)
429         {
430           unsigned char gnumode;
431           if ((sk->enclen < strlen ("GNU") + 1) ||
432               (0 != memcmp ("GNU", sk->encdata, strlen ("GNU"))))
433             return CDK_Inv_Packet;
434           gnumode = sk->encdata[strlen ("GNU")];
435           /* we only handle gnu-dummy (mode 1).
436              mode 2 should refer to external smart cards.
437            */
438           if (gnumode != 1)
439             return CDK_Inv_Packet;
440           /* gnu-dummy should have no more data */
441           if (sk->enclen != strlen ("GNU") + 1)
442             return CDK_Inv_Packet;
443         }
444       nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
445       if (!nskey)
446         {
447           gnutls_assert ();
448           return CDK_Inv_Algo;
449         }
450       /* We mark each MPI entry with NULL to indicate a protected key. */
451       for (i = 0; i < nskey; i++)
452         sk->mpi[i] = NULL;
453       sk->is_protected = 1;
454     }
455
456   sk->is_primary = 1;
457   _cdk_copy_pk_to_sk (sk->pk, sk);
458   return 0;
459 }
460
461
462 static cdk_error_t
463 read_secret_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
464 {
465   cdk_error_t rc;
466
467   if (!inp || !sk || !sk->pk)
468     return CDK_Inv_Value;
469
470   rc = read_secret_key (inp, pktlen, sk);
471   sk->is_primary = 0;
472   return rc;
473 }
474
475
476 static cdk_error_t
477 read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
478 {
479   const byte *p;
480   byte *buf;
481   size_t len, nread;
482   cdk_error_t rc;
483
484   if (!inp || !attr || !pktlen)
485     return CDK_Inv_Value;
486
487   if (DEBUG_PKT)
488     _gnutls_write_log ("read_attribute: %d octets\n", (int) pktlen);
489
490   strcpy (attr->name, "[attribute]");
491   attr->len = strlen (attr->name);
492   buf = cdk_calloc (1, pktlen);
493   if (!buf)
494     return CDK_Out_Of_Core;
495   rc = stream_read (inp, buf, pktlen, &nread);
496   if (rc)
497     {
498       cdk_free (buf);
499       return CDK_Inv_Packet;
500     }
501   p = buf;
502   len = *p++;
503   pktlen--;
504   if (len == 255)
505     {
506       len = _cdk_buftou32 (p);
507       p += 4;
508       pktlen -= 4;
509     }
510   else if (len >= 192)
511     {
512       if (pktlen < 2)
513         {
514           cdk_free (buf);
515           return CDK_Inv_Packet;
516         }
517       len = ((len - 192) << 8) + *p + 192;
518       p++;
519       pktlen--;
520     }
521
522   if (*p != 1)                  /* Currently only 1, meaning an image, is defined. */
523     {
524       cdk_free (buf);
525       return CDK_Inv_Packet;
526     }
527   p++;
528   len--;
529
530   if (len >= pktlen)
531     return CDK_Inv_Packet;
532   attr->attrib_img = cdk_calloc (1, len);
533   if (!attr->attrib_img)
534     {
535       cdk_free (buf);
536       return CDK_Out_Of_Core;
537     }
538   attr->attrib_len = len;
539   memcpy (attr->attrib_img, p, len);
540   cdk_free (buf);
541   return rc;
542 }
543
544
545 static cdk_error_t
546 read_user_id (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id)
547 {
548   size_t nread;
549   cdk_error_t rc;
550
551   if (!inp || !user_id)
552     return CDK_Inv_Value;
553   if (!pktlen)
554     return CDK_Inv_Packet;
555
556   if (DEBUG_PKT)
557     _gnutls_write_log ("read_user_id: %lu octets\n", pktlen);
558
559   user_id->len = pktlen;
560   rc = stream_read (inp, user_id->name, pktlen, &nread);
561   if (rc)
562     return rc;
563   if (nread != pktlen)
564     return CDK_Inv_Packet;
565   user_id->name[nread] = '\0';
566   return rc;
567 }
568
569
570 static cdk_error_t
571 read_subpkt (cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes)
572 {
573   byte c, c1;
574   size_t size, nread, n;
575   cdk_subpkt_t node;
576   cdk_error_t rc;
577
578   if (!inp || !r_nbytes)
579     return CDK_Inv_Value;
580
581   if (DEBUG_PKT)
582     _gnutls_write_log ("read_subpkt:\n");
583
584   n = 0;
585   *r_nbytes = 0;
586   c = cdk_stream_getc (inp);
587   n++;
588   if (c == 255)
589     {
590       size = read_32 (inp);
591       n += 4;
592     }
593   else if (c >= 192 && c < 255)
594     {
595       c1 = cdk_stream_getc (inp);
596       n++;
597       if (c1 == 0)
598         return 0;
599       size = ((c - 192) << 8) + c1 + 192;
600     }
601   else if (c < 192)
602     size = c;
603   else
604     return CDK_Inv_Packet;
605
606   node = cdk_subpkt_new (size);
607   if (!node)
608     return CDK_Out_Of_Core;
609   node->size = size;
610   node->type = cdk_stream_getc (inp);
611   if (DEBUG_PKT)
612     _gnutls_write_log (" %d octets %d type\n", node->size, node->type);
613   n++;
614   node->size--;
615   rc = stream_read (inp, node->d, node->size, &nread);
616   n += nread;
617   if (rc)
618     return rc;
619   *r_nbytes = n;
620   if (!*r_ctx)
621     *r_ctx = node;
622   else
623     cdk_subpkt_add (*r_ctx, node);
624   return rc;
625 }
626
627
628 static cdk_error_t
629 read_onepass_sig (cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig)
630 {
631   if (!inp || !sig)
632     return CDK_Inv_Value;
633
634   if (DEBUG_PKT)
635     _gnutls_write_log ("read_onepass_sig: %d octets\n", (int) pktlen);
636
637   if (pktlen != 13)
638     return CDK_Inv_Packet;
639   sig->version = cdk_stream_getc (inp);
640   if (sig->version != 3)
641     return CDK_Inv_Packet_Ver;
642   sig->sig_class = cdk_stream_getc (inp);
643   sig->digest_algo = _pgp_hash_algo_to_gnutls (cdk_stream_getc (inp));
644   sig->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
645   sig->keyid[0] = read_32 (inp);
646   sig->keyid[1] = read_32 (inp);
647   sig->last = cdk_stream_getc (inp);
648   return 0;
649 }
650
651
652 static cdk_error_t
653 parse_sig_subpackets (cdk_pkt_signature_t sig)
654 {
655   cdk_subpkt_t node;
656
657   /* Setup the standard packet entries, so we can use V4
658      signatures similar to V3. */
659   for (node = sig->unhashed; node; node = node->next)
660     {
661       if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8)
662         {
663           sig->keyid[0] = _cdk_buftou32 (node->d);
664           sig->keyid[1] = _cdk_buftou32 (node->d + 4);
665         }
666       else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0)
667         {
668           /* Sometimes this packet might be placed in the unhashed area */
669           sig->flags.exportable = 0;
670         }
671     }
672   for (node = sig->hashed; node; node = node->next)
673     {
674       if (node->type == CDK_SIGSUBPKT_SIG_CREATED && node->size >= 4)
675         sig->timestamp = _cdk_buftou32 (node->d);
676       else if (node->type == CDK_SIGSUBPKT_SIG_EXPIRE && node->size >= 4)
677         {
678           sig->expiredate = _cdk_buftou32 (node->d);
679           if (sig->expiredate > 0 && sig->expiredate < (u32) gnutls_time (NULL))
680             sig->flags.expired = 1;
681         }
682       else if (node->type == CDK_SIGSUBPKT_POLICY)
683         sig->flags.policy_url = 1;
684       else if (node->type == CDK_SIGSUBPKT_NOTATION)
685         sig->flags.notation = 1;
686       else if (node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0)
687         sig->flags.revocable = 0;
688       else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0)
689         sig->flags.exportable = 0;
690     }
691   if (sig->sig_class == 0x1F)
692     {
693       cdk_desig_revoker_t r, rnode;
694
695       for (node = sig->hashed; node; node = node->next)
696         {
697           if (node->type == CDK_SIGSUBPKT_REV_KEY)
698             {
699               if (node->size < 22)
700                 continue;
701               rnode = cdk_calloc (1, sizeof *rnode);
702               if (!rnode)
703                 return CDK_Out_Of_Core;
704               rnode->r_class = node->d[0];
705               rnode->algid = node->d[1];
706               memcpy (rnode->fpr, node->d + 2, KEY_FPR_LEN);
707               if (!sig->revkeys)
708                 sig->revkeys = rnode;
709               else
710                 {
711                   for (r = sig->revkeys; r->next; r = r->next)
712                     ;
713                   r->next = rnode;
714                 }
715             }
716         }
717     }
718
719   return 0;
720 }
721
722
723 static cdk_error_t
724 read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig)
725 {
726   size_t nbytes;
727   size_t i, size, nsig;
728   cdk_error_t rc;
729
730   if (!inp || !sig)
731     return CDK_Inv_Value;
732
733   if (DEBUG_PKT)
734     _gnutls_write_log ("read_signature: %d octets\n", (int) pktlen);
735
736   if (pktlen < 16)
737     return CDK_Inv_Packet;
738   sig->version = cdk_stream_getc (inp);
739   if (sig->version < 2 || sig->version > 4)
740     return CDK_Inv_Packet_Ver;
741
742   sig->flags.exportable = 1;
743   sig->flags.revocable = 1;
744
745   if (sig->version < 4)
746     {
747       if (cdk_stream_getc (inp) != 5)
748         return CDK_Inv_Packet;
749       sig->sig_class = cdk_stream_getc (inp);
750       sig->timestamp = read_32 (inp);
751       sig->keyid[0] = read_32 (inp);
752       sig->keyid[1] = read_32 (inp);
753       sig->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
754       sig->digest_algo = _pgp_hash_algo_to_gnutls (cdk_stream_getc (inp));
755       sig->digest_start[0] = cdk_stream_getc (inp);
756       sig->digest_start[1] = cdk_stream_getc (inp);
757       nsig = cdk_pk_get_nsig (sig->pubkey_algo);
758       if (!nsig)
759         return CDK_Inv_Algo;
760       for (i = 0; i < nsig; i++)
761         {
762           rc = read_mpi (inp, &sig->mpi[i], 0);
763           if (rc)
764             return rc;
765         }
766     }
767   else
768     {
769       sig->sig_class = cdk_stream_getc (inp);
770       sig->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
771       sig->digest_algo = _pgp_hash_algo_to_gnutls (cdk_stream_getc (inp));
772       sig->hashed_size = read_16 (inp);
773       size = sig->hashed_size;
774       sig->hashed = NULL;
775       while (size > 0)
776         {
777           rc = read_subpkt (inp, &sig->hashed, &nbytes);
778           if (rc)
779             return rc;
780           size -= nbytes;
781         }
782       sig->unhashed_size = read_16 (inp);
783       size = sig->unhashed_size;
784       sig->unhashed = NULL;
785       while (size > 0)
786         {
787           rc = read_subpkt (inp, &sig->unhashed, &nbytes);
788           if (rc)
789             return rc;
790           size -= nbytes;
791         }
792
793       rc = parse_sig_subpackets (sig);
794       if (rc)
795         return rc;
796
797       sig->digest_start[0] = cdk_stream_getc (inp);
798       sig->digest_start[1] = cdk_stream_getc (inp);
799       nsig = cdk_pk_get_nsig (sig->pubkey_algo);
800       if (!nsig)
801         return CDK_Inv_Algo;
802       for (i = 0; i < nsig; i++)
803         {
804           rc = read_mpi (inp, &sig->mpi[i], 0);
805           if (rc)
806             return rc;
807         }
808     }
809
810   return 0;
811 }
812
813
814 static cdk_error_t
815 read_literal (cdk_stream_t inp, size_t pktlen,
816               cdk_pkt_literal_t * ret_pt, int is_partial)
817 {
818   cdk_pkt_literal_t pt = *ret_pt;
819   size_t nread;
820   cdk_error_t rc;
821
822   if (!inp || !pt)
823     return CDK_Inv_Value;
824
825   if (DEBUG_PKT)
826     _gnutls_write_log ("read_literal: %d octets\n", (int) pktlen);
827
828   pt->mode = cdk_stream_getc (inp);
829   if (pt->mode != 0x62 && pt->mode != 0x74 && pt->mode != 0x75)
830     return CDK_Inv_Packet;
831   if (cdk_stream_eof (inp))
832     return CDK_Inv_Packet;
833
834   pt->namelen = cdk_stream_getc (inp);
835   if (pt->namelen > 0)
836     {
837       *ret_pt = pt = cdk_realloc (pt, sizeof *pt + pt->namelen + 2);
838       if (!pt)
839         return CDK_Out_Of_Core;
840       pt->name = (char *) pt + sizeof (*pt);
841       rc = stream_read (inp, pt->name, pt->namelen, &nread);
842       if (rc)
843         return rc;
844       if ((int) nread != pt->namelen)
845         return CDK_Inv_Packet;
846       pt->name[pt->namelen] = '\0';
847     }
848   pt->timestamp = read_32 (inp);
849   pktlen = pktlen - 6 - pt->namelen;
850   if (is_partial)
851     _cdk_stream_set_blockmode (inp, pktlen);
852   pt->buf = inp;
853   pt->len = pktlen;
854   return 0;
855 }
856
857
858 /* Read an old packet CTB and return the length of the body. */
859 static void
860 read_old_length (cdk_stream_t inp, int ctb, size_t * r_len, size_t * r_size)
861 {
862   int llen = ctb & 0x03;
863
864   if (llen == 0)
865     {
866       *r_len = cdk_stream_getc (inp);
867       (*r_size)++;
868     }
869   else if (llen == 1)
870     {
871       *r_len = read_16 (inp);
872       (*r_size) += 2;
873     }
874   else if (llen == 2)
875     {
876       *r_len = read_32 (inp);
877       (*r_size) += 4;
878     }
879   else
880     {
881       *r_len = 0;
882       *r_size = 0;
883     }
884 }
885
886
887 /* Read a new CTB and decode the body length. */
888 static void
889 read_new_length (cdk_stream_t inp,
890                  size_t * r_len, size_t * r_size, size_t * r_partial)
891 {
892   int c, c1;
893
894   c = cdk_stream_getc (inp);
895   (*r_size)++;
896   if (c < 192)
897     *r_len = c;
898   else if (c >= 192 && c <= 223)
899     {
900       c1 = cdk_stream_getc (inp);
901       (*r_size)++;
902       *r_len = ((c - 192) << 8) + c1 + 192;
903     }
904   else if (c == 255)
905     {
906       *r_len = read_32 (inp);
907       (*r_size) += 4;
908     }
909   else
910     {
911       *r_len = 1 << (c & 0x1f);
912       *r_partial = 1;
913     }
914 }
915
916
917 /* Skip the current packet body. */
918 static void
919 skip_packet (cdk_stream_t inp, size_t pktlen)
920 {
921   byte buf[BUFSIZE];
922   size_t nread, buflen = DIM (buf);
923
924   while (pktlen > 0)
925     {
926       stream_read (inp, buf, pktlen > buflen ? buflen : pktlen, &nread);
927       pktlen -= nread;
928     }
929
930   assert (pktlen == 0);
931 }
932
933
934 /**
935  * cdk_pkt_read:
936  * @inp: the input stream
937  * @pkt: allocated packet handle to store the packet
938  *
939  * Parse the next packet on the @inp stream and return its contents in @pkt.
940  **/
941 cdk_error_t
942 cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
943 {
944   int ctb, is_newctb;
945   int pkttype;
946   size_t pktlen = 0, pktsize = 0, is_partial = 0;
947   cdk_error_t rc;
948
949   if (!inp || !pkt)
950     return CDK_Inv_Value;
951
952   ctb = cdk_stream_getc (inp);
953   if (cdk_stream_eof (inp) || ctb == EOF)
954     return CDK_EOF;
955   else if (!ctb)
956     return CDK_Inv_Packet;
957
958   pktsize++;
959   if (!(ctb & 0x80))
960     {
961       _cdk_log_info ("cdk_pkt_read: no openpgp data found. "
962                      "(ctb=%02X; fpos=%02X)\n", (int) ctb,
963                      (int) cdk_stream_tell (inp));
964       return CDK_Inv_Packet;
965     }
966
967   if (ctb & 0x40)               /* RFC2440 packet format. */
968     {
969       pkttype = ctb & 0x3f;
970       is_newctb = 1;
971     }
972   else                          /* the old RFC1991 packet format. */
973     {
974       pkttype = ctb & 0x3f;
975       pkttype >>= 2;
976       is_newctb = 0;
977     }
978
979   if (pkttype > 63)
980     {
981       _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype);
982       return CDK_Inv_Packet;
983     }
984
985   if (is_newctb)
986     read_new_length (inp, &pktlen, &pktsize, &is_partial);
987   else
988     read_old_length (inp, ctb, &pktlen, &pktsize);
989
990   pkt->pkttype = pkttype;
991   pkt->pktlen = pktlen;
992   pkt->pktsize = pktsize + pktlen;
993   pkt->old_ctb = is_newctb ? 0 : 1;
994
995   rc = 0;
996   switch (pkt->pkttype)
997     {
998     case CDK_PKT_ATTRIBUTE:
999       pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
1000                                      + pkt->pktlen + 16 + 1);
1001       if (!pkt->pkt.user_id)
1002         return CDK_Out_Of_Core;
1003       pkt->pkt.user_id->name =
1004         (char *) pkt->pkt.user_id + sizeof (*pkt->pkt.user_id);
1005
1006       rc = read_attribute (inp, pktlen, pkt->pkt.user_id);
1007       pkt->pkttype = CDK_PKT_ATTRIBUTE;
1008       break;
1009
1010     case CDK_PKT_USER_ID:
1011       pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
1012                                      + pkt->pktlen + 1);
1013       if (!pkt->pkt.user_id)
1014         return CDK_Out_Of_Core;
1015       pkt->pkt.user_id->name =
1016         (char *) pkt->pkt.user_id + sizeof (*pkt->pkt.user_id);
1017       rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
1018       break;
1019
1020     case CDK_PKT_PUBLIC_KEY:
1021       pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
1022       if (!pkt->pkt.public_key)
1023         return CDK_Out_Of_Core;
1024       rc = read_public_key (inp, pktlen, pkt->pkt.public_key);
1025       break;
1026
1027     case CDK_PKT_PUBLIC_SUBKEY:
1028       pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
1029       if (!pkt->pkt.public_key)
1030         return CDK_Out_Of_Core;
1031       rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key);
1032       break;
1033
1034     case CDK_PKT_SECRET_KEY:
1035       pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
1036       if (!pkt->pkt.secret_key)
1037         return CDK_Out_Of_Core;
1038       pkt->pkt.secret_key->pk = cdk_calloc (1,
1039                                             sizeof *pkt->pkt.secret_key->pk);
1040       if (!pkt->pkt.secret_key->pk)
1041         return CDK_Out_Of_Core;
1042       rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
1043       break;
1044
1045     case CDK_PKT_SECRET_SUBKEY:
1046       pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
1047       if (!pkt->pkt.secret_key)
1048         return CDK_Out_Of_Core;
1049       pkt->pkt.secret_key->pk = cdk_calloc (1,
1050                                             sizeof *pkt->pkt.secret_key->pk);
1051       if (!pkt->pkt.secret_key->pk)
1052         return CDK_Out_Of_Core;
1053       rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
1054       break;
1055
1056     case CDK_PKT_LITERAL:
1057       pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
1058       if (!pkt->pkt.literal)
1059         return CDK_Out_Of_Core;
1060       rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial);
1061       break;
1062
1063     case CDK_PKT_ONEPASS_SIG:
1064       pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
1065       if (!pkt->pkt.onepass_sig)
1066         return CDK_Out_Of_Core;
1067       rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
1068       break;
1069
1070     case CDK_PKT_SIGNATURE:
1071       pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
1072       if (!pkt->pkt.signature)
1073         return CDK_Out_Of_Core;
1074       rc = read_signature (inp, pktlen, pkt->pkt.signature);
1075       break;
1076
1077     case CDK_PKT_PUBKEY_ENC:
1078       pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
1079       if (!pkt->pkt.pubkey_enc)
1080         return CDK_Out_Of_Core;
1081       rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
1082       break;
1083
1084     case CDK_PKT_COMPRESSED:
1085       pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
1086       if (!pkt->pkt.compressed)
1087         return CDK_Out_Of_Core;
1088       rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
1089       break;
1090
1091     case CDK_PKT_MDC:
1092       pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
1093       if (!pkt->pkt.mdc)
1094         return CDK_Out_Of_Core;
1095       rc = read_mdc (inp, pkt->pkt.mdc);
1096       break;
1097
1098     default:
1099       /* Skip all packets we don't understand */
1100       skip_packet (inp, pktlen);
1101       break;
1102     }
1103
1104   return rc;
1105 }