diff --git a/test/Makefile b/test/Makefile index d9aa750d07..2e699dc7ae 100644 --- a/test/Makefile +++ b/test/Makefile @@ -69,6 +69,7 @@ V3NAMETEST= v3nametest HEARTBEATTEST= heartbeat_test CONSTTIMETEST= constant_time_test VERIFYEXTRATEST= verify_extra_test +CLIENTHELLOTEST= clienthellotest TESTS= alltests @@ -85,7 +86,8 @@ EXE= $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(ECDSATEST)$(EXE_EXT) $(ECDHTEST) $(JPAKETEST)$(EXE_EXT) $(SECMEMTEST)$(EXE_EXT) \ $(SRPTEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) \ $(HEARTBEATTEST)$(EXE_EXT) $(P5_CRPT2_TEST)$(EXE_EXT) \ - $(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) + $(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) \ + $(CLIENTHELLOTEST)$(EXE_EXT) # $(METHTEST)$(EXE_EXT) @@ -99,7 +101,7 @@ OBJ= $(BNTEST).o $(ECTEST).o $(ECDSATEST).o $(ECDHTEST).o $(IDEATEST).o \ $(BFTEST).o $(SSLTEST).o $(DSATEST).o $(EXPTEST).o $(RSATEST).o \ $(EVPTEST).o $(EVPEXTRATEST).o $(IGETEST).o $(JPAKETEST).o $(V3NAMETEST).o \ $(GOST2814789TEST).o $(HEARTBEATTEST).o $(P5_CRPT2_TEST).o \ - $(CONSTTIMETEST).o $(VERIFYEXTRATEST).o testutil.o + $(CONSTTIMETEST).o $(VERIFYEXTRATEST).o $(CLIENTHELLOTEST).o testutil.o SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \ $(MD2TEST).c $(MD4TEST).c $(MD5TEST).c \ @@ -110,7 +112,7 @@ SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \ $(BFTEST).c $(SSLTEST).c $(DSATEST).c $(EXPTEST).c $(RSATEST).c \ $(EVPTEST).c $(EVPEXTRATEST).c $(IGETEST).c $(JPAKETEST).c $(V3NAMETEST).c \ $(GOST2814789TEST).c $(HEARTBEATTEST).c $(P5_CRPT2_TEST).c \ - $(CONSTTIMETEST).c $(VERIFYEXTRATEST).c testutil.c + $(CONSTTIMETEST).c $(VERIFYEXTRATEST).c $(CLIENTHELLOTEST).c testutil.c HEADER= testutil.h @@ -151,7 +153,7 @@ alltests: \ test_ige test_jpake test_secmem \ test_srp test_cms test_v3name test_ocsp \ test_gost2814789 test_heartbeat test_p5_crpt2 \ - test_constant_time test_verify_extra + test_constant_time test_verify_extra test_clienthello test_evp: $(EVPTEST)$(EXE_EXT) evptests.txt @echo $(START) $@ @@ -404,6 +406,10 @@ test_verify_extra: $(VERIFYEXTRATEST)$(EXE_EXT) @echo $(START) $@ ../util/shlib_wrap.sh ./$(VERIFYEXTRATEST) +test_clienthello: $(CLIENTHELLOTEST)$(EXE_EXT) + @echo $(START) $@ + ../util/shlib_wrap.sh ./$(CLIENTHELLOTEST) + update: local_depend @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi @@ -594,6 +600,9 @@ $(CONSTTIMETEST)$(EXE_EXT): $(CONSTTIMETEST).o $(VERIFYEXTRATEST)$(EXE_EXT): $(VERIFYEXTRATEST).o @target=$(VERIFYEXTRATEST) $(BUILD_CMD) +$(CLIENTHELLOTEST)$(EXE_EXT): $(CLIENTHELLOTEST).o + @target=$(CLIENTHELLOTEST) $(BUILD_CMD) + #$(AESTEST).o: $(AESTEST).c # $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c @@ -627,6 +636,24 @@ bntest.o: ../include/openssl/symhacks.h ../include/openssl/x509.h bntest.o: ../include/openssl/x509_vfy.h bntest.c casttest.o: ../e_os.h ../include/openssl/cast.h ../include/openssl/e_os2.h casttest.o: ../include/openssl/opensslconf.h casttest.c +clienthellotest.o: ../include/openssl/asn1.h ../include/openssl/bio.h +clienthellotest.o: ../include/openssl/buffer.h ../include/openssl/comp.h +clienthellotest.o: ../include/openssl/crypto.h ../include/openssl/dtls1.h +clienthellotest.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +clienthellotest.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +clienthellotest.o: ../include/openssl/err.h ../include/openssl/evp.h +clienthellotest.o: ../include/openssl/hmac.h ../include/openssl/lhash.h +clienthellotest.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h +clienthellotest.o: ../include/openssl/opensslconf.h +clienthellotest.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h +clienthellotest.o: ../include/openssl/pem.h ../include/openssl/pem2.h +clienthellotest.o: ../include/openssl/pkcs7.h ../include/openssl/safestack.h +clienthellotest.o: ../include/openssl/sha.h ../include/openssl/srtp.h +clienthellotest.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +clienthellotest.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +clienthellotest.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +clienthellotest.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h +clienthellotest.o: clienthellotest.c constant_time_test.o: ../e_os.h ../include/internal/constant_time_locl.h constant_time_test.o: ../include/openssl/e_os2.h constant_time_test.o: ../include/openssl/opensslconf.h constant_time_test.c diff --git a/test/clienthellotest.c b/test/clienthellotest.c new file mode 100644 index 0000000000..acc56f84c6 --- /dev/null +++ b/test/clienthellotest.c @@ -0,0 +1,218 @@ +/* Written by Matt Caswell for the OpenSSL Project */ +/* ==================================================================== + * Copyright (c) 1998-2015 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 + +#include +#include +#include +#include +#include + + +#define CLIENT_VERSION_LEN 2 +#define SESSION_ID_LEN_LEN 1 +#define CIPHERS_LEN_LEN 2 +#define COMPRESSION_LEN_LEN 1 +#define EXTENSIONS_LEN_LEN 2 +#define EXTENSION_TYPE_LEN 2 +#define EXTENSION_SIZE_LEN 2 + + +#define TOTAL_NUM_TESTS 2 + +/* + * Test that explicitly setting ticket data results in it appearing in the + * ClientHello for TLS1.2 + */ +#define TEST_SET_SESSION_TICK_DATA_TLS_1_2 0 + +/* + * Test that explicitly setting ticket data results in it appearing in the + * ClientHello for a negotiated SSL/TLS version + */ +#define TEST_SET_SESSION_TICK_DATA_VER_NEG 1 + +int main(int argc, char *argv[]) +{ + SSL_CTX *ctx; + SSL *con; + BIO *rbio; + BIO *wbio; + BIO *err; + long len; + unsigned char *data; + unsigned char *dataend; + char *dummytick = "Hello World!"; + unsigned int tmplen; + unsigned int type; + unsigned int size; + int testresult = 0; + int currtest = 0; + + SSL_library_init(); + SSL_load_error_strings(); + + err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); + + CRYPTO_malloc_debug_init(); + CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + + /* + * For each test set up an SSL_CTX and SSL and see what ClientHello gets + * produced when we try to connect + */ + for (; currtest < TOTAL_NUM_TESTS; currtest++) { + testresult = 0; + if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2) { + ctx = SSL_CTX_new(TLSv1_2_method()); + } else { + ctx = SSL_CTX_new(TLS_method()); + } + con = SSL_new(ctx); + + rbio = BIO_new(BIO_s_mem()); + wbio = BIO_new(BIO_s_mem()); + SSL_set_bio(con, rbio, wbio); + SSL_set_connect_state(con); + + if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2 + || currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) { + if (!SSL_set_session_ticket_ext(con, dummytick, strlen(dummytick))) + goto end; + } + + if (SSL_connect(con) > 0) { + /* This shouldn't succeed because we don't have a server! */ + goto end; + } + + len = BIO_get_mem_data(wbio, (char **)&data); + dataend = data + len; + + /* Skip the record header */ + data += SSL3_RT_HEADER_LENGTH; + /* Skip the handshake message header */ + data += SSL3_HM_HEADER_LENGTH; + /* Skip client version and random */ + data += CLIENT_VERSION_LEN + SSL3_RANDOM_SIZE; + if (data + SESSION_ID_LEN_LEN > dataend) + goto end; + /* Skip session id */ + tmplen = *data; + data += SESSION_ID_LEN_LEN + tmplen; + if (data + CIPHERS_LEN_LEN > dataend) + goto end; + /* Skip ciphers */ + tmplen = ((*data) << 8) | *(data + 1); + data += CIPHERS_LEN_LEN + tmplen; + if (data + COMPRESSION_LEN_LEN > dataend) + goto end; + /* Skip compression */ + tmplen = *data; + data += COMPRESSION_LEN_LEN + tmplen; + if (data + EXTENSIONS_LEN_LEN > dataend) + goto end; + /* Extensions len */ + tmplen = ((*data) << 8) | *(data + 1); + data += EXTENSIONS_LEN_LEN; + if (data + tmplen > dataend) + goto end; + + /* Loop through all extensions */ + while (tmplen > EXTENSION_TYPE_LEN + EXTENSION_SIZE_LEN) { + type = ((*data) << 8) | *(data + 1); + data += EXTENSION_TYPE_LEN; + size = ((*data) << 8) | *(data + 1); + data += EXTENSION_SIZE_LEN; + if (data + size > dataend) + goto end; + + if (type == TLSEXT_TYPE_session_ticket) { + if (currtest == TEST_SET_SESSION_TICK_DATA_TLS_1_2 + || currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) { + if (size == strlen(dummytick) + && memcmp(data, dummytick, size) == 0) { + /* Ticket data is as we expected */ + testresult = 1; + } else { + printf("Received session ticket is not as expected\n"); + } + break; + } + } + + tmplen -= EXTENSION_TYPE_LEN + EXTENSION_SIZE_LEN + size; + data += size; + } + + end: + SSL_free(con); + SSL_CTX_free(ctx); + if (!testresult) { + printf("ClientHello test: FAILED (Test %d)\n", currtest); + break; + } + } + + ERR_free_strings(); + ERR_remove_thread_state(NULL); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + CRYPTO_mem_leaks(err); + + return testresult?0:1; +}