1 /* write-packet.c - Write OpenPGP packets
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
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/>
35 stream_write (cdk_stream_t s
, const void *buf
, size_t buflen
)
39 nwritten
= cdk_stream_write (s
, buf
, buflen
);
41 return _cdk_stream_get_errno (s
);
47 stream_read (cdk_stream_t s
, void *buf
, size_t buflen
, size_t * r_nread
)
53 nread
= cdk_stream_read (s
, buf
, buflen
);
55 return _cdk_stream_get_errno (s
);
62 stream_putc (cdk_stream_t s
, int c
)
64 int nwritten
= cdk_stream_putc (s
, c
);
66 return _cdk_stream_get_errno (s
);
72 write_32 (cdk_stream_t out
, u32 u
)
80 return stream_write (out
, buf
, 4);
85 write_16 (cdk_stream_t out
, u16 u
)
91 return stream_write (out
, buf
, 2);
96 calc_mpisize (bigint_t mpi
[MAX_CDK_PK_PARTS
], size_t ncount
)
101 for (i
= 0; i
< ncount
; i
++)
102 size
+= (_gnutls_mpi_get_nbits (mpi
[i
]) + 7) / 8 + 2;
108 write_mpi (cdk_stream_t out
, bigint_t m
)
110 byte buf
[MAX_MPI_BYTES
+ 2];
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
);
123 return map_gnutls_error (err
);
124 return stream_write (out
, buf
, nread
);
129 write_mpibuf (cdk_stream_t out
, bigint_t mpi
[MAX_CDK_PK_PARTS
], size_t count
)
134 for (i
= 0; i
< count
; i
++)
136 rc
= write_mpi (out
, mpi
[i
]);
145 pkt_encode_len (cdk_stream_t out
, size_t pktlen
)
150 return CDK_Inv_Value
;
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)
162 rc
= stream_putc (out
, (pktlen
>> 8) + 192);
164 rc
= stream_putc (out
, (pktlen
& 0xff));
168 rc
= stream_putc (out
, 255);
170 rc
= write_32 (out
, pktlen
);
178 write_head_new (cdk_stream_t out
, size_t size
, int type
)
183 return CDK_Inv_Value
;
185 if (type
< 0 || type
> 63)
186 return CDK_Inv_Packet
;
187 rc
= stream_putc (out
, (0xC0 | type
));
189 rc
= pkt_encode_len (out
, size
);
195 write_head_old (cdk_stream_t out
, size_t size
, int type
)
201 return CDK_Inv_Value
;
203 if (type
< 0 || type
> 16)
204 return CDK_Inv_Packet
;
205 ctb
= 0x80 | (type
<< 2);
210 else if (size
< 65536)
214 rc
= stream_putc (out
, ctb
);
220 rc
= stream_putc (out
, size
);
221 else if (size
< 65536)
222 rc
= write_16 (out
, size
);
224 rc
= write_32 (out
, size
);
231 /* Write special PGP2 packet header. PGP2 (wrongly) uses two byte header
232 length for signatures and keys even if the size is < 256. */
234 pkt_write_head2 (cdk_stream_t out
, size_t size
, int type
)
238 rc
= cdk_stream_putc (out
, 0x80 | (type
<< 2) | 1);
240 rc
= cdk_stream_putc (out
, size
>> 8);
242 rc
= cdk_stream_putc (out
, size
& 0xff);
248 pkt_write_head (cdk_stream_t out
, int old_ctb
, size_t size
, int type
)
251 return write_head_old (out
, size
, type
);
252 return write_head_new (out
, size
, type
);
257 write_pubkey_enc (cdk_stream_t out
, cdk_pkt_pubkey_enc_t pke
, int old_ctb
)
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
))
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
);
279 rc
= stream_putc (out
, pke
->version
);
281 rc
= write_32 (out
, pke
->keyid
[0]);
283 rc
= write_32 (out
, pke
->keyid
[1]);
285 rc
= stream_putc (out
, _cdk_pub_algo_to_pgp (pke
->pubkey_algo
));
287 rc
= write_mpibuf (out
, pke
->mpi
, nenc
);
293 write_mdc (cdk_stream_t out
, cdk_pkt_mdc_t mdc
)
298 return CDK_Inv_Value
;
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 */
306 rc
= stream_putc (out
, 0x14);
308 rc
= stream_write (out
, mdc
->hash
, DIM (mdc
->hash
));
314 calc_subpktsize (cdk_subpkt_t s
)
318 /* In the count mode, no buffer is returned. */
319 _cdk_subpkt_get_array (s
, 1, &nbytes
);
325 write_v3_sig (cdk_stream_t out
, cdk_pkt_signature_t sig
, int nsig
)
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
);
334 rc
= pkt_write_head (out
, 1, size
, CDK_PKT_SIGNATURE
);
336 rc
= stream_putc (out
, sig
->version
);
338 rc
= stream_putc (out
, 5);
340 rc
= stream_putc (out
, sig
->sig_class
);
342 rc
= write_32 (out
, sig
->timestamp
);
344 rc
= write_32 (out
, sig
->keyid
[0]);
346 rc
= write_32 (out
, sig
->keyid
[1]);
348 rc
= stream_putc (out
, _cdk_pub_algo_to_pgp (sig
->pubkey_algo
));
350 rc
= stream_putc (out
, _gnutls_hash_algo_to_pgp (sig
->digest_algo
));
352 rc
= stream_putc (out
, sig
->digest_start
[0]);
354 rc
= stream_putc (out
, sig
->digest_start
[1]);
356 rc
= write_mpibuf (out
, sig
->mpi
, nsig
);
362 write_signature (cdk_stream_t out
, cdk_pkt_signature_t sig
, int old_ctb
)
365 size_t nbytes
, size
, nsig
;
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
);
377 _gnutls_write_log ("write_signature:\n");
379 nsig
= cdk_pk_get_nsig (sig
->pubkey_algo
);
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
);
390 return gnutls_assert_val(rc
);
392 rc
= stream_putc (out
, 4);
394 return gnutls_assert_val(rc
);
396 rc
= stream_putc (out
, sig
->sig_class
);
398 return gnutls_assert_val(rc
);
400 rc
= stream_putc (out
, _cdk_pub_algo_to_pgp (sig
->pubkey_algo
));
402 return gnutls_assert_val(rc
);
404 rc
= stream_putc (out
, _gnutls_hash_algo_to_pgp (sig
->digest_algo
));
406 return gnutls_assert_val(rc
);
408 rc
= write_16 (out
, sig
->hashed_size
);
410 return gnutls_assert_val(rc
);
412 buf
= _cdk_subpkt_get_array (sig
->hashed
, 0, &nbytes
);
414 return gnutls_assert_val(CDK_Out_Of_Core
);
416 rc
= stream_write (out
, buf
, nbytes
);
419 return gnutls_assert_val(rc
);
421 rc
= write_16 (out
, sig
->unhashed_size
);
423 return gnutls_assert_val(rc
);
425 buf
= _cdk_subpkt_get_array (sig
->unhashed
, 0, &nbytes
);
427 return gnutls_assert_val(CDK_Out_Of_Core
);
429 rc
= stream_write (out
, buf
, nbytes
);
432 return gnutls_assert_val(rc
);
434 rc
= stream_putc (out
, sig
->digest_start
[0]);
436 return gnutls_assert_val(rc
);
438 rc
= stream_putc (out
, sig
->digest_start
[1]);
440 return gnutls_assert_val(rc
);
442 rc
= write_mpibuf (out
, sig
->mpi
, nsig
);
444 return gnutls_assert_val(rc
);
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;
459 return CDK_Inv_Value
;
461 if (pk
->version
< 2 || pk
->version
> 4)
462 return CDK_Inv_Packet
;
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
);
472 size
+= 2; /* expire date */
475 size
+= calc_mpisize (pk
->mpi
, npkey
);
477 rc
= pkt_write_head2 (out
, size
, pkttype
);
479 rc
= pkt_write_head (out
, old_ctb
, size
, pkttype
);
481 rc
= stream_putc (out
, pk
->version
);
483 rc
= write_32 (out
, pk
->timestamp
);
484 if (!rc
&& pk
->version
< 4)
487 ndays
= (u16
) ((pk
->expiredate
- pk
->timestamp
) / 86400L);
488 rc
= write_16 (out
, ndays
);
491 rc
= stream_putc (out
, _cdk_pub_algo_to_pgp (pk
->pubkey_algo
));
493 rc
= write_mpibuf (out
, pk
->mpi
, npkey
);
499 calc_s2ksize (cdk_pkt_seckey_t sk
)
503 if (!sk
->is_protected
)
505 switch (sk
->protect
.s2k
->mode
)
513 case CDK_S2K_ITERSALTED
:
516 case CDK_S2K_GNU_EXT
:
520 nbytes
+= sk
->protect
.ivlen
;
521 nbytes
++; /* single cipher byte */
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
;
536 return CDK_Inv_Value
;
539 return CDK_Inv_Value
;
541 if (pk
->version
< 2 || pk
->version
> 4)
542 return CDK_Inv_Packet
;
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
)
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;
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. */
578 pkttype
= is_subkey
? CDK_PKT_SECRET_SUBKEY
: CDK_PKT_SECRET_KEY
;
579 rc
= pkt_write_head (out
, old_ctb
, size
, pkttype
);
581 rc
= stream_putc (out
, pk
->version
);
583 rc
= write_32 (out
, pk
->timestamp
);
584 if (!rc
&& pk
->version
< 4)
588 ndays
= (u16
) ((pk
->expiredate
- pk
->timestamp
) / 86400L);
589 rc
= write_16 (out
, ndays
);
592 rc
= stream_putc (out
, _cdk_pub_algo_to_pgp (pk
->pubkey_algo
));
595 rc
= write_mpibuf (out
, pk
->mpi
, npkey
);
599 if (sk
->is_protected
== 0)
600 rc
= stream_putc (out
, 0x00);
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);
611 stream_putc (out
, _gnutls_cipher_to_pgp (sk
->protect
.algo
));
613 rc
= stream_putc (out
, sk
->protect
.s2k
->mode
);
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
);
624 return CDK_Inv_Value
;
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
);
637 rc
= write_mpibuf (out
, sk
->mpi
, nskey
);
641 sk
->csum
= _cdk_sk_get_csum (sk
);
642 rc
= write_16 (out
, sk
->csum
);
651 write_compressed (cdk_stream_t out
, cdk_pkt_compressed_t cd
)
656 return CDK_Inv_Value
;
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
);
664 rc
= stream_putc (out
, cd
->algorithm
);
670 write_literal (cdk_stream_t out
, cdk_pkt_literal_t pt
, int old_ctb
)
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. */
682 return CDK_Inv_Packet
;
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
);
692 rc
= stream_putc (out
, pt
->mode
);
695 rc
= stream_putc (out
, pt
->namelen
);
700 rc
= stream_write (out
, pt
->name
, pt
->namelen
);
702 rc
= write_32 (out
, pt
->timestamp
);
706 while (!cdk_stream_eof (pt
->buf
) && !rc
)
708 rc
= stream_read (pt
->buf
, buf
, DIM (buf
), &size
);
710 rc
= stream_write (out
, buf
, size
);
713 memset (buf
, 0, sizeof (buf
));
719 write_onepass_sig (cdk_stream_t out
, cdk_pkt_onepass_sig_t sig
)
724 return CDK_Inv_Value
;
726 if (sig
->version
!= 3)
727 return CDK_Inv_Packet
;
730 _gnutls_write_log ("write_onepass_sig:\n");
732 rc
= pkt_write_head (out
, 0, 13, CDK_PKT_ONEPASS_SIG
);
734 rc
= stream_putc (out
, sig
->version
);
736 rc
= stream_putc (out
, sig
->sig_class
);
738 rc
= stream_putc (out
, _gnutls_hash_algo_to_pgp (sig
->digest_algo
));
740 rc
= stream_putc (out
, _cdk_pub_algo_to_pgp (sig
->pubkey_algo
));
742 rc
= write_32 (out
, sig
->keyid
[0]);
744 rc
= write_32 (out
, sig
->keyid
[1]);
746 rc
= stream_putc (out
, sig
->last
);
752 write_user_id (cdk_stream_t out
, cdk_pkt_userid_t id
, int old_ctb
,
758 return CDK_Inv_Value
;
760 if (pkttype
== CDK_PKT_ATTRIBUTE
)
763 return CDK_Inv_Value
;
765 pkt_write_head (out
, old_ctb
, id
->attrib_len
+ 6, CDK_PKT_ATTRIBUTE
);
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
);
777 return CDK_Inv_Value
;
778 rc
= pkt_write_head (out
, old_ctb
, id
->len
, CDK_PKT_USER_ID
);
780 rc
= stream_write (out
, id
->name
, id
->len
);
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.
796 cdk_pkt_write (cdk_stream_t out
, cdk_packet_t pkt
)
801 return CDK_Inv_Value
;
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
);
811 case CDK_PKT_ONEPASS_SIG
:
812 rc
= write_onepass_sig (out
, pkt
->pkt
.onepass_sig
);
815 rc
= write_mdc (out
, pkt
->pkt
.mdc
);
817 case CDK_PKT_PUBKEY_ENC
:
818 rc
= write_pubkey_enc (out
, pkt
->pkt
.pubkey_enc
, pkt
->old_ctb
);
820 case CDK_PKT_SIGNATURE
:
821 rc
= write_signature (out
, pkt
->pkt
.signature
, pkt
->old_ctb
);
823 case CDK_PKT_PUBLIC_KEY
:
824 rc
= write_public_key (out
, pkt
->pkt
.public_key
, 0, pkt
->old_ctb
);
826 case CDK_PKT_PUBLIC_SUBKEY
:
827 rc
= write_public_key (out
, pkt
->pkt
.public_key
, 1, pkt
->old_ctb
);
829 case CDK_PKT_COMPRESSED
:
830 rc
= write_compressed (out
, pkt
->pkt
.compressed
);
832 case CDK_PKT_SECRET_KEY
:
833 rc
= write_secret_key (out
, pkt
->pkt
.secret_key
, 0, pkt
->old_ctb
);
835 case CDK_PKT_SECRET_SUBKEY
:
836 rc
= write_secret_key (out
, pkt
->pkt
.secret_key
, 1, pkt
->old_ctb
);
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
);
848 _gnutls_write_log ("write_packet rc=%d pkttype=%d\n", rc
, pkt
->pkttype
);
854 _cdk_pkt_write2 (cdk_stream_t out
, int pkttype
, void *pktctx
)
859 rc
= cdk_pkt_new (&pkt
);
865 case CDK_PKT_PUBLIC_KEY
:
866 case CDK_PKT_PUBLIC_SUBKEY
:
867 pkt
->pkt
.public_key
= pktctx
;
869 case CDK_PKT_SIGNATURE
:
870 pkt
->pkt
.signature
= pktctx
;
872 case CDK_PKT_SECRET_KEY
:
873 case CDK_PKT_SECRET_SUBKEY
:
874 pkt
->pkt
.secret_key
= pktctx
;
877 case CDK_PKT_USER_ID
:
878 pkt
->pkt
.user_id
= pktctx
;
881 pkt
->pkttype
= pkttype
;
882 rc
= cdk_pkt_write (out
, pkt
);
889 _cdk_pkt_write_fp (FILE * out
, cdk_packet_t pkt
)
894 rc
= _cdk_stream_fpopen (out
, 1, &so
);
897 rc
= cdk_pkt_write (so
, pkt
);
898 cdk_stream_close (so
);