Replace keywrap AEADs with upstream's APIs.

This finally removes the last Android hack. Both Chromium and Android
end up needing this thing (Chromium needs it for WebCrypto but currently
uses the EVP_AEAD version and Android needs it by way of
wpa_supplicant).

On the Android side, the alternative is we finish upstream's
NEED_INTERNAL_AES_WRAP patch, but then it just uses its own key-wrap
implementation. This seems a little silly, considering we have a version
of key-wrap under a different API anyway.

It also doesn't make much sense to leave the EVP_AEAD API around if we
don't want people to use it and Chromium's the only consumer. Remove it
and I'll switch Chromium to the new---er, old--- APIs next roll.

Change-Id: I23a89cda25bddb6ac1033e4cd408165f393d1e6c
Reviewed-on: https://boringssl-review.googlesource.com/11410
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/aes/CMakeLists.txt b/crypto/aes/CMakeLists.txt
index 509fed9..33eebf5 100644
--- a/crypto/aes/CMakeLists.txt
+++ b/crypto/aes/CMakeLists.txt
@@ -53,6 +53,7 @@
   OBJECT
 
   aes.c
+  key_wrap.c
   mode_wrappers.c
 
   ${AES_ARCH_SOURCES}
diff --git a/crypto/aes/aes_test.cc b/crypto/aes/aes_test.cc
index e488d81..4fb3a31 100644
--- a/crypto/aes/aes_test.cc
+++ b/crypto/aes/aes_test.cc
@@ -15,88 +15,168 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <memory>
+#include <vector>
+
 #include <openssl/aes.h>
 #include <openssl/crypto.h>
 
+#include "../test/file_test.h"
 
-static bool TestAES(const uint8_t *key, size_t key_len,
-                    const uint8_t plaintext[AES_BLOCK_SIZE],
-                    const uint8_t ciphertext[AES_BLOCK_SIZE]) {
+
+static bool TestRaw(FileTest *t) {
+  std::vector<uint8_t> key, plaintext, ciphertext;
+  if (!t->GetBytes(&key, "Key") ||
+      !t->GetBytes(&plaintext, "Plaintext") ||
+      !t->GetBytes(&ciphertext, "Ciphertext")) {
+    return false;
+  }
+
+  if (plaintext.size() != AES_BLOCK_SIZE ||
+      ciphertext.size() != AES_BLOCK_SIZE) {
+    t->PrintLine("Plaintext or Ciphertext not a block size.");
+    return false;
+  }
+
   AES_KEY aes_key;
-  if (AES_set_encrypt_key(key, key_len * 8, &aes_key) != 0) {
-    fprintf(stderr, "AES_set_encrypt_key failed\n");
+  if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_encrypt_key failed.");
     return false;
   }
 
   // Test encryption.
   uint8_t block[AES_BLOCK_SIZE];
-  AES_encrypt(plaintext, block, &aes_key);
-  if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_encrypt gave the wrong output\n");
+  AES_encrypt(plaintext.data(), block, &aes_key);
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("AES_encrypt gave the wrong output.");
     return false;
   }
 
   // Test in-place encryption.
-  memcpy(block, plaintext, AES_BLOCK_SIZE);
+  memcpy(block, plaintext.data(), AES_BLOCK_SIZE);
   AES_encrypt(block, block, &aes_key);
-  if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_encrypt gave the wrong output\n");
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("In-place AES_encrypt gave the wrong output.");
     return false;
   }
 
-  if (AES_set_decrypt_key(key, key_len * 8, &aes_key) != 0) {
-    fprintf(stderr, "AES_set_decrypt_key failed\n");
+  if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_decrypt_key failed.");
     return false;
   }
 
   // Test decryption.
-  AES_decrypt(ciphertext, block, &aes_key);
-  if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_decrypt gave the wrong output\n");
+  AES_decrypt(ciphertext.data(), block, &aes_key);
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("AES_decrypt gave the wrong output.");
     return false;
   }
 
   // Test in-place decryption.
-  memcpy(block, ciphertext, AES_BLOCK_SIZE);
+  memcpy(block, ciphertext.data(), AES_BLOCK_SIZE);
   AES_decrypt(block, block, &aes_key);
-  if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_decrypt gave the wrong output\n");
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("In-place AES_decrypt gave the wrong output.");
     return false;
   }
+
   return true;
 }
 
-int main() {
-  CRYPTO_library_init();
+static bool TestKeyWrap(FileTest *t) {
+  // All test vectors use the default IV, so test both with implicit and
+  // explicit IV.
+  //
+  // TODO(davidben): Find test vectors that use a different IV.
+  static const uint8_t kDefaultIV[] = {
+      0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  };
 
-  // Test vectors from FIPS-197, Appendix C.
-  if (!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
-                                "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-               128 / 8,
-               (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
-                                "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-               (const uint8_t *)"\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
-                                "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a") ||
-      !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
-                                "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                                "\x10\x11\x12\x13\x14\x15\x16\x17",
-               192 / 8,
-               (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
-                                "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-               (const uint8_t *)"\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
-                                "\x6e\xaf\x70\xa0\xec\x0d\x71\x91") ||
-      !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
-                                "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                                "\x10\x11\x12\x13\x14\x15\x16\x17"
-                                "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-               256 / 8,
-               (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
-                                "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-               (const uint8_t *)"\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
-                                "\xea\xfc\x49\x90\x4b\x49\x60\x89")) {
+  std::vector<uint8_t> key, plaintext, ciphertext;
+  if (!t->GetBytes(&key, "Key") ||
+      !t->GetBytes(&plaintext, "Plaintext") ||
+      !t->GetBytes(&ciphertext, "Ciphertext")) {
     return false;
   }
 
-  printf("PASS\n");
-  return 0;
+  if (plaintext.size() + 8 != ciphertext.size()) {
+    t->PrintLine("Invalid Plaintext and Ciphertext lengths.");
+    return false;
+  }
+
+  AES_KEY aes_key;
+  if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_encrypt_key failed.");
+    return false;
+  }
+
+  std::unique_ptr<uint8_t[]> buf(new uint8_t[ciphertext.size()]);
+  if (AES_wrap_key(&aes_key, nullptr /* iv */, buf.get(), plaintext.data(),
+                   plaintext.size()) != static_cast<int>(ciphertext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("AES_wrap_key with implicit IV failed.");
+    return false;
+  }
+
+  memset(buf.get(), 0, ciphertext.size());
+  if (AES_wrap_key(&aes_key, kDefaultIV, buf.get(), plaintext.data(),
+                   plaintext.size()) != static_cast<int>(ciphertext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("AES_wrap_key with explicit IV failed.");
+    return false;
+  }
+
+  if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_decrypt_key failed.");
+    return false;
+  }
+
+  buf.reset(new uint8_t[plaintext.size()]);
+  if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
+                     ciphertext.size()) != static_cast<int>(plaintext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("AES_unwrap_key with implicit IV failed.");
+    return false;
+  }
+
+  memset(buf.get(), 0, plaintext.size());
+  if (AES_unwrap_key(&aes_key, kDefaultIV, buf.get(), ciphertext.data(),
+                     ciphertext.size()) != static_cast<int>(plaintext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("AES_unwrap_key with explicit IV failed.");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestAES(FileTest *t, void *arg) {
+  if (t->GetParameter() == "Raw") {
+    return TestRaw(t);
+  }
+  if (t->GetParameter() == "KeyWrap") {
+    return TestKeyWrap(t);
+  }
+
+  t->PrintLine("Unknown mode '%s'.", t->GetParameter().c_str());
+  return false;
+}
+
+int main(int argc, char **argv) {
+  CRYPTO_library_init();
+
+  if (argc != 2) {
+    fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+    return 1;
+  }
+
+  return FileTestMain(TestAES, nullptr, argv[1]);
 }
diff --git a/crypto/aes/aes_tests.txt b/crypto/aes/aes_tests.txt
new file mode 100644
index 0000000..d4e4c61
--- /dev/null
+++ b/crypto/aes/aes_tests.txt
@@ -0,0 +1,50 @@
+# Test vectors from FIPS-197, Appendix C.
+
+Mode = Raw
+Key = 000102030405060708090a0b0c0d0e0f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 69c4e0d86a7b0430d8cdb78070b4c55a
+
+Mode = Raw
+Key = 000102030405060708090a0b0c0d0e0f1011121314151617
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = dda97ca4864cdfe06eaf70a0ec0d7191
+
+Mode = Raw
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 8ea2b7ca516745bfeafc49904b496089
+
+
+# Test vectors from
+# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f1011121314151617
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f1011121314151617
+Plaintext = 00112233445566778899aabbccddeeff0001020304050607
+Ciphertext = 031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff0001020304050607
+Ciphertext = a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f
+Ciphertext = 28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21
diff --git a/crypto/aes/key_wrap.c b/crypto/aes/key_wrap.c
new file mode 100644
index 0000000..e955c47
--- /dev/null
+++ b/crypto/aes/key_wrap.c
@@ -0,0 +1,134 @@
+/* ====================================================================
+ * Copyright (c) 2001-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ==================================================================== */
+
+#include <openssl/aes.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+
+/* kDefaultIV is the default IV value given in RFC 3394, 2.2.3.1. */
+static const uint8_t kDefaultIV[] = {
+    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+};
+
+int AES_wrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out,
+                 const uint8_t *in, size_t in_len) {
+  /* See RFC 3394, section 2.2.1. */
+
+  if (in_len > INT_MAX - 8 || in_len < 8 || in_len % 8 != 0) {
+    return -1;
+  }
+
+  if (iv == NULL) {
+    iv = kDefaultIV;
+  }
+
+  memmove(out + 8, in, in_len);
+  uint8_t A[AES_BLOCK_SIZE];
+  memcpy(A, iv, 8);
+
+  size_t n = in_len / 8;
+
+  for (unsigned j = 0; j < 6; j++) {
+    for (size_t i = 1; i <= n; i++) {
+      memcpy(A + 8, out + 8 * i, 8);
+      AES_encrypt(A, A, key);
+
+      uint32_t t = (uint32_t)(n * j + i);
+      A[7] ^= t & 0xff;
+      A[6] ^= (t >> 8) & 0xff;
+      A[5] ^= (t >> 16) & 0xff;
+      A[4] ^= (t >> 24) & 0xff;
+      memcpy(out + 8 * i, A + 8, 8);
+    }
+  }
+
+  memcpy(out, A, 8);
+  return (int)in_len + 8;
+}
+
+int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out,
+                   const uint8_t *in, size_t in_len) {
+  /* See RFC 3394, section 2.2.2. */
+
+  if (in_len > INT_MAX || in_len < 16 || in_len % 8 != 0) {
+    return -1;
+  }
+
+  if (iv == NULL) {
+    iv = kDefaultIV;
+  }
+
+  uint8_t A[AES_BLOCK_SIZE];
+  memcpy(A, in, 8);
+  memmove(out, in + 8, in_len - 8);
+
+  size_t n = (in_len / 8) - 1;
+
+  for (unsigned j = 5; j < 6; j--) {
+    for (size_t i = n; i > 0; i--) {
+      uint32_t t = (uint32_t)(n * j + i);
+      A[7] ^= t & 0xff;
+      A[6] ^= (t >> 8) & 0xff;
+      A[5] ^= (t >> 16) & 0xff;
+      A[4] ^= (t >> 24) & 0xff;
+      memcpy(A + 8, out + 8 * (i - 1), 8);
+      AES_decrypt(A, A, key);
+      memcpy(out + 8 * (i - 1), A + 8, 8);
+    }
+  }
+
+  if (CRYPTO_memcmp(A, iv, 8) != 0) {
+    return -1;
+  }
+
+  return (int)in_len - 8;
+}
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc
index 0dbb8c6..b33a36d 100644
--- a/crypto/cipher/aead_test.cc
+++ b/crypto/cipher/aead_test.cc
@@ -316,8 +316,6 @@
   { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true },
   { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true },
   { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true },
-  { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap, true },
-  { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap, true },
   { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false },
   { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false },
   { "", NULL, false },
diff --git a/crypto/cipher/e_aes.c b/crypto/cipher/e_aes.c
index 963aecc..9225d6a 100644
--- a/crypto/cipher/e_aes.c
+++ b/crypto/cipher/e_aes.c
@@ -1179,266 +1179,6 @@
 const EVP_AEAD *EVP_aead_aes_256_gcm(void) { return &aead_aes_256_gcm; }
 
 
-/* AES Key Wrap is specified in
- * http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
- * or https://tools.ietf.org/html/rfc3394 */
-
-struct aead_aes_key_wrap_ctx {
-  uint8_t key[32];
-  unsigned key_bits;
-};
-
-static int aead_aes_key_wrap_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                  size_t key_len, size_t tag_len) {
-  struct aead_aes_key_wrap_ctx *kw_ctx;
-  const size_t key_bits = key_len * 8;
-
-  if (key_bits != 128 && key_bits != 256) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
-    return 0; /* EVP_AEAD_CTX_init should catch this. */
-  }
-
-  if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
-    tag_len = 8;
-  }
-
-  if (tag_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
-    return 0;
-  }
-
-  kw_ctx = OPENSSL_malloc(sizeof(struct aead_aes_key_wrap_ctx));
-  if (kw_ctx == NULL) {
-    OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-
-  memcpy(kw_ctx->key, key, key_len);
-  kw_ctx->key_bits = key_bits;
-
-  ctx->aead_state = kw_ctx;
-  return 1;
-}
-
-static void aead_aes_key_wrap_cleanup(EVP_AEAD_CTX *ctx) {
-  struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
-  OPENSSL_cleanse(kw_ctx, sizeof(struct aead_aes_key_wrap_ctx));
-  OPENSSL_free(kw_ctx);
-}
-
-/* kDefaultAESKeyWrapNonce is the default nonce value given in 2.2.3.1. */
-static const uint8_t kDefaultAESKeyWrapNonce[8] = {0xa6, 0xa6, 0xa6, 0xa6,
-                                                   0xa6, 0xa6, 0xa6, 0xa6};
-
-
-static int aead_aes_key_wrap_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                  size_t *out_len, size_t max_out_len,
-                                  const uint8_t *nonce, size_t nonce_len,
-                                  const uint8_t *in, size_t in_len,
-                                  const uint8_t *ad, size_t ad_len) {
-  const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
-  union {
-    double align;
-    AES_KEY ks;
-  } ks;
-  /* Variables in this function match up with the variables in the second half
-   * of section 2.2.1. */
-  unsigned i, j, n;
-  uint8_t A[AES_BLOCK_SIZE];
-
-  if (ad_len != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_AD_SIZE);
-    return 0;
-  }
-
-  if (nonce_len == 0) {
-    nonce = kDefaultAESKeyWrapNonce;
-    nonce_len = sizeof(kDefaultAESKeyWrapNonce);
-  }
-
-  if (nonce_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-
-  if (in_len % 8 != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE);
-    return 0;
-  }
-
-  /* The code below only handles a 32-bit |t| thus 6*|n| must be less than
-   * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
-   * conservatively cap it to 2^32-16 to stop 32-bit platforms complaining that
-   * a comparison is always true. */
-  if (in_len > 0xfffffff0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
-    return 0;
-  }
-
-  n = in_len / 8;
-
-  if (n < 2) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE);
-    return 0;
-  }
-
-  if (in_len + 8 < in_len) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
-    return 0;
-  }
-
-  if (max_out_len < in_len + 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  if (AES_set_encrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
-    return 0;
-  }
-
-  memmove(out + 8, in, in_len);
-  memcpy(A, nonce, 8);
-
-  for (j = 0; j < 6; j++) {
-    for (i = 1; i <= n; i++) {
-      uint32_t t;
-
-      memcpy(A + 8, out + 8 * i, 8);
-      AES_encrypt(A, A, &ks.ks);
-      t = n * j + i;
-      A[7] ^= t & 0xff;
-      A[6] ^= (t >> 8) & 0xff;
-      A[5] ^= (t >> 16) & 0xff;
-      A[4] ^= (t >> 24) & 0xff;
-      memcpy(out + 8 * i, A + 8, 8);
-    }
-  }
-
-  memcpy(out, A, 8);
-  *out_len = in_len + 8;
-  return 1;
-}
-
-static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                  size_t *out_len, size_t max_out_len,
-                                  const uint8_t *nonce, size_t nonce_len,
-                                  const uint8_t *in, size_t in_len,
-                                  const uint8_t *ad, size_t ad_len) {
-  const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
-  union {
-    double align;
-    AES_KEY ks;
-  } ks;
-  /* Variables in this function match up with the variables in the second half
-   * of section 2.2.1. */
-  unsigned i, j, n;
-  uint8_t A[AES_BLOCK_SIZE];
-
-  if (ad_len != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_AD_SIZE);
-    return 0;
-  }
-
-  if (nonce_len == 0) {
-    nonce = kDefaultAESKeyWrapNonce;
-    nonce_len = sizeof(kDefaultAESKeyWrapNonce);
-  }
-
-  if (nonce_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-
-  if (in_len % 8 != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE);
-    return 0;
-  }
-
-  /* The code below only handles a 32-bit |t| thus 6*|n| must be less than
-   * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
-   * conservatively cap it to 2^32-8 to stop 32-bit platforms complaining that
-   * a comparison is always true. */
-  if (in_len > 0xfffffff8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
-    return 0;
-  }
-
-  if (in_len < 24) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
-    return 0;
-  }
-
-  n = (in_len / 8) - 1;
-
-  if (max_out_len < in_len - 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  if (AES_set_decrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
-    return 0;
-  }
-
-  memcpy(A, in, 8);
-  memmove(out, in + 8, in_len - 8);
-
-  for (j = 5; j < 6; j--) {
-    for (i = n; i > 0; i--) {
-      uint32_t t;
-
-      t = n * j + i;
-      A[7] ^= t & 0xff;
-      A[6] ^= (t >> 8) & 0xff;
-      A[5] ^= (t >> 16) & 0xff;
-      A[4] ^= (t >> 24) & 0xff;
-      memcpy(A + 8, out + 8 * (i - 1), 8);
-      AES_decrypt(A, A, &ks.ks);
-      memcpy(out + 8 * (i - 1), A + 8, 8);
-    }
-  }
-
-  if (CRYPTO_memcmp(A, nonce, 8) != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
-    return 0;
-  }
-
-  *out_len = in_len - 8;
-  return 1;
-}
-
-static const EVP_AEAD aead_aes_128_key_wrap = {
-    16, /* key len */
-    8,  /* nonce len */
-    8,  /* overhead */
-    8,  /* max tag length */
-    aead_aes_key_wrap_init,
-    NULL, /* init_with_direction */
-    aead_aes_key_wrap_cleanup,
-    aead_aes_key_wrap_seal,
-    aead_aes_key_wrap_open,
-    NULL, /* get_iv */
-};
-
-static const EVP_AEAD aead_aes_256_key_wrap = {
-    32, /* key len */
-    8,  /* nonce len */
-    8,  /* overhead */
-    8,  /* max tag length */
-    aead_aes_key_wrap_init,
-    NULL, /* init_with_direction */
-    aead_aes_key_wrap_cleanup,
-    aead_aes_key_wrap_seal,
-    aead_aes_key_wrap_open,
-    NULL, /* get_iv */
-};
-
-const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; }
-
-const EVP_AEAD *EVP_aead_aes_256_key_wrap(void) { return &aead_aes_256_key_wrap; }
-
-
 #define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH
 #define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12
 
diff --git a/crypto/cipher/test/aes_128_key_wrap_tests.txt b/crypto/cipher/test/aes_128_key_wrap_tests.txt
deleted file mode 100644
index 561ec90..0000000
--- a/crypto/cipher/test/aes_128_key_wrap_tests.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# These test vectors have been taken from
-# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
-
-KEY: 000102030405060708090A0B0C0D0E0F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF
-AD:
-CT: 1FA68B0A8112B447AEF34BD8FB5A7B82
-TAG: 9D3E862371D2CFE5
diff --git a/crypto/cipher/test/aes_256_key_wrap_tests.txt b/crypto/cipher/test/aes_256_key_wrap_tests.txt
deleted file mode 100644
index 92d3a04..0000000
--- a/crypto/cipher/test/aes_256_key_wrap_tests.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-# These test vectors have been taken from
-# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
-
-KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF
-AD:
-CT: 64E8C3F9CE0F5BA263E9777905818A2A
-TAG: 93C8191E7D6E8AE7
-
-KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF0001020304050607
-AD:
-CT: A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB895
-TAG: 8CD5D17D6B254DA1
-
-KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F
-AD:
-CT: 28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43B
-TAG: FB988B9B7A02DD21
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index af81fa6..fff0e49 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -105,20 +105,6 @@
  * suites. */
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void);
 
-/* EVP_aead_aes_128_key_wrap is AES-128 Key Wrap mode. This should never be
- * used except to interoperate with existing systems that use this mode.
- *
- * If the nonce is empty then the default nonce will be used, otherwise it must
- * be eight bytes long. The input must be a multiple of eight bytes long. No
- * additional data can be given to this mode. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_key_wrap(void);
-
-/* EVP_aead_aes_256_key_wrap is AES-256 in Key Wrap mode. This should never be
- * used except to interoperate with existing systems that use this mode.
- *
- * See |EVP_aead_aes_128_key_wrap| for details. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_key_wrap(void);
-
 /* EVP_aead_aes_128_ctr_hmac_sha256 is AES-128 in CTR mode with HMAC-SHA256 for
  * authentication. The nonce is 12 bytes; the bottom 32-bits are used as the
  * block counter, thus the maximum plaintext size is 64GB. */
diff --git a/include/openssl/aes.h b/include/openssl/aes.h
index ed060ff..2aef918 100644
--- a/include/openssl/aes.h
+++ b/include/openssl/aes.h
@@ -139,16 +139,28 @@
                                        uint8_t *ivec, int *num, int enc);
 
 
-/* Android compatibility section.
+/* AES key wrap.
  *
- * These functions are declared, temporarily, for Android because
- * wpa_supplicant will take a little time to sync with upstream. Outside of
- * Android they'll have no definition. */
+ * These functions implement AES Key Wrap mode, as defined in RFC 3394. They
+ * should never be used except to interoperate with existing systems that use
+ * this mode. */
 
-OPENSSL_EXPORT int AES_wrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out,
-                                const uint8_t *in, unsigned in_len);
-OPENSSL_EXPORT int AES_unwrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out,
-                                  const uint8_t *in, unsigned in_len);
+/* AES_wrap_key performs AES key wrap on |in| which must be a multiple of 8
+ * bytes. |iv| must point to an 8 byte value or be NULL to use the default IV.
+ * |key| must have been configured for encryption. On success, it writes
+ * |in_len| + 8 bytes to |out| and returns |in_len| + 8. Otherwise, it returns
+ * -1. */
+OPENSSL_EXPORT int AES_wrap_key(const AES_KEY *key, const uint8_t *iv,
+                                uint8_t *out, const uint8_t *in, size_t in_len);
+
+/* AES_unwrap_key performs AES key unwrap on |in| which must be a multiple of 8
+ * bytes. |iv| must point to an 8 byte value or be NULL to use the default IV.
+ * |key| must have been configured for decryption. On success, it writes
+ * |in_len| - 8 bytes to |out| and returns |in_len| - 8. Otherwise, it returns
+ * -1. */
+OPENSSL_EXPORT int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv,
+                                  uint8_t *out, const uint8_t *in,
+                                  size_t in_len);
 
 
 #if defined(__cplusplus)
diff --git a/util/all_tests.json b/util/all_tests.json
index f95a21e..ac4b3c7 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -1,5 +1,5 @@
 [
-	["crypto/aes/aes_test"],
+	["crypto/aes/aes_test", "crypto/aes/aes_tests.txt"],
 	["crypto/asn1/asn1_test"],
 	["crypto/base64/base64_test"],
 	["crypto/bio/bio_test"],
@@ -7,9 +7,7 @@
 	["crypto/bytestring/bytestring_test"],
 	["crypto/chacha/chacha_test"],
 	["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"],
-	["crypto/cipher/aead_test", "aes-128-key-wrap", "crypto/cipher/test/aes_128_key_wrap_tests.txt"],
 	["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"],
-	["crypto/cipher/aead_test", "aes-256-key-wrap", "crypto/cipher/test/aes_256_key_wrap_tests.txt"],
 	["crypto/cipher/aead_test", "chacha20-poly1305", "crypto/cipher/test/chacha20_poly1305_tests.txt"],
 	["crypto/cipher/aead_test", "chacha20-poly1305-old", "crypto/cipher/test/chacha20_poly1305_old_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt"],