|
14 | 14 |
|
15 | 15 | #include <openssl/cipher.h> |
16 | 16 | #include <openssl/aes.h> |
| 17 | +#include <openssl/rand.h> |
17 | 18 |
|
18 | 19 | #include <vector> |
19 | 20 |
|
|
23 | 24 | #include "internal.h" |
24 | 25 | #include "../../test/test_util.h" |
25 | 26 |
|
| 27 | +static constexpr size_t AESXTS_RAND_MSG_MAX_LEN = 8192; |
| 28 | + |
26 | 29 | #if defined(OPENSSL_LINUX) |
27 | 30 | #include <sys/mman.h> |
28 | 31 | #endif |
@@ -1202,7 +1205,7 @@ TEST(XTSTest, TestVectors) { |
1202 | 1205 | in_p = in.get(); |
1203 | 1206 | out_p = out.get(); |
1204 | 1207 | #endif |
1205 | | - for (bool in_place : {false, true}) { |
| 1208 | + for (bool in_place : {false, true}) { |
1206 | 1209 | SCOPED_TRACE(in_place); |
1207 | 1210 |
|
1208 | 1211 | // Test encryption. |
@@ -1240,6 +1243,106 @@ TEST(XTSTest, TestVectors) { |
1240 | 1243 | #endif |
1241 | 1244 | } |
1242 | 1245 |
|
| 1246 | +TEST(XTSTest, EncryptDecryptRand) { |
| 1247 | +#if defined(OPENSSL_LINUX) |
| 1248 | + int pagesize = sysconf(_SC_PAGE_SIZE); |
| 1249 | + ASSERT_GE(pagesize, 0); |
| 1250 | + uint8_t *in_buffer_beg = get_buffer_beg(pagesize); |
| 1251 | + uint8_t *out_buffer_beg = get_buffer_beg(pagesize); |
| 1252 | + uint8_t *in_buffer_end = in_buffer_beg + pagesize; |
| 1253 | + uint8_t *out_buffer_end = out_buffer_beg + pagesize; |
| 1254 | +#endif |
| 1255 | + |
| 1256 | + const EVP_CIPHER *cipher = EVP_aes_256_xts(); |
| 1257 | + bssl::ScopedEVP_CIPHER_CTX ctx; |
| 1258 | + std::vector<uint8_t> key(EVP_CIPHER_key_length(cipher)), iv(EVP_CIPHER_iv_length(cipher)); |
| 1259 | + |
| 1260 | + // Test AESXTS Encrypt and Decrypt with random messages of incremental lenghts |
| 1261 | + for (size_t msg_len = 16; msg_len < AESXTS_RAND_MSG_MAX_LEN; msg_len += 1) { |
| 1262 | + |
| 1263 | + std::vector<uint8_t> plaintext(msg_len); |
| 1264 | + RAND_bytes(plaintext.data(), msg_len); |
| 1265 | + |
| 1266 | + SCOPED_TRACE(plaintext.size()); |
| 1267 | + |
| 1268 | + int len = 0; |
| 1269 | + uint8_t *in_p = nullptr, *out_p = nullptr; |
| 1270 | + #if defined(OPENSSL_LINUX) |
| 1271 | + std::unique_ptr<uint8_t[]> in, out; |
| 1272 | + |
| 1273 | + for (bool beg: {false, true}) { |
| 1274 | + if (pagesize < (int)plaintext.size() && !beg) { |
| 1275 | + // For small page sizes skip page bound edge cases |
| 1276 | + in.reset(new uint8_t[plaintext.size()]); |
| 1277 | + out.reset(new uint8_t[plaintext.size()]); |
| 1278 | + in_p = in.get(); |
| 1279 | + out_p = out.get(); |
| 1280 | + } else if (pagesize < (int)plaintext.size() && beg) { |
| 1281 | + // Skip second iteration for small page sizes since it would use |
| 1282 | + // identical allocation for |in_p| and |out_p| buffers |
| 1283 | + continue; |
| 1284 | + } else { |
| 1285 | + if (!beg) { |
| 1286 | + in_p = in_buffer_end - plaintext.size(); |
| 1287 | + out_p = out_buffer_end - plaintext.size(); |
| 1288 | + } else { |
| 1289 | + in_p = in_buffer_end - pagesize; |
| 1290 | + out_p = out_buffer_end - pagesize; |
| 1291 | + } |
| 1292 | + OPENSSL_memset(in_p, 0x00, plaintext.size()); |
| 1293 | + OPENSSL_memset(out_p, 0x00, plaintext.size()); |
| 1294 | + } |
| 1295 | + #else |
| 1296 | + std::unique_ptr<uint8_t[]> in(new uint8_t[plaintext.size()]); |
| 1297 | + std::unique_ptr<uint8_t[]> out(new uint8_t[plaintext.size()]); |
| 1298 | + in_p = in.get(); |
| 1299 | + out_p = out.get(); |
| 1300 | + #endif |
| 1301 | + for (bool in_place : {false, true}) { |
| 1302 | + SCOPED_TRACE(in_place); |
| 1303 | + |
| 1304 | + // Generate random key and iv for each encryption test |
| 1305 | + RAND_bytes(key.data(), EVP_CIPHER_key_length(cipher)); |
| 1306 | + RAND_bytes(iv.data(), EVP_CIPHER_iv_length(cipher)); |
| 1307 | + |
| 1308 | + // Test encryption. |
| 1309 | + |
| 1310 | + OPENSSL_memcpy(in_p, plaintext.data(), plaintext.size()); |
| 1311 | + if (in_place) { |
| 1312 | + out_p = in_p; |
| 1313 | + } |
| 1314 | + |
| 1315 | + ctx.Reset(); |
| 1316 | + len = 0; |
| 1317 | + ASSERT_TRUE(EVP_EncryptInit_ex(ctx.get(), cipher, nullptr, key.data(), |
| 1318 | + iv.data())); |
| 1319 | + ASSERT_TRUE( |
| 1320 | + EVP_EncryptUpdate(ctx.get(), out_p, &len, in_p, plaintext.size())); |
| 1321 | + ASSERT_EQ(static_cast<size_t>(len), plaintext.size()); |
| 1322 | + |
| 1323 | + // Test decryption. |
| 1324 | + |
| 1325 | + if (!in_place) { |
| 1326 | + OPENSSL_memset(in_p, 0, len); |
| 1327 | + } |
| 1328 | + |
| 1329 | + ctx.Reset(); |
| 1330 | + len = 0; |
| 1331 | + ASSERT_TRUE(EVP_DecryptInit_ex(ctx.get(), cipher, nullptr, key.data(), |
| 1332 | + iv.data())); |
| 1333 | + ASSERT_TRUE( |
| 1334 | + EVP_DecryptUpdate(ctx.get(), in_p, &len, out_p, plaintext.size())); |
| 1335 | + ASSERT_EQ(static_cast<size_t>(len), plaintext.size()); |
| 1336 | + EXPECT_EQ(Bytes(plaintext), Bytes(in_p, static_cast<size_t>(len))); |
| 1337 | + } |
| 1338 | + } |
| 1339 | +#if defined(OPENSSL_LINUX) |
| 1340 | + } |
| 1341 | + free_memory(in_buffer_end, pagesize); |
| 1342 | + free_memory(out_buffer_end, pagesize); |
| 1343 | +#endif |
| 1344 | +} |
| 1345 | + |
1243 | 1346 | // Negative test for key1 = key2 |
1244 | 1347 | TEST(XTSTest, DuplicateKey) { |
1245 | 1348 |
|
|
0 commit comments