2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
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
11 * Unit test for Cisco DTLS1_BAD_VER session resume, as used by
12 * AnyConnect VPN protocol.
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
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
22 * fixed up it's the wrong thing to test against — because if changes
23 * 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.
27 * So we handle the server side manually. In a session resume there isn't
28 * much to be done anyway.
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>
41 #include "../ssl/packet_locl.h"
42 #include "../e_os.h" /* for OSSL_NELEM() */
44 /* 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)
47 static unsigned char client_random[SSL3_RANDOM_SIZE];
48 static unsigned char server_random[SSL3_RANDOM_SIZE];
50 /* These are all generated locally, sized purely according to our own whim */
51 static unsigned char session_id[32];
52 static unsigned char master_secret[48];
53 static unsigned char cookie[20];
55 /* We've hard-coded the cipher suite; we know it's 104 bytes */
56 static 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)
61 static EVP_MD_CTX *handshake_md;
63 static 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)
68 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
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);
83 static SSL_SESSION *client_session(void)
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,
105 const unsigned char *p = session_asn1;
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));
111 return d2i_SSL_SESSION(NULL, &p, sizeof(session_asn1));
114 /* PACKET_equal() doesn't quite do what we need. Provide a version that
115 * does, in a form that can easily be moved to ssl_locl.h if anyone else
116 * cares to come up with a better name and use it too... */
117 __owur static ossl_inline int PACKET_starts(PACKET *pkt, const void *ptr,
120 if (PACKET_remaining(pkt) < num)
122 if (CRYPTO_memcmp(pkt->curr, ptr, num) != 0)
125 packet_forward(pkt, num);
129 /* Returns 1 for initial ClientHello, 2 for ClientHello with cookie */
130 static int validate_client_hello(BIO *wbio)
135 int cookie_found = 0;
138 len = BIO_get_mem_data(wbio, (char **)&data);
139 if (!PACKET_buf_init(&pkt, data, len))
142 /* Check record header type */
143 if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
146 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
148 /* Skip the rest of the record header */
149 if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
152 /* Check it's a ClientHello */
153 if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CLIENT_HELLO)
155 /* Skip the rest of the handshake message header */
156 if (!PACKET_forward(&pkt, DTLS1_HM_HEADER_LENGTH - 1))
159 /* Check client version */
160 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
164 if (!PACKET_copy_bytes(&pkt, client_random, SSL3_RANDOM_SIZE))
167 /* Check session id length and content */
168 if (!PACKET_get_1(&pkt, &u))
170 if (u != sizeof(session_id) || !PACKET_starts(&pkt, session_id, u))
174 if (!PACKET_get_1(&pkt, &u))
177 if (u != sizeof(cookie) || !PACKET_starts(&pkt, cookie, u))
183 if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
186 /* Skip compression */
187 if (!PACKET_get_1(&pkt, &u) || !PACKET_forward(&pkt, u))
190 /* Skip extensions */
191 if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
194 /* Now we are at the end */
195 if (PACKET_remaining(&pkt))
198 /* Update handshake MAC for second ClientHello (with cookie) */
199 if (cookie_found && !EVP_DigestUpdate(handshake_md, data + MAC_OFFSET,
201 printf("EVP_DigestUpdate() failed\n");
203 (void)BIO_reset(wbio);
205 return 1 + cookie_found;
208 static int send_hello_verify(BIO *rbio)
210 static unsigned char hello_verify[] = {
211 0x16, /* Handshake */
212 0x01, 0x00, /* DTLS1_BAD_VER */
213 0x00, 0x00, /* Epoch 0 */
214 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Seq# 0 */
215 0x00, 0x23, /* Length */
216 0x03, /* Hello Verify */
217 0x00, 0x00, 0x17, /* Length */
218 0x00, 0x00, /* Seq# 0 */
219 0x00, 0x00, 0x00, /* Fragment offset */
220 0x00, 0x00, 0x17, /* Fragment length */
221 0x01, 0x00, /* DTLS1_BAD_VER */
222 0x14, /* Cookie length */
223 #define HV_COOKIE_OFS 28 /* Cookie goes here */
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00,
229 memcpy(hello_verify + HV_COOKIE_OFS, cookie, sizeof(cookie));
231 BIO_write(rbio, hello_verify, sizeof(hello_verify));
236 static int send_server_hello(BIO *rbio)
238 static unsigned char server_hello[] = {
239 0x16, /* Handshake */
240 0x01, 0x00, /* DTLS1_BAD_VER */
241 0x00, 0x00, /* Epoch 0 */
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* Seq# 1 */
243 0x00, 0x52, /* Length */
244 0x02, /* Server Hello */
245 0x00, 0x00, 0x46, /* Length */
246 0x00, 0x01, /* Seq# */
247 0x00, 0x00, 0x00, /* Fragment offset */
248 0x00, 0x00, 0x46, /* Fragment length */
249 0x01, 0x00, /* DTLS1_BAD_VER */
250 #define SH_RANDOM_OFS 27 /* Server random goes here */
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255 0x20, /* Session ID length */
256 #define SH_SESSID_OFS 60 /* Session ID goes here */
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x2f, /* Cipher suite AES128-SHA */
262 0x00, /* Compression null */
264 static unsigned char change_cipher_spec[] = {
265 0x14, /* Change Cipher Spec */
266 0x01, 0x00, /* DTLS1_BAD_VER */
267 0x00, 0x00, /* Epoch 0 */
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* Seq# 2 */
269 0x00, 0x03, /* Length */
270 0x01, 0x00, 0x02, /* Message */
273 memcpy(server_hello + SH_RANDOM_OFS, server_random, sizeof(server_random));
274 memcpy(server_hello + SH_SESSID_OFS, session_id, sizeof(session_id));
276 if (!EVP_DigestUpdate(handshake_md, server_hello + MAC_OFFSET,
277 sizeof(server_hello) - MAC_OFFSET))
278 printf("EVP_DigestUpdate() failed\n");
280 BIO_write(rbio, server_hello, sizeof(server_hello));
281 BIO_write(rbio, change_cipher_spec, sizeof(change_cipher_spec));
286 /* Create header, HMAC, pad, encrypt and send a record */
287 static int send_record(BIO *rbio, unsigned char type, unsigned long seqnr,
288 const void *msg, size_t len)
290 /* Note that the order of the record header fields on the wire,
291 * and in the HMAC, is different. So we just keep them in separate
292 * variables and handle them individually. */
293 static unsigned char epoch[2] = { 0x00, 0x01 };
294 static unsigned char seq[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
295 static unsigned char ver[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */
296 unsigned char lenbytes[2];
298 EVP_CIPHER_CTX *enc_ctx;
299 unsigned char iv[16];
303 #ifdef SIXTY_FOUR_BIT_LONG
304 seq[0] = (seqnr >> 40) & 0xff;
305 seq[1] = (seqnr >> 32) & 0xff;
307 seq[2] = (seqnr >> 24) & 0xff;
308 seq[3] = (seqnr >> 16) & 0xff;
309 seq[4] = (seqnr >> 8) & 0xff;
310 seq[5] = seqnr & 0xff;
312 pad = 15 - ((len + SHA_DIGEST_LENGTH) % 16);
313 enc = OPENSSL_malloc(len + SHA_DIGEST_LENGTH + 1 + pad);
317 /* Copy record to encryption buffer */
318 memcpy(enc, msg, len);
320 /* Append HMAC to data */
321 ctx = HMAC_CTX_new();
322 HMAC_Init_ex(ctx, mac_key, 20, EVP_sha1(), NULL);
323 HMAC_Update(ctx, epoch, 2);
324 HMAC_Update(ctx, seq, 6);
325 HMAC_Update(ctx, &type, 1);
326 HMAC_Update(ctx, ver, 2); /* Version */
327 lenbytes[0] = len >> 8;
328 lenbytes[1] = len & 0xff;
329 HMAC_Update(ctx, lenbytes, 2); /* Length */
330 HMAC_Update(ctx, enc, len); /* Finally the data itself */
331 HMAC_Final(ctx, enc + len, NULL);
334 /* Append padding bytes */
335 len += SHA_DIGEST_LENGTH;
340 /* Generate IV, and encrypt */
341 RAND_bytes(iv, sizeof(iv));
342 enc_ctx = EVP_CIPHER_CTX_new();
343 EVP_CipherInit_ex(enc_ctx, EVP_aes_128_cbc(), NULL, enc_key, iv, 1);
344 EVP_Cipher(enc_ctx, enc, enc, len);
345 EVP_CIPHER_CTX_free(enc_ctx);
347 /* Finally write header (from fragmented variables), IV and encrypted record */
348 BIO_write(rbio, &type, 1);
349 BIO_write(rbio, ver, 2);
350 BIO_write(rbio, epoch, 2);
351 BIO_write(rbio, seq, 6);
352 lenbytes[0] = (len + sizeof(iv)) >> 8;
353 lenbytes[1] = (len + sizeof(iv)) & 0xff;
354 BIO_write(rbio, lenbytes, 2);
356 BIO_write(rbio, iv, sizeof(iv));
357 BIO_write(rbio, enc, len);
363 static int send_finished(SSL *s, BIO *rbio)
365 static unsigned char finished_msg[DTLS1_HM_HEADER_LENGTH +
366 TLS1_FINISH_MAC_LENGTH] = {
368 0x00, 0x00, 0x0c, /* Length */
369 0x00, 0x03, /* Seq# 3 */
370 0x00, 0x00, 0x00, /* Fragment offset */
371 0x00, 0x00, 0x0c, /* Fragment length */
372 /* Finished MAC (12 bytes) */
374 unsigned char handshake_hash[EVP_MAX_MD_SIZE];
376 /* Derive key material */
377 do_PRF(TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
378 server_random, SSL3_RANDOM_SIZE,
379 client_random, SSL3_RANDOM_SIZE,
380 key_block, sizeof(key_block));
382 /* Generate Finished MAC */
383 if (!EVP_DigestFinal_ex(handshake_md, handshake_hash, NULL))
384 printf("EVP_DigestFinal_ex() failed\n");
386 do_PRF(TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
387 handshake_hash, EVP_MD_CTX_size(handshake_md),
389 finished_msg + DTLS1_HM_HEADER_LENGTH, TLS1_FINISH_MAC_LENGTH);
391 return send_record(rbio, SSL3_RT_HANDSHAKE, 0,
392 finished_msg, sizeof(finished_msg));
395 static int validate_ccs(BIO *wbio)
402 len = BIO_get_mem_data(wbio, (char **)&data);
403 if (!PACKET_buf_init(&pkt, data, len))
406 /* Check record header type */
407 if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_CHANGE_CIPHER_SPEC)
410 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
412 /* Skip the rest of the record header */
413 if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
416 /* Check ChangeCipherSpec message */
417 if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CCS)
419 /* A DTLS1_BAD_VER ChangeCipherSpec also contains the
420 * handshake sequence number (which is 2 here) */
421 if (!PACKET_get_net_2(&pkt, &u) || u != 0x0002)
424 /* Now check the Finished packet */
425 if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
427 if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
430 /* Check epoch is now 1 */
431 if (!PACKET_get_net_2(&pkt, &u) || u != 0x0001)
434 /* That'll do for now. If OpenSSL accepted *our* Finished packet
435 * then it's evidently remembered that DTLS1_BAD_VER doesn't
436 * include the handshake header in the MAC. There's not a lot of
437 * point in implementing decryption here, just to check that it
438 * continues to get it right for one more packet. */
443 #define NODROP(x) { x##UL, 0 }
444 #define DROP(x) { x##UL, 1 }
450 NODROP(1), NODROP(3), NODROP(2),
451 NODROP(0x1234), NODROP(0x1230), NODROP(0x1235),
452 NODROP(0xffff), NODROP(0x10001), NODROP(0xfffe), NODROP(0x10000),
453 DROP(0x10001), DROP(0xff), NODROP(0x100000), NODROP(0x800000), NODROP(0x7fffe1),
454 NODROP(0xffffff), NODROP(0x1000000), NODROP(0xfffffe), DROP(0xffffff), NODROP(0x1000010),
455 NODROP(0xfffffd), NODROP(0x1000011), DROP(0x12), NODROP(0x1000012),
456 NODROP(0x1ffffff), NODROP(0x2000000), DROP(0x1ff00fe), NODROP(0x2000001),
457 NODROP(0x20fffff), NODROP(0x2105500), DROP(0x20ffffe), NODROP(0x21054ff),
458 NODROP(0x211ffff), DROP(0x2110000), NODROP(0x2120000)
459 /* The last test should be NODROP, because a DROP wouldn't get tested. */
462 int main(int argc, char *argv[])
474 err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
476 CRYPTO_set_mem_debug(1);
477 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
479 RAND_bytes(session_id, sizeof(session_id));
480 RAND_bytes(master_secret, sizeof(master_secret));
481 RAND_bytes(cookie, sizeof(cookie));
482 RAND_bytes(server_random + 4, sizeof(server_random) - 4);
483 time((void *)server_random);
485 sess = client_session();
487 printf("Failed to generate SSL_SESSION\n");
491 handshake_md = EVP_MD_CTX_new();
492 if (handshake_md == NULL ||
493 !EVP_DigestInit_ex(handshake_md, EVP_md5_sha1(), NULL)) {
494 printf("Failed to initialise handshake_md\n");
498 ctx = SSL_CTX_new(DTLS_client_method());
500 printf("Failed to allocate SSL_CTX\n");
503 if (!SSL_CTX_set_min_proto_version(ctx, DTLS1_BAD_VER)) {
504 printf("SSL_CTX_set_min_proto_version() failed\n");
507 if (!SSL_CTX_set_max_proto_version(ctx, DTLS1_BAD_VER)) {
508 printf("SSL_CTX_set_max_proto_version() failed\n");
512 if (!SSL_CTX_set_cipher_list(ctx, "AES128-SHA")) {
513 printf("SSL_CTX_set_cipher_list() failed\n");
518 if (!SSL_set_session(con, sess)) {
519 printf("SSL_set_session() failed\n");
522 SSL_SESSION_free(sess);
524 rbio = BIO_new(BIO_s_mem());
525 wbio = BIO_new(BIO_s_mem());
527 BIO_set_nbio(rbio, 1);
528 BIO_set_nbio(wbio, 1);
530 SSL_set_bio(con, rbio, wbio);
531 SSL_set_connect_state(con);
533 /* Send initial ClientHello */
534 ret = SSL_do_handshake(con);
535 if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
536 printf("Unexpected handshake result at initial call!\n");
540 if (validate_client_hello(wbio) != 1) {
541 printf("Initial ClientHello failed validation\n");
544 if (send_hello_verify(rbio) != 1) {
545 printf("Failed to send HelloVerify\n");
548 ret = SSL_do_handshake(con);
549 if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
550 printf("Unexpected handshake result after HelloVerify!\n");
553 if (validate_client_hello(wbio) != 2) {
554 printf("Second ClientHello failed validation\n");
557 if (send_server_hello(rbio) != 1) {
558 printf("Failed to send ServerHello\n");
561 ret = SSL_do_handshake(con);
562 if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
563 printf("Unexpected handshake result after ServerHello!\n");
566 if (send_finished(con, rbio) != 1) {
567 printf("Failed to send Finished\n");
570 ret = SSL_do_handshake(con);
572 printf("Handshake not successful after Finished!\n");
575 if (validate_ccs(wbio) != 1) {
576 printf("Failed to validate client CCS/Finished\n");
580 /* While we're here and crafting packets by hand, we might as well do a
581 bit of a stress test on the DTLS record replay handling. Not Cisco-DTLS
582 specific but useful anyway for the general case. It's been broken
583 before, and in fact was broken even for a basic 0, 2, 1 test case
584 when this test was first added.... */
585 for (i = 0; i < (int)OSSL_NELEM(tests); i++) {
586 unsigned long recv_buf[2];
588 if (send_record(rbio, SSL3_RT_APPLICATION_DATA, tests[i].seq,
589 &tests[i].seq, sizeof(unsigned long)) != 1) {
590 printf("Failed to send data seq #0x%lx (%d)\n",
598 ret = SSL_read(con, recv_buf, 2 * sizeof(unsigned long));
599 if (ret != sizeof(unsigned long)) {
600 printf("SSL_read failed or wrong size on seq#0x%lx (%d)\n",
604 if (recv_buf[0] != tests[i].seq) {
605 printf("Wrong data packet received (0x%lx not 0x%lx) at packet %d\n",
606 recv_buf[0], tests[i].seq, i);
610 if (tests[i-1].drop) {
611 printf("Error: last test cannot be DROP()\n");
621 EVP_MD_CTX_free(handshake_md);
623 ERR_print_errors_fp(stderr);
626 printf("Cisco BadDTLS test: FAILED\n");
630 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
631 if (CRYPTO_mem_leaks(err) <= 0)
636 return testresult?0:1;