*** empty log message ***
[gnutls.git] / libextra / opencdk / read-packet.c
blob9bdc0258552acd9c2cfaa7bc917eb307112cf6c0
1 /* read-packet.c - Read OpenPGP packets
2 * Copyright (C) 2001, 2002, 2003 Timo Schulz
4 * This file is part of OpenCDK.
6 * OpenCDK is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * OpenCDK is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with OpenCDK; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24 #include <string.h>
25 #include <stdio.h>
26 #include <assert.h>
28 #include "opencdk.h"
29 #include "main.h"
30 #include "packet.h"
31 #include "cipher.h"
34 static int
35 stream_getc( cdk_stream_t s )
37 return cdk_stream_getc( s );
42 static int
43 stream_read (cdk_stream_t s, void * buf, size_t count, size_t * r_nread)
45 int nread = cdk_stream_read (s, buf, count);
46 if( !nread )
47 return CDK_File_Error;
48 if( r_nread )
49 *r_nread = nread;
50 return 0;
54 static u32
55 read_32 (cdk_stream_t buf)
57 u32 u = 0;
58 int c;
60 if( !buf )
61 return (u32) -1;
63 if( (c = stream_getc( buf )) == EOF )
64 return (u32)-1;
65 u |= c << 24;
66 if( (c = stream_getc( buf )) == EOF )
67 return (u32)-1;
68 u |= c << 16;
69 if( (c = stream_getc( buf )) == EOF )
70 return (u32)-1;
71 u |= c << 8;
72 if( (c = stream_getc( buf )) == EOF )
73 return (u32)-1;
74 u |= c;
75 return u;
79 static u16
80 read_16 (cdk_stream_t buf)
82 u16 u = 0;
83 int c;
85 if( !buf )
86 return (u16)-1;
88 if( (c = stream_getc( buf )) == EOF )
89 return (u16)-1;
90 u |= c << 8;
91 if( (c = stream_getc( buf )) == EOF )
92 return (u16)-1;
93 u |= c;
94 return u;
98 #define check_s2k_mode( mode ) ( \
99 (mode) == CDK_S2K_SIMPLE \
100 || (mode) == CDK_S2K_SALTED \
101 || (mode) == CDK_S2K_ITERSALTED \
104 static int
105 read_s2k( cdk_stream_t inp, cdk_s2k_t s2k )
107 size_t nread = 0;
108 int rc = 0;
110 if( !inp || !s2k )
111 return CDK_Inv_Value;
113 if( DEBUG_PKT )
114 _cdk_log_debug( "** read S2K part\n" );
116 s2k->mode = stream_getc( inp );
117 if( s2k->mode == EOF || !check_s2k_mode( s2k->mode ) )
118 return CDK_Inv_Packet;
119 s2k->hash_algo = stream_getc( inp );
120 if( s2k->mode == CDK_S2K_SIMPLE ) {
121 memset( s2k->salt, 0, sizeof s2k->salt );
122 /* nothing else to do */
124 else if( s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED ) {
125 rc = stream_read( inp, s2k->salt, sizeof s2k->salt, &nread );
126 if( !rc && nread != sizeof s2k->salt )
127 return CDK_Inv_Packet;
128 if( !rc && s2k->mode == CDK_S2K_ITERSALTED ) {
129 s2k->count = stream_getc( inp );
130 if( s2k->count == EOF )
131 return CDK_Inv_Packet;
134 else
135 return CDK_Inv_Mode;
136 return rc;
140 static int
141 read_mpi (cdk_stream_t inp, cdk_mpi_t * ret_m, int secure)
143 cdk_mpi_t m = NULL;
144 size_t nread = 0, nbits = 0, nbytes = 0;
145 int rc = 0;
147 if( !inp || !ret_m )
148 return CDK_Inv_Value;
150 if (DEBUG_PKT)
151 _cdk_log_debug ("** read MPI part\n");
153 nbits = read_16 (inp);
154 nbytes = (nbits + 7) / 8;
155 if( nbits > MAX_MPI_BITS || nbits == 0 )
156 return CDK_MPI_Error; /* sanity check */
157 m = secure ? cdk_salloc( sizeof *m + nbytes + 2, 1 ) :
158 cdk_calloc( 1, sizeof *m + nbytes + 2 );
159 if( !m )
160 return CDK_Out_Of_Core;
161 m->bytes = nbytes;
162 m->bits = nbits;
164 /* the prefix encodes the length of the MPI data */
165 m->data[0] = nbits >> 8;
166 m->data[1] = nbits;
167 rc = stream_read( inp, m->data + 2, nbytes, &nread );
168 if( !rc && nread != nbytes )
169 rc = CDK_MPI_Error;
170 *ret_m = m;
171 return rc;
175 size_t
176 _cdk_pkt_read_len( FILE * inp, int * ret_partial )
178 int c1 = 0, c2 = 0;
179 size_t pktlen = 0;
181 if( (c1 = fgetc (inp)) == EOF )
182 return (size_t)EOF;
183 if( c1 < 224 || c1 == 255 )
184 *ret_partial = 0; /* end of partial data */
185 if( c1 < 192 )
186 pktlen = c1;
187 else if( c1 >= 192 && c1 <= 223 ) {
188 if( (c2 = fgetc( inp )) == EOF )
189 return (size_t)EOF;
190 pktlen = ((c1 - 192) << 8) + c2 + 192;
192 else if( c1 == 255 ) {
193 pktlen = fgetc( inp ) << 24;
194 pktlen |= fgetc( inp ) << 16;
195 pktlen |= fgetc( inp ) << 8;
196 pktlen |= fgetc( inp );
197 if( !pktlen )
198 return (size_t)EOF;
200 else
201 pktlen = 1 << (c1 & 0x1f);
202 return pktlen;
206 static int
207 read_encrypted( cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc,
208 int partial, int mdc )
210 int rc = 0, version;
212 if( !inp || !enc )
213 return CDK_Inv_Value;
215 if( DEBUG_PKT )
216 _cdk_log_debug( "** read encrypted packet %d bytes\n", pktlen );
218 if( mdc ) {
219 version = stream_getc( inp );
220 if( version != 1 )
221 return CDK_Inv_Packet;
222 enc->mdc_method = CDK_MD_SHA1;
223 pktlen--;
225 if( pktlen < 10 )
226 return CDK_Inv_Packet; /* we need at least blocksize + 2 bytes */
227 if( partial )
228 _cdk_stream_set_blockmode( inp, pktlen );
229 enc->len = pktlen;
230 enc->buf = inp;
231 return rc;
235 static int
236 read_symkey_enc( cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske )
238 cdk_s2k_t s2k;
239 size_t nread = 0, minlen = 0;
240 int rc = 0;
242 if( !inp || !ske )
243 return CDK_Inv_Value;
245 if( DEBUG_PKT )
246 _cdk_log_debug( "** read symmetric key encrypted packet\n" );
248 ske->version = stream_getc( inp );
249 if( ske->version != 4 )
250 return CDK_Inv_Packet;
252 s2k = ske->s2k = cdk_calloc( 1, sizeof *ske->s2k );
253 if( !ske->s2k )
254 return CDK_Out_Of_Core;
256 ske->cipher_algo = stream_getc( inp );
257 s2k->mode = stream_getc( inp );
258 switch( s2k->mode ) {
259 case 0: minlen = 0; break;
260 case 1: minlen = 8; break;
261 case 3: minlen = 9; break;
263 s2k->hash_algo = stream_getc( inp );
264 if( s2k->mode == 0 )
265 ; /* nothing to do */
266 else if( s2k->mode == 1 || s2k->mode == 3 ) {
267 rc = stream_read( inp, s2k->salt, DIM (s2k->salt), &nread);
268 if( !rc && nread != DIM( s2k->salt ) )
269 return CDK_Inv_Packet;
270 if( !rc && s2k->mode == 3 )
271 s2k->count = stream_getc( inp );
273 else
274 return CDK_Inv_Packet;
275 ske->seskeylen = pktlen - 4 - minlen;
276 if( ske->seskeylen > sizeof ske->seskey )
277 return CDK_Inv_Packet;
278 for( nread = 0; nread < ske->seskeylen; nread++ ) {
279 ske->seskey[nread] = stream_getc( inp );
280 if( cdk_stream_eof( inp ) )
281 break;
283 return rc;
287 static int
288 read_pubkey_enc( cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke )
290 int rc = 0;
291 int i, nenc = 0;
293 if( !inp || !pke )
294 return CDK_Inv_Value;
296 if( DEBUG_PKT )
297 _cdk_log_debug( "** read public key encrypted packet\n" );
299 if( pktlen < 10 )
300 return CDK_Inv_Packet;
301 pke->version = stream_getc( inp );
302 if( pke->version < 2 || pke->version > 3 )
303 return CDK_Inv_Packet;
304 pke->keyid[0] = read_32( inp );
305 pke->keyid[1] = read_32( inp );
306 if( !pke->keyid[0] && !pke->keyid[1] )
307 pke->throw_keyid = 1; /* RFC2440 "speculative" keyID */
308 pke->pubkey_algo = stream_getc( inp );
309 nenc = cdk_pk_get_nenc( pke->pubkey_algo );
310 if( !nenc )
311 return CDK_Inv_Algo;
312 for( i = 0; i < nenc; i++ ) {
313 rc = read_mpi( inp, &pke->mpi[i], 0 );
314 if( rc )
315 break;
317 return rc;
321 static int
322 read_mdc( cdk_stream_t inp, cdk_pkt_mdc_t mdc )
324 size_t n = 0;
325 int rc = 0;
327 if( !inp || !mdc )
328 return CDK_Inv_Value;
330 if (DEBUG_PKT)
331 _cdk_log_debug ("** read MDC packet\n");
333 rc = stream_read( inp, mdc->hash, 20, &n );
334 if( !rc && n != 20 )
335 rc = CDK_Inv_Packet;
336 return rc;
340 static int
341 read_compressed( cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c )
343 if (!inp || !c)
344 return CDK_Inv_Value;
346 if (DEBUG_PKT)
347 _cdk_log_debug ("** read compressed packet\n");
349 c->algorithm = stream_getc( inp );
350 if( c->algorithm > 2 )
351 return CDK_Inv_Packet;
353 /* don't know the size, so we read until EOF */
354 if( !pktlen ) {
355 c->len = 0;
356 c->buf = inp;
359 return 0;
363 static int
364 read_public_key( cdk_stream_t inp, cdk_pkt_pubkey_t pk )
366 int i = 0, ndays, npkey;
367 int rc = 0;
369 if (!inp || !pk)
370 return CDK_Inv_Value;
372 if( DEBUG_PKT )
373 _cdk_log_debug( "** read public key packet\n" );
375 pk->is_invalid = 1; /* default to detect missing self signatures */
376 pk->is_revoked = 0;
377 pk->has_expired = 0;
379 pk->version = stream_getc( inp );
380 if( pk->version < 2 || pk->version > 4 )
381 return CDK_Inv_Packet_Ver;
382 pk->timestamp = read_32( inp );
383 if( pk->version < 4 ) {
384 ndays = read_16( inp );
385 if( ndays )
386 pk->expiredate = pk->timestamp + ndays * 86400L;
388 pk->pubkey_algo = stream_getc( inp );
389 npkey = cdk_pk_get_npkey( pk->pubkey_algo );
390 if( !npkey )
391 return CDK_Inv_Algo;
392 for( i = 0; i < npkey; i++ ) {
393 rc = read_mpi( inp, &pk->mpi[i], 0 );
394 if ( rc )
395 break;
397 pk->pubkey_usage = _cdk_pk_algo_usage( pk->pubkey_algo );
398 return rc;
402 static int
403 read_public_subkey( cdk_stream_t inp, cdk_pkt_pubkey_t pk )
405 if( !inp || !pk )
406 return CDK_Inv_Value;
407 return read_public_key( inp, pk );
411 static int
412 read_secret_key( cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk )
414 size_t p1 = 0, p2 = 0, nread = 0;
415 int i = 0, blklen = 0, nskey = 0;
416 int rc = 0;
418 if( !inp || !sk || !sk->pk )
419 return CDK_Inv_Value;
421 if (DEBUG_PKT)
422 _cdk_log_debug ("** read secret key\n");
424 p1 = cdk_stream_tell( inp );
425 rc = read_public_key( inp, sk->pk );
426 if( rc )
427 return rc;
429 sk->s2k_usage = stream_getc( inp );
430 sk->protect.sha1chk = 0;
431 if( sk->s2k_usage == 254 || sk->s2k_usage == 255 ) {
432 sk->protect.sha1chk = (sk->s2k_usage == 254);
433 sk->protect.algo = stream_getc( inp );
434 sk->protect.s2k = cdk_calloc( 1, sizeof *sk->protect.s2k );
435 if( !sk->protect.s2k )
436 return CDK_Out_Of_Core;
437 rc = read_s2k( inp, sk->protect.s2k );
438 if( rc )
439 return rc;
440 blklen = cdk_cipher_get_algo_blklen( sk->protect.algo );
441 if( !blklen )
442 return CDK_Inv_Packet;
443 sk->protect.ivlen = blklen;
444 rc = stream_read( inp, sk->protect.iv, sk->protect.ivlen, &nread );
445 if( !rc && nread != sk->protect.ivlen )
446 return CDK_Inv_Packet;
448 else
449 sk->protect.algo = sk->s2k_usage;
450 if( sk->protect.algo == CDK_CIPHER_NONE ) {
451 sk->csum = 0;
452 nskey = cdk_pk_get_nskey( sk->pk->pubkey_algo );
453 if( !nskey )
454 return CDK_Inv_Algo;
455 for( i = 0; i < nskey; i++ ) {
456 rc = read_mpi( inp, &sk->mpi[i], 1 );
457 if( rc )
458 break;
460 if( !rc ) {
461 sk->csum = read_16( inp );
462 sk->is_protected = 0;
465 else if( sk->pk->version < 4 ) {
466 /* mpi size isn't encrypted! */
467 nskey = cdk_pk_get_nskey( sk->pk->pubkey_algo );
468 if( !nskey )
469 return CDK_Inv_Algo;
470 for( i = 0; i < nskey; i++ ) {
471 rc = read_mpi( inp, &sk->mpi[i], 1 );
472 if( rc )
473 break;
475 if( !rc ) {
476 sk->csum = read_16( inp );
477 sk->is_protected = 1;
480 else {
481 /* we need to read the rest of the packet because we don't
482 have any information how long the encrypted mpi's are */
483 p2 = cdk_stream_tell( inp );
484 p2 -= p1;
485 sk->enclen = pktlen - p2;
486 if( sk->enclen < 2 )
487 return CDK_Inv_Packet; /* at least 16 bits for the checksum! */
488 sk->encdata = cdk_calloc( 1, sk->enclen + 1 );
489 if( !sk->encdata )
490 return CDK_Out_Of_Core;
491 rc = stream_read( inp, sk->encdata, sk->enclen, &nread );
492 if( rc )
493 return CDK_Inv_Packet;
494 nskey = cdk_pk_get_nskey( sk->pk->pubkey_algo );
495 if( !nskey )
496 return CDK_Inv_Algo;
497 for( i = 0; i < nskey; i++ )
498 sk->mpi[i] = NULL;
499 sk->is_protected = 1;
501 sk->is_primary = 1;
502 _cdk_copy_pk_to_sk( sk->pk, sk );
503 return rc;
507 static int
508 read_secret_subkey( cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk )
510 int rc = 0;
512 if( !inp || !sk || !sk->pk )
513 return CDK_Inv_Value;
515 rc = read_secret_key( inp, pktlen, sk );
516 sk->is_primary = 0;
517 return rc;
521 static int
522 read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr)
524 size_t nread = 0;
525 byte * buf;
526 const byte * p;
527 int len = 0;
528 int rc = 0;
530 if( !inp || !attr || !pktlen )
531 return CDK_Inv_Value;
533 strcpy( attr->name, "[attribute]" );
534 attr->len = strlen( attr->name );
535 buf = cdk_calloc( 1, pktlen );
536 if( !buf )
537 return CDK_Out_Of_Core;
538 rc = stream_read( inp, buf, pktlen, &nread );
539 if( rc ) {
540 cdk_free( buf );
541 return CDK_Inv_Packet;
543 p = buf;
544 len = *p++;
545 if (len == 255) {
546 len = _cdk_buftou32( p );
547 p += 4;
548 pktlen -= 4;
550 else if (len >= 192) {
551 if( pktlen < 2 ) {
552 cdk_free( buf );
553 return CDK_Inv_Packet;
555 len = ((len - 192) << 8) + *p + 192;
556 p++;
557 pktlen--;
559 if( *p != 1 ) { /* ATTRIBUTE IMAGE */
560 cdk_free( buf );
561 return CDK_Inv_Packet;
563 p++;
565 attr->attrib_img = cdk_calloc( 1, len );
566 if( !attr->attrib_img )
567 return CDK_Out_Of_Core;
568 attr->attrib_len = len;
569 memcpy( attr->attrib_img, p, len );
570 cdk_free( buf );
571 return rc;
575 static int
576 read_user_id( cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id )
578 size_t nread = 0;
579 int rc = 0;
581 if( !inp || !user_id )
582 return CDK_Inv_Value;
583 if( !pktlen )
584 return CDK_Inv_Packet;
586 if (DEBUG_PKT)
587 _cdk_log_debug ("** read user ID packet: ");
589 user_id->len = pktlen;
590 rc = stream_read( inp, user_id->name, pktlen, &nread );
591 if( !rc && nread != pktlen )
592 return CDK_Inv_Packet;
593 user_id->name[nread] = '\0';
594 if (DEBUG_PKT)
595 _cdk_log_debug ("%s\n", user_id->name);
596 return rc;
600 static int
601 read_subpkt( cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes )
603 byte c, c1;
604 size_t size = 0, nread, n = 0;
605 cdk_subpkt_t node;
606 int rc = 0;
608 if( !inp || !r_nbytes )
609 return CDK_Inv_Value;
611 if (DEBUG_PKT)
612 _cdk_log_debug ("** read sub packet");
614 *r_nbytes = 0;
615 c = stream_getc( inp );
616 n++;
617 if( c == 255 ) {
618 size = read_32( inp );
619 n += 4;
620 node = cdk_subpkt_new( size );
622 else if( c >= 192 && c < 255 ) {
623 c1 = stream_getc( inp );
624 n++;
625 if( c1 == 0 )
626 return 0;
627 size = ((c - 192) << 8) + c1 + 192;
628 node = cdk_subpkt_new( size );
630 else if( c < 192 ) {
631 size = c;
632 node = cdk_subpkt_new( size );
634 else
635 return CDK_Inv_Packet;
637 if (DEBUG_PKT)
638 _cdk_log_debug (" `%d' bytes\n", size);
640 if( !node )
641 return CDK_Out_Of_Core;
642 node->size = size;
643 node->type = stream_getc( inp );
644 n++;
645 node->size--;
646 rc = stream_read( inp, node->d, node->size, &nread );
647 n += nread;
648 if( rc )
649 return rc;
650 *r_nbytes = n;
651 if( !*r_ctx )
652 *r_ctx = node;
653 else
654 cdk_subpkt_add( *r_ctx, node );
655 return rc;
659 static int
660 read_onepass_sig( cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig )
662 if( !inp || !sig )
663 return CDK_Inv_Value;
665 if (DEBUG_PKT)
666 _cdk_log_debug ("** read one pass signature packet\n");
668 if( pktlen < 13 )
669 return CDK_Inv_Packet;
670 sig->version = stream_getc( inp );
671 if( sig->version != 3 )
672 return CDK_Inv_Packet_Ver;
673 sig->sig_class = stream_getc( inp );
674 sig->digest_algo = stream_getc( inp );
675 sig->pubkey_algo = stream_getc( inp );
676 sig->keyid[0] = read_32( inp );
677 sig->keyid[1] = read_32( inp );
678 sig->last = stream_getc( inp );
679 return 0;
683 static int
684 read_signature( cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig )
686 cdk_subpkt_t node = NULL;
687 size_t nbytes;
688 int i, size, nsig;
689 int rc = 0;
691 if( !inp || !sig )
692 return CDK_Inv_Value;
694 if( DEBUG_PKT )
695 _cdk_log_debug( "** read signature packet\n" );
697 if( pktlen < 10 )
698 return CDK_Inv_Packet;
699 sig->version = stream_getc( inp );
700 if( sig->version < 2 || sig->version > 4 )
701 return CDK_Inv_Packet_Ver;
703 sig->flags.exportable = 1;
704 sig->flags.revocable = 1;
706 if( sig->version < 4 ) {
707 if( stream_getc( inp ) != 5 )
708 return CDK_Inv_Packet;
709 sig->sig_class = stream_getc( inp );
710 sig->timestamp = read_32( inp );
711 sig->keyid[0] = read_32( inp );
712 sig->keyid[1] = read_32( inp );
713 sig->pubkey_algo = stream_getc( inp );
714 sig->digest_algo = stream_getc( inp );
715 sig->digest_start[0] = stream_getc( inp );
716 sig->digest_start[1] = stream_getc( inp );
717 nsig = cdk_pk_get_nsig( sig->pubkey_algo );
718 if( !nsig )
719 return CDK_Inv_Algo;
720 for( i = 0; i < nsig; i++ ) {
721 rc = read_mpi( inp, &sig->mpi[i], 0 );
722 if( rc )
723 break;
726 else {
727 sig->sig_class = stream_getc( inp );
728 sig->pubkey_algo = stream_getc( inp );
729 sig->digest_algo = stream_getc( inp );
730 sig->hashed_size = read_16( inp );
731 size = sig->hashed_size;
732 sig->hashed = NULL;
733 while( size > 0 ) {
734 rc = read_subpkt( inp, &sig->hashed, &nbytes );
735 if( rc )
736 break;
737 size -= nbytes;
739 sig->unhashed_size = read_16( inp );
740 size = sig->unhashed_size;
741 sig->unhashed = NULL;
742 while( size > 0 ) {
743 rc = read_subpkt( inp, &sig->unhashed, &nbytes );
744 if( rc )
745 break;
746 size -= nbytes;
749 /* Setup the standard packet entries, so we can use V4
750 signatures similar to V3. */
751 for( node = sig->unhashed; node; node = node->next ) {
752 if( node->type == CDK_SIGSUBPKT_ISSUER ) {
753 sig->keyid[0] = _cdk_buftou32( node->d );
754 sig->keyid[1] = _cdk_buftou32( node->d + 4 );
756 else if( node->type == CDK_SIGSUBPKT_EXPORTABLE
757 && node->d[0] == 0 ) {
758 /* this packet might be also placed in the unhashed area */
759 sig->flags.exportable = 0;
762 for( node = sig->hashed; node; node = node->next ) {
763 if( node->type == CDK_SIGSUBPKT_SIG_CREATED )
764 sig->timestamp = _cdk_buftou32( node->d );
765 else if( node->type == CDK_SIGSUBPKT_SIG_EXPIRE ) {
766 sig->expiredate = _cdk_buftou32( node->d );
767 if( sig->expiredate > 0
768 && sig->expiredate < _cdk_timestamp() )
769 sig->flags.expired = 1;
771 else if( node->type == CDK_SIGSUBPKT_POLICY )
772 sig->flags.policy_url = 1;
773 else if( node->type == CDK_SIGSUBPKT_NOTATION )
774 sig->flags.notation = 1;
775 else if( node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0 )
776 sig->flags.revocable = 0;
777 else if( node->type == CDK_SIGSUBPKT_EXPORTABLE
778 && node->d[0] == 0 )
779 sig->flags.exportable = 0;
781 if( sig->sig_class == 0x1F ) {
782 cdk_desig_revoker_t r, rnode;
783 for( node = sig->hashed; node; node = node->next ) {
784 if( node->type == CDK_SIGSUBPKT_REV_KEY ) {
785 rnode = cdk_calloc( 1, sizeof * rnode );
786 if( !rnode )
787 return CDK_Out_Of_Core;
788 rnode->class = node->d[0];
789 rnode->algid = node->d[1];
790 memcpy( rnode->fpr, node->d+2, 20 );
791 if( !sig->revkeys )
792 sig->revkeys = rnode;
793 else {
794 for( r = sig->revkeys; r->next; r = r->next )
796 r->next = rnode;
801 sig->digest_start[0] = stream_getc( inp );
802 sig->digest_start[1] = stream_getc( inp );
803 nsig = cdk_pk_get_nsig( sig->pubkey_algo );
804 if( !nsig )
805 return CDK_Inv_Algo;
806 for( i = 0; i < nsig; i++ ) {
807 rc = read_mpi( inp, &sig->mpi[i], 0 );
808 if( rc )
809 break;
812 return rc;
816 static int
817 read_literal( cdk_stream_t inp, size_t pktlen, cdk_pkt_literal_t * ret_pt,
818 int partial )
820 cdk_pkt_literal_t pt = *ret_pt;
821 size_t nread = 0;
822 int rc = 0;
824 if( !inp || !pt )
825 return CDK_Inv_Value;
827 if( DEBUG_PKT )
828 _cdk_log_debug( "** read literal packet\n" );
830 pt->mode = stream_getc( inp );
831 if( pt->mode != 0x62 && pt->mode != 0x74 )
832 return CDK_Inv_Packet;
833 pt->namelen = stream_getc( inp );
834 if( pt->namelen ) {
835 *ret_pt = pt = cdk_realloc( pt, sizeof * pt + pt->namelen + 1 );
836 if( !pt )
837 return CDK_Out_Of_Core;
838 rc = stream_read( inp, pt->name, pt->namelen, &nread );
839 if( !rc && nread != pt->namelen )
840 return CDK_Inv_Packet;
841 pt->name[pt->namelen] = '\0';
843 pt->timestamp = read_32( inp );
844 pktlen = pktlen - 6 - pt->namelen;
845 if( partial )
846 _cdk_stream_set_blockmode( inp, pktlen );
847 pt->buf = inp;
848 pt->len = pktlen;
849 return rc;
853 static void
854 read_old_length( cdk_stream_t inp, int ctb, size_t *r_len, size_t *r_size )
856 int llen = ctb & 0x03;
858 if( llen == 0 ) {
859 *r_len = stream_getc( inp );
860 (*r_size)++;
862 else if( llen == 1 ) {
863 *r_len = read_16( inp );
864 (*r_size) += 2;
866 else if( llen == 2 ) {
867 *r_len = read_32( inp );
868 (*r_size) += 4;
870 else {
871 *r_len = 0;
872 *r_size = 0;
877 static void
878 read_new_length( cdk_stream_t inp,
879 size_t *r_len, size_t *r_size, size_t *r_partial )
881 int c, c1;
883 c = stream_getc( inp );
884 (*r_size)++;
885 if( c < 192 )
886 *r_len = c;
887 else if( c >= 192 && c <= 223 ) {
888 c1 = stream_getc( inp );
889 (*r_size)++;
890 *r_len = ((c - 192) << 8) + c1 + 192;
892 else if( c == 255 ) {
893 *r_len = read_32( inp );
894 (*r_size) += 4;
896 else {
897 *r_len = 1 << (c & 0x1f);
898 *r_partial = 1;
903 /* we use a buffer to make it faster to skip larger unknown packets. */
904 static void
905 skip_packet( cdk_stream_t inp, size_t pktlen )
907 byte buf[4096];
908 size_t nread;
910 while( pktlen > 4095 ) {
911 stream_read( inp, buf, sizeof buf-1, &nread );
912 pktlen -= nread;
914 stream_read( inp, buf, pktlen, &nread );
915 pktlen -= nread;
916 assert( pktlen == 0 );
921 * cdk_pkt_read:
922 * @inp: the input stream
923 * @pkt: allocated packet handle to store the packet
925 * Parse the next packet on the @inp stream and return its contents in @pkt.
927 cdk_error_t
928 cdk_pkt_read( cdk_stream_t inp, cdk_packet_t pkt )
930 int use_mdc = 0;
931 int ctb = 0, is_newctb = 0, is_partial = 0;
932 int rc = 0, pkttype = 0;
933 size_t pktlen = 0, pktsize = 0;
935 if( !inp || !pkt )
936 return CDK_Inv_Value;
938 ctb = stream_getc( inp );
939 if( cdk_stream_eof( inp ) || ctb == EOF )
940 return CDK_EOF;
941 else if( !ctb )
942 return CDK_Inv_Packet;
944 pktsize++;
945 if( !(ctb & 0x80) ) {
946 _cdk_log_info ("no valid openpgp data found. "
947 "(ctb=%02X; fpos=%02X)\n",ctb, cdk_stream_tell( inp ) );
948 return CDK_Inv_Packet;
950 if( ctb & 0x40 ) { /* RFC2440 */
951 pkttype = ctb & 0x3f;
952 is_newctb = 1;
954 else { /* RFC1991 */
955 pkttype = ctb & 0x3f;
956 pkttype >>= 2;
958 if( pkttype > 63 ) {
959 _cdk_log_info ("unknown packet type (%d)\n", pkttype);
960 return CDK_Inv_Packet;
962 if( is_newctb )
963 read_new_length( inp, &pktlen, &pktsize, &is_partial );
964 else
965 read_old_length( inp, ctb, &pktlen, &pktsize );
967 pkt->pkttype = pkttype;
968 pkt->pktlen = pktlen;
969 pkt->pktsize = pktsize + pktlen;
970 pkt->old_ctb = is_newctb? 0 : 1;
972 switch( pkt->pkttype ) {
973 case CDK_PKT_ATTRIBUTE:
974 pkt->pkt.user_id = cdk_calloc (1,
975 sizeof *pkt->pkt.user_id + pkt->pktlen);
976 if (!pkt->pkt.user_id)
977 return CDK_Out_Of_Core;
978 rc = read_attribute (inp, pktlen, pkt->pkt.user_id);
979 pkt->pkttype = CDK_PKT_USER_ID; /* treated as an user id */
980 break;
982 case CDK_PKT_USER_ID:
983 pkt->pkt.user_id = cdk_calloc (1,
984 sizeof *pkt->pkt.user_id + pkt->pktlen);
985 if (!pkt->pkt.user_id)
986 return CDK_Out_Of_Core;
987 rc = read_user_id (inp, pktlen, pkt->pkt.user_id);
988 break;
990 case CDK_PKT_PUBLIC_KEY:
991 pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
992 if (!pkt->pkt.public_key)
993 return CDK_Out_Of_Core;
994 rc = read_public_key (inp, pkt->pkt.public_key);
995 break;
997 case CDK_PKT_PUBLIC_SUBKEY:
998 pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key);
999 if (!pkt->pkt.public_key)
1000 return CDK_Out_Of_Core;
1001 rc = read_public_subkey (inp, pkt->pkt.public_key);
1002 break;
1004 case CDK_PKT_SECRET_KEY:
1005 pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
1006 if (!pkt->pkt.secret_key)
1007 return CDK_Out_Of_Core;
1008 pkt->pkt.secret_key->pk =cdk_calloc (1,
1009 sizeof *pkt->pkt.secret_key->pk);
1010 if (!pkt->pkt.secret_key->pk)
1011 return CDK_Out_Of_Core;
1012 rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key);
1013 break;
1015 case CDK_PKT_SECRET_SUBKEY:
1016 pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key);
1017 if (!pkt->pkt.secret_key)
1018 return CDK_Out_Of_Core;
1019 pkt->pkt.secret_key->pk =
1020 cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk);
1021 if (!pkt->pkt.secret_key->pk)
1022 return CDK_Out_Of_Core;
1023 rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key);
1024 break;
1026 case CDK_PKT_LITERAL:
1027 pkt->pkt.literal = cdk_calloc( 1, sizeof *pkt->pkt.literal );
1028 if (!pkt->pkt.literal)
1029 return CDK_Out_Of_Core;
1030 rc = read_literal( inp, pktlen, &pkt->pkt.literal, is_partial);
1031 break;
1033 case CDK_PKT_ONEPASS_SIG:
1034 pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig);
1035 if (!pkt->pkt.onepass_sig)
1036 return CDK_Out_Of_Core;
1037 rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig);
1038 break;
1040 case CDK_PKT_SIGNATURE:
1041 pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature);
1042 if (!pkt->pkt.signature)
1043 return CDK_Out_Of_Core;
1044 rc = read_signature (inp, pktlen, pkt->pkt.signature);
1045 break;
1047 case CDK_PKT_ENCRYPTED_MDC:
1048 case CDK_PKT_ENCRYPTED:
1049 pkt->pkt.encrypted = cdk_calloc (1, sizeof *pkt->pkt.encrypted);
1050 if (!pkt->pkt.encrypted)
1051 return CDK_Out_Of_Core;
1052 use_mdc = (pkt->pkttype == CDK_PKT_ENCRYPTED_MDC) ? 1 : 0;
1053 rc = read_encrypted( inp, pktlen, pkt->pkt.encrypted,
1054 is_partial, use_mdc );
1055 break;
1057 case CDK_PKT_SYMKEY_ENC:
1058 pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc);
1059 if (!pkt->pkt.symkey_enc)
1060 return CDK_Out_Of_Core;
1061 rc = read_symkey_enc (inp, pktlen, pkt->pkt.symkey_enc);
1062 break;
1064 case CDK_PKT_PUBKEY_ENC:
1065 pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc);
1066 if (!pkt->pkt.pubkey_enc)
1067 return CDK_Out_Of_Core;
1068 rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc);
1069 break;
1071 case CDK_PKT_COMPRESSED:
1072 pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed);
1073 if (!pkt->pkt.compressed)
1074 return CDK_Out_Of_Core;
1075 rc = read_compressed (inp, pktlen, pkt->pkt.compressed);
1076 break;
1078 case CDK_PKT_MDC:
1079 pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc);
1080 if (!pkt->pkt.mdc)
1081 return CDK_Out_Of_Core;
1082 rc = read_mdc (inp, pkt->pkt.mdc);
1083 break;
1085 default:
1086 /* skip all packets we don't understand */
1087 skip_packet( inp, pktlen );
1088 break;
1091 return rc;