X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=ssl%2Fheartbeat_test.c;h=c77e7f7065e789c7cf3c0768e7d2c4cdfa614891;hb=1d97c8435171a7af575f73c526d79e1ef0ee5960;hp=eb08ee6b0d24856130dc94ca978c646e7c813a3d;hpb=6af080acaf57c74e3cd96642f2900fa602407d10;p=thirdparty%2Fopenssl.git diff --git a/ssl/heartbeat_test.c b/ssl/heartbeat_test.c index eb08ee6b0d..c77e7f7065 100644 --- a/ssl/heartbeat_test.c +++ b/ssl/heartbeat_test.c @@ -1,5 +1,5 @@ /* test/heartbeat_test.c */ -/* +/*- * Unit test for TLS heartbeats. * * Acts as a regression test against the Heartbleed bug (CVE-2014-0160). @@ -38,17 +38,23 @@ * http://mike-bland.com/tags/heartbleed.html */ +#define OPENSSL_UNIT_TEST + #include "../ssl/ssl_locl.h" + +#include "testutil.h" #include #include #include #include +#if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST) + /* As per https://tools.ietf.org/html/rfc6520#section-4 */ -static const int MIN_PADDING_SIZE = 16; +#define MIN_PADDING_SIZE 16 /* Maximum number of payload characters to print as test output */ -static const int MAX_PRINTABLE_CHARACTERS = 1024; +#define MAX_PRINTABLE_CHARACTERS 1024 typedef struct heartbeat_test_fixture { @@ -68,6 +74,7 @@ static HEARTBEAT_TEST_FIXTURE set_up(const char* const test_case_name, const SSL_METHOD* meth) { HEARTBEAT_TEST_FIXTURE fixture; + int setup_ok = 1; memset(&fixture, 0, sizeof(fixture)); fixture.test_case_name = test_case_name; @@ -75,7 +82,8 @@ static HEARTBEAT_TEST_FIXTURE set_up(const char* const test_case_name, if (!fixture.ctx) { fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n", - test_case_name); + test_case_name); + setup_ok = 0; goto fail; } @@ -83,14 +91,34 @@ static HEARTBEAT_TEST_FIXTURE set_up(const char* const test_case_name, if (!fixture.s) { fprintf(stderr, "Failed to allocate SSL for test: %s\n", test_case_name); + setup_ok = 0; + goto fail; + } + + if (!ssl_init_wbio_buffer(fixture.s, 1)) + { + fprintf(stderr, "Failed to set up wbio buffer for test: %s\n", + test_case_name); + setup_ok = 0; + goto fail; + } + + if (!ssl3_setup_buffers(fixture.s)) + { + fprintf(stderr, "Failed to setup buffers for test: %s\n", + test_case_name); + setup_ok = 0; goto fail; } - ssl_init_wbio_buffer(fixture.s, 1); - ssl3_setup_buffers(fixture.s); + /* Clear the memory for the return buffer, since this isn't automatically + * zeroed in opt mode and will cause spurious test failures that will change + * with each execution. + */ + memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len); fail: - if (!fixture.s) + if (!setup_ok) { ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); @@ -144,21 +172,21 @@ static HEARTBEAT_TEST_FIXTURE set_up_tls(const char* const test_case_name) static void tear_down(HEARTBEAT_TEST_FIXTURE fixture) { ERR_print_errors_fp(stderr); - memset(fixture.s, 0, sizeof(*fixture.s)); SSL_free(fixture.s); - memset(fixture.ctx, 0, sizeof(*fixture.ctx)); SSL_CTX_free(fixture.ctx); } static void print_payload(const char* const prefix, const unsigned char *payload, const int n) { - const int end = n < MAX_PRINTABLE_CHARACTERS ? n : MAX_PRINTABLE_CHARACTERS; + const int end = n < MAX_PRINTABLE_CHARACTERS ? n + : MAX_PRINTABLE_CHARACTERS; + int i = 0; + printf("%s %d character%s", prefix, n, n == 1 ? "" : "s"); if (end != n) printf(" (first %d shown)", end); printf("\n \""); - int i = 0; for (; i != end; ++i) { const unsigned char c = payload[i]; @@ -166,7 +194,7 @@ static void print_payload(const char* const prefix, else printf("\\x%02x", c); } printf("\"\n"); -} + } static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) { @@ -174,6 +202,9 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) SSL* s = fixture.s; unsigned char *payload = fixture.payload; unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1]; + int return_value; + unsigned const char *p; + int actual_payload_len; s->s3->rrec.data = payload; s->s3->rrec.length = strlen((const char*)payload); @@ -184,7 +215,7 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) * point */ memcpy((char *)sent_buf, (const char*)payload, sizeof(sent_buf)); - int return_value = fixture.process_heartbeat(s); + return_value = fixture.process_heartbeat(s); if (return_value != fixture.expected_return_value) { @@ -195,9 +226,9 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) } /* If there is any byte alignment, it will be stored in wbuf.offset. */ - unsigned const char *p = &(s->s3->wbuf.buf[ + p = &(s->s3->wbuf.buf[ fixture.return_payload_offset + s->s3->wbuf.offset]); - int actual_payload_len = 0; + actual_payload_len = 0; n2s(p, actual_payload_len); if (actual_payload_len != fixture.expected_payload_len) @@ -211,7 +242,7 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) } else { - char* actual_payload = strndup((const char*)p, actual_payload_len); + char* actual_payload = BUF_strndup((const char*)p, actual_payload_len); if (strcmp(actual_payload, fixture.expected_return_payload) != 0) { printf("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n", @@ -219,7 +250,7 @@ static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture) actual_payload); result = 1; } - free(actual_payload); + OPENSSL_free(actual_payload); } if (result != 0) @@ -236,19 +267,17 @@ static int honest_payload_size(unsigned char payload_buf[]) } #define SETUP_HEARTBEAT_TEST_FIXTURE(type)\ - HEARTBEAT_TEST_FIXTURE fixture = set_up_##type(__func__);\ - int result = 0 + SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type) #define EXECUTE_HEARTBEAT_TEST()\ - if (execute_heartbeat(fixture) != 0) result = 1;\ - tear_down(fixture);\ - return result + EXECUTE_TEST(execute_heartbeat, tear_down) static int test_dtls1_not_bleeding() { SETUP_HEARTBEAT_TEST_FIXTURE(dtls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding" + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS+4] = + " Not bleeding, sixteen spaces of padding" " "; const int payload_buf_len = honest_payload_size(payload_buf); @@ -262,13 +291,15 @@ static int test_dtls1_not_bleeding() static int test_dtls1_not_bleeding_empty_payload() { + int payload_buf_len; + SETUP_HEARTBEAT_TEST_FIXTURE(dtls); /* Three-byte pad at the beginning for type and payload length, plus a NUL * at the end */ - unsigned char payload_buf[4 + MIN_PADDING_SIZE]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; - const int payload_buf_len = honest_payload_size(payload_buf); + unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS]; + memset(payload_buf, ' ', MIN_PADDING_SIZE+3); + payload_buf[MIN_PADDING_SIZE+3] = '\0'; + payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; fixture.sent_payload_len = payload_buf_len; @@ -282,7 +313,8 @@ static int test_dtls1_heartbleed() { SETUP_HEARTBEAT_TEST_FIXTURE(dtls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " HEARTBLEED "; + unsigned char payload_buf[4+MAX_PRINTABLE_CHARACTERS] = + " HEARTBLEED "; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -297,9 +329,9 @@ static int test_dtls1_heartbleed_empty_payload() SETUP_HEARTBEAT_TEST_FIXTURE(dtls); /* Excluding the NUL at the end, one byte short of type + payload length + * minimum padding */ - unsigned char payload_buf[MIN_PADDING_SIZE + 3]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4]; + memset(payload_buf, ' ', MIN_PADDING_SIZE+2); + payload_buf[MIN_PADDING_SIZE+2] = '\0'; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -330,8 +362,9 @@ static int test_tls1_not_bleeding() { SETUP_HEARTBEAT_TEST_FIXTURE(tls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding" - " "; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS+4] = + " Not bleeding, sixteen spaces of padding" + " "; const int payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; @@ -344,13 +377,15 @@ static int test_tls1_not_bleeding() static int test_tls1_not_bleeding_empty_payload() { + int payload_buf_len; + SETUP_HEARTBEAT_TEST_FIXTURE(tls); /* Three-byte pad at the beginning for type and payload length, plus a NUL * at the end */ - unsigned char payload_buf[4 + MIN_PADDING_SIZE]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; - const int payload_buf_len = honest_payload_size(payload_buf); + unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS]; + memset(payload_buf, ' ', MIN_PADDING_SIZE+3); + payload_buf[MIN_PADDING_SIZE+3] = '\0'; + payload_buf_len = honest_payload_size(payload_buf); fixture.payload = &payload_buf[0]; fixture.sent_payload_len = payload_buf_len; @@ -364,7 +399,8 @@ static int test_tls1_heartbleed() { SETUP_HEARTBEAT_TEST_FIXTURE(tls); /* Three-byte pad at the beginning for type and payload length */ - unsigned char payload_buf[] = " HEARTBLEED "; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS+4] = + " HEARTBLEED "; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -379,9 +415,9 @@ static int test_tls1_heartbleed_empty_payload() SETUP_HEARTBEAT_TEST_FIXTURE(tls); /* Excluding the NUL at the end, one byte short of type + payload length + * minimum padding */ - unsigned char payload_buf[MIN_PADDING_SIZE + 3]; - memset(payload_buf, ' ', sizeof(payload_buf)); - payload_buf[sizeof(payload_buf) - 1] = '\0'; + unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4]; + memset(payload_buf, ' ', MIN_PADDING_SIZE+2); + payload_buf[MIN_PADDING_SIZE+2] = '\0'; fixture.payload = &payload_buf[0]; fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS; @@ -396,29 +432,30 @@ static int test_tls1_heartbleed_empty_payload() int main(int argc, char *argv[]) { + int result = 0; + SSL_library_init(); SSL_load_error_strings(); - const int num_failed = test_dtls1_not_bleeding() + - test_dtls1_not_bleeding_empty_payload() + - test_dtls1_heartbleed() + - test_dtls1_heartbleed_empty_payload() + - /* The following test causes an assertion failure at - * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g: */ - (OPENSSL_VERSION_NUMBER >= 0x1000107fL ? - test_dtls1_heartbleed_excessive_plaintext_length() : 0) + - test_tls1_not_bleeding() + - test_tls1_not_bleeding_empty_payload() + - test_tls1_heartbleed() + - test_tls1_heartbleed_empty_payload() + - 0; - + ADD_TEST(test_dtls1_not_bleeding); + ADD_TEST(test_dtls1_not_bleeding_empty_payload); + ADD_TEST(test_dtls1_heartbleed); + ADD_TEST(test_dtls1_heartbleed_empty_payload); + ADD_TEST(test_dtls1_heartbleed_excessive_plaintext_length); + ADD_TEST(test_tls1_not_bleeding); + ADD_TEST(test_tls1_not_bleeding_empty_payload); + ADD_TEST(test_tls1_heartbleed); + ADD_TEST(test_tls1_heartbleed_empty_payload); + + result = run_tests(argv[0]); ERR_print_errors_fp(stderr); + return result; + } - if (num_failed != 0) - { - printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : ""); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; +#else /* OPENSSL_NO_HEARTBEATS*/ + +int main(int argc, char *argv[]) + { + return EXIT_SUCCESS; } +#endif /* OPENSSL_NO_HEARTBEATS */