blob: 1c836b9c17cb416f2d817ba970de20a63ef08480 [file] [log] [blame]
David Woodhouse16938282016-07-25 14:31:43 +01001/*
Matt Caswell829b2b82017-04-11 16:26:13 +01002 * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
David Woodhouse16938282016-07-25 14:31:43 +01003 *
4 * Licensed under the OpenSSL license (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/*
11 * Unit test for Cisco DTLS1_BAD_VER session resume, as used by
12 * AnyConnect VPN protocol.
13 *
14 * This is designed to exercise the code paths in
15 * http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/dtls.c
16 * which have frequently been affected by regressions in DTLS1_BAD_VER
17 * support.
18 *
19 * Note that unlike other SSL tests, we don't test against our own SSL
20 * server method. Firstly because we don't have one; we *only* support
21 * DTLS1_BAD_VER as a client. And secondly because even if that were
Richard Levitted68a0ea2017-12-08 11:40:30 +010022 * fixed up it's the wrong thing to test against - because if changes
David Woodhouse16938282016-07-25 14:31:43 +010023 * are made in generic DTLS code which don't take DTLS1_BAD_VER into
24 * account, there's plenty of scope for making those changes such that
25 * they break *both* the client and the server in the same way.
26 *
27 * So we handle the server side manually. In a session resume there isn't
28 * much to be done anyway.
29 */
30#include <string.h>
31
32#include <openssl/opensslconf.h>
33#include <openssl/bio.h>
34#include <openssl/crypto.h>
35#include <openssl/evp.h>
36#include <openssl/ssl.h>
37#include <openssl/err.h>
38#include <openssl/rand.h>
39#include <openssl/kdf.h>
Richard Levitte9cc76cc2016-08-05 10:14:56 +020040#include "../ssl/packet_locl.h"
Rich Salz176db6d2017-08-22 08:35:43 -040041#include "internal/nelem.h"
Matt Caswell829b2b82017-04-11 16:26:13 +010042#include "testutil.h"
43
David Woodhouse16938282016-07-25 14:31:43 +010044/* For DTLS1_BAD_VER packets the MAC doesn't include the handshake header */
45#define MAC_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH)
46
47static unsigned char client_random[SSL3_RANDOM_SIZE];
48static unsigned char server_random[SSL3_RANDOM_SIZE];
49
50/* These are all generated locally, sized purely according to our own whim */
51static unsigned char session_id[32];
52static unsigned char master_secret[48];
53static unsigned char cookie[20];
54
55/* We've hard-coded the cipher suite; we know it's 104 bytes */
56static unsigned char key_block[104];
57#define mac_key (key_block + 20)
58#define dec_key (key_block + 40)
59#define enc_key (key_block + 56)
60
61static EVP_MD_CTX *handshake_md;
62
63static int do_PRF(const void *seed1, int seed1_len,
64 const void *seed2, int seed2_len,
65 const void *seed3, int seed3_len,
66 unsigned char *out, int olen)
67{
68 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
69 size_t outlen = olen;
70
71 /* No error handling. If it all screws up, the test will fail anyway */
72 EVP_PKEY_derive_init(pctx);
73 EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_md5_sha1());
74 EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, master_secret, sizeof(master_secret));
75 EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, seed1_len);
76 EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, seed2_len);
77 EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, seed3_len);
78 EVP_PKEY_derive(pctx, out, &outlen);
79 EVP_PKEY_CTX_free(pctx);
80 return 1;
81}
82
83static SSL_SESSION *client_session(void)
84{
85 static unsigned char session_asn1[] = {
86 0x30, 0x5F, /* SEQUENCE, length 0x5F */
87 0x02, 0x01, 0x01, /* INTEGER, SSL_SESSION_ASN1_VERSION */
88 0x02, 0x02, 0x01, 0x00, /* INTEGER, DTLS1_BAD_VER */
89 0x04, 0x02, 0x00, 0x2F, /* OCTET_STRING, AES128-SHA */
90 0x04, 0x20, /* OCTET_STRING, session id */
91#define SS_SESSID_OFS 15 /* Session ID goes here */
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x04, 0x30, /* OCTET_STRING, master secret */
97#define SS_SECRET_OFS 49 /* Master secret goes here */
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 };
105 const unsigned char *p = session_asn1;
106
107 /* Copy the randomly-generated fields into the above ASN1 */
108 memcpy(session_asn1 + SS_SESSID_OFS, session_id, sizeof(session_id));
109 memcpy(session_asn1 + SS_SECRET_OFS, master_secret, sizeof(master_secret));
110
111 return d2i_SSL_SESSION(NULL, &p, sizeof(session_asn1));
112}
113
David Woodhouse16938282016-07-25 14:31:43 +0100114/* Returns 1 for initial ClientHello, 2 for ClientHello with cookie */
115static int validate_client_hello(BIO *wbio)
116{
David Woodhouseeb633d02016-08-06 11:25:46 +0100117 PACKET pkt, pkt2;
David Woodhouse16938282016-07-25 14:31:43 +0100118 long len;
119 unsigned char *data;
120 int cookie_found = 0;
Benjamin Kaduk165cc512017-10-11 08:18:13 -0500121 unsigned int u = 0;
David Woodhouse16938282016-07-25 14:31:43 +0100122
123 len = BIO_get_mem_data(wbio, (char **)&data);
124 if (!PACKET_buf_init(&pkt, data, len))
125 return 0;
126
127 /* Check record header type */
128 if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
129 return 0;
130 /* Version */
131 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
132 return 0;
133 /* Skip the rest of the record header */
134 if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
135 return 0;
136
137 /* Check it's a ClientHello */
138 if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CLIENT_HELLO)
139 return 0;
140 /* Skip the rest of the handshake message header */
141 if (!PACKET_forward(&pkt, DTLS1_HM_HEADER_LENGTH - 1))
142 return 0;
143
144 /* Check client version */
145 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
146 return 0;
147
148 /* Store random */
149 if (!PACKET_copy_bytes(&pkt, client_random, SSL3_RANDOM_SIZE))
150 return 0;
151
152 /* Check session id length and content */
David Woodhouseeb633d02016-08-06 11:25:46 +0100153 if (!PACKET_get_length_prefixed_1(&pkt, &pkt2) ||
154 !PACKET_equal(&pkt2, session_id, sizeof(session_id)))
David Woodhouse16938282016-07-25 14:31:43 +0100155 return 0;
156
157 /* Check cookie */
David Woodhouseeb633d02016-08-06 11:25:46 +0100158 if (!PACKET_get_length_prefixed_1(&pkt, &pkt2))
David Woodhouse16938282016-07-25 14:31:43 +0100159 return 0;
David Woodhouseeb633d02016-08-06 11:25:46 +0100160 if (PACKET_remaining(&pkt2)) {
161 if (!PACKET_equal(&pkt2, cookie, sizeof(cookie)))
David Woodhouse16938282016-07-25 14:31:43 +0100162 return 0;
163 cookie_found = 1;
164 }
165
166 /* Skip ciphers */
167 if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
168 return 0;
169
170 /* Skip compression */
171 if (!PACKET_get_1(&pkt, &u) || !PACKET_forward(&pkt, u))
172 return 0;
173
174 /* Skip extensions */
175 if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
176 return 0;
177
178 /* Now we are at the end */
179 if (PACKET_remaining(&pkt))
180 return 0;
181
182 /* Update handshake MAC for second ClientHello (with cookie) */
183 if (cookie_found && !EVP_DigestUpdate(handshake_md, data + MAC_OFFSET,
184 len - MAC_OFFSET))
Matt Caswell829b2b82017-04-11 16:26:13 +0100185 return 0;
David Woodhouse16938282016-07-25 14:31:43 +0100186
187 (void)BIO_reset(wbio);
188
189 return 1 + cookie_found;
190}
191
192static int send_hello_verify(BIO *rbio)
193{
194 static unsigned char hello_verify[] = {
195 0x16, /* Handshake */
196 0x01, 0x00, /* DTLS1_BAD_VER */
197 0x00, 0x00, /* Epoch 0 */
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Seq# 0 */
199 0x00, 0x23, /* Length */
200 0x03, /* Hello Verify */
201 0x00, 0x00, 0x17, /* Length */
202 0x00, 0x00, /* Seq# 0 */
203 0x00, 0x00, 0x00, /* Fragment offset */
204 0x00, 0x00, 0x17, /* Fragment length */
205 0x01, 0x00, /* DTLS1_BAD_VER */
206 0x14, /* Cookie length */
207#define HV_COOKIE_OFS 28 /* Cookie goes here */
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00,
211 };
212
213 memcpy(hello_verify + HV_COOKIE_OFS, cookie, sizeof(cookie));
214
215 BIO_write(rbio, hello_verify, sizeof(hello_verify));
216
217 return 1;
218}
219
220static int send_server_hello(BIO *rbio)
221{
222 static unsigned char server_hello[] = {
223 0x16, /* Handshake */
224 0x01, 0x00, /* DTLS1_BAD_VER */
225 0x00, 0x00, /* Epoch 0 */
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* Seq# 1 */
227 0x00, 0x52, /* Length */
228 0x02, /* Server Hello */
229 0x00, 0x00, 0x46, /* Length */
230 0x00, 0x01, /* Seq# */
231 0x00, 0x00, 0x00, /* Fragment offset */
232 0x00, 0x00, 0x46, /* Fragment length */
233 0x01, 0x00, /* DTLS1_BAD_VER */
234#define SH_RANDOM_OFS 27 /* Server random goes here */
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x20, /* Session ID length */
240#define SH_SESSID_OFS 60 /* Session ID goes here */
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x2f, /* Cipher suite AES128-SHA */
246 0x00, /* Compression null */
247 };
248 static unsigned char change_cipher_spec[] = {
249 0x14, /* Change Cipher Spec */
250 0x01, 0x00, /* DTLS1_BAD_VER */
251 0x00, 0x00, /* Epoch 0 */
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* Seq# 2 */
253 0x00, 0x03, /* Length */
254 0x01, 0x00, 0x02, /* Message */
255 };
256
257 memcpy(server_hello + SH_RANDOM_OFS, server_random, sizeof(server_random));
258 memcpy(server_hello + SH_SESSID_OFS, session_id, sizeof(session_id));
259
260 if (!EVP_DigestUpdate(handshake_md, server_hello + MAC_OFFSET,
261 sizeof(server_hello) - MAC_OFFSET))
Matt Caswell829b2b82017-04-11 16:26:13 +0100262 return 0;
David Woodhouse16938282016-07-25 14:31:43 +0100263
264 BIO_write(rbio, server_hello, sizeof(server_hello));
265 BIO_write(rbio, change_cipher_spec, sizeof(change_cipher_spec));
266
267 return 1;
268}
269
270/* Create header, HMAC, pad, encrypt and send a record */
Matt Caswell829b2b82017-04-11 16:26:13 +0100271static int send_record(BIO *rbio, unsigned char type, uint64_t seqnr,
David Woodhouse16938282016-07-25 14:31:43 +0100272 const void *msg, size_t len)
273{
274 /* Note that the order of the record header fields on the wire,
275 * and in the HMAC, is different. So we just keep them in separate
276 * variables and handle them individually. */
277 static unsigned char epoch[2] = { 0x00, 0x01 };
278 static unsigned char seq[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
279 static unsigned char ver[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */
280 unsigned char lenbytes[2];
281 HMAC_CTX *ctx;
282 EVP_CIPHER_CTX *enc_ctx;
283 unsigned char iv[16];
284 unsigned char pad;
285 unsigned char *enc;
286
David Woodhouse16938282016-07-25 14:31:43 +0100287 seq[0] = (seqnr >> 40) & 0xff;
288 seq[1] = (seqnr >> 32) & 0xff;
David Woodhouse16938282016-07-25 14:31:43 +0100289 seq[2] = (seqnr >> 24) & 0xff;
290 seq[3] = (seqnr >> 16) & 0xff;
291 seq[4] = (seqnr >> 8) & 0xff;
292 seq[5] = seqnr & 0xff;
293
294 pad = 15 - ((len + SHA_DIGEST_LENGTH) % 16);
295 enc = OPENSSL_malloc(len + SHA_DIGEST_LENGTH + 1 + pad);
296 if (enc == NULL)
297 return 0;
298
299 /* Copy record to encryption buffer */
300 memcpy(enc, msg, len);
301
302 /* Append HMAC to data */
303 ctx = HMAC_CTX_new();
304 HMAC_Init_ex(ctx, mac_key, 20, EVP_sha1(), NULL);
305 HMAC_Update(ctx, epoch, 2);
306 HMAC_Update(ctx, seq, 6);
307 HMAC_Update(ctx, &type, 1);
308 HMAC_Update(ctx, ver, 2); /* Version */
Andy Polyakov3a63c0e2017-11-11 22:23:12 +0100309 lenbytes[0] = (unsigned char)(len >> 8);
310 lenbytes[1] = (unsigned char)(len);
David Woodhouse16938282016-07-25 14:31:43 +0100311 HMAC_Update(ctx, lenbytes, 2); /* Length */
312 HMAC_Update(ctx, enc, len); /* Finally the data itself */
313 HMAC_Final(ctx, enc + len, NULL);
314 HMAC_CTX_free(ctx);
315
316 /* Append padding bytes */
317 len += SHA_DIGEST_LENGTH;
318 do {
319 enc[len++] = pad;
320 } while (len % 16);
321
322 /* Generate IV, and encrypt */
323 RAND_bytes(iv, sizeof(iv));
324 enc_ctx = EVP_CIPHER_CTX_new();
325 EVP_CipherInit_ex(enc_ctx, EVP_aes_128_cbc(), NULL, enc_key, iv, 1);
326 EVP_Cipher(enc_ctx, enc, enc, len);
327 EVP_CIPHER_CTX_free(enc_ctx);
328
329 /* Finally write header (from fragmented variables), IV and encrypted record */
330 BIO_write(rbio, &type, 1);
331 BIO_write(rbio, ver, 2);
332 BIO_write(rbio, epoch, 2);
333 BIO_write(rbio, seq, 6);
Andy Polyakov3a63c0e2017-11-11 22:23:12 +0100334 lenbytes[0] = (unsigned char)((len + sizeof(iv)) >> 8);
335 lenbytes[1] = (unsigned char)(len + sizeof(iv));
David Woodhouse16938282016-07-25 14:31:43 +0100336 BIO_write(rbio, lenbytes, 2);
337
338 BIO_write(rbio, iv, sizeof(iv));
339 BIO_write(rbio, enc, len);
340
341 OPENSSL_free(enc);
342 return 1;
343}
344
345static int send_finished(SSL *s, BIO *rbio)
346{
347 static unsigned char finished_msg[DTLS1_HM_HEADER_LENGTH +
348 TLS1_FINISH_MAC_LENGTH] = {
349 0x14, /* Finished */
350 0x00, 0x00, 0x0c, /* Length */
351 0x00, 0x03, /* Seq# 3 */
352 0x00, 0x00, 0x00, /* Fragment offset */
353 0x00, 0x00, 0x0c, /* Fragment length */
354 /* Finished MAC (12 bytes) */
355 };
356 unsigned char handshake_hash[EVP_MAX_MD_SIZE];
357
358 /* Derive key material */
359 do_PRF(TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
360 server_random, SSL3_RANDOM_SIZE,
361 client_random, SSL3_RANDOM_SIZE,
362 key_block, sizeof(key_block));
363
364 /* Generate Finished MAC */
365 if (!EVP_DigestFinal_ex(handshake_md, handshake_hash, NULL))
Matt Caswell829b2b82017-04-11 16:26:13 +0100366 return 0;
David Woodhouse16938282016-07-25 14:31:43 +0100367
368 do_PRF(TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
369 handshake_hash, EVP_MD_CTX_size(handshake_md),
370 NULL, 0,
371 finished_msg + DTLS1_HM_HEADER_LENGTH, TLS1_FINISH_MAC_LENGTH);
372
373 return send_record(rbio, SSL3_RT_HANDSHAKE, 0,
374 finished_msg, sizeof(finished_msg));
375}
376
377static int validate_ccs(BIO *wbio)
378{
379 PACKET pkt;
380 long len;
381 unsigned char *data;
382 unsigned int u;
383
384 len = BIO_get_mem_data(wbio, (char **)&data);
385 if (!PACKET_buf_init(&pkt, data, len))
386 return 0;
387
388 /* Check record header type */
389 if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_CHANGE_CIPHER_SPEC)
390 return 0;
391 /* Version */
392 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
393 return 0;
394 /* Skip the rest of the record header */
395 if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
396 return 0;
397
398 /* Check ChangeCipherSpec message */
399 if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CCS)
400 return 0;
401 /* A DTLS1_BAD_VER ChangeCipherSpec also contains the
402 * handshake sequence number (which is 2 here) */
403 if (!PACKET_get_net_2(&pkt, &u) || u != 0x0002)
404 return 0;
405
406 /* Now check the Finished packet */
407 if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
408 return 0;
409 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
410 return 0;
411
412 /* Check epoch is now 1 */
413 if (!PACKET_get_net_2(&pkt, &u) || u != 0x0001)
414 return 0;
415
416 /* That'll do for now. If OpenSSL accepted *our* Finished packet
417 * then it's evidently remembered that DTLS1_BAD_VER doesn't
418 * include the handshake header in the MAC. There's not a lot of
419 * point in implementing decryption here, just to check that it
420 * continues to get it right for one more packet. */
421
422 return 1;
423}
424
425#define NODROP(x) { x##UL, 0 }
426#define DROP(x) { x##UL, 1 }
427
428static struct {
Matt Caswell829b2b82017-04-11 16:26:13 +0100429 uint64_t seq;
David Woodhouse16938282016-07-25 14:31:43 +0100430 int drop;
431} tests[] = {
432 NODROP(1), NODROP(3), NODROP(2),
433 NODROP(0x1234), NODROP(0x1230), NODROP(0x1235),
434 NODROP(0xffff), NODROP(0x10001), NODROP(0xfffe), NODROP(0x10000),
435 DROP(0x10001), DROP(0xff), NODROP(0x100000), NODROP(0x800000), NODROP(0x7fffe1),
436 NODROP(0xffffff), NODROP(0x1000000), NODROP(0xfffffe), DROP(0xffffff), NODROP(0x1000010),
437 NODROP(0xfffffd), NODROP(0x1000011), DROP(0x12), NODROP(0x1000012),
438 NODROP(0x1ffffff), NODROP(0x2000000), DROP(0x1ff00fe), NODROP(0x2000001),
439 NODROP(0x20fffff), NODROP(0x2105500), DROP(0x20ffffe), NODROP(0x21054ff),
440 NODROP(0x211ffff), DROP(0x2110000), NODROP(0x2120000)
441 /* The last test should be NODROP, because a DROP wouldn't get tested. */
442};
443
Matt Caswell829b2b82017-04-11 16:26:13 +0100444static int test_bad_dtls(void)
David Woodhouse16938282016-07-25 14:31:43 +0100445{
Matt Caswell829b2b82017-04-11 16:26:13 +0100446 SSL_SESSION *sess = NULL;
447 SSL_CTX *ctx = NULL;
448 SSL *con = NULL;
449 BIO *rbio = NULL;
450 BIO *wbio = NULL;
Matthias Kraftaf5883f2016-09-30 10:50:17 +0200451 time_t now = 0;
David Woodhouse16938282016-07-25 14:31:43 +0100452 int testresult = 0;
453 int ret;
454 int i;
455
David Woodhouse16938282016-07-25 14:31:43 +0100456 RAND_bytes(session_id, sizeof(session_id));
457 RAND_bytes(master_secret, sizeof(master_secret));
458 RAND_bytes(cookie, sizeof(cookie));
459 RAND_bytes(server_random + 4, sizeof(server_random) - 4);
Matthias Kraftaf5883f2016-09-30 10:50:17 +0200460
461 now = time(NULL);
462 memcpy(server_random, &now, sizeof(now));
David Woodhouse16938282016-07-25 14:31:43 +0100463
464 sess = client_session();
Matt Caswell829b2b82017-04-11 16:26:13 +0100465 if (!TEST_ptr(sess))
David Woodhouse16938282016-07-25 14:31:43 +0100466 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100467
468 handshake_md = EVP_MD_CTX_new();
Matt Caswell829b2b82017-04-11 16:26:13 +0100469 if (!TEST_ptr(handshake_md)
470 || !TEST_true(EVP_DigestInit_ex(handshake_md, EVP_md5_sha1(),
471 NULL)))
David Woodhouse16938282016-07-25 14:31:43 +0100472 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100473
474 ctx = SSL_CTX_new(DTLS_client_method());
Matt Caswell829b2b82017-04-11 16:26:13 +0100475 if (!TEST_ptr(ctx)
476 || !TEST_true(SSL_CTX_set_min_proto_version(ctx, DTLS1_BAD_VER))
477 || !TEST_true(SSL_CTX_set_max_proto_version(ctx, DTLS1_BAD_VER))
478 || !TEST_true(SSL_CTX_set_cipher_list(ctx, "AES128-SHA")))
479 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100480
481 con = SSL_new(ctx);
Matt Caswell829b2b82017-04-11 16:26:13 +0100482 if (!TEST_ptr(con)
483 || !TEST_true(SSL_set_session(con, sess)))
484 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100485 SSL_SESSION_free(sess);
486
487 rbio = BIO_new(BIO_s_mem());
488 wbio = BIO_new(BIO_s_mem());
489
Matt Caswell829b2b82017-04-11 16:26:13 +0100490 if (!TEST_ptr(rbio)
491 || !TEST_ptr(wbio))
492 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100493
494 SSL_set_bio(con, rbio, wbio);
Matt Caswell829b2b82017-04-11 16:26:13 +0100495
496 if (!TEST_true(BIO_up_ref(rbio))) {
497 /*
498 * We can't up-ref but we assigned ownership to con, so we shouldn't
499 * free in the "end" block
500 */
501 rbio = wbio = NULL;
502 goto end;
503 }
504
505 if (!TEST_true(BIO_up_ref(wbio))) {
506 wbio = NULL;
507 goto end;
508 }
509
David Woodhouse16938282016-07-25 14:31:43 +0100510 SSL_set_connect_state(con);
511
512 /* Send initial ClientHello */
513 ret = SSL_do_handshake(con);
Matt Caswell829b2b82017-04-11 16:26:13 +0100514 if (!TEST_int_le(ret, 0)
515 || !TEST_int_eq(SSL_get_error(con, ret), SSL_ERROR_WANT_READ)
516 || !TEST_int_eq(validate_client_hello(wbio), 1)
517 || !TEST_true(send_hello_verify(rbio)))
518 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100519
David Woodhouse16938282016-07-25 14:31:43 +0100520 ret = SSL_do_handshake(con);
Matt Caswell829b2b82017-04-11 16:26:13 +0100521 if (!TEST_int_le(ret, 0)
522 || !TEST_int_eq(SSL_get_error(con, ret), SSL_ERROR_WANT_READ)
523 || !TEST_int_eq(validate_client_hello(wbio), 2)
524 || !TEST_true(send_server_hello(rbio)))
525 goto end;
526
David Woodhouse16938282016-07-25 14:31:43 +0100527 ret = SSL_do_handshake(con);
Matt Caswell829b2b82017-04-11 16:26:13 +0100528 if (!TEST_int_le(ret, 0)
529 || !TEST_int_eq(SSL_get_error(con, ret), SSL_ERROR_WANT_READ)
530 || !TEST_true(send_finished(con, rbio)))
531 goto end;
532
David Woodhouse16938282016-07-25 14:31:43 +0100533 ret = SSL_do_handshake(con);
Matt Caswell829b2b82017-04-11 16:26:13 +0100534 if (!TEST_int_gt(ret, 0)
535 || !TEST_true(validate_ccs(wbio)))
536 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100537
538 /* While we're here and crafting packets by hand, we might as well do a
539 bit of a stress test on the DTLS record replay handling. Not Cisco-DTLS
540 specific but useful anyway for the general case. It's been broken
541 before, and in fact was broken even for a basic 0, 2, 1 test case
542 when this test was first added.... */
543 for (i = 0; i < (int)OSSL_NELEM(tests); i++) {
Matt Caswell829b2b82017-04-11 16:26:13 +0100544 uint64_t recv_buf[2];
David Woodhouse16938282016-07-25 14:31:43 +0100545
Matt Caswell829b2b82017-04-11 16:26:13 +0100546 if (!TEST_true(send_record(rbio, SSL3_RT_APPLICATION_DATA, tests[i].seq,
547 &tests[i].seq, sizeof(uint64_t)))) {
Todd Shortd1186c32017-04-13 10:20:04 -0400548 TEST_error("Failed to send data seq #0x%x%08x (%d)\n",
549 (unsigned int)(tests[i].seq >> 32), (unsigned int)tests[i].seq, i);
Matt Caswell829b2b82017-04-11 16:26:13 +0100550 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100551 }
552
553 if (tests[i].drop)
554 continue;
555
Matt Caswell829b2b82017-04-11 16:26:13 +0100556 ret = SSL_read(con, recv_buf, 2 * sizeof(uint64_t));
557 if (!TEST_int_eq(ret, (int)sizeof(uint64_t))) {
Todd Shortd1186c32017-04-13 10:20:04 -0400558 TEST_error("SSL_read failed or wrong size on seq#0x%x%08x (%d)\n",
559 (unsigned int)(tests[i].seq >> 32), (unsigned int)tests[i].seq, i);
Matt Caswell829b2b82017-04-11 16:26:13 +0100560 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100561 }
Matt Caswell829b2b82017-04-11 16:26:13 +0100562 if (!TEST_true(recv_buf[0] == tests[i].seq))
563 goto end;
David Woodhouse16938282016-07-25 14:31:43 +0100564 }
David Woodhouse16938282016-07-25 14:31:43 +0100565
Matt Caswell829b2b82017-04-11 16:26:13 +0100566 /* The last test cannot be DROP() */
567 if (!TEST_false(tests[i-1].drop))
568 goto end;
569
570 testresult = 1;
571
David Woodhouse16938282016-07-25 14:31:43 +0100572 end:
Matt Caswell829b2b82017-04-11 16:26:13 +0100573 BIO_free(rbio);
574 BIO_free(wbio);
575 SSL_free(con);
576 SSL_CTX_free(ctx);
577 EVP_MD_CTX_free(handshake_md);
David Woodhouse16938282016-07-25 14:31:43 +0100578
Matt Caswell829b2b82017-04-11 16:26:13 +0100579 return testresult;
580}
David Woodhouse16938282016-07-25 14:31:43 +0100581
Pauliad887412017-07-18 11:48:27 +1000582int setup_tests(void)
Matt Caswell829b2b82017-04-11 16:26:13 +0100583{
584 ADD_TEST(test_bad_dtls);
Pauliad887412017-07-18 11:48:27 +1000585 return 1;
David Woodhouse16938282016-07-25 14:31:43 +0100586}