1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53 
54 #include <limits.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 #include <algorithm>
59 #include <string>
60 #include <vector>
61 
62 #include <gtest/gtest.h>
63 
64 #include <openssl/aes.h>
65 #include <openssl/cipher.h>
66 #include <openssl/err.h>
67 #include <openssl/nid.h>
68 #include <openssl/rand.h>
69 #include <openssl/sha.h>
70 #include <openssl/span.h>
71 
72 #include "../test/file_test.h"
73 #include "../test/test_util.h"
74 #include "../test/wycheproof_util.h"
75 #include "./internal.h"
76 
77 
GetCipher(const std::string & name)78 static const EVP_CIPHER *GetCipher(const std::string &name) {
79   if (name == "DES-CBC") {
80     return EVP_des_cbc();
81   } else if (name == "DES-ECB") {
82     return EVP_des_ecb();
83   } else if (name == "DES-EDE") {
84     return EVP_des_ede();
85   } else if (name == "DES-EDE3") {
86     return EVP_des_ede3();
87   } else if (name == "DES-EDE-CBC") {
88     return EVP_des_ede_cbc();
89   } else if (name == "DES-EDE3-CBC") {
90     return EVP_des_ede3_cbc();
91   } else if (name == "RC4") {
92     return EVP_rc4();
93   } else if (name == "AES-128-ECB") {
94     return EVP_aes_128_ecb();
95   } else if (name == "AES-256-ECB") {
96     return EVP_aes_256_ecb();
97   } else if (name == "AES-128-CBC") {
98     return EVP_aes_128_cbc();
99   } else if (name == "AES-128-GCM") {
100     return EVP_aes_128_gcm();
101   } else if (name == "AES-128-OFB") {
102     return EVP_aes_128_ofb();
103   } else if (name == "AES-192-CBC") {
104     return EVP_aes_192_cbc();
105   } else if (name == "AES-192-CTR") {
106     return EVP_aes_192_ctr();
107   } else if (name == "AES-192-ECB") {
108     return EVP_aes_192_ecb();
109   } else if (name == "AES-192-GCM") {
110     return EVP_aes_192_gcm();
111   } else if (name == "AES-192-OFB") {
112     return EVP_aes_192_ofb();
113   } else if (name == "AES-256-CBC") {
114     return EVP_aes_256_cbc();
115   } else if (name == "AES-128-CTR") {
116     return EVP_aes_128_ctr();
117   } else if (name == "AES-256-CTR") {
118     return EVP_aes_256_ctr();
119   } else if (name == "AES-256-GCM") {
120     return EVP_aes_256_gcm();
121   } else if (name == "AES-256-OFB") {
122     return EVP_aes_256_ofb();
123   }
124   return nullptr;
125 }
126 
127 enum class Operation {
128   // kBoth tests both encryption and decryption.
129   kBoth,
130   // kEncrypt tests encryption. The result of encryption should always
131   // successfully decrypt, so this should only be used if the test file has a
132   // matching decrypt-only vector.
133   kEncrypt,
134   // kDecrypt tests decryption. This should only be used if the test file has a
135   // matching encrypt-only input, or if multiple ciphertexts are valid for
136   // a given plaintext and this is a non-canonical ciphertext.
137   kDecrypt,
138   // kInvalidDecrypt tests decryption and expects it to fail, e.g. due to
139   // invalid tag or padding.
140   kInvalidDecrypt,
141 };
142 
OperationToString(Operation op)143 static const char *OperationToString(Operation op) {
144   switch (op) {
145     case Operation::kBoth:
146       return "Both";
147     case Operation::kEncrypt:
148       return "Encrypt";
149     case Operation::kDecrypt:
150       return "Decrypt";
151     case Operation::kInvalidDecrypt:
152       return "InvalidDecrypt";
153   }
154   abort();
155 }
156 
157 // MaybeCopyCipherContext, if |copy| is true, replaces |*ctx| with a, hopefully
158 // equivalent, copy of it.
MaybeCopyCipherContext(bool copy,bssl::UniquePtr<EVP_CIPHER_CTX> * ctx)159 static bool MaybeCopyCipherContext(bool copy,
160                                    bssl::UniquePtr<EVP_CIPHER_CTX> *ctx) {
161   if (!copy) {
162     return true;
163   }
164   bssl::UniquePtr<EVP_CIPHER_CTX> ctx2(EVP_CIPHER_CTX_new());
165   if (!ctx2 || !EVP_CIPHER_CTX_copy(ctx2.get(), ctx->get())) {
166     return false;
167   }
168   *ctx = std::move(ctx2);
169   return true;
170 }
171 
TestCipherAPI(const EVP_CIPHER * cipher,Operation op,bool padding,bool copy,bool in_place,bool use_evp_cipher,size_t chunk_size,bssl::Span<const uint8_t> key,bssl::Span<const uint8_t> iv,bssl::Span<const uint8_t> plaintext,bssl::Span<const uint8_t> ciphertext,bssl::Span<const uint8_t> aad,bssl::Span<const uint8_t> tag)172 static void TestCipherAPI(const EVP_CIPHER *cipher, Operation op, bool padding,
173                           bool copy, bool in_place, bool use_evp_cipher,
174                           size_t chunk_size, bssl::Span<const uint8_t> key,
175                           bssl::Span<const uint8_t> iv,
176                           bssl::Span<const uint8_t> plaintext,
177                           bssl::Span<const uint8_t> ciphertext,
178                           bssl::Span<const uint8_t> aad,
179                           bssl::Span<const uint8_t> tag) {
180   bool encrypt = op == Operation::kEncrypt;
181   bool is_custom_cipher =
182       EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_CUSTOM_CIPHER;
183   bssl::Span<const uint8_t> in = encrypt ? plaintext : ciphertext;
184   bssl::Span<const uint8_t> expected = encrypt ? ciphertext : plaintext;
185   bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
186 
187   // Some |EVP_CIPHER|s take a variable-length key, and need to first be
188   // configured with the key length, which requires configuring the cipher.
189   bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
190   ASSERT_TRUE(ctx);
191   ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, /*engine=*/nullptr,
192                                 /*key=*/nullptr, /*iv=*/nullptr,
193                                 encrypt ? 1 : 0));
194   ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()));
195   if (!padding) {
196     ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0));
197   }
198 
199   // Configure the key.
200   ASSERT_TRUE(MaybeCopyCipherContext(copy, &ctx));
201   ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), /*cipher=*/nullptr,
202                                 /*engine=*/nullptr, key.data(), /*iv=*/nullptr,
203                                 /*enc=*/-1));
204 
205   // Configure the IV to run the actual operation. Callers that wish to use a
206   // key for multiple, potentially concurrent, operations will likely copy at
207   // this point. The |EVP_CIPHER_CTX| API uses the same type to represent a
208   // pre-computed key schedule and a streaming operation.
209   ASSERT_TRUE(MaybeCopyCipherContext(copy, &ctx));
210   if (is_aead) {
211     ASSERT_LE(iv.size(), size_t{INT_MAX});
212     ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_IVLEN,
213                                     static_cast<int>(iv.size()), 0));
214   } else {
215     ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get()));
216   }
217   ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), /*cipher=*/nullptr,
218                                 /*engine=*/nullptr,
219                                 /*key=*/nullptr, iv.data(), /*enc=*/-1));
220 
221   if (is_aead && !encrypt) {
222     ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_TAG,
223                                     tag.size(),
224                                     const_cast<uint8_t *>(tag.data())));
225   }
226 
227   // Note: the deprecated |EVP_CIPHER|-based AEAD API is sensitive to whether
228   // parameters are NULL, so it is important to skip the |in| and |aad|
229   // |EVP_CipherUpdate| calls when empty.
230   while (!aad.empty()) {
231     size_t todo =
232         chunk_size == 0 ? aad.size() : std::min(aad.size(), chunk_size);
233     if (use_evp_cipher) {
234       // AEADs always use the "custom cipher" return value convention. Passing a
235       // null output pointer triggers the AAD logic.
236       ASSERT_TRUE(is_custom_cipher);
237       ASSERT_EQ(static_cast<int>(todo),
238                 EVP_Cipher(ctx.get(), nullptr, aad.data(), todo));
239     } else {
240       int len;
241       ASSERT_TRUE(EVP_CipherUpdate(ctx.get(), nullptr, &len, aad.data(), todo));
242       // Although it doesn't output anything, |EVP_CipherUpdate| should claim to
243       // output the input length.
244       EXPECT_EQ(len, static_cast<int>(todo));
245     }
246     aad = aad.subspan(todo);
247   }
248 
249   // Set up the output buffer.
250   size_t max_out = in.size();
251   size_t block_size = EVP_CIPHER_CTX_block_size(ctx.get());
252   if (block_size > 1 &&
253       (EVP_CIPHER_CTX_flags(ctx.get()) & EVP_CIPH_NO_PADDING) == 0 &&
254       EVP_CIPHER_CTX_encrypting(ctx.get())) {
255     max_out += block_size - (max_out % block_size);
256   }
257   std::vector<uint8_t> result(max_out);
258   if (in_place) {
259     std::copy(in.begin(), in.end(), result.begin());
260     in = bssl::MakeConstSpan(result).first(in.size());
261   }
262 
263   size_t total = 0;
264   int len;
265   while (!in.empty()) {
266     size_t todo = chunk_size == 0 ? in.size() : std::min(in.size(), chunk_size);
267     EXPECT_LE(todo, static_cast<size_t>(INT_MAX));
268     ASSERT_TRUE(MaybeCopyCipherContext(copy, &ctx));
269     if (use_evp_cipher) {
270       // |EVP_Cipher| sometimes returns the number of bytes written, or -1 on
271       // error, and sometimes 1 or 0, implicitly writing |in_len| bytes.
272       if (is_custom_cipher) {
273         len = EVP_Cipher(ctx.get(), result.data() + total, in.data(), todo);
274       } else {
275         ASSERT_EQ(
276             1, EVP_Cipher(ctx.get(), result.data() + total, in.data(), todo));
277         len = static_cast<int>(todo);
278       }
279     } else {
280       ASSERT_TRUE(EVP_CipherUpdate(ctx.get(), result.data() + total, &len,
281                                    in.data(), static_cast<int>(todo)));
282     }
283     ASSERT_GE(len, 0);
284     total += static_cast<size_t>(len);
285     in = in.subspan(todo);
286   }
287   if (op == Operation::kInvalidDecrypt) {
288     if (use_evp_cipher) {
289       // Only the "custom cipher" return value convention can report failures.
290       // Passing all nulls should act like |EVP_CipherFinal_ex|.
291       ASSERT_TRUE(is_custom_cipher);
292       EXPECT_EQ(-1, EVP_Cipher(ctx.get(), nullptr, nullptr, 0));
293     } else {
294       // Invalid padding and invalid tags all appear as a failed
295       // |EVP_CipherFinal_ex|.
296       EXPECT_FALSE(EVP_CipherFinal_ex(ctx.get(), result.data() + total, &len));
297     }
298   } else {
299     if (use_evp_cipher) {
300       if (is_custom_cipher) {
301         // Only the "custom cipher" convention has an |EVP_CipherFinal_ex|
302         // equivalent.
303         len = EVP_Cipher(ctx.get(), nullptr, nullptr, 0);
304       } else {
305         len = 0;
306       }
307     } else {
308       ASSERT_TRUE(EVP_CipherFinal_ex(ctx.get(), result.data() + total, &len));
309     }
310     ASSERT_GE(len, 0);
311     total += static_cast<size_t>(len);
312     result.resize(total);
313     EXPECT_EQ(Bytes(expected), Bytes(result));
314     if (encrypt && is_aead) {
315       uint8_t rtag[16];
316       ASSERT_LE(tag.size(), sizeof(rtag));
317       ASSERT_TRUE(MaybeCopyCipherContext(copy, &ctx));
318       ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG,
319                                       tag.size(), rtag));
320       EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size()));
321     }
322   }
323 }
324 
TestLowLevelAPI(const EVP_CIPHER * cipher,Operation op,bool in_place,size_t chunk_size,bssl::Span<const uint8_t> key,bssl::Span<const uint8_t> iv,bssl::Span<const uint8_t> plaintext,bssl::Span<const uint8_t> ciphertext)325 static void TestLowLevelAPI(
326     const EVP_CIPHER *cipher, Operation op, bool in_place, size_t chunk_size,
327     bssl::Span<const uint8_t> key, bssl::Span<const uint8_t> iv,
328     bssl::Span<const uint8_t> plaintext, bssl::Span<const uint8_t> ciphertext) {
329   bool encrypt = op == Operation::kEncrypt;
330   bssl::Span<const uint8_t> in = encrypt ? plaintext : ciphertext;
331   bssl::Span<const uint8_t> expected = encrypt ? ciphertext : plaintext;
332   int nid = EVP_CIPHER_nid(cipher);
333   bool is_ctr = nid == NID_aes_128_ctr || nid == NID_aes_192_ctr ||
334                 nid == NID_aes_256_ctr;
335   bool is_cbc = nid == NID_aes_128_cbc || nid == NID_aes_192_cbc ||
336                 nid == NID_aes_256_cbc;
337   bool is_ofb = nid == NID_aes_128_ofb128 || nid == NID_aes_192_ofb128 ||
338                 nid == NID_aes_256_ofb128;
339   if (!is_ctr && !is_cbc && !is_ofb) {
340     return;
341   }
342 
343   // Invalid ciphertexts are not possible in any of the ciphers where this API
344   // applies.
345   ASSERT_NE(op, Operation::kInvalidDecrypt);
346 
347   AES_KEY aes;
348   if (encrypt || !is_cbc) {
349     ASSERT_EQ(0, AES_set_encrypt_key(key.data(), key.size() * 8, &aes));
350   } else {
351     ASSERT_EQ(0, AES_set_decrypt_key(key.data(), key.size() * 8, &aes));
352   }
353 
354   std::vector<uint8_t> result;
355   if (in_place) {
356     result.assign(in.begin(), in.end());
357   } else {
358     result.resize(expected.size());
359   }
360   bssl::Span<uint8_t> out = bssl::MakeSpan(result);
361   // Input and output sizes for all the low-level APIs should match.
362   ASSERT_EQ(in.size(), out.size());
363 
364   // The low-level APIs all use block-size IVs.
365   ASSERT_EQ(iv.size(), size_t{AES_BLOCK_SIZE});
366   uint8_t ivec[AES_BLOCK_SIZE];
367   OPENSSL_memcpy(ivec, iv.data(), iv.size());
368 
369   if (is_ctr) {
370     unsigned num = 0;
371     uint8_t ecount_buf[AES_BLOCK_SIZE];
372     if (chunk_size == 0) {
373       AES_ctr128_encrypt(in.data(), out.data(), in.size(), &aes, ivec,
374                          ecount_buf, &num);
375     } else {
376       do {
377         size_t todo = std::min(in.size(), chunk_size);
378         AES_ctr128_encrypt(in.data(), out.data(), todo, &aes, ivec, ecount_buf,
379                            &num);
380         in = in.subspan(todo);
381         out = out.subspan(todo);
382       } while (!in.empty());
383     }
384     EXPECT_EQ(Bytes(expected), Bytes(result));
385   } else if (is_cbc && chunk_size % AES_BLOCK_SIZE == 0) {
386     // Note |AES_cbc_encrypt| requires block-aligned chunks.
387     if (chunk_size == 0) {
388       AES_cbc_encrypt(in.data(), out.data(), in.size(), &aes, ivec, encrypt);
389     } else {
390       do {
391         size_t todo = std::min(in.size(), chunk_size);
392         AES_cbc_encrypt(in.data(), out.data(), todo, &aes, ivec, encrypt);
393         in = in.subspan(todo);
394         out = out.subspan(todo);
395       } while (!in.empty());
396     }
397     EXPECT_EQ(Bytes(expected), Bytes(result));
398   } else if (is_ofb) {
399     int num = 0;
400     if (chunk_size == 0) {
401       AES_ofb128_encrypt(in.data(), out.data(), in.size(), &aes, ivec, &num);
402     } else {
403       do {
404         size_t todo = std::min(in.size(), chunk_size);
405         AES_ofb128_encrypt(in.data(), out.data(), todo, &aes, ivec, &num);
406         in = in.subspan(todo);
407         out = out.subspan(todo);
408       } while (!in.empty());
409     }
410     EXPECT_EQ(Bytes(expected), Bytes(result));
411   }
412 }
413 
TestCipher(const EVP_CIPHER * cipher,Operation input_op,bool padding,bssl::Span<const uint8_t> key,bssl::Span<const uint8_t> iv,bssl::Span<const uint8_t> plaintext,bssl::Span<const uint8_t> ciphertext,bssl::Span<const uint8_t> aad,bssl::Span<const uint8_t> tag)414 static void TestCipher(const EVP_CIPHER *cipher, Operation input_op,
415                        bool padding, bssl::Span<const uint8_t> key,
416                        bssl::Span<const uint8_t> iv,
417                        bssl::Span<const uint8_t> plaintext,
418                        bssl::Span<const uint8_t> ciphertext,
419                        bssl::Span<const uint8_t> aad,
420                        bssl::Span<const uint8_t> tag) {
421   size_t block_size = EVP_CIPHER_block_size(cipher);
422   std::vector<Operation> ops;
423   if (input_op == Operation::kBoth) {
424     ops = {Operation::kEncrypt, Operation::kDecrypt};
425   } else {
426     ops = {input_op};
427   }
428   for (Operation op : ops) {
429     SCOPED_TRACE(OperationToString(op));
430     // Zero indicates a single-shot API.
431     static const size_t kChunkSizes[] = {0,  1,  2,  5,  7,  8,  9,  15, 16,
432                                          17, 31, 32, 33, 63, 64, 65, 512};
433     for (size_t chunk_size : kChunkSizes) {
434       SCOPED_TRACE(chunk_size);
435       if (chunk_size > plaintext.size() && chunk_size > ciphertext.size() &&
436           chunk_size > aad.size()) {
437         continue;
438       }
439       for (bool in_place : {false, true}) {
440         SCOPED_TRACE(in_place);
441         for (bool copy : {false, true}) {
442           SCOPED_TRACE(copy);
443           TestCipherAPI(cipher, op, padding, copy, in_place,
444                         /*use_evp_cipher=*/false, chunk_size, key, iv,
445                         plaintext, ciphertext, aad, tag);
446           if (!padding && chunk_size % block_size == 0) {
447             TestCipherAPI(cipher, op, padding, copy, in_place,
448                           /*use_evp_cipher=*/true, chunk_size, key, iv,
449                           plaintext, ciphertext, aad, tag);
450           }
451         }
452         if (!padding) {
453           TestLowLevelAPI(cipher, op, in_place, chunk_size, key, iv, plaintext,
454                           ciphertext);
455         }
456       }
457     }
458   }
459 }
460 
CipherFileTest(FileTest * t)461 static void CipherFileTest(FileTest *t) {
462   std::string cipher_str;
463   ASSERT_TRUE(t->GetAttribute(&cipher_str, "Cipher"));
464   const EVP_CIPHER *cipher = GetCipher(cipher_str);
465   ASSERT_TRUE(cipher);
466 
467   std::vector<uint8_t> key, iv, plaintext, ciphertext, aad, tag;
468   ASSERT_TRUE(t->GetBytes(&key, "Key"));
469   ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
470   ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
471   if (EVP_CIPHER_iv_length(cipher) > 0) {
472     ASSERT_TRUE(t->GetBytes(&iv, "IV"));
473   }
474   if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) {
475     ASSERT_TRUE(t->GetBytes(&aad, "AAD"));
476     ASSERT_TRUE(t->GetBytes(&tag, "Tag"));
477   }
478 
479   Operation op = Operation::kBoth;
480   if (t->HasAttribute("Operation")) {
481     const std::string &str = t->GetAttributeOrDie("Operation");
482     if (str == "Encrypt" || str == "ENCRYPT") {
483       op = Operation::kEncrypt;
484     } else if (str == "Decrypt" || str == "DECRYPT") {
485       op = Operation::kDecrypt;
486     } else if (str == "InvalidDecrypt") {
487       op = Operation::kInvalidDecrypt;
488     } else {
489       FAIL() << "Unknown operation: " << str;
490     }
491   }
492 
493   TestCipher(cipher, op, /*padding=*/false, key, iv, plaintext, ciphertext, aad,
494              tag);
495 }
496 
TEST(CipherTest,TestVectors)497 TEST(CipherTest, TestVectors) {
498   FileTestGTest("crypto/cipher_extra/test/cipher_tests.txt", CipherFileTest);
499 }
500 
TEST(CipherTest,CAVP_AES_128_CBC)501 TEST(CipherTest, CAVP_AES_128_CBC) {
502   FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt",
503                 CipherFileTest);
504 }
505 
TEST(CipherTest,CAVP_AES_128_CTR)506 TEST(CipherTest, CAVP_AES_128_CTR) {
507   FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt",
508                 CipherFileTest);
509 }
510 
TEST(CipherTest,CAVP_AES_192_CBC)511 TEST(CipherTest, CAVP_AES_192_CBC) {
512   FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt",
513                 CipherFileTest);
514 }
515 
TEST(CipherTest,CAVP_AES_192_CTR)516 TEST(CipherTest, CAVP_AES_192_CTR) {
517   FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt",
518                 CipherFileTest);
519 }
520 
TEST(CipherTest,CAVP_AES_256_CBC)521 TEST(CipherTest, CAVP_AES_256_CBC) {
522   FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt",
523                 CipherFileTest);
524 }
525 
TEST(CipherTest,CAVP_AES_256_CTR)526 TEST(CipherTest, CAVP_AES_256_CTR) {
527   FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt",
528                 CipherFileTest);
529 }
530 
TEST(CipherTest,CAVP_TDES_CBC)531 TEST(CipherTest, CAVP_TDES_CBC) {
532   FileTestGTest("crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt",
533                 CipherFileTest);
534 }
535 
TEST(CipherTest,CAVP_TDES_ECB)536 TEST(CipherTest, CAVP_TDES_ECB) {
537   FileTestGTest("crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt",
538                 CipherFileTest);
539 }
540 
TEST(CipherTest,WycheproofAESCBC)541 TEST(CipherTest, WycheproofAESCBC) {
542   FileTestGTest("third_party/wycheproof_testvectors/aes_cbc_pkcs5_test.txt",
543                 [](FileTest *t) {
544                   t->IgnoreInstruction("type");
545                   t->IgnoreInstruction("ivSize");
546 
547                   std::string key_size;
548                   ASSERT_TRUE(t->GetInstruction(&key_size, "keySize"));
549                   const EVP_CIPHER *cipher;
550                   switch (atoi(key_size.c_str())) {
551                     case 128:
552                       cipher = EVP_aes_128_cbc();
553                       break;
554                     case 192:
555                       cipher = EVP_aes_192_cbc();
556                       break;
557                     case 256:
558                       cipher = EVP_aes_256_cbc();
559                       break;
560                     default:
561                       FAIL() << "Unsupported key size: " << key_size;
562                   }
563 
564                   std::vector<uint8_t> key, iv, msg, ct;
565                   ASSERT_TRUE(t->GetBytes(&key, "key"));
566                   ASSERT_TRUE(t->GetBytes(&iv, "iv"));
567                   ASSERT_TRUE(t->GetBytes(&msg, "msg"));
568                   ASSERT_TRUE(t->GetBytes(&ct, "ct"));
569                   WycheproofResult result;
570                   ASSERT_TRUE(GetWycheproofResult(t, &result));
571                   TestCipher(cipher,
572                              result.IsValid() ? Operation::kBoth
573                                               : Operation::kInvalidDecrypt,
574                              /*padding=*/true, key, iv, msg, ct, /*aad=*/{},
575                              /*tag=*/{});
576                 });
577 }
578 
TEST(CipherTest,SHA1WithSecretSuffix)579 TEST(CipherTest, SHA1WithSecretSuffix) {
580   uint8_t buf[SHA_CBLOCK * 4];
581   RAND_bytes(buf, sizeof(buf));
582   // Hashing should run in time independent of the bytes.
583   CONSTTIME_SECRET(buf, sizeof(buf));
584 
585   // Exhaustively testing interesting cases in this function is cubic in the
586   // block size, so we test in 3-byte increments.
587   constexpr size_t kSkip = 3;
588   // This value should be less than 8 to test the edge case when the 8-byte
589   // length wraps to the next block.
590   static_assert(kSkip < 8, "kSkip is too large");
591 
592   // |EVP_sha1_final_with_secret_suffix| is sensitive to the public length of
593   // the partial block previously hashed. In TLS, this is the HMAC prefix, the
594   // header, and the public minimum padding length.
595   for (size_t prefix = 0; prefix < SHA_CBLOCK; prefix += kSkip) {
596     SCOPED_TRACE(prefix);
597     // The first block is treated differently, so we run with up to three
598     // blocks of length variability.
599     for (size_t max_len = 0; max_len < 3 * SHA_CBLOCK; max_len += kSkip) {
600       SCOPED_TRACE(max_len);
601       for (size_t len = 0; len <= max_len; len += kSkip) {
602         SCOPED_TRACE(len);
603 
604         uint8_t expected[SHA_DIGEST_LENGTH];
605         SHA1(buf, prefix + len, expected);
606         CONSTTIME_DECLASSIFY(expected, sizeof(expected));
607 
608         // Make a copy of the secret length to avoid interfering with the loop.
609         size_t secret_len = len;
610         CONSTTIME_SECRET(&secret_len, sizeof(secret_len));
611 
612         SHA_CTX ctx;
613         SHA1_Init(&ctx);
614         SHA1_Update(&ctx, buf, prefix);
615         uint8_t computed[SHA_DIGEST_LENGTH];
616         ASSERT_TRUE(EVP_sha1_final_with_secret_suffix(
617             &ctx, computed, buf + prefix, secret_len, max_len));
618 
619         CONSTTIME_DECLASSIFY(computed, sizeof(computed));
620         EXPECT_EQ(Bytes(expected), Bytes(computed));
621       }
622     }
623   }
624 }
625 
TEST(CipherTest,GetCipher)626 TEST(CipherTest, GetCipher) {
627   const EVP_CIPHER *cipher = EVP_get_cipherbynid(NID_aes_128_gcm);
628   ASSERT_TRUE(cipher);
629   EXPECT_EQ(NID_aes_128_gcm, EVP_CIPHER_nid(cipher));
630 
631   cipher = EVP_get_cipherbyname("aes-128-gcm");
632   ASSERT_TRUE(cipher);
633   EXPECT_EQ(NID_aes_128_gcm, EVP_CIPHER_nid(cipher));
634 
635   cipher = EVP_get_cipherbyname("AES-128-GCM");
636   ASSERT_TRUE(cipher);
637   EXPECT_EQ(NID_aes_128_gcm, EVP_CIPHER_nid(cipher));
638 
639   // We support a tcpdump-specific alias for 3DES.
640   cipher = EVP_get_cipherbyname("3des");
641   ASSERT_TRUE(cipher);
642   EXPECT_EQ(NID_des_ede3_cbc, EVP_CIPHER_nid(cipher));
643 }
644