2 * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * Unit test for TLS heartbeats.
13 * Acts as a regression test against the Heartbleed bug (CVE-2014-0160).
15 * Author: Mike Bland (mbland@acm.org, http://mike-bland.com/)
17 * License: Creative Commons Attribution 4.0 International (CC By 4.0)
18 * http://creativecommons.org/licenses/by/4.0/deed.en_US
22 * The program returns zero on success. It will print a message with a count
23 * of the number of failed tests and return nonzero if any tests fail.
25 * It will print the contents of the request and response buffers for each
26 * failing test. In a "fixed" version, all the tests should pass and there
27 * should be no output.
29 * In a "bleeding" version, you'll see:
31 * test_dtls1_heartbleed failed:
32 * expected payload len: 0
36 * received 1024 characters
37 * "HEARTBLEED \xde\xad\xbe\xef..."
38 * ** test_dtls1_heartbleed failed **
40 * The contents of the returned buffer in the failing test will depend on the
41 * contents of memory on your machine.
45 * http://mike-bland.com/2014/04/12/heartbleed.html
46 * http://mike-bland.com/tags/heartbleed.html
49 #define OPENSSL_UNIT_TEST
51 #include "../ssl/ssl_locl.h"
59 #if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST)
61 /* As per https://tools.ietf.org/html/rfc6520#section-4 */
62 # define MIN_PADDING_SIZE 16
64 /* Maximum number of payload characters to print as test output */
65 # define MAX_PRINTABLE_CHARACTERS 1024
67 typedef struct heartbeat_test_fixture {
70 const char *test_case_name;
71 int (*process_heartbeat) (SSL *s, unsigned char *p, unsigned int length);
72 unsigned char *payload;
74 int expected_return_value;
75 int return_payload_offset;
76 int expected_payload_len;
77 const char *expected_return_payload;
78 } HEARTBEAT_TEST_FIXTURE;
80 static HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name,
81 const SSL_METHOD *meth)
83 HEARTBEAT_TEST_FIXTURE fixture;
85 memset(&fixture, 0, sizeof(fixture));
86 fixture.test_case_name = test_case_name;
88 fixture.ctx = SSL_CTX_new(meth);
90 fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n",
96 fixture.s = SSL_new(fixture.ctx);
98 fprintf(stderr, "Failed to allocate SSL for test: %s\n",
104 if (!ssl_init_wbio_buffer(fixture.s)) {
105 fprintf(stderr, "Failed to set up wbio buffer for test: %s\n",
111 if (!ssl3_setup_buffers(fixture.s)) {
112 fprintf(stderr, "Failed to setup buffers for test: %s\n",
119 * Clear the memory for the return buffer, since this isn't automatically
120 * zeroed in opt mode and will cause spurious test failures that will
121 * change with each execution.
123 memset(fixture.s->rlayer.wbuf.buf, 0, fixture.s->rlayer.wbuf.len);
127 ERR_print_errors_fp(stderr);
133 static HEARTBEAT_TEST_FIXTURE set_up_dtls(const char *const test_case_name)
135 HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
136 DTLS_server_method());
137 fixture.process_heartbeat = dtls1_process_heartbeat;
140 * As per dtls1_get_record(), skipping the following from the beginning
141 * of the returned heartbeat message: type-1 byte; version-2 bytes;
142 * sequence number-8 bytes; length-2 bytes And then skipping the 1-byte
143 * type encoded by process_heartbeat for a total of 14 bytes, at which
144 * point we can grab the length and the payload we seek.
146 fixture.return_payload_offset = 14;
150 /* Needed by ssl3_write_bytes() */
151 static int dummy_handshake(SSL *s)
156 static void tear_down(HEARTBEAT_TEST_FIXTURE fixture)
158 ERR_print_errors_fp(stderr);
160 SSL_CTX_free(fixture.ctx);
163 static void print_payload(const char *const prefix,
164 const unsigned char *payload, const int n)
166 const int end = n < MAX_PRINTABLE_CHARACTERS ? n
167 : MAX_PRINTABLE_CHARACTERS;
170 printf("%s %d character%s", prefix, n, n == 1 ? "" : "s");
172 printf(" (first %d shown)", end);
175 for (; i != end; ++i) {
176 const unsigned char c = payload[i];
180 printf("\\x%02x", c);
185 static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
189 unsigned char *payload = fixture.payload;
190 unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1];
192 unsigned const char *p;
193 int actual_payload_len;
195 s->rlayer.rrec.data = payload;
196 s->rlayer.rrec.length = strlen((const char *)payload);
197 *payload++ = TLS1_HB_REQUEST;
198 s2n(fixture.sent_payload_len, payload);
201 * Make a local copy of the request, since it gets overwritten at some
204 memcpy(sent_buf, payload, sizeof(sent_buf));
206 return_value = fixture.process_heartbeat(s, s->rlayer.rrec.data,
207 s->rlayer.rrec.length);
209 if (return_value != fixture.expected_return_value) {
210 printf("%s failed: expected return value %d, received %d\n",
211 fixture.test_case_name, fixture.expected_return_value,
217 * If there is any byte alignment, it will be stored in wbuf.offset.
220 wbuf.buf[fixture.return_payload_offset + s->rlayer.wbuf.offset]);
221 actual_payload_len = 0;
222 n2s(p, actual_payload_len);
224 if (actual_payload_len != fixture.expected_payload_len) {
225 printf("%s failed:\n expected payload len: %d\n received: %d\n",
226 fixture.test_case_name, fixture.expected_payload_len,
228 print_payload("sent", sent_buf, strlen((const char *)sent_buf));
229 print_payload("received", p, actual_payload_len);
232 char *actual_payload =
233 OPENSSL_strndup((const char *)p, actual_payload_len);
234 if (strcmp(actual_payload, fixture.expected_return_payload) != 0) {
236 ("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n",
237 fixture.test_case_name, fixture.expected_return_payload,
241 OPENSSL_free(actual_payload);
245 printf("** %s failed **\n--------\n", fixture.test_case_name);
250 static int honest_payload_size(unsigned char payload_buf[])
252 /* Omit three-byte pad at the beginning for type and payload length */
253 return strlen((const char *)&payload_buf[3]) - MIN_PADDING_SIZE;
256 # define SETUP_HEARTBEAT_TEST_FIXTURE(type)\
257 SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type)
259 # define EXECUTE_HEARTBEAT_TEST()\
260 EXECUTE_TEST(execute_heartbeat, tear_down)
262 static int test_dtls1_not_bleeding()
264 SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
265 /* Three-byte pad at the beginning for type and payload length */
266 unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4] =
267 " Not bleeding, sixteen spaces of padding" " ";
268 const int payload_buf_len = honest_payload_size(payload_buf);
270 fixture.payload = &payload_buf[0];
271 fixture.sent_payload_len = payload_buf_len;
272 fixture.expected_return_value = 0;
273 fixture.expected_payload_len = payload_buf_len;
274 fixture.expected_return_payload =
275 "Not bleeding, sixteen spaces of padding";
276 EXECUTE_HEARTBEAT_TEST();
279 static int test_dtls1_not_bleeding_empty_payload()
283 SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
285 * Three-byte pad at the beginning for type and payload length, plus a
288 unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS];
289 memset(payload_buf, ' ', MIN_PADDING_SIZE + 3);
290 payload_buf[MIN_PADDING_SIZE + 3] = '\0';
291 payload_buf_len = honest_payload_size(payload_buf);
293 fixture.payload = &payload_buf[0];
294 fixture.sent_payload_len = payload_buf_len;
295 fixture.expected_return_value = 0;
296 fixture.expected_payload_len = payload_buf_len;
297 fixture.expected_return_payload = "";
298 EXECUTE_HEARTBEAT_TEST();
301 static int test_dtls1_heartbleed()
303 SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
304 /* Three-byte pad at the beginning for type and payload length */
305 unsigned char payload_buf[4 + MAX_PRINTABLE_CHARACTERS] =
308 fixture.payload = &payload_buf[0];
309 fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
310 fixture.expected_return_value = 0;
311 fixture.expected_payload_len = 0;
312 fixture.expected_return_payload = "";
313 EXECUTE_HEARTBEAT_TEST();
316 static int test_dtls1_heartbleed_empty_payload()
318 SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
320 * Excluding the NUL at the end, one byte short of type + payload length
323 unsigned char payload_buf[MAX_PRINTABLE_CHARACTERS + 4];
324 memset(payload_buf, ' ', MIN_PADDING_SIZE + 2);
325 payload_buf[MIN_PADDING_SIZE + 2] = '\0';
327 fixture.payload = &payload_buf[0];
328 fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
329 fixture.expected_return_value = 0;
330 fixture.expected_payload_len = 0;
331 fixture.expected_return_payload = "";
332 EXECUTE_HEARTBEAT_TEST();
335 static int test_dtls1_heartbleed_excessive_plaintext_length()
337 SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
339 * Excluding the NUL at the end, one byte in excess of maximum allowed
340 * heartbeat message length
342 unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2];
343 memset(payload_buf, ' ', sizeof(payload_buf));
344 payload_buf[sizeof(payload_buf) - 1] = '\0';
346 fixture.payload = &payload_buf[0];
347 fixture.sent_payload_len = honest_payload_size(payload_buf);
348 fixture.expected_return_value = 0;
349 fixture.expected_payload_len = 0;
350 fixture.expected_return_payload = "";
351 EXECUTE_HEARTBEAT_TEST();
354 # undef EXECUTE_HEARTBEAT_TEST
355 # undef SETUP_HEARTBEAT_TEST_FIXTURE
357 int main(int argc, char *argv[])
361 ADD_TEST(test_dtls1_not_bleeding);
362 ADD_TEST(test_dtls1_not_bleeding_empty_payload);
363 ADD_TEST(test_dtls1_heartbleed);
364 ADD_TEST(test_dtls1_heartbleed_empty_payload);
365 ADD_TEST(test_dtls1_heartbleed_excessive_plaintext_length);
367 result = run_tests(argv[0]);
368 ERR_print_errors_fp(stderr);
372 #else /* OPENSSL_NO_HEARTBEATS */
374 int main(int argc, char *argv[])
378 #endif /* OPENSSL_NO_HEARTBEATS */