removed unused variables.
[gnutls.git] / lib / opencdk / read-packet.c
blob6abb088529129637473ea5135333dec2e9172bab
1 /* read-packet.c - Read OpenPGP packets
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 * Author: Timo Schulz
6 * This file is part of OpenCDK.
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 3 of
11 * the License, or (at your option) any later version.
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.
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/>
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>
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>
39 /* The version of the MDC packet considering the lastest OpenPGP draft. */
40 #define MDC_PKT_VER 1
42 static int
43 stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread)
45 *r_nread = cdk_stream_read (s, buf, buflen);
46 return *r_nread > 0 ? 0 : _cdk_stream_get_errno (s);
50 /* Try to read 4 octets from the stream. */
51 static u32
52 read_32 (cdk_stream_t s)
54 byte buf[4];
55 size_t nread;
57 assert (s != NULL);
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];
66 /* Try to read 2 octets from a stream. */
67 static u16
68 read_16 (cdk_stream_t s)
70 byte buf[2];
71 size_t nread;
73 assert (s != NULL);
75 stream_read (s, buf, 2, &nread);
76 if (nread != 2)
77 return (u16) - 1;
78 return buf[0] << 8 | buf[1];
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)
86 size_t nread;
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)
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;
99 if (s2k->mode == CDK_S2K_ITERSALTED)
100 s2k->count = cdk_stream_getc (inp);
102 else if (s2k->mode == CDK_S2K_GNU_EXT)
104 /* GNU extensions to the S2K : read DETAILS from gnupg */
105 return 0;
107 else
108 return CDK_Not_Implemented;
110 return 0;
114 static cdk_error_t
115 read_mpi (cdk_stream_t inp, bigint_t * ret_m, int secure)
117 bigint_t m;
118 int err;
119 byte buf[MAX_MPI_BYTES + 2];
120 size_t nread, nbits;
121 cdk_error_t rc;
123 if (!inp || !ret_m)
124 return CDK_Inv_Value;
126 *ret_m = NULL;
127 nbits = read_16 (inp);
128 nread = (nbits + 7) / 8;
130 if (nbits > MAX_MPI_BITS || nbits == 0)
132 _gnutls_write_log ("read_mpi: too large %d bits\n", (int) nbits);
133 return gnutls_assert_val(CDK_MPI_Error); /* Sanity check */
136 rc = stream_read (inp, buf + 2, nread, &nread);
137 if (!rc && nread != ((nbits + 7) / 8))
139 _gnutls_write_log ("read_mpi: too short %d < %d\n", (int) nread,
140 (int) ((nbits + 7) / 8));
141 return gnutls_assert_val(CDK_MPI_Error);
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 gnutls_assert_val(map_gnutls_error (err));
151 *ret_m = m;
152 return rc;
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)
162 int c1, c2;
163 size_t pktlen;
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)
174 c2 = fgetc (inp);
175 if (c2 == EOF)
176 return (size_t) EOF;
177 pktlen = ((c1 - 192) << 8) + c2 + 192;
179 else if (c1 == 255)
181 pktlen = fgetc (inp) << 24;
182 pktlen |= fgetc (inp) << 16;
183 pktlen |= fgetc (inp) << 8;
184 pktlen |= fgetc (inp) << 0;
186 else
187 pktlen = 1 << (c1 & 0x1f);
188 return pktlen;
192 static cdk_error_t
193 read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke)
195 size_t i, nenc;
197 if (!inp || !pke)
198 return CDK_Inv_Value;
200 if (DEBUG_PKT)
201 _gnutls_write_log ("read_pubkey_enc: %d octets\n", (int) pktlen);
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++)
218 cdk_error_t rc = read_mpi (inp, &pke->mpi[i], 0);
219 if (rc)
220 return gnutls_assert_val(rc);
223 return 0;
228 static cdk_error_t
229 read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc)
231 size_t n;
232 cdk_error_t rc;
234 if (!inp || !mdc)
235 return CDK_Inv_Value;
237 if (DEBUG_PKT)
238 _gnutls_write_log ("read_mdc:\n");
240 rc = stream_read (inp, mdc->hash, DIM (mdc->hash), &n);
241 if (rc)
242 return rc;
244 return n != DIM (mdc->hash) ? CDK_Inv_Packet : 0;
248 static cdk_error_t
249 read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c)
251 if (!inp || !c)
252 return CDK_Inv_Value;
254 if (DEBUG_PKT)
255 _gnutls_write_log ("read_compressed: %d octets\n", (int) pktlen);
257 c->algorithm = cdk_stream_getc (inp);
258 if (c->algorithm > 3)
259 return CDK_Inv_Packet;
261 /* don't know the size, so we read until EOF */
262 if (!pktlen)
264 c->len = 0;
265 c->buf = inp;
268 /* FIXME: Support partial bodies. */
269 return 0;
273 static cdk_error_t
274 read_public_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
276 size_t i, ndays, npkey;
278 if (!inp || !pk)
279 return CDK_Inv_Value;
281 if (DEBUG_PKT)
282 _gnutls_write_log ("read_public_key: %d octets\n", (int) pktlen);
284 pk->is_invalid = 1; /* default to detect missing self signatures */
285 pk->is_revoked = 0;
286 pk->has_expired = 0;
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)
294 ndays = read_16 (inp);
295 if (ndays)
296 pk->expiredate = pk->timestamp + ndays * 86400L;
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)
303 gnutls_assert ();
304 _gnutls_write_log ("invalid public key algorithm %d\n",
305 pk->pubkey_algo);
306 return CDK_Inv_Algo;
308 for (i = 0; i < npkey; i++)
310 cdk_error_t rc = read_mpi (inp, &pk->mpi[i], 0);
311 if (rc)
312 return gnutls_assert_val(rc);
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;
322 static cdk_error_t
323 read_public_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk)
325 if (!inp || !pk)
326 return CDK_Inv_Value;
327 return read_public_key (inp, pktlen, pk);
330 static cdk_error_t
331 read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
333 size_t p1, p2, nread;
334 int i, nskey;
335 int rc;
337 if (!inp || !sk || !sk->pk)
338 return CDK_Inv_Value;
340 if (DEBUG_PKT)
341 _gnutls_write_log ("read_secret_key: %d octets\n", (int) pktlen);
343 p1 = cdk_stream_tell (inp);
344 rc = read_public_key (inp, pktlen, sk->pk);
345 if (rc)
346 return rc;
348 sk->s2k_usage = cdk_stream_getc (inp);
349 sk->protect.sha1chk = 0;
350 if (sk->s2k_usage == 254 || sk->s2k_usage == 255)
352 sk->protect.sha1chk = (sk->s2k_usage == 254);
353 sk->protect.algo = _pgp_cipher_to_gnutls (cdk_stream_getc (inp));
354 if (sk->protect.algo == GNUTLS_CIPHER_UNKNOWN)
355 return gnutls_assert_val(CDK_Inv_Algo);
357 sk->protect.s2k = cdk_calloc (1, sizeof *sk->protect.s2k);
358 if (!sk->protect.s2k)
359 return CDK_Out_Of_Core;
360 rc = read_s2k (inp, sk->protect.s2k);
361 if (rc)
362 return rc;
363 /* refer to --export-secret-subkeys in gpg(1) */
364 if (sk->protect.s2k->mode == CDK_S2K_GNU_EXT)
365 sk->protect.ivlen = 0;
366 else
368 sk->protect.ivlen = gnutls_cipher_get_block_size (sk->protect.algo);
369 if (!sk->protect.ivlen)
370 return CDK_Inv_Packet;
371 rc = stream_read (inp, sk->protect.iv, sk->protect.ivlen, &nread);
372 if (rc)
373 return rc;
374 if (nread != sk->protect.ivlen)
375 return CDK_Inv_Packet;
378 else
379 sk->protect.algo = _pgp_cipher_to_gnutls (sk->s2k_usage);
380 if (sk->protect.algo == GNUTLS_CIPHER_UNKNOWN)
381 return gnutls_assert_val(CDK_Inv_Algo);
382 else if (sk->protect.algo == GNUTLS_CIPHER_NULL)
384 sk->csum = 0;
385 nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
386 if (!nskey)
388 gnutls_assert ();
389 return CDK_Inv_Algo;
391 for (i = 0; i < nskey; i++)
393 rc = read_mpi (inp, &sk->mpi[i], 1);
394 if (rc)
395 return gnutls_assert_val(rc);
397 sk->csum = read_16 (inp);
398 sk->is_protected = 0;
400 else if (sk->pk->version < 4)
402 /* The length of each multiprecision integer is stored in plaintext. */
403 nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
404 if (!nskey)
406 gnutls_assert ();
407 return CDK_Inv_Algo;
409 for (i = 0; i < nskey; i++)
411 rc = read_mpi (inp, &sk->mpi[i], 1);
412 if (rc)
413 return gnutls_assert_val(rc);
415 sk->csum = read_16 (inp);
416 sk->is_protected = 1;
418 else
420 /* We need to read the rest of the packet because we do not
421 have any information how long the encrypted mpi's are */
422 p2 = cdk_stream_tell (inp);
423 p2 -= p1;
424 sk->enclen = pktlen - p2;
425 if (sk->enclen < 2)
426 return CDK_Inv_Packet; /* at least 16 bits for the checksum! */
427 sk->encdata = cdk_calloc (1, sk->enclen + 1);
428 if (!sk->encdata)
429 return CDK_Out_Of_Core;
430 if (stream_read (inp, sk->encdata, sk->enclen, &nread))
431 return CDK_Inv_Packet;
432 /* Handle the GNU S2K extensions we know (just gnu-dummy right now): */
433 if (sk->protect.s2k->mode == CDK_S2K_GNU_EXT)
435 unsigned char gnumode;
436 if ((sk->enclen < strlen ("GNU") + 1) ||
437 (0 != memcmp ("GNU", sk->encdata, strlen ("GNU"))))
438 return CDK_Inv_Packet;
439 gnumode = sk->encdata[strlen ("GNU")];
440 /* we only handle gnu-dummy (mode 1).
441 mode 2 should refer to external smart cards.
443 if (gnumode != 1)
444 return CDK_Inv_Packet;
445 /* gnu-dummy should have no more data */
446 if (sk->enclen != strlen ("GNU") + 1)
447 return CDK_Inv_Packet;
449 nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo);
450 if (!nskey)
452 gnutls_assert ();
453 return CDK_Inv_Algo;
455 /* We mark each MPI entry with NULL to indicate a protected key. */
456 for (i = 0; i < nskey; i++)
457 sk->mpi[i] = NULL;
458 sk->is_protected = 1;
461 sk->is_primary = 1;
462 _cdk_copy_pk_to_sk (sk->pk, sk);
463 return 0;
467 static cdk_error_t
468 read_secret_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk)
470 cdk_error_t rc;
472 if (!inp || !sk || !sk->pk)
473 return CDK_Inv_Value;
475 rc = read_secret_key (inp, pktlen, sk);
476 sk->is_primary = 0;
477 return rc;
480 #define ATTRIBUTE "[attribute]"
482 static cdk_error_t
483 read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr, int name_size)
485 const byte *p;
486 byte *buf;
487 size_t len, nread;
488 cdk_error_t rc;
490 if (!inp || !attr || !pktlen)
491 return CDK_Inv_Value;
493 if (DEBUG_PKT)
494 _gnutls_write_log ("read_attribute: %d octets\n", (int) pktlen);
496 _gnutls_str_cpy (attr->name, name_size, ATTRIBUTE);
497 attr->len = MIN(name_size, sizeof(ATTRIBUTE)-1);
499 buf = cdk_calloc (1, pktlen);
500 if (!buf)
501 return CDK_Out_Of_Core;
502 rc = stream_read (inp, buf, pktlen, &nread);
503 if (rc)
505 cdk_free (buf);
506 return CDK_Inv_Packet;
508 p = buf;
509 len = *p++;
510 pktlen--;
511 if (len == 255)
513 len = _cdk_buftou32 (p);
514 p += 4;
515 pktlen -= 4;
517 else if (len >= 192)
519 if (pktlen < 2)
521 cdk_free (buf);
522 return CDK_Inv_Packet;
524 len = ((len - 192) << 8) + *p + 192;
525 p++;
526 pktlen--;
529 if (*p != 1) /* Currently only 1, meaning an image, is defined. */
531 cdk_free (buf);
532 return CDK_Inv_Packet;
534 p++;
535 len--;
537 if (len >= pktlen)
538 return CDK_Inv_Packet;
539 attr->attrib_img = cdk_calloc (1, len);
540 if (!attr->attrib_img)
542 cdk_free (buf);
543 return CDK_Out_Of_Core;
545 attr->attrib_len = len;
546 memcpy (attr->attrib_img, p, len);
547 cdk_free (buf);
548 return rc;
552 static cdk_error_t
553 read_user_id (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id)
555 size_t nread;
556 cdk_error_t rc;
558 if (!inp || !user_id)
559 return CDK_Inv_Value;
560 if (!pktlen)
561 return CDK_Inv_Packet;
563 if (DEBUG_PKT)
564 _gnutls_write_log ("read_user_id: %lu octets\n", (unsigned long)pktlen);
566 user_id->len = pktlen;
567 rc = stream_read (inp, user_id->name, pktlen, &nread);
568 if (rc)
569 return rc;
570 if (nread != pktlen)
571 return CDK_Inv_Packet;
572 user_id->name[nread] = '\0';
573 return rc;
577 static cdk_error_t
578 read_subpkt (cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes)
580 byte c, c1;
581 size_t size, nread, n;
582 cdk_subpkt_t node;
583 cdk_error_t rc;
585 if (!inp || !r_nbytes)
586 return CDK_Inv_Value;
588 if (DEBUG_PKT)
589 _gnutls_write_log ("read_subpkt:\n");
591 n = 0;
592 *r_nbytes = 0;
593 c = cdk_stream_getc (inp);
594 n++;
595 if (c == 255)
597 size = read_32 (inp);
598 n += 4;
600 else if (c >= 192 && c < 255)
602 c1 = cdk_stream_getc (inp);
603 n++;
604 if (c1 == 0)
605 return 0;
606 size = ((c - 192) << 8) + c1 + 192;
608 else if (c < 192)
609 size = c;
610 else
611 return CDK_Inv_Packet;
613 node = cdk_subpkt_new (size);
614 if (!node)
615 return CDK_Out_Of_Core;
616 node->size = size;
617 node->type = cdk_stream_getc (inp);
618 if (DEBUG_PKT)
619 _gnutls_write_log (" %d octets %d type\n", node->size, node->type);
620 n++;
621 node->size--;
622 rc = stream_read (inp, node->d, node->size, &nread);
623 n += nread;
624 if (rc)
625 return rc;
626 *r_nbytes = n;
627 if (!*r_ctx)
628 *r_ctx = node;
629 else
630 cdk_subpkt_add (*r_ctx, node);
631 return rc;
635 static cdk_error_t
636 read_onepass_sig (cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig)
638 if (!inp || !sig)
639 return CDK_Inv_Value;
641 if (DEBUG_PKT)
642 _gnutls_write_log ("read_onepass_sig: %d octets\n", (int) pktlen);
644 if (pktlen != 13)
645 return CDK_Inv_Packet;
646 sig->version = cdk_stream_getc (inp);
647 if (sig->version != 3)
648 return CDK_Inv_Packet_Ver;
649 sig->sig_class = cdk_stream_getc (inp);
650 sig->digest_algo = _pgp_hash_algo_to_gnutls (cdk_stream_getc (inp));
651 sig->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
652 sig->keyid[0] = read_32 (inp);
653 sig->keyid[1] = read_32 (inp);
654 sig->last = cdk_stream_getc (inp);
655 return 0;
659 static cdk_error_t
660 parse_sig_subpackets (cdk_pkt_signature_t sig)
662 cdk_subpkt_t node;
664 /* Setup the standard packet entries, so we can use V4
665 signatures similar to V3. */
666 for (node = sig->unhashed; node; node = node->next)
668 if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8)
670 sig->keyid[0] = _cdk_buftou32 (node->d);
671 sig->keyid[1] = _cdk_buftou32 (node->d + 4);
673 else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0)
675 /* Sometimes this packet might be placed in the unhashed area */
676 sig->flags.exportable = 0;
679 for (node = sig->hashed; node; node = node->next)
681 if (node->type == CDK_SIGSUBPKT_SIG_CREATED && node->size >= 4)
682 sig->timestamp = _cdk_buftou32 (node->d);
683 else if (node->type == CDK_SIGSUBPKT_SIG_EXPIRE && node->size >= 4)
685 sig->expiredate = _cdk_buftou32 (node->d);
686 if (sig->expiredate > 0 && sig->expiredate < (u32) gnutls_time (NULL))
687 sig->flags.expired = 1;
689 else if (node->type == CDK_SIGSUBPKT_POLICY)
690 sig->flags.policy_url = 1;
691 else if (node->type == CDK_SIGSUBPKT_NOTATION)
692 sig->flags.notation = 1;
693 else if (node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0)
694 sig->flags.revocable = 0;
695 else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0)
696 sig->flags.exportable = 0;
698 if (sig->sig_class == 0x1F)
700 cdk_desig_revoker_t r, rnode;
702 for (node = sig->hashed; node; node = node->next)
704 if (node->type == CDK_SIGSUBPKT_REV_KEY)
706 if (node->size < 22)
707 continue;
708 rnode = cdk_calloc (1, sizeof *rnode);
709 if (!rnode)
710 return CDK_Out_Of_Core;
711 rnode->r_class = node->d[0];
712 rnode->algid = node->d[1];
713 memcpy (rnode->fpr, node->d + 2, KEY_FPR_LEN);
714 if (!sig->revkeys)
715 sig->revkeys = rnode;
716 else
718 for (r = sig->revkeys; r->next; r = r->next)
720 r->next = rnode;
726 return 0;
730 static cdk_error_t
731 read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig)
733 size_t nbytes;
734 size_t i, nsig;
735 ssize_t size;
736 cdk_error_t rc;
738 if (!inp || !sig)
739 return gnutls_assert_val(CDK_Inv_Value);
741 if (DEBUG_PKT)
742 _gnutls_write_log ("read_signature: %d octets\n", (int) pktlen);
744 if (pktlen < 16)
745 return gnutls_assert_val(CDK_Inv_Packet);
746 sig->version = cdk_stream_getc (inp);
747 if (sig->version < 2 || sig->version > 4)
748 return gnutls_assert_val(CDK_Inv_Packet_Ver);
750 sig->flags.exportable = 1;
751 sig->flags.revocable = 1;
753 if (sig->version < 4)
755 if (cdk_stream_getc (inp) != 5)
756 return gnutls_assert_val(CDK_Inv_Packet);
757 sig->sig_class = cdk_stream_getc (inp);
758 sig->timestamp = read_32 (inp);
759 sig->keyid[0] = read_32 (inp);
760 sig->keyid[1] = read_32 (inp);
761 sig->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
762 sig->digest_algo = _pgp_hash_algo_to_gnutls (cdk_stream_getc (inp));
763 sig->digest_start[0] = cdk_stream_getc (inp);
764 sig->digest_start[1] = cdk_stream_getc (inp);
765 nsig = cdk_pk_get_nsig (sig->pubkey_algo);
766 if (!nsig)
767 return gnutls_assert_val(CDK_Inv_Algo);
768 for (i = 0; i < nsig; i++)
770 rc = read_mpi (inp, &sig->mpi[i], 0);
771 if (rc)
772 return gnutls_assert_val(rc);
775 else
777 sig->sig_class = cdk_stream_getc (inp);
778 sig->pubkey_algo = _pgp_pub_algo_to_cdk (cdk_stream_getc (inp));
779 sig->digest_algo = _pgp_hash_algo_to_gnutls (cdk_stream_getc (inp));
780 sig->hashed_size = read_16 (inp);
781 size = sig->hashed_size;
782 sig->hashed = NULL;
783 while (size > 0)
785 rc = read_subpkt (inp, &sig->hashed, &nbytes);
786 if (rc)
787 return gnutls_assert_val(rc);
788 size -= nbytes;
790 sig->unhashed_size = read_16 (inp);
791 size = sig->unhashed_size;
792 sig->unhashed = NULL;
793 while (size > 0)
795 rc = read_subpkt (inp, &sig->unhashed, &nbytes);
796 if (rc)
797 return gnutls_assert_val(rc);
798 size -= nbytes;
801 rc = parse_sig_subpackets (sig);
802 if (rc)
803 return gnutls_assert_val(rc);
805 sig->digest_start[0] = cdk_stream_getc (inp);
806 sig->digest_start[1] = cdk_stream_getc (inp);
807 nsig = cdk_pk_get_nsig (sig->pubkey_algo);
808 if (!nsig)
809 return gnutls_assert_val(CDK_Inv_Algo);
810 for (i = 0; i < nsig; i++)
812 rc = read_mpi (inp, &sig->mpi[i], 0);
813 if (rc)
814 return gnutls_assert_val(rc);
818 return 0;
822 static cdk_error_t
823 read_literal (cdk_stream_t inp, size_t pktlen,
824 cdk_pkt_literal_t * ret_pt, int is_partial)
826 cdk_pkt_literal_t pt = *ret_pt;
827 size_t nread;
828 cdk_error_t rc;
830 if (!inp || !pt)
831 return CDK_Inv_Value;
833 if (DEBUG_PKT)
834 _gnutls_write_log ("read_literal: %d octets\n", (int) pktlen);
836 pt->mode = cdk_stream_getc (inp);
837 if (pt->mode != 0x62 && pt->mode != 0x74 && pt->mode != 0x75)
838 return CDK_Inv_Packet;
839 if (cdk_stream_eof (inp))
840 return CDK_Inv_Packet;
842 pt->namelen = cdk_stream_getc (inp);
843 if (pt->namelen > 0)
845 *ret_pt = pt = cdk_realloc (pt, sizeof *pt + pt->namelen + 2);
846 if (!pt)
847 return CDK_Out_Of_Core;
848 pt->name = (char *) pt + sizeof (*pt);
849 rc = stream_read (inp, pt->name, pt->namelen, &nread);
850 if (rc)
851 return rc;
852 if ((int) nread != pt->namelen)
853 return CDK_Inv_Packet;
854 pt->name[pt->namelen] = '\0';
856 pt->timestamp = read_32 (inp);
857 pktlen = pktlen - 6 - pt->namelen;
858 if (is_partial)
859 _cdk_stream_set_blockmode (inp, pktlen);
860 pt->buf = inp;
861 pt->len = pktlen;
862 return 0;
866 /* Read an old packet CTB and return the length of the body. */
867 static void
868 read_old_length (cdk_stream_t inp, int ctb, size_t * r_len, size_t * r_size)
870 int llen = ctb & 0x03;
872 if (llen == 0)
874 *r_len = cdk_stream_getc (inp);
875 (*r_size)++;
877 else if (llen == 1)
879 *r_len = read_16 (inp);
880 (*r_size) += 2;
882 else if (llen == 2)
884 *r_len = read_32 (inp);
885 (*r_size) += 4;
887 else
889 *r_len = 0;
890 *r_size = 0;
895 /* Read a new CTB and decode the body length. */
896 static void
897 read_new_length (cdk_stream_t inp,
898 size_t * r_len, size_t * r_size, size_t * r_partial)
900 int c, c1;
902 c = cdk_stream_getc (inp);
903 (*r_size)++;
904 if (c < 192)
905 *r_len = c;
906 else if (c >= 192 && c <= 223)
908 c1 = cdk_stream_getc (inp);
909 (*r_size)++;
910 *r_len = ((c - 192) << 8) + c1 + 192;
912 else if (c == 255)
914 *r_len = read_32 (inp);
915 (*r_size) += 4;
917 else
919 *r_len = 1 << (c & 0x1f);
920 *r_partial = 1;
925 /* Skip the current packet body. */
926 static void
927 skip_packet (cdk_stream_t inp, size_t pktlen)
929 byte buf[BUFSIZE];
930 size_t nread, buflen = DIM (buf);
932 while (pktlen > 0)
934 stream_read (inp, buf, pktlen > buflen ? buflen : pktlen, &nread);
935 pktlen -= nread;
938 assert (pktlen == 0);
943 * cdk_pkt_read:
944 * @inp: the input stream
945 * @pkt: allocated packet handle to store the packet
947 * Parse the next packet on the @inp stream and return its contents in @pkt.
949 cdk_error_t
950 cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt)
952 int ctb, is_newctb;
953 int pkttype;
954 size_t pktlen = 0, pktsize = 0, is_partial = 0;
955 cdk_error_t rc;
957 if (!inp || !pkt)
958 return CDK_Inv_Value;
960 ctb = cdk_stream_getc (inp);
961 if (cdk_stream_eof (inp) || ctb == EOF)
962 return CDK_EOF;
963 else if (!ctb)
964 return gnutls_assert_val(CDK_Inv_Packet);
966 pktsize++;
967 if (!(ctb & 0x80))
969 _cdk_log_info ("cdk_pkt_read: no openpgp data found. "
970 "(ctb=%02X; fpos=%02X)\n", (int) ctb,
971 (int) cdk_stream_tell (inp));
972 return gnutls_assert_val(CDK_Inv_Packet);
975 if (ctb & 0x40) /* RFC2440 packet format. */
977 pkttype = ctb & 0x3f;
978 is_newctb = 1;
980 else /* the old RFC1991 packet format. */
982 pkttype = ctb & 0x3f;
983 pkttype >>= 2;
984 is_newctb = 0;
987 if (pkttype > 63)
989 _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype);
990 return gnutls_assert_val(CDK_Inv_Packet);
993 if (is_newctb)
994 read_new_length (inp, &pktlen, &pktsize, &is_partial);
995 else
996 read_old_length (inp, ctb, &pktlen, &pktsize);
998 pkt->pkttype = pkttype;
999 pkt->pktlen = pktlen;
1000 pkt->pktsize = pktsize + pktlen;
1001 pkt->old_ctb = is_newctb ? 0 : 1;
1003 rc = 0;
1004 switch (pkt->pkttype)
1006 case CDK_PKT_ATTRIBUTE:
1007 #define NAME_SIZE (pkt->pktlen + 16 + 1)
1008 pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
1009 + NAME_SIZE);
1010 if (!pkt->pkt.user_id)
1011 return gnutls_assert_val(CDK_Out_Of_Core);
1012 pkt->pkt.user_id->name =
1013 (char *) pkt->pkt.user_id + sizeof (*pkt->pkt.user_id);
1015 rc = read_attribute (inp, pktlen, pkt->pkt.user_id, NAME_SIZE);
1016 pkt->pkttype = CDK_PKT_ATTRIBUTE;
1017 if (rc)
1018 return gnutls_assert_val(rc);
1019 break;
1021 case CDK_PKT_USER_ID:
1022 pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id
1023 + pkt->pktlen + 1);
1024 if (!pkt->pkt.user_id)
1025 return gnutls_assert_val(CDK_Out_Of_Core);
1026 pkt->pkt.user_id->name =
1027 (char *) pkt->pkt.user_id + sizeof (*pkt->pkt.user_id);
1028 rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
1029 if (rc)
1030 return gnutls_assert_val(rc);
1031 break;
1033 case CDK_PKT_PUBLIC_KEY:
1034 pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
1035 if (!pkt->pkt.public_key)
1036 return gnutls_assert_val(CDK_Out_Of_Core);
1037 rc = read_public_key (inp, pktlen, pkt->pkt.public_key);
1038 if (rc)
1039 return gnutls_assert_val(rc);
1040 break;
1042 case CDK_PKT_PUBLIC_SUBKEY:
1043 pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
1044 if (!pkt->pkt.public_key)
1045 return gnutls_assert_val(CDK_Out_Of_Core);
1046 rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key);
1047 if (rc)
1048 return gnutls_assert_val(rc);
1049 break;
1051 case CDK_PKT_SECRET_KEY:
1052 pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
1053 if (!pkt->pkt.secret_key)
1054 return gnutls_assert_val(CDK_Out_Of_Core);
1055 pkt->pkt.secret_key->pk = cdk_calloc (1,
1056 sizeof *pkt->pkt.secret_key->pk);
1057 if (!pkt->pkt.secret_key->pk)
1058 return gnutls_assert_val(CDK_Out_Of_Core);
1059 rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
1060 if (rc)
1061 return gnutls_assert_val(rc);
1062 break;
1064 case CDK_PKT_SECRET_SUBKEY:
1065 pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
1066 if (!pkt->pkt.secret_key)
1067 return gnutls_assert_val(CDK_Out_Of_Core);
1068 pkt->pkt.secret_key->pk = cdk_calloc (1,
1069 sizeof *pkt->pkt.secret_key->pk);
1070 if (!pkt->pkt.secret_key->pk)
1071 return gnutls_assert_val(CDK_Out_Of_Core);
1072 rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
1073 if (rc)
1074 return gnutls_assert_val(rc);
1075 break;
1077 case CDK_PKT_LITERAL:
1078 pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal);
1079 if (!pkt->pkt.literal)
1080 return gnutls_assert_val(CDK_Out_Of_Core);
1081 rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial);
1082 if (rc)
1083 return gnutls_assert_val(rc);
1084 break;
1086 case CDK_PKT_ONEPASS_SIG:
1087 pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
1088 if (!pkt->pkt.onepass_sig)
1089 return gnutls_assert_val(CDK_Out_Of_Core);
1090 rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
1091 if (rc)
1092 return gnutls_assert_val(rc);
1093 break;
1095 case CDK_PKT_SIGNATURE:
1096 pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
1097 if (!pkt->pkt.signature)
1098 return gnutls_assert_val(CDK_Out_Of_Core);
1099 rc = read_signature (inp, pktlen, pkt->pkt.signature);
1100 if (rc)
1101 return gnutls_assert_val(rc);
1102 break;
1104 case CDK_PKT_PUBKEY_ENC:
1105 pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
1106 if (!pkt->pkt.pubkey_enc)
1107 return gnutls_assert_val(CDK_Out_Of_Core);
1108 rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
1109 if (rc)
1110 return gnutls_assert_val(rc);
1111 break;
1113 case CDK_PKT_COMPRESSED:
1114 pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
1115 if (!pkt->pkt.compressed)
1116 return gnutls_assert_val(CDK_Out_Of_Core);
1117 rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
1118 if (rc)
1119 return gnutls_assert_val(rc);
1120 break;
1122 case CDK_PKT_MDC:
1123 pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
1124 if (!pkt->pkt.mdc)
1125 return gnutls_assert_val(CDK_Out_Of_Core);
1126 rc = read_mdc (inp, pkt->pkt.mdc);
1127 if (rc)
1128 return gnutls_assert_val(rc);
1129 break;
1131 default:
1132 /* Skip all packets we don't understand */
1133 skip_packet (inp, pktlen);
1134 break;
1137 return rc;