1*0a6a1f1dSLionel Sambuc /* test/heartbeat_test.c */
2*0a6a1f1dSLionel Sambuc /*-
3*0a6a1f1dSLionel Sambuc * Unit test for TLS heartbeats.
4*0a6a1f1dSLionel Sambuc *
5*0a6a1f1dSLionel Sambuc * Acts as a regression test against the Heartbleed bug (CVE-2014-0160).
6*0a6a1f1dSLionel Sambuc *
7*0a6a1f1dSLionel Sambuc * Author: Mike Bland (mbland@acm.org, http://mike-bland.com/)
8*0a6a1f1dSLionel Sambuc * Date: 2014-04-12
9*0a6a1f1dSLionel Sambuc * License: Creative Commons Attribution 4.0 International (CC By 4.0)
10*0a6a1f1dSLionel Sambuc * http://creativecommons.org/licenses/by/4.0/deed.en_US
11*0a6a1f1dSLionel Sambuc *
12*0a6a1f1dSLionel Sambuc * OUTPUT
13*0a6a1f1dSLionel Sambuc * ------
14*0a6a1f1dSLionel Sambuc * The program returns zero on success. It will print a message with a count
15*0a6a1f1dSLionel Sambuc * of the number of failed tests and return nonzero if any tests fail.
16*0a6a1f1dSLionel Sambuc *
17*0a6a1f1dSLionel Sambuc * It will print the contents of the request and response buffers for each
18*0a6a1f1dSLionel Sambuc * failing test. In a "fixed" version, all the tests should pass and there
19*0a6a1f1dSLionel Sambuc * should be no output.
20*0a6a1f1dSLionel Sambuc *
21*0a6a1f1dSLionel Sambuc * In a "bleeding" version, you'll see:
22*0a6a1f1dSLionel Sambuc *
23*0a6a1f1dSLionel Sambuc * test_dtls1_heartbleed failed:
24*0a6a1f1dSLionel Sambuc * expected payload len: 0
25*0a6a1f1dSLionel Sambuc * received: 1024
26*0a6a1f1dSLionel Sambuc * sent 26 characters
27*0a6a1f1dSLionel Sambuc * "HEARTBLEED "
28*0a6a1f1dSLionel Sambuc * received 1024 characters
29*0a6a1f1dSLionel Sambuc * "HEARTBLEED \xde\xad\xbe\xef..."
30*0a6a1f1dSLionel Sambuc * ** test_dtls1_heartbleed failed **
31*0a6a1f1dSLionel Sambuc *
32*0a6a1f1dSLionel Sambuc * The contents of the returned buffer in the failing test will depend on the
33*0a6a1f1dSLionel Sambuc * contents of memory on your machine.
34*0a6a1f1dSLionel Sambuc *
35*0a6a1f1dSLionel Sambuc * MORE INFORMATION
36*0a6a1f1dSLionel Sambuc * ----------------
37*0a6a1f1dSLionel Sambuc * http://mike-bland.com/2014/04/12/heartbleed.html
38*0a6a1f1dSLionel Sambuc * http://mike-bland.com/tags/heartbleed.html
39*0a6a1f1dSLionel Sambuc */
40*0a6a1f1dSLionel Sambuc
41*0a6a1f1dSLionel Sambuc #define OPENSSL_UNIT_TEST
42*0a6a1f1dSLionel Sambuc
43*0a6a1f1dSLionel Sambuc #include "../test/testutil.h"
44*0a6a1f1dSLionel Sambuc
45*0a6a1f1dSLionel Sambuc #include "../ssl/ssl_locl.h"
46*0a6a1f1dSLionel Sambuc #include <ctype.h>
47*0a6a1f1dSLionel Sambuc #include <stdio.h>
48*0a6a1f1dSLionel Sambuc #include <stdlib.h>
49*0a6a1f1dSLionel Sambuc #include <string.h>
50*0a6a1f1dSLionel Sambuc
51*0a6a1f1dSLionel Sambuc #if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST)
52*0a6a1f1dSLionel Sambuc
53*0a6a1f1dSLionel Sambuc /* As per https://tools.ietf.org/html/rfc6520#section-4 */
54*0a6a1f1dSLionel Sambuc # define MIN_PADDING_SIZE 16
55*0a6a1f1dSLionel Sambuc
56*0a6a1f1dSLionel Sambuc /* Maximum number of payload characters to print as test output */
57*0a6a1f1dSLionel Sambuc # define MAX_PRINTABLE_CHARACTERS 1024
58*0a6a1f1dSLionel Sambuc
59*0a6a1f1dSLionel Sambuc typedef struct heartbeat_test_fixture {
60*0a6a1f1dSLionel Sambuc SSL_CTX *ctx;
61*0a6a1f1dSLionel Sambuc SSL *s;
62*0a6a1f1dSLionel Sambuc const char *test_case_name;
63*0a6a1f1dSLionel Sambuc int (*process_heartbeat) (SSL *s);
64*0a6a1f1dSLionel Sambuc unsigned char *payload;
65*0a6a1f1dSLionel Sambuc int sent_payload_len;
66*0a6a1f1dSLionel Sambuc int expected_return_value;
67*0a6a1f1dSLionel Sambuc int return_payload_offset;
68*0a6a1f1dSLionel Sambuc int expected_payload_len;
69*0a6a1f1dSLionel Sambuc const char *expected_return_payload;
70*0a6a1f1dSLionel Sambuc } HEARTBEAT_TEST_FIXTURE;
71*0a6a1f1dSLionel Sambuc
set_up(const char * const test_case_name,const SSL_METHOD * meth)72*0a6a1f1dSLionel Sambuc static HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name,
73*0a6a1f1dSLionel Sambuc const SSL_METHOD *meth)
74*0a6a1f1dSLionel Sambuc {
75*0a6a1f1dSLionel Sambuc HEARTBEAT_TEST_FIXTURE fixture;
76*0a6a1f1dSLionel Sambuc int setup_ok = 1;
77*0a6a1f1dSLionel Sambuc memset(&fixture, 0, sizeof(fixture));
78*0a6a1f1dSLionel Sambuc fixture.test_case_name = test_case_name;
79*0a6a1f1dSLionel Sambuc
80*0a6a1f1dSLionel Sambuc fixture.ctx = SSL_CTX_new(meth);
81*0a6a1f1dSLionel Sambuc if (!fixture.ctx) {
82*0a6a1f1dSLionel Sambuc fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n",
83*0a6a1f1dSLionel Sambuc test_case_name);
84*0a6a1f1dSLionel Sambuc setup_ok = 0;
85*0a6a1f1dSLionel Sambuc goto fail;
86*0a6a1f1dSLionel Sambuc }
87*0a6a1f1dSLionel Sambuc
88*0a6a1f1dSLionel Sambuc fixture.s = SSL_new(fixture.ctx);
89*0a6a1f1dSLionel Sambuc if (!fixture.s) {
90*0a6a1f1dSLionel Sambuc fprintf(stderr, "Failed to allocate SSL for test: %s\n",
91*0a6a1f1dSLionel Sambuc test_case_name);
92*0a6a1f1dSLionel Sambuc setup_ok = 0;
93*0a6a1f1dSLionel Sambuc goto fail;
94*0a6a1f1dSLionel Sambuc }
95*0a6a1f1dSLionel Sambuc
96*0a6a1f1dSLionel Sambuc if (!ssl_init_wbio_buffer(fixture.s, 1)) {
97*0a6a1f1dSLionel Sambuc fprintf(stderr, "Failed to set up wbio buffer for test: %s\n",
98*0a6a1f1dSLionel Sambuc test_case_name);
99*0a6a1f1dSLionel Sambuc setup_ok = 0;
100*0a6a1f1dSLionel Sambuc goto fail;
101*0a6a1f1dSLionel Sambuc }
102*0a6a1f1dSLionel Sambuc
103*0a6a1f1dSLionel Sambuc if (!ssl3_setup_buffers(fixture.s)) {
104*0a6a1f1dSLionel Sambuc fprintf(stderr, "Failed to setup buffers for test: %s\n",
105*0a6a1f1dSLionel Sambuc test_case_name);
106*0a6a1f1dSLionel Sambuc setup_ok = 0;
107*0a6a1f1dSLionel Sambuc goto fail;
108*0a6a1f1dSLionel Sambuc }
109*0a6a1f1dSLionel Sambuc
110*0a6a1f1dSLionel Sambuc /*
111*0a6a1f1dSLionel Sambuc * Clear the memory for the return buffer, since this isn't automatically
112*0a6a1f1dSLionel Sambuc * zeroed in opt mode and will cause spurious test failures that will
113*0a6a1f1dSLionel Sambuc * change with each execution.
114*0a6a1f1dSLionel Sambuc */
115*0a6a1f1dSLionel Sambuc memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len);
116*0a6a1f1dSLionel Sambuc
117*0a6a1f1dSLionel Sambuc fail:
118*0a6a1f1dSLionel Sambuc if (!setup_ok) {
119*0a6a1f1dSLionel Sambuc ERR_print_errors_fp(stderr);
120*0a6a1f1dSLionel Sambuc exit(EXIT_FAILURE);
121*0a6a1f1dSLionel Sambuc }
122*0a6a1f1dSLionel Sambuc return fixture;
123*0a6a1f1dSLionel Sambuc }
124*0a6a1f1dSLionel Sambuc
set_up_dtls(const char * const test_case_name)125*0a6a1f1dSLionel Sambuc static HEARTBEAT_TEST_FIXTURE set_up_dtls(const char *const test_case_name)
126*0a6a1f1dSLionel Sambuc {
127*0a6a1f1dSLionel Sambuc HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
128*0a6a1f1dSLionel Sambuc DTLSv1_server_method());
129*0a6a1f1dSLionel Sambuc fixture.process_heartbeat = dtls1_process_heartbeat;
130*0a6a1f1dSLionel Sambuc
131*0a6a1f1dSLionel Sambuc /*
132*0a6a1f1dSLionel Sambuc * As per dtls1_get_record(), skipping the following from the beginning
133*0a6a1f1dSLionel Sambuc * of the returned heartbeat message: type-1 byte; version-2 bytes;
134*0a6a1f1dSLionel Sambuc * sequence number-8 bytes; length-2 bytes And then skipping the 1-byte
135*0a6a1f1dSLionel Sambuc * type encoded by process_heartbeat for a total of 14 bytes, at which
136*0a6a1f1dSLionel Sambuc * point we can grab the length and the payload we seek.
137*0a6a1f1dSLionel Sambuc */
138*0a6a1f1dSLionel Sambuc fixture.return_payload_offset = 14;
139*0a6a1f1dSLionel Sambuc return fixture;
140*0a6a1f1dSLionel Sambuc }
141*0a6a1f1dSLionel Sambuc
142*0a6a1f1dSLionel Sambuc /* Needed by ssl3_write_bytes() */
dummy_handshake(SSL * s)143*0a6a1f1dSLionel Sambuc static int dummy_handshake(SSL *s)
144*0a6a1f1dSLionel Sambuc {
145*0a6a1f1dSLionel Sambuc return 1;
146*0a6a1f1dSLionel Sambuc }
147*0a6a1f1dSLionel Sambuc
set_up_tls(const char * const test_case_name)148*0a6a1f1dSLionel Sambuc static HEARTBEAT_TEST_FIXTURE set_up_tls(const char *const test_case_name)
149*0a6a1f1dSLionel Sambuc {
150*0a6a1f1dSLionel Sambuc HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
151*0a6a1f1dSLionel Sambuc TLSv1_server_method());
152*0a6a1f1dSLionel Sambuc fixture.process_heartbeat = tls1_process_heartbeat;
153*0a6a1f1dSLionel Sambuc fixture.s->handshake_func = dummy_handshake;
154*0a6a1f1dSLionel Sambuc
155*0a6a1f1dSLionel Sambuc /*
156*0a6a1f1dSLionel Sambuc * As per do_ssl3_write(), skipping the following from the beginning of
157*0a6a1f1dSLionel Sambuc * the returned heartbeat message: type-1 byte; version-2 bytes; length-2
158*0a6a1f1dSLionel Sambuc * bytes And then skipping the 1-byte type encoded by process_heartbeat
159*0a6a1f1dSLionel Sambuc * for a total of 6 bytes, at which point we can grab the length and the
160*0a6a1f1dSLionel Sambuc * payload we seek.
161*0a6a1f1dSLionel Sambuc */
162*0a6a1f1dSLionel Sambuc fixture.return_payload_offset = 6;
163*0a6a1f1dSLionel Sambuc return fixture;
164*0a6a1f1dSLionel Sambuc }
165*0a6a1f1dSLionel Sambuc
tear_down(HEARTBEAT_TEST_FIXTURE fixture)166*0a6a1f1dSLionel Sambuc static void tear_down(HEARTBEAT_TEST_FIXTURE fixture)
167*0a6a1f1dSLionel Sambuc {
168*0a6a1f1dSLionel Sambuc ERR_print_errors_fp(stderr);
169*0a6a1f1dSLionel Sambuc SSL_free(fixture.s);
170*0a6a1f1dSLionel Sambuc SSL_CTX_free(fixture.ctx);
171*0a6a1f1dSLionel Sambuc }
172*0a6a1f1dSLionel Sambuc
print_payload(const char * const prefix,const unsigned char * payload,const int n)173*0a6a1f1dSLionel Sambuc static void print_payload(const char *const prefix,
174*0a6a1f1dSLionel Sambuc const unsigned char *payload, const int n)
175*0a6a1f1dSLionel Sambuc {
176*0a6a1f1dSLionel Sambuc const int end = n < MAX_PRINTABLE_CHARACTERS ? n
177*0a6a1f1dSLionel Sambuc : MAX_PRINTABLE_CHARACTERS;
178*0a6a1f1dSLionel Sambuc int i = 0;
179*0a6a1f1dSLionel Sambuc
180*0a6a1f1dSLionel Sambuc printf("%s %d character%s", prefix, n, n == 1 ? "" : "s");
181*0a6a1f1dSLionel Sambuc if (end != n)
182*0a6a1f1dSLionel Sambuc printf(" (first %d shown)", end);
183*0a6a1f1dSLionel Sambuc printf("\n \"");
184*0a6a1f1dSLionel Sambuc
185*0a6a1f1dSLionel Sambuc for (; i != end; ++i) {
186*0a6a1f1dSLionel Sambuc const unsigned char c = payload[i];
187*0a6a1f1dSLionel Sambuc if (isprint(c))
188*0a6a1f1dSLionel Sambuc fputc(c, stdout);
189*0a6a1f1dSLionel Sambuc else
190*0a6a1f1dSLionel Sambuc printf("\\x%02x", c);
191*0a6a1f1dSLionel Sambuc }
192*0a6a1f1dSLionel Sambuc printf("\"\n");
193*0a6a1f1dSLionel Sambuc }
194*0a6a1f1dSLionel Sambuc
execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)195*0a6a1f1dSLionel Sambuc static int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
196*0a6a1f1dSLionel Sambuc {
197*0a6a1f1dSLionel Sambuc int result = 0;
198*0a6a1f1dSLionel Sambuc SSL *s = fixture.s;
199*0a6a1f1dSLionel Sambuc unsigned char *payload = fixture.payload;
200*0a6a1f1dSLionel Sambuc unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1];
201*0a6a1f1dSLionel Sambuc int return_value;
202*0a6a1f1dSLionel Sambuc unsigned const char *p;
203*0a6a1f1dSLionel Sambuc int actual_payload_len;
204*0a6a1f1dSLionel Sambuc
205*0a6a1f1dSLionel Sambuc s->s3->rrec.data = payload;
206*0a6a1f1dSLionel Sambuc s->s3->rrec.length = strlen((const char *)payload);
207*0a6a1f1dSLionel Sambuc *payload++ = TLS1_HB_REQUEST;
208*0a6a1f1dSLionel Sambuc s2n(fixture.sent_payload_len, payload);
209*0a6a1f1dSLionel Sambuc
210*0a6a1f1dSLionel Sambuc /*
211*0a6a1f1dSLionel Sambuc * Make a local copy of the request, since it gets overwritten at some
212*0a6a1f1dSLionel Sambuc * point
213*0a6a1f1dSLionel Sambuc */
214*0a6a1f1dSLionel Sambuc memcpy((char *)sent_buf, (const char *)payload, sizeof(sent_buf));
215*0a6a1f1dSLionel Sambuc
216*0a6a1f1dSLionel Sambuc return_value = fixture.process_heartbeat(s);
217*0a6a1f1dSLionel Sambuc
218*0a6a1f1dSLionel Sambuc if (return_value != fixture.expected_return_value) {
219*0a6a1f1dSLionel Sambuc printf("%s failed: expected return value %d, received %d\n",
220*0a6a1f1dSLionel Sambuc fixture.test_case_name, fixture.expected_return_value,
221*0a6a1f1dSLionel Sambuc return_value);
222*0a6a1f1dSLionel Sambuc result = 1;
223*0a6a1f1dSLionel Sambuc }
224*0a6a1f1dSLionel Sambuc
225*0a6a1f1dSLionel Sambuc /*
226*0a6a1f1dSLionel Sambuc * If there is any byte alignment, it will be stored in wbuf.offset.
227*0a6a1f1dSLionel Sambuc */
228*0a6a1f1dSLionel Sambuc p = &(s->s3->
229*0a6a1f1dSLionel Sambuc wbuf.buf[fixture.return_payload_offset + s->s3->wbuf.offset]);
230*0a6a1f1dSLionel Sambuc actual_payload_len = 0;
231*0a6a1f1dSLionel Sambuc n2s(p, actual_payload_len);
232*0a6a1f1dSLionel Sambuc
233*0a6a1f1dSLionel Sambuc if (actual_payload_len != fixture.expected_payload_len) {
234*0a6a1f1dSLionel Sambuc printf("%s failed:\n expected payload len: %d\n received: %d\n",
235*0a6a1f1dSLionel Sambuc fixture.test_case_name, fixture.expected_payload_len,
236*0a6a1f1dSLionel Sambuc actual_payload_len);
237*0a6a1f1dSLionel Sambuc print_payload("sent", sent_buf, strlen((const char *)sent_buf));
238*0a6a1f1dSLionel Sambuc print_payload("received", p, actual_payload_len);
239*0a6a1f1dSLionel Sambuc result = 1;
240*0a6a1f1dSLionel Sambuc } else {
241*0a6a1f1dSLionel Sambuc char *actual_payload =
242*0a6a1f1dSLionel Sambuc BUF_strndup((const char *)p, actual_payload_len);
243*0a6a1f1dSLionel Sambuc if (strcmp(actual_payload, fixture.expected_return_payload) != 0) {
244*0a6a1f1dSLionel Sambuc printf
245*0a6a1f1dSLionel Sambuc ("%s failed:\n expected payload: \"%s\"\n received: \"%s\"\n",
246*0a6a1f1dSLionel Sambuc fixture.test_case_name, fixture.expected_return_payload,
247*0a6a1f1dSLionel Sambuc actual_payload);
248*0a6a1f1dSLionel Sambuc result = 1;
249*0a6a1f1dSLionel Sambuc }
250*0a6a1f1dSLionel Sambuc OPENSSL_free(actual_payload);
251*0a6a1f1dSLionel Sambuc }
252*0a6a1f1dSLionel Sambuc
253*0a6a1f1dSLionel Sambuc if (result != 0) {
254*0a6a1f1dSLionel Sambuc printf("** %s failed **\n--------\n", fixture.test_case_name);
255*0a6a1f1dSLionel Sambuc }
256*0a6a1f1dSLionel Sambuc return result;
257*0a6a1f1dSLionel Sambuc }
258*0a6a1f1dSLionel Sambuc
honest_payload_size(unsigned char payload_buf[])259*0a6a1f1dSLionel Sambuc static int honest_payload_size(unsigned char payload_buf[])
260*0a6a1f1dSLionel Sambuc {
261*0a6a1f1dSLionel Sambuc /* Omit three-byte pad at the beginning for type and payload length */
262*0a6a1f1dSLionel Sambuc return strlen((const char *)&payload_buf[3]) - MIN_PADDING_SIZE;
263*0a6a1f1dSLionel Sambuc }
264*0a6a1f1dSLionel Sambuc
265*0a6a1f1dSLionel Sambuc # define SETUP_HEARTBEAT_TEST_FIXTURE(type)\
266*0a6a1f1dSLionel Sambuc SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type)
267*0a6a1f1dSLionel Sambuc
268*0a6a1f1dSLionel Sambuc # define EXECUTE_HEARTBEAT_TEST()\
269*0a6a1f1dSLionel Sambuc EXECUTE_TEST(execute_heartbeat, tear_down)
270*0a6a1f1dSLionel Sambuc
test_dtls1_not_bleeding()271*0a6a1f1dSLionel Sambuc static int test_dtls1_not_bleeding()
272*0a6a1f1dSLionel Sambuc {
273*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
274*0a6a1f1dSLionel Sambuc /* Three-byte pad at the beginning for type and payload length */
275*0a6a1f1dSLionel Sambuc unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding"
276*0a6a1f1dSLionel Sambuc " ";
277*0a6a1f1dSLionel Sambuc const int payload_buf_len = honest_payload_size(payload_buf);
278*0a6a1f1dSLionel Sambuc
279*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
280*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = payload_buf_len;
281*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
282*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = payload_buf_len;
283*0a6a1f1dSLionel Sambuc fixture.expected_return_payload =
284*0a6a1f1dSLionel Sambuc "Not bleeding, sixteen spaces of padding";
285*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
286*0a6a1f1dSLionel Sambuc }
287*0a6a1f1dSLionel Sambuc
test_dtls1_not_bleeding_empty_payload()288*0a6a1f1dSLionel Sambuc static int test_dtls1_not_bleeding_empty_payload()
289*0a6a1f1dSLionel Sambuc {
290*0a6a1f1dSLionel Sambuc int payload_buf_len;
291*0a6a1f1dSLionel Sambuc
292*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
293*0a6a1f1dSLionel Sambuc /*
294*0a6a1f1dSLionel Sambuc * Three-byte pad at the beginning for type and payload length, plus a
295*0a6a1f1dSLionel Sambuc * NUL at the end
296*0a6a1f1dSLionel Sambuc */
297*0a6a1f1dSLionel Sambuc unsigned char payload_buf[4 + MIN_PADDING_SIZE];
298*0a6a1f1dSLionel Sambuc memset(payload_buf, ' ', sizeof(payload_buf));
299*0a6a1f1dSLionel Sambuc payload_buf[sizeof(payload_buf) - 1] = '\0';
300*0a6a1f1dSLionel Sambuc payload_buf_len = honest_payload_size(payload_buf);
301*0a6a1f1dSLionel Sambuc
302*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
303*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = payload_buf_len;
304*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
305*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = payload_buf_len;
306*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
307*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
308*0a6a1f1dSLionel Sambuc }
309*0a6a1f1dSLionel Sambuc
test_dtls1_heartbleed()310*0a6a1f1dSLionel Sambuc static int test_dtls1_heartbleed()
311*0a6a1f1dSLionel Sambuc {
312*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
313*0a6a1f1dSLionel Sambuc /* Three-byte pad at the beginning for type and payload length */
314*0a6a1f1dSLionel Sambuc unsigned char payload_buf[] = " HEARTBLEED ";
315*0a6a1f1dSLionel Sambuc
316*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
317*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
318*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
319*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = 0;
320*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
321*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
322*0a6a1f1dSLionel Sambuc }
323*0a6a1f1dSLionel Sambuc
test_dtls1_heartbleed_empty_payload()324*0a6a1f1dSLionel Sambuc static int test_dtls1_heartbleed_empty_payload()
325*0a6a1f1dSLionel Sambuc {
326*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
327*0a6a1f1dSLionel Sambuc /*
328*0a6a1f1dSLionel Sambuc * Excluding the NUL at the end, one byte short of type + payload length
329*0a6a1f1dSLionel Sambuc * + minimum padding
330*0a6a1f1dSLionel Sambuc */
331*0a6a1f1dSLionel Sambuc unsigned char payload_buf[MIN_PADDING_SIZE + 3];
332*0a6a1f1dSLionel Sambuc memset(payload_buf, ' ', sizeof(payload_buf));
333*0a6a1f1dSLionel Sambuc payload_buf[sizeof(payload_buf) - 1] = '\0';
334*0a6a1f1dSLionel Sambuc
335*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
336*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
337*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
338*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = 0;
339*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
340*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
341*0a6a1f1dSLionel Sambuc }
342*0a6a1f1dSLionel Sambuc
test_dtls1_heartbleed_excessive_plaintext_length()343*0a6a1f1dSLionel Sambuc static int test_dtls1_heartbleed_excessive_plaintext_length()
344*0a6a1f1dSLionel Sambuc {
345*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
346*0a6a1f1dSLionel Sambuc /*
347*0a6a1f1dSLionel Sambuc * Excluding the NUL at the end, one byte in excess of maximum allowed
348*0a6a1f1dSLionel Sambuc * heartbeat message length
349*0a6a1f1dSLionel Sambuc */
350*0a6a1f1dSLionel Sambuc unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2];
351*0a6a1f1dSLionel Sambuc memset(payload_buf, ' ', sizeof(payload_buf));
352*0a6a1f1dSLionel Sambuc payload_buf[sizeof(payload_buf) - 1] = '\0';
353*0a6a1f1dSLionel Sambuc
354*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
355*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = honest_payload_size(payload_buf);
356*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
357*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = 0;
358*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
359*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
360*0a6a1f1dSLionel Sambuc }
361*0a6a1f1dSLionel Sambuc
test_tls1_not_bleeding()362*0a6a1f1dSLionel Sambuc static int test_tls1_not_bleeding()
363*0a6a1f1dSLionel Sambuc {
364*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(tls);
365*0a6a1f1dSLionel Sambuc /* Three-byte pad at the beginning for type and payload length */
366*0a6a1f1dSLionel Sambuc unsigned char payload_buf[] = " Not bleeding, sixteen spaces of padding"
367*0a6a1f1dSLionel Sambuc " ";
368*0a6a1f1dSLionel Sambuc const int payload_buf_len = honest_payload_size(payload_buf);
369*0a6a1f1dSLionel Sambuc
370*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
371*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = payload_buf_len;
372*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
373*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = payload_buf_len;
374*0a6a1f1dSLionel Sambuc fixture.expected_return_payload =
375*0a6a1f1dSLionel Sambuc "Not bleeding, sixteen spaces of padding";
376*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
377*0a6a1f1dSLionel Sambuc }
378*0a6a1f1dSLionel Sambuc
test_tls1_not_bleeding_empty_payload()379*0a6a1f1dSLionel Sambuc static int test_tls1_not_bleeding_empty_payload()
380*0a6a1f1dSLionel Sambuc {
381*0a6a1f1dSLionel Sambuc int payload_buf_len;
382*0a6a1f1dSLionel Sambuc
383*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(tls);
384*0a6a1f1dSLionel Sambuc /*
385*0a6a1f1dSLionel Sambuc * Three-byte pad at the beginning for type and payload length, plus a
386*0a6a1f1dSLionel Sambuc * NUL at the end
387*0a6a1f1dSLionel Sambuc */
388*0a6a1f1dSLionel Sambuc unsigned char payload_buf[4 + MIN_PADDING_SIZE];
389*0a6a1f1dSLionel Sambuc memset(payload_buf, ' ', sizeof(payload_buf));
390*0a6a1f1dSLionel Sambuc payload_buf[sizeof(payload_buf) - 1] = '\0';
391*0a6a1f1dSLionel Sambuc payload_buf_len = honest_payload_size(payload_buf);
392*0a6a1f1dSLionel Sambuc
393*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
394*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = payload_buf_len;
395*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
396*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = payload_buf_len;
397*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
398*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
399*0a6a1f1dSLionel Sambuc }
400*0a6a1f1dSLionel Sambuc
test_tls1_heartbleed()401*0a6a1f1dSLionel Sambuc static int test_tls1_heartbleed()
402*0a6a1f1dSLionel Sambuc {
403*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(tls);
404*0a6a1f1dSLionel Sambuc /* Three-byte pad at the beginning for type and payload length */
405*0a6a1f1dSLionel Sambuc unsigned char payload_buf[] = " HEARTBLEED ";
406*0a6a1f1dSLionel Sambuc
407*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
408*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
409*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
410*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = 0;
411*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
412*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
413*0a6a1f1dSLionel Sambuc }
414*0a6a1f1dSLionel Sambuc
test_tls1_heartbleed_empty_payload()415*0a6a1f1dSLionel Sambuc static int test_tls1_heartbleed_empty_payload()
416*0a6a1f1dSLionel Sambuc {
417*0a6a1f1dSLionel Sambuc SETUP_HEARTBEAT_TEST_FIXTURE(tls);
418*0a6a1f1dSLionel Sambuc /*
419*0a6a1f1dSLionel Sambuc * Excluding the NUL at the end, one byte short of type + payload length
420*0a6a1f1dSLionel Sambuc * + minimum padding
421*0a6a1f1dSLionel Sambuc */
422*0a6a1f1dSLionel Sambuc unsigned char payload_buf[MIN_PADDING_SIZE + 3];
423*0a6a1f1dSLionel Sambuc memset(payload_buf, ' ', sizeof(payload_buf));
424*0a6a1f1dSLionel Sambuc payload_buf[sizeof(payload_buf) - 1] = '\0';
425*0a6a1f1dSLionel Sambuc
426*0a6a1f1dSLionel Sambuc fixture.payload = &payload_buf[0];
427*0a6a1f1dSLionel Sambuc fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
428*0a6a1f1dSLionel Sambuc fixture.expected_return_value = 0;
429*0a6a1f1dSLionel Sambuc fixture.expected_payload_len = 0;
430*0a6a1f1dSLionel Sambuc fixture.expected_return_payload = "";
431*0a6a1f1dSLionel Sambuc EXECUTE_HEARTBEAT_TEST();
432*0a6a1f1dSLionel Sambuc }
433*0a6a1f1dSLionel Sambuc
434*0a6a1f1dSLionel Sambuc # undef EXECUTE_HEARTBEAT_TEST
435*0a6a1f1dSLionel Sambuc # undef SETUP_HEARTBEAT_TEST_FIXTURE
436*0a6a1f1dSLionel Sambuc
main(int argc,char * argv[])437*0a6a1f1dSLionel Sambuc int main(int argc, char *argv[])
438*0a6a1f1dSLionel Sambuc {
439*0a6a1f1dSLionel Sambuc int num_failed;
440*0a6a1f1dSLionel Sambuc
441*0a6a1f1dSLionel Sambuc SSL_library_init();
442*0a6a1f1dSLionel Sambuc SSL_load_error_strings();
443*0a6a1f1dSLionel Sambuc
444*0a6a1f1dSLionel Sambuc num_failed = test_dtls1_not_bleeding() +
445*0a6a1f1dSLionel Sambuc test_dtls1_not_bleeding_empty_payload() +
446*0a6a1f1dSLionel Sambuc test_dtls1_heartbleed() + test_dtls1_heartbleed_empty_payload() +
447*0a6a1f1dSLionel Sambuc /*
448*0a6a1f1dSLionel Sambuc * The following test causes an assertion failure at
449*0a6a1f1dSLionel Sambuc * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g:
450*0a6a1f1dSLionel Sambuc */
451*0a6a1f1dSLionel Sambuc (OPENSSL_VERSION_NUMBER >= 0x1000107fL ?
452*0a6a1f1dSLionel Sambuc test_dtls1_heartbleed_excessive_plaintext_length() : 0) +
453*0a6a1f1dSLionel Sambuc test_tls1_not_bleeding() +
454*0a6a1f1dSLionel Sambuc test_tls1_not_bleeding_empty_payload() +
455*0a6a1f1dSLionel Sambuc test_tls1_heartbleed() + test_tls1_heartbleed_empty_payload() + 0;
456*0a6a1f1dSLionel Sambuc
457*0a6a1f1dSLionel Sambuc ERR_print_errors_fp(stderr);
458*0a6a1f1dSLionel Sambuc
459*0a6a1f1dSLionel Sambuc if (num_failed != 0) {
460*0a6a1f1dSLionel Sambuc printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : "");
461*0a6a1f1dSLionel Sambuc return EXIT_FAILURE;
462*0a6a1f1dSLionel Sambuc }
463*0a6a1f1dSLionel Sambuc return EXIT_SUCCESS;
464*0a6a1f1dSLionel Sambuc }
465*0a6a1f1dSLionel Sambuc
466*0a6a1f1dSLionel Sambuc #else /* OPENSSL_NO_HEARTBEATS */
467*0a6a1f1dSLionel Sambuc
main(int argc,char * argv[])468*0a6a1f1dSLionel Sambuc int main(int argc, char *argv[])
469*0a6a1f1dSLionel Sambuc {
470*0a6a1f1dSLionel Sambuc return EXIT_SUCCESS;
471*0a6a1f1dSLionel Sambuc }
472*0a6a1f1dSLionel Sambuc #endif /* OPENSSL_NO_HEARTBEATS */
473