1267188Sjkim/* test/heartbeat_test.c */
2280304Sjkim/*-
3267188Sjkim * Unit test for TLS heartbeats.
4267188Sjkim *
5267188Sjkim * Acts as a regression test against the Heartbleed bug (CVE-2014-0160).
6267188Sjkim *
7267188Sjkim * Author:  Mike Bland (mbland@acm.org, http://mike-bland.com/)
8267188Sjkim * Date:    2014-04-12
9267188Sjkim * License: Creative Commons Attribution 4.0 International (CC By 4.0)
10267188Sjkim *          http://creativecommons.org/licenses/by/4.0/deed.en_US
11267188Sjkim *
12267188Sjkim * OUTPUT
13267188Sjkim * ------
14267188Sjkim * The program returns zero on success. It will print a message with a count
15267188Sjkim * of the number of failed tests and return nonzero if any tests fail.
16267188Sjkim *
17267188Sjkim * It will print the contents of the request and response buffers for each
18267188Sjkim * failing test. In a "fixed" version, all the tests should pass and there
19267188Sjkim * should be no output.
20267188Sjkim *
21267188Sjkim * In a "bleeding" version, you'll see:
22267188Sjkim *
23267188Sjkim *   test_dtls1_heartbleed failed:
24267188Sjkim *     expected payload len: 0
25267188Sjkim *     received: 1024
26267188Sjkim *   sent 26 characters
27267188Sjkim *     "HEARTBLEED                "
28267188Sjkim *   received 1024 characters
29267188Sjkim *     "HEARTBLEED                \xde\xad\xbe\xef..."
30267188Sjkim *   ** test_dtls1_heartbleed failed **
31267188Sjkim *
32267188Sjkim * The contents of the returned buffer in the failing test will depend on the
33267188Sjkim * contents of memory on your machine.
34267188Sjkim *
35267188Sjkim * MORE INFORMATION
36267188Sjkim * ----------------
37267188Sjkim * http://mike-bland.com/2014/04/12/heartbleed.html
38267188Sjkim * http://mike-bland.com/tags/heartbleed.html
39267188Sjkim */
40267188Sjkim
41269686Sjkim#define OPENSSL_UNIT_TEST
42269686Sjkim
43269686Sjkim#include "../test/testutil.h"
44269686Sjkim
45267188Sjkim#include "../ssl/ssl_locl.h"
46267188Sjkim#include <ctype.h>
47267188Sjkim#include <stdio.h>
48267188Sjkim#include <stdlib.h>
49267188Sjkim#include <string.h>
50267188Sjkim
51269686Sjkim#if !defined(OPENSSL_NO_HEARTBEATS) && !defined(OPENSSL_NO_UNIT_TEST)
52267188Sjkim
53267188Sjkim/* As per https://tools.ietf.org/html/rfc6520#section-4 */
54280304Sjkim# define MIN_PADDING_SIZE        16
55267188Sjkim
56267188Sjkim/* Maximum number of payload characters to print as test output */
57280304Sjkim# define MAX_PRINTABLE_CHARACTERS        1024
58267188Sjkim
59280304Sjkimtypedef struct heartbeat_test_fixture {
60280304Sjkim    SSL_CTX *ctx;
61280304Sjkim    SSL *s;
62280304Sjkim    const char *test_case_name;
63280304Sjkim    int (*process_heartbeat) (SSL *s);
64280304Sjkim    unsigned char *payload;
65280304Sjkim    int sent_payload_len;
66280304Sjkim    int expected_return_value;
67280304Sjkim    int return_payload_offset;
68280304Sjkim    int expected_payload_len;
69280304Sjkim    const char *expected_return_payload;
70280304Sjkim} HEARTBEAT_TEST_FIXTURE;
71267188Sjkim
72280304Sjkimstatic HEARTBEAT_TEST_FIXTURE set_up(const char *const test_case_name,
73280304Sjkim                                     const SSL_METHOD *meth)
74280304Sjkim{
75280304Sjkim    HEARTBEAT_TEST_FIXTURE fixture;
76280304Sjkim    int setup_ok = 1;
77280304Sjkim    memset(&fixture, 0, sizeof(fixture));
78280304Sjkim    fixture.test_case_name = test_case_name;
79267188Sjkim
80280304Sjkim    fixture.ctx = SSL_CTX_new(meth);
81280304Sjkim    if (!fixture.ctx) {
82280304Sjkim        fprintf(stderr, "Failed to allocate SSL_CTX for test: %s\n",
83280304Sjkim                test_case_name);
84280304Sjkim        setup_ok = 0;
85280304Sjkim        goto fail;
86280304Sjkim    }
87267188Sjkim
88280304Sjkim    fixture.s = SSL_new(fixture.ctx);
89280304Sjkim    if (!fixture.s) {
90280304Sjkim        fprintf(stderr, "Failed to allocate SSL for test: %s\n",
91280304Sjkim                test_case_name);
92280304Sjkim        setup_ok = 0;
93280304Sjkim        goto fail;
94280304Sjkim    }
95267188Sjkim
96280304Sjkim    if (!ssl_init_wbio_buffer(fixture.s, 1)) {
97280304Sjkim        fprintf(stderr, "Failed to set up wbio buffer for test: %s\n",
98280304Sjkim                test_case_name);
99280304Sjkim        setup_ok = 0;
100280304Sjkim        goto fail;
101280304Sjkim    }
102267188Sjkim
103280304Sjkim    if (!ssl3_setup_buffers(fixture.s)) {
104280304Sjkim        fprintf(stderr, "Failed to setup buffers for test: %s\n",
105280304Sjkim                test_case_name);
106280304Sjkim        setup_ok = 0;
107280304Sjkim        goto fail;
108280304Sjkim    }
109267188Sjkim
110280304Sjkim    /*
111280304Sjkim     * Clear the memory for the return buffer, since this isn't automatically
112280304Sjkim     * zeroed in opt mode and will cause spurious test failures that will
113280304Sjkim     * change with each execution.
114280304Sjkim     */
115280304Sjkim    memset(fixture.s->s3->wbuf.buf, 0, fixture.s->s3->wbuf.len);
116267188Sjkim
117280304Sjkim fail:
118280304Sjkim    if (!setup_ok) {
119280304Sjkim        ERR_print_errors_fp(stderr);
120280304Sjkim        exit(EXIT_FAILURE);
121280304Sjkim    }
122280304Sjkim    return fixture;
123280304Sjkim}
124267188Sjkim
125280304Sjkimstatic HEARTBEAT_TEST_FIXTURE set_up_dtls(const char *const test_case_name)
126280304Sjkim{
127280304Sjkim    HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
128280304Sjkim                                            DTLSv1_server_method());
129280304Sjkim    fixture.process_heartbeat = dtls1_process_heartbeat;
130267188Sjkim
131280304Sjkim    /*
132280304Sjkim     * As per dtls1_get_record(), skipping the following from the beginning
133280304Sjkim     * of the returned heartbeat message: type-1 byte; version-2 bytes;
134280304Sjkim     * sequence number-8 bytes; length-2 bytes And then skipping the 1-byte
135280304Sjkim     * type encoded by process_heartbeat for a total of 14 bytes, at which
136280304Sjkim     * point we can grab the length and the payload we seek.
137280304Sjkim     */
138280304Sjkim    fixture.return_payload_offset = 14;
139280304Sjkim    return fixture;
140280304Sjkim}
141267188Sjkim
142267188Sjkim/* Needed by ssl3_write_bytes() */
143280304Sjkimstatic int dummy_handshake(SSL *s)
144280304Sjkim{
145280304Sjkim    return 1;
146280304Sjkim}
147267188Sjkim
148280304Sjkimstatic HEARTBEAT_TEST_FIXTURE set_up_tls(const char *const test_case_name)
149280304Sjkim{
150280304Sjkim    HEARTBEAT_TEST_FIXTURE fixture = set_up(test_case_name,
151280304Sjkim                                            TLSv1_server_method());
152280304Sjkim    fixture.process_heartbeat = tls1_process_heartbeat;
153280304Sjkim    fixture.s->handshake_func = dummy_handshake;
154267188Sjkim
155280304Sjkim    /*
156280304Sjkim     * As per do_ssl3_write(), skipping the following from the beginning of
157280304Sjkim     * the returned heartbeat message: type-1 byte; version-2 bytes; length-2
158280304Sjkim     * bytes And then skipping the 1-byte type encoded by process_heartbeat
159280304Sjkim     * for a total of 6 bytes, at which point we can grab the length and the
160280304Sjkim     * payload we seek.
161280304Sjkim     */
162280304Sjkim    fixture.return_payload_offset = 6;
163280304Sjkim    return fixture;
164280304Sjkim}
165267188Sjkim
166267188Sjkimstatic void tear_down(HEARTBEAT_TEST_FIXTURE fixture)
167280304Sjkim{
168280304Sjkim    ERR_print_errors_fp(stderr);
169280304Sjkim    SSL_free(fixture.s);
170280304Sjkim    SSL_CTX_free(fixture.ctx);
171280304Sjkim}
172267188Sjkim
173280304Sjkimstatic void print_payload(const char *const prefix,
174280304Sjkim                          const unsigned char *payload, const int n)
175280304Sjkim{
176280304Sjkim    const int end = n < MAX_PRINTABLE_CHARACTERS ? n
177280304Sjkim        : MAX_PRINTABLE_CHARACTERS;
178280304Sjkim    int i = 0;
179267188Sjkim
180280304Sjkim    printf("%s %d character%s", prefix, n, n == 1 ? "" : "s");
181280304Sjkim    if (end != n)
182280304Sjkim        printf(" (first %d shown)", end);
183280304Sjkim    printf("\n  \"");
184267188Sjkim
185280304Sjkim    for (; i != end; ++i) {
186280304Sjkim        const unsigned char c = payload[i];
187280304Sjkim        if (isprint(c))
188280304Sjkim            fputc(c, stdout);
189280304Sjkim        else
190280304Sjkim            printf("\\x%02x", c);
191280304Sjkim    }
192280304Sjkim    printf("\"\n");
193280304Sjkim}
194267188Sjkim
195267188Sjkimstatic int execute_heartbeat(HEARTBEAT_TEST_FIXTURE fixture)
196280304Sjkim{
197280304Sjkim    int result = 0;
198280304Sjkim    SSL *s = fixture.s;
199280304Sjkim    unsigned char *payload = fixture.payload;
200280304Sjkim    unsigned char sent_buf[MAX_PRINTABLE_CHARACTERS + 1];
201280304Sjkim    int return_value;
202280304Sjkim    unsigned const char *p;
203280304Sjkim    int actual_payload_len;
204267188Sjkim
205280304Sjkim    s->s3->rrec.data = payload;
206280304Sjkim    s->s3->rrec.length = strlen((const char *)payload);
207280304Sjkim    *payload++ = TLS1_HB_REQUEST;
208280304Sjkim    s2n(fixture.sent_payload_len, payload);
209267188Sjkim
210280304Sjkim    /*
211280304Sjkim     * Make a local copy of the request, since it gets overwritten at some
212280304Sjkim     * point
213280304Sjkim     */
214280304Sjkim    memcpy((char *)sent_buf, (const char *)payload, sizeof(sent_buf));
215267188Sjkim
216280304Sjkim    return_value = fixture.process_heartbeat(s);
217267188Sjkim
218280304Sjkim    if (return_value != fixture.expected_return_value) {
219280304Sjkim        printf("%s failed: expected return value %d, received %d\n",
220280304Sjkim               fixture.test_case_name, fixture.expected_return_value,
221280304Sjkim               return_value);
222280304Sjkim        result = 1;
223280304Sjkim    }
224267188Sjkim
225280304Sjkim    /*
226280304Sjkim     * If there is any byte alignment, it will be stored in wbuf.offset.
227280304Sjkim     */
228280304Sjkim    p = &(s->s3->
229280304Sjkim          wbuf.buf[fixture.return_payload_offset + s->s3->wbuf.offset]);
230280304Sjkim    actual_payload_len = 0;
231280304Sjkim    n2s(p, actual_payload_len);
232267188Sjkim
233280304Sjkim    if (actual_payload_len != fixture.expected_payload_len) {
234280304Sjkim        printf("%s failed:\n  expected payload len: %d\n  received: %d\n",
235280304Sjkim               fixture.test_case_name, fixture.expected_payload_len,
236280304Sjkim               actual_payload_len);
237280304Sjkim        print_payload("sent", sent_buf, strlen((const char *)sent_buf));
238280304Sjkim        print_payload("received", p, actual_payload_len);
239280304Sjkim        result = 1;
240280304Sjkim    } else {
241280304Sjkim        char *actual_payload =
242280304Sjkim            BUF_strndup((const char *)p, actual_payload_len);
243280304Sjkim        if (strcmp(actual_payload, fixture.expected_return_payload) != 0) {
244280304Sjkim            printf
245280304Sjkim                ("%s failed:\n  expected payload: \"%s\"\n  received: \"%s\"\n",
246280304Sjkim                 fixture.test_case_name, fixture.expected_return_payload,
247280304Sjkim                 actual_payload);
248280304Sjkim            result = 1;
249280304Sjkim        }
250280304Sjkim        OPENSSL_free(actual_payload);
251280304Sjkim    }
252267188Sjkim
253280304Sjkim    if (result != 0) {
254280304Sjkim        printf("** %s failed **\n--------\n", fixture.test_case_name);
255280304Sjkim    }
256280304Sjkim    return result;
257280304Sjkim}
258267188Sjkim
259267188Sjkimstatic int honest_payload_size(unsigned char payload_buf[])
260280304Sjkim{
261280304Sjkim    /* Omit three-byte pad at the beginning for type and payload length */
262280304Sjkim    return strlen((const char *)&payload_buf[3]) - MIN_PADDING_SIZE;
263280304Sjkim}
264267188Sjkim
265280304Sjkim# define SETUP_HEARTBEAT_TEST_FIXTURE(type)\
266269686Sjkim  SETUP_TEST_FIXTURE(HEARTBEAT_TEST_FIXTURE, set_up_##type)
267267188Sjkim
268280304Sjkim# define EXECUTE_HEARTBEAT_TEST()\
269269686Sjkim  EXECUTE_TEST(execute_heartbeat, tear_down)
270267188Sjkim
271267188Sjkimstatic int test_dtls1_not_bleeding()
272280304Sjkim{
273280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
274280304Sjkim    /* Three-byte pad at the beginning for type and payload length */
275280304Sjkim    unsigned char payload_buf[] = "   Not bleeding, sixteen spaces of padding"
276280304Sjkim        "                ";
277280304Sjkim    const int payload_buf_len = honest_payload_size(payload_buf);
278267188Sjkim
279280304Sjkim    fixture.payload = &payload_buf[0];
280280304Sjkim    fixture.sent_payload_len = payload_buf_len;
281280304Sjkim    fixture.expected_return_value = 0;
282280304Sjkim    fixture.expected_payload_len = payload_buf_len;
283280304Sjkim    fixture.expected_return_payload =
284280304Sjkim        "Not bleeding, sixteen spaces of padding";
285280304Sjkim    EXECUTE_HEARTBEAT_TEST();
286280304Sjkim}
287267188Sjkim
288267188Sjkimstatic int test_dtls1_not_bleeding_empty_payload()
289280304Sjkim{
290280304Sjkim    int payload_buf_len;
291267188Sjkim
292280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
293280304Sjkim    /*
294280304Sjkim     * Three-byte pad at the beginning for type and payload length, plus a
295280304Sjkim     * NUL at the end
296280304Sjkim     */
297280304Sjkim    unsigned char payload_buf[4 + MIN_PADDING_SIZE];
298280304Sjkim    memset(payload_buf, ' ', sizeof(payload_buf));
299280304Sjkim    payload_buf[sizeof(payload_buf) - 1] = '\0';
300280304Sjkim    payload_buf_len = honest_payload_size(payload_buf);
301267188Sjkim
302280304Sjkim    fixture.payload = &payload_buf[0];
303280304Sjkim    fixture.sent_payload_len = payload_buf_len;
304280304Sjkim    fixture.expected_return_value = 0;
305280304Sjkim    fixture.expected_payload_len = payload_buf_len;
306280304Sjkim    fixture.expected_return_payload = "";
307280304Sjkim    EXECUTE_HEARTBEAT_TEST();
308280304Sjkim}
309267188Sjkim
310267188Sjkimstatic int test_dtls1_heartbleed()
311280304Sjkim{
312280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
313280304Sjkim    /* Three-byte pad at the beginning for type and payload length */
314280304Sjkim    unsigned char payload_buf[] = "   HEARTBLEED                ";
315267188Sjkim
316280304Sjkim    fixture.payload = &payload_buf[0];
317280304Sjkim    fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
318280304Sjkim    fixture.expected_return_value = 0;
319280304Sjkim    fixture.expected_payload_len = 0;
320280304Sjkim    fixture.expected_return_payload = "";
321280304Sjkim    EXECUTE_HEARTBEAT_TEST();
322280304Sjkim}
323267188Sjkim
324267188Sjkimstatic int test_dtls1_heartbleed_empty_payload()
325280304Sjkim{
326280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
327280304Sjkim    /*
328280304Sjkim     * Excluding the NUL at the end, one byte short of type + payload length
329280304Sjkim     * + minimum padding
330280304Sjkim     */
331280304Sjkim    unsigned char payload_buf[MIN_PADDING_SIZE + 3];
332280304Sjkim    memset(payload_buf, ' ', sizeof(payload_buf));
333280304Sjkim    payload_buf[sizeof(payload_buf) - 1] = '\0';
334267188Sjkim
335280304Sjkim    fixture.payload = &payload_buf[0];
336280304Sjkim    fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
337280304Sjkim    fixture.expected_return_value = 0;
338280304Sjkim    fixture.expected_payload_len = 0;
339280304Sjkim    fixture.expected_return_payload = "";
340280304Sjkim    EXECUTE_HEARTBEAT_TEST();
341280304Sjkim}
342267188Sjkim
343267188Sjkimstatic int test_dtls1_heartbleed_excessive_plaintext_length()
344280304Sjkim{
345280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(dtls);
346280304Sjkim    /*
347280304Sjkim     * Excluding the NUL at the end, one byte in excess of maximum allowed
348280304Sjkim     * heartbeat message length
349280304Sjkim     */
350280304Sjkim    unsigned char payload_buf[SSL3_RT_MAX_PLAIN_LENGTH + 2];
351280304Sjkim    memset(payload_buf, ' ', sizeof(payload_buf));
352280304Sjkim    payload_buf[sizeof(payload_buf) - 1] = '\0';
353267188Sjkim
354280304Sjkim    fixture.payload = &payload_buf[0];
355280304Sjkim    fixture.sent_payload_len = honest_payload_size(payload_buf);
356280304Sjkim    fixture.expected_return_value = 0;
357280304Sjkim    fixture.expected_payload_len = 0;
358280304Sjkim    fixture.expected_return_payload = "";
359280304Sjkim    EXECUTE_HEARTBEAT_TEST();
360280304Sjkim}
361267188Sjkim
362267188Sjkimstatic int test_tls1_not_bleeding()
363280304Sjkim{
364280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(tls);
365280304Sjkim    /* Three-byte pad at the beginning for type and payload length */
366280304Sjkim    unsigned char payload_buf[] = "   Not bleeding, sixteen spaces of padding"
367280304Sjkim        "                ";
368280304Sjkim    const int payload_buf_len = honest_payload_size(payload_buf);
369267188Sjkim
370280304Sjkim    fixture.payload = &payload_buf[0];
371280304Sjkim    fixture.sent_payload_len = payload_buf_len;
372280304Sjkim    fixture.expected_return_value = 0;
373280304Sjkim    fixture.expected_payload_len = payload_buf_len;
374280304Sjkim    fixture.expected_return_payload =
375280304Sjkim        "Not bleeding, sixteen spaces of padding";
376280304Sjkim    EXECUTE_HEARTBEAT_TEST();
377280304Sjkim}
378267188Sjkim
379267188Sjkimstatic int test_tls1_not_bleeding_empty_payload()
380280304Sjkim{
381280304Sjkim    int payload_buf_len;
382267188Sjkim
383280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(tls);
384280304Sjkim    /*
385280304Sjkim     * Three-byte pad at the beginning for type and payload length, plus a
386280304Sjkim     * NUL at the end
387280304Sjkim     */
388280304Sjkim    unsigned char payload_buf[4 + MIN_PADDING_SIZE];
389280304Sjkim    memset(payload_buf, ' ', sizeof(payload_buf));
390280304Sjkim    payload_buf[sizeof(payload_buf) - 1] = '\0';
391280304Sjkim    payload_buf_len = honest_payload_size(payload_buf);
392267188Sjkim
393280304Sjkim    fixture.payload = &payload_buf[0];
394280304Sjkim    fixture.sent_payload_len = payload_buf_len;
395280304Sjkim    fixture.expected_return_value = 0;
396280304Sjkim    fixture.expected_payload_len = payload_buf_len;
397280304Sjkim    fixture.expected_return_payload = "";
398280304Sjkim    EXECUTE_HEARTBEAT_TEST();
399280304Sjkim}
400267188Sjkim
401267188Sjkimstatic int test_tls1_heartbleed()
402280304Sjkim{
403280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(tls);
404280304Sjkim    /* Three-byte pad at the beginning for type and payload length */
405280304Sjkim    unsigned char payload_buf[] = "   HEARTBLEED                ";
406267188Sjkim
407280304Sjkim    fixture.payload = &payload_buf[0];
408280304Sjkim    fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
409280304Sjkim    fixture.expected_return_value = 0;
410280304Sjkim    fixture.expected_payload_len = 0;
411280304Sjkim    fixture.expected_return_payload = "";
412280304Sjkim    EXECUTE_HEARTBEAT_TEST();
413280304Sjkim}
414267188Sjkim
415267188Sjkimstatic int test_tls1_heartbleed_empty_payload()
416280304Sjkim{
417280304Sjkim    SETUP_HEARTBEAT_TEST_FIXTURE(tls);
418280304Sjkim    /*
419280304Sjkim     * Excluding the NUL at the end, one byte short of type + payload length
420280304Sjkim     * + minimum padding
421280304Sjkim     */
422280304Sjkim    unsigned char payload_buf[MIN_PADDING_SIZE + 3];
423280304Sjkim    memset(payload_buf, ' ', sizeof(payload_buf));
424280304Sjkim    payload_buf[sizeof(payload_buf) - 1] = '\0';
425267188Sjkim
426280304Sjkim    fixture.payload = &payload_buf[0];
427280304Sjkim    fixture.sent_payload_len = MAX_PRINTABLE_CHARACTERS;
428280304Sjkim    fixture.expected_return_value = 0;
429280304Sjkim    fixture.expected_payload_len = 0;
430280304Sjkim    fixture.expected_return_payload = "";
431280304Sjkim    EXECUTE_HEARTBEAT_TEST();
432280304Sjkim}
433267188Sjkim
434280304Sjkim# undef EXECUTE_HEARTBEAT_TEST
435280304Sjkim# undef SETUP_HEARTBEAT_TEST_FIXTURE
436267188Sjkim
437267188Sjkimint main(int argc, char *argv[])
438280304Sjkim{
439280304Sjkim    int num_failed;
440267188Sjkim
441280304Sjkim    SSL_library_init();
442280304Sjkim    SSL_load_error_strings();
443267188Sjkim
444280304Sjkim    num_failed = test_dtls1_not_bleeding() +
445280304Sjkim        test_dtls1_not_bleeding_empty_payload() +
446280304Sjkim        test_dtls1_heartbleed() + test_dtls1_heartbleed_empty_payload() +
447280304Sjkim        /*
448280304Sjkim         * The following test causes an assertion failure at
449280304Sjkim         * ssl/d1_pkt.c:dtls1_write_bytes() in versions prior to 1.0.1g:
450280304Sjkim         */
451280304Sjkim        (OPENSSL_VERSION_NUMBER >= 0x1000107fL ?
452280304Sjkim         test_dtls1_heartbleed_excessive_plaintext_length() : 0) +
453280304Sjkim        test_tls1_not_bleeding() +
454280304Sjkim        test_tls1_not_bleeding_empty_payload() +
455280304Sjkim        test_tls1_heartbleed() + test_tls1_heartbleed_empty_payload() + 0;
456267188Sjkim
457280304Sjkim    ERR_print_errors_fp(stderr);
458267188Sjkim
459280304Sjkim    if (num_failed != 0) {
460280304Sjkim        printf("%d test%s failed\n", num_failed, num_failed != 1 ? "s" : "");
461280304Sjkim        return EXIT_FAILURE;
462280304Sjkim    }
463280304Sjkim    return EXIT_SUCCESS;
464280304Sjkim}
465267188Sjkim
466280304Sjkim#else                           /* OPENSSL_NO_HEARTBEATS */
467267188Sjkim
468267188Sjkimint main(int argc, char *argv[])
469280304Sjkim{
470280304Sjkim    return EXIT_SUCCESS;
471280304Sjkim}
472280304Sjkim#endif                          /* OPENSSL_NO_HEARTBEATS */
473