diff options
author | Hugo Landau <hlandau@openssl.org> | 2022-05-31 20:22:40 +0100 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2022-09-23 11:59:13 +1000 |
commit | b88ce46ee88c4128f72694e42160622844971d04 (patch) | |
tree | 3edc587990721e76378bd7a8429c8b2919c61f41 /test/bio_dgram_test.c | |
parent | a29ad912b82f50ef876bef99c66522dccd41b6f8 (diff) |
BIO_s_dgram_pair
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18442)
Diffstat (limited to 'test/bio_dgram_test.c')
-rw-r--r-- | test/bio_dgram_test.c | 298 |
1 files changed, 297 insertions, 1 deletions
diff --git a/test/bio_dgram_test.c b/test/bio_dgram_test.c index 7f147283b9..4dd2893c1b 100644 --- a/test/bio_dgram_test.c +++ b/test/bio_dgram_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,7 @@ #include <string.h> #include <openssl/bio.h> +#include <openssl/rand.h> #include "testutil.h" #include "internal/sockets.h" @@ -450,6 +451,299 @@ static int test_bio_dgram(int idx) bio_dgram_cases[idx].local); } +static int random_data(const uint32_t *key, uint8_t *data, size_t data_len, size_t offset) +{ + int ret = 0, outl; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; + static const uint8_t zeroes[2048]; + uint32_t counter[4] = {0}; + + counter[0] = (uint32_t)offset; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + goto err; + + cipher = EVP_CIPHER_fetch(NULL, "ChaCha20", NULL); + if (cipher == NULL) + goto err; + + if (EVP_EncryptInit_ex2(ctx, cipher, (uint8_t *)key, (uint8_t *)counter, NULL) == 0) + goto err; + + while (data_len > 0) { + outl = data_len > sizeof(zeroes) ? (int)sizeof(zeroes) : (int)data_len; + if (EVP_EncryptUpdate(ctx, data, &outl, zeroes, outl) != 1) + goto err; + + data += outl; + data_len -= outl; + } + + ret = 1; +err: + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cipher); + return ret; +} + +static int test_bio_dgram_pair(void) +{ + int testresult = 0, blen, mtu1, mtu2, r; + BIO *bio1 = NULL, *bio2 = NULL; + uint8_t scratch[2048 + 4], scratch2[2048]; + uint32_t key[8]; + size_t i, num_dgram, num_processed = 0; + BIO_MSG msgs[2] = {0}, rmsgs[2] = {0}; + BIO_ADDR *addr1 = NULL, *addr2 = NULL, *addr3 = NULL, *addr4 = NULL; + struct in_addr in_local; + size_t total = 0; + const uint32_t ref_caps = BIO_DGRAM_CAP_HANDLES_SRC_ADDR + | BIO_DGRAM_CAP_HANDLES_DST_ADDR + | BIO_DGRAM_CAP_PROVIDES_SRC_ADDR + | BIO_DGRAM_CAP_PROVIDES_DST_ADDR; + + in_local.s_addr = ntohl(0x7f000001); + + for (i = 0; i < OSSL_NELEM(key); ++i) + key[i] = test_random(); + + if (!TEST_int_eq(BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0), 1)) + goto err; + + mtu1 = BIO_dgram_get_mtu(bio1); + if (!TEST_int_ge(mtu1, 1280)) + goto err; + + mtu2 = BIO_dgram_get_mtu(bio2); + if (!TEST_int_ge(mtu2, 1280)) + goto err; + + if (!TEST_int_eq(mtu1, mtu2)) + goto err; + + if (!TEST_int_le(mtu1, sizeof(scratch) - 4)) + goto err; + + for (i = 0;; ++i) { + if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), i), 1)) + goto err; + + blen = (*(uint32_t*)scratch) % mtu1; + r = BIO_write(bio1, scratch + 4, blen); + if (r == -1) + break; + + if (!TEST_int_eq(r, blen)) + goto err; + + total += blen; + if (!TEST_size_t_lt(total, 1 * 1024 * 1024)) + goto err; + } + + /* + * Should be able to fit at least 9 datagrams in default write buffer size + * in worst case + */ + if (!TEST_int_ge(i, 9)) + goto err; + + /* Check we read back the same data */ + num_dgram = i; + for (i = 0; i < num_dgram; ++i) { + if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), i), 1)) + goto err; + + blen = (*(uint32_t*)scratch) % mtu1; + r = BIO_read(bio2, scratch2, sizeof(scratch2)); + if (!TEST_int_eq(r, blen)) + goto err; + + if (!TEST_mem_eq(scratch + 4, blen, scratch2, blen)) + goto err; + } + + /* Should now be out of data */ + if (!TEST_int_eq(BIO_read(bio2, scratch2, sizeof(scratch2)), -1)) + goto err; + + /* sendmmsg/recvmmsg */ + if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), 0), 1)) + goto err; + + msgs[0].data = scratch; + msgs[0].data_len = 19; + msgs[1].data = scratch + 19; + msgs[1].data_len = 46; + + if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), OSSL_NELEM(msgs), 0, + &num_processed)) + || !TEST_size_t_eq(num_processed, 2)) + goto err; + + rmsgs[0].data = scratch2; + rmsgs[0].data_len = 64; + rmsgs[1].data = scratch2 + 64; + rmsgs[1].data_len = 64; + if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0, + &num_processed)) + || !TEST_size_t_eq(num_processed, 2)) + goto err; + + if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, scratch, 19)) + goto err; + + if (!TEST_mem_eq(rmsgs[1].data, rmsgs[1].data_len, scratch + 19, 46)) + goto err; + + /* sendmmsg/recvmmsg with peer */ + addr1 = BIO_ADDR_new(); + if (!TEST_ptr(addr1)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_rawmake(addr1, AF_INET, &in_local, + sizeof(in_local), 1234), 1)) + goto err; + + addr2 = BIO_ADDR_new(); + if (!TEST_ptr(addr2)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_rawmake(addr2, AF_INET, &in_local, + sizeof(in_local), 2345), 1)) + goto err; + + addr3 = BIO_ADDR_new(); + if (!TEST_ptr(addr3)) + goto err; + + addr4 = BIO_ADDR_new(); + if (!TEST_ptr(addr4)) + goto err; + + msgs[0].peer = addr1; + + /* fails due to lack of caps on peer */ + if (!TEST_false(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), OSSL_NELEM(msgs), + 0, &num_processed)) + || !TEST_size_t_eq(num_processed, 0)) + goto err; + + if (!TEST_int_eq(BIO_dgram_set_caps(bio2, ref_caps), 1)) + goto err; + + if (!TEST_int_eq(BIO_dgram_get_caps(bio2), ref_caps)) + goto err; + + if (!TEST_int_eq(BIO_dgram_get_effective_caps(bio1), ref_caps)) + goto err; + + if (!TEST_int_eq(BIO_dgram_get_effective_caps(bio2), 0)) + goto err; + + if (!TEST_int_eq(BIO_dgram_set_caps(bio1, ref_caps), 1)) + goto err; + + /* succeeds with cap now available */ + if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), 1, 0, &num_processed)) + || !TEST_size_t_eq(num_processed, 1)) + goto err; + + /* enable local addr support */ + if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(bio2, 1), 1)) + goto err; + + rmsgs[0].data = scratch2; + rmsgs[0].data_len = 64; + rmsgs[0].peer = addr3; + rmsgs[0].local = addr4; + if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0, + &num_processed)) + || !TEST_size_t_eq(num_processed, 1)) + goto err; + + if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, msgs[0].data, 19)) + goto err; + + /* We didn't set the source address so this should be zero */ + if (!TEST_int_eq(BIO_ADDR_family(addr3), 0)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_family(addr4), AF_INET)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_rawport(addr4), 1234)) + goto err; + + /* test source address */ + msgs[0].local = addr2; + + if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(bio1, 1), 1)) + goto err; + + if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), 1, 0, &num_processed)) + || !TEST_size_t_eq(num_processed, 1)) + goto err; + + rmsgs[0].data = scratch2; + rmsgs[0].data_len = 64; + if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0, &num_processed)) + || !TEST_size_t_eq(num_processed, 1)) + goto err; + + if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, + msgs[0].data, msgs[0].data_len)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_family(addr3), AF_INET)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_rawport(addr3), 2345)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_family(addr4), AF_INET)) + goto err; + + if (!TEST_int_eq(BIO_ADDR_rawport(addr4), 1234)) + goto err; + + /* test truncation, pending */ + r = BIO_write(bio1, scratch, 64); + if (!TEST_int_eq(r, 64)) + goto err; + + memset(scratch2, 0, 64); + if (!TEST_int_eq(BIO_dgram_set_no_trunc(bio2, 1), 1)) + goto err; + + if (!TEST_int_eq(BIO_read(bio2, scratch2, 32), -1)) + goto err; + + if (!TEST_int_eq(BIO_pending(bio2), 64)) + goto err; + + if (!TEST_int_eq(BIO_dgram_set_no_trunc(bio2, 0), 1)) + goto err; + + if (!TEST_int_eq(BIO_read(bio2, scratch2, 32), 32)) + goto err; + + if (!TEST_mem_eq(scratch, 32, scratch2, 32)) + goto err; + + testresult = 1; +err: + BIO_free(bio1); + BIO_free(bio2); + BIO_ADDR_free(addr1); + BIO_ADDR_free(addr2); + BIO_ADDR_free(addr3); + BIO_ADDR_free(addr4); + return testresult; +} + #endif /* !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) */ int setup_tests(void) @@ -461,6 +755,8 @@ int setup_tests(void) #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) ADD_ALL_TESTS(test_bio_dgram, OSSL_NELEM(bio_dgram_cases)); + ADD_TEST(test_bio_dgram_pair); #endif + return 1; } |