simplified calculations
[gnutls.git] / lib / opencdk / write-packet.c
blob521728fd4be8857d85428b4a66ab025cd8bb0201
1 /* write-packet.c - Write 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 <assert.h>
30 #include "opencdk.h"
31 #include "main.h"
34 static int
35 stream_write (cdk_stream_t s, const void *buf, size_t buflen)
37 int nwritten;
39 nwritten = cdk_stream_write (s, buf, buflen);
40 if (nwritten == EOF)
41 return _cdk_stream_get_errno (s);
42 return 0;
46 static int
47 stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread)
49 int nread;
51 assert (r_nread);
53 nread = cdk_stream_read (s, buf, buflen);
54 if (nread == EOF)
55 return _cdk_stream_get_errno (s);
56 *r_nread = nread;
57 return 0;
61 static int
62 stream_putc (cdk_stream_t s, int c)
64 int nwritten = cdk_stream_putc (s, c);
65 if (nwritten == EOF)
66 return _cdk_stream_get_errno (s);
67 return 0;
71 static int
72 write_32 (cdk_stream_t out, u32 u)
74 byte buf[4];
76 buf[0] = u >> 24;
77 buf[1] = u >> 16;
78 buf[2] = u >> 8;
79 buf[3] = u;
80 return stream_write (out, buf, 4);
84 static int
85 write_16 (cdk_stream_t out, u16 u)
87 byte buf[2];
89 buf[0] = u >> 8;
90 buf[1] = u;
91 return stream_write (out, buf, 2);
95 static size_t
96 calc_mpisize (bigint_t mpi[MAX_CDK_PK_PARTS], size_t ncount)
98 size_t size, i;
100 size = 0;
101 for (i = 0; i < ncount; i++)
102 size += (_gnutls_mpi_get_nbits (mpi[i]) + 7) / 8 + 2;
103 return size;
107 static int
108 write_mpi (cdk_stream_t out, bigint_t m)
110 byte buf[MAX_MPI_BYTES + 2];
111 size_t nbits, nread;
112 int err;
114 if (!out || !m)
115 return CDK_Inv_Value;
116 nbits = _gnutls_mpi_get_nbits (m);
117 if (nbits > MAX_MPI_BITS || nbits < 1)
118 return CDK_MPI_Error;
120 nread = MAX_MPI_BYTES + 2;
121 err = _gnutls_mpi_print_pgp (m, buf, &nread);
122 if (err < 0)
123 return map_gnutls_error (err);
124 return stream_write (out, buf, nread);
128 static cdk_error_t
129 write_mpibuf (cdk_stream_t out, bigint_t mpi[MAX_CDK_PK_PARTS], size_t count)
131 size_t i;
132 cdk_error_t rc;
134 for (i = 0; i < count; i++)
136 rc = write_mpi (out, mpi[i]);
137 if (rc)
138 return rc;
140 return 0;
144 static cdk_error_t
145 pkt_encode_len (cdk_stream_t out, size_t pktlen)
147 cdk_error_t rc;
149 if (!out)
150 return CDK_Inv_Value;
152 if (!pktlen)
154 /* Block mode, partial bodies, with 'DEF_BLOCKSIZE' from main.h */
155 rc = stream_putc (out, (0xE0 | DEF_BLOCKBITS));
157 else if (pktlen < 192)
158 rc = stream_putc (out, pktlen);
159 else if (pktlen < 8384)
161 pktlen -= 192;
162 rc = stream_putc (out, (pktlen >> 8) + 192);
163 if (!rc)
164 rc = stream_putc (out, (pktlen & 0xff));
166 else
168 rc = stream_putc (out, 255);
169 if (!rc)
170 rc = write_32 (out, pktlen);
173 return rc;
177 static cdk_error_t
178 write_head_new (cdk_stream_t out, size_t size, int type)
180 cdk_error_t rc;
182 if (!out)
183 return CDK_Inv_Value;
185 if (type < 0 || type > 63)
186 return CDK_Inv_Packet;
187 rc = stream_putc (out, (0xC0 | type));
188 if (!rc)
189 rc = pkt_encode_len (out, size);
190 return rc;
194 static cdk_error_t
195 write_head_old (cdk_stream_t out, size_t size, int type)
197 cdk_error_t rc;
198 int ctb;
200 if (!out)
201 return CDK_Inv_Value;
203 if (type < 0 || type > 16)
204 return CDK_Inv_Packet;
205 ctb = 0x80 | (type << 2);
206 if (!size)
207 ctb |= 3;
208 else if (size < 256)
210 else if (size < 65536)
211 ctb |= 1;
212 else
213 ctb |= 2;
214 rc = stream_putc (out, ctb);
215 if (!size)
216 return rc;
217 if (!rc)
219 if (size < 256)
220 rc = stream_putc (out, size);
221 else if (size < 65536)
222 rc = write_16 (out, size);
223 else
224 rc = write_32 (out, size);
227 return rc;
231 /* Write special PGP2 packet header. PGP2 (wrongly) uses two byte header
232 length for signatures and keys even if the size is < 256. */
233 static cdk_error_t
234 pkt_write_head2 (cdk_stream_t out, size_t size, int type)
236 cdk_error_t rc;
238 rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1);
239 if (!rc)
240 rc = cdk_stream_putc (out, size >> 8);
241 if (!rc)
242 rc = cdk_stream_putc (out, size & 0xff);
243 return rc;
247 static int
248 pkt_write_head (cdk_stream_t out, int old_ctb, size_t size, int type)
250 if (old_ctb)
251 return write_head_old (out, size, type);
252 return write_head_new (out, size, type);
256 static int
257 write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb)
259 size_t size;
260 int rc, nenc;
262 if (!out || !pke)
263 return CDK_Inv_Value;
265 if (pke->version < 2 || pke->version > 3)
266 return CDK_Inv_Packet;
267 if (!KEY_CAN_ENCRYPT (pke->pubkey_algo))
268 return CDK_Inv_Algo;
270 if (DEBUG_PKT)
271 _gnutls_write_log ("write_pubkey_enc:\n");
273 nenc = cdk_pk_get_nenc (pke->pubkey_algo);
274 size = 10 + calc_mpisize (pke->mpi, nenc);
275 rc = pkt_write_head (out, old_ctb, size, CDK_PKT_PUBKEY_ENC);
276 if (rc)
277 return rc;
279 rc = stream_putc (out, pke->version);
280 if (!rc)
281 rc = write_32 (out, pke->keyid[0]);
282 if (!rc)
283 rc = write_32 (out, pke->keyid[1]);
284 if (!rc)
285 rc = stream_putc (out, _cdk_pub_algo_to_pgp (pke->pubkey_algo));
286 if (!rc)
287 rc = write_mpibuf (out, pke->mpi, nenc);
288 return rc;
292 static cdk_error_t
293 write_mdc (cdk_stream_t out, cdk_pkt_mdc_t mdc)
295 cdk_error_t rc;
297 if (!out || !mdc)
298 return CDK_Inv_Value;
300 if (DEBUG_PKT)
301 _gnutls_write_log ("write_mdc:\n");
303 /* This packet requires a fixed header encoding */
304 rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */
305 if (!rc)
306 rc = stream_putc (out, 0x14);
307 if (!rc)
308 rc = stream_write (out, mdc->hash, DIM (mdc->hash));
309 return rc;
313 static size_t
314 calc_subpktsize (cdk_subpkt_t s)
316 size_t nbytes;
318 /* In the count mode, no buffer is returned. */
319 _cdk_subpkt_get_array (s, 1, &nbytes);
320 return nbytes;
324 static cdk_error_t
325 write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig)
327 size_t size;
328 cdk_error_t rc;
330 size = 19 + calc_mpisize (sig->mpi, nsig);
331 if (is_RSA (sig->pubkey_algo))
332 rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE);
333 else
334 rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE);
335 if (!rc)
336 rc = stream_putc (out, sig->version);
337 if (!rc)
338 rc = stream_putc (out, 5);
339 if (!rc)
340 rc = stream_putc (out, sig->sig_class);
341 if (!rc)
342 rc = write_32 (out, sig->timestamp);
343 if (!rc)
344 rc = write_32 (out, sig->keyid[0]);
345 if (!rc)
346 rc = write_32 (out, sig->keyid[1]);
347 if (!rc)
348 rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo));
349 if (!rc)
350 rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo));
351 if (!rc)
352 rc = stream_putc (out, sig->digest_start[0]);
353 if (!rc)
354 rc = stream_putc (out, sig->digest_start[1]);
355 if (!rc)
356 rc = write_mpibuf (out, sig->mpi, nsig);
357 return rc;
361 static cdk_error_t
362 write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb)
364 byte *buf;
365 size_t nbytes, size, nsig;
366 cdk_error_t rc;
368 if (!out || !sig)
369 return CDK_Inv_Value;
371 if (!KEY_CAN_SIGN (sig->pubkey_algo))
372 return gnutls_assert_val(CDK_Inv_Algo);
373 if (sig->version < 2 || sig->version > 4)
374 return gnutls_assert_val(CDK_Inv_Packet);
376 if (DEBUG_PKT)
377 _gnutls_write_log ("write_signature:\n");
379 nsig = cdk_pk_get_nsig (sig->pubkey_algo);
380 if (!nsig)
381 return gnutls_assert_val(CDK_Inv_Algo);
382 if (sig->version < 4)
383 return write_v3_sig (out, sig, nsig);
385 size = 10 + calc_subpktsize (sig->hashed)
386 + calc_subpktsize (sig->unhashed) + calc_mpisize (sig->mpi, nsig);
388 rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE);
389 if (rc)
390 return gnutls_assert_val(rc);
392 rc = stream_putc (out, 4);
393 if (rc)
394 return gnutls_assert_val(rc);
396 rc = stream_putc (out, sig->sig_class);
397 if (rc)
398 return gnutls_assert_val(rc);
400 rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo));
401 if (rc)
402 return gnutls_assert_val(rc);
404 rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo));
405 if (rc)
406 return gnutls_assert_val(rc);
408 rc = write_16 (out, sig->hashed_size);
409 if (rc)
410 return gnutls_assert_val(rc);
412 buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes);
413 if (!buf)
414 return gnutls_assert_val(CDK_Out_Of_Core);
416 rc = stream_write (out, buf, nbytes);
417 cdk_free (buf);
418 if (rc)
419 return gnutls_assert_val(rc);
421 rc = write_16 (out, sig->unhashed_size);
422 if (rc)
423 return gnutls_assert_val(rc);
425 buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes);
426 if (!buf)
427 return gnutls_assert_val(CDK_Out_Of_Core);
429 rc = stream_write (out, buf, nbytes);
430 cdk_free (buf);
431 if (rc)
432 return gnutls_assert_val(rc);
434 rc = stream_putc (out, sig->digest_start[0]);
435 if (rc)
436 return gnutls_assert_val(rc);
438 rc = stream_putc (out, sig->digest_start[1]);
439 if (rc)
440 return gnutls_assert_val(rc);
442 rc = write_mpibuf (out, sig->mpi, nsig);
443 if (rc)
444 return gnutls_assert_val(rc);
446 return 0;
450 static cdk_error_t
451 write_public_key (cdk_stream_t out, cdk_pkt_pubkey_t pk,
452 int is_subkey, int old_ctb)
454 int pkttype, ndays = 0;
455 size_t npkey = 0, size = 6;
456 cdk_error_t rc;
458 if (!out || !pk)
459 return CDK_Inv_Value;
461 if (pk->version < 2 || pk->version > 4)
462 return CDK_Inv_Packet;
464 if (DEBUG_PKT)
465 _gnutls_write_log ("write_public_key: subkey=%d\n", is_subkey);
467 pkttype = is_subkey ? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY;
468 npkey = cdk_pk_get_npkey (pk->pubkey_algo);
469 if (!npkey)
470 return CDK_Inv_Algo;
471 if (pk->version < 4)
472 size += 2; /* expire date */
473 if (is_subkey)
474 old_ctb = 0;
475 size += calc_mpisize (pk->mpi, npkey);
476 if (old_ctb)
477 rc = pkt_write_head2 (out, size, pkttype);
478 else
479 rc = pkt_write_head (out, old_ctb, size, pkttype);
480 if (!rc)
481 rc = stream_putc (out, pk->version);
482 if (!rc)
483 rc = write_32 (out, pk->timestamp);
484 if (!rc && pk->version < 4)
486 if (pk->expiredate)
487 ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
488 rc = write_16 (out, ndays);
490 if (!rc)
491 rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo));
492 if (!rc)
493 rc = write_mpibuf (out, pk->mpi, npkey);
494 return rc;
498 static int
499 calc_s2ksize (cdk_pkt_seckey_t sk)
501 size_t nbytes = 0;
503 if (!sk->is_protected)
504 return 0;
505 switch (sk->protect.s2k->mode)
507 case CDK_S2K_SIMPLE:
508 nbytes = 2;
509 break;
510 case CDK_S2K_SALTED:
511 nbytes = 10;
512 break;
513 case CDK_S2K_ITERSALTED:
514 nbytes = 11;
515 break;
516 case CDK_S2K_GNU_EXT:
517 nbytes = 2;
518 break;
520 nbytes += sk->protect.ivlen;
521 nbytes++; /* single cipher byte */
522 return nbytes;
526 static cdk_error_t
527 write_secret_key (cdk_stream_t out, cdk_pkt_seckey_t sk,
528 int is_subkey, int old_ctb)
530 cdk_pkt_pubkey_t pk = NULL;
531 size_t size = 6, npkey, nskey;
532 int pkttype, s2k_mode;
533 cdk_error_t rc;
535 if (!out || !sk)
536 return CDK_Inv_Value;
538 if (!sk->pk)
539 return CDK_Inv_Value;
540 pk = sk->pk;
541 if (pk->version < 2 || pk->version > 4)
542 return CDK_Inv_Packet;
544 if (DEBUG_PKT)
545 _gnutls_write_log ("write_secret_key:\n");
547 npkey = cdk_pk_get_npkey (pk->pubkey_algo);
548 nskey = cdk_pk_get_nskey (pk->pubkey_algo);
549 if (!npkey || !nskey)
551 gnutls_assert ();
552 return CDK_Inv_Algo;
554 if (pk->version < 4)
555 size += 2;
556 /* If the key is unprotected, the 1 extra byte:
557 1 octet - cipher algorithm byte (0x00)
558 the other bytes depend on the mode:
559 a) simple checksum - 2 octets
560 b) sha-1 checksum - 20 octets */
561 size = !sk->is_protected ? size + 1 : size + 1 + calc_s2ksize (sk);
562 size += calc_mpisize (pk->mpi, npkey);
563 if (sk->version == 3 || !sk->is_protected)
565 if (sk->version == 3)
567 size += 2; /* force simple checksum */
568 sk->protect.sha1chk = 0;
570 else
571 size += sk->protect.sha1chk ? 20 : 2;
572 size += calc_mpisize (sk->mpi, nskey);
574 else /* We do not know anything about the encrypted mpi's so we
575 treat the data as uint8_t. */
576 size += sk->enclen;
578 pkttype = is_subkey ? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY;
579 rc = pkt_write_head (out, old_ctb, size, pkttype);
580 if (!rc)
581 rc = stream_putc (out, pk->version);
582 if (!rc)
583 rc = write_32 (out, pk->timestamp);
584 if (!rc && pk->version < 4)
586 u16 ndays = 0;
587 if (pk->expiredate)
588 ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L);
589 rc = write_16 (out, ndays);
591 if (!rc)
592 rc = stream_putc (out, _cdk_pub_algo_to_pgp (pk->pubkey_algo));
594 if (!rc)
595 rc = write_mpibuf (out, pk->mpi, npkey);
597 if (!rc)
599 if (sk->is_protected == 0)
600 rc = stream_putc (out, 0x00);
601 else
603 if (is_RSA (pk->pubkey_algo) && pk->version < 4)
604 rc = stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo));
605 else if (sk->protect.s2k)
607 s2k_mode = sk->protect.s2k->mode;
608 rc = stream_putc (out, sk->protect.sha1chk ? 0xFE : 0xFF);
609 if (!rc)
610 rc =
611 stream_putc (out, _gnutls_cipher_to_pgp (sk->protect.algo));
612 if (!rc)
613 rc = stream_putc (out, sk->protect.s2k->mode);
614 if (!rc)
615 rc = stream_putc (out, sk->protect.s2k->hash_algo);
616 if (!rc && (s2k_mode == 1 || s2k_mode == 3))
618 rc = stream_write (out, sk->protect.s2k->salt, 8);
619 if (!rc && s2k_mode == 3)
620 rc = stream_putc (out, sk->protect.s2k->count);
623 else
624 return CDK_Inv_Value;
625 if (!rc)
626 rc = stream_write (out, sk->protect.iv, sk->protect.ivlen);
629 if (!rc && sk->is_protected && pk->version == 4)
631 if (sk->encdata && sk->enclen)
632 rc = stream_write (out, sk->encdata, sk->enclen);
634 else
636 if (!rc)
637 rc = write_mpibuf (out, sk->mpi, nskey);
638 if (!rc)
640 if (!sk->csum)
641 sk->csum = _cdk_sk_get_csum (sk);
642 rc = write_16 (out, sk->csum);
646 return rc;
650 static cdk_error_t
651 write_compressed (cdk_stream_t out, cdk_pkt_compressed_t cd)
653 cdk_error_t rc;
655 if (!out || !cd)
656 return CDK_Inv_Value;
658 if (DEBUG_PKT)
659 _gnutls_write_log ("packet: write_compressed\n");
661 /* Use an old (RFC1991) header for this packet. */
662 rc = pkt_write_head (out, 1, 0, CDK_PKT_COMPRESSED);
663 if (!rc)
664 rc = stream_putc (out, cd->algorithm);
665 return rc;
669 static cdk_error_t
670 write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb)
672 byte buf[BUFSIZE];
673 size_t size;
674 cdk_error_t rc;
676 if (!out || !pt)
677 return CDK_Inv_Value;
679 /* We consider a packet without a body as an invalid packet.
680 At least one octet must be present. */
681 if (!pt->len)
682 return CDK_Inv_Packet;
684 if (DEBUG_PKT)
685 _gnutls_write_log ("write_literal:\n");
687 size = 6 + pt->namelen + pt->len;
688 rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL);
689 if (rc)
690 return rc;
692 rc = stream_putc (out, pt->mode);
693 if (rc)
694 return rc;
695 rc = stream_putc (out, pt->namelen);
696 if (rc)
697 return rc;
699 if (pt->namelen > 0)
700 rc = stream_write (out, pt->name, pt->namelen);
701 if (!rc)
702 rc = write_32 (out, pt->timestamp);
703 if (rc)
704 return rc;
706 while (!cdk_stream_eof (pt->buf) && !rc)
708 rc = stream_read (pt->buf, buf, DIM (buf), &size);
709 if (!rc)
710 rc = stream_write (out, buf, size);
713 memset (buf, 0, sizeof (buf));
714 return rc;
718 static cdk_error_t
719 write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig)
721 cdk_error_t rc;
723 if (!out || !sig)
724 return CDK_Inv_Value;
726 if (sig->version != 3)
727 return CDK_Inv_Packet;
729 if (DEBUG_PKT)
730 _gnutls_write_log ("write_onepass_sig:\n");
732 rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG);
733 if (!rc)
734 rc = stream_putc (out, sig->version);
735 if (!rc)
736 rc = stream_putc (out, sig->sig_class);
737 if (!rc)
738 rc = stream_putc (out, _gnutls_hash_algo_to_pgp (sig->digest_algo));
739 if (!rc)
740 rc = stream_putc (out, _cdk_pub_algo_to_pgp (sig->pubkey_algo));
741 if (!rc)
742 rc = write_32 (out, sig->keyid[0]);
743 if (!rc)
744 rc = write_32 (out, sig->keyid[1]);
745 if (!rc)
746 rc = stream_putc (out, sig->last);
747 return rc;
751 static cdk_error_t
752 write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb,
753 int pkttype)
755 cdk_error_t rc;
757 if (!out || !id)
758 return CDK_Inv_Value;
760 if (pkttype == CDK_PKT_ATTRIBUTE)
762 if (!id->attrib_img)
763 return CDK_Inv_Value;
764 rc =
765 pkt_write_head (out, old_ctb, id->attrib_len + 6, CDK_PKT_ATTRIBUTE);
766 if (rc)
767 return rc;
768 /* Write subpacket part. */
769 stream_putc (out, 255);
770 write_32 (out, id->attrib_len + 1);
771 stream_putc (out, 1);
772 rc = stream_write (out, id->attrib_img, id->attrib_len);
774 else
776 if (!id->name)
777 return CDK_Inv_Value;
778 rc = pkt_write_head (out, old_ctb, id->len, CDK_PKT_USER_ID);
779 if (!rc)
780 rc = stream_write (out, id->name, id->len);
783 return rc;
788 * cdk_pkt_write:
789 * @out: the output stream handle
790 * @pkt: the packet itself
792 * Write the contents of @pkt into the @out stream.
793 * Return 0 on success.
795 cdk_error_t
796 cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt)
798 cdk_error_t rc;
800 if (!out || !pkt)
801 return CDK_Inv_Value;
803 if (DEBUG_PKT)
804 _gnutls_write_log ("write packet pkttype=%d\n", pkt->pkttype);
806 switch (pkt->pkttype)
808 case CDK_PKT_LITERAL:
809 rc = write_literal (out, pkt->pkt.literal, pkt->old_ctb);
810 break;
811 case CDK_PKT_ONEPASS_SIG:
812 rc = write_onepass_sig (out, pkt->pkt.onepass_sig);
813 break;
814 case CDK_PKT_MDC:
815 rc = write_mdc (out, pkt->pkt.mdc);
816 break;
817 case CDK_PKT_PUBKEY_ENC:
818 rc = write_pubkey_enc (out, pkt->pkt.pubkey_enc, pkt->old_ctb);
819 break;
820 case CDK_PKT_SIGNATURE:
821 rc = write_signature (out, pkt->pkt.signature, pkt->old_ctb);
822 break;
823 case CDK_PKT_PUBLIC_KEY:
824 rc = write_public_key (out, pkt->pkt.public_key, 0, pkt->old_ctb);
825 break;
826 case CDK_PKT_PUBLIC_SUBKEY:
827 rc = write_public_key (out, pkt->pkt.public_key, 1, pkt->old_ctb);
828 break;
829 case CDK_PKT_COMPRESSED:
830 rc = write_compressed (out, pkt->pkt.compressed);
831 break;
832 case CDK_PKT_SECRET_KEY:
833 rc = write_secret_key (out, pkt->pkt.secret_key, 0, pkt->old_ctb);
834 break;
835 case CDK_PKT_SECRET_SUBKEY:
836 rc = write_secret_key (out, pkt->pkt.secret_key, 1, pkt->old_ctb);
837 break;
838 case CDK_PKT_USER_ID:
839 case CDK_PKT_ATTRIBUTE:
840 rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb, pkt->pkttype);
841 break;
842 default:
843 rc = CDK_Inv_Packet;
844 break;
847 if (DEBUG_PKT)
848 _gnutls_write_log ("write_packet rc=%d pkttype=%d\n", rc, pkt->pkttype);
849 return rc;
853 cdk_error_t
854 _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx)
856 cdk_packet_t pkt;
857 cdk_error_t rc;
859 rc = cdk_pkt_new (&pkt);
860 if (rc)
861 return rc;
863 switch (pkttype)
865 case CDK_PKT_PUBLIC_KEY:
866 case CDK_PKT_PUBLIC_SUBKEY:
867 pkt->pkt.public_key = pktctx;
868 break;
869 case CDK_PKT_SIGNATURE:
870 pkt->pkt.signature = pktctx;
871 break;
872 case CDK_PKT_SECRET_KEY:
873 case CDK_PKT_SECRET_SUBKEY:
874 pkt->pkt.secret_key = pktctx;
875 break;
877 case CDK_PKT_USER_ID:
878 pkt->pkt.user_id = pktctx;
879 break;
881 pkt->pkttype = pkttype;
882 rc = cdk_pkt_write (out, pkt);
883 cdk_free (pkt);
884 return rc;
888 cdk_error_t
889 _cdk_pkt_write_fp (FILE * out, cdk_packet_t pkt)
891 cdk_stream_t so;
892 cdk_error_t rc;
894 rc = _cdk_stream_fpopen (out, 1, &so);
895 if (rc)
896 return rc;
897 rc = cdk_pkt_write (so, pkt);
898 cdk_stream_close (so);
899 return rc;