Add generic AES-GCM-SIV support.
AES-GCM-SIV is an AEAD with nonce-misuse resistance. It can reuse
hardware support for AES-GCM and thus encrypt at ~66% the speed, and
decrypt at 100% the speed, of AES-GCM.
See https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02
This implementation is generic, not optimised, and reuses existing AES
and GHASH support as much as possible. It is guarded by !OPENSSL_SMALL,
at least for now.
Change-Id: Ia9f77b256ef5dfb8588bb9ecfe6ee0e827626f57
Reviewed-on: https://boringssl-review.googlesource.com/12541
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc
index b33a36d..8dbc8a2 100644
--- a/crypto/cipher/aead_test.cc
+++ b/crypto/cipher/aead_test.cc
@@ -23,6 +23,16 @@
#include "../test/file_test.h"
+
+#if defined(OPENSSL_SMALL)
+const EVP_AEAD* EVP_aead_aes_128_gcm_siv(void) {
+ return nullptr;
+}
+const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
+ return nullptr;
+}
+#endif
+
namespace bssl {
// This program tests an AEAD against a series of test vectors from a file,
@@ -302,6 +312,8 @@
static const struct KnownAEAD kAEADs[] = {
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false },
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false },
+ { "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false },
+ { "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false },
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
{ "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
@@ -342,6 +354,11 @@
}
const EVP_AEAD *const aead = known_aead->func();
+ if (aead == NULL) {
+ // AEAD is not compiled in this configuration.
+ printf("PASS\n");
+ return 0;
+ }
if (!TestCleanupAfterInitFailure(aead)) {
return 1;
diff --git a/crypto/cipher/e_aes.c b/crypto/cipher/e_aes.c
index 9225d6a..f99022f 100644
--- a/crypto/cipher/e_aes.c
+++ b/crypto/cipher/e_aes.c
@@ -1446,6 +1446,305 @@
return &aead_aes_256_ctr_hmac_sha256;
}
+#if !defined(OPENSSL_SMALL)
+
+#define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
+
+struct aead_aes_gcm_siv_ctx {
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ block128_f kgk_block;
+ unsigned is_256:1;
+};
+
+static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ 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 = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+ }
+
+ if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
+ return 0;
+ }
+
+ struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
+ OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_ctx));
+ if (gcm_siv_ctx == NULL) {
+ return 0;
+ }
+ memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));
+
+ if (aesni_capable()) {
+ aesni_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)aesni_encrypt;
+ } else if (hwaes_capable()) {
+ aes_hw_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)aes_hw_encrypt;
+ } else if (vpaes_capable()) {
+ vpaes_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)vpaes_encrypt;
+ } else {
+ AES_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)AES_encrypt;
+ }
+
+ gcm_siv_ctx->is_256 = (key_len == 32);
+ ctx->aead_state = gcm_siv_ctx;
+
+ return 1;
+}
+
+static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {
+ struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+ OPENSSL_cleanse(gcm_siv_ctx, sizeof(struct aead_aes_gcm_siv_ctx));
+ OPENSSL_free(gcm_siv_ctx);
+}
+
+/* gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
+ * |in| to |out|, using the block function |enc_block| with |key| in counter
+ * mode, starting at |initial_counter|. This differs from the traditional
+ * counter mode code in that the counter is handled little-endian, only the
+ * first four bytes are used and the GCM-SIV tweak to the final byte is
+ * applied. The |in| and |out| pointers may be equal but otherwise must not
+ * alias. */
+static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t initial_counter[AES_BLOCK_SIZE],
+ block128_f enc_block, const AES_KEY *key) {
+ union {
+ uint32_t w[4];
+ uint8_t c[16];
+ } counter;
+
+ memcpy(counter.c, initial_counter, AES_BLOCK_SIZE);
+ counter.c[15] |= 0x80;
+
+ for (size_t done = 0; done < in_len;) {
+ uint8_t keystream[AES_BLOCK_SIZE];
+ enc_block(counter.c, keystream, key);
+ counter.w[0]++;
+
+ size_t todo = AES_BLOCK_SIZE;
+ if (in_len - done < todo) {
+ todo = in_len - done;
+ }
+
+ for (size_t i = 0; i < todo; i++) {
+ out[done + i] = keystream[i] ^ in[done + i];
+ }
+
+ done += todo;
+ }
+}
+
+/* gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
+ * AD. The result is written to |out_tag|. */
+static void gcm_siv_polyval(uint8_t out_tag[16], const uint8_t *in,
+ size_t in_len, const uint8_t *ad, size_t ad_len,
+ const uint8_t auth_key[16]) {
+ struct polyval_ctx polyval_ctx;
+ CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
+
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
+
+ uint8_t scratch[16];
+ if (ad_len & 15) {
+ memset(scratch, 0, sizeof(scratch));
+ memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+ }
+
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
+ if (in_len & 15) {
+ memset(scratch, 0, sizeof(scratch));
+ memcpy(scratch, &in[in_len & ~15], in_len & 15);
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+ }
+
+ union {
+ uint8_t c[16];
+ struct {
+ uint64_t ad;
+ uint64_t in;
+ } bitlens;
+ } length_block;
+
+ length_block.bitlens.ad = ad_len * 8;
+ length_block.bitlens.in = in_len * 8;
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block.c,
+ sizeof(length_block));
+
+ CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
+ out_tag[15] &= 0x7f;
+}
+
+/* gcm_siv_record_keys contains the keys used for a specific GCM-SIV record. */
+struct gcm_siv_record_keys {
+ uint8_t auth_key[16];
+ union {
+ double align;
+ AES_KEY ks;
+ } enc_key;
+ block128_f enc_block;
+};
+
+/* gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
+ * given nonce and writes them to |*out_keys|. */
+static void gcm_siv_keys(
+ const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
+ struct gcm_siv_record_keys *out_keys,
+ const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_TAG_LEN]) {
+ const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
+ gcm_siv_ctx->kgk_block(nonce, out_keys->auth_key, key);
+
+ if (gcm_siv_ctx->is_256) {
+ uint8_t record_enc_key[32];
+ gcm_siv_ctx->kgk_block(out_keys->auth_key, record_enc_key + 16, key);
+ gcm_siv_ctx->kgk_block(record_enc_key + 16, record_enc_key, key);
+ aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
+ record_enc_key, sizeof(record_enc_key));
+ } else {
+ uint8_t record_enc_key[16];
+ gcm_siv_ctx->kgk_block(out_keys->auth_key, record_enc_key, key);
+ aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
+ record_enc_key, sizeof(record_enc_key));
+ }
+}
+
+static int aead_aes_gcm_siv_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_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+ const uint64_t in_len_64 = in_len;
+ const uint64_t ad_len_64 = ad_len;
+
+ if (in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN < in_len ||
+ in_len_64 > (UINT64_C(1) << 36) ||
+ ad_len_64 >= (UINT64_C(1) << 61)) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != AES_BLOCK_SIZE) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+
+ struct gcm_siv_record_keys keys;
+ gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
+
+ uint8_t tag[16];
+ gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key);
+ keys.enc_block(tag, tag, &keys.enc_key.ks);
+
+ gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
+
+ memcpy(&out[in_len], tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
+ *out_len = in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+
+ return 1;
+}
+
+static int aead_aes_gcm_siv_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 uint64_t ad_len_64 = ad_len;
+ if (ad_len_64 >= (UINT64_C(1) << 61)) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ const uint64_t in_len_64 = in_len;
+ if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
+ in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+ const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+
+ if (max_out_len < plaintext_len) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ struct gcm_siv_record_keys keys;
+ gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
+
+ gcm_siv_crypt(out, in, plaintext_len, &in[plaintext_len], keys.enc_block,
+ &keys.enc_key.ks);
+
+ uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
+ gcm_siv_polyval(expected_tag, out, plaintext_len, ad, ad_len, keys.auth_key);
+ keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
+
+ if (CRYPTO_memcmp(expected_tag, &in[plaintext_len], sizeof(expected_tag)) !=
+ 0) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ *out_len = plaintext_len;
+ return 1;
+}
+
+static const EVP_AEAD aead_aes_128_gcm_siv = {
+ 16, /* key length */
+ AES_BLOCK_SIZE, /* nonce length */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+
+ aead_aes_gcm_siv_init,
+ NULL /* init_with_direction */,
+ aead_aes_gcm_siv_cleanup,
+ aead_aes_gcm_siv_seal,
+ aead_aes_gcm_siv_open,
+ NULL /* get_iv */,
+};
+
+static const EVP_AEAD aead_aes_256_gcm_siv = {
+ 32, /* key length */
+ AES_BLOCK_SIZE, /* nonce length */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+
+ aead_aes_gcm_siv_init,
+ NULL /* init_with_direction */,
+ aead_aes_gcm_siv_cleanup,
+ aead_aes_gcm_siv_seal,
+ aead_aes_gcm_siv_open,
+ NULL /* get_iv */,
+};
+
+const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
+ return &aead_aes_128_gcm_siv;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
+ return &aead_aes_256_gcm_siv;
+}
+
+#endif /* !OPENSSL_SMALL */
+
int EVP_has_aes_hardware(void) {
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
return aesni_capable() && crypto_gcm_clmul_enabled();
diff --git a/crypto/cipher/test/aes_128_gcm_siv_tests.txt b/crypto/cipher/test/aes_128_gcm_siv_tests.txt
new file mode 100644
index 0000000..a929b59
--- /dev/null
+++ b/crypto/cipher/test/aes_128_gcm_siv_tests.txt
@@ -0,0 +1,236 @@
+# This is the example from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#section-8
+
+KEY: ee8e1ed9ff2540ae8f2ba9f50bc2f27c
+NONCE: 752abad3e0afb5f434dc4310f71f3d21
+IN: "Hello world"
+AD: "example"
+CT: 810649724764545b3625ff
+TAG: 010a10f4942710781d2948ac0192572f
+
+# Test vectors from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-B
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: cb52de357fad226ae428d0ed5a575496
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: 7e139f58002d68ee
+TAG: 715835541f2136f03b6dc80ae0a8ac46
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: 4a87f0cd26e5d5086e90da02
+TAG: 4dff905e48d512e9c34ae8f3be66ec43
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 048ca58c46d2368ce00132389f40b511
+TAG: 971da9aa385283522c4f67a9aedb37e5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: e1cf1cf545d2743ec005b26bd2c836ac1a4233d646c195ffa401f28063127baa
+TAG: 1071338b8c2930d3ec4c17cecbefa4b4
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: 2e7e6881a02d57b877794b2fbfbfef5484f1cf74f4ad53a751b2582c0e698466bd9a49dcab53806d8e31d864c4632d00
+TAG: 04b1b8a9c1630ff028b14d2e57bca429
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: 0ac5be860726209d9218de3e9d533743e1efe1595bc58f93f00e9bb9a7558dc1e1b14a9c0d49eb5064c7efa79842f9c7cfdd77614709f0b545d3227498e774d5
+TAG: 860b73a1ed8a5b9acd925c3f3f49c5c5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4919e29e9890e452
+TAG: 1433a5c0284c911163888dbd128e6874
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: db55d6da719fe0473538294e
+TAG: 5a8ab948ccd205a70c78e8fdf954693b
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: aea3c54272abc1b58ed34a536743f4da
+TAG: da10d98bfe23784cfdfd0af97b6d5b78
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: aa694c0cfe148100cb5c6e27a77a7ff7b4233d6af251d9faa3d84f7c0d1113f1
+TAG: 778c5b68356a1a6a6f3c14a8f96c35ca
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 9ac909928bcde79c2afa885df9c035c85a9eab136f6f6ea11034456bd306ea3c5dd542f706fffe538b5f139fa9dc622e
+TAG: 26c0c0d146d38787ca0fcbc3f911577a
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: c56be9d61ecf6a31a6289cddc9b91aaf84cdb53a3913b825d6eb5e157906dfb0a308c6b0b095d6fd1a5b761ca7fa0e39ca92f38ae206eec844c0c4ab0c1c165e
+TAG: a60986309b99431a35dd8c5ebeef8375
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 47995b96
+TAG: 16b668094202cadde992e0c16205793c
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 8fe25de75089e9f849150e57ab7f7810981cd319
+TAG: 89ca91ebc560709432fe9496746404cc
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: b26d43ae158316ac37f41579ccf1d461274e
+TAG: 13b7c01d08dd6969d51d1bf0fbbdc4d2
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: cb52de357fad226ae428d0ed5a575496
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: 7e139f58002d68ee
+TAG: 715835541f2136f03b6dc80ae0a8ac46
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: 4a87f0cd26e5d5086e90da02
+TAG: 4dff905e48d512e9c34ae8f3be66ec43
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 048ca58c46d2368ce00132389f40b511
+TAG: 971da9aa385283522c4f67a9aedb37e5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: e1cf1cf545d2743ec005b26bd2c836ac1a4233d646c195ffa401f28063127baa
+TAG: 1071338b8c2930d3ec4c17cecbefa4b4
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: 2e7e6881a02d57b877794b2fbfbfef5484f1cf74f4ad53a751b2582c0e698466bd9a49dcab53806d8e31d864c4632d00
+TAG: 04b1b8a9c1630ff028b14d2e57bca429
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: 0ac5be860726209d9218de3e9d533743e1efe1595bc58f93f00e9bb9a7558dc1e1b14a9c0d49eb5064c7efa79842f9c7cfdd77614709f0b545d3227498e774d5
+TAG: 860b73a1ed8a5b9acd925c3f3f49c5c5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4919e29e9890e452
+TAG: 1433a5c0284c911163888dbd128e6874
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: db55d6da719fe0473538294e
+TAG: 5a8ab948ccd205a70c78e8fdf954693b
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: aea3c54272abc1b58ed34a536743f4da
+TAG: da10d98bfe23784cfdfd0af97b6d5b78
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: aa694c0cfe148100cb5c6e27a77a7ff7b4233d6af251d9faa3d84f7c0d1113f1
+TAG: 778c5b68356a1a6a6f3c14a8f96c35ca
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 9ac909928bcde79c2afa885df9c035c85a9eab136f6f6ea11034456bd306ea3c5dd542f706fffe538b5f139fa9dc622e
+TAG: 26c0c0d146d38787ca0fcbc3f911577a
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: c56be9d61ecf6a31a6289cddc9b91aaf84cdb53a3913b825d6eb5e157906dfb0a308c6b0b095d6fd1a5b761ca7fa0e39ca92f38ae206eec844c0c4ab0c1c165e
+TAG: a60986309b99431a35dd8c5ebeef8375
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 47995b96
+TAG: 16b668094202cadde992e0c16205793c
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 8fe25de75089e9f849150e57ab7f7810981cd319
+TAG: 89ca91ebc560709432fe9496746404cc
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: b26d43ae158316ac37f41579ccf1d461274e
+TAG: 13b7c01d08dd6969d51d1bf0fbbdc4d2
diff --git a/crypto/cipher/test/aes_256_gcm_siv_tests.txt b/crypto/cipher/test/aes_256_gcm_siv_tests.txt
new file mode 100644
index 0000000..cd38e23
--- /dev/null
+++ b/crypto/cipher/test/aes_256_gcm_siv_tests.txt
@@ -0,0 +1,226 @@
+# Test vectors from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-B
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: eb7ccf36eeff369241379c87cc08e4f0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: ab3f382a6f0fb4c3
+TAG: a0a69e07b73281f5cdfd034f646cfa08
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: be8d81f033ca23b953da2197
+TAG: cdf3ba70da9c7cbd45f5140ba0cca9f1
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 46e05b7116dbe27aaeffe99892194072
+TAG: be19d78991c62130cf97f628c37c3eaa
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: 23ddbe9ef342b03003f56d6b4a2e8aff035c7d7cfd705e1ab4502904254bb67a
+TAG: 16c5944034050657af7c0fec7efbc40f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: b104c8945f280e75b52c05c45a63d1872c7f0552b1501968d9913d71207d0433f978f1a3eecdf782016b77e8c9d3ff53
+TAG: abedb4841c20f3b05e61e0fd1fcaf3d0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: e3f2bd14f4c80c9cea4c90c81f0e4d7eedb87eb19a7c0cf5a5a95cd3e441a71083b1191d115e9a9ff008b93feeb5a86d012a3e0adb89de2d1e3225479022292f
+TAG: 3ced67f5e03bb476a738c1343926dc19
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4dca2c16c3b0413c
+TAG: ac9b952c76a6f8b5df315f88126daa1c
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: ee0ca9068b5b85dfe115a660
+TAG: 756d6155927271077d790a05390ecb71
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: 590edb785c0cb89d19f031fa7e7d4f91
+TAG: ac2c8f711c86dbecc8c7b663c5fbc1ea
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: dcf2024f5f98d463b82a8673c47dd82159748cac8bcc7c76b8cfa26029cb333c
+TAG: a9b406643e190e602fb104fbb842a1ac
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 79216506b1ddadfe16366e4ec886d10dc9400b995259f74c0091f9b5a6add5680a612130f6c31ab833aa76d9b2be86de
+TAG: 3ddfe9ad2c350980942638d3f954ac6d
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: 9535eb67240c49f30a0de5a90670813fa615e71fcb4c522ca79d9a33459a22f8c6a56d650bf0b15eecdd706e7689cf6510a281724613fea76b5366b40574b1b9
+TAG: abcb59ee31d25ee8889b70d7c36f9a41
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 9611baa0
+TAG: 53daf2bc5916f7a6750f2432068dabee
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 78e3a1b54daa6547f775f30c38a45e887aea5c87
+TAG: f65187d8c28adba364d659b627b16431
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: c6d3d28704bf20067d62e1a3872d40dda44b
+TAG: 6ac0135a4379dbc67967ff55fd4d1f2f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: eb7ccf36eeff369241379c87cc08e4f0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: ab3f382a6f0fb4c3
+TAG: a0a69e07b73281f5cdfd034f646cfa08
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: be8d81f033ca23b953da2197
+TAG: cdf3ba70da9c7cbd45f5140ba0cca9f1
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 46e05b7116dbe27aaeffe99892194072
+TAG: be19d78991c62130cf97f628c37c3eaa
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: 23ddbe9ef342b03003f56d6b4a2e8aff035c7d7cfd705e1ab4502904254bb67a
+TAG: 16c5944034050657af7c0fec7efbc40f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: b104c8945f280e75b52c05c45a63d1872c7f0552b1501968d9913d71207d0433f978f1a3eecdf782016b77e8c9d3ff53
+TAG: abedb4841c20f3b05e61e0fd1fcaf3d0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: e3f2bd14f4c80c9cea4c90c81f0e4d7eedb87eb19a7c0cf5a5a95cd3e441a71083b1191d115e9a9ff008b93feeb5a86d012a3e0adb89de2d1e3225479022292f
+TAG: 3ced67f5e03bb476a738c1343926dc19
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4dca2c16c3b0413c
+TAG: ac9b952c76a6f8b5df315f88126daa1c
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: ee0ca9068b5b85dfe115a660
+TAG: 756d6155927271077d790a05390ecb71
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: 590edb785c0cb89d19f031fa7e7d4f91
+TAG: ac2c8f711c86dbecc8c7b663c5fbc1ea
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: dcf2024f5f98d463b82a8673c47dd82159748cac8bcc7c76b8cfa26029cb333c
+TAG: a9b406643e190e602fb104fbb842a1ac
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 79216506b1ddadfe16366e4ec886d10dc9400b995259f74c0091f9b5a6add5680a612130f6c31ab833aa76d9b2be86de
+TAG: 3ddfe9ad2c350980942638d3f954ac6d
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: 9535eb67240c49f30a0de5a90670813fa615e71fcb4c522ca79d9a33459a22f8c6a56d650bf0b15eecdd706e7689cf6510a281724613fea76b5366b40574b1b9
+TAG: abcb59ee31d25ee8889b70d7c36f9a41
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 9611baa0
+TAG: 53daf2bc5916f7a6750f2432068dabee
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 78e3a1b54daa6547f775f30c38a45e887aea5c87
+TAG: f65187d8c28adba364d659b627b16431
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: c6d3d28704bf20067d62e1a3872d40dda44b
+TAG: 6ac0135a4379dbc67967ff55fd4d1f2f
diff --git a/crypto/modes/CMakeLists.txt b/crypto/modes/CMakeLists.txt
index 17faa15..dc9e504 100644
--- a/crypto/modes/CMakeLists.txt
+++ b/crypto/modes/CMakeLists.txt
@@ -48,10 +48,11 @@
OBJECT
cbc.c
- ctr.c
- ofb.c
cfb.c
+ ctr.c
gcm.c
+ ofb.c
+ polyval.c
${MODES_ARCH_SOURCES}
)
diff --git a/crypto/modes/internal.h b/crypto/modes/internal.h
index 64232c4..a53da04 100644
--- a/crypto/modes/internal.h
+++ b/crypto/modes/internal.h
@@ -189,6 +189,12 @@
uint8_t ecount_buf[16], unsigned *num,
ctr128_f ctr);
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t *ivec);
+#endif
+
/* GCM.
*
@@ -328,11 +334,36 @@
block128_f block);
-#if !defined(OPENSSL_NO_ASM) && \
- (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
-void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
- const void *key, const uint8_t *ivec);
-#endif
+/* POLYVAL.
+ *
+ * POLYVAL is a polynomial authenticator that operates over a field very
+ * similar to the one that GHASH uses. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#section-3. */
+
+typedef union {
+ uint64_t u[2];
+ uint8_t c[16];
+} polyval_block;
+
+struct polyval_ctx {
+ polyval_block S;
+ u128 Htable[16];
+ gmult_func gmult;
+ ghash_func ghash;
+};
+
+/* CRYPTO_POLYVAL_init initialises |ctx| using |key|. */
+void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]);
+
+/* CRYPTO_POLYVAL_update_blocks updates the accumulator in |ctx| given the
+ * blocks from |in|. Only a whole number of blocks can be processed so |in_len|
+ * must be a multiple of 16. */
+void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+ size_t in_len);
+
+/* CRYPTO_POLYVAL_finish writes the accumulator from |ctx| to |out|. */
+void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/crypto/modes/polyval.c b/crypto/modes/polyval.c
new file mode 100644
index 0000000..c5121a1
--- /dev/null
+++ b/crypto/modes/polyval.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/base.h>
+
+#if !defined(OPENSSL_SMALL)
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+/* byte_reverse reverses the order of the bytes in |b->c|. */
+static void byte_reverse(polyval_block *b) {
+ const uint64_t t = CRYPTO_bswap8(b->u[0]);
+ b->u[0] = CRYPTO_bswap8(b->u[1]);
+ b->u[1] = t;
+}
+
+/* reverse_and_mulX_ghash interprets the bytes |b->c| as a reversed element of
+ * the GHASH field, multiplies that by 'x' and serialises the result back into
+ * |b|, but with GHASH's backwards bit ordering. */
+static void reverse_and_mulX_ghash(polyval_block *b) {
+ uint64_t hi = b->u[0];
+ uint64_t lo = b->u[1];
+ const unsigned carry = constant_time_eq(hi & 1, 1);
+ hi >>= 1;
+ hi |= lo << 63;
+ lo >>= 1;
+ lo ^= ((uint64_t) constant_time_select(carry, 0xe1, 0)) << 56;
+
+ b->u[0] = CRYPTO_bswap8(lo);
+ b->u[1] = CRYPTO_bswap8(hi);
+}
+
+/* POLYVAL(H, X_1, ..., X_n) =
+ * ByteReverse(GHASH(mulX_GHASH(ByteReverse(H)), ByteReverse(X_1), ...,
+ * ByteReverse(X_n))).
+ *
+ * See https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-A. */
+
+void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]) {
+ polyval_block H;
+ memcpy(H.c, key, 16);
+ reverse_and_mulX_ghash(&H);
+
+ CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, ctx->Htable, H.c);
+ memset(&ctx->S, 0, sizeof(ctx->S));
+}
+
+void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+ size_t in_len) {
+ assert((in_len & 15) == 0);
+ polyval_block reversed[32];
+
+ while (in_len > 0) {
+ size_t todo = in_len;
+ if (todo > sizeof(reversed)) {
+ todo = sizeof(reversed);
+ }
+ memcpy(reversed, in, todo);
+ in_len -= todo;
+
+ size_t blocks = todo / sizeof(polyval_block);
+ for (size_t i = 0; i < blocks; i++) {
+ byte_reverse(&reversed[i]);
+ }
+
+ ctx->ghash(ctx->S.u, ctx->Htable, (const uint8_t *) reversed, todo);
+ }
+}
+
+void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]) {
+ polyval_block S = ctx->S;
+ byte_reverse(&S);
+ memcpy(out, &S.c, sizeof(polyval_block));
+}
+
+
+#endif /* !OPENSSL_SMALL */
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index fff0e49..eaa2b8f 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -114,6 +114,14 @@
* authentication. See |EVP_aead_aes_128_ctr_hmac_sha256| for details. */
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void);
+/* EVP_aead_aes_128_gcm_siv is AES-128 in GCM-SIV mode. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void);
+
+/* EVP_aead_aes_256_gcm_siv is AES-256 in GCM-SIV mode. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void);
+
/* EVP_has_aes_hardware returns one if we enable hardware support for fast and
* constant-time AES-GCM. */
OPENSSL_EXPORT int EVP_has_aes_hardware(void);
diff --git a/tool/speed.cc b/tool/speed.cc
index f16a9eb..5fd1058 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -654,6 +654,12 @@
kLegacyADLen, selected) ||
!SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
kLegacyADLen, selected) ||
+#if !defined(OPENSSL_SMALL)
+ !SpeedAEAD(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
+ selected) ||
+ !SpeedAEAD(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
+ selected) ||
+#endif
!SpeedHash(EVP_sha1(), "SHA-1", selected) ||
!SpeedHash(EVP_sha256(), "SHA-256", selected) ||
!SpeedHash(EVP_sha512(), "SHA-512", selected) ||
diff --git a/util/all_tests.json b/util/all_tests.json
index d2e39ce..5ffa5e8 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -8,6 +8,8 @@
["crypto/chacha/chacha_test"],
["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"],
["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"],
+ ["crypto/cipher/aead_test", "aes-128-gcm-siv", "crypto/cipher/test/aes_128_gcm_siv_tests.txt"],
+ ["crypto/cipher/aead_test", "aes-256-gcm-siv", "crypto/cipher/test/aes_256_gcm_siv_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"],