summaryrefslogtreecommitdiffstats
path: root/test/dtlsv1listentest.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2016-01-21 12:22:58 +0000
committerMatt Caswell <matt@openssl.org>2016-02-05 20:47:36 +0000
commitce0865d8dcf4ed088a9e9ae3aa2310b7bd8c295e (patch)
tree8fb23cc3932a033d64e94b13e4ec991cb1fb6b57 /test/dtlsv1listentest.c
parent4b1043ef1b54b0cf27d00cff9ff9a63f2c523e63 (diff)
Add tests for DTLSv1_listen
Adds a set of tests for the newly rewritten DTLSv1_listen function. The test pokes various packets at the function and then checks the return value and the data written out to ensure it is what we would have expected. Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Diffstat (limited to 'test/dtlsv1listentest.c')
-rw-r--r--test/dtlsv1listentest.c478
1 files changed, 478 insertions, 0 deletions
diff --git a/test/dtlsv1listentest.c b/test/dtlsv1listentest.c
new file mode 100644
index 0000000000..28b493e091
--- /dev/null
+++ b/test/dtlsv1listentest.c
@@ -0,0 +1,478 @@
+/*
+ * Written by Matt Caswell for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 2016 The OpenSSL Project. 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.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <string.h>
+#include <sys/socket.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#include "e_os.h"
+
+/* Just a ClientHello without a cookie */
+const unsigned char clienthello_nocookie[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x3A, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x2E, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x2E, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x00, /* Cookie len */
+ 0x00, 0x04, /* Ciphersuites len */
+ 0x00, 0x2f, /* AES128-SHA */
+ 0x00, 0xff, /* Empty reneg info SCSV */
+ 0x01, /* Compression methods len */
+ 0x00, /* Null compression */
+ 0x00, 0x00 /* Extensions len */
+};
+
+/* First fragment of a ClientHello without a cookie */
+const unsigned char clienthello_nocookie_frag[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x30, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x2E, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x24, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x00 /* Cookie len */
+};
+
+/* First fragment of a ClientHello which is too short */
+const unsigned char clienthello_nocookie_short[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x2F, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x2E, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x23, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00 /* Session id len */
+};
+
+/* Second fragment of a ClientHello */
+const unsigned char clienthello_2ndfrag[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x38, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x2E, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x02, /* Fragment offset */
+ 0x00, 0x00, 0x2C, /* Fragment length */
+ /* Version skipped - sent in first fragment */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x00, /* Cookie len */
+ 0x00, 0x04, /* Ciphersuites len */
+ 0x00, 0x2f, /* AES128-SHA */
+ 0x00, 0xff, /* Empty reneg info SCSV */
+ 0x01, /* Compression methods len */
+ 0x00, /* Null compression */
+ 0x00, 0x00 /* Extensions len */
+};
+
+/* A ClientHello with a good cookie */
+const unsigned char clienthello_cookie[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x4E, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x42, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x42, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x14, /* Cookie len */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
+ 0x00, 0x04, /* Ciphersuites len */
+ 0x00, 0x2f, /* AES128-SHA */
+ 0x00, 0xff, /* Empty reneg info SCSV */
+ 0x01, /* Compression methods len */
+ 0x00, /* Null compression */
+ 0x00, 0x00 /* Extensions len */
+};
+
+/* A fragmented ClientHello with a good cookie */
+const unsigned char clienthello_cookie_frag[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x44, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x42, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x38, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x14, /* Cookie len */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
+};
+
+
+/* A ClientHello with a bad cookie */
+const unsigned char clienthello_badcookie[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x4E, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x42, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x42, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x14, /* Cookie len */
+ 0x01, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
+ 0x00, 0x04, /* Ciphersuites len */
+ 0x00, 0x2f, /* AES128-SHA */
+ 0x00, 0xff, /* Empty reneg info SCSV */
+ 0x01, /* Compression methods len */
+ 0x00, /* Null compression */
+ 0x00, 0x00 /* Extensions len */
+};
+
+/* A fragmented ClientHello with the fragment boundary mid cookie */
+const unsigned char clienthello_cookie_short[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x43, /* Record Length */
+ 0x01, /* ClientHello */
+ 0x00, 0x00, 0x42, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x37, /* Fragment length */
+ 0xFE, 0xFD, /* DTLSv1.2 */
+ 0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
+ 0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
+ 0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
+ 0x00, /* Session id len */
+ 0x14, /* Cookie len */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12 /* Cookie */
+};
+
+/* Bad record - too short */
+const unsigned char record_short[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Record sequence number */
+};
+
+const unsigned char verify[] = {
+ 0x16, /* Handshake */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x00, 0x00, /* Epoch */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
+ 0x00, 0x23, /* Record Length */
+ 0x03, /* HelloVerifyRequest */
+ 0x00, 0x00, 0x17, /* Message length */
+ 0x00, 0x00, /* Message sequence */
+ 0x00, 0x00, 0x00, /* Fragment offset */
+ 0x00, 0x00, 0x17, /* Fragment length */
+ 0xFE, 0xFF, /* DTLSv1.0 */
+ 0x14, /* Cookie len */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
+};
+
+struct {
+ const unsigned char *in;
+ unsigned int inlen;
+ /*
+ * GOOD == positive return value from DTLSv1_listen, no output yet
+ * VERIFY == 0 return value, HelloVerifyRequest sent
+ * DROP == 0 return value, no output
+ */
+ enum {GOOD, VERIFY, DROP} outtype;
+} testpackets[9] = {
+ {
+ clienthello_nocookie,
+ sizeof(clienthello_nocookie),
+ VERIFY
+ },
+ {
+ clienthello_nocookie_frag,
+ sizeof(clienthello_nocookie_frag),
+ VERIFY
+ },
+ {
+ clienthello_nocookie_short,
+ sizeof(clienthello_nocookie_short),
+ DROP
+ },
+ {
+ clienthello_2ndfrag,
+ sizeof(clienthello_2ndfrag),
+ DROP
+ },
+ {
+ clienthello_cookie,
+ sizeof(clienthello_cookie),
+ GOOD
+ },
+ {
+ clienthello_cookie_frag,
+ sizeof(clienthello_cookie_frag),
+ GOOD
+ },
+ {
+ clienthello_badcookie,
+ sizeof(clienthello_badcookie),
+ VERIFY
+ },
+ {
+ clienthello_cookie_short,
+ sizeof(clienthello_cookie_short),
+ DROP
+ },
+ {
+ record_short,
+ sizeof(record_short),
+ DROP
+ }
+};
+
+#define COOKIE_LEN 20
+
+static int cookie_gen(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
+{
+ unsigned int i;
+
+ for (i = 0; i < COOKIE_LEN; i++, cookie++) {
+ *cookie = i;
+ }
+ *cookie_len = COOKIE_LEN;
+
+ return 1;
+}
+
+static int cookie_verify(SSL *ssl, const unsigned char *cookie,
+ unsigned int cookie_len)
+{
+ unsigned int i;
+
+ if (cookie_len != COOKIE_LEN)
+ return 0;
+
+ for (i = 0; i < COOKIE_LEN; i++, cookie++) {
+ if (*cookie != i)
+ return 0;
+ }
+
+ return 1;
+}
+
+int main(void)
+{
+ SSL_CTX *ctx = NULL;
+ SSL *ssl = NULL;
+ BIO *outbio = NULL;
+ BIO *inbio = NULL;
+ BIO_ADDR *peer = BIO_ADDR_new();
+ char *data;
+ long datalen;
+ int ret, success = 0;
+ size_t i;
+
+ /* Initialise libssl */
+ SSL_load_error_strings();
+ SSL_library_init();
+
+ ctx = SSL_CTX_new(DTLS_server_method());
+ if (ctx == NULL || peer == NULL)
+ goto err;
+
+ SSL_CTX_set_cookie_generate_cb(ctx, cookie_gen);
+ SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify);
+
+ /* Create an SSL object for the connection */
+ ssl = SSL_new(ctx);
+ if (ssl == NULL)
+ goto err;
+
+ outbio = BIO_new(BIO_s_mem());
+ if (outbio == NULL)
+ goto err;
+ SSL_set_wbio(ssl, outbio);
+
+ success = 1;
+ for (i = 0; i < OSSL_NELEM(testpackets) && success; i++) {
+ inbio = BIO_new_mem_buf((char *)testpackets[i].in,
+ testpackets[i].inlen);
+ if (inbio == NULL) {
+ success = 0;
+ goto err;
+ }
+ /* Set Non-blocking IO behaviour */
+ BIO_set_mem_eof_return(inbio, -1);
+
+ SSL_set_rbio(ssl, inbio);
+
+ /* Process the incoming packet */
+ ret = DTLSv1_listen(ssl, peer);
+ if (ret < 0) {
+ success = 0;
+ goto err;
+ }
+
+ datalen = BIO_get_mem_data(outbio, &data);
+
+ if (testpackets[i].outtype == VERIFY) {
+ if (ret == 0) {
+ if (datalen != sizeof(verify)
+ || (memcmp(data, verify, sizeof(verify)) != 0)) {
+ printf("Test %ld failure: incorrect HelloVerifyRequest\n", i);
+ success = 0;
+ } else {
+ printf("Test %ld success\n", i);
+ }
+ } else {
+ printf ("Test %ld failure: should not have succeeded\n", i);
+ success = 0;
+ }
+ } else if (datalen == 0) {
+ if ((ret == 0 && testpackets[i].outtype == DROP)
+ || (ret == 1 && testpackets[i].outtype == GOOD)) {
+ printf("Test %ld success\n", i);
+ } else {
+ printf("Test %ld failure: wrong return value\n", i);
+ success = 0;
+ }
+ } else {
+ printf("Test %ld failure: Unexpected data output\n", i);
+ success = 0;
+ }
+ (void)BIO_reset(outbio);
+ inbio = NULL;
+ /* Frees up inbio */
+ SSL_set_rbio(ssl, NULL);
+ }
+
+ err:
+ if (!success)
+ ERR_print_errors_fp(stderr);
+ /* Also frees up outbio */
+ SSL_free(ssl);
+ SSL_CTX_free(ctx);
+ BIO_free(inbio);
+ /* Unitialise libssl */
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_cleanup();
+#endif
+ CONF_modules_unload(1);
+ CRYPTO_cleanup_all_ex_data();
+ EVP_cleanup();
+ ERR_remove_thread_state(NULL);
+ ERR_free_strings();
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+ CRYPTO_mem_leaks_fp(stderr);
+#endif
+ return success ? 0 : 1;
+}
+