Add AES-192-GCM support to EVP_AEAD.

(But don't use it for anything new; interop only.)

Change-Id: I59dfb0d3fd4745b5f8d75aa38f7846431d3348c3
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/37444
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/cipher_extra/aead_test.cc b/crypto/cipher_extra/aead_test.cc
index 25924bd..c363750 100644
--- a/crypto/cipher_extra/aead_test.cc
+++ b/crypto/cipher_extra/aead_test.cc
@@ -53,6 +53,8 @@
      true, 0},
     {"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
      false, true, true, 0},
+    {"AES_192_GCM", EVP_aead_aes_192_gcm, "aes_192_gcm_tests.txt", false, true,
+     true, 0},
     {"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true,
      true, 0},
     {"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
@@ -801,9 +803,8 @@
         aead = EVP_aead_aes_128_gcm();
         break;
       case 192:
-        // Skip AES-192-GCM tests.
-        t->SkipCurrent();
-        return;
+        aead = EVP_aead_aes_192_gcm();
+        break;
       case 256:
         aead = EVP_aead_aes_256_gcm();
         break;
diff --git a/crypto/cipher_extra/test/aes_192_gcm_tests.txt b/crypto/cipher_extra/test/aes_192_gcm_tests.txt
new file mode 100644
index 0000000..154e3c3
--- /dev/null
+++ b/crypto/cipher_extra/test/aes_192_gcm_tests.txt
@@ -0,0 +1,43 @@
+# Test vectors from NIST: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+
+KEY: 000000000000000000000000000000000000000000000000
+NONCE: 000000000000000000000000
+AD:
+TAG: cd33b28ac773f74ba00ed1f312572435
+IN:
+CT:
+
+KEY: 000000000000000000000000000000000000000000000000
+NONCE: 000000000000000000000000
+AD:
+TAG: 2ff58d80033927ab8ef4d4587514f0fb
+IN: 00000000000000000000000000000000
+CT: 98e7247c07f0fe411c267e4384b0f600
+
+KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c
+NONCE: cafebabefacedbaddecaf888
+AD:
+TAG: 9924a7c8587336bfb118024db8674a14
+IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+CT: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
+
+KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c
+NONCE: cafebabefacedbaddecaf888
+AD:  feedfacedeadbeeffeedfacedeadbeefabaddad2
+TAG: 2519498e80f1478f37ba55bd6d27618c
+IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+CT: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
+
+KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c
+NONCE: cafebabefacedbad
+AD:  feedfacedeadbeeffeedfacedeadbeefabaddad2
+TAG: 65dcc57fcf623a24094fcca40d3533f8
+IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+CT: 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
+
+KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c
+NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+AD:  feedfacedeadbeeffeedfacedeadbeefabaddad2
+TAG: dcf566ff291c25bbb8568fc3d376a6d9
+IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+CT: d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b
diff --git a/crypto/fipsmodule/cipher/e_aes.c b/crypto/fipsmodule/cipher/e_aes.c
index 72910ed..2b30fb0 100644
--- a/crypto/fipsmodule/cipher/e_aes.c
+++ b/crypto/fipsmodule/cipher/e_aes.c
@@ -890,7 +890,7 @@
                                   size_t key_len, size_t tag_len) {
   const size_t key_bits = key_len * 8;
 
-  if (key_bits != 128 && key_bits != 256) {
+  if (key_bits != 128 && key_bits != 192 && key_bits != 256) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
     return 0;  // EVP_AEAD_CTX_init should catch this.
   }
@@ -1063,6 +1063,21 @@
   out->open_gather = aead_aes_gcm_open_gather;
 }
 
+DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_192_gcm) {
+  memset(out, 0, sizeof(EVP_AEAD));
+
+  out->key_len = 24;
+  out->nonce_len = 12;
+  out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
+  out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
+  out->seal_scatter_supports_extra_in = 1;
+
+  out->init = aead_aes_gcm_init;
+  out->cleanup = aead_aes_gcm_cleanup;
+  out->seal_scatter = aead_aes_gcm_seal_scatter;
+  out->open_gather = aead_aes_gcm_open_gather;
+}
+
 DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm) {
   memset(out, 0, sizeof(EVP_AEAD));
 
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index 963b2c7..6d78db2 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -99,6 +99,19 @@
 // parameters, only use 12-byte nonces.
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm(void);
 
+// EVP_aead_aes_192_gcm is AES-192 in Galois Counter Mode.
+//
+// WARNING: AES-192 is superfluous and shouldn't exist. NIST should never have
+// defined it. Use only when interop with another system requires it, never
+// de novo.
+//
+// Note: AES-GCM should only be used with 12-byte (96-bit) nonces. Although it
+// is specified to take a variable-length nonce, nonces with other lengths are
+// effectively randomized, which means one must consider collisions. Unless
+// implementing an existing protocol which has already specified incorrect
+// parameters, only use 12-byte nonces.
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_192_gcm(void);
+
 // EVP_aead_aes_256_gcm is AES-256 in Galois Counter Mode.
 //
 // Note: AES-GCM should only be used with 12-byte (96-bit) nonces. Although it
diff --git a/sources.cmake b/sources.cmake
index 1569ce9..8dc65e6 100644
--- a/sources.cmake
+++ b/sources.cmake
@@ -14,6 +14,7 @@
   crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt
   crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt
   crypto/cipher_extra/test/aes_128_gcm_tests.txt
+  crypto/cipher_extra/test/aes_192_gcm_tests.txt
   crypto/cipher_extra/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
   crypto/cipher_extra/test/aes_256_cbc_sha1_tls_tests.txt
   crypto/cipher_extra/test/aes_256_cbc_sha256_tls_tests.txt