no-dtls,
no-ec,
no-ec2m,
+ no-siv,
no-legacy,
no-rfc3779,
no-sock,
}
OPENSSL_clear_free(loopargs[k].key, keylen);
- /* SIV mode only allows for a single Update operation */
- if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_SIV_MODE)
+ /* GCM-SIV/SIV mode only allows for a single Update operation */
+ if (EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_SIV_MODE
+ || EVP_CIPHER_get_mode(evp_cipher) == EVP_CIPH_GCM_SIV_MODE)
(void)EVP_CIPHER_CTX_ctrl(loopargs[k].ctx,
EVP_CTRL_SET_SPEED, 1, NULL);
}
#endif
}
+void ossl_gcm_init_4bit(u128 Htable[16], const u64 H[2])
+{
+ struct gcm_funcs_st funcs;
+
+ gcm_get_funcs(&funcs);
+ funcs.ginit(Htable, H);
+}
+
+void ossl_gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
+{
+ struct gcm_funcs_st funcs;
+
+ gcm_get_funcs(&funcs);
+ funcs.gmult(Xi, Htable);
+}
+
+void ossl_gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
+ const u8 *inp, size_t len)
+{
+ struct gcm_funcs_st funcs;
+ u64 tmp[2];
+ size_t i;
+
+ gcm_get_funcs(&funcs);
+ if (funcs.ghash != NULL) {
+ funcs.ghash(Xi, Htable, inp, len);
+ } else {
+ /* Emulate ghash if needed */
+ for (i = 0; i < len; i += 16) {
+ memcpy(tmp, &inp[i], sizeof(tmp));
+ Xi[0] ^= tmp[0];
+ Xi[1] ^= tmp[1];
+ funcs.gmult(Xi, Htable);
+ }
+ }
+}
+
void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
{
DECLARE_IS_ENDIAN;
=head2 SIV Mode
+Both the AES-SIV and AES-GCM-SIV ciphers fall under this mode.
+
For SIV mode ciphers the behaviour of the EVP interface is subtly
altered and several additional ctrl operations are supported.
#endif
};
+/* GHASH functions */
+void ossl_gcm_init_4bit(u128 Htable[16], const u64 H[2]);
+void ossl_gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
+ const u8 *inp, size_t len);
+void ossl_gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]);
+
/*
* The maximum permitted number of cipher blocks per data unit in XTS mode.
* Reference IEEE Std 1619-2018.
#define OSSL_CIPHER_CTS_MODE_CS2 "CS2"
#define OSSL_CIPHER_CTS_MODE_CS3 "CS3"
+/* Known CIPHER names (not a complete list) */
+#define OSSL_CIPHER_NAME_AES_128_GCM_SIV "AES-128-GCM-SIV"
+#define OSSL_CIPHER_NAME_AES_192_GCM_SIV "AES-192-GCM-SIV"
+#define OSSL_CIPHER_NAME_AES_256_GCM_SIV "AES-256-GCM-SIV"
+
/* digest parameters */
#define OSSL_DIGEST_PARAM_XOFLEN "xoflen" /* size_t */
#define OSSL_DIGEST_PARAM_SSL3_MS "ssl3-ms" /* octet string */
# define EVP_CIPH_WRAP_MODE 0x10002
# define EVP_CIPH_OCB_MODE 0x10003
# define EVP_CIPH_SIV_MODE 0x10004
+# define EVP_CIPH_GCM_SIV_MODE 0x10005
# define EVP_CIPH_MODE 0xF0007
/* Set if variable length cipher */
# define EVP_CIPH_VARIABLE_LENGTH 0x8
ALG(PROV_NAMES_AES_128_SIV, ossl_aes128siv_functions),
ALG(PROV_NAMES_AES_192_SIV, ossl_aes192siv_functions),
ALG(PROV_NAMES_AES_256_SIV, ossl_aes256siv_functions),
+ ALG(PROV_NAMES_AES_128_GCM_SIV, ossl_aes128gcm_siv_functions),
+ ALG(PROV_NAMES_AES_192_GCM_SIV, ossl_aes192gcm_siv_functions),
+ ALG(PROV_NAMES_AES_256_GCM_SIV, ossl_aes256gcm_siv_functions),
#endif /* OPENSSL_NO_SIV */
ALG(PROV_NAMES_AES_256_GCM, ossl_aes256gcm_functions),
ALG(PROV_NAMES_AES_192_GCM, ossl_aes192gcm_functions),
$CHACHAPOLY_GOAL=../../libdefault.a
$SIV_GOAL=../../libdefault.a
+IF[{- !$disabled{asm} -}]
+ $GHASHDEF_x86=GHASH_ASM
+ $GHASHDEF_x86_sse2=OPENSSL_IA32_SSE2
+
+ $GHASHDEF_x86_64=GHASH_ASM
+ $GHASHDEF_x86_64_sse2=OPENSSL_IA32_SSE2
+
+ # ghash-ia64.s doesn't work on VMS
+ IF[{- $config{target} !~ /^vms-/ -}]
+ $GHASHDEF_ia64=GHASH_ASM
+ ENDIF
+
+ $GHASHDEF_sparcv9=GHASH_ASM
+
+ $GHASHDEF_alpha=GHASH_ASM
+
+ $GHASHDEF_s390x=GHASH_ASM
+
+ $GHASHDEF_armv4=GHASH_ASM
+ $GHASHDEF_aarch64=
+
+ $GHASHDEF_parisc11=GHASH_ASM
+ $GHASHDEF_parisc20_64=$GHASHDEF_parisc11
+
+ $GHASHDEF_ppc32=
+ $GHASHDEF_ppc64=$GHASHDEF_ppc32
+
+ $GHASHDEF_c64xplus=GHASH_ASM
+
+ $GHASHDEF_riscv64=GHASH_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+
+ IF[$GHASHDEF_{- $target{asm_arch} -}]
+ $GHASHDEF=$GHASHDEF_{- $target{asm_arch} -}
+ IF[{- !$disabled{sse2} -}]
+ IF[$GHASHDEF_{- $target{asm_arch} -}_sse2]
+ $GHASHDEF=$GHASHDEF_{- $target{asm_arch} -}_sse2
+ ENDIF
+ ENDIF
+ ENDIF
+ENDIF
+
# This source is common building blocks for all ciphers in all our providers.
SOURCE[$COMMON_GOAL]=\
ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \
SOURCE[$AES_GOAL]=cipher_aes_xts_fips.c
IF[{- !$disabled{siv} -}]
+ DEFINE[$SIV_GOAL]=$GHASHDEF
SOURCE[$SIV_GOAL]=\
- cipher_aes_siv.c cipher_aes_siv_hw.c
+ cipher_aes_siv.c cipher_aes_siv_hw.c \
+ cipher_aes_gcm_siv.c cipher_aes_gcm_siv_hw.c cipher_aes_gcm_siv_polyval.c
ENDIF
IF[{- !$disabled{des} -}]
--- /dev/null
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for AES SIV mode */
+
+/*
+ * This file uses the low level AES functions (which are deprecated for
+ * non-internal use) in order to implement provider AES ciphers.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/proverr.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/ciphercommon_aead.h"
+#include "prov/provider_ctx.h"
+#include "cipher_aes_gcm_siv.h"
+
+static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]);
+
+static void *ossl_aes_gcm_siv_newctx(void *provctx, size_t keybits)
+{
+ PROV_AES_GCM_SIV_CTX *ctx;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ ctx = OPENSSL_zalloc(sizeof(*ctx));
+ if (ctx != NULL) {
+ ctx->key_len = keybits / 8;
+ ctx->hw = ossl_prov_cipher_hw_aes_gcm_siv(keybits);
+ ctx->libctx = PROV_LIBCTX_OF(provctx);
+ ctx->provctx = provctx;
+ }
+ return ctx;
+}
+
+static void ossl_aes_gcm_siv_freectx(void *vctx)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+
+ if (ctx == NULL)
+ return;
+
+ OPENSSL_clear_free(ctx->aad, ctx->aad_len);
+ ctx->hw->clean_ctx(ctx);
+ OPENSSL_clear_free(ctx, sizeof(*ctx));
+}
+
+static void *ossl_aes_gcm_siv_dupctx(void *vctx)
+{
+ PROV_AES_GCM_SIV_CTX *in = (PROV_AES_GCM_SIV_CTX *)vctx;
+ PROV_AES_GCM_SIV_CTX *ret;
+
+ if (!ossl_prov_is_running())
+ return NULL;
+
+ if (in->hw == NULL)
+ return NULL;
+
+ ret = OPENSSL_memdup(in, sizeof(*in));
+ if (ret == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ /* NULL-out these things we create later */
+ ret->aad = NULL;
+ ret->ecb_ctx = NULL;
+
+ if (in->aad == NULL) {
+ if ((ret->aad = OPENSSL_memdup(in->aad, UP16(ret->aad_len))) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (!in->hw->dup_ctx(ret, in))
+ goto err;
+
+ return ret;
+ err:
+ if (ret != NULL) {
+ OPENSSL_clear_free(ret->aad, ret->aad_len);
+ OPENSSL_free(ret);
+ }
+ return NULL;
+}
+
+static int ossl_aes_gcm_siv_init(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[], int enc)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ ctx->enc = enc;
+
+ if (key != NULL) {
+ if (keylen != ctx->key_len) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ memcpy(ctx->key_gen_key, key, ctx->key_len);
+ }
+ if (iv != NULL) {
+ if (ivlen != sizeof(ctx->nonce)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+ return 0;
+ }
+ memcpy(ctx->nonce, iv, sizeof(ctx->nonce));
+ }
+
+ if (!ctx->hw->initkey(ctx))
+ return 0;
+
+ return ossl_aes_gcm_siv_set_ctx_params(ctx, params);
+}
+
+static int ossl_aes_gcm_siv_einit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 1);
+}
+
+static int ossl_aes_gcm_siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
+ const unsigned char *iv, size_t ivlen,
+ const OSSL_PARAM params[])
+{
+ return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 0);
+}
+
+#define ossl_aes_gcm_siv_stream_update ossl_aes_gcm_siv_cipher
+static int ossl_aes_gcm_siv_cipher(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize, const unsigned char *in, size_t inl)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+ int error = 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ /* The RFC has a test case for this, but we don't try to do anything */
+ if (inl == 0) {
+ if (outl != NULL)
+ *outl = 0;
+ return 1;
+ }
+
+ if (outsize < inl) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ error |= !ctx->hw->cipher(ctx, out, in, inl);
+
+ if (outl != NULL && !error)
+ *outl = inl;
+ return !error;
+}
+
+static int ossl_aes_gcm_siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
+ size_t outsize)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+ int error = 0;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ error |= !ctx->hw->cipher(vctx, out, NULL, 0);
+
+ if (outl != NULL && !error)
+ *outl = 0;
+ return !error;
+}
+
+static int ossl_aes_gcm_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+ OSSL_PARAM *p;
+
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
+ if (!ctx->enc || !ctx->generated_tag
+ || p->data_size != sizeof(ctx->tag)
+ || !OSSL_PARAM_set_octet_string(p, ctx->tag, sizeof(ctx->tag))) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, sizeof(ctx->tag))) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+ return 0;
+ }
+ return 1;
+}
+
+static const OSSL_PARAM aes_gcm_siv_known_gettable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *ossl_aes_gcm_siv_gettable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return aes_gcm_siv_known_gettable_ctx_params;
+}
+
+static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+ const OSSL_PARAM *p;
+ unsigned int speed = 0;
+
+ if (params == NULL)
+ return 1;
+
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+ if (p != NULL) {
+ if (p->data_type != OSSL_PARAM_OCTET_STRING
+ || p->data_size != sizeof(ctx->user_tag)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ if (!ctx->enc) {
+ memcpy(ctx->user_tag, p->data, sizeof(ctx->tag));
+ ctx->have_user_tag = 1;
+ }
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
+ if (p != NULL) {
+ if (!OSSL_PARAM_get_uint(p, &speed)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ ctx->speed = !!speed;
+ }
+ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+ if (p != NULL) {
+ size_t key_len;
+
+ if (!OSSL_PARAM_get_size_t(p, &key_len)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+ return 0;
+ }
+ /* The key length can not be modified */
+ if (key_len != ctx->key_len) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static const OSSL_PARAM aes_gcm_siv_known_settable_ctx_params[] = {
+ OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+ OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
+ OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+ OSSL_PARAM_END
+};
+static const OSSL_PARAM *ossl_aes_gcm_siv_settable_ctx_params(ossl_unused void *cctx,
+ ossl_unused void *provctx)
+{
+ return aes_gcm_siv_known_settable_ctx_params;
+}
+
+#define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \
+static OSSL_FUNC_cipher_newctx_fn ossl_##alg##kbits##_##lc##_newctx; \
+static OSSL_FUNC_cipher_freectx_fn ossl_##alg##_##lc##_freectx; \
+static OSSL_FUNC_cipher_dupctx_fn ossl_##alg##_##lc##_dupctx; \
+static OSSL_FUNC_cipher_encrypt_init_fn ossl_##alg##_##lc##_einit; \
+static OSSL_FUNC_cipher_decrypt_init_fn ossl_##alg##_##lc##_dinit; \
+static OSSL_FUNC_cipher_update_fn ossl_##alg##_##lc##_stream_update; \
+static OSSL_FUNC_cipher_final_fn ossl_##alg##_##lc##_stream_final; \
+static OSSL_FUNC_cipher_cipher_fn ossl_##alg##_##lc##_cipher; \
+static OSSL_FUNC_cipher_get_params_fn ossl_##alg##_##kbits##_##lc##_get_params; \
+static OSSL_FUNC_cipher_get_ctx_params_fn ossl_##alg##_##lc##_get_ctx_params; \
+static OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_##alg##_##lc##_gettable_ctx_params; \
+static OSSL_FUNC_cipher_set_ctx_params_fn ossl_##alg##_##lc##_set_ctx_params; \
+static OSSL_FUNC_cipher_settable_ctx_params_fn ossl_##alg##_##lc##_settable_ctx_params; \
+static int ossl_##alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \
+{ \
+ return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \
+ flags, kbits, blkbits, ivbits); \
+} \
+static void * ossl_##alg##kbits##_##lc##_newctx(void *provctx) \
+{ \
+ return ossl_##alg##_##lc##_newctx(provctx, kbits); \
+} \
+const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \
+ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))ossl_##alg##kbits##_##lc##_newctx }, \
+ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_##alg##_##lc##_freectx }, \
+ { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))ossl_##alg##_##lc##_dupctx }, \
+ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_einit }, \
+ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_dinit }, \
+ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##alg##_##lc##_stream_update }, \
+ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_##alg##_##lc##_stream_final }, \
+ { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_##alg##_##lc##_cipher }, \
+ { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))ossl_##alg##_##kbits##_##lc##_get_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))ossl_cipher_generic_gettable_params }, \
+ { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_get_ctx_params }, \
+ { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_gettable_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_set_ctx_params }, \
+ { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_settable_ctx_params }, \
+ { 0, NULL } \
+}
+
+IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 128, 8, 96);
+IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 192, 8, 96);
+IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 256, 8, 96);
--- /dev/null
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#include "prov/ciphercommon.h"
+#include "crypto/aes_platform.h"
+
+#define BLOCK_SIZE 16
+#define NONCE_SIZE 12
+#define TAG_SIZE 16
+
+/* AAD manipulation macros */
+#define UP16(x) (((x) + 15) & ~0x0F)
+#define DOWN16(x) ((x) & ~0x0F)
+#define REMAINDER16(x) ((x) & 0x0F)
+#define IS16(x) (((x) & 0x0F) == 0)
+
+typedef struct prov_cipher_hw_aes_gcm_siv_st {
+ int (*initkey)(void *vctx);
+ int (*cipher)(void *vctx, unsigned char *out, const unsigned char *in,
+ size_t len);
+ int (*dup_ctx)(void *vdst, void *vsrc);
+ void (*clean_ctx)(void *vctx);
+} PROV_CIPHER_HW_AES_GCM_SIV;
+
+/* Arranged for alignment purposes */
+typedef struct prov_aes_gcm_siv_ctx_st {
+ EVP_CIPHER_CTX *ecb_ctx;
+ const PROV_CIPHER_HW_AES_GCM_SIV *hw; /* maybe not used, yet? */
+ uint8_t *aad; /* Allocated, rounded up to 16 bytes, from user */
+ OSSL_LIB_CTX *libctx;
+ OSSL_PROVIDER *provctx;
+ size_t aad_len; /* actual AAD length */
+ size_t key_len;
+ uint8_t key_gen_key[32]; /* from user */
+ uint8_t msg_enc_key[32]; /* depends on key size */
+ uint8_t msg_auth_key[BLOCK_SIZE];
+ uint8_t tag[TAG_SIZE]; /* generated tag, given to user or compared to user */
+ uint8_t user_tag[TAG_SIZE]; /* from user */
+ uint8_t nonce[NONCE_SIZE]; /* from user */
+ u128 Htable[16]; /* Polyval calculations via ghash */
+ unsigned int enc : 1; /* Set to 1 if we are encrypting or 0 otherwise */
+ unsigned int have_user_tag : 1;
+ unsigned int generated_tag : 1;
+ unsigned int used_enc : 1;
+ unsigned int used_dec : 1;
+ unsigned int speed : 1;
+} PROV_AES_GCM_SIV_CTX;
+
+const PROV_CIPHER_HW_AES_GCM_SIV *ossl_prov_cipher_hw_aes_gcm_siv(size_t keybits);
+
+void ossl_polyval_ghash_init(u128 Htable[16], const uint64_t H[2]);
+void ossl_polyval_ghash_hash(const u128 Htable[16], uint8_t *tag, const uint8_t *inp, size_t len);
+
+/* Define our own BSWAP8/BSWAP4, if not already defined */
+#ifndef BSWAP8
+static ossl_inline uint64_t BSWAP8(uint64_t n)
+{
+ uint8_t *p = (uint8_t *)&n;
+
+ return (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
+}
+#endif
+
+#ifndef BSWAP4
+static ossl_inline uint32_t BSWAP4(uint32_t n)
+{
+ uint8_t *p = (uint8_t *)&n;
+
+ return GETU32(p);
+}
+#endif
--- /dev/null
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/evp.h>
+#include <internal/endian.h>
+#include <prov/implementations.h>
+#include "cipher_aes_gcm_siv.h"
+
+static int aes_gcm_siv_ctr32(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *init_counter,
+ unsigned char *out, const unsigned char *in, size_t len);
+
+static int aes_gcm_siv_initkey(void *vctx)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+ uint8_t output[BLOCK_SIZE];
+ uint32_t counter = 0x0;
+ size_t i;
+ union {
+ uint32_t counter;
+ uint8_t block[BLOCK_SIZE];
+ } data;
+ int out_len;
+ EVP_CIPHER *ecb = NULL;
+ DECLARE_IS_ENDIAN;
+
+ switch (ctx->key_len) {
+ case 16:
+ ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-128-ECB", NULL);
+ break;
+ case 24:
+ ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-192-ECB", NULL);
+ break;
+ case 32:
+ ecb = EVP_CIPHER_fetch(ctx->libctx, "AES-256-ECB", NULL);
+ break;
+ default:
+ goto err;
+ }
+
+ if (ctx->ecb_ctx == NULL && (ctx->ecb_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto err;
+ if (!EVP_EncryptInit_ex2(ctx->ecb_ctx, ecb, ctx->key_gen_key, NULL, NULL))
+ goto err;
+
+ memset(&data, 0, sizeof(data));
+ memcpy(&data.block[sizeof(data.counter)], ctx->nonce, NONCE_SIZE);
+
+ /* msg_auth_key is always 16 bytes in size, regardless of AES128/AES256 */
+ /* counter is stored little-endian */
+ for (i = 0; i < BLOCK_SIZE; i += 8) {
+ if (IS_LITTLE_ENDIAN) {
+ data.counter = counter;
+ } else {
+ data.counter = BSWAP4(counter);
+ }
+ /* Block size is 16 (128 bits), but only 8 bytes are used */
+ out_len = BLOCK_SIZE;
+ if (!EVP_EncryptUpdate(ctx->ecb_ctx, output, &out_len, data.block, BLOCK_SIZE))
+ goto err;
+ memcpy(&ctx->msg_auth_key[i], output, 8);
+ counter++;
+ }
+
+ /* msg_enc_key length is directly tied to key length AES128/AES256 */
+ for (i = 0; i < ctx->key_len; i += 8) {
+ if (IS_LITTLE_ENDIAN) {
+ data.counter = counter;
+ } else {
+ data.counter = BSWAP4(counter);
+ }
+ /* Block size is 16 bytes (128 bits), but only 8 bytes are used */
+ out_len = BLOCK_SIZE;
+ if (!EVP_EncryptUpdate(ctx->ecb_ctx, output, &out_len, data.block, BLOCK_SIZE))
+ goto err;
+ memcpy(&ctx->msg_enc_key[i], output, 8);
+ counter++;
+ }
+
+ if (!EVP_EncryptInit_ex2(ctx->ecb_ctx, ecb, ctx->msg_enc_key, NULL, NULL))
+ goto err;
+
+ /* Freshen up the state */
+ ctx->used_enc = 0;
+ ctx->used_dec = 0;
+ EVP_CIPHER_free(ecb);
+ return 1;
+ err:
+ EVP_CIPHER_CTX_free(ctx->ecb_ctx);
+ EVP_CIPHER_free(ecb);
+ ctx->ecb_ctx = NULL;
+ return 0;
+}
+
+static int aes_gcm_siv_aad(PROV_AES_GCM_SIV_CTX *ctx,
+ const unsigned char *aad, size_t len)
+{
+ size_t to_alloc;
+ uint8_t *ptr;
+ uint64_t len64;
+
+ /* length of 0 resets the AAD */
+ if (len == 0) {
+ OPENSSL_free(ctx->aad);
+ ctx->aad = NULL;
+ ctx->aad_len = 0;
+ return 1;
+ }
+ to_alloc = UP16(ctx->aad_len + len);
+ /* need to check the size of the AAD per RFC8452 */
+ len64 = to_alloc;
+ if (len64 > ((uint64_t)1 << 36))
+ return 0;
+ ptr = OPENSSL_realloc(ctx->aad, to_alloc);
+ if (ptr == NULL)
+ return 0;
+ ctx->aad = ptr;
+ memcpy(&ctx->aad[ctx->aad_len], aad, len);
+ ctx->aad_len += len;
+ if (to_alloc > ctx->aad_len)
+ memset(&ctx->aad[ctx->aad_len], 0, to_alloc - ctx->aad_len);
+ return 1;
+}
+
+static int aes_gcm_siv_finish(PROV_AES_GCM_SIV_CTX *ctx)
+{
+ int ret = 0;
+
+ if (ctx->enc)
+ return ctx->generated_tag;
+ ret = !CRYPTO_memcmp(ctx->tag, ctx->user_tag, sizeof(ctx->tag));
+ ret &= ctx->have_user_tag;
+ return ret;
+}
+
+static int aes_gcm_siv_encrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ uint64_t len_blk[2];
+ uint8_t S_s[TAG_SIZE];
+ uint8_t counter_block[TAG_SIZE];
+ uint8_t padding[BLOCK_SIZE];
+ size_t i;
+ int64_t len64 = len;
+ int out_len;
+ int error = 0;
+ DECLARE_IS_ENDIAN;
+
+ ctx->generated_tag = 0;
+ if (!ctx->speed && ctx->used_enc)
+ return 0;
+ /* need to check the size of the input! */
+ if (len64 > ((int64_t)1 << 36) || len == 0)
+ return 0;
+
+ if (IS_LITTLE_ENDIAN) {
+ len_blk[0] = (uint64_t)ctx->aad_len * 8;
+ len_blk[1] = (uint64_t)len * 8;
+ } else {
+ len_blk[0] = BSWAP8((uint64_t)ctx->aad_len * 8);
+ len_blk[1] = BSWAP8((uint64_t)len * 8);
+ }
+ memset(S_s, 0, TAG_SIZE);
+ ossl_polyval_ghash_init(ctx->Htable, (const uint64_t*)ctx->msg_auth_key);
+
+ if (ctx->aad != NULL) {
+ /* AAD is allocated with padding, but need to adjust length */
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, ctx->aad, UP16(ctx->aad_len));
+ }
+ if (DOWN16(len) > 0)
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *) in, DOWN16(len));
+ if (!IS16(len)) {
+ /* deal with padding - probably easier to memset the padding first rather than calculate */
+ memset(padding, 0, sizeof(padding));
+ memcpy(padding, &in[DOWN16(len)], REMAINDER16(len));
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, padding, sizeof(padding));
+ }
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *) len_blk, sizeof(len_blk));
+
+ for (i = 0; i < NONCE_SIZE; i++)
+ S_s[i] ^= ctx->nonce[i];
+
+ S_s[TAG_SIZE - 1] &= 0x7f;
+ out_len = sizeof(ctx->tag);
+ error |= !EVP_EncryptUpdate(ctx->ecb_ctx, ctx->tag, &out_len, S_s, sizeof(S_s));
+ memcpy(counter_block, ctx->tag, TAG_SIZE);
+ counter_block[TAG_SIZE - 1] |= 0x80;
+
+ error |= !aes_gcm_siv_ctr32(ctx, counter_block, out, in, len);
+
+ ctx->generated_tag = !error;
+ /* Regardless of error */
+ ctx->used_enc = 1;
+ return !error;
+}
+
+static int aes_gcm_siv_decrypt(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *in,
+ unsigned char *out, size_t len)
+{
+ uint8_t counter_block[TAG_SIZE];
+ uint64_t len_blk[2];
+ uint8_t S_s[TAG_SIZE];
+ size_t i;
+ uint64_t padding[2];
+ int64_t len64 = len;
+ int out_len;
+ int error = 0;
+ DECLARE_IS_ENDIAN;
+
+ ctx->generated_tag = 0;
+ if (!ctx->speed && ctx->used_dec)
+ return 0;
+ /* need to check the size of the input! */
+ if (len64 > ((int64_t)1 << 36) || len == 0)
+ return 0;
+
+ memcpy(counter_block, ctx->user_tag, sizeof(counter_block));
+ counter_block[TAG_SIZE - 1] |= 0x80;
+
+ error |= !aes_gcm_siv_ctr32(ctx, counter_block, out, in, len);
+
+ if (IS_LITTLE_ENDIAN) {
+ len_blk[0] = (uint64_t)ctx->aad_len * 8;
+ len_blk[1] = (uint64_t)len * 8;
+ } else {
+ len_blk[0] = BSWAP8((uint64_t)ctx->aad_len * 8);
+ len_blk[1] = BSWAP8((uint64_t)len * 8);
+ }
+ memset(S_s, 0, TAG_SIZE);
+ ossl_polyval_ghash_init(ctx->Htable, (const uint64_t*)ctx->msg_auth_key);
+ if (ctx->aad != NULL) {
+ /* AAD allocated with padding, but need to adjust length */
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, ctx->aad, UP16(ctx->aad_len));
+ }
+ if (DOWN16(len) > 0)
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, out, DOWN16(len));
+ if (!IS16(len)) {
+ /* deal with padding - probably easier to "memset" the padding first rather than calculate */
+ padding[0] = padding[1] = 0;
+ memcpy(padding, &out[DOWN16(len)], REMAINDER16(len));
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *)padding, sizeof(padding));
+ }
+ ossl_polyval_ghash_hash(ctx->Htable, S_s, (uint8_t *)len_blk, TAG_SIZE);
+
+ for (i = 0; i < NONCE_SIZE; i++)
+ S_s[i] ^= ctx->nonce[i];
+
+ S_s[TAG_SIZE - 1] &= 0x7f;
+
+ /*
+ * In the ctx, user_tag is the one received/set by the user,
+ * and tag is generated from the input
+ */
+ out_len = sizeof(ctx->tag);
+ error |= !EVP_EncryptUpdate(ctx->ecb_ctx, ctx->tag, &out_len, S_s, sizeof(S_s));
+ ctx->generated_tag = !error;
+ /* Regardless of error */
+ ctx->used_dec = 1;
+ return !error;
+}
+
+static int aes_gcm_siv_cipher(void *vctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+
+ /* EncryptFinal or DecryptFinal */
+ if (in == NULL)
+ return aes_gcm_siv_finish(ctx);
+
+ /* Deal with associated data */
+ if (out == NULL)
+ return aes_gcm_siv_aad(ctx, in, len);
+
+ if (ctx->enc)
+ return aes_gcm_siv_encrypt(ctx, in, out, len);
+
+ return aes_gcm_siv_decrypt(ctx, in, out, len);
+}
+
+static void aes_gcm_siv_clean_ctx(void *vctx)
+{
+ PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
+
+ EVP_CIPHER_CTX_free(ctx->ecb_ctx);
+ ctx->ecb_ctx = NULL;
+}
+
+static int aes_gcm_siv_dup_ctx(void *vdst, void *vsrc)
+{
+ PROV_AES_GCM_SIV_CTX *dst = (PROV_AES_GCM_SIV_CTX *)vdst;
+ PROV_AES_GCM_SIV_CTX *src = (PROV_AES_GCM_SIV_CTX *)vsrc;
+
+ dst->ecb_ctx = NULL;
+ if (src->ecb_ctx != NULL) {
+ if ((dst->ecb_ctx = EVP_CIPHER_CTX_new()) == NULL)
+ goto err;
+ if (!EVP_CIPHER_CTX_copy(dst->ecb_ctx, src->ecb_ctx))
+ goto err;
+ }
+ return 1;
+
+ err:
+ EVP_CIPHER_CTX_free(dst->ecb_ctx);
+ dst->ecb_ctx = NULL;
+ return 0;
+}
+
+static const PROV_CIPHER_HW_AES_GCM_SIV aes_gcm_siv_hw =
+{
+ aes_gcm_siv_initkey,
+ aes_gcm_siv_cipher,
+ aes_gcm_siv_dup_ctx,
+ aes_gcm_siv_clean_ctx,
+};
+
+const PROV_CIPHER_HW_AES_GCM_SIV *ossl_prov_cipher_hw_aes_gcm_siv(size_t keybits)
+{
+ return &aes_gcm_siv_hw;
+}
+
+/* AES-GCM-SIV needs AES-CTR32, which is different than the AES-CTR implementation */
+static int aes_gcm_siv_ctr32(PROV_AES_GCM_SIV_CTX *ctx, const unsigned char *init_counter,
+ unsigned char *out, const unsigned char *in, size_t len)
+{
+ uint8_t keystream[BLOCK_SIZE];
+ int out_len;
+ size_t i;
+ size_t j;
+ size_t todo;
+ uint32_t counter;
+ int error = 0;
+ union {
+ uint32_t x32[BLOCK_SIZE / sizeof(uint32_t)];
+ uint8_t x8[BLOCK_SIZE];
+ } block;
+ DECLARE_IS_ENDIAN;
+
+ memcpy(&block, init_counter, sizeof(block));
+ if (IS_BIG_ENDIAN) {
+ counter = BSWAP4(block.x32[0]);
+ }
+
+ for (i = 0; i < len; i += sizeof(block)) {
+ out_len = BLOCK_SIZE;
+ error |= !EVP_EncryptUpdate(ctx->ecb_ctx, keystream, &out_len, (uint8_t*)&block, sizeof(block));
+ if (IS_LITTLE_ENDIAN) {
+ block.x32[0]++;
+ } else {
+ counter++;
+ block.x32[0] = BSWAP4(counter);
+ }
+ todo = len - i;
+ if (todo > sizeof(keystream))
+ todo = sizeof(keystream);
+ /* Non optimal, but avoids alignment issues */
+ for (j = 0; j < todo; j++)
+ out[i + j] = in[i + j] ^ keystream[j];
+ }
+ return !error;
+}
--- /dev/null
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
+#include <openssl/evp.h>
+#include <internal/endian.h>
+#include <prov/implementations.h>
+#include "cipher_aes_gcm_siv.h"
+
+static ossl_inline void mulx_ghash(uint64_t *a)
+{
+ uint64_t t[2], mask;
+
+ t[0] = BSWAP8(a[0]);
+ t[1] = BSWAP8(a[1]);
+ mask = -(int64_t)(t[1] & 1) & 0xe1;
+ mask <<= 56;
+
+ a[1] = BSWAP8((t[1] >> 1) ^ (t[0] << 63));
+ a[0] = BSWAP8((t[0] >> 1) ^ mask);
+}
+
+#define aligned64(p) (((uintptr_t)p & 0x07) == 0)
+static ossl_inline void byte_reverse16(uint8_t *out, const uint8_t *in)
+{
+ if (aligned64(out) && aligned64(in)) {
+ ((uint64_t *)out)[0] = BSWAP8(((uint64_t *)in)[1]);
+ ((uint64_t *)out)[1] = BSWAP8(((uint64_t *)in)[0]);
+ } else {
+ int i;
+
+ for (i = 0; i < 16; i++)
+ out[i] = in[15 - i];
+ }
+}
+
+/* Initialization of POLYVAL via existing GHASH implementation */
+void ossl_polyval_ghash_init(u128 Htable[16], const uint64_t H[2])
+{
+ uint64_t tmp[2];
+ DECLARE_IS_ENDIAN;
+
+ byte_reverse16((uint8_t *)tmp, (const uint8_t *)H);
+ mulx_ghash(tmp);
+ if (IS_LITTLE_ENDIAN) {
+ /* "H is stored in host byte order" */
+ tmp[0] = BSWAP8(tmp[0]);
+ tmp[1] = BSWAP8(tmp[1]);
+ }
+
+ ossl_gcm_init_4bit(Htable, (u64*)tmp);
+}
+
+/* Implmentation of POLYVAL via existing GHASH implementation */
+void ossl_polyval_ghash_hash(const u128 Htable[16], uint8_t *tag, const uint8_t *inp, size_t len)
+{
+ uint64_t out[2];
+ uint64_t tmp[2];
+ size_t i;
+
+ byte_reverse16((uint8_t *)out, (uint8_t *)tag);
+
+ /*
+ * This implementation doesn't deal with partials, callers do,
+ * so, len is a multiple of 16
+ */
+ for (i = 0; i < len; i += 16) {
+ byte_reverse16((uint8_t *)tmp, &inp[i]);
+ ossl_gcm_ghash_4bit((u64*)out, Htable, (uint8_t *)tmp, 16);
+ }
+ byte_reverse16(tag, (uint8_t *)out);
+}
extern const OSSL_DISPATCH ossl_aes128siv_functions[];
extern const OSSL_DISPATCH ossl_aes192siv_functions[];
extern const OSSL_DISPATCH ossl_aes256siv_functions[];
+extern const OSSL_DISPATCH ossl_aes128gcm_siv_functions[];
+extern const OSSL_DISPATCH ossl_aes192gcm_siv_functions[];
+extern const OSSL_DISPATCH ossl_aes256gcm_siv_functions[];
#endif /* OPENSSL_NO_SIV */
/* MACs */
#define PROV_NAMES_AES_128_SIV "AES-128-SIV"
#define PROV_NAMES_AES_192_SIV "AES-192-SIV"
#define PROV_NAMES_AES_256_SIV "AES-256-SIV"
+#define PROV_NAMES_AES_128_GCM_SIV "AES-128-GCM-SIV"
+#define PROV_NAMES_AES_192_GCM_SIV "AES-192-GCM-SIV"
+#define PROV_NAMES_AES_256_GCM_SIV "AES-256-GCM-SIV"
#define PROV_NAMES_ARIA_256_GCM "ARIA-256-GCM:1.2.410.200046.1.1.36"
#define PROV_NAMES_ARIA_192_GCM "ARIA-192-GCM:1.2.410.200046.1.1.35"
#define PROV_NAMES_ARIA_128_GCM "ARIA-128-GCM:1.2.410.200046.1.1.34"
&& EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_STREAM_CIPHER)
|| ((EVP_CIPHER_get_flags(cdat->cipher) & EVP_CIPH_FLAG_CTS) != 0)
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_SIV_MODE
+ || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_GCM_SIV_MODE
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_XTS_MODE
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE)
break;
my $no_ec = disabled("ec");
my $no_gost = disabled("gost");
my $no_sm2 = disabled("sm2");
+my $no_siv = disabled("siv");
# Default config depends on if the legacy module is built or not
my $defaultcnf = $no_legacy ? 'default.cnf' : 'default-and-legacy.cnf';
# (i.e. The algorithms are not present in the fips provider)
my @defltfiles = qw(
evpciph_aes_ocb.txt
- evpciph_aes_siv.txt
evpciph_aria.txt
evpciph_bf.txt
evpciph_camellia.txt
);
push @defltfiles, qw(evppkey_brainpool.txt) unless $no_ec;
push @defltfiles, qw(evppkey_sm2.txt) unless $no_sm2;
+push @defltfiles, qw(evpciph_aes_gcm_siv.txt) unless $no_siv;
+push @defltfiles, qw(evpciph_aes_siv.txt) unless $no_siv;
plan tests =>
+ (scalar(@configs) * scalar(@files))
--- /dev/null
+#
+# Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# Tests start with one of these keywords
+# Cipher Decrypt Derive Digest Encoding KDF MAC PBE
+# PrivPubKeyPair Sign Verify VerifyRecover
+# and continue until a blank line. Lines starting with a pound sign are ignored.
+
+Title = RFC8452 AES-GCM-SIV
+
+Cipher = aes-128-gcm-siv
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 578782fff6013b815b287c22493a364c
+Plaintext = 0100000000000000
+Ciphertext = b5d839330ac7b786
+
+
+Cipher = aes-128-gcm-siv
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = a4978db357391a0bc4fdec8b0d106639
+Plaintext = 010000000000000000000000
+Ciphertext = 7323ea61d05932260047d942
+
+
+Cipher = aes-128-gcm-siv
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 303aaf90f6fe21199c6068577437a0c4
+Plaintext = 01000000000000000000000000000000
+Ciphertext = 743f7c8077ab25f8624e2e948579cf77
+
+
+Cipher = aes-128-gcm-siv
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 1a8e45dcd4578c667cd86847bf6155ff
+Plaintext = 0100000000000000000000000000000002000000000000000000000000000000
+Ciphertext = 84e07e62ba83a6585417245d7ec413a9fe427d6315c09b57ce45f2e3936a9445
+
+
+Cipher = aes-128-gcm-siv
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 5e6e311dbf395d35b0fe39c2714388f8
+Plaintext = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+Ciphertext = 3fd24ce1f5a67b75bf2351f181a475c7b800a5b4d3dcf70106b1eea82fa1d64df42bf7226122fa92e17a40eeaac1201b
+
+
+Cipher = aes-128-gcm-siv
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 8a263dd317aa88d56bdf3936dba75bb8
+Plaintext = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+Ciphertext = 2433668f1058190f6d43e360f4f35cd8e475127cfca7028ea8ab5c20f7ab2af02516a2bdcbc08d521be37ff28c152bba36697f25b4cd169c6590d1dd39566d3f
+
+
+Cipher = aes-128-gcm-siv
+AAD = 01
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 3b0a1a2560969cdf790d99759abd1508
+Plaintext = 0200000000000000
+Ciphertext = 1e6daba35669f427
+
+
+Cipher = aes-128-gcm-siv
+AAD = 01
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 08299c5102745aaa3a0c469fad9e075a
+Plaintext = 020000000000000000000000
+Ciphertext = 296c7889fd99f41917f44620
+
+
+Cipher = aes-128-gcm-siv
+AAD = 01
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 8f8936ec039e4e4bb97ebd8c4457441f
+Plaintext = 02000000000000000000000000000000
+Ciphertext = e2b0c5da79a901c1745f700525cb335b
+
+
+Cipher = aes-128-gcm-siv
+AAD = 01
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = e6af6a7f87287da059a71684ed3498e1
+Plaintext = 0200000000000000000000000000000003000000000000000000000000000000
+Ciphertext = 620048ef3c1e73e57e02bb8562c416a319e73e4caac8e96a1ecb2933145a1d71
+
+
+Cipher = aes-128-gcm-siv
+AAD = 01
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 6a8cc3865f76897c2e4b245cf31c51f2
+Plaintext = 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+Ciphertext = 50c8303ea93925d64090d07bd109dfd9515a5a33431019c17d93465999a8b0053201d723120a8562b838cdff25bf9d1e
+
+
+Cipher = aes-128-gcm-siv
+AAD = 01
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = cdc46ae475563de037001ef84ae21744
+Plaintext = 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+Ciphertext = 2f5c64059db55ee0fb847ed513003746aca4e61c711b5de2e7a77ffd02da42feec601910d3467bb8b36ebbaebce5fba30d36c95f48a3e7980f0e7ac299332a80
+
+
+Cipher = aes-128-gcm-siv
+AAD = 010000000000000000000000
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 07eb1f84fb28f8cb73de8e99e2f48a14
+Plaintext = 02000000
+Ciphertext = a8fe3e87
+
+
+Cipher = aes-128-gcm-siv
+AAD = 010000000000000000000000000000000200
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 24afc9805e976f451e6d87f6fe106514
+Plaintext = 0300000000000000000000000000000004000000
+Ciphertext = 6bb0fecf5ded9b77f902c7d5da236a4391dd0297
+
+
+Cipher = aes-128-gcm-siv
+AAD = 0100000000000000000000000000000002000000
+Key = 01000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = bff9b2ef00fb47920cc72a0c0f13b9fd
+Plaintext = 030000000000000000000000000000000400
+Ciphertext = 44d0aaf6fb2f1f34add5e8064e83e12a2ada
+
+Cipher = aes-128-gcm-siv
+AAD = 46bb91c3c5
+Key = 36864200e0eaf5284d884a0e77d31646
+IV = bae8e37fc83441b16034566b
+Tag = 711bd85bc1e4d3e0a462e074eea428a8
+Plaintext = 7a806c
+Ciphertext = af60eb
+
+
+Cipher = aes-128-gcm-siv
+AAD = fc880c94a95198874296
+Key = aedb64a6c590bc84d1a5e269e4b47801
+IV = afc0577e34699b9e671fdd4f
+Tag = d6a9c45545cfc11f03ad743dba20f966
+Plaintext = bdc66f146545
+Ciphertext = bb93a3e34d3c
+
+
+Cipher = aes-128-gcm-siv
+AAD = 046787f3ea22c127aaf195d1894728
+Key = d5cc1fd161320b6920ce07787f86743b
+IV = 275d1ab32f6d1f0434d8848c
+Tag = 1d02fd0cd174c84fc5dae2f60f52fd2b
+Plaintext = 1177441f195495860f
+Ciphertext = 4f37281f7ad12949d0
+
+
+Cipher = aes-128-gcm-siv
+AAD = c9882e5386fd9f92ec489c8fde2be2cf97e74e93
+Key = b3fed1473c528b8426a582995929a149
+IV = 9e9ad8780c8d63d0ab4149c0
+Tag = c1dc2f871fb7561da1286e655e24b7b0
+Plaintext = 9f572c614b4745914474e7c7
+Ciphertext = f54673c5ddf710c745641c8b
+
+
+Cipher = aes-128-gcm-siv
+AAD = 2950a70d5a1db2316fd568378da107b52b0da55210cc1c1b0a
+Key = 2d4ed87da44102952ef94b02b805249b
+IV = ac80e6f61455bfac8308a2d4
+Tag = 83b3449b9f39552de99dc214a1190b0b
+Plaintext = 0d8c8451178082355c9e940fea2f58
+Ciphertext = c9ff545e07b88a015f05b274540aa1
+
+
+Cipher = aes-128-gcm-siv
+AAD = 1860f762ebfbd08284e421702de0de18baa9c9596291b08466f37de21c7f
+Key = bde3b2f204d1e9f8b06bc47f9745b3d1
+IV = ae06556fb6aa7890bebc18fe
+Tag = 3e377094f04709f64d7b985310a4db84
+Plaintext = 6b3db4da3d57aa94842b9803a96e07fb6de7
+Ciphertext = 6298b296e24e8cc35dce0bed484b7f30d580
+
+
+Cipher = aes-128-gcm-siv
+AAD = 7576f7028ec6eb5ea7e298342a94d4b202b370ef9768ec6561c4fe6b7e7296fa859c21
+Key = f901cfe8a69615a93fdf7a98cad48179
+IV = 6245709fb18853f68d833640
+Tag = 2d15506c84a9edd65e13e9d24a2a6e70
+Plaintext = e42a3c02c25b64869e146d7b233987bddfc240871d
+Ciphertext = 391cc328d484a4f46406181bcd62efd9b3ee197d05
+
+
+# AES_256_GCM_SIV
+
+
+Cipher = aes-256-gcm-siv
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 843122130f7364b761e0b97427e3df28
+Plaintext = 0100000000000000
+Ciphertext = c2ef328e5c71c83b
+
+
+Cipher = aes-256-gcm-siv
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 8ca50da9ae6559e48fd10f6e5c9ca17e
+Plaintext = 010000000000000000000000
+Ciphertext = 9aab2aeb3faa0a34aea8e2b1
+
+
+Cipher = aes-256-gcm-siv
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = c9eac6fa700942702e90862383c6c366
+Plaintext = 01000000000000000000000000000000
+Ciphertext = 85a01b63025ba19b7fd3ddfc033b3e76
+
+
+Cipher = aes-256-gcm-siv
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = e819e63abcd020b006a976397632eb5d
+Plaintext = 0100000000000000000000000000000002000000000000000000000000000000
+Ciphertext = 4a6a9db4c8c6549201b9edb53006cba821ec9cf850948a7c86c68ac7539d027f
+
+
+Cipher = aes-256-gcm-siv
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 790bc96880a99ba804bd12c0e6a22cc4
+Plaintext = 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+Ciphertext = c00d121893a9fa603f48ccc1ca3c57ce7499245ea0046db16c53c7c66fe717e39cf6c748837b61f6ee3adcee17534ed5
+
+
+Cipher = aes-256-gcm-siv
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 112864c269fc0d9d88c61fa47e39aa08
+Plaintext = 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+Ciphertext = c2d5160a1f8683834910acdafc41fbb1632d4a353e8b905ec9a5499ac34f96c7e1049eb080883891a4db8caaa1f99dd004d80487540735234e3744512c6f90ce
+
+
+Cipher = aes-256-gcm-siv
+AAD = 01
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 91213f267e3b452f02d01ae33e4ec854
+Plaintext = 0200000000000000
+Ciphertext = 1de22967237a8132
+
+
+Cipher = aes-256-gcm-siv
+AAD = 01
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = c1a4a19ae800941ccdc57cc8413c277f
+Plaintext = 020000000000000000000000
+Ciphertext = 163d6f9cc1b346cd453a2e4c
+
+
+Cipher = aes-256-gcm-siv
+AAD = 01
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = b292d28ff61189e8e49f3875ef91aff7
+Plaintext = 02000000000000000000000000000000
+Ciphertext = c91545823cc24f17dbb0e9e807d5ec17
+
+
+Cipher = aes-256-gcm-siv
+AAD = 01
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = aea1bad12702e1965604374aab96dbbc
+Plaintext = 0200000000000000000000000000000003000000000000000000000000000000
+Ciphertext = 07dad364bfc2b9da89116d7bef6daaaf6f255510aa654f920ac81b94e8bad365
+
+
+Cipher = aes-256-gcm-siv
+AAD = 01
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 03332742b228c647173616cfd44c54eb
+Plaintext = 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+Ciphertext = c67a1f0f567a5198aa1fcc8e3f21314336f7f51ca8b1af61feac35a86416fa47fbca3b5f749cdf564527f2314f42fe25
+
+
+Cipher = aes-256-gcm-siv
+AAD = 01
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 5bde0285037c5de81e5b570a049b62a0
+Plaintext = 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+Ciphertext = 67fd45e126bfb9a79930c43aad2d36967d3f0e4d217c1e551f59727870beefc98cb933a8fce9de887b1e40799988db1fc3f91880ed405b2dd298318858467c89
+
+
+Cipher = aes-256-gcm-siv
+AAD = 010000000000000000000000
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = 1835e517741dfddccfa07fa4661b74cf
+Plaintext = 02000000
+Ciphertext = 22b3f4cd
+
+
+Cipher = aes-256-gcm-siv
+AAD = 010000000000000000000000000000000200
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = b879ad976d8242acc188ab59cabfe307
+Plaintext = 0300000000000000000000000000000004000000
+Ciphertext = 43dd0163cdb48f9fe3212bf61b201976067f342b
+
+
+Cipher = aes-256-gcm-siv
+AAD = 0100000000000000000000000000000002000000
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+IV = 030000000000000000000000
+Tag = cfcdf5042112aa29685c912fc2056543
+Plaintext = 030000000000000000000000000000000400
+Ciphertext = 462401724b5ce6588d5a54aae5375513a075
+
+Cipher = aes-256-gcm-siv
+AAD = 4fbdc66f14
+Key = bae8e37fc83441b16034566b7a806c46bb91c3c5aedb64a6c590bc84d1a5e269
+IV = e4b47801afc0577e34699b9e
+Tag = 93da9bb81333aee0c785b240d319719d
+Plaintext = 671fdd
+Ciphertext = 0eaccb
+
+
+Cipher = aes-256-gcm-siv
+AAD = 6787f3ea22c127aaf195
+Key = 6545fc880c94a95198874296d5cc1fd161320b6920ce07787f86743b275d1ab3
+IV = 2f6d1f0434d8848c1177441f
+Tag = 6b62b84dc40c84636a5ec12020ec8c2c
+Plaintext = 195495860f04
+Ciphertext = a254dad4f3f9
+
+
+Cipher = aes-256-gcm-siv
+AAD = 489c8fde2be2cf97e74e932d4ed87d
+Key = d1894728b3fed1473c528b8426a582995929a1499e9ad8780c8d63d0ab4149c0
+IV = 9f572c614b4745914474e7c7
+Tag = c0fd3dc6628dfe55ebb0b9fb2295c8c2
+Plaintext = c9882e5386fd9f92ec
+Ciphertext = 0df9e308678244c44b
+
+
+Cipher = aes-256-gcm-siv
+AAD = 0da55210cc1c1b0abde3b2f204d1e9f8b06bc47f
+Key = a44102952ef94b02b805249bac80e6f61455bfac8308a2d40d8c845117808235
+IV = 5c9e940fea2f582950a70d5a
+Tag = 404099c2587f64979f21826706d497d5
+Plaintext = 1db2316fd568378da107b52b
+Ciphertext = 8dbeb9f7255bf5769dd56692
+
+
+Cipher = aes-256-gcm-siv
+AAD = f37de21c7ff901cfe8a69615a93fdf7a98cad481796245709f
+Key = 9745b3d1ae06556fb6aa7890bebc18fe6b3db4da3d57aa94842b9803a96e07fb
+IV = 6de71860f762ebfbd08284e4
+Tag = b3080d28f6ebb5d3648ce97bd5ba67fd
+Plaintext = 21702de0de18baa9c9596291b08466
+Ciphertext = 793576dfa5c0f88729a7ed3c2f1bff
+
+
+Cipher = aes-256-gcm-siv
+AAD = 9c2159058b1f0fe91433a5bdc20e214eab7fecef4454a10ef0657df21ac7
+Key = b18853f68d833640e42a3c02c25b64869e146d7b233987bddfc240871d7576f7
+IV = 028ec6eb5ea7e298342a94d4
+Tag = 454fc2a154fea91f8363a39fec7d0a49
+Plaintext = b202b370ef9768ec6561c4fe6b7e7296fa85
+Ciphertext = 857e16a64915a787637687db4a9519635cdd
+
+
+Cipher = aes-256-gcm-siv
+AAD = 734320ccc9d9bbbb19cb81b2af4ecbc3e72834321f7aa0f70b7282b4f33df23f167541
+Key = 3c535de192eaed3822a2fbbe2ca9dfc88255e14a661b8aa82cc54236093bbc23
+IV = 688089e55540db1872504e1c
+Tag = 9d6c7029675b89eaf4ba1ded1a286594
+Plaintext = ced532ce4159b035277d4dfbb7db62968b13cd4eec
+Ciphertext = 626660c26ea6612fb17ad91e8e767639edd6c9faee
+
+# The tests in this section use AEAD_AES_256_GCM_SIV and are crafted to
+# test correct wrapping of the block counter.
+
+Cipher = aes-256-gcm-siv
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 000000000000000000000000
+Tag = ffffffff000000000000000000000000
+Plaintext = 000000000000000000000000000000004db923dc793ee6497c76dcc03a98e108
+Ciphertext = f3f80f2cf0cb2dd9c5984fcda908456cc537703b5ba70324a6793a7bf218d3ea
+
+
+Cipher = aes-256-gcm-siv
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 000000000000000000000000
+Tag = ffffffff000000000000000000000000
+Plaintext = eb3640277c7ffd1303c7a542d02d3e4c0000000000000000
+Ciphertext = 18ce4f0b8cb4d0cac65fea8f79257b20888e53e72299e56d
+
+