2 * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
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
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/core_names.h>
33 #include <openssl/params.h>
34 #include <openssl/opensslconf.h>
35 #include <openssl/bio.h>
36 #include <openssl/crypto.h>
37 #include <openssl/evp.h>
38 #include <openssl/ssl.h>
39 #include <openssl/err.h>
40 #include <openssl/rand.h>
41 #include <openssl/kdf.h>
42 #include "internal/packet.h"
43 #include "internal/nelem.h"
46 /* For DTLS1_BAD_VER packets the MAC doesn't include the handshake header */
47 #define MAC_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH)
49 static unsigned char client_random
[SSL3_RANDOM_SIZE
];
50 static unsigned char server_random
[SSL3_RANDOM_SIZE
];
52 /* These are all generated locally, sized purely according to our own whim */
53 static unsigned char session_id
[32];
54 static unsigned char master_secret
[48];
55 static unsigned char cookie
[20];
57 /* We've hard-coded the cipher suite; we know it's 104 bytes */
58 static unsigned char key_block
[104];
59 #define mac_key (key_block + 20)
60 #define dec_key (key_block + 40)
61 #define enc_key (key_block + 56)
63 static EVP_MD_CTX
*handshake_md
;
65 static int do_PRF(const void *seed1
, int seed1_len
,
66 const void *seed2
, int seed2_len
,
67 const void *seed3
, int seed3_len
,
68 unsigned char *out
, int olen
)
70 EVP_PKEY_CTX
*pctx
= EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF
, NULL
);
73 /* No error handling. If it all screws up, the test will fail anyway */
74 EVP_PKEY_derive_init(pctx
);
75 EVP_PKEY_CTX_set_tls1_prf_md(pctx
, EVP_md5_sha1());
76 EVP_PKEY_CTX_set1_tls1_prf_secret(pctx
, master_secret
, sizeof(master_secret
));
77 EVP_PKEY_CTX_add1_tls1_prf_seed(pctx
, seed1
, seed1_len
);
78 EVP_PKEY_CTX_add1_tls1_prf_seed(pctx
, seed2
, seed2_len
);
79 EVP_PKEY_CTX_add1_tls1_prf_seed(pctx
, seed3
, seed3_len
);
80 EVP_PKEY_derive(pctx
, out
, &outlen
);
81 EVP_PKEY_CTX_free(pctx
);
85 static SSL_SESSION
*client_session(void)
87 static unsigned char session_asn1
[] = {
88 0x30, 0x5F, /* SEQUENCE, length 0x5F */
89 0x02, 0x01, 0x01, /* INTEGER, SSL_SESSION_ASN1_VERSION */
90 0x02, 0x02, 0x01, 0x00, /* INTEGER, DTLS1_BAD_VER */
91 0x04, 0x02, 0x00, 0x2F, /* OCTET_STRING, AES128-SHA */
92 0x04, 0x20, /* OCTET_STRING, session id */
93 #define SS_SESSID_OFS 15 /* Session ID goes here */
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x04, 0x30, /* OCTET_STRING, master secret */
99 #define SS_SECRET_OFS 49 /* Master secret goes here */
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 const unsigned char *p
= session_asn1
;
109 /* Copy the randomly-generated fields into the above ASN1 */
110 memcpy(session_asn1
+ SS_SESSID_OFS
, session_id
, sizeof(session_id
));
111 memcpy(session_asn1
+ SS_SECRET_OFS
, master_secret
, sizeof(master_secret
));
113 return d2i_SSL_SESSION(NULL
, &p
, sizeof(session_asn1
));
116 /* Returns 1 for initial ClientHello, 2 for ClientHello with cookie */
117 static int validate_client_hello(BIO
*wbio
)
122 int cookie_found
= 0;
125 len
= BIO_get_mem_data(wbio
, (char **)&data
);
126 if (!PACKET_buf_init(&pkt
, data
, len
))
129 /* Check record header type */
130 if (!PACKET_get_1(&pkt
, &u
) || u
!= SSL3_RT_HANDSHAKE
)
133 if (!PACKET_get_net_2(&pkt
, &u
) || u
!= DTLS1_BAD_VER
)
135 /* Skip the rest of the record header */
136 if (!PACKET_forward(&pkt
, DTLS1_RT_HEADER_LENGTH
- 3))
139 /* Check it's a ClientHello */
140 if (!PACKET_get_1(&pkt
, &u
) || u
!= SSL3_MT_CLIENT_HELLO
)
142 /* Skip the rest of the handshake message header */
143 if (!PACKET_forward(&pkt
, DTLS1_HM_HEADER_LENGTH
- 1))
146 /* Check client version */
147 if (!PACKET_get_net_2(&pkt
, &u
) || u
!= DTLS1_BAD_VER
)
151 if (!PACKET_copy_bytes(&pkt
, client_random
, SSL3_RANDOM_SIZE
))
154 /* Check session id length and content */
155 if (!PACKET_get_length_prefixed_1(&pkt
, &pkt2
) ||
156 !PACKET_equal(&pkt2
, session_id
, sizeof(session_id
)))
160 if (!PACKET_get_length_prefixed_1(&pkt
, &pkt2
))
162 if (PACKET_remaining(&pkt2
)) {
163 if (!PACKET_equal(&pkt2
, cookie
, sizeof(cookie
)))
169 if (!PACKET_get_net_2(&pkt
, &u
) || !PACKET_forward(&pkt
, u
))
172 /* Skip compression */
173 if (!PACKET_get_1(&pkt
, &u
) || !PACKET_forward(&pkt
, u
))
176 /* Skip extensions */
177 if (!PACKET_get_net_2(&pkt
, &u
) || !PACKET_forward(&pkt
, u
))
180 /* Now we are at the end */
181 if (PACKET_remaining(&pkt
))
184 /* Update handshake MAC for second ClientHello (with cookie) */
185 if (cookie_found
&& !EVP_DigestUpdate(handshake_md
, data
+ MAC_OFFSET
,
189 (void)BIO_reset(wbio
);
191 return 1 + cookie_found
;
194 static int send_hello_verify(BIO
*rbio
)
196 static unsigned char hello_verify
[] = {
197 0x16, /* Handshake */
198 0x01, 0x00, /* DTLS1_BAD_VER */
199 0x00, 0x00, /* Epoch 0 */
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Seq# 0 */
201 0x00, 0x23, /* Length */
202 0x03, /* Hello Verify */
203 0x00, 0x00, 0x17, /* Length */
204 0x00, 0x00, /* Seq# 0 */
205 0x00, 0x00, 0x00, /* Fragment offset */
206 0x00, 0x00, 0x17, /* Fragment length */
207 0x01, 0x00, /* DTLS1_BAD_VER */
208 0x14, /* Cookie length */
209 #define HV_COOKIE_OFS 28 /* Cookie goes here */
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00,
215 memcpy(hello_verify
+ HV_COOKIE_OFS
, cookie
, sizeof(cookie
));
217 BIO_write(rbio
, hello_verify
, sizeof(hello_verify
));
222 static int send_server_hello(BIO
*rbio
)
224 static unsigned char server_hello
[] = {
225 0x16, /* Handshake */
226 0x01, 0x00, /* DTLS1_BAD_VER */
227 0x00, 0x00, /* Epoch 0 */
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* Seq# 1 */
229 0x00, 0x52, /* Length */
230 0x02, /* Server Hello */
231 0x00, 0x00, 0x46, /* Length */
232 0x00, 0x01, /* Seq# */
233 0x00, 0x00, 0x00, /* Fragment offset */
234 0x00, 0x00, 0x46, /* Fragment length */
235 0x01, 0x00, /* DTLS1_BAD_VER */
236 #define SH_RANDOM_OFS 27 /* Server random goes here */
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x20, /* Session ID length */
242 #define SH_SESSID_OFS 60 /* Session ID goes here */
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 0x00, 0x2f, /* Cipher suite AES128-SHA */
248 0x00, /* Compression null */
250 static unsigned char change_cipher_spec
[] = {
251 0x14, /* Change Cipher Spec */
252 0x01, 0x00, /* DTLS1_BAD_VER */
253 0x00, 0x00, /* Epoch 0 */
254 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* Seq# 2 */
255 0x00, 0x03, /* Length */
256 0x01, 0x00, 0x02, /* Message */
259 memcpy(server_hello
+ SH_RANDOM_OFS
, server_random
, sizeof(server_random
));
260 memcpy(server_hello
+ SH_SESSID_OFS
, session_id
, sizeof(session_id
));
262 if (!EVP_DigestUpdate(handshake_md
, server_hello
+ MAC_OFFSET
,
263 sizeof(server_hello
) - MAC_OFFSET
))
266 BIO_write(rbio
, server_hello
, sizeof(server_hello
));
267 BIO_write(rbio
, change_cipher_spec
, sizeof(change_cipher_spec
));
272 /* Create header, HMAC, pad, encrypt and send a record */
273 static int send_record(BIO
*rbio
, unsigned char type
, uint64_t seqnr
,
274 const void *msg
, size_t len
)
276 /* Note that the order of the record header fields on the wire,
277 * and in the HMAC, is different. So we just keep them in separate
278 * variables and handle them individually. */
279 static unsigned char epoch
[2] = { 0x00, 0x01 };
280 static unsigned char seq
[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
281 static unsigned char ver
[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */
282 unsigned char lenbytes
[2];
285 EVP_CIPHER_CTX
*enc_ctx
;
286 unsigned char iv
[16];
289 OSSL_PARAM params
[2];
291 seq
[0] = (seqnr
>> 40) & 0xff;
292 seq
[1] = (seqnr
>> 32) & 0xff;
293 seq
[2] = (seqnr
>> 24) & 0xff;
294 seq
[3] = (seqnr
>> 16) & 0xff;
295 seq
[4] = (seqnr
>> 8) & 0xff;
296 seq
[5] = seqnr
& 0xff;
298 pad
= 15 - ((len
+ SHA_DIGEST_LENGTH
) % 16);
299 enc
= OPENSSL_malloc(len
+ SHA_DIGEST_LENGTH
+ 1 + pad
);
303 /* Copy record to encryption buffer */
304 memcpy(enc
, msg
, len
);
306 /* Append HMAC to data */
307 hmac
= EVP_MAC_fetch(NULL
, "HMAC", NULL
);
308 ctx
= EVP_MAC_CTX_new(hmac
);
310 params
[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST
,
312 params
[1] = OSSL_PARAM_construct_end();
313 EVP_MAC_init(ctx
, mac_key
, 20, params
);
314 EVP_MAC_update(ctx
, epoch
, 2);
315 EVP_MAC_update(ctx
, seq
, 6);
316 EVP_MAC_update(ctx
, &type
, 1);
317 EVP_MAC_update(ctx
, ver
, 2); /* Version */
318 lenbytes
[0] = (unsigned char)(len
>> 8);
319 lenbytes
[1] = (unsigned char)(len
);
320 EVP_MAC_update(ctx
, lenbytes
, 2); /* Length */
321 EVP_MAC_update(ctx
, enc
, len
); /* Finally the data itself */
322 EVP_MAC_final(ctx
, enc
+ len
, NULL
, SHA_DIGEST_LENGTH
);
323 EVP_MAC_CTX_free(ctx
);
325 /* Append padding bytes */
326 len
+= SHA_DIGEST_LENGTH
;
331 /* Generate IV, and encrypt */
332 RAND_bytes(iv
, sizeof(iv
));
333 enc_ctx
= EVP_CIPHER_CTX_new();
334 EVP_CipherInit_ex(enc_ctx
, EVP_aes_128_cbc(), NULL
, enc_key
, iv
, 1);
335 EVP_Cipher(enc_ctx
, enc
, enc
, len
);
336 EVP_CIPHER_CTX_free(enc_ctx
);
338 /* Finally write header (from fragmented variables), IV and encrypted record */
339 BIO_write(rbio
, &type
, 1);
340 BIO_write(rbio
, ver
, 2);
341 BIO_write(rbio
, epoch
, 2);
342 BIO_write(rbio
, seq
, 6);
343 lenbytes
[0] = (unsigned char)((len
+ sizeof(iv
)) >> 8);
344 lenbytes
[1] = (unsigned char)(len
+ sizeof(iv
));
345 BIO_write(rbio
, lenbytes
, 2);
347 BIO_write(rbio
, iv
, sizeof(iv
));
348 BIO_write(rbio
, enc
, len
);
354 static int send_finished(SSL
*s
, BIO
*rbio
)
356 static unsigned char finished_msg
[DTLS1_HM_HEADER_LENGTH
+
357 TLS1_FINISH_MAC_LENGTH
] = {
359 0x00, 0x00, 0x0c, /* Length */
360 0x00, 0x03, /* Seq# 3 */
361 0x00, 0x00, 0x00, /* Fragment offset */
362 0x00, 0x00, 0x0c, /* Fragment length */
363 /* Finished MAC (12 bytes) */
365 unsigned char handshake_hash
[EVP_MAX_MD_SIZE
];
367 /* Derive key material */
368 do_PRF(TLS_MD_KEY_EXPANSION_CONST
, TLS_MD_KEY_EXPANSION_CONST_SIZE
,
369 server_random
, SSL3_RANDOM_SIZE
,
370 client_random
, SSL3_RANDOM_SIZE
,
371 key_block
, sizeof(key_block
));
373 /* Generate Finished MAC */
374 if (!EVP_DigestFinal_ex(handshake_md
, handshake_hash
, NULL
))
377 do_PRF(TLS_MD_SERVER_FINISH_CONST
, TLS_MD_SERVER_FINISH_CONST_SIZE
,
378 handshake_hash
, EVP_MD_CTX_size(handshake_md
),
380 finished_msg
+ DTLS1_HM_HEADER_LENGTH
, TLS1_FINISH_MAC_LENGTH
);
382 return send_record(rbio
, SSL3_RT_HANDSHAKE
, 0,
383 finished_msg
, sizeof(finished_msg
));
386 static int validate_ccs(BIO
*wbio
)
393 len
= BIO_get_mem_data(wbio
, (char **)&data
);
394 if (!PACKET_buf_init(&pkt
, data
, len
))
397 /* Check record header type */
398 if (!PACKET_get_1(&pkt
, &u
) || u
!= SSL3_RT_CHANGE_CIPHER_SPEC
)
401 if (!PACKET_get_net_2(&pkt
, &u
) || u
!= DTLS1_BAD_VER
)
403 /* Skip the rest of the record header */
404 if (!PACKET_forward(&pkt
, DTLS1_RT_HEADER_LENGTH
- 3))
407 /* Check ChangeCipherSpec message */
408 if (!PACKET_get_1(&pkt
, &u
) || u
!= SSL3_MT_CCS
)
410 /* A DTLS1_BAD_VER ChangeCipherSpec also contains the
411 * handshake sequence number (which is 2 here) */
412 if (!PACKET_get_net_2(&pkt
, &u
) || u
!= 0x0002)
415 /* Now check the Finished packet */
416 if (!PACKET_get_1(&pkt
, &u
) || u
!= SSL3_RT_HANDSHAKE
)
418 if (!PACKET_get_net_2(&pkt
, &u
) || u
!= DTLS1_BAD_VER
)
421 /* Check epoch is now 1 */
422 if (!PACKET_get_net_2(&pkt
, &u
) || u
!= 0x0001)
425 /* That'll do for now. If OpenSSL accepted *our* Finished packet
426 * then it's evidently remembered that DTLS1_BAD_VER doesn't
427 * include the handshake header in the MAC. There's not a lot of
428 * point in implementing decryption here, just to check that it
429 * continues to get it right for one more packet. */
434 #define NODROP(x) { x##UL, 0 }
435 #define DROP(x) { x##UL, 1 }
441 NODROP(1), NODROP(3), NODROP(2),
442 NODROP(0x1234), NODROP(0x1230), NODROP(0x1235),
443 NODROP(0xffff), NODROP(0x10001), NODROP(0xfffe), NODROP(0x10000),
444 DROP(0x10001), DROP(0xff), NODROP(0x100000), NODROP(0x800000), NODROP(0x7fffe1),
445 NODROP(0xffffff), NODROP(0x1000000), NODROP(0xfffffe), DROP(0xffffff), NODROP(0x1000010),
446 NODROP(0xfffffd), NODROP(0x1000011), DROP(0x12), NODROP(0x1000012),
447 NODROP(0x1ffffff), NODROP(0x2000000), DROP(0x1ff00fe), NODROP(0x2000001),
448 NODROP(0x20fffff), NODROP(0x2105500), DROP(0x20ffffe), NODROP(0x21054ff),
449 NODROP(0x211ffff), DROP(0x2110000), NODROP(0x2120000)
450 /* The last test should be NODROP, because a DROP wouldn't get tested. */
453 static int test_bad_dtls(void)
455 SSL_SESSION
*sess
= NULL
;
465 RAND_bytes(session_id
, sizeof(session_id
));
466 RAND_bytes(master_secret
, sizeof(master_secret
));
467 RAND_bytes(cookie
, sizeof(cookie
));
468 RAND_bytes(server_random
+ 4, sizeof(server_random
) - 4);
471 memcpy(server_random
, &now
, sizeof(now
));
473 sess
= client_session();
477 handshake_md
= EVP_MD_CTX_new();
478 if (!TEST_ptr(handshake_md
)
479 || !TEST_true(EVP_DigestInit_ex(handshake_md
, EVP_md5_sha1(),
483 ctx
= SSL_CTX_new(DTLS_client_method());
485 || !TEST_true(SSL_CTX_set_min_proto_version(ctx
, DTLS1_BAD_VER
))
486 || !TEST_true(SSL_CTX_set_max_proto_version(ctx
, DTLS1_BAD_VER
))
487 || !TEST_true(SSL_CTX_set_cipher_list(ctx
, "AES128-SHA")))
492 || !TEST_true(SSL_set_session(con
, sess
)))
494 SSL_SESSION_free(sess
);
496 rbio
= BIO_new(BIO_s_mem());
497 wbio
= BIO_new(BIO_s_mem());
503 SSL_set_bio(con
, rbio
, wbio
);
505 if (!TEST_true(BIO_up_ref(rbio
))) {
507 * We can't up-ref but we assigned ownership to con, so we shouldn't
508 * free in the "end" block
514 if (!TEST_true(BIO_up_ref(wbio
))) {
519 SSL_set_connect_state(con
);
521 /* Send initial ClientHello */
522 ret
= SSL_do_handshake(con
);
523 if (!TEST_int_le(ret
, 0)
524 || !TEST_int_eq(SSL_get_error(con
, ret
), SSL_ERROR_WANT_READ
)
525 || !TEST_int_eq(validate_client_hello(wbio
), 1)
526 || !TEST_true(send_hello_verify(rbio
)))
529 ret
= SSL_do_handshake(con
);
530 if (!TEST_int_le(ret
, 0)
531 || !TEST_int_eq(SSL_get_error(con
, ret
), SSL_ERROR_WANT_READ
)
532 || !TEST_int_eq(validate_client_hello(wbio
), 2)
533 || !TEST_true(send_server_hello(rbio
)))
536 ret
= SSL_do_handshake(con
);
537 if (!TEST_int_le(ret
, 0)
538 || !TEST_int_eq(SSL_get_error(con
, ret
), SSL_ERROR_WANT_READ
)
539 || !TEST_true(send_finished(con
, rbio
)))
542 ret
= SSL_do_handshake(con
);
543 if (!TEST_int_gt(ret
, 0)
544 || !TEST_true(validate_ccs(wbio
)))
547 /* While we're here and crafting packets by hand, we might as well do a
548 bit of a stress test on the DTLS record replay handling. Not Cisco-DTLS
549 specific but useful anyway for the general case. It's been broken
550 before, and in fact was broken even for a basic 0, 2, 1 test case
551 when this test was first added.... */
552 for (i
= 0; i
< (int)OSSL_NELEM(tests
); i
++) {
553 uint64_t recv_buf
[2];
555 if (!TEST_true(send_record(rbio
, SSL3_RT_APPLICATION_DATA
, tests
[i
].seq
,
556 &tests
[i
].seq
, sizeof(uint64_t)))) {
557 TEST_error("Failed to send data seq #0x%x%08x (%d)\n",
558 (unsigned int)(tests
[i
].seq
>> 32), (unsigned int)tests
[i
].seq
, i
);
565 ret
= SSL_read(con
, recv_buf
, 2 * sizeof(uint64_t));
566 if (!TEST_int_eq(ret
, (int)sizeof(uint64_t))) {
567 TEST_error("SSL_read failed or wrong size on seq#0x%x%08x (%d)\n",
568 (unsigned int)(tests
[i
].seq
>> 32), (unsigned int)tests
[i
].seq
, i
);
571 if (!TEST_true(recv_buf
[0] == tests
[i
].seq
))
575 /* The last test cannot be DROP() */
576 if (!TEST_false(tests
[i
-1].drop
))
586 EVP_MD_CTX_free(handshake_md
);
591 int setup_tests(void)
593 ADD_TEST(test_bad_dtls
);