/
niceSOFT
/
dovecot
Обзор
Документация
Войти
/
niceSOFT
/
dovecot
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/lib-dcrypt/test-stream.c
789 строк
22 KB
Timo Sirainen
lib-dcrypt: Detect ML-KEM support at runtime instead of at build time
05 авг 2026, 17:44
05 авг 2026, 17:44
820b08f
Код
Авторство
О чём код?
/* Copyright (c) Dovecot authors, see top-level COPYING file */ #include "lib.h" #include "buffer.h" #include "str.h" #include "dcrypt.h" #include "dcrypt-iostream.h" #include "ostream.h" #include "ostream-encrypt.h" #include "istream.h" #include "istream-decrypt.h" #include "istream-hash.h" #include "istream-base64.h" #include "randgen.h" #include "hash-method.h" #include "test-common.h" #include "hex-binary.h" #include <fcntl.h> #include <sys/stat.h> #include <stdio.h> #include <openssl/evp.h> #if defined(NID_X25519) # define HAVE_X25519 #endif static const char key_v1_priv[] = "-----BEGIN PRIVATE KEY-----\n" "MIGpAgEAMBAGByqGSM49AgEGBSuBBAAjBIGRMIGOAgEBBEGz2V2VMi/5s+Z+GJh7\n" "4WfqZjZUpqqm+NJWojm6BbrZMY+9ZComlTGVcUZ007acFxV93oMmrfmtRUb5ynrb\n" "MRFskKFGA0QAAwHrAJc8TvyPzspOoz6UH1C1YRmaUVm8tsLu2d0dYtZeOKJUl52J\n" "4o8MKIg+ce4q0mTNFrhj+glKj29ppWti6JGAQA==\n" "-----END PRIVATE KEY-----"; static const char key_v1_pub[] = "-----BEGIN PUBLIC KEY-----\n" "MFgwEAYHKoZIzj0CAQYFK4EEACMDRAADAesAlzxO/I/Oyk6jPpQfULVhGZpRWby2\n" "wu7Z3R1i1l44olSXnYnijwwoiD5x7irSZM0WuGP6CUqPb2mla2LokYBA\n" "-----END PUBLIC KEY-----"; static const char key_v2_priv[] = "-----BEGIN PRIVATE KEY-----\n" "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgtuQJA+uboZWVwgHc\n" "DciyVdrovAPwlMqshDK3s78IDDuhRANCAAQm0VEdzLB9PtD0HA8JK1zifWnj8M00\n" "FQzedfp9SQsWyA8dzs5/NFR5MTe6Xbh/ndKEs1zZH3vZ4FlNrilZc0st\n" "-----END PRIVATE KEY-----"; static const char key_v2_pub[] = "-----BEGIN PUBLIC KEY-----\n" "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJtFRHcywfT7Q9BwPCStc4n1p4/DN\n" "NBUM3nX6fUkLFsgPHc7OfzRUeTE3ul24f53ShLNc2R972eBZTa4pWXNLLQ==\n" "-----END PUBLIC KEY-----"; static const char test_sample_v1_hash[] = "1d7cc2cc1f1983f76241cc42389911e88590ad58cf9d54cafeb5b198d3723dd1"; static const char test_sample_v1_short_hash[] = "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"; static const char test_sample_v2_hash[] = "2e31218656dd34db65b321688bf418dee4ee785e99eb9c21e0d29b4af27a863e"; static struct dcrypt_keypair test_v1_kp; static struct dcrypt_keypair test_v2_kp; static const char *const test_algos[] = { LN_aes_256_gcm"-"LN_sha256, LN_aes_256_cbc"-"LN_sha256, LN_camellia_192_ofb128"-"LN_sha256, #ifdef NID_chacha20_poly1305 LN_chacha20_poly1305"-"LN_sha256, #endif }; static void test_static_v1_input(void) { ssize_t siz; const struct hash_method *hash = hash_method_lookup("sha256"); unsigned char hash_ctx[hash->context_size]; unsigned char hash_digest[hash->digest_size]; hash->init(hash_ctx); test_begin("test_static_v1_input"); struct istream *is_1 = i_stream_create_file(DCRYPT_SRC_DIR"/sample-v1.asc", IO_BLOCK_SIZE); struct istream *is_2 = i_stream_create_base64_decoder(is_1); i_stream_unref(&is_1); struct istream *is_3 = i_stream_create_decrypt(is_2, test_v1_kp.priv); i_stream_unref(&is_2); struct istream *is_4 = i_stream_create_hash(is_3, hash, hash_ctx); i_stream_unref(&is_3); while((siz = i_stream_read(is_4))>0) { i_stream_skip(is_4, siz); } if (is_4->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_4)); test_assert(is_4->stream_errno == 0); i_stream_unref(&is_4); hash->result(hash_ctx, hash_digest); test_assert(strcmp(test_sample_v1_hash, binary_to_hex(hash_digest, sizeof(hash_digest))) == 0); test_end(); } static void test_static_v1_input_short(void) { ssize_t siz; const struct hash_method *hash = hash_method_lookup("sha256"); unsigned char hash_ctx[hash->context_size]; unsigned char hash_digest[hash->digest_size]; hash->init(hash_ctx); test_begin("test_static_v1_input_short"); struct istream *is_1 = i_stream_create_file(DCRYPT_SRC_DIR"/sample-v1_short.asc", IO_BLOCK_SIZE); struct istream *is_2 = i_stream_create_base64_decoder(is_1); i_stream_unref(&is_1); struct istream *is_3 = i_stream_create_decrypt(is_2, test_v1_kp.priv); i_stream_unref(&is_2); struct istream *is_4 = i_stream_create_hash(is_3, hash, hash_ctx); i_stream_unref(&is_3); while((siz = i_stream_read(is_4))>0) { i_stream_skip(is_4, siz); } if (is_4->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_4)); test_assert(is_4->stream_errno == 0); i_stream_unref(&is_4); hash->result(hash_ctx, hash_digest); test_assert(strcmp(test_sample_v1_short_hash, binary_to_hex(hash_digest, sizeof(hash_digest))) == 0); test_end(); } static void test_static_v2_input(void) { test_begin("test_static_v2_input"); ssize_t amt; const struct hash_method *hash = hash_method_lookup("sha256"); unsigned char hash_ctx[hash->context_size]; unsigned char hash_digest[hash->digest_size]; hash->init(hash_ctx); struct istream *is_1 = i_stream_create_file(DCRYPT_SRC_DIR"/sample-v2.asc", IO_BLOCK_SIZE); struct istream *is_2 = i_stream_create_base64_decoder(is_1); i_stream_unref(&is_1); struct istream *is_3 = i_stream_create_decrypt(is_2, test_v2_kp.priv); i_stream_unref(&is_2); struct istream *is_4 = i_stream_create_hash(is_3, hash, hash_ctx); i_stream_unref(&is_3); while((amt = i_stream_read(is_4))>0) { i_stream_skip(is_4, amt); } if (is_4->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_4)); test_assert(is_4->stream_errno == 0); i_stream_unref(&is_4); hash->result(hash_ctx, hash_digest); test_assert(strcmp(test_sample_v2_hash, binary_to_hex(hash_digest, sizeof(hash_digest))) == 0); test_end(); /** this code is left here to show how the sample file is created struct istream *is = i_stream_create_file("../lib-language/udhr_fra.txt", 8192); struct istream *is_2 = i_stream_create_hash(is, hash, hash_ctx); int fd = open("sample-v2.bin", O_CREAT|O_TRUNC|O_WRONLY, S_IRWXU); struct ostream *os = o_stream_create_fd_file(fd, 0, TRUE); struct ostream *os_2 = o_stream_create_encrypt(os, "aes-256-gcm-sha256", test_v2_kp.pub, IO_STREAM_ENC_INTEGRITY_AEAD); const unsigned char *ptr; size_t siz; while(i_stream_read_data(is_2, &ptr, &siz, 0)>0) { o_stream_nsend(os_2, ptr, siz); i_stream_skip(is_2, siz); } i_assert(o_stream_finish(os_2) > 0); o_stream_close(os_2); i_stream_close(is_2); hash->result(hash_ctx, hash_digest); printf("%s\n", binary_to_hex(hash_digest, sizeof(hash_digest))); */ } static void test_write_read_v1(void) { test_begin("test_write_read_v1"); unsigned char payload[IO_BLOCK_SIZE]; const unsigned char *ptr; size_t pos = 0, siz; random_fill(payload, IO_BLOCK_SIZE); buffer_t *buf = buffer_create_dynamic(default_pool, sizeof(payload)); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "<unused>", test_v2_kp.pub, IO_STREAM_ENC_VERSION_1); o_stream_nsend(os_2, payload, sizeof(payload)); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); test_assert(os_2->stream_errno == 0); test_assert(o_stream_finish(os_2) > 0); test_assert(os_2->stream_errno == 0); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, test_v2_kp.priv); size_t offset = 0; test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); } static void test_write_read_v1_short(void) { test_begin("test_write_read_v1_short"); unsigned char payload[1]; const unsigned char *ptr; size_t pos = 0, siz; random_fill(payload, 1); buffer_t *buf = buffer_create_dynamic(default_pool, 64); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "<unused>", test_v2_kp.pub, IO_STREAM_ENC_VERSION_1); o_stream_nsend(os_2, payload, sizeof(payload)); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); test_assert(os_2->stream_errno == 0); test_assert(o_stream_finish(os_2) > 0); test_assert(os_2->stream_errno == 0); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, test_v2_kp.priv); size_t offset = 0; test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (siz > sizeof(payload) || pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); } static void test_write_read_v1_empty(void) { const unsigned char *ptr; size_t siz; test_begin("test_write_read_v1_empty"); buffer_t *buf = buffer_create_dynamic(default_pool, 64); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, "<unused>", test_v1_kp.pub, IO_STREAM_ENC_VERSION_1); test_assert(o_stream_finish(os_2) > 0); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); o_stream_unref(&os); o_stream_unref(&os_2); /* this should've been enough */ struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, test_v1_kp.priv); /* read should not fail */ test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); size_t offset = 0; ssize_t ret; while ((ret = i_stream_read_data(is_2, &ptr, &siz, 0)) >= 0) { test_assert(ret == 0); if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); }; test_assert(is_2->stream_errno == 0); if (is_2->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_2)); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); } static void test_write_read_v2_real(const struct dcrypt_keypair *pair, const char *kalg, const char *algo) { test_begin(t_strdup_printf("test_write_read_v2(%s, %s)", kalg, algo)); enum io_stream_encrypt_flags flags = 0; unsigned char payload[IO_BLOCK_SIZE*10] = {0}; const unsigned char *ptr; size_t pos = 0, siz; random_fill(payload, IO_BLOCK_SIZE*10); if (strstr(algo, "-gcm") != NULL || strstr(algo, "-poly1305") != NULL) flags |= IO_STREAM_ENC_INTEGRITY_AEAD; else flags |= IO_STREAM_ENC_INTEGRITY_HMAC; buffer_t *buf = buffer_create_dynamic(default_pool, sizeof(payload)); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, algo, pair->pub, flags); o_stream_nsend(os_2, payload, sizeof(payload)); test_assert(o_stream_finish(os_2) > 0); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); /* test regression where read fails due to incorrect behaviour when buffer is full before going to decrypt code */ i_stream_set_max_buffer_size(is, 8192); test_assert(i_stream_read(is) > 0); struct istream *is_2 = i_stream_create_decrypt(is, pair->priv); size_t offset = 0; test_istream_set_size(is, 0); test_istream_set_allow_eof(is, FALSE); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); else test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); if (is_2->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_2)); /* test seeking */ for (size_t i = sizeof(payload)-100; i > 100; i -= 100) { i_stream_seek(is_2, i); test_assert_idx(i_stream_read_data(is_2, &ptr, &siz, 0) == 1, i); test_assert_idx(memcmp(ptr, payload + i, siz) == 0, i); } i_stream_seek(is_2, 0); test_assert(i_stream_read_data(is_2, &ptr, &siz, 0) == 1); test_assert(memcmp(ptr, payload, siz) == 0); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); } static void test_write_read_v2_short(const char *curve, const char *algo, const struct dcrypt_keypair *kp); static void test_write_read_v2_empty(const char *curve, const char *algo, const struct dcrypt_keypair *kp); static void test_write_read_v2_algos(const char *kalg, const struct dcrypt_keypair *pair) { for (size_t i = 0; i < N_ELEMENTS(test_algos); i++) { test_write_read_v2_real(pair, kalg, test_algos[i]); test_write_read_v2_empty(kalg, test_algos[i], pair); test_write_read_v2_short(kalg, test_algos[i], pair); } } static void test_write_read_v2(void) { test_write_read_v2_algos(SN_X9_62_prime256v1, &test_v2_kp); } #ifdef HAVE_X25519 static void test_write_read_v2_x25519(void) { struct dcrypt_keypair pair; const char *error; bool ret = dcrypt_keypair_generate(&pair, DCRYPT_KEY_EC, 0, SN_X25519, &error); if (!ret) i_fatal("%s", error); test_write_read_v2_algos(SN_X25519, &pair); dcrypt_keypair_unref(&pair); } static void test_write_read_v2_x448(void) { struct dcrypt_keypair pair; const char *error; bool ret = dcrypt_keypair_generate(&pair, DCRYPT_KEY_EC, 0, SN_X448, &error); if (!ret) i_fatal("%s", error); test_write_read_v2_algos(SN_X448, &pair); dcrypt_keypair_unref(&pair); } #endif /* Whether the OpenSSL we're running against supports ML-KEM. This can't be decided at build time. */ static bool have_kem = FALSE; static void test_kem_detect(void) { struct dcrypt_keypair pair; const char *error; have_kem = dcrypt_keypair_generate(&pair, DCRYPT_KEY_KEM, 0, DCRYPT_ML_KEM_512, &error); if (!have_kem) { i_info("ML-KEM not supported by OpenSSL, " "skipping ML-KEM tests: %s", error); return; } dcrypt_keypair_unref(&pair); } static void test_write_read_v2_kem_curve(const char *curve) { struct dcrypt_keypair pair; const char *error; bool ret = dcrypt_keypair_generate(&pair, DCRYPT_KEY_KEM, 0, curve, &error); if (!ret) i_fatal("%s", error); test_write_read_v2_algos(curve, &pair); dcrypt_keypair_unref(&pair); } static void test_write_read_v2_kem(void) { static const char *const curves[] = { DCRYPT_ML_KEM_512, DCRYPT_ML_KEM_768, DCRYPT_ML_KEM_1024 }; if (!have_kem) return; for (size_t i = 0; i < N_ELEMENTS(curves); i++) T_BEGIN { test_write_read_v2_kem_curve(curves[i]); } T_END; } static void test_write_read_v2_short(const char *curve, const char *algo, const struct dcrypt_keypair *kp) { test_begin(t_strdup_printf("test_write_read_v2_short(%s, %s)", curve, algo)); enum io_stream_encrypt_flags flags = 0; unsigned char payload[1]; const unsigned char *ptr; size_t pos = 0, siz; random_fill(payload, 1); if (strstr(algo, "-gcm") != NULL || strstr(algo, "-poly1305") != NULL) flags |= IO_STREAM_ENC_INTEGRITY_AEAD; else flags |= IO_STREAM_ENC_INTEGRITY_HMAC; buffer_t *buf = buffer_create_dynamic(default_pool, 64); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, algo, kp->pub, flags); o_stream_nsend(os_2, payload, sizeof(payload)); test_assert(o_stream_finish(os_2) > 0); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); o_stream_unref(&os); o_stream_unref(&os_2); struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, kp->priv); size_t offset = 0; test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); while(i_stream_read_data(is_2, &ptr, &siz, 0)>=0) { if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); test_istream_set_size(is, ++offset); test_assert_idx(pos + siz <= sizeof(payload), pos); if (siz > sizeof(payload) || pos + siz > sizeof(payload)) break; test_assert_idx(siz == 0 || memcmp(ptr, payload + pos, siz) == 0, pos); i_stream_skip(is_2, siz); pos += siz; } test_assert(is_2->stream_errno == 0); if (is_2->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_2)); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); } static void test_write_read_v2_empty(const char *curve, const char *algo, const struct dcrypt_keypair *kp) { const unsigned char *ptr; size_t siz; enum io_stream_encrypt_flags flags = 0; test_begin(t_strdup_printf("test_write_read_v2_empty(%s, %s)", curve, algo)); if (strstr(algo, "-gcm") != NULL || strstr(algo, "-poly1305") != NULL) flags |= IO_STREAM_ENC_INTEGRITY_AEAD; else flags |= IO_STREAM_ENC_INTEGRITY_HMAC; buffer_t *buf = buffer_create_dynamic(default_pool, 64); struct ostream *os = o_stream_create_buffer(buf); struct ostream *os_2 = o_stream_create_encrypt(os, algo, kp->pub, flags); test_assert(o_stream_finish(os_2) > 0); if (os_2->stream_errno != 0) i_debug("error: %s", o_stream_get_error(os_2)); o_stream_unref(&os); o_stream_unref(&os_2); /* this should've been enough */ struct istream *is = test_istream_create_data(buf->data, buf->used); struct istream *is_2 = i_stream_create_decrypt(is, kp->priv); /* read should not fail */ size_t offset = 0; test_istream_set_allow_eof(is, FALSE); test_istream_set_size(is, 0); ssize_t ret; while ((ret = i_stream_read_data(is_2, &ptr, &siz, 0)) >= 0) { test_assert(ret == 0); if (offset == buf->used) test_istream_set_allow_eof(is, TRUE); test_istream_set_size(is, ++offset); }; test_assert(is_2->stream_errno == 0); if (is_2->stream_errno != 0) i_debug("error: %s", i_stream_get_error(is_2)); i_stream_unref(&is); i_stream_unref(&is_2); buffer_free(&buf); test_end(); } static int no_op_cb(const char *digest ATTR_UNUSED, struct dcrypt_private_key **priv_key_r ATTR_UNUSED, const char **error_r ATTR_UNUSED, void *context ATTR_UNUSED) { return 0; } static void test_read_0_to_400_byte_garbage(void) { test_begin("test_read_0_to_100_byte_garbage"); char data[512]; memset(data, 0, sizeof(data)); for (size_t s = 0; s <= 400; ++s) { struct istream *is = test_istream_create_data(data, s); struct istream *ds = i_stream_create_decrypt_callback(is, no_op_cb, NULL); test_istream_set_size(is, 0); test_istream_set_allow_eof(is, FALSE); ssize_t siz = 0; for (size_t offset = 0; offset <= s && siz == 0; offset++) { if (offset == s) test_istream_set_allow_eof(is, TRUE); test_istream_set_size(is, offset); siz = i_stream_read(ds); } test_assert_idx(siz < 0, s); i_stream_unref(&ds); i_stream_unref(&is); } test_end(); } static void test_read_large_header(void) { test_begin("test_read_large_header"); struct istream *is = test_istream_create_data(IOSTREAM_CRYPT_MAGIC, sizeof(IOSTREAM_CRYPT_MAGIC)); struct istream *ds = i_stream_create_decrypt_callback(is, no_op_cb, NULL); test_istream_set_allow_eof(is, FALSE); test_istream_set_max_buffer_size(is, sizeof(IOSTREAM_CRYPT_MAGIC)); test_assert(i_stream_read(ds) == -1); i_stream_unref(&ds); i_stream_unref(&is); test_end(); } static void test_read_increment(void) { test_begin("test_read_increment"); ssize_t amt, total, i; struct istream *is_1 = i_stream_create_file( DCRYPT_SRC_DIR"/sample-v2.asc", IO_BLOCK_SIZE); struct istream *is_2 = i_stream_create_base64_decoder(is_1); i_stream_unref(&is_1); struct istream *is_3 = i_stream_create_decrypt(is_2, test_v2_kp.priv); i_stream_unref(&is_2); total = 0; i = 500; i_stream_set_max_buffer_size(is_3, i); while((amt = i_stream_read(is_3)) > 0) { total += amt; i_stream_set_max_buffer_size(is_3, ++i); } /* make sure snapshotting works: */ i_stream_skip(is_3, 1); test_assert(i_stream_read(is_3) == -1); test_assert(total == 13534); test_assert(is_3->stream_errno == 0); test_assert(is_3->eof); i_stream_unref(&is_3); test_end(); } static void test_read_garbage(void) { test_begin("test_read_garbage"); unsigned char buf[512]; for (int i = 0; i < 5; i++) { random_fill(buf, sizeof(buf)); memcpy(buf, IOSTREAM_CRYPT_MAGIC, sizeof(IOSTREAM_CRYPT_MAGIC)); buf[sizeof(IOSTREAM_CRYPT_MAGIC)+1] = '\x02'; struct istream *is = test_istream_create_data(buf, sizeof(buf)); struct istream *ds = i_stream_create_decrypt_callback(is, no_op_cb, NULL); i_stream_unref(&is); test_assert(i_stream_read(ds) == -1); test_assert(ds->stream_errno == EIO || ds->stream_errno == EPIPE); i_stream_unref(&ds); } test_end(); } static void test_free_keys() { dcrypt_key_unref_private(&test_v1_kp.priv); dcrypt_key_unref_public(&test_v1_kp.pub); dcrypt_key_unref_private(&test_v2_kp.priv); dcrypt_key_unref_public(&test_v2_kp.pub); } int main(void) { struct dcrypt_settings set = { .module_dir = ".libs" }; const char *error; if (!dcrypt_initialize(NULL, &set, &error)) { i_error("No functional dcrypt backend found - " "skipping tests: %s", error); return 0; } test_assert(dcrypt_key_load_private(&test_v1_kp.priv, key_v1_priv, NULL, NULL, &error)); test_assert(dcrypt_key_load_public(&test_v1_kp.pub, key_v1_pub, &error)); test_assert(dcrypt_key_load_private(&test_v2_kp.priv, key_v2_priv, NULL, NULL, &error)); test_assert(dcrypt_key_load_public(&test_v2_kp.pub, key_v2_pub, &error)); static void (*const test_functions[])(void) = { test_static_v1_input, test_static_v1_input_short, test_static_v2_input, test_read_increment, test_write_read_v1, test_write_read_v1_short, test_write_read_v1_empty, test_write_read_v2, #ifdef HAVE_X25519 test_write_read_v2_x448, test_write_read_v2_x25519, #endif test_write_read_v2_kem, test_free_keys, test_read_0_to_400_byte_garbage, test_read_large_header, test_read_garbage, NULL }; test_kem_detect(); return test_run(test_functions); }