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 */