4b616a77ffb46eca8885af08fbda9a7c1e86b8dc
[openssl.git] / test / dtlsv1listentest.c
1 /*
2  * Written by Matt Caswell for the OpenSSL project.
3  */
4 /* ====================================================================
5  * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    openssl-core@openssl.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57
58 #include <string.h>
59 #include <sys/socket.h>
60 #include <openssl/ssl.h>
61 #include <openssl/bio.h>
62 #include <openssl/err.h>
63 #include <openssl/conf.h>
64 #include <openssl/engine.h>
65 #include "e_os.h"
66
67 /* Just a ClientHello without a cookie */
68 static const unsigned char clienthello_nocookie[] = {
69     0x16, /* Handshake */
70     0xFE, 0xFF, /* DTLSv1.0 */
71     0x00, 0x00, /* Epoch */
72     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
73     0x00, 0x3A, /* Record Length */
74     0x01, /* ClientHello */
75     0x00, 0x00, 0x2E, /* Message length */
76     0x00, 0x00, /* Message sequence */
77     0x00, 0x00, 0x00, /* Fragment offset */
78     0x00, 0x00, 0x2E, /* Fragment length */
79     0xFE, 0xFD, /* DTLSv1.2 */
80     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
81     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
82     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
83     0x00, /* Session id len */
84     0x00, /* Cookie len */
85     0x00, 0x04, /* Ciphersuites len */
86     0x00, 0x2f, /* AES128-SHA */
87     0x00, 0xff, /* Empty reneg info SCSV */
88     0x01, /* Compression methods len */
89     0x00, /* Null compression */
90     0x00, 0x00 /* Extensions len */
91 };
92
93 /* First fragment of a ClientHello without a cookie */
94 static const unsigned char clienthello_nocookie_frag[] = {
95     0x16, /* Handshake */
96     0xFE, 0xFF, /* DTLSv1.0 */
97     0x00, 0x00, /* Epoch */
98     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
99     0x00, 0x30, /* Record Length */
100     0x01, /* ClientHello */
101     0x00, 0x00, 0x2E, /* Message length */
102     0x00, 0x00, /* Message sequence */
103     0x00, 0x00, 0x00, /* Fragment offset */
104     0x00, 0x00, 0x24, /* Fragment length */
105     0xFE, 0xFD, /* DTLSv1.2 */
106     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
107     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
108     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
109     0x00, /* Session id len */
110     0x00 /* Cookie len */
111 };
112
113 /* First fragment of a ClientHello which is too short */
114 static const unsigned char clienthello_nocookie_short[] = {
115     0x16, /* Handshake */
116     0xFE, 0xFF, /* DTLSv1.0 */
117     0x00, 0x00, /* Epoch */
118     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
119     0x00, 0x2F, /* Record Length */
120     0x01, /* ClientHello */
121     0x00, 0x00, 0x2E, /* Message length */
122     0x00, 0x00, /* Message sequence */
123     0x00, 0x00, 0x00, /* Fragment offset */
124     0x00, 0x00, 0x23, /* Fragment length */
125     0xFE, 0xFD, /* DTLSv1.2 */
126     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
127     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
128     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
129     0x00 /* Session id len */
130 };
131
132 /* Second fragment of a ClientHello */
133 static const unsigned char clienthello_2ndfrag[] = {
134     0x16, /* Handshake */
135     0xFE, 0xFF, /* DTLSv1.0 */
136     0x00, 0x00, /* Epoch */
137     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
138     0x00, 0x38, /* Record Length */
139     0x01, /* ClientHello */
140     0x00, 0x00, 0x2E, /* Message length */
141     0x00, 0x00, /* Message sequence */
142     0x00, 0x00, 0x02, /* Fragment offset */
143     0x00, 0x00, 0x2C, /* Fragment length */
144     /* Version skipped - sent in first fragment */
145     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
146     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
147     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
148     0x00, /* Session id len */
149     0x00, /* Cookie len */
150     0x00, 0x04, /* Ciphersuites len */
151     0x00, 0x2f, /* AES128-SHA */
152     0x00, 0xff, /* Empty reneg info SCSV */
153     0x01, /* Compression methods len */
154     0x00, /* Null compression */
155     0x00, 0x00 /* Extensions len */
156 };
157
158 /* A ClientHello with a good cookie */
159 static const unsigned char clienthello_cookie[] = {
160     0x16, /* Handshake */
161     0xFE, 0xFF, /* DTLSv1.0 */
162     0x00, 0x00, /* Epoch */
163     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
164     0x00, 0x4E, /* Record Length */
165     0x01, /* ClientHello */
166     0x00, 0x00, 0x42, /* Message length */
167     0x00, 0x00, /* Message sequence */
168     0x00, 0x00, 0x00, /* Fragment offset */
169     0x00, 0x00, 0x42, /* Fragment length */
170     0xFE, 0xFD, /* DTLSv1.2 */
171     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
172     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
173     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
174     0x00, /* Session id len */
175     0x14, /* Cookie len */
176     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
177     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
178     0x00, 0x04, /* Ciphersuites len */
179     0x00, 0x2f, /* AES128-SHA */
180     0x00, 0xff, /* Empty reneg info SCSV */
181     0x01, /* Compression methods len */
182     0x00, /* Null compression */
183     0x00, 0x00 /* Extensions len */
184 };
185
186 /* A fragmented ClientHello with a good cookie */
187 static const unsigned char clienthello_cookie_frag[] = {
188     0x16, /* Handshake */
189     0xFE, 0xFF, /* DTLSv1.0 */
190     0x00, 0x00, /* Epoch */
191     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
192     0x00, 0x44, /* Record Length */
193     0x01, /* ClientHello */
194     0x00, 0x00, 0x42, /* Message length */
195     0x00, 0x00, /* Message sequence */
196     0x00, 0x00, 0x00, /* Fragment offset */
197     0x00, 0x00, 0x38, /* Fragment length */
198     0xFE, 0xFD, /* DTLSv1.2 */
199     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
200     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
201     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
202     0x00, /* Session id len */
203     0x14, /* Cookie len */
204     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
205     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
206 };
207
208
209 /* A ClientHello with a bad cookie */
210 static const unsigned char clienthello_badcookie[] = {
211     0x16, /* Handshake */
212     0xFE, 0xFF, /* DTLSv1.0 */
213     0x00, 0x00, /* Epoch */
214     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
215     0x00, 0x4E, /* Record Length */
216     0x01, /* ClientHello */
217     0x00, 0x00, 0x42, /* Message length */
218     0x00, 0x00, /* Message sequence */
219     0x00, 0x00, 0x00, /* Fragment offset */
220     0x00, 0x00, 0x42, /* Fragment length */
221     0xFE, 0xFD, /* DTLSv1.2 */
222     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
223     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
224     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
225     0x00, /* Session id len */
226     0x14, /* Cookie len */
227     0x01, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
228     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
229     0x00, 0x04, /* Ciphersuites len */
230     0x00, 0x2f, /* AES128-SHA */
231     0x00, 0xff, /* Empty reneg info SCSV */
232     0x01, /* Compression methods len */
233     0x00, /* Null compression */
234     0x00, 0x00 /* Extensions len */
235 };
236
237 /* A fragmented ClientHello with the fragment boundary mid cookie */
238 static const unsigned char clienthello_cookie_short[] = {
239     0x16, /* Handshake */
240     0xFE, 0xFF, /* DTLSv1.0 */
241     0x00, 0x00, /* Epoch */
242     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
243     0x00, 0x43, /* Record Length */
244     0x01, /* ClientHello */
245     0x00, 0x00, 0x42, /* Message length */
246     0x00, 0x00, /* Message sequence */
247     0x00, 0x00, 0x00, /* Fragment offset */
248     0x00, 0x00, 0x37, /* Fragment length */
249     0xFE, 0xFD, /* DTLSv1.2 */
250     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
251     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
252     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
253     0x00, /* Session id len */
254     0x14, /* Cookie len */
255     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
256     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12 /* Cookie */
257 };
258
259 /* Bad record - too short */
260 static const unsigned char record_short[] = {
261     0x16, /* Handshake */
262     0xFE, 0xFF, /* DTLSv1.0 */
263     0x00, 0x00, /* Epoch */
264     0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Record sequence number */
265 };
266
267 static const unsigned char verify[] = {
268     0x16, /* Handshake */
269     0xFE, 0xFF, /* DTLSv1.0 */
270     0x00, 0x00, /* Epoch */
271     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
272     0x00, 0x23, /* Record Length */
273     0x03, /* HelloVerifyRequest */
274     0x00, 0x00, 0x17, /* Message length */
275     0x00, 0x00, /* Message sequence */
276     0x00, 0x00, 0x00, /* Fragment offset */
277     0x00, 0x00, 0x17, /* Fragment length */
278     0xFE, 0xFF, /* DTLSv1.0 */
279     0x14, /* Cookie len */
280     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
281     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
282 };
283
284 static struct {
285     const unsigned char *in;
286     unsigned int inlen;
287     /*
288      * GOOD == positive return value from DTLSv1_listen, no output yet
289      * VERIFY == 0 return value, HelloVerifyRequest sent
290      * DROP == 0 return value, no output
291      */
292     enum {GOOD, VERIFY, DROP} outtype;
293 } testpackets[9] = {
294     {
295         clienthello_nocookie,
296         sizeof(clienthello_nocookie),
297         VERIFY
298     },
299     {
300         clienthello_nocookie_frag,
301         sizeof(clienthello_nocookie_frag),
302         VERIFY
303     },
304     {
305         clienthello_nocookie_short,
306         sizeof(clienthello_nocookie_short),
307         DROP
308     },
309     {
310         clienthello_2ndfrag,
311         sizeof(clienthello_2ndfrag),
312         DROP
313     },
314     {
315         clienthello_cookie,
316         sizeof(clienthello_cookie),
317         GOOD
318     },
319     {
320         clienthello_cookie_frag,
321         sizeof(clienthello_cookie_frag),
322         GOOD
323     },
324     {
325         clienthello_badcookie,
326         sizeof(clienthello_badcookie),
327         VERIFY
328     },
329     {
330         clienthello_cookie_short,
331         sizeof(clienthello_cookie_short),
332         DROP
333     },
334     {
335         record_short,
336         sizeof(record_short),
337         DROP
338     }
339 };
340
341 #define COOKIE_LEN  20
342
343 static int cookie_gen(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
344 {
345     unsigned int i;
346
347     for (i = 0; i < COOKIE_LEN; i++, cookie++) {
348         *cookie = i;
349     }
350     *cookie_len = COOKIE_LEN;
351
352     return 1;
353 }
354
355 static int cookie_verify(SSL *ssl, const unsigned char *cookie,
356                          unsigned int cookie_len)
357 {
358     unsigned int i;
359
360     if (cookie_len != COOKIE_LEN)
361         return 0;
362
363     for (i = 0; i < COOKIE_LEN; i++, cookie++) {
364         if (*cookie != i)
365             return 0;
366     }
367
368     return 1;
369 }
370
371 int main(void)
372 {
373     SSL_CTX *ctx = NULL;
374     SSL *ssl = NULL;
375     BIO *outbio = NULL;
376     BIO *inbio = NULL;
377     BIO_ADDR *peer = BIO_ADDR_new();
378     char *data;
379     long datalen;
380     int ret, success = 0;
381     size_t i;
382
383     /* Initialise libssl */
384     SSL_load_error_strings();
385     SSL_library_init();
386
387     ctx = SSL_CTX_new(DTLS_server_method());
388     if (ctx == NULL || peer == NULL)
389         goto err;
390
391     SSL_CTX_set_cookie_generate_cb(ctx, cookie_gen);
392     SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify);
393
394     /* Create an SSL object for the connection */
395     ssl = SSL_new(ctx);
396     if (ssl == NULL)
397         goto err;
398
399     outbio = BIO_new(BIO_s_mem());
400     if (outbio == NULL)
401         goto err;
402     SSL_set_wbio(ssl, outbio);
403
404     success = 1;
405     for (i = 0; i < OSSL_NELEM(testpackets) && success; i++) {
406         inbio = BIO_new_mem_buf((char *)testpackets[i].in,
407                                 testpackets[i].inlen);
408         if (inbio == NULL) {
409             success = 0;
410             goto err;
411         }
412         /* Set Non-blocking IO behaviour */
413         BIO_set_mem_eof_return(inbio, -1);
414
415         SSL_set_rbio(ssl, inbio);
416
417         /* Process the incoming packet */
418         ret = DTLSv1_listen(ssl, peer);
419         if (ret < 0) {
420             success = 0;
421             goto err;
422         }
423
424         datalen = BIO_get_mem_data(outbio, &data);
425
426         if (testpackets[i].outtype == VERIFY) {
427             if (ret == 0) {
428                 if (datalen != sizeof(verify)
429                         || (memcmp(data, verify, sizeof(verify)) != 0)) {
430                     printf("Test %ld failure: incorrect HelloVerifyRequest\n", i);
431                     success = 0;
432                 } else {
433                     printf("Test %ld success\n", i);
434                 }
435             } else {
436                 printf ("Test %ld failure: should not have succeeded\n", i);
437                 success = 0;
438             }
439         } else if (datalen == 0) {
440             if ((ret == 0 && testpackets[i].outtype == DROP)
441                     || (ret == 1 && testpackets[i].outtype == GOOD)) {
442                 printf("Test %ld success\n", i);
443             } else {
444                 printf("Test %ld failure: wrong return value\n", i);
445                 success = 0;
446             }
447         } else {
448             printf("Test %ld failure: Unexpected data output\n", i);
449             success = 0;
450         }
451         (void)BIO_reset(outbio);
452         inbio = NULL;
453         /* Frees up inbio */
454         SSL_set_rbio(ssl, NULL);
455     }
456
457  err:
458     if (!success)
459         ERR_print_errors_fp(stderr);
460     /* Also frees up outbio */
461     SSL_free(ssl);
462     SSL_CTX_free(ctx);
463     BIO_free(inbio);
464     /* Unitialise libssl */
465 #ifndef OPENSSL_NO_ENGINE
466     ENGINE_cleanup();
467 #endif
468     CONF_modules_unload(1);
469     CRYPTO_cleanup_all_ex_data();
470     EVP_cleanup();
471     ERR_remove_thread_state(NULL);
472     ERR_free_strings();
473 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
474     CRYPTO_mem_leaks_fp(stderr);
475 #endif
476     return success ? 0 : 1;
477 }
478