summaryrefslogtreecommitdiffstats
path: root/src/tests/partial-length.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/partial-length.cpp')
-rw-r--r--src/tests/partial-length.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/tests/partial-length.cpp b/src/tests/partial-length.cpp
new file mode 100644
index 0000000..1e0b3cb
--- /dev/null
+++ b/src/tests/partial-length.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2017-2020 [Ribose Inc](https://www.ribose.com).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <fstream>
+#include <vector>
+#include <string>
+
+#include <rnp/rnp.h>
+#include "rnp_tests.h"
+#include "support.h"
+#include "librepgp/stream-common.h"
+#include "librepgp/stream-packet.h"
+#include "utils.h"
+#include <json.h>
+#include <vector>
+#include <string>
+
+// structure for filling input
+typedef struct {
+ uint32_t remaining;
+ uint8_t dummy;
+} dummy_reader_ctx_st;
+
+// reader of sequence of dummy bytes
+static bool
+dummy_reader(void *app_ctx, void *buf, size_t len, size_t *read)
+{
+ size_t filled = 0;
+ dummy_reader_ctx_st *ctx = NULL;
+ ctx = (dummy_reader_ctx_st *) app_ctx;
+ filled = (len > ctx->remaining) ? ctx->remaining : len;
+ if (filled > 0) {
+ memset(buf, ctx->dummy, filled);
+ ctx->remaining -= filled;
+ }
+ *read = filled;
+ return true;
+}
+
+static void
+test_partial_length_init(rnp_ffi_t *ffi, uint32_t key_flags)
+{
+ rnp_input_t input = NULL;
+ // init ffi
+ assert_rnp_success(rnp_ffi_create(ffi, "GPG", "GPG"));
+ assert_rnp_success(
+ rnp_ffi_set_pass_provider(*ffi, ffi_string_password_provider, (void *) "password"));
+ if (key_flags & RNP_LOAD_SAVE_SECRET_KEYS) {
+ assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/secring.gpg"));
+ assert_rnp_success(rnp_load_keys(*ffi, "GPG", input, key_flags));
+ assert_rnp_success(rnp_input_destroy(input));
+ }
+ if (key_flags & RNP_LOAD_SAVE_PUBLIC_KEYS) {
+ assert_rnp_success(rnp_input_from_path(&input, "data/keyrings/1/pubring.gpg"));
+ assert_rnp_success(rnp_load_keys(*ffi, "GPG", input, key_flags));
+ assert_rnp_success(rnp_input_destroy(input));
+ }
+}
+
+TEST_F(rnp_tests, test_partial_length_public_key)
+{
+ rnp_input_t input = NULL;
+ rnp_ffi_t ffi = NULL;
+ assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG"));
+ assert_rnp_success(
+ rnp_input_from_path(&input, "data/test_partial_length/pubring.gpg.partial"));
+ assert_int_equal(rnp_load_keys(ffi, "GPG", input, RNP_LOAD_SAVE_PUBLIC_KEYS),
+ RNP_ERROR_BAD_FORMAT);
+ assert_rnp_success(rnp_input_destroy(input));
+ assert_rnp_success(rnp_ffi_destroy(ffi));
+}
+
+TEST_F(rnp_tests, test_partial_length_signature)
+{
+ rnp_ffi_t ffi = NULL;
+ rnp_input_t input = NULL;
+ rnp_output_t output = NULL;
+ // init ffi
+ test_partial_length_init(&ffi, RNP_LOAD_SAVE_PUBLIC_KEYS);
+ // message having partial length signature packet
+ assert_rnp_success(
+ rnp_input_from_path(&input, "data/test_partial_length/message.txt.partial-signed"));
+ assert_rnp_success(rnp_output_to_null(&output));
+ rnp_op_verify_t verify = NULL;
+ assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
+ assert_rnp_failure(rnp_op_verify_execute(verify));
+ // cleanup
+ assert_rnp_success(rnp_op_verify_destroy(verify));
+ assert_rnp_success(rnp_input_destroy(input));
+ assert_rnp_success(rnp_output_destroy(output));
+ assert_rnp_success(rnp_ffi_destroy(ffi));
+}
+
+TEST_F(rnp_tests, test_partial_length_first_packet_256)
+{
+ rnp_ffi_t ffi = NULL;
+ rnp_input_t input = NULL;
+ rnp_output_t output = NULL;
+ // init ffi
+ test_partial_length_init(&ffi, RNP_LOAD_SAVE_PUBLIC_KEYS);
+ // message having first partial length packet of 256 bytes
+ assert_rnp_success(
+ rnp_input_from_path(&input, "data/test_partial_length/message.txt.partial-256"));
+ assert_rnp_success(rnp_output_to_null(&output));
+ rnp_op_verify_t verify = NULL;
+ assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
+ assert_rnp_success(rnp_op_verify_execute(verify));
+ // cleanup
+ assert_rnp_success(rnp_op_verify_destroy(verify));
+ assert_rnp_success(rnp_input_destroy(input));
+ assert_rnp_success(rnp_output_destroy(output));
+ assert_rnp_success(rnp_ffi_destroy(ffi));
+}
+
+TEST_F(rnp_tests, test_partial_length_zero_last_chunk)
+{
+ rnp_ffi_t ffi = NULL;
+ rnp_input_t input = NULL;
+ rnp_output_t output = NULL;
+ // init ffi
+ test_partial_length_init(&ffi, RNP_LOAD_SAVE_PUBLIC_KEYS);
+ // message in partial packets having 0-size last chunk
+ assert_rnp_success(
+ rnp_input_from_path(&input, "data/test_partial_length/message.txt.partial-zero-last"));
+ assert_rnp_success(rnp_output_to_null(&output));
+ rnp_op_verify_t verify = NULL;
+ assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
+ assert_rnp_success(rnp_op_verify_execute(verify));
+ // cleanup
+ assert_rnp_success(rnp_op_verify_destroy(verify));
+ assert_rnp_success(rnp_input_destroy(input));
+ assert_rnp_success(rnp_output_destroy(output));
+ assert_rnp_success(rnp_ffi_destroy(ffi));
+}
+
+TEST_F(rnp_tests, test_partial_length_largest)
+{
+ rnp_ffi_t ffi = NULL;
+ rnp_input_t input = NULL;
+ rnp_output_t output = NULL;
+ // init ffi
+ test_partial_length_init(&ffi, RNP_LOAD_SAVE_PUBLIC_KEYS);
+ // message having largest possible partial packet
+ assert_rnp_success(
+ rnp_input_from_path(&input, "data/test_partial_length/message.txt.partial-1g"));
+ assert_rnp_success(rnp_output_to_null(&output));
+ rnp_op_verify_t verify = NULL;
+ assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output));
+ assert_rnp_success(rnp_op_verify_execute(verify));
+ // cleanup
+ assert_rnp_success(rnp_op_verify_destroy(verify));
+ assert_rnp_success(rnp_input_destroy(input));
+ assert_rnp_success(rnp_output_destroy(output));
+ assert_rnp_success(rnp_ffi_destroy(ffi));
+}
+
+TEST_F(rnp_tests, test_partial_length_first_packet_length)
+{
+ rnp_ffi_t ffi = NULL;
+ rnp_input_t input = NULL;
+ rnp_output_t output = NULL;
+ rnp_op_sign_t sign = NULL;
+ rnp_key_handle_t key = NULL;
+ // uncacheable size will emulate unknown length from callback source
+ size_t uncacheable_size = PGP_INPUT_CACHE_SIZE + 1;
+ // init ffi
+ test_partial_length_init(&ffi, RNP_LOAD_SAVE_SECRET_KEYS);
+ // generate a sequence of octets with appropriate length using callback
+ dummy_reader_ctx_st reader_ctx;
+ reader_ctx.dummy = 'X';
+ reader_ctx.remaining = uncacheable_size;
+ assert_rnp_success(rnp_input_from_callback(&input, dummy_reader, NULL, &reader_ctx));
+ assert_rnp_success(rnp_output_to_memory(&output, uncacheable_size + 1024));
+ assert_rnp_success(rnp_op_sign_create(&sign, ffi, input, output));
+ assert_rnp_success(rnp_locate_key(ffi, "keyid", "7BC6709B15C23A4A", &key));
+ assert_rnp_success(rnp_op_sign_add_signature(sign, key, NULL));
+ assert_rnp_success(rnp_key_handle_destroy(key));
+ key = NULL;
+ // signing
+ assert_rnp_success(rnp_op_sign_execute(sign));
+ // read from the saved packets
+ pgp_source_t src;
+ uint8_t * mem = NULL;
+ size_t len = 0;
+ assert_rnp_success(rnp_output_memory_get_buf(output, &mem, &len, false));
+ assert_rnp_success(init_mem_src(&src, mem, len, false));
+ // skip first packet (one-pass signature)
+ pgp_packet_body_t body(PGP_PKT_ONE_PASS_SIG);
+ assert_rnp_success(body.read(src));
+ // checking next packet header (should be partial length literal data)
+ uint8_t flags = 0;
+ assert_true(src_read_eq(&src, &flags, 1));
+ assert_int_equal(flags, PGP_PTAG_ALWAYS_SET | PGP_PTAG_NEW_FORMAT | PGP_PKT_LITDATA);
+ // checking length
+ bool last = true; // should be reset by stream_read_partial_chunk_len()
+ assert_true(stream_read_partial_chunk_len(&src, &len, &last));
+ assert_true(len >= PGP_PARTIAL_PKT_FIRST_PART_MIN_SIZE);
+ assert_false(last);
+ // cleanup
+ src_close(&src);
+ assert_rnp_success(rnp_op_sign_destroy(sign));
+ assert_rnp_success(rnp_input_destroy(input));
+ assert_rnp_success(rnp_output_destroy(output));
+ assert_rnp_success(rnp_ffi_destroy(ffi));
+}