xref: /freebsd/crypto/openssl/test/recordlentest.c (revision dece5b05f577fc4c6b89af7ad48dfbdf7cc4945c)
1 /*
2  * Copyright 2017-2026 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 
12 #include <openssl/evp.h>
13 
14 #include "helpers/ssltestlib.h"
15 #include "testutil.h"
16 
17 static char *cert = NULL;
18 static char *privkey = NULL;
19 
20 #define TEST_PLAINTEXT_OVERFLOW_OK 0
21 #define TEST_PLAINTEXT_OVERFLOW_NOT_OK 1
22 #define TEST_ENCRYPTED_OVERFLOW_TLS1_3_OK 2
23 #define TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK 3
24 #define TEST_ENCRYPTED_OVERFLOW_TLS1_2_OK 4
25 #define TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK 5
26 
27 #define TOTAL_RECORD_OVERFLOW_TESTS 6
28 
29 static int write_record(BIO *b, size_t len, uint8_t rectype, int recversion)
30 {
31     unsigned char header[SSL3_RT_HEADER_LENGTH];
32     size_t written;
33     unsigned char buf[256];
34 
35     memset(buf, 0, sizeof(buf));
36 
37     header[0] = rectype;
38     header[1] = (recversion >> 8) & 0xff;
39     header[2] = recversion & 0xff;
40     header[3] = (len >> 8) & 0xff;
41     header[4] = len & 0xff;
42 
43     if (!BIO_write_ex(b, header, SSL3_RT_HEADER_LENGTH, &written)
44         || written != SSL3_RT_HEADER_LENGTH)
45         return 0;
46 
47     while (len > 0) {
48         size_t outlen;
49 
50         if (len > sizeof(buf))
51             outlen = sizeof(buf);
52         else
53             outlen = len;
54 
55         if (!BIO_write_ex(b, buf, outlen, &written)
56             || written != outlen)
57             return 0;
58 
59         len -= outlen;
60     }
61 
62     return 1;
63 }
64 
65 #if !defined(OPENSSL_NO_DTLS1_2)
66 static int write_dtls_record(BIO *b, size_t len, uint8_t rectype,
67     int recversion, uint16_t epoch, uint64_t seq)
68 {
69     unsigned char record[DTLS1_RT_HEADER_LENGTH + 256] = { 0 };
70     size_t written, i;
71 
72     if (len > sizeof(record) - DTLS1_RT_HEADER_LENGTH)
73         return 0;
74 
75     record[0] = rectype;
76     record[1] = (recversion >> 8) & 0xff;
77     record[2] = recversion & 0xff;
78     record[3] = (epoch >> 8) & 0xff;
79     record[4] = epoch & 0xff;
80     for (i = 0; i < 6; i++)
81         record[10 - i] = (seq >> (8 * i)) & 0xff;
82     record[11] = (len >> 8) & 0xff;
83     record[12] = len & 0xff;
84 
85     return BIO_write_ex(b, record, DTLS1_RT_HEADER_LENGTH + len, &written)
86         && written == DTLS1_RT_HEADER_LENGTH + len;
87 }
88 #endif
89 
90 static int fail_due_to_record_overflow(int enc)
91 {
92     long err = ERR_peek_error();
93     int reason;
94 
95     if (enc)
96         reason = SSL_R_ENCRYPTED_LENGTH_TOO_LONG;
97     else
98         reason = SSL_R_DATA_LENGTH_TOO_LONG;
99 
100     if (ERR_GET_LIB(err) == ERR_LIB_SSL
101         && ERR_GET_REASON(err) == reason)
102         return 1;
103 
104     return 0;
105 }
106 
107 static int test_record_overflow(int idx)
108 {
109     SSL_CTX *cctx = NULL, *sctx = NULL;
110     SSL *clientssl = NULL, *serverssl = NULL;
111     int testresult = 0;
112     size_t len = 0;
113     size_t written;
114     int overf_expected;
115     unsigned char buf;
116     BIO *serverbio;
117     int recversion;
118 
119 #ifdef OPENSSL_NO_TLS1_2
120     if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_OK
121         || idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK)
122         return 1;
123 #endif
124 #if defined(OPENSSL_NO_TLS1_3) \
125     || (defined(OPENSSL_NO_EC) && defined(OPENSSL_NO_DH))
126     if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_OK
127         || idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK)
128         return 1;
129 #endif
130 
131     if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
132             TLS_client_method(),
133             TLS1_VERSION, 0,
134             &sctx, &cctx, cert, privkey)))
135         goto end;
136 
137     if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_OK
138         || idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK) {
139         len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
140 #ifndef OPENSSL_NO_COMP
141         len -= SSL3_RT_MAX_COMPRESSED_OVERHEAD;
142 #endif
143         SSL_CTX_set_max_proto_version(sctx, TLS1_2_VERSION);
144     } else if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_OK
145         || idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK) {
146         len = SSL3_RT_MAX_TLS13_ENCRYPTED_LENGTH;
147     }
148 
149     if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
150             NULL, NULL)))
151         goto end;
152 
153     serverbio = SSL_get_rbio(serverssl);
154 
155     if (idx == TEST_PLAINTEXT_OVERFLOW_OK
156         || idx == TEST_PLAINTEXT_OVERFLOW_NOT_OK) {
157         len = SSL3_RT_MAX_PLAIN_LENGTH;
158 
159         if (idx == TEST_PLAINTEXT_OVERFLOW_NOT_OK)
160             len++;
161 
162         if (!TEST_true(write_record(serverbio, len,
163                 SSL3_RT_HANDSHAKE, TLS1_VERSION)))
164             goto end;
165 
166         if (!TEST_int_le(SSL_accept(serverssl), 0))
167             goto end;
168 
169         overf_expected = (idx == TEST_PLAINTEXT_OVERFLOW_OK) ? 0 : 1;
170         if (!TEST_int_eq(fail_due_to_record_overflow(0), overf_expected))
171             goto end;
172 
173         goto success;
174     }
175 
176     if (!TEST_true(create_ssl_connection(serverssl, clientssl,
177             SSL_ERROR_NONE)))
178         goto end;
179 
180     if (idx == TEST_ENCRYPTED_OVERFLOW_TLS1_2_NOT_OK
181         || idx == TEST_ENCRYPTED_OVERFLOW_TLS1_3_NOT_OK) {
182         overf_expected = 1;
183         len++;
184     } else {
185         overf_expected = 0;
186     }
187 
188     recversion = TLS1_2_VERSION;
189 
190     if (!TEST_true(write_record(serverbio, len, SSL3_RT_APPLICATION_DATA,
191             recversion)))
192         goto end;
193 
194     if (!TEST_false(SSL_read_ex(serverssl, &buf, sizeof(buf), &written)))
195         goto end;
196 
197     if (!TEST_int_eq(fail_due_to_record_overflow(1), overf_expected))
198         goto end;
199 
200 success:
201     testresult = 1;
202 
203 end:
204     SSL_free(serverssl);
205     SSL_free(clientssl);
206     SSL_CTX_free(sctx);
207     SSL_CTX_free(cctx);
208     return testresult;
209 }
210 
211 static int write_and_read_app_data(SSL *serverssl, SSL *clientssl)
212 {
213     static const unsigned char msg = 0xa5;
214     unsigned char buf = 0;
215     size_t readbytes = 0, written = 0;
216 
217     return TEST_true(SSL_write_ex(clientssl, &msg, sizeof(msg), &written))
218         && TEST_size_t_eq(written, sizeof(msg))
219         && TEST_true(SSL_read_ex(serverssl, &buf, sizeof(buf),
220             &readbytes))
221         && TEST_size_t_eq(readbytes, sizeof(msg))
222         && TEST_uchar_eq(buf, msg);
223 }
224 
225 typedef enum {
226     SHORT_AEAD_RECORD_AES,
227     SHORT_AEAD_RECORD_ARIA,
228     SHORT_AEAD_RECORD_CHACHA
229 } SHORT_AEAD_RECORD_CIPHER;
230 
231 typedef struct {
232     const char *cipher;
233     size_t record_len;
234     SHORT_AEAD_RECORD_CIPHER cipher_type;
235 } SHORT_AEAD_RECORD_TEST;
236 
237 #if !defined(OPENSSL_NO_TLS1_2)
238 static const SHORT_AEAD_RECORD_TEST short_aead_record_tests[] = {
239     { TLS1_TXT_RSA_WITH_AES_128_CCM, 0, SHORT_AEAD_RECORD_AES },
240     { TLS1_TXT_RSA_WITH_AES_128_CCM,
241         EVP_CCM_TLS_EXPLICIT_IV_LEN + EVP_CCM_TLS_TAG_LEN - 1,
242         SHORT_AEAD_RECORD_AES },
243     { TLS1_TXT_RSA_WITH_AES_128_CCM_8,
244         EVP_CCM_TLS_EXPLICIT_IV_LEN + EVP_CCM8_TLS_TAG_LEN - 1,
245         SHORT_AEAD_RECORD_AES },
246     { TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
247         EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN - 1,
248         SHORT_AEAD_RECORD_AES },
249     { TLS1_TXT_RSA_WITH_ARIA_128_GCM_SHA256,
250         EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN - 1,
251         SHORT_AEAD_RECORD_ARIA },
252     { TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
253         EVP_CHACHAPOLY_TLS_TAG_LEN - 1, SHORT_AEAD_RECORD_CHACHA },
254 };
255 #endif
256 
257 static void alert_cb(int write_p, int version, int content_type,
258     const void *buf, size_t len, SSL *ssl, void *arg)
259 {
260     unsigned char *alert = arg;
261     const unsigned char *alert_data = buf;
262 
263     if (write_p && content_type == SSL3_RT_ALERT && len == 2) {
264         alert[0] = alert_data[0];
265         alert[1] = alert_data[1];
266     }
267 }
268 
269 #ifndef OPENSSL_NO_TLS1_2
270 static int test_tls12_short_aead_record(int idx)
271 {
272     const SHORT_AEAD_RECORD_TEST *test = &short_aead_record_tests[idx];
273     SSL_CTX *cctx = NULL, *sctx = NULL;
274     SSL *clientssl = NULL, *serverssl = NULL;
275     int testresult = 0;
276     size_t readbytes;
277     unsigned char buf, alert[2] = { 0 };
278 
279 #ifdef OPENSSL_NO_AES
280     if (test->cipher_type == SHORT_AEAD_RECORD_AES)
281         return TEST_skip("AES is disabled");
282 #endif
283 #ifdef OPENSSL_NO_ARIA
284     if (test->cipher_type == SHORT_AEAD_RECORD_ARIA)
285         return TEST_skip("ARIA is disabled");
286 #endif
287 #if defined(OPENSSL_NO_CHACHA) || defined(OPENSSL_NO_POLY1305) \
288     || defined(OPENSSL_NO_EC)
289     if (test->cipher_type == SHORT_AEAD_RECORD_CHACHA)
290         return TEST_skip("ChaCha20-Poly1305 or EC is disabled");
291 #endif
292 
293     if (!TEST_true(create_ssl_ctx_pair(NULL, TLS_server_method(),
294             TLS_client_method(), TLS1_2_VERSION, TLS1_2_VERSION,
295             &sctx, &cctx, cert, privkey)))
296         goto end;
297 
298     /* CCM-8 is not available at the default security level. */
299     SSL_CTX_set_security_level(sctx, 0);
300     SSL_CTX_set_security_level(cctx, 0);
301 
302     if (!TEST_true(SSL_CTX_set_cipher_list(sctx, test->cipher))
303         || !TEST_true(SSL_CTX_set_cipher_list(cctx, test->cipher))
304         || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
305             NULL, NULL)))
306         goto end;
307 
308     SSL_set_msg_callback(serverssl, alert_cb);
309     SSL_set_msg_callback_arg(serverssl, &alert);
310 
311     if (!TEST_true(create_ssl_connection(serverssl, clientssl,
312             SSL_ERROR_NONE))
313         || !TEST_true(write_and_read_app_data(serverssl, clientssl))
314         || !TEST_true(write_record(SSL_get_rbio(serverssl), test->record_len,
315             SSL3_RT_APPLICATION_DATA, TLS1_2_VERSION))
316         || !TEST_false(SSL_read_ex(serverssl, &buf, sizeof(buf), &readbytes))
317         || !TEST_uchar_eq(alert[0], SSL3_AL_FATAL)
318         || !TEST_uchar_eq(alert[1], SSL_AD_BAD_RECORD_MAC))
319         goto end;
320 
321     testresult = 1;
322 end:
323     SSL_free(serverssl);
324     SSL_free(clientssl);
325     SSL_CTX_free(sctx);
326     SSL_CTX_free(cctx);
327     return testresult;
328 }
329 #endif
330 
331 #ifndef OPENSSL_NO_DTLS1_2
332 static int test_dtls12_short_aead_record(void)
333 {
334     SSL_CTX *cctx = NULL, *sctx = NULL;
335     SSL *clientssl = NULL, *serverssl = NULL;
336     int testresult = 0, ret;
337     size_t readbytes = 0;
338     unsigned char buf = 0, alert[2] = { 0 };
339 
340 #ifdef OPENSSL_NO_AES
341     return TEST_skip("AES is disabled");
342 #endif
343 
344     if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(),
345             DTLS_client_method(), DTLS1_2_VERSION, DTLS1_2_VERSION,
346             &sctx, &cctx, cert, privkey)))
347         goto end;
348 
349     SSL_CTX_set_security_level(sctx, 0);
350     SSL_CTX_set_security_level(cctx, 0);
351 
352     if (!TEST_true(SSL_CTX_set_cipher_list(sctx,
353             TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256))
354         || !TEST_true(SSL_CTX_set_cipher_list(cctx,
355             TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256))
356         || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
357             NULL, NULL)))
358         goto end;
359 
360     SSL_set_msg_callback(serverssl, alert_cb);
361     SSL_set_msg_callback_arg(serverssl, &alert);
362 
363     /*
364      * The forged record uses the first application-data sequence number. A
365      * valid client write after this must still be accepted.
366      */
367     if (!TEST_true(create_ssl_connection(serverssl, clientssl,
368             SSL_ERROR_NONE))
369         || !TEST_true(write_dtls_record(SSL_get_rbio(serverssl),
370             EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN - 1,
371             SSL3_RT_APPLICATION_DATA, DTLS1_2_VERSION, 1, 1)))
372         goto end;
373 
374     ERR_clear_error();
375     ret = SSL_read_ex(serverssl, &buf, sizeof(buf), &readbytes);
376     if (!TEST_false(ret)
377         || !TEST_int_eq(SSL_get_error(serverssl, ret), SSL_ERROR_WANT_READ)
378         || !TEST_uchar_eq(alert[0], 0)
379         || !TEST_uchar_eq(alert[1], 0)
380         || !TEST_true(write_and_read_app_data(serverssl, clientssl)))
381         goto end;
382 
383     testresult = 1;
384 end:
385     SSL_free(serverssl);
386     SSL_free(clientssl);
387     SSL_CTX_free(sctx);
388     SSL_CTX_free(cctx);
389     return testresult;
390 }
391 #endif
392 
393 OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
394 
395 int setup_tests(void)
396 {
397     if (!test_skip_common_options()) {
398         TEST_error("Error parsing test options\n");
399         return 0;
400     }
401 
402     if (!TEST_ptr(cert = test_get_argument(0))
403         || !TEST_ptr(privkey = test_get_argument(1)))
404         return 0;
405 
406     ADD_ALL_TESTS(test_record_overflow, TOTAL_RECORD_OVERFLOW_TESTS);
407 #ifndef OPENSSL_NO_TLS1_2
408     ADD_ALL_TESTS(test_tls12_short_aead_record,
409         OSSL_NELEM(short_aead_record_tests));
410 #endif
411 #ifndef OPENSSL_NO_DTLS1_2
412     ADD_TEST(test_dtls12_short_aead_record);
413 #endif
414     return 1;
415 }
416 
417 void cleanup_tests(void)
418 {
419     bio_s_mempacket_test_free();
420 }
421