xref: /openssl/test/dtlsv1listentest.c (revision 909f1a2e)
1 /*
2  * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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
8  */
9 
10 #include <string.h>
11 #include <openssl/ssl.h>
12 #include <openssl/bio.h>
13 #include <openssl/err.h>
14 #include <openssl/conf.h>
15 #include "internal/nelem.h"
16 #include "testutil.h"
17 
18 #ifndef OPENSSL_NO_SOCK
19 
20 /* Just a ClientHello without a cookie */
21 static const unsigned char clienthello_nocookie[] = {
22     0x16, /* Handshake */
23     0xFE, 0xFF, /* DTLSv1.0 */
24     0x00, 0x00, /* Epoch */
25     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
26     0x00, 0x3A, /* Record Length */
27     0x01, /* ClientHello */
28     0x00, 0x00, 0x2E, /* Message length */
29     0x00, 0x00, /* Message sequence */
30     0x00, 0x00, 0x00, /* Fragment offset */
31     0x00, 0x00, 0x2E, /* Fragment length */
32     0xFE, 0xFD, /* DTLSv1.2 */
33     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
34     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
35     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
36     0x00, /* Session id len */
37     0x00, /* Cookie len */
38     0x00, 0x04, /* Ciphersuites len */
39     0x00, 0x2f, /* AES128-SHA */
40     0x00, 0xff, /* Empty reneg info SCSV */
41     0x01, /* Compression methods len */
42     0x00, /* Null compression */
43     0x00, 0x00 /* Extensions len */
44 };
45 
46 /* First fragment of a ClientHello without a cookie */
47 static const unsigned char clienthello_nocookie_frag[] = {
48     0x16, /* Handshake */
49     0xFE, 0xFF, /* DTLSv1.0 */
50     0x00, 0x00, /* Epoch */
51     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
52     0x00, 0x30, /* Record Length */
53     0x01, /* ClientHello */
54     0x00, 0x00, 0x2E, /* Message length */
55     0x00, 0x00, /* Message sequence */
56     0x00, 0x00, 0x00, /* Fragment offset */
57     0x00, 0x00, 0x24, /* Fragment length */
58     0xFE, 0xFD, /* DTLSv1.2 */
59     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
60     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
61     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
62     0x00, /* Session id len */
63     0x00 /* Cookie len */
64 };
65 
66 /* First fragment of a ClientHello which is too short */
67 static const unsigned char clienthello_nocookie_short[] = {
68     0x16, /* Handshake */
69     0xFE, 0xFF, /* DTLSv1.0 */
70     0x00, 0x00, /* Epoch */
71     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
72     0x00, 0x2F, /* Record Length */
73     0x01, /* ClientHello */
74     0x00, 0x00, 0x2E, /* Message length */
75     0x00, 0x00, /* Message sequence */
76     0x00, 0x00, 0x00, /* Fragment offset */
77     0x00, 0x00, 0x23, /* Fragment length */
78     0xFE, 0xFD, /* DTLSv1.2 */
79     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
80     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
81     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
82     0x00 /* Session id len */
83 };
84 
85 /* Second fragment of a ClientHello */
86 static const unsigned char clienthello_2ndfrag[] = {
87     0x16, /* Handshake */
88     0xFE, 0xFF, /* DTLSv1.0 */
89     0x00, 0x00, /* Epoch */
90     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
91     0x00, 0x38, /* Record Length */
92     0x01, /* ClientHello */
93     0x00, 0x00, 0x2E, /* Message length */
94     0x00, 0x00, /* Message sequence */
95     0x00, 0x00, 0x02, /* Fragment offset */
96     0x00, 0x00, 0x2C, /* Fragment length */
97     /* Version skipped - sent in first fragment */
98     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
99     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
100     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
101     0x00, /* Session id len */
102     0x00, /* Cookie len */
103     0x00, 0x04, /* Ciphersuites len */
104     0x00, 0x2f, /* AES128-SHA */
105     0x00, 0xff, /* Empty reneg info SCSV */
106     0x01, /* Compression methods len */
107     0x00, /* Null compression */
108     0x00, 0x00 /* Extensions len */
109 };
110 
111 /* A ClientHello with a good cookie */
112 static const unsigned char clienthello_cookie[] = {
113     0x16, /* Handshake */
114     0xFE, 0xFF, /* DTLSv1.0 */
115     0x00, 0x00, /* Epoch */
116     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
117     0x00, 0x4E, /* Record Length */
118     0x01, /* ClientHello */
119     0x00, 0x00, 0x42, /* Message length */
120     0x00, 0x00, /* Message sequence */
121     0x00, 0x00, 0x00, /* Fragment offset */
122     0x00, 0x00, 0x42, /* Fragment length */
123     0xFE, 0xFD, /* DTLSv1.2 */
124     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
125     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
126     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
127     0x00, /* Session id len */
128     0x14, /* Cookie len */
129     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
130     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
131     0x00, 0x04, /* Ciphersuites len */
132     0x00, 0x2f, /* AES128-SHA */
133     0x00, 0xff, /* Empty reneg info SCSV */
134     0x01, /* Compression methods len */
135     0x00, /* Null compression */
136     0x00, 0x00 /* Extensions len */
137 };
138 
139 /* A fragmented ClientHello with a good cookie */
140 static const unsigned char clienthello_cookie_frag[] = {
141     0x16, /* Handshake */
142     0xFE, 0xFF, /* DTLSv1.0 */
143     0x00, 0x00, /* Epoch */
144     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
145     0x00, 0x44, /* Record Length */
146     0x01, /* ClientHello */
147     0x00, 0x00, 0x42, /* Message length */
148     0x00, 0x00, /* Message sequence */
149     0x00, 0x00, 0x00, /* Fragment offset */
150     0x00, 0x00, 0x38, /* Fragment length */
151     0xFE, 0xFD, /* DTLSv1.2 */
152     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
153     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
154     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
155     0x00, /* Session id len */
156     0x14, /* Cookie len */
157     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
158     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
159 };
160 
161 
162 /* A ClientHello with a bad cookie */
163 static const unsigned char clienthello_badcookie[] = {
164     0x16, /* Handshake */
165     0xFE, 0xFF, /* DTLSv1.0 */
166     0x00, 0x00, /* Epoch */
167     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
168     0x00, 0x4E, /* Record Length */
169     0x01, /* ClientHello */
170     0x00, 0x00, 0x42, /* Message length */
171     0x00, 0x00, /* Message sequence */
172     0x00, 0x00, 0x00, /* Fragment offset */
173     0x00, 0x00, 0x42, /* Fragment length */
174     0xFE, 0xFD, /* DTLSv1.2 */
175     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
176     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
177     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
178     0x00, /* Session id len */
179     0x14, /* Cookie len */
180     0x01, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
181     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, /* Cookie */
182     0x00, 0x04, /* Ciphersuites len */
183     0x00, 0x2f, /* AES128-SHA */
184     0x00, 0xff, /* Empty reneg info SCSV */
185     0x01, /* Compression methods len */
186     0x00, /* Null compression */
187     0x00, 0x00 /* Extensions len */
188 };
189 
190 /* A fragmented ClientHello with the fragment boundary mid cookie */
191 static const unsigned char clienthello_cookie_short[] = {
192     0x16, /* Handshake */
193     0xFE, 0xFF, /* DTLSv1.0 */
194     0x00, 0x00, /* Epoch */
195     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
196     0x00, 0x43, /* Record Length */
197     0x01, /* ClientHello */
198     0x00, 0x00, 0x42, /* Message length */
199     0x00, 0x00, /* Message sequence */
200     0x00, 0x00, 0x00, /* Fragment offset */
201     0x00, 0x00, 0x37, /* Fragment length */
202     0xFE, 0xFD, /* DTLSv1.2 */
203     0xCA, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
204     0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
205     0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, /* Random */
206     0x00, /* Session id len */
207     0x14, /* Cookie len */
208     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
209     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12 /* Cookie */
210 };
211 
212 /* Bad record - too short */
213 static const unsigned char record_short[] = {
214     0x16, /* Handshake */
215     0xFE, 0xFF, /* DTLSv1.0 */
216     0x00, 0x00, /* Epoch */
217     0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* Record sequence number */
218 };
219 
220 static const unsigned char verify[] = {
221     0x16, /* Handshake */
222     0xFE, 0xFF, /* DTLSv1.0 */
223     0x00, 0x00, /* Epoch */
224     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Record sequence number */
225     0x00, 0x23, /* Record Length */
226     0x03, /* HelloVerifyRequest */
227     0x00, 0x00, 0x17, /* Message length */
228     0x00, 0x00, /* Message sequence */
229     0x00, 0x00, 0x00, /* Fragment offset */
230     0x00, 0x00, 0x17, /* Fragment length */
231     0xFE, 0xFF, /* DTLSv1.0 */
232     0x14, /* Cookie len */
233     0x00, 0x01, 0x02, 0x03, 0x04, 005, 0x06, 007, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
234     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13 /* Cookie */
235 };
236 
237 typedef struct {
238     const unsigned char *in;
239     unsigned int inlen;
240     /*
241      * GOOD == positive return value from DTLSv1_listen, no output yet
242      * VERIFY == 0 return value, HelloVerifyRequest sent
243      * DROP == 0 return value, no output
244      */
245     enum {GOOD, VERIFY, DROP} outtype;
246 } tests;
247 
248 static tests testpackets[9] = {
249     { clienthello_nocookie, sizeof(clienthello_nocookie), VERIFY },
250     { clienthello_nocookie_frag, sizeof(clienthello_nocookie_frag), VERIFY },
251     { clienthello_nocookie_short, sizeof(clienthello_nocookie_short), DROP },
252     { clienthello_2ndfrag, sizeof(clienthello_2ndfrag), DROP },
253     { clienthello_cookie, sizeof(clienthello_cookie), GOOD },
254     { clienthello_cookie_frag, sizeof(clienthello_cookie_frag), GOOD },
255     { clienthello_badcookie, sizeof(clienthello_badcookie), VERIFY },
256     { clienthello_cookie_short, sizeof(clienthello_cookie_short), DROP },
257     { record_short, sizeof(record_short), DROP }
258 };
259 
260 # define COOKIE_LEN  20
261 
cookie_gen(SSL * ssl,unsigned char * cookie,unsigned int * cookie_len)262 static int cookie_gen(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
263 {
264     unsigned int i;
265 
266     for (i = 0; i < COOKIE_LEN; i++, cookie++)
267         *cookie = i;
268     *cookie_len = COOKIE_LEN;
269 
270     return 1;
271 }
272 
cookie_verify(SSL * ssl,const unsigned char * cookie,unsigned int cookie_len)273 static int cookie_verify(SSL *ssl, const unsigned char *cookie,
274                          unsigned int cookie_len)
275 {
276     unsigned int i;
277 
278     if (cookie_len != COOKIE_LEN)
279         return 0;
280 
281     for (i = 0; i < COOKIE_LEN; i++, cookie++) {
282         if (*cookie != i)
283             return 0;
284     }
285 
286     return 1;
287 }
288 
dtls_listen_test(int i)289 static int dtls_listen_test(int i)
290 {
291     SSL_CTX *ctx = NULL;
292     SSL *ssl = NULL;
293     BIO *outbio = NULL;
294     BIO *inbio = NULL;
295     BIO_ADDR *peer = NULL;
296     tests *tp = &testpackets[i];
297     char *data;
298     long datalen;
299     int ret, success = 0;
300 
301     if (!TEST_ptr(ctx = SSL_CTX_new(DTLS_server_method()))
302             || !TEST_ptr(peer = BIO_ADDR_new()))
303         goto err;
304     SSL_CTX_set_cookie_generate_cb(ctx, cookie_gen);
305     SSL_CTX_set_cookie_verify_cb(ctx, cookie_verify);
306 
307     /* Create an SSL object and set the BIO */
308     if (!TEST_ptr(ssl = SSL_new(ctx))
309             || !TEST_ptr(outbio = BIO_new(BIO_s_mem())))
310         goto err;
311     SSL_set0_wbio(ssl, outbio);
312 
313     /* Set Non-blocking IO behaviour */
314     if (!TEST_ptr(inbio = BIO_new_mem_buf((char *)tp->in, tp->inlen)))
315         goto err;
316     BIO_set_mem_eof_return(inbio, -1);
317     SSL_set0_rbio(ssl, inbio);
318 
319     /* Process the incoming packet */
320     if (!TEST_int_ge(ret = DTLSv1_listen(ssl, peer), 0))
321         goto err;
322     datalen = BIO_get_mem_data(outbio, &data);
323 
324     if (tp->outtype == VERIFY) {
325         if (!TEST_int_eq(ret, 0)
326                 || !TEST_mem_eq(data, datalen, verify, sizeof(verify)))
327             goto err;
328     } else if (datalen == 0) {
329         if (!TEST_true((ret == 0 && tp->outtype == DROP)
330                 || (ret == 1 && tp->outtype == GOOD)))
331             goto err;
332     } else {
333         TEST_info("Test %d: unexpected data output", i);
334         goto err;
335     }
336     (void)BIO_reset(outbio);
337     inbio = NULL;
338     SSL_set0_rbio(ssl, NULL);
339     success = 1;
340 
341  err:
342     /* Also frees up outbio */
343     SSL_free(ssl);
344     SSL_CTX_free(ctx);
345     BIO_free(inbio);
346     OPENSSL_free(peer);
347     return success;
348 }
349 #endif
350 
setup_tests(void)351 int setup_tests(void)
352 {
353 #ifndef OPENSSL_NO_SOCK
354     ADD_ALL_TESTS(dtls_listen_test, (int)OSSL_NELEM(testpackets));
355 #endif
356     return 1;
357 }
358