2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
31 * All rights reserved.
32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
33 * their moral rights under the UK Copyright Design and Patents Act 1988 to
34 * be recorded as the authors of this copyright work.
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
42 * Unless required by applicable law or agreed to in writing, software
43 * distributed under the License is distributed on an "AS IS" BASIS,
44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
51 * This file contains the base functions used by the writers.
55 #ifdef HAVE_SYS_CDEFS_H
56 #include <sys/cdefs.h>
59 #if defined(__NetBSD__)
60 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
61 __RCSID("$NetBSD: writer.c,v 1.15 2009/10/07 16:19:51 agc Exp $");
64 #include <sys/types.h>
73 #ifdef HAVE_OPENSSL_CAST_H
74 #include <openssl/cast.h>
80 #include "signature.h"
82 #include "packet-parse.h"
83 #include "readerwriter.h"
85 #include "netpgpdefs.h"
87 #include "netpgpdigest.h"
91 * return 1 if OK, otherwise 0
94 base_write(const void *src
, unsigned len
, __ops_output_t
*out
)
96 return out
->writer
.writer(src
, len
, &out
->errors
, &out
->writer
);
100 * \ingroup Core_WritePackets
105 * \return 1 if OK, otherwise 0
109 __ops_write(__ops_output_t
*output
, const void *src
, unsigned len
)
111 return base_write(src
, len
, output
);
115 * \ingroup Core_WritePackets
119 * \return 1 if OK, otherwise 0
123 __ops_write_scalar(__ops_output_t
*output
, unsigned n
, unsigned len
)
129 if (!base_write(&c
, 1, output
)) {
137 * \ingroup Core_WritePackets
140 * \return 1 if OK, otherwise 0
144 __ops_write_mpi(__ops_output_t
*output
, const BIGNUM
*bn
)
146 unsigned char buf
[NETPGP_BUFSIZ
];
147 unsigned bits
= (unsigned)BN_num_bits(bn
);
150 (void) fprintf(stderr
, "__ops_write_mpi: too large %u\n", bits
);
154 return __ops_write_scalar(output
, bits
, 2) &&
155 __ops_write(output
, buf
, (bits
+ 7) / 8);
159 * \ingroup Core_WritePackets
162 * \return 1 if OK, otherwise 0
166 __ops_write_ptag(__ops_output_t
*output
, __ops_content_tag_t tag
)
170 c
= tag
| OPS_PTAG_ALWAYS_SET
| OPS_PTAG_NEW_FORMAT
;
171 return base_write(&c
, 1, output
);
175 * \ingroup Core_WritePackets
178 * \return 1 if OK, otherwise 0
182 __ops_write_length(__ops_output_t
*output
, unsigned len
)
188 return base_write(c
, 1, output
);
190 if (len
< 8192 + 192) {
191 c
[0] = ((len
- 192) >> 8) + 192;
192 c
[1] = (len
- 192) % 256;
193 return base_write(c
, 2, output
);
195 return __ops_write_scalar(output
, 0xff, 1) &&
196 __ops_write_scalar(output
, len
, 4);
200 * Note that we finalise from the top down, so we don't use writers below
201 * that have already been finalised
204 writer_info_finalise(__ops_error_t
**errors
, __ops_writer_t
*writer
)
208 if (writer
->finaliser
) {
209 ret
= writer
->finaliser(errors
, writer
);
210 writer
->finaliser
= NULL
;
212 if (writer
->next
&& !writer_info_finalise(errors
, writer
->next
)) {
213 writer
->finaliser
= NULL
;
220 writer_info_delete(__ops_writer_t
*writer
)
222 /* we should have finalised before deleting */
223 if (writer
->finaliser
) {
224 (void) fprintf(stderr
, "writer_info_delete: not finalised\n");
228 writer_info_delete(writer
->next
);
232 if (writer
->destroyer
) {
233 writer
->destroyer(writer
);
234 writer
->destroyer
= NULL
;
236 writer
->writer
= NULL
;
240 * \ingroup Core_Writers
242 * Set a writer in output. There should not be another writer set.
244 * \param output The output structure
248 * \param arg The argument for the writer and destroyer
251 __ops_writer_set(__ops_output_t
*output
,
252 __ops_writer_func_t
*writer
,
253 __ops_writer_finaliser_t
*finaliser
,
254 __ops_writer_destroyer_t
*destroyer
,
257 if (output
->writer
.writer
) {
258 (void) fprintf(stderr
, "__ops_writer_set: already set\n");
260 output
->writer
.writer
= writer
;
261 output
->writer
.finaliser
= finaliser
;
262 output
->writer
.destroyer
= destroyer
;
263 output
->writer
.arg
= arg
;
268 * \ingroup Core_Writers
270 * Push a writer in output. There must already be another writer set.
272 * \param output The output structure
276 * \param arg The argument for the writer and destroyer
279 __ops_writer_push(__ops_output_t
*output
,
280 __ops_writer_func_t
*writer
,
281 __ops_writer_finaliser_t
*finaliser
,
282 __ops_writer_destroyer_t
*destroyer
,
285 __ops_writer_t
*copy
;
287 if ((copy
= calloc(1, sizeof(*copy
))) == NULL
) {
288 (void) fprintf(stderr
, "__ops_writer_push: bad alloc\n");
289 } else if (output
->writer
.writer
== NULL
) {
290 (void) fprintf(stderr
, "__ops_writer_push: no orig writer\n");
292 *copy
= output
->writer
;
293 output
->writer
.next
= copy
;
295 output
->writer
.writer
= writer
;
296 output
->writer
.finaliser
= finaliser
;
297 output
->writer
.destroyer
= destroyer
;
298 output
->writer
.arg
= arg
;
303 __ops_writer_pop(__ops_output_t
*output
)
305 __ops_writer_t
*next
;
307 /* Make sure the finaliser has been called. */
308 if (output
->writer
.finaliser
) {
309 (void) fprintf(stderr
,
310 "__ops_writer_pop: finaliser not called\n");
311 } else if (output
->writer
.next
== NULL
) {
312 (void) fprintf(stderr
,
313 "__ops_writer_pop: not a stacked writer\n");
315 if (output
->writer
.destroyer
) {
316 output
->writer
.destroyer(&output
->writer
);
318 next
= output
->writer
.next
;
319 output
->writer
= *next
;
325 * \ingroup Core_Writers
327 * Close the writer currently set in output.
329 * \param output The output structure
332 __ops_writer_close(__ops_output_t
*output
)
334 unsigned ret
= writer_info_finalise(&output
->errors
, &output
->writer
);
336 writer_info_delete(&output
->writer
);
341 * \ingroup Core_Writers
343 * Get the arg supplied to __ops_createinfo_set_writer().
345 * \param writer The writer_info structure
349 __ops_writer_get_arg(__ops_writer_t
*writer
)
355 * \ingroup Core_Writers
357 * Write to the next writer down in the stack.
359 * \param src The data to write.
360 * \param len The length of src.
361 * \param errors A place to store errors.
362 * \param writer The writer_info structure.
363 * \return Success - if 0, then errors should contain the error.
366 __ops_stacked_write(const void *src
, unsigned len
,
367 __ops_error_t
** errors
, __ops_writer_t
*writer
)
369 return writer
->next
->writer(src
, len
, errors
, writer
->next
);
373 * \ingroup Core_Writers
375 * Free the arg. Many writers just have a calloc()ed lump of storage, this
376 * function releases it.
378 * \param writer the info structure.
381 generic_destroyer(__ops_writer_t
*writer
)
383 free(__ops_writer_get_arg(writer
));
387 * \ingroup Core_Writers
389 * A writer that just writes to the next one down. Useful for when you
390 * want to insert just a finaliser into the stack.
393 __ops_writer_passthrough(const unsigned char *src
,
395 __ops_error_t
**errors
,
396 __ops_writer_t
*writer
)
398 return __ops_stacked_write(src
, len
, errors
, writer
);
401 /**************************************************************************/
409 __ops_create_sig_t
*sig
;
410 __ops_memory_t
*trailing
;
414 dash_esc_writer(const unsigned char *src
,
416 __ops_error_t
**errors
,
417 __ops_writer_t
*writer
)
419 dashesc_t
*dash
= __ops_writer_get_arg(writer
);
422 if (__ops_get_debug_level(__FILE__
)) {
425 (void) fprintf(stderr
, "dash_esc_writer writing %u:\n", len
);
426 for (i
= 0; i
< len
; i
++) {
427 fprintf(stderr
, "0x%02x ", src
[i
]);
428 if (((i
+ 1) % 16) == 0) {
429 (void) fprintf(stderr
, "\n");
430 } else if (((i
+ 1) % 8) == 0) {
431 (void) fprintf(stderr
, " ");
434 (void) fprintf(stderr
, "\n");
436 /* XXX: make this efficient */
437 for (n
= 0; n
< len
; ++n
) {
442 !__ops_stacked_write("- ", 2, errors
, writer
)) {
447 dash
->seen_nl
= src
[n
] == '\n';
449 if (dash
->seen_nl
&& !dash
->seen_cr
) {
450 if (!__ops_stacked_write("\r", 1, errors
, writer
)) {
453 __ops_sig_add_data(dash
->sig
, "\r", 1);
455 dash
->seen_cr
= src
[n
] == '\r';
457 if (!__ops_stacked_write(&src
[n
], 1, errors
, writer
)) {
461 /* trailing whitespace isn't included in the signature */
462 if (src
[n
] == ' ' || src
[n
] == '\t') {
463 __ops_memory_add(dash
->trailing
, &src
[n
], 1);
465 if ((l
= __ops_mem_len(dash
->trailing
)) != 0) {
466 if (!dash
->seen_nl
&& !dash
->seen_cr
) {
467 __ops_sig_add_data(dash
->sig
,
468 __ops_mem_data(dash
->trailing
), l
);
470 __ops_memory_clear(dash
->trailing
);
472 __ops_sig_add_data(dash
->sig
, &src
[n
], 1);
482 dash_escaped_destroyer(__ops_writer_t
*writer
)
486 dash
= __ops_writer_get_arg(writer
);
487 __ops_memory_free(dash
->trailing
);
492 * \ingroup Core_WritersNext
493 * \brief Push Clearsigned Writer onto stack
498 __ops_writer_push_clearsigned(__ops_output_t
*output
, __ops_create_sig_t
*sig
)
500 static const char header
[] =
501 "-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: ";
506 hash
= __ops_text_from_hash(__ops_sig_get_hash(sig
));
507 if ((dash
= calloc(1, sizeof(*dash
))) == NULL
) {
508 OPS_ERROR(&output
->errors
, OPS_E_W
, "Bad alloc");
511 ret
= (__ops_write(output
, header
, sizeof(header
) - 1) &&
512 __ops_write(output
, hash
, strlen(hash
)) &&
513 __ops_write(output
, "\r\n\r\n", 4));
516 OPS_ERROR(&output
->errors
, OPS_E_W
,
517 "Error pushing clearsigned header");
523 dash
->trailing
= __ops_memory_new();
524 __ops_writer_push(output
, dash_esc_writer
, NULL
,
525 dash_escaped_destroyer
, dash
);
539 static const char b64map
[] =
540 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
543 base64_writer(const unsigned char *src
,
545 __ops_error_t
**errors
,
546 __ops_writer_t
*writer
)
548 base64_t
*base64
= __ops_writer_get_arg(writer
);
551 for (n
= 0; n
< len
;) {
552 base64
->checksum
= __ops_crc24(base64
->checksum
, src
[n
]);
553 if (base64
->pos
== 0) {
554 /* XXXXXX00 00000000 00000000 */
555 if (!__ops_stacked_write(&b64map
[(unsigned)src
[n
] >> 2],
556 1, errors
, writer
)) {
560 /* 000000XX xxxx0000 00000000 */
561 base64
->t
= (src
[n
++] & 3) << 4;
563 } else if (base64
->pos
== 1) {
564 /* 000000xx XXXX0000 00000000 */
565 base64
->t
+= (unsigned)src
[n
] >> 4;
566 if (!__ops_stacked_write(&b64map
[base64
->t
], 1,
571 /* 00000000 0000XXXX xx000000 */
572 base64
->t
= (src
[n
++] & 0xf) << 2;
574 } else if (base64
->pos
== 2) {
575 /* 00000000 0000xxxx XX000000 */
576 base64
->t
+= (unsigned)src
[n
] >> 6;
577 if (!__ops_stacked_write(&b64map
[base64
->t
], 1,
582 /* 00000000 00000000 00XXXXXX */
583 if (!__ops_stacked_write(&b64map
[src
[n
++] & 0x3f], 1,
596 sig_finaliser(__ops_error_t
**errors
, __ops_writer_t
*writer
)
598 static const char trail
[] = "\r\n-----END PGP SIGNATURE-----\r\n";
602 base64
= __ops_writer_get_arg(writer
);
604 if (!__ops_stacked_write(&b64map
[base64
->t
], 1, errors
,
608 if (base64
->pos
== 1 &&
609 !__ops_stacked_write("==", 2, errors
, writer
)) {
612 if (base64
->pos
== 2 &&
613 !__ops_stacked_write("=", 1, errors
, writer
)) {
617 /* Ready for the checksum */
618 if (!__ops_stacked_write("\r\n=", 3, errors
, writer
)) {
622 base64
->pos
= 0; /* get ready to write the checksum */
624 c
[0] = base64
->checksum
>> 16;
625 c
[1] = base64
->checksum
>> 8;
626 c
[2] = base64
->checksum
;
627 /* push the checksum through our own writer */
628 if (!base64_writer(c
, 3, errors
, writer
)) {
632 return __ops_stacked_write(trail
, sizeof(trail
) - 1, errors
, writer
);
636 * \struct linebreak_t
645 linebreak_writer(const unsigned char *src
,
647 __ops_error_t
** errors
,
648 __ops_writer_t
* writer
)
650 linebreak_t
*linebreak
= __ops_writer_get_arg(writer
);
653 for (n
= 0; n
< len
; ++n
, ++linebreak
->pos
) {
654 if (src
[n
] == '\r' || src
[n
] == '\n') {
657 if (linebreak
->pos
== BREAKPOS
) {
658 if (!__ops_stacked_write("\r\n", 2, errors
, writer
)) {
663 if (!__ops_stacked_write(&src
[n
], 1, errors
, writer
)) {
672 * \ingroup Core_WritersNext
673 * \brief Push armoured signature on stack
677 __ops_writer_use_armored_sig(__ops_output_t
*output
)
679 static const char header
[] =
680 "\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: "
681 NETPGP_VERSION_STRING
683 linebreak_t
*linebreak
;
686 __ops_writer_pop(output
);
687 if (__ops_write(output
, header
, sizeof(header
) - 1) == 0) {
688 OPS_ERROR(&output
->errors
, OPS_E_W
,
689 "Error switching to armoured signature");
692 if ((linebreak
= calloc(1, sizeof(*linebreak
))) == NULL
) {
693 OPS_ERROR(&output
->errors
, OPS_E_W
,
694 "__ops_writer_use_armored_sig: Bad alloc");
697 __ops_writer_push(output
, linebreak_writer
, NULL
,
700 base64
= calloc(1, sizeof(*base64
));
702 OPS_MEMORY_ERROR(&output
->errors
);
705 base64
->checksum
= CRC24_INIT
;
706 __ops_writer_push(output
, base64_writer
, sig_finaliser
,
707 generic_destroyer
, base64
);
712 armoured_message_finaliser(__ops_error_t
**errors
, __ops_writer_t
*writer
)
714 /* TODO: This is same as sig_finaliser apart from trailer. */
715 static const char *trailer
= "\r\n-----END PGP MESSAGE-----\r\n";
719 base64
= __ops_writer_get_arg(writer
);
721 if (!__ops_stacked_write(&b64map
[base64
->t
], 1, errors
,
725 if (base64
->pos
== 1 &&
726 !__ops_stacked_write("==", 2, errors
, writer
)) {
729 if (base64
->pos
== 2 &&
730 !__ops_stacked_write("=", 1, errors
, writer
)) {
734 /* Ready for the checksum */
735 if (!__ops_stacked_write("\r\n=", 3, errors
, writer
)) {
739 base64
->pos
= 0; /* get ready to write the checksum */
741 c
[0] = base64
->checksum
>> 16;
742 c
[1] = base64
->checksum
>> 8;
743 c
[2] = base64
->checksum
;
744 /* push the checksum through our own writer */
745 if (!base64_writer(c
, 3, errors
, writer
)) {
749 return __ops_stacked_write(trailer
, strlen(trailer
), errors
, writer
);
753 \ingroup Core_WritersNext
754 \brief Write a PGP MESSAGE
755 \todo replace with generic function
758 __ops_writer_push_armor_msg(__ops_output_t
*output
)
760 static const char header
[] = "-----BEGIN PGP MESSAGE-----\r\n";
761 linebreak_t
*linebreak
;
764 __ops_write(output
, header
, sizeof(header
) - 1);
765 __ops_write(output
, "\r\n", 2);
766 if ((linebreak
= calloc(1, sizeof(*linebreak
))) == NULL
) {
767 (void) fprintf(stderr
,
768 "__ops_writer_push_armor_msg: bad lb alloc\n");
771 __ops_writer_push(output
, linebreak_writer
, NULL
,
774 if ((base64
= calloc(1, sizeof(*base64
))) == NULL
) {
775 (void) fprintf(stderr
,
776 "__ops_writer_push_armor_msg: bad alloc\n");
779 base64
->checksum
= CRC24_INIT
;
780 __ops_writer_push(output
, base64_writer
,
781 armoured_message_finaliser
, generic_destroyer
,
786 armoured_finaliser(__ops_armor_type_t type
,
787 __ops_error_t
**errors
,
788 __ops_writer_t
*writer
)
790 static const char tail_pubkey
[] =
791 "\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n";
792 static const char tail_private_key
[] =
793 "\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n";
795 unsigned int sz_tail
= 0;
796 const char *tail
= NULL
;
800 case OPS_PGP_PUBLIC_KEY_BLOCK
:
802 sz_tail
= sizeof(tail_pubkey
) - 1;
805 case OPS_PGP_PRIVATE_KEY_BLOCK
:
806 tail
= tail_private_key
;
807 sz_tail
= sizeof(tail_private_key
) - 1;
811 (void) fprintf(stderr
, "armoured_finaliser: unusual type\n");
814 base64
= __ops_writer_get_arg(writer
);
816 if (!__ops_stacked_write(&b64map
[base64
->t
], 1, errors
,
820 if (base64
->pos
== 1 && !__ops_stacked_write("==", 2, errors
,
824 if (base64
->pos
== 2 && !__ops_stacked_write("=", 1, errors
,
829 /* Ready for the checksum */
830 if (!__ops_stacked_write("\r\n=", 3, errors
, writer
)) {
833 base64
->pos
= 0; /* get ready to write the checksum */
834 c
[0] = base64
->checksum
>> 16;
835 c
[1] = base64
->checksum
>> 8;
836 c
[2] = base64
->checksum
;
837 /* push the checksum through our own writer */
838 if (!base64_writer(c
, 3, errors
, writer
)) {
841 return __ops_stacked_write(tail
, sz_tail
, errors
, writer
);
845 armored_pubkey_fini(__ops_error_t
**errors
, __ops_writer_t
*writer
)
847 return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK
, errors
, writer
);
851 armored_privkey_fini(__ops_error_t
**errors
, __ops_writer_t
*writer
)
853 return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK
, errors
, writer
);
856 /* \todo use this for other armoured types */
858 \ingroup Core_WritersNext
859 \brief Push Armoured Writer on stack (generic)
862 __ops_writer_push_armoured(__ops_output_t
*output
, __ops_armor_type_t type
)
864 static char hdr_pubkey
[] =
865 "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: "
866 NETPGP_VERSION_STRING
868 static char hdr_private_key
[] =
869 "-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: "
870 NETPGP_VERSION_STRING
872 unsigned int sz_hdr
= 0;
873 unsigned (*finaliser
) (__ops_error_t
**, __ops_writer_t
*);
875 linebreak_t
*linebreak
;
880 case OPS_PGP_PUBLIC_KEY_BLOCK
:
882 sz_hdr
= sizeof(hdr_pubkey
) - 1;
883 finaliser
= armored_pubkey_fini
;
886 case OPS_PGP_PRIVATE_KEY_BLOCK
:
887 header
= hdr_private_key
;
888 sz_hdr
= sizeof(hdr_private_key
) - 1;
889 finaliser
= armored_privkey_fini
;
893 (void) fprintf(stderr
,
894 "__ops_writer_push_armoured: unusual type\n");
897 if ((linebreak
= calloc(1, sizeof(*linebreak
))) == NULL
) {
898 (void) fprintf(stderr
,
899 "__ops_writer_push_armoured: bad alloc\n");
902 __ops_write(output
, header
, sz_hdr
);
903 __ops_writer_push(output
, linebreak_writer
, NULL
,
906 if ((base64
= calloc(1, sizeof(*base64
))) == NULL
) {
907 (void) fprintf(stderr
,
908 "__ops_writer_push_armoured: bad alloc\n");
911 base64
->checksum
= CRC24_INIT
;
912 __ops_writer_push(output
, base64_writer
, finaliser
,
913 generic_destroyer
, base64
);
916 /**************************************************************************/
919 __ops_crypt_t
*crypt
;
924 * This writer simply takes plaintext as input,
925 * encrypts it with the given key
926 * and outputs the resulting encrypted text
929 encrypt_writer(const unsigned char *src
,
931 __ops_error_t
**errors
,
932 __ops_writer_t
*writer
)
934 #define BUFSZ 1024 /* arbitrary number */
935 unsigned char encbuf
[BUFSZ
];
938 crypt_t
*pgp_encrypt
;
941 pgp_encrypt
= (crypt_t
*) __ops_writer_get_arg(writer
);
942 if (!__ops_is_sa_supported(pgp_encrypt
->crypt
->alg
)) {
943 (void) fprintf(stderr
, "encrypt_writer: not supported\n");
946 while (remaining
> 0) {
947 unsigned size
= (remaining
< BUFSZ
) ? remaining
: BUFSZ
;
949 /* memcpy(buf,src,size); // \todo copy needed here? */
950 pgp_encrypt
->crypt
->cfb_encrypt(pgp_encrypt
->crypt
, encbuf
,
953 if (__ops_get_debug_level(__FILE__
)) {
956 (void) fprintf(stderr
, "WRITING:\nunencrypted: ");
957 for (i
= 0; i
< 16; i
++) {
958 (void) fprintf(stderr
, "%2x ", src
[done
+ i
]);
960 (void) fprintf(stderr
, "\nencrypted: ");
961 for (i
= 0; i
< 16; i
++) {
962 (void) fprintf(stderr
, "%2x ", encbuf
[i
]);
964 (void) fprintf(stderr
, "\n");
966 if (!__ops_stacked_write(encbuf
, size
, errors
, writer
)) {
967 if (__ops_get_debug_level(__FILE__
)) {
969 "encrypted_writer: stacked write\n");
981 encrypt_destroyer(__ops_writer_t
*writer
)
983 crypt_t
*pgp_encrypt
= (crypt_t
*) __ops_writer_get_arg(writer
);
985 if (pgp_encrypt
->free_crypt
) {
986 free(pgp_encrypt
->crypt
);
992 \ingroup Core_WritersNext
993 \brief Push Encrypted Writer onto stack (create SE packets)
996 __ops_push_enc_crypt(__ops_output_t
*output
, __ops_crypt_t
*pgp_crypt
)
998 /* Create encrypt to be used with this writer */
999 /* Remember to free this in the destroyer */
1000 crypt_t
*pgp_encrypt
;
1002 if ((pgp_encrypt
= calloc(1, sizeof(*pgp_encrypt
))) == NULL
) {
1003 (void) fprintf(stderr
, "__ops_push_enc_crypt: bad alloc\n");
1005 /* Setup the encrypt */
1006 pgp_encrypt
->crypt
= pgp_crypt
;
1007 pgp_encrypt
->free_crypt
= 0;
1008 /* And push writer on stack */
1009 __ops_writer_push(output
, encrypt_writer
, NULL
,
1010 encrypt_destroyer
, pgp_encrypt
);
1014 /**************************************************************************/
1017 __ops_crypt_t
*crypt
;
1020 static unsigned encrypt_se_ip_writer(const unsigned char *,
1024 static void encrypt_se_ip_destroyer(__ops_writer_t
*);
1029 \ingroup Core_WritersNext
1030 \brief Push Encrypted SE IP Writer onto stack
1033 __ops_push_enc_se_ip(__ops_output_t
*output
, const __ops_key_t
*pubkey
)
1036 __ops_crypt_t
*encrypted
;
1037 /* Create se_ip to be used with this writer */
1038 /* Remember to free this in the destroyer */
1039 encrypt_se_ip_t
*se_ip
;
1040 __ops_pk_sesskey_t
*encrypted_pk_sesskey
;
1042 if ((se_ip
= calloc(1, sizeof(*se_ip
))) == NULL
) {
1043 (void) fprintf(stderr
, "__ops_push_enc_se_ip: bad alloc\n");
1047 /* Create and write encrypted PK session key */
1048 encrypted_pk_sesskey
= __ops_create_pk_sesskey(pubkey
);
1049 __ops_write_pk_sesskey(output
, encrypted_pk_sesskey
);
1051 /* Setup the se_ip */
1052 if ((encrypted
= calloc(1, sizeof(*encrypted
))) == NULL
) {
1054 (void) fprintf(stderr
, "__ops_push_enc_se_ip: bad alloc\n");
1057 __ops_crypt_any(encrypted
, encrypted_pk_sesskey
->symm_alg
);
1058 if ((iv
= calloc(1, encrypted
->blocksize
)) == NULL
) {
1061 (void) fprintf(stderr
, "__ops_push_enc_se_ip: bad alloc\n");
1064 encrypted
->set_iv(encrypted
, iv
);
1065 encrypted
->set_crypt_key(encrypted
, &encrypted_pk_sesskey
->key
[0]);
1066 __ops_encrypt_init(encrypted
);
1068 se_ip
->crypt
= encrypted
;
1070 /* And push writer on stack */
1071 __ops_writer_push(output
, encrypt_se_ip_writer
, NULL
,
1072 encrypt_se_ip_destroyer
, se_ip
);
1074 free(encrypted_pk_sesskey
);
1079 encrypt_se_ip_writer(const unsigned char *src
,
1081 __ops_error_t
**errors
,
1082 __ops_writer_t
*writer
)
1084 const unsigned int bufsz
= 128;
1085 encrypt_se_ip_t
*se_ip
= __ops_writer_get_arg(writer
);
1086 __ops_output_t
*litoutput
;
1087 __ops_output_t
*zoutput
;
1088 __ops_output_t
*output
;
1089 __ops_memory_t
*litmem
;
1090 __ops_memory_t
*zmem
;
1091 __ops_memory_t
*localmem
;
1094 __ops_setup_memory_write(&litoutput
, &litmem
, bufsz
);
1095 __ops_setup_memory_write(&zoutput
, &zmem
, bufsz
);
1096 __ops_setup_memory_write(&output
, &localmem
, bufsz
);
1098 /* create literal data packet from source data */
1099 __ops_write_litdata(litoutput
, src
, (const int)len
, OPS_LDT_BINARY
);
1100 if (__ops_mem_len(litmem
) <= len
) {
1101 (void) fprintf(stderr
, "encrypt_se_ip_writer: bad len\n");
1105 /* create compressed packet from literal data packet */
1106 __ops_writez(__ops_mem_data(litmem
), __ops_mem_len(litmem
), zoutput
);
1108 /* create SE IP packet set from this compressed literal data */
1109 __ops_write_se_ip_pktset(__ops_mem_data(zmem
),
1110 __ops_mem_len(zmem
),
1111 se_ip
->crypt
, output
);
1112 if (__ops_mem_len(localmem
) <= __ops_mem_len(zmem
)) {
1113 (void) fprintf(stderr
,
1114 "encrypt_se_ip_writer: bad comp len\n");
1118 /* now write memory to next writer */
1119 ret
= __ops_stacked_write(__ops_mem_data(localmem
),
1120 __ops_mem_len(localmem
),
1123 __ops_memory_free(localmem
);
1124 __ops_memory_free(zmem
);
1125 __ops_memory_free(litmem
);
1131 encrypt_se_ip_destroyer(__ops_writer_t
*writer
)
1133 encrypt_se_ip_t
*se_ip
;
1135 se_ip
= __ops_writer_get_arg(writer
);
1141 __ops_write_se_ip_pktset(const unsigned char *data
,
1142 const unsigned int len
,
1143 __ops_crypt_t
*crypted
,
1144 __ops_output_t
*output
)
1146 __ops_output_t
*mdcoutput
;
1147 __ops_memory_t
*mdc
;
1148 unsigned char hashed
[OPS_SHA1_HASH_SIZE
];
1149 unsigned char *preamble
;
1150 const size_t sz_mdc
= 1 + 1 + OPS_SHA1_HASH_SIZE
;
1154 sz_preamble
= crypted
->blocksize
+ 2;
1155 if ((preamble
= calloc(1, sz_preamble
)) == NULL
) {
1156 (void) fprintf(stderr
, "__ops_write_se_ip_pktset: bad alloc\n");
1159 sz_buf
= sz_preamble
+ len
+ sz_mdc
;
1161 if (!__ops_write_ptag(output
, OPS_PTAG_CT_SE_IP_DATA
) ||
1162 !__ops_write_length(output
, 1 + sz_buf
) ||
1163 !__ops_write_scalar(output
, SE_IP_DATA_VERSION
, 1)) {
1167 __ops_random(preamble
, crypted
->blocksize
);
1168 preamble
[crypted
->blocksize
] = preamble
[crypted
->blocksize
- 2];
1169 preamble
[crypted
->blocksize
+ 1] = preamble
[crypted
->blocksize
- 1];
1171 if (__ops_get_debug_level(__FILE__
)) {
1174 fprintf(stderr
, "\npreamble: ");
1175 for (i
= 0; i
< sz_preamble
; i
++) {
1176 fprintf(stderr
, " 0x%02x", preamble
[i
]);
1178 fprintf(stderr
, "\n");
1181 /* now construct MDC packet and add to the end of the buffer */
1182 __ops_setup_memory_write(&mdcoutput
, &mdc
, sz_mdc
);
1183 __ops_calc_mdc_hash(preamble
, sz_preamble
, data
, len
, &hashed
[0]);
1184 __ops_write_mdc(hashed
, mdcoutput
);
1186 if (__ops_get_debug_level(__FILE__
)) {
1188 size_t sz_plaintext
= len
;
1189 size_t sz_mdc2
= 1 + 1 + OPS_SHA1_HASH_SIZE
;
1190 unsigned char *digest
;
1192 (void) fprintf(stderr
, "\nplaintext: ");
1193 for (i
= 0; i
< sz_plaintext
; i
++) {
1194 (void) fprintf(stderr
, " 0x%02x", data
[i
]);
1196 (void) fprintf(stderr
, "\n");
1198 (void) fprintf(stderr
, "\nmdc: ");
1199 digest
= __ops_mem_data(mdc
);
1200 for (i
= 0; i
< sz_mdc2
; i
++) {
1201 (void) fprintf(stderr
, " 0x%02x", digest
[i
]);
1203 (void) fprintf(stderr
, "\n");
1206 /* and write it out */
1207 __ops_push_enc_crypt(output
, crypted
);
1208 if (__ops_get_debug_level(__FILE__
)) {
1209 (void) fprintf(stderr
,
1210 "writing %" PRIsize
"u + %u + %" PRIsize
"u\n",
1211 sz_preamble
, len
, __ops_mem_len(mdc
));
1213 if (!__ops_write(output
, preamble
, sz_preamble
) ||
1214 !__ops_write(output
, data
, len
) ||
1215 !__ops_write(output
, __ops_mem_data(mdc
), __ops_mem_len(mdc
))) {
1216 /* \todo fix cleanup here and in old code functions */
1220 __ops_writer_pop(output
);
1223 __ops_teardown_memory_write(mdcoutput
, mdc
);
1234 fd_writer(const unsigned char *src
, unsigned len
,
1235 __ops_error_t
**errors
,
1236 __ops_writer_t
*writer
)
1238 writer_fd_t
*writerfd
;
1241 writerfd
= __ops_writer_get_arg(writer
);
1242 n
= write(writerfd
->fd
, src
, len
);
1244 OPS_SYSTEM_ERROR_1(errors
, OPS_E_W_WRITE_FAILED
, "write",
1245 "file descriptor %d", writerfd
->fd
);
1248 if ((unsigned) n
!= len
) {
1249 OPS_ERROR_1(errors
, OPS_E_W_WRITE_TOO_SHORT
,
1250 "file descriptor %d", writerfd
->fd
);
1257 writer_fd_destroyer(__ops_writer_t
*writer
)
1259 free(__ops_writer_get_arg(writer
));
1263 * \ingroup Core_WritersFirst
1264 * \brief Write to a File
1266 * Set the writer in output to be a stock writer that writes to a file
1267 * descriptor. If another writer has already been set, then that is
1270 * \param output The output structure
1271 * \param fd The file descriptor
1276 __ops_writer_set_fd(__ops_output_t
*output
, int fd
)
1278 writer_fd_t
*writer
;
1280 if ((writer
= calloc(1, sizeof(*writer
))) == NULL
) {
1281 (void) fprintf(stderr
, "__ops_writer_set_fd: bad alloc\n");
1284 __ops_writer_set(output
, fd_writer
, NULL
, writer_fd_destroyer
, writer
);
1289 memory_writer(const unsigned char *src
,
1291 __ops_error_t
**errors
,
1292 __ops_writer_t
*writer
)
1294 __ops_memory_t
*mem
;
1297 mem
= __ops_writer_get_arg(writer
);
1298 __ops_memory_add(mem
, src
, len
);
1303 * \ingroup Core_WritersFirst
1304 * \brief Write to memory
1306 * Set a memory writer.
1308 * \param output The output structure
1309 * \param mem The memory structure
1310 * \note It is the caller's responsiblity to call __ops_memory_free(mem)
1311 * \sa __ops_memory_free()
1315 __ops_writer_set_memory(__ops_output_t
*output
, __ops_memory_t
*mem
)
1317 __ops_writer_set(output
, memory_writer
, NULL
, NULL
, mem
);
1320 /**************************************************************************/
1323 __ops_hash_alg_t hash_alg
;
1325 unsigned char *hashed
;
1329 skey_checksum_writer(const unsigned char *src
,
1331 __ops_error_t
**errors
,
1332 __ops_writer_t
*writer
)
1334 skey_checksum_t
*sum
;
1337 sum
= __ops_writer_get_arg(writer
);
1338 /* add contents to hash */
1339 sum
->hash
.add(&sum
->hash
, src
, len
);
1340 /* write to next stacked writer */
1341 ret
= __ops_stacked_write(src
, len
, errors
, writer
);
1342 /* tidy up and return */
1347 skey_checksum_finaliser(__ops_error_t
**errors
, __ops_writer_t
*writer
)
1349 skey_checksum_t
*sum
;
1351 sum
= __ops_writer_get_arg(writer
);
1353 printf("errors in skey_checksum_finaliser\n");
1355 sum
->hash
.finish(&sum
->hash
, sum
->hashed
);
1360 skey_checksum_destroyer(__ops_writer_t
*writer
)
1362 skey_checksum_t
*sum
;
1364 sum
= __ops_writer_get_arg(writer
);
1369 \ingroup Core_WritersNext
1374 __ops_push_checksum_writer(__ops_output_t
*output
, __ops_seckey_t
*seckey
)
1376 /* XXX: push a SHA-1 checksum writer (and change s2k to 254). */
1377 skey_checksum_t
*sum
;
1379 if ((sum
= calloc(1, sizeof(*sum
))) == NULL
) {
1380 (void) fprintf(stderr
, "__ops_push_checksum_writer: bad alloc\n");
1382 /* configure the arg */
1383 sum
->hash_alg
= seckey
->hash_alg
;
1384 sum
->hashed
= seckey
->checkhash
;
1386 __ops_hash_any(&sum
->hash
, sum
->hash_alg
);
1387 if (!sum
->hash
.init(&sum
->hash
)) {
1388 (void) fprintf(stderr
,
1389 "__ops_push_checksum_writer: bad hash init\n");
1390 /* just continue and die */
1391 /* XXX - agc - no way to return failure */
1393 __ops_writer_push(output
, skey_checksum_writer
,
1394 skey_checksum_finaliser
, skey_checksum_destroyer
, sum
);
1398 /**************************************************************************/
1400 #define MAX_PARTIAL_DATA_LENGTH 1073741824
1403 __ops_crypt_t
*crypt
;
1404 __ops_memory_t
*mem_data
;
1405 __ops_memory_t
*litmem
;
1406 __ops_output_t
*litoutput
;
1407 __ops_memory_t
*se_ip_mem
;
1408 __ops_output_t
*se_ip_out
;
1414 str_enc_se_ip_writer(const unsigned char *src
,
1416 __ops_error_t
**errors
,
1417 __ops_writer_t
*writer
);
1420 str_enc_se_ip_finaliser(__ops_error_t
**errors
,
1421 __ops_writer_t
* writer
);
1423 static void str_enc_se_ip_destroyer(__ops_writer_t
*writer
);
1428 \ingroup Core_WritersNext
1433 __ops_push_stream_enc_se_ip(__ops_output_t
*output
, const __ops_key_t
*pubkey
)
1435 __ops_pk_sesskey_t
*encrypted_pk_sesskey
;
1436 const unsigned int bufsz
= 1024;
1437 str_enc_se_ip_t
*se_ip
;
1438 __ops_crypt_t
*encrypted
;
1441 if ((se_ip
= calloc(1, sizeof(*se_ip
))) == NULL
) {
1442 (void) fprintf(stderr
,
1443 "__ops_push_stream_enc_se_ip: bad alloc\n");
1446 encrypted_pk_sesskey
= __ops_create_pk_sesskey(pubkey
);
1447 __ops_write_pk_sesskey(output
, encrypted_pk_sesskey
);
1449 /* Setup the se_ip */
1450 if ((encrypted
= calloc(1, sizeof(*encrypted
))) == NULL
) {
1452 (void) fprintf(stderr
,
1453 "__ops_push_stream_enc_se_ip: bad alloc\n");
1456 __ops_crypt_any(encrypted
, encrypted_pk_sesskey
->symm_alg
);
1457 if ((iv
= calloc(1, encrypted
->blocksize
)) == NULL
) {
1460 (void) fprintf(stderr
,
1461 "__ops_push_stream_enc_se_ip: bad alloc\n");
1464 encrypted
->set_iv(encrypted
, iv
);
1465 encrypted
->set_crypt_key(encrypted
, &encrypted_pk_sesskey
->key
[0]);
1466 __ops_encrypt_init(encrypted
);
1468 se_ip
->crypt
= encrypted
;
1470 se_ip
->mem_data
= __ops_memory_new();
1471 __ops_memory_init(se_ip
->mem_data
, bufsz
);
1473 se_ip
->litmem
= NULL
;
1474 se_ip
->litoutput
= NULL
;
1476 __ops_setup_memory_write(&se_ip
->se_ip_out
, &se_ip
->se_ip_mem
, bufsz
);
1478 /* And push writer on stack */
1479 __ops_writer_push(output
,
1480 str_enc_se_ip_writer
,
1481 str_enc_se_ip_finaliser
,
1482 str_enc_se_ip_destroyer
, se_ip
);
1484 free(encrypted_pk_sesskey
);
1489 /* calculate the partial data length */
1491 __ops_partial_data_len(unsigned int len
)
1493 unsigned int mask
= MAX_PARTIAL_DATA_LENGTH
;
1497 (void) fprintf(stderr
, "__ops_partial_data_len: 0 len\n");
1500 if (len
> MAX_PARTIAL_DATA_LENGTH
) {
1501 return MAX_PARTIAL_DATA_LENGTH
;
1503 for (i
= 0; i
<= 30; i
++) {
1513 __ops_write_partial_len(unsigned int len
, __ops_output_t
*output
)
1515 /* len must be a power of 2 from 0 to 30 */
1519 for (i
= 0; i
<= 30; i
++) {
1520 if ((len
>> i
) & 1) {
1525 return __ops_write(output
, &c
, 1);
1529 stream_write_litdata(__ops_output_t
*output
,
1530 const unsigned char *data
,
1534 size_t pdlen
= __ops_partial_data_len(len
);
1536 __ops_write_partial_len(pdlen
, output
);
1537 __ops_write(output
, data
, pdlen
);
1545 stream_write_litdata_first(__ops_output_t
*output
,
1546 const unsigned char *data
,
1548 const __ops_litdata_type_t type
)
1550 /* \todo add filename */
1551 /* \todo add date */
1552 /* \todo do we need to check text data for <cr><lf> line endings ? */
1557 sz_towrite
= 1 + 1 + 4 + len
;
1558 sz_pd
= __ops_partial_data_len(sz_towrite
);
1560 (void) fprintf(stderr
,
1561 "stream_write_litdata_first: bad sz_pd\n");
1564 __ops_write_ptag(output
, OPS_PTAG_CT_LITDATA
);
1565 __ops_write_partial_len(sz_pd
, output
);
1566 __ops_write_scalar(output
, (unsigned)type
, 1);
1567 __ops_write_scalar(output
, 0, 1);
1568 __ops_write_scalar(output
, 0, 4);
1569 __ops_write(output
, data
, sz_pd
- 6);
1571 data
+= (sz_pd
- 6);
1572 sz_towrite
-= sz_pd
;
1574 return stream_write_litdata(output
, data
, sz_towrite
);
1578 stream_write_litdata_last(__ops_output_t
*output
,
1579 const unsigned char *data
,
1582 __ops_write_length(output
, len
);
1583 return __ops_write(output
, data
, len
);
1587 stream_write_se_ip(__ops_output_t
*output
,
1588 const unsigned char *data
,
1590 str_enc_se_ip_t
*se_ip
)
1595 pdlen
= __ops_partial_data_len(len
);
1596 __ops_write_partial_len(pdlen
, output
);
1598 __ops_push_enc_crypt(output
, se_ip
->crypt
);
1599 __ops_write(output
, data
, pdlen
);
1600 __ops_writer_pop(output
);
1602 se_ip
->hash
.add(&se_ip
->hash
, data
, pdlen
);
1611 stream_write_se_ip_first(__ops_output_t
*output
,
1612 const unsigned char *data
,
1614 str_enc_se_ip_t
*se_ip
)
1616 unsigned char *preamble
;
1622 blocksize
= se_ip
->crypt
->blocksize
;
1623 sz_preamble
= blocksize
+ 2;
1624 sz_towrite
= sz_preamble
+ 1 + len
;
1625 if ((preamble
= calloc(1, sz_preamble
)) == NULL
) {
1626 (void) fprintf(stderr
,
1627 "stream_write_se_ip_first: bad alloc\n");
1630 sz_pd
= __ops_partial_data_len(sz_towrite
);
1633 (void) fprintf(stderr
,
1634 "stream_write_se_ip_first: bad sz_pd\n");
1637 __ops_write_ptag(output
, OPS_PTAG_CT_SE_IP_DATA
);
1638 __ops_write_partial_len(sz_pd
, output
);
1639 __ops_write_scalar(output
, SE_IP_DATA_VERSION
, 1);
1640 __ops_push_enc_crypt(output
, se_ip
->crypt
);
1642 __ops_random(preamble
, blocksize
);
1643 preamble
[blocksize
] = preamble
[blocksize
- 2];
1644 preamble
[blocksize
+ 1] = preamble
[blocksize
- 1];
1645 __ops_hash_any(&se_ip
->hash
, OPS_HASH_SHA1
);
1646 if (!se_ip
->hash
.init(&se_ip
->hash
)) {
1648 (void) fprintf(stderr
,
1649 "stream_write_se_ip_first: bad hash init\n");
1652 __ops_write(output
, preamble
, sz_preamble
);
1653 se_ip
->hash
.add(&se_ip
->hash
, preamble
, sz_preamble
);
1654 __ops_write(output
, data
, sz_pd
- sz_preamble
- 1);
1655 se_ip
->hash
.add(&se_ip
->hash
, data
, sz_pd
- sz_preamble
- 1);
1656 data
+= (sz_pd
- sz_preamble
- 1);
1657 sz_towrite
-= sz_pd
;
1658 __ops_writer_pop(output
);
1659 stream_write_se_ip(output
, data
, sz_towrite
, se_ip
);
1665 stream_write_se_ip_last(__ops_output_t
*output
,
1666 const unsigned char *data
,
1668 str_enc_se_ip_t
*se_ip
)
1670 __ops_output_t
*mdcoutput
;
1671 __ops_memory_t
*mdcmem
;
1673 unsigned char hashed
[OPS_SHA1_HASH_SIZE
];
1674 const size_t sz_mdc
= 1 + 1 + OPS_SHA1_HASH_SIZE
;
1675 size_t sz_buf
= len
+ sz_mdc
;
1677 se_ip
->hash
.add(&se_ip
->hash
, data
, len
);
1679 /* MDC packet tag */
1681 se_ip
->hash
.add(&se_ip
->hash
, &c
, 1);
1683 /* MDC packet len */
1684 c
= OPS_SHA1_HASH_SIZE
;
1685 se_ip
->hash
.add(&se_ip
->hash
, &c
, 1);
1688 se_ip
->hash
.finish(&se_ip
->hash
, hashed
);
1690 __ops_setup_memory_write(&mdcoutput
, &mdcmem
, sz_mdc
);
1691 __ops_write_mdc(hashed
, mdcoutput
);
1693 /* write length of last se_ip chunk */
1694 __ops_write_length(output
, sz_buf
);
1696 /* encode everting */
1697 __ops_push_enc_crypt(output
, se_ip
->crypt
);
1699 __ops_write(output
, data
, len
);
1700 __ops_write(output
, __ops_mem_data(mdcmem
), __ops_mem_len(mdcmem
));
1702 __ops_writer_pop(output
);
1704 __ops_teardown_memory_write(mdcoutput
, mdcmem
);
1710 str_enc_se_ip_writer(const unsigned char *src
,
1712 __ops_error_t
**errors
,
1713 __ops_writer_t
*writer
)
1715 str_enc_se_ip_t
*se_ip
= __ops_writer_get_arg(writer
);
1718 if (se_ip
->litoutput
== NULL
) { /* first literal data chunk
1719 * is not yet written */
1722 __ops_memory_add(se_ip
->mem_data
, src
, len
);
1723 datalength
= __ops_mem_len(se_ip
->mem_data
);
1725 /* 4.2.2.4. Partial Body Lengths */
1726 /* The first partial length MUST be at least 512 octets long. */
1727 if (datalength
< 512) {
1728 return 1; /* will wait for more data or
1731 __ops_setup_memory_write(&se_ip
->litoutput
,
1732 &se_ip
->litmem
, datalength
+ 32);
1733 stream_write_litdata_first(se_ip
->litoutput
,
1734 __ops_mem_data(se_ip
->mem_data
),
1738 stream_write_se_ip_first(se_ip
->se_ip_out
,
1739 __ops_mem_data(se_ip
->litmem
),
1740 __ops_mem_len(se_ip
->litmem
), se_ip
);
1742 stream_write_litdata(se_ip
->litoutput
, src
, len
);
1743 stream_write_se_ip(se_ip
->se_ip_out
,
1744 __ops_mem_data(se_ip
->litmem
),
1745 __ops_mem_len(se_ip
->litmem
), se_ip
);
1748 /* now write memory to next writer */
1749 ret
= __ops_stacked_write(__ops_mem_data(se_ip
->se_ip_mem
),
1750 __ops_mem_len(se_ip
->se_ip_mem
),
1753 __ops_memory_clear(se_ip
->litmem
);
1754 __ops_memory_clear(se_ip
->se_ip_mem
);
1760 str_enc_se_ip_finaliser(__ops_error_t
**errors
, __ops_writer_t
*writer
)
1762 str_enc_se_ip_t
*se_ip
= __ops_writer_get_arg(writer
);
1763 /* write last chunk of data */
1765 if (se_ip
->litoutput
== NULL
) {
1766 /* first literal data chunk was not written */
1767 /* so we know the total length of data, write a simple packet */
1769 /* create literal data packet from buffered data */
1770 __ops_setup_memory_write(&se_ip
->litoutput
, &se_ip
->litmem
,
1771 __ops_mem_len(se_ip
->mem_data
) + 32);
1773 __ops_write_litdata(se_ip
->litoutput
,
1774 __ops_mem_data(se_ip
->mem_data
),
1775 (const int)__ops_mem_len(se_ip
->mem_data
),
1778 /* create SE IP packet set from this literal data */
1779 __ops_write_se_ip_pktset(
1780 __ops_mem_data(se_ip
->litmem
),
1781 __ops_mem_len(se_ip
->litmem
),
1782 se_ip
->crypt
, se_ip
->se_ip_out
);
1785 /* finish writing */
1786 stream_write_litdata_last(se_ip
->litoutput
, NULL
, 0);
1787 stream_write_se_ip_last(se_ip
->se_ip_out
,
1788 __ops_mem_data(se_ip
->litmem
),
1789 __ops_mem_len(se_ip
->litmem
), se_ip
);
1792 /* now write memory to next writer */
1793 return __ops_stacked_write(__ops_mem_data(se_ip
->se_ip_mem
),
1794 __ops_mem_len(se_ip
->se_ip_mem
),
1799 str_enc_se_ip_destroyer(__ops_writer_t
*writer
)
1801 str_enc_se_ip_t
*se_ip
= __ops_writer_get_arg(writer
);
1803 __ops_memory_free(se_ip
->mem_data
);
1804 __ops_teardown_memory_write(se_ip
->litoutput
, se_ip
->litmem
);
1805 __ops_teardown_memory_write(se_ip
->se_ip_out
, se_ip
->se_ip_mem
);
1807 se_ip
->crypt
->decrypt_finish(se_ip
->crypt
);