6eb2e5ccfbb8abae301d5317ae3792884b80beb7
[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 <openssl/ssl.h>
60 #include <openssl/bio.h>
61 #include <openssl/err.h>
62 #include <openssl/conf.h>
63 #ifndef OPENSSL_NO_ENGINE
64  #include <openssl/engine.h>
65 #endif
66 #include "e_os.h"
67
68 #ifndef OPENSSL_NO_SOCK
69
70 /* Just a ClientHello without a cookie */
71 static const unsigned char clienthello_nocookie[] = {
72     0x16, /* Handshake */
73     0xFE, 0xFF, /* DTLSv1.0 */
74     0x00, 0x00, /* Epoch */
75     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
76     0x00, 0x3A, /* Record Length */
77     0x01, /* ClientHello */
78     0x00, 0x00, 0x2E, /* Message length */
79     0x00, 0x00, /* Message sequence */
80     0x00, 0x00, 0x00, /* Fragment offset */
81     0x00, 0x00, 0x2E, /* Fragment length */
82     0xFE, 0xFD, /* DTLSv1.2 */
83     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
84     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
85     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
86     0x00, /* Session id len */
87     0x00, /* Cookie len */
88     0x00, 0x04, /* Ciphersuites len */
89     0x00, 0x2f, /* AES128-SHA */
90     0x00, 0xff, /* Empty reneg info SCSV */
91     0x01, /* Compression methods len */
92     0x00, /* Null compression */
93     0x00, 0x00 /* Extensions len */
94 };
95
96 /* First fragment of a ClientHello without a cookie */
97 static const unsigned char clienthello_nocookie_frag[] = {
98     0x16, /* Handshake */
99     0xFE, 0xFF, /* DTLSv1.0 */
100     0x00, 0x00, /* Epoch */
101     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
102     0x00, 0x30, /* Record Length */
103     0x01, /* ClientHello */
104     0x00, 0x00, 0x2E, /* Message length */
105     0x00, 0x00, /* Message sequence */
106     0x00, 0x00, 0x00, /* Fragment offset */
107     0x00, 0x00, 0x24, /* Fragment length */
108     0xFE, 0xFD, /* DTLSv1.2 */
109     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
110     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
111     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
112     0x00, /* Session id len */
113     0x00 /* Cookie len */
114 };
115
116 /* First fragment of a ClientHello which is too short */
117 static const unsigned char clienthello_nocookie_short[] = {
118     0x16, /* Handshake */
119     0xFE, 0xFF, /* DTLSv1.0 */
120     0x00, 0x00, /* Epoch */
121     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
122     0x00, 0x2F, /* Record Length */
123     0x01, /* ClientHello */
124     0x00, 0x00, 0x2E, /* Message length */
125     0x00, 0x00, /* Message sequence */
126     0x00, 0x00, 0x00, /* Fragment offset */
127     0x00, 0x00, 0x23, /* Fragment length */
128     0xFE, 0xFD, /* DTLSv1.2 */
129     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
130     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
131     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
132     0x00 /* Session id len */
133 };
134
135 /* Second fragment of a ClientHello */
136 static const unsigned char clienthello_2ndfrag[] = {
137     0x16, /* Handshake */
138     0xFE, 0xFF, /* DTLSv1.0 */
139     0x00, 0x00, /* Epoch */
140     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
141     0x00, 0x38, /* Record Length */
142     0x01, /* ClientHello */
143     0x00, 0x00, 0x2E, /* Message length */
144     0x00, 0x00, /* Message sequence */
145     0x00, 0x00, 0x02, /* Fragment offset */
146     0x00, 0x00, 0x2C, /* Fragment length */
147     /* Version skipped - sent in first fragment */
148     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
149     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
150     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
151     0x00, /* Session id len */
152     0x00, /* Cookie len */
153     0x00, 0x04, /* Ciphersuites len */
154     0x00, 0x2f, /* AES128-SHA */
155     0x00, 0xff, /* Empty reneg info SCSV */
156     0x01, /* Compression methods len */
157     0x00, /* Null compression */
158     0x00, 0x00 /* Extensions len */
159 };
160
161 /* A ClientHello with a good cookie */
162 static const unsigned char clienthello_cookie[] = {
163     0x16, /* Handshake */
164     0xFE, 0xFF, /* DTLSv1.0 */
165     0x00, 0x00, /* Epoch */
166     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
167     0x00, 0x4E, /* Record Length */
168     0x01, /* ClientHello */
169     0x00, 0x00, 0x42, /* Message length */
170     0x00, 0x00, /* Message sequence */
171     0x00, 0x00, 0x00, /* Fragment offset */
172     0x00, 0x00, 0x42, /* Fragment length */
173     0xFE, 0xFD, /* DTLSv1.2 */
174     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
175     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
176     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
177     0x00, /* Session id len */
178     0x14, /* Cookie len */
179     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
180     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
181     0x00, 0x04, /* Ciphersuites len */
182     0x00, 0x2f, /* AES128-SHA */
183     0x00, 0xff, /* Empty reneg info SCSV */
184     0x01, /* Compression methods len */
185     0x00, /* Null compression */
186     0x00, 0x00 /* Extensions len */
187 };
188
189 /* A fragmented ClientHello with a good cookie */
190 static const unsigned char clienthello_cookie_frag[] = {
191     0x16, /* Handshake */
192     0xFE, 0xFF, /* DTLSv1.0 */
193     0x00, 0x00, /* Epoch */
194     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
195     0x00, 0x44, /* Record Length */
196     0x01, /* ClientHello */
197     0x00, 0x00, 0x42, /* Message length */
198     0x00, 0x00, /* Message sequence */
199     0x00, 0x00, 0x00, /* Fragment offset */
200     0x00, 0x00, 0x38, /* Fragment length */
201     0xFE, 0xFD, /* DTLSv1.2 */
202     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
203     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
204     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
205     0x00, /* Session id len */
206     0x14, /* Cookie len */
207     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
208     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
209 };
210
211
212 /* A ClientHello with a bad cookie */
213 static const unsigned char clienthello_badcookie[] = {
214     0x16, /* Handshake */
215     0xFE, 0xFF, /* DTLSv1.0 */
216     0x00, 0x00, /* Epoch */
217     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
218     0x00, 0x4E, /* Record Length */
219     0x01, /* ClientHello */
220     0x00, 0x00, 0x42, /* Message length */
221     0x00, 0x00, /* Message sequence */
222     0x00, 0x00, 0x00, /* Fragment offset */
223     0x00, 0x00, 0x42, /* Fragment length */
224     0xFE, 0xFD, /* DTLSv1.2 */
225     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
226     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
227     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
228     0x00, /* Session id len */
229     0x14, /* Cookie len */
230     0x01, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
231     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
232     0x00, 0x04, /* Ciphersuites len */
233     0x00, 0x2f, /* AES128-SHA */
234     0x00, 0xff, /* Empty reneg info SCSV */
235     0x01, /* Compression methods len */
236     0x00, /* Null compression */
237     0x00, 0x00 /* Extensions len */
238 };
239
240 /* A fragmented ClientHello with the fragment boundary mid cookie */
241 static const unsigned char clienthello_cookie_short[] = {
242     0x16, /* Handshake */
243     0xFE, 0xFF, /* DTLSv1.0 */
244     0x00, 0x00, /* Epoch */
245     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
246     0x00, 0x43, /* Record Length */
247     0x01, /* ClientHello */
248     0x00, 0x00, 0x42, /* Message length */
249     0x00, 0x00, /* Message sequence */
250     0x00, 0x00, 0x00, /* Fragment offset */
251     0x00, 0x00, 0x37, /* Fragment length */
252     0xFE, 0xFD, /* DTLSv1.2 */
253     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
254     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
255     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
256     0x00, /* Session id len */
257     0x14, /* Cookie len */
258     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
259     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12 /* Cookie */
260 };
261
262 /* Bad record - too short */
263 static const unsigned char record_short[] = {
264     0x16, /* Handshake */
265     0xFE, 0xFF, /* DTLSv1.0 */
266     0x00, 0x00, /* Epoch */
267     0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Record sequence number */
268 };
269
270 static const unsigned char verify[] = {
271     0x16, /* Handshake */
272     0xFE, 0xFF, /* DTLSv1.0 */
273     0x00, 0x00, /* Epoch */
274     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
275     0x00, 0x23, /* Record Length */
276     0x03, /* HelloVerifyRequest */
277     0x00, 0x00, 0x17, /* Message length */
278     0x00, 0x00, /* Message sequence */
279     0x00, 0x00, 0x00, /* Fragment offset */
280     0x00, 0x00, 0x17, /* Fragment length */
281     0xFE, 0xFF, /* DTLSv1.0 */
282     0x14, /* Cookie len */
283     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
284     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
285 };
286
287 static struct {
288     const unsigned char *in;
289     unsigned int inlen;
290     /*
291      * GOOD == positive return value from DTLSv1_listen, no output yet
292      * VERIFY == 0 return value, HelloVerifyRequest sent
293      * DROP == 0 return value, no output
294      */
295     enum {GOOD, VERIFY, DROP} outtype;
296 } testpackets[9] = {
297     {
298         clienthello_nocookie,
299         sizeof(clienthello_nocookie),
300         VERIFY
301     },
302     {
303         clienthello_nocookie_frag,
304         sizeof(clienthello_nocookie_frag),
305         VERIFY
306     },
307     {
308         clienthello_nocookie_short,
309         sizeof(clienthello_nocookie_short),
310         DROP
311     },
312     {
313         clienthello_2ndfrag,
314         sizeof(clienthello_2ndfrag),
315         DROP
316     },
317     {
318         clienthello_cookie,
319         sizeof(clienthello_cookie),
320         GOOD
321     },
322     {
323         clienthello_cookie_frag,
324         sizeof(clienthello_cookie_frag),
325         GOOD
326     },
327     {
328         clienthello_badcookie,
329         sizeof(clienthello_badcookie),
330         VERIFY
331     },
332     {
333         clienthello_cookie_short,
334         sizeof(clienthello_cookie_short),
335         DROP
336     },
337     {
338         record_short,
339         sizeof(record_short),
340         DROP
341     }
342 };
343
344 # define COOKIE_LEN  20
345
346 static int cookie_gen(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
347 {
348     unsigned int i;
349
350     for (i = 0; i < COOKIE_LEN; i++, cookie++) {
351         *cookie = i;
352     }
353     *cookie_len = COOKIE_LEN;
354
355     return 1;
356 }
357
358 static int cookie_verify(SSL *ssl, const unsigned char *cookie,
359                          unsigned int cookie_len)
360 {
361     unsigned int i;
362
363     if (cookie_len != COOKIE_LEN)
364         return 0;
365
366     for (i = 0; i < COOKIE_LEN; i++, cookie++) {
367         if (*cookie != i)
368             return 0;
369     }
370
371     return 1;
372 }
373 #endif
374
375 int main(void)
376 {
377 #ifndef OPENSSL_NO_SOCK
378     SSL_CTX *ctx = NULL;
379     SSL *ssl = NULL;
380     BIO *outbio = NULL;
381     BIO *inbio = NULL;
382     BIO_ADDR *peer = BIO_ADDR_new();
383     char *data;
384     long datalen;
385     int ret, success = 0;
386     long i;
387
388     ctx = SSL_CTX_new(DTLS_server_method());
389     if (ctx == NULL || peer == NULL)
390         goto err;
391
392     SSL_CTX_set_cookie_generate_cb(ctx, cookie_gen);
393     SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify);
394
395     /* Create an SSL object for the connection */
396     ssl = SSL_new(ctx);
397     if (ssl == NULL)
398         goto err;
399
400     outbio = BIO_new(BIO_s_mem());
401     if (outbio == NULL)
402         goto err;
403     SSL_set_wbio(ssl, outbio);
404
405     success = 1;
406     for (i = 0; i < (long)OSSL_NELEM(testpackets) && success; i++) {
407         inbio = BIO_new_mem_buf((char *)testpackets[i].in,
408                                 testpackets[i].inlen);
409         if (inbio == NULL) {
410             success = 0;
411             goto err;
412         }
413         /* Set Non-blocking IO behaviour */
414         BIO_set_mem_eof_return(inbio, -1);
415
416         SSL_set_rbio(ssl, inbio);
417
418         /* Process the incoming packet */
419         ret = DTLSv1_listen(ssl, peer);
420         if (ret < 0) {
421             success = 0;
422             goto err;
423         }
424
425         datalen = BIO_get_mem_data(outbio, &data);
426
427         if (testpackets[i].outtype == VERIFY) {
428             if (ret == 0) {
429                 if (datalen != sizeof(verify)
430                         || (memcmp(data, verify, sizeof(verify)) != 0)) {
431                     printf("Test %ld failure: incorrect HelloVerifyRequest\n", i);
432                     success = 0;
433                 } else {
434                     printf("Test %ld success\n", i);
435                 }
436             } else {
437                 printf ("Test %ld failure: should not have succeeded\n", i);
438                 success = 0;
439             }
440         } else if (datalen == 0) {
441             if ((ret == 0 && testpackets[i].outtype == DROP)
442                     || (ret == 1 && testpackets[i].outtype == GOOD)) {
443                 printf("Test %ld success\n", i);
444             } else {
445                 printf("Test %ld failure: wrong return value\n", i);
446                 success = 0;
447             }
448         } else {
449             printf("Test %ld failure: Unexpected data output\n", i);
450             success = 0;
451         }
452         (void)BIO_reset(outbio);
453         inbio = NULL;
454         /* Frees up inbio */
455         SSL_set_rbio(ssl, NULL);
456     }
457
458  err:
459     if (!success)
460         ERR_print_errors_fp(stderr);
461     /* Also frees up outbio */
462     SSL_free(ssl);
463     SSL_CTX_free(ctx);
464     BIO_free(inbio);
465     OPENSSL_free(peer);
466 # ifndef OPENSSL_NO_CRYPTO_MDEBUG
467     CRYPTO_mem_leaks_fp(stderr);
468 # endif
469     return success ? 0 : 1;
470 #else
471     printf("DTLSv1_listen() is not supported by this build - skipping\n");
472     return 0;
473 #endif
474 }