blob: 048093fa913c728c9a6eb43fddc41dfc0a52f1fa [file] [log] [blame]
Gilles Peskinea3237ef2023-09-18 14:23:13 +02001/* BEGIN_HEADER */
2/* Testing of mbedtls_ssl_decrypt_buf() specifically, focusing on negative
3 * testing (using malformed inputs). */
4
5#include <mbedtls/ssl.h>
6#include <ssl_misc.h>
7#include <test/ssl_helpers.h>
8
9/* END_HEADER */
10
11/* BEGIN_DEPENDENCIES
12 * depends_on:MBEDTLS_SSL_TLS_C
13 * END_DEPENDENCIES
14 */
15
16/* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2 */
17void ssl_decrypt_non_etm_cbc(int cipher_type, int hash_id, int trunc_hmac,
18 int length_selector)
19{
20 /*
21 * Test record decryption for CBC without EtM, focused on the verification
22 * of padding and MAC.
23 *
24 * Actually depends on TLS 1.2 and either AES, ARIA or Camellia, but since
25 * the test framework doesn't support alternation in dependency statements,
26 * just depend on AES.
27 *
28 * The length_selector argument is interpreted as follows:
29 * - if it's -1, the plaintext length is 0 and minimal padding is applied
30 * - if it's -2, the plaintext length is 0 and maximal padding is applied
31 * - otherwise it must be in [0, 255] and is padding_length from RFC 5246:
32 * it's the length of the rest of the padding, that is, excluding the
33 * byte that encodes the length. The minimal non-zero plaintext length
34 * that gives this padding_length is automatically selected.
35 */
36 mbedtls_ssl_context ssl; /* ONLY for debugging */
37 mbedtls_ssl_transform t0, t1;
38 mbedtls_record rec, rec_save;
39 unsigned char *buf = NULL, *buf_save = NULL;
40 size_t buflen, olen = 0;
41 size_t plaintext_len, block_size, i;
42 unsigned char padlen; /* excluding the padding_length byte */
Gilles Peskinea3237ef2023-09-18 14:23:13 +020043 int exp_ret;
44 int ret;
45 const unsigned char pad_max_len = 255; /* Per the standard */
46
47 mbedtls_ssl_init(&ssl);
48 mbedtls_ssl_transform_init(&t0);
49 mbedtls_ssl_transform_init(&t1);
50 MD_OR_USE_PSA_INIT();
51
52 /* Set up transforms with dummy keys */
53 ret = mbedtls_test_ssl_build_transforms(&t0, &t1, cipher_type, hash_id,
54 0, trunc_hmac,
55 MBEDTLS_SSL_VERSION_TLS1_2,
56 0, 0);
57
58 TEST_ASSERT(ret == 0);
59
60 /* Determine padding/plaintext length */
61 TEST_ASSERT(length_selector >= -2 && length_selector <= 255);
62 block_size = t0.ivlen;
63 if (length_selector < 0) {
64 plaintext_len = 0;
65
66 /* Minimal padding
67 * The +1 is for the padding_length byte, not counted in padlen. */
68 padlen = block_size - (t0.maclen + 1) % block_size;
69
70 /* Maximal padding? */
71 if (length_selector == -2) {
72 padlen += block_size * ((pad_max_len - padlen) / block_size);
73 }
74 } else {
75 padlen = length_selector;
76
77 /* Minimal non-zero plaintext_length giving desired padding.
78 * The +1 is for the padding_length byte, not counted in padlen. */
79 plaintext_len = block_size - (padlen + t0.maclen + 1) % block_size;
80 }
81
82 /* Prepare a buffer for record data */
83 buflen = block_size
84 + plaintext_len
85 + t0.maclen
86 + padlen + 1;
87 TEST_CALLOC(buf, buflen);
88 TEST_CALLOC(buf_save, buflen);
89
90 /* Prepare a dummy record header */
91 memset(rec.ctr, 0, sizeof(rec.ctr));
92 rec.type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
93 mbedtls_ssl_write_version(rec.ver, MBEDTLS_SSL_TRANSPORT_STREAM,
94 MBEDTLS_SSL_VERSION_TLS1_2);
95#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
96 rec.cid_len = 0;
97#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
98
99 /* Prepare dummy record content */
100 rec.buf = buf;
101 rec.buf_len = buflen;
102 rec.data_offset = block_size;
103 rec.data_len = plaintext_len;
104 memset(rec.buf + rec.data_offset, 42, rec.data_len);
105
Gilles Peskinea3237ef2023-09-18 14:23:13 +0200106 /* Set dummy IV */
107 memset(t0.iv_enc, 0x55, t0.ivlen);
108 memcpy(rec.buf, t0.iv_enc, t0.ivlen);
109
110 /*
111 * Prepare a pre-encryption record (with MAC and padding), and save it.
112 */
Gilles Peskine9099d3f2023-09-18 13:11:50 +0200113 TEST_EQUAL(0, mbedtls_test_ssl_prepare_record_mac(&rec, &t0));
Gilles Peskinea3237ef2023-09-18 14:23:13 +0200114
115 /* Pad */
116 memset(rec.buf + rec.data_offset + rec.data_len, padlen, padlen + 1);
117 rec.data_len += padlen + 1;
118
119 /* Save correct pre-encryption record */
120 rec_save = rec;
121 rec_save.buf = buf_save;
122 memcpy(buf_save, buf, buflen);
123
124 /*
125 * Encrypt and decrypt the correct record, expecting success
126 */
127 TEST_EQUAL(0, mbedtls_test_psa_cipher_encrypt_helper(
128 &t0, t0.iv_enc, t0.ivlen, rec.buf + rec.data_offset,
129 rec.data_len, rec.buf + rec.data_offset, &olen));
130 rec.data_offset -= t0.ivlen;
131 rec.data_len += t0.ivlen;
132
133 TEST_EQUAL(0, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
134
135 /*
136 * Modify each byte of the pre-encryption record before encrypting and
137 * decrypting it, expecting failure every time.
138 */
139 for (i = block_size; i < buflen; i++) {
140 mbedtls_test_set_step(i);
141
142 /* Restore correct pre-encryption record */
143 rec = rec_save;
144 rec.buf = buf;
145 memcpy(buf, buf_save, buflen);
146
147 /* Corrupt one byte of the data (could be plaintext, MAC or padding) */
148 rec.buf[i] ^= 0x01;
149
150 /* Encrypt */
151 TEST_EQUAL(0, mbedtls_test_psa_cipher_encrypt_helper(
152 &t0, t0.iv_enc, t0.ivlen, rec.buf + rec.data_offset,
153 rec.data_len, rec.buf + rec.data_offset, &olen));
154 rec.data_offset -= t0.ivlen;
155 rec.data_len += t0.ivlen;
156
157 /* Decrypt and expect failure */
158 TEST_EQUAL(MBEDTLS_ERR_SSL_INVALID_MAC,
159 mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
160 }
161
162 /*
163 * Use larger values of the padding bytes - with small buffers, this tests
164 * the case where the announced padlen would be larger than the buffer
165 * (and before that, than the buffer minus the size of the MAC), to make
166 * sure our padding checking code does not perform any out-of-bounds reads
167 * in this case. (With larger buffers, ie when the plaintext is long or
168 * maximal length padding is used, this is less relevant but still doesn't
169 * hurt to test.)
170 *
171 * (Start the loop with correct padding, just to double-check that record
172 * saving did work, and that we're overwriting the correct bytes.)
173 */
174 for (i = padlen; i <= pad_max_len; i++) {
175 mbedtls_test_set_step(i);
176
177 /* Restore correct pre-encryption record */
178 rec = rec_save;
179 rec.buf = buf;
180 memcpy(buf, buf_save, buflen);
181
182 /* Set padding bytes to new value */
183 memset(buf + buflen - padlen - 1, i, padlen + 1);
184
185 /* Encrypt */
186 TEST_EQUAL(0, mbedtls_test_psa_cipher_encrypt_helper(
187 &t0, t0.iv_enc, t0.ivlen, rec.buf + rec.data_offset,
188 rec.data_len, rec.buf + rec.data_offset, &olen));
189 rec.data_offset -= t0.ivlen;
190 rec.data_len += t0.ivlen;
191
192 /* Decrypt and expect failure except the first time */
193 exp_ret = (i == padlen) ? 0 : MBEDTLS_ERR_SSL_INVALID_MAC;
194 TEST_EQUAL(exp_ret, mbedtls_ssl_decrypt_buf(&ssl, &t1, &rec));
195 }
196
197exit:
Gilles Peskinea3237ef2023-09-18 14:23:13 +0200198 mbedtls_ssl_free(&ssl);
199 mbedtls_ssl_transform_free(&t0);
200 mbedtls_ssl_transform_free(&t1);
201 mbedtls_free(buf);
202 mbedtls_free(buf_save);
203 MD_OR_USE_PSA_DONE();
204}
205/* END_CASE */