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