xref: /freebsd/sys/crypto/openssl/amd64/ossl_aes_gcm.c (revision 47d767dab54895f3ba8abac6ab2295797394659e)
19a3444d9SMark Johnston /*
29a3444d9SMark Johnston  * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved.
39a3444d9SMark Johnston  * Copyright (c) 2021, Intel Corporation. All Rights Reserved.
49a3444d9SMark Johnston  *
59a3444d9SMark Johnston  * Licensed under the Apache License 2.0 (the "License").  You may not use
69a3444d9SMark Johnston  * this file except in compliance with the License.  You can obtain a copy
79a3444d9SMark Johnston  * in the file LICENSE in the source distribution or at
89a3444d9SMark Johnston  * https://www.openssl.org/source/license.html
99a3444d9SMark Johnston  */
109a3444d9SMark Johnston 
119a3444d9SMark Johnston /*
129b1d8728SMark Johnston  * This file contains 2 AES-GCM wrapper implementations from OpenSSL, using
139b1d8728SMark Johnston  * AES-NI and VAES extensions respectively.  These were ported from
149b1d8728SMark Johnston  * cipher_aes_gcm_hw_aesni.inc and cipher_aes_gcm_hw_vaes_avx512.inc.  The
159b1d8728SMark Johnston  * AES-NI implementation makes use of a generic C implementation for partial
169b1d8728SMark Johnston  * blocks, ported from gcm128.c with OPENSSL_SMALL_FOOTPRINT defined.
179a3444d9SMark Johnston  */
189a3444d9SMark Johnston 
199a3444d9SMark Johnston #include <sys/endian.h>
209a3444d9SMark Johnston #include <sys/systm.h>
219a3444d9SMark Johnston 
229a3444d9SMark Johnston #include <crypto/openssl/ossl.h>
239a3444d9SMark Johnston #include <crypto/openssl/ossl_aes_gcm.h>
249a3444d9SMark Johnston #include <crypto/openssl/ossl_cipher.h>
259a3444d9SMark Johnston 
269a3444d9SMark Johnston #include <opencrypto/cryptodev.h>
279a3444d9SMark Johnston 
289a3444d9SMark Johnston _Static_assert(
299a3444d9SMark Johnston     sizeof(struct ossl_gcm_context) <= sizeof(struct ossl_cipher_context),
309a3444d9SMark Johnston     "ossl_gcm_context too large");
319a3444d9SMark Johnston 
329a3444d9SMark Johnston void aesni_set_encrypt_key(const void *key, int bits, void *ctx);
339a3444d9SMark Johnston 
349a3444d9SMark Johnston static void
gcm_init(struct ossl_gcm_context * ctx,const void * key,size_t keylen)359a3444d9SMark Johnston gcm_init(struct ossl_gcm_context *ctx, const void *key, size_t keylen)
369a3444d9SMark Johnston {
379a3444d9SMark Johnston 	KASSERT(keylen == 128 || keylen == 192 || keylen == 256,
389a3444d9SMark Johnston 	    ("%s: invalid key length %zu", __func__, keylen));
399a3444d9SMark Johnston 
409a3444d9SMark Johnston 	memset(&ctx->gcm, 0, sizeof(ctx->gcm));
419a3444d9SMark Johnston 	memset(&ctx->aes_ks, 0, sizeof(ctx->aes_ks));
429a3444d9SMark Johnston 	aesni_set_encrypt_key(key, keylen, &ctx->aes_ks);
439a3444d9SMark Johnston 	ctx->ops->init(ctx, key, keylen);
449a3444d9SMark Johnston }
459a3444d9SMark Johnston 
469a3444d9SMark Johnston static void
gcm_tag(struct ossl_gcm_context * ctx,unsigned char * tag,size_t len)479a3444d9SMark Johnston gcm_tag(struct ossl_gcm_context *ctx, unsigned char *tag, size_t len)
489a3444d9SMark Johnston {
499a3444d9SMark Johnston 	(void)ctx->ops->finish(ctx, NULL, 0);
509a3444d9SMark Johnston 	memcpy(tag, ctx->gcm.Xi.c, len);
519a3444d9SMark Johnston }
529a3444d9SMark Johnston 
539a3444d9SMark Johnston void ossl_gcm_gmult_avx512(uint64_t Xi[2], void *gcm128ctx);
549a3444d9SMark Johnston void ossl_aes_gcm_init_avx512(const void *ks, void *gcm128ctx);
559a3444d9SMark Johnston void ossl_aes_gcm_setiv_avx512(const void *ks, void *gcm128ctx,
569a3444d9SMark Johnston     const unsigned char *iv, size_t ivlen);
579a3444d9SMark Johnston void ossl_aes_gcm_update_aad_avx512(void *gcm128ctx, const unsigned char *aad,
589a3444d9SMark Johnston     size_t len);
599a3444d9SMark Johnston void ossl_aes_gcm_encrypt_avx512(const void *ks, void *gcm128ctx,
609a3444d9SMark Johnston     unsigned int *pblocklen, const unsigned char *in, size_t len,
619a3444d9SMark Johnston     unsigned char *out);
629a3444d9SMark Johnston void ossl_aes_gcm_decrypt_avx512(const void *ks, void *gcm128ctx,
639a3444d9SMark Johnston     unsigned int *pblocklen, const unsigned char *in, size_t len,
649a3444d9SMark Johnston     unsigned char *out);
659a3444d9SMark Johnston void ossl_aes_gcm_finalize_avx512(void *gcm128ctx, unsigned int pblocklen);
669a3444d9SMark Johnston 
679a3444d9SMark Johnston static void
gcm_init_avx512(struct ossl_gcm_context * ctx,const void * key,size_t keylen)689a3444d9SMark Johnston gcm_init_avx512(struct ossl_gcm_context *ctx, const void *key, size_t keylen)
699a3444d9SMark Johnston {
709a3444d9SMark Johnston 	ossl_aes_gcm_init_avx512(&ctx->aes_ks, &ctx->gcm);
719a3444d9SMark Johnston }
729a3444d9SMark Johnston 
739a3444d9SMark Johnston static void
gcm_setiv_avx512(struct ossl_gcm_context * ctx,const unsigned char * iv,size_t len)749a3444d9SMark Johnston gcm_setiv_avx512(struct ossl_gcm_context *ctx, const unsigned char *iv,
759a3444d9SMark Johnston     size_t len)
769a3444d9SMark Johnston {
779a3444d9SMark Johnston 	KASSERT(len == AES_GCM_IV_LEN,
789a3444d9SMark Johnston 	    ("%s: invalid IV length %zu", __func__, len));
799a3444d9SMark Johnston 
809a3444d9SMark Johnston 	ctx->gcm.Yi.u[0] = 0;		/* Current counter */
819a3444d9SMark Johnston 	ctx->gcm.Yi.u[1] = 0;
829a3444d9SMark Johnston 	ctx->gcm.Xi.u[0] = 0;		/* AAD hash */
839a3444d9SMark Johnston 	ctx->gcm.Xi.u[1] = 0;
849a3444d9SMark Johnston 	ctx->gcm.len.u[0] = 0;		/* AAD length */
859a3444d9SMark Johnston 	ctx->gcm.len.u[1] = 0;		/* Message length */
869a3444d9SMark Johnston 	ctx->gcm.ares = 0;
879a3444d9SMark Johnston 	ctx->gcm.mres = 0;
889a3444d9SMark Johnston 
899a3444d9SMark Johnston 	ossl_aes_gcm_setiv_avx512(&ctx->aes_ks, ctx, iv, len);
909a3444d9SMark Johnston }
919a3444d9SMark Johnston 
929a3444d9SMark Johnston static int
gcm_aad_avx512(struct ossl_gcm_context * ctx,const unsigned char * aad,size_t len)939a3444d9SMark Johnston gcm_aad_avx512(struct ossl_gcm_context *ctx, const unsigned char *aad,
949a3444d9SMark Johnston     size_t len)
959a3444d9SMark Johnston {
969a3444d9SMark Johnston 	uint64_t alen = ctx->gcm.len.u[0];
979a3444d9SMark Johnston 	size_t lenblks;
989a3444d9SMark Johnston 	unsigned int ares;
999a3444d9SMark Johnston 
1009a3444d9SMark Johnston 	/* Bad sequence: call of AAD update after message processing */
1019a3444d9SMark Johnston 	if (ctx->gcm.len.u[1])
1029a3444d9SMark Johnston 		return -2;
1039a3444d9SMark Johnston 
1049a3444d9SMark Johnston 	alen += len;
1059a3444d9SMark Johnston 	/* AAD is limited by 2^64 bits, thus 2^61 bytes */
1069a3444d9SMark Johnston 	if (alen > (1ull << 61) || (sizeof(len) == 8 && alen < len))
1079a3444d9SMark Johnston 		return -1;
1089a3444d9SMark Johnston 	ctx->gcm.len.u[0] = alen;
1099a3444d9SMark Johnston 
1109a3444d9SMark Johnston 	ares = ctx->gcm.ares;
1119a3444d9SMark Johnston 	/* Partial AAD block left from previous AAD update calls */
1129a3444d9SMark Johnston 	if (ares > 0) {
1139a3444d9SMark Johnston 		/*
1149a3444d9SMark Johnston 		 * Fill partial block buffer till full block
1159a3444d9SMark Johnston 		 * (note, the hash is stored reflected)
1169a3444d9SMark Johnston 		 */
1179a3444d9SMark Johnston 		while (ares > 0 && len > 0) {
1189a3444d9SMark Johnston 			ctx->gcm.Xi.c[15 - ares] ^= *(aad++);
1199a3444d9SMark Johnston 			--len;
1209a3444d9SMark Johnston 			ares = (ares + 1) % AES_BLOCK_LEN;
1219a3444d9SMark Johnston 		}
1229a3444d9SMark Johnston 		/* Full block gathered */
1239a3444d9SMark Johnston 		if (ares == 0) {
1249a3444d9SMark Johnston 			ossl_gcm_gmult_avx512(ctx->gcm.Xi.u, ctx);
1259a3444d9SMark Johnston 		} else { /* no more AAD */
1269a3444d9SMark Johnston 			ctx->gcm.ares = ares;
1279a3444d9SMark Johnston 			return 0;
1289a3444d9SMark Johnston 		}
1299a3444d9SMark Johnston 	}
1309a3444d9SMark Johnston 
1319a3444d9SMark Johnston 	/* Bulk AAD processing */
1329a3444d9SMark Johnston 	lenblks = len & ((size_t)(-AES_BLOCK_LEN));
1339a3444d9SMark Johnston 	if (lenblks > 0) {
1349a3444d9SMark Johnston 		ossl_aes_gcm_update_aad_avx512(ctx, aad, lenblks);
1359a3444d9SMark Johnston 		aad += lenblks;
1369a3444d9SMark Johnston 		len -= lenblks;
1379a3444d9SMark Johnston 	}
1389a3444d9SMark Johnston 
1399a3444d9SMark Johnston 	/* Add remaining AAD to the hash (note, the hash is stored reflected) */
1409a3444d9SMark Johnston 	if (len > 0) {
1419a3444d9SMark Johnston 		ares = (unsigned int)len;
1429a3444d9SMark Johnston 		for (size_t i = 0; i < len; ++i)
1439a3444d9SMark Johnston 			ctx->gcm.Xi.c[15 - i] ^= aad[i];
1449a3444d9SMark Johnston 	}
1459a3444d9SMark Johnston 
1469a3444d9SMark Johnston 	ctx->gcm.ares = ares;
1479a3444d9SMark Johnston 
1489a3444d9SMark Johnston 	return 0;
1499a3444d9SMark Johnston }
1509a3444d9SMark Johnston 
1519a3444d9SMark Johnston static int
_gcm_encrypt_avx512(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len,bool encrypt)1529a3444d9SMark Johnston _gcm_encrypt_avx512(struct ossl_gcm_context *ctx, const unsigned char *in,
1539a3444d9SMark Johnston     unsigned char *out, size_t len, bool encrypt)
1549a3444d9SMark Johnston {
1559a3444d9SMark Johnston 	uint64_t mlen = ctx->gcm.len.u[1];
1569a3444d9SMark Johnston 
1579a3444d9SMark Johnston 	mlen += len;
1589a3444d9SMark Johnston 	if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len))
1599a3444d9SMark Johnston 		return -1;
1609a3444d9SMark Johnston 
1619a3444d9SMark Johnston 	ctx->gcm.len.u[1] = mlen;
1629a3444d9SMark Johnston 
1639a3444d9SMark Johnston 	/* Finalize GHASH(AAD) if AAD partial blocks left unprocessed */
1649a3444d9SMark Johnston 	if (ctx->gcm.ares > 0) {
1659a3444d9SMark Johnston 		ossl_gcm_gmult_avx512(ctx->gcm.Xi.u, ctx);
1669a3444d9SMark Johnston 		ctx->gcm.ares = 0;
1679a3444d9SMark Johnston 	}
1689a3444d9SMark Johnston 
1699a3444d9SMark Johnston 	if (encrypt) {
1709a3444d9SMark Johnston 		ossl_aes_gcm_encrypt_avx512(&ctx->aes_ks, ctx, &ctx->gcm.mres,
1719a3444d9SMark Johnston 		    in, len, out);
1729a3444d9SMark Johnston 	} else {
1739a3444d9SMark Johnston 		ossl_aes_gcm_decrypt_avx512(&ctx->aes_ks, ctx, &ctx->gcm.mres,
1749a3444d9SMark Johnston 		    in, len, out);
1759a3444d9SMark Johnston 	}
1769a3444d9SMark Johnston 
1779a3444d9SMark Johnston 	return 0;
1789a3444d9SMark Johnston }
1799a3444d9SMark Johnston 
1809a3444d9SMark Johnston static int
gcm_encrypt_avx512(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)1819a3444d9SMark Johnston gcm_encrypt_avx512(struct ossl_gcm_context *ctx, const unsigned char *in,
1829a3444d9SMark Johnston     unsigned char *out, size_t len)
1839a3444d9SMark Johnston {
1849a3444d9SMark Johnston 	return _gcm_encrypt_avx512(ctx, in, out, len, true);
1859a3444d9SMark Johnston }
1869a3444d9SMark Johnston 
1879a3444d9SMark Johnston static int
gcm_decrypt_avx512(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)1889a3444d9SMark Johnston gcm_decrypt_avx512(struct ossl_gcm_context *ctx, const unsigned char *in,
1899a3444d9SMark Johnston     unsigned char *out, size_t len)
1909a3444d9SMark Johnston {
1919a3444d9SMark Johnston 	return _gcm_encrypt_avx512(ctx, in, out, len, false);
1929a3444d9SMark Johnston }
1939a3444d9SMark Johnston 
1949a3444d9SMark Johnston static int
gcm_finish_avx512(struct ossl_gcm_context * ctx,const unsigned char * tag,size_t len)1959a3444d9SMark Johnston gcm_finish_avx512(struct ossl_gcm_context *ctx, const unsigned char *tag,
1969a3444d9SMark Johnston     size_t len)
1979a3444d9SMark Johnston {
1989a3444d9SMark Johnston 	unsigned int *res = &ctx->gcm.mres;
1999a3444d9SMark Johnston 
2009a3444d9SMark Johnston 	/* Finalize AAD processing */
2019a3444d9SMark Johnston 	if (ctx->gcm.ares > 0)
2029a3444d9SMark Johnston 		res = &ctx->gcm.ares;
2039a3444d9SMark Johnston 
2049a3444d9SMark Johnston 	ossl_aes_gcm_finalize_avx512(ctx, *res);
2059a3444d9SMark Johnston 
2069a3444d9SMark Johnston 	ctx->gcm.ares = ctx->gcm.mres = 0;
2079a3444d9SMark Johnston 
2089a3444d9SMark Johnston 	if (tag != NULL)
2099a3444d9SMark Johnston 		return timingsafe_bcmp(ctx->gcm.Xi.c, tag, len);
2109a3444d9SMark Johnston 	return 0;
2119a3444d9SMark Johnston }
2129a3444d9SMark Johnston 
2139a3444d9SMark Johnston static const struct ossl_aes_gcm_ops gcm_ops_avx512 = {
2149a3444d9SMark Johnston 	.init = gcm_init_avx512,
2159a3444d9SMark Johnston 	.setiv = gcm_setiv_avx512,
2169a3444d9SMark Johnston 	.aad = gcm_aad_avx512,
2179a3444d9SMark Johnston 	.encrypt = gcm_encrypt_avx512,
2189a3444d9SMark Johnston 	.decrypt = gcm_decrypt_avx512,
2199a3444d9SMark Johnston 	.finish = gcm_finish_avx512,
2209a3444d9SMark Johnston 	.tag = gcm_tag,
2219a3444d9SMark Johnston };
2229a3444d9SMark Johnston 
2239b1d8728SMark Johnston size_t aesni_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
2249b1d8728SMark Johnston     const void *key, unsigned char ivec[16], uint64_t *Xi);
2259b1d8728SMark Johnston size_t aesni_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
2269b1d8728SMark Johnston     const void *key, unsigned char ivec[16], uint64_t *Xi);
2279b1d8728SMark Johnston void aesni_encrypt(const unsigned char *in, unsigned char *out, void *ks);
2289b1d8728SMark Johnston void aesni_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
2299b1d8728SMark Johnston     size_t blocks, void *ks, const unsigned char *iv);
2309b1d8728SMark Johnston 
2319b1d8728SMark Johnston void gcm_init_avx(__uint128_t Htable[16], uint64_t Xi[2]);
2329b1d8728SMark Johnston void gcm_gmult_avx(uint64_t Xi[2], const __uint128_t Htable[16]);
2339b1d8728SMark Johnston void gcm_ghash_avx(uint64_t Xi[2], const __uint128_t Htable[16], const void *in,
2349b1d8728SMark Johnston     size_t len);
2359b1d8728SMark Johnston 
2369b1d8728SMark Johnston static void
gcm_init_aesni(struct ossl_gcm_context * ctx,const void * key,size_t keylen)2379b1d8728SMark Johnston gcm_init_aesni(struct ossl_gcm_context *ctx, const void *key, size_t keylen)
2389b1d8728SMark Johnston {
2399b1d8728SMark Johnston 	aesni_encrypt(ctx->gcm.H.c, ctx->gcm.H.c, &ctx->aes_ks);
2409b1d8728SMark Johnston 
2419b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
2429b1d8728SMark Johnston 	ctx->gcm.H.u[0] = bswap64(ctx->gcm.H.u[0]);
2439b1d8728SMark Johnston 	ctx->gcm.H.u[1] = bswap64(ctx->gcm.H.u[1]);
2449b1d8728SMark Johnston #endif
2459b1d8728SMark Johnston 
2469b1d8728SMark Johnston 	gcm_init_avx(ctx->gcm.Htable, ctx->gcm.H.u);
2479b1d8728SMark Johnston }
2489b1d8728SMark Johnston 
2499b1d8728SMark Johnston static void
gcm_setiv_aesni(struct ossl_gcm_context * ctx,const unsigned char * iv,size_t len)2509b1d8728SMark Johnston gcm_setiv_aesni(struct ossl_gcm_context *ctx, const unsigned char *iv,
2519b1d8728SMark Johnston     size_t len)
2529b1d8728SMark Johnston {
2539b1d8728SMark Johnston 	uint32_t ctr;
2549b1d8728SMark Johnston 
2559b1d8728SMark Johnston 	KASSERT(len == AES_GCM_IV_LEN,
2569b1d8728SMark Johnston 	    ("%s: invalid IV length %zu", __func__, len));
2579b1d8728SMark Johnston 
2589b1d8728SMark Johnston 	ctx->gcm.len.u[0] = 0;
2599b1d8728SMark Johnston 	ctx->gcm.len.u[1] = 0;
2609b1d8728SMark Johnston 	ctx->gcm.ares = ctx->gcm.mres = 0;
2619b1d8728SMark Johnston 
2629b1d8728SMark Johnston 	memcpy(ctx->gcm.Yi.c, iv, len);
2639b1d8728SMark Johnston 	ctx->gcm.Yi.c[12] = 0;
2649b1d8728SMark Johnston 	ctx->gcm.Yi.c[13] = 0;
2659b1d8728SMark Johnston 	ctx->gcm.Yi.c[14] = 0;
2669b1d8728SMark Johnston 	ctx->gcm.Yi.c[15] = 1;
2679b1d8728SMark Johnston 	ctr = 1;
2689b1d8728SMark Johnston 
2699b1d8728SMark Johnston 	ctx->gcm.Xi.u[0] = 0;
2709b1d8728SMark Johnston 	ctx->gcm.Xi.u[1] = 0;
2719b1d8728SMark Johnston 
2729b1d8728SMark Johnston 	aesni_encrypt(ctx->gcm.Yi.c, ctx->gcm.EK0.c, &ctx->aes_ks);
2739b1d8728SMark Johnston 	ctr++;
2749b1d8728SMark Johnston 
2759b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
2769b1d8728SMark Johnston 	ctx->gcm.Yi.d[3] = bswap32(ctr);
2779b1d8728SMark Johnston #else
2789b1d8728SMark Johnston 	ctx->gcm.Yi.d[3] = ctr;
2799b1d8728SMark Johnston #endif
2809b1d8728SMark Johnston }
2819b1d8728SMark Johnston 
2829b1d8728SMark Johnston static int
gcm_aad_aesni(struct ossl_gcm_context * ctx,const unsigned char * aad,size_t len)2839b1d8728SMark Johnston gcm_aad_aesni(struct ossl_gcm_context *ctx, const unsigned char *aad,
2849b1d8728SMark Johnston     size_t len)
2859b1d8728SMark Johnston {
2869b1d8728SMark Johnston 	size_t i;
2879b1d8728SMark Johnston 	unsigned int n;
2889b1d8728SMark Johnston 	uint64_t alen = ctx->gcm.len.u[0];
2899b1d8728SMark Johnston 
2909b1d8728SMark Johnston 	if (ctx->gcm.len.u[1])
2919b1d8728SMark Johnston 		return -2;
2929b1d8728SMark Johnston 
2939b1d8728SMark Johnston 	alen += len;
2949b1d8728SMark Johnston 	if (alen > (1ull << 61) || (sizeof(len) == 8 && alen < len))
2959b1d8728SMark Johnston 		return -1;
2969b1d8728SMark Johnston 	ctx->gcm.len.u[0] = alen;
2979b1d8728SMark Johnston 
2989b1d8728SMark Johnston 	n = ctx->gcm.ares;
2999b1d8728SMark Johnston 	if (n) {
3009b1d8728SMark Johnston 		while (n && len) {
3019b1d8728SMark Johnston 			ctx->gcm.Xi.c[n] ^= *(aad++);
3029b1d8728SMark Johnston 			--len;
3039b1d8728SMark Johnston 			n = (n + 1) % 16;
3049b1d8728SMark Johnston 		}
3059b1d8728SMark Johnston 		if (n == 0)
3069b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
3079b1d8728SMark Johnston 		else {
3089b1d8728SMark Johnston 			ctx->gcm.ares = n;
3099b1d8728SMark Johnston 			return 0;
3109b1d8728SMark Johnston 		}
3119b1d8728SMark Johnston 	}
3129b1d8728SMark Johnston 	if ((i = (len & (size_t)-AES_BLOCK_LEN))) {
3139b1d8728SMark Johnston 		gcm_ghash_avx(ctx->gcm.Xi.u, ctx->gcm.Htable, aad, i);
3149b1d8728SMark Johnston 		aad += i;
3159b1d8728SMark Johnston 		len -= i;
3169b1d8728SMark Johnston 	}
3179b1d8728SMark Johnston 	if (len) {
3189b1d8728SMark Johnston 		n = (unsigned int)len;
3199b1d8728SMark Johnston 		for (i = 0; i < len; ++i)
3209b1d8728SMark Johnston 			ctx->gcm.Xi.c[i] ^= aad[i];
3219b1d8728SMark Johnston 	}
3229b1d8728SMark Johnston 
3239b1d8728SMark Johnston 	ctx->gcm.ares = n;
3249b1d8728SMark Johnston 	return 0;
3259b1d8728SMark Johnston }
3269b1d8728SMark Johnston 
3279b1d8728SMark Johnston static int
gcm_encrypt(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)3289b1d8728SMark Johnston gcm_encrypt(struct ossl_gcm_context *ctx, const unsigned char *in,
3299b1d8728SMark Johnston     unsigned char *out, size_t len)
3309b1d8728SMark Johnston {
3319b1d8728SMark Johnston 	unsigned int n, ctr, mres;
3329b1d8728SMark Johnston 	size_t i;
3339b1d8728SMark Johnston 	uint64_t mlen = ctx->gcm.len.u[1];
3349b1d8728SMark Johnston 
3359b1d8728SMark Johnston 	mlen += len;
3369b1d8728SMark Johnston 	if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len))
3379b1d8728SMark Johnston 		return -1;
3389b1d8728SMark Johnston 	ctx->gcm.len.u[1] = mlen;
3399b1d8728SMark Johnston 
3409b1d8728SMark Johnston 	mres = ctx->gcm.mres;
3419b1d8728SMark Johnston 
3429b1d8728SMark Johnston 	if (ctx->gcm.ares) {
3439b1d8728SMark Johnston 		/* First call to encrypt finalizes GHASH(AAD) */
3449b1d8728SMark Johnston 		gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
3459b1d8728SMark Johnston 		ctx->gcm.ares = 0;
3469b1d8728SMark Johnston 	}
3479b1d8728SMark Johnston 
3489b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
3499b1d8728SMark Johnston 	ctr = bswap32(ctx->gcm.Yi.d[3]);
3509b1d8728SMark Johnston #else
3519b1d8728SMark Johnston 	ctr = ctx->gcm.Yi.d[3];
3529b1d8728SMark Johnston #endif
3539b1d8728SMark Johnston 
3549b1d8728SMark Johnston 	n = mres % 16;
3559b1d8728SMark Johnston 	for (i = 0; i < len; ++i) {
3569b1d8728SMark Johnston 		if (n == 0) {
3579b1d8728SMark Johnston 			aesni_encrypt(ctx->gcm.Yi.c, ctx->gcm.EKi.c,
3589b1d8728SMark Johnston 			    &ctx->aes_ks);
3599b1d8728SMark Johnston 			++ctr;
3609b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
3619b1d8728SMark Johnston 			ctx->gcm.Yi.d[3] = bswap32(ctr);
3629b1d8728SMark Johnston #else
3639b1d8728SMark Johnston 			ctx->gcm.Yi.d[3] = ctr;
3649b1d8728SMark Johnston #endif
3659b1d8728SMark Johnston 		}
3669b1d8728SMark Johnston 		ctx->gcm.Xi.c[n] ^= out[i] = in[i] ^ ctx->gcm.EKi.c[n];
3679b1d8728SMark Johnston 		mres = n = (n + 1) % 16;
3689b1d8728SMark Johnston 		if (n == 0)
3699b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
3709b1d8728SMark Johnston 	}
3719b1d8728SMark Johnston 
3729b1d8728SMark Johnston 	ctx->gcm.mres = mres;
3739b1d8728SMark Johnston 	return 0;
3749b1d8728SMark Johnston }
3759b1d8728SMark Johnston 
3769b1d8728SMark Johnston static int
gcm_encrypt_ctr32(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)3779b1d8728SMark Johnston gcm_encrypt_ctr32(struct ossl_gcm_context *ctx, const unsigned char *in,
3789b1d8728SMark Johnston     unsigned char *out, size_t len)
3799b1d8728SMark Johnston {
3809b1d8728SMark Johnston 	unsigned int n, ctr, mres;
3819b1d8728SMark Johnston 	size_t i;
3829b1d8728SMark Johnston 	uint64_t mlen = ctx->gcm.len.u[1];
3839b1d8728SMark Johnston 
3849b1d8728SMark Johnston 	mlen += len;
3859b1d8728SMark Johnston 	if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len))
3869b1d8728SMark Johnston 		return -1;
3879b1d8728SMark Johnston 	ctx->gcm.len.u[1] = mlen;
3889b1d8728SMark Johnston 
3899b1d8728SMark Johnston 	mres = ctx->gcm.mres;
3909b1d8728SMark Johnston 
3919b1d8728SMark Johnston 	if (ctx->gcm.ares) {
3929b1d8728SMark Johnston 		/* First call to encrypt finalizes GHASH(AAD) */
3939b1d8728SMark Johnston 		gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
3949b1d8728SMark Johnston 		ctx->gcm.ares = 0;
3959b1d8728SMark Johnston 	}
3969b1d8728SMark Johnston 
3979b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
3989b1d8728SMark Johnston 	ctr = bswap32(ctx->gcm.Yi.d[3]);
3999b1d8728SMark Johnston #else
4009b1d8728SMark Johnston 	ctr = ctx->gcm.Yi.d[3];
4019b1d8728SMark Johnston #endif
4029b1d8728SMark Johnston 
4039b1d8728SMark Johnston 	n = mres % 16;
4049b1d8728SMark Johnston 	if (n) {
4059b1d8728SMark Johnston 		while (n && len) {
4069b1d8728SMark Johnston 			ctx->gcm.Xi.c[n] ^= *(out++) = *(in++) ^ ctx->gcm.EKi.c[n];
4079b1d8728SMark Johnston 			--len;
4089b1d8728SMark Johnston 			n = (n + 1) % 16;
4099b1d8728SMark Johnston 		}
4109b1d8728SMark Johnston 		if (n == 0) {
4119b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
4129b1d8728SMark Johnston 			mres = 0;
4139b1d8728SMark Johnston 		} else {
4149b1d8728SMark Johnston 			ctx->gcm.mres = n;
4159b1d8728SMark Johnston 			return 0;
4169b1d8728SMark Johnston 		}
4179b1d8728SMark Johnston 	}
4189b1d8728SMark Johnston 	if ((i = (len & (size_t)-16))) {
4199b1d8728SMark Johnston 		size_t j = i / 16;
4209b1d8728SMark Johnston 
4219b1d8728SMark Johnston 		aesni_ctr32_encrypt_blocks(in, out, j, &ctx->aes_ks, ctx->gcm.Yi.c);
4229b1d8728SMark Johnston 		ctr += (unsigned int)j;
4239b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
4249b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = bswap32(ctr);
4259b1d8728SMark Johnston #else
4269b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = ctr;
4279b1d8728SMark Johnston #endif
4289b1d8728SMark Johnston 		in += i;
4299b1d8728SMark Johnston 		len -= i;
4309b1d8728SMark Johnston 		while (j--) {
4319b1d8728SMark Johnston 			for (i = 0; i < 16; ++i)
4329b1d8728SMark Johnston 				ctx->gcm.Xi.c[i] ^= out[i];
4339b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
4349b1d8728SMark Johnston 			out += 16;
4359b1d8728SMark Johnston 		}
4369b1d8728SMark Johnston 	}
4379b1d8728SMark Johnston 	if (len) {
4389b1d8728SMark Johnston 		aesni_encrypt(ctx->gcm.Yi.c, ctx->gcm.EKi.c, &ctx->aes_ks);
4399b1d8728SMark Johnston 		++ctr;
4409b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
4419b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = bswap32(ctr);
4429b1d8728SMark Johnston #else
4439b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = ctr;
4449b1d8728SMark Johnston #endif
4459b1d8728SMark Johnston 		while (len--) {
4469b1d8728SMark Johnston 			ctx->gcm.Xi.c[mres++] ^= out[n] = in[n] ^ ctx->gcm.EKi.c[n];
4479b1d8728SMark Johnston 			++n;
4489b1d8728SMark Johnston 		}
4499b1d8728SMark Johnston 	}
4509b1d8728SMark Johnston 
4519b1d8728SMark Johnston 	ctx->gcm.mres = mres;
4529b1d8728SMark Johnston 	return 0;
4539b1d8728SMark Johnston }
4549b1d8728SMark Johnston 
4559b1d8728SMark Johnston static int
gcm_encrypt_aesni(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)4569b1d8728SMark Johnston gcm_encrypt_aesni(struct ossl_gcm_context *ctx, const unsigned char *in,
4579b1d8728SMark Johnston     unsigned char *out, size_t len)
4589b1d8728SMark Johnston {
4599b1d8728SMark Johnston 	size_t bulk = 0, res;
4609b1d8728SMark Johnston 	int error;
4619b1d8728SMark Johnston 
462*47d767daSMark Johnston 	res = MIN(len, (AES_BLOCK_LEN - ctx->gcm.mres) % AES_BLOCK_LEN);
4639b1d8728SMark Johnston 	if ((error = gcm_encrypt(ctx, in, out, res)) != 0)
4649b1d8728SMark Johnston 		return error;
4659b1d8728SMark Johnston 
4669b1d8728SMark Johnston 	bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
4679b1d8728SMark Johnston 	    &ctx->aes_ks, ctx->gcm.Yi.c, ctx->gcm.Xi.u);
4689b1d8728SMark Johnston 	ctx->gcm.len.u[1] += bulk;
4699b1d8728SMark Johnston 	bulk += res;
4709b1d8728SMark Johnston 
4719b1d8728SMark Johnston 	if ((error = gcm_encrypt_ctr32(ctx, in + bulk, out + bulk,
4729b1d8728SMark Johnston 	    len - bulk)) != 0)
4739b1d8728SMark Johnston 		return error;
4749b1d8728SMark Johnston 
4759b1d8728SMark Johnston 	return 0;
4769b1d8728SMark Johnston }
4779b1d8728SMark Johnston 
4789b1d8728SMark Johnston static int
gcm_decrypt(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)4799b1d8728SMark Johnston gcm_decrypt(struct ossl_gcm_context *ctx, const unsigned char *in,
4809b1d8728SMark Johnston     unsigned char *out, size_t len)
4819b1d8728SMark Johnston {
4829b1d8728SMark Johnston 	unsigned int n, ctr, mres;
4839b1d8728SMark Johnston 	size_t i;
4849b1d8728SMark Johnston 	uint64_t mlen = ctx->gcm.len.u[1];
4859b1d8728SMark Johnston 
4869b1d8728SMark Johnston 	mlen += len;
4879b1d8728SMark Johnston 	if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len))
4889b1d8728SMark Johnston 		return -1;
4899b1d8728SMark Johnston 	ctx->gcm.len.u[1] = mlen;
4909b1d8728SMark Johnston 
4919b1d8728SMark Johnston 	mres = ctx->gcm.mres;
4929b1d8728SMark Johnston 
4939b1d8728SMark Johnston 	if (ctx->gcm.ares) {
4949b1d8728SMark Johnston 		/* First call to encrypt finalizes GHASH(AAD) */
4959b1d8728SMark Johnston 		gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
4969b1d8728SMark Johnston 		ctx->gcm.ares = 0;
4979b1d8728SMark Johnston 	}
4989b1d8728SMark Johnston 
4999b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
5009b1d8728SMark Johnston 	ctr = bswap32(ctx->gcm.Yi.d[3]);
5019b1d8728SMark Johnston #else
5029b1d8728SMark Johnston 	ctr = ctx->gcm.Yi.d[3];
5039b1d8728SMark Johnston #endif
5049b1d8728SMark Johnston 
5059b1d8728SMark Johnston 	n = mres % 16;
5069b1d8728SMark Johnston 	for (i = 0; i < len; ++i) {
5079b1d8728SMark Johnston 		uint8_t c;
5089b1d8728SMark Johnston 		if (n == 0) {
5099b1d8728SMark Johnston 			aesni_encrypt(ctx->gcm.Yi.c, ctx->gcm.EKi.c,
5109b1d8728SMark Johnston 			    &ctx->aes_ks);
5119b1d8728SMark Johnston 			++ctr;
5129b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
5139b1d8728SMark Johnston 			ctx->gcm.Yi.d[3] = bswap32(ctr);
5149b1d8728SMark Johnston #else
5159b1d8728SMark Johnston 			ctx->gcm.Yi.d[3] = ctr;
5169b1d8728SMark Johnston #endif
5179b1d8728SMark Johnston 		}
5189b1d8728SMark Johnston 		c = in[i];
5199b1d8728SMark Johnston 		out[i] = c ^ ctx->gcm.EKi.c[n];
5209b1d8728SMark Johnston 		ctx->gcm.Xi.c[n] ^= c;
5219b1d8728SMark Johnston 		mres = n = (n + 1) % 16;
5229b1d8728SMark Johnston 		if (n == 0)
5239b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
5249b1d8728SMark Johnston 	}
5259b1d8728SMark Johnston 
5269b1d8728SMark Johnston 	ctx->gcm.mres = mres;
5279b1d8728SMark Johnston 	return 0;
5289b1d8728SMark Johnston }
5299b1d8728SMark Johnston 
5309b1d8728SMark Johnston static int
gcm_decrypt_ctr32(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)5319b1d8728SMark Johnston gcm_decrypt_ctr32(struct ossl_gcm_context *ctx, const unsigned char *in,
5329b1d8728SMark Johnston     unsigned char *out, size_t len)
5339b1d8728SMark Johnston {
5349b1d8728SMark Johnston 	unsigned int n, ctr, mres;
5359b1d8728SMark Johnston 	size_t i;
5369b1d8728SMark Johnston 	uint64_t mlen = ctx->gcm.len.u[1];
5379b1d8728SMark Johnston 
5389b1d8728SMark Johnston 	mlen += len;
5399b1d8728SMark Johnston 	if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len))
5409b1d8728SMark Johnston 		return -1;
5419b1d8728SMark Johnston 	ctx->gcm.len.u[1] = mlen;
5429b1d8728SMark Johnston 
5439b1d8728SMark Johnston 	mres = ctx->gcm.mres;
5449b1d8728SMark Johnston 
5459b1d8728SMark Johnston 	if (ctx->gcm.ares) {
5469b1d8728SMark Johnston 		/* First call to decrypt finalizes GHASH(AAD) */
5479b1d8728SMark Johnston 		gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
5489b1d8728SMark Johnston 		ctx->gcm.ares = 0;
5499b1d8728SMark Johnston 	}
5509b1d8728SMark Johnston 
5519b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
5529b1d8728SMark Johnston 	ctr = bswap32(ctx->gcm.Yi.d[3]);
5539b1d8728SMark Johnston #else
5549b1d8728SMark Johnston 	ctr = ctx->gcm.Yi.d[3];
5559b1d8728SMark Johnston #endif
5569b1d8728SMark Johnston 
5579b1d8728SMark Johnston 	n = mres % 16;
5589b1d8728SMark Johnston 	if (n) {
5599b1d8728SMark Johnston 		while (n && len) {
5609b1d8728SMark Johnston 			uint8_t c = *(in++);
5619b1d8728SMark Johnston 			*(out++) = c ^ ctx->gcm.EKi.c[n];
5629b1d8728SMark Johnston 			ctx->gcm.Xi.c[n] ^= c;
5639b1d8728SMark Johnston 			--len;
5649b1d8728SMark Johnston 			n = (n + 1) % 16;
5659b1d8728SMark Johnston 		}
5669b1d8728SMark Johnston 		if (n == 0) {
5679b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
5689b1d8728SMark Johnston 			mres = 0;
5699b1d8728SMark Johnston 		} else {
5709b1d8728SMark Johnston 			ctx->gcm.mres = n;
5719b1d8728SMark Johnston 			return 0;
5729b1d8728SMark Johnston 		}
5739b1d8728SMark Johnston 	}
5749b1d8728SMark Johnston 	if ((i = (len & (size_t)-16))) {
5759b1d8728SMark Johnston 		size_t j = i / 16;
5769b1d8728SMark Johnston 
5779b1d8728SMark Johnston 		while (j--) {
5789b1d8728SMark Johnston 			size_t k;
5799b1d8728SMark Johnston 			for (k = 0; k < 16; ++k)
5809b1d8728SMark Johnston 				ctx->gcm.Xi.c[k] ^= in[k];
5819b1d8728SMark Johnston 			gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
5829b1d8728SMark Johnston 			in += 16;
5839b1d8728SMark Johnston 		}
5849b1d8728SMark Johnston 		j = i / 16;
5859b1d8728SMark Johnston 		in -= i;
5869b1d8728SMark Johnston 		aesni_ctr32_encrypt_blocks(in, out, j, &ctx->aes_ks, ctx->gcm.Yi.c);
5879b1d8728SMark Johnston 		ctr += (unsigned int)j;
5889b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
5899b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = bswap32(ctr);
5909b1d8728SMark Johnston #else
5919b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = ctr;
5929b1d8728SMark Johnston #endif
5939b1d8728SMark Johnston 		out += i;
5949b1d8728SMark Johnston 		in += i;
5959b1d8728SMark Johnston 		len -= i;
5969b1d8728SMark Johnston 	}
5979b1d8728SMark Johnston 	if (len) {
5989b1d8728SMark Johnston 		aesni_encrypt(ctx->gcm.Yi.c, ctx->gcm.EKi.c, &ctx->aes_ks);
5999b1d8728SMark Johnston 		++ctr;
6009b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
6019b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = bswap32(ctr);
6029b1d8728SMark Johnston #else
6039b1d8728SMark Johnston 		ctx->gcm.Yi.d[3] = ctr;
6049b1d8728SMark Johnston #endif
6059b1d8728SMark Johnston 		while (len--) {
6069b1d8728SMark Johnston 			uint8_t c = in[n];
6079b1d8728SMark Johnston 			ctx->gcm.Xi.c[mres++] ^= c;
6089b1d8728SMark Johnston 			out[n] = c ^ ctx->gcm.EKi.c[n];
6099b1d8728SMark Johnston 			++n;
6109b1d8728SMark Johnston 		}
6119b1d8728SMark Johnston 	}
6129b1d8728SMark Johnston 
6139b1d8728SMark Johnston 	ctx->gcm.mres = mres;
6149b1d8728SMark Johnston 	return 0;
6159b1d8728SMark Johnston }
6169b1d8728SMark Johnston 
6179b1d8728SMark Johnston static int
gcm_decrypt_aesni(struct ossl_gcm_context * ctx,const unsigned char * in,unsigned char * out,size_t len)6189b1d8728SMark Johnston gcm_decrypt_aesni(struct ossl_gcm_context *ctx, const unsigned char *in,
6199b1d8728SMark Johnston     unsigned char *out, size_t len)
6209b1d8728SMark Johnston {
6219b1d8728SMark Johnston 	size_t bulk = 0, res;
6229b1d8728SMark Johnston 	int error;
6239b1d8728SMark Johnston 
624*47d767daSMark Johnston 	res = MIN(len, (AES_BLOCK_LEN - ctx->gcm.mres) % AES_BLOCK_LEN);
6259b1d8728SMark Johnston 	if ((error = gcm_decrypt(ctx, in, out, res)) != 0)
6269b1d8728SMark Johnston 		return error;
6279b1d8728SMark Johnston 
628*47d767daSMark Johnston 	bulk = aesni_gcm_decrypt(in + res, out + res, len - res, &ctx->aes_ks,
629*47d767daSMark Johnston 	    ctx->gcm.Yi.c, ctx->gcm.Xi.u);
6309b1d8728SMark Johnston 	ctx->gcm.len.u[1] += bulk;
6319b1d8728SMark Johnston 	bulk += res;
6329b1d8728SMark Johnston 
6339b1d8728SMark Johnston 	if ((error = gcm_decrypt_ctr32(ctx, in + bulk, out + bulk, len - bulk)) != 0)
6349b1d8728SMark Johnston 		return error;
6359b1d8728SMark Johnston 
6369b1d8728SMark Johnston 	return 0;
6379b1d8728SMark Johnston }
6389b1d8728SMark Johnston 
6399b1d8728SMark Johnston static int
gcm_finish_aesni(struct ossl_gcm_context * ctx,const unsigned char * tag,size_t len)6409b1d8728SMark Johnston gcm_finish_aesni(struct ossl_gcm_context *ctx, const unsigned char *tag,
6419b1d8728SMark Johnston     size_t len)
6429b1d8728SMark Johnston {
6439b1d8728SMark Johnston 	uint64_t alen = ctx->gcm.len.u[0] << 3;
6449b1d8728SMark Johnston 	uint64_t clen = ctx->gcm.len.u[1] << 3;
6459b1d8728SMark Johnston 
6469b1d8728SMark Johnston 	if (ctx->gcm.mres || ctx->gcm.ares)
6479b1d8728SMark Johnston 		gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
6489b1d8728SMark Johnston 
6499b1d8728SMark Johnston #if BYTE_ORDER == LITTLE_ENDIAN
6509b1d8728SMark Johnston 	alen = bswap64(alen);
6519b1d8728SMark Johnston 	clen = bswap64(clen);
6529b1d8728SMark Johnston #endif
6539b1d8728SMark Johnston 
6549b1d8728SMark Johnston 	ctx->gcm.Xi.u[0] ^= alen;
6559b1d8728SMark Johnston 	ctx->gcm.Xi.u[1] ^= clen;
6569b1d8728SMark Johnston 	gcm_gmult_avx(ctx->gcm.Xi.u, ctx->gcm.Htable);
6579b1d8728SMark Johnston 
6589b1d8728SMark Johnston 	ctx->gcm.Xi.u[0] ^= ctx->gcm.EK0.u[0];
6599b1d8728SMark Johnston 	ctx->gcm.Xi.u[1] ^= ctx->gcm.EK0.u[1];
6609b1d8728SMark Johnston 
6619b1d8728SMark Johnston 	if (tag != NULL)
6629b1d8728SMark Johnston 		return timingsafe_bcmp(ctx->gcm.Xi.c, tag, len);
6639b1d8728SMark Johnston 	return 0;
6649b1d8728SMark Johnston }
6659b1d8728SMark Johnston 
6669b1d8728SMark Johnston static const struct ossl_aes_gcm_ops gcm_ops_aesni = {
6679b1d8728SMark Johnston 	.init = gcm_init_aesni,
6689b1d8728SMark Johnston 	.setiv = gcm_setiv_aesni,
6699b1d8728SMark Johnston 	.aad = gcm_aad_aesni,
6709b1d8728SMark Johnston 	.encrypt = gcm_encrypt_aesni,
6719b1d8728SMark Johnston 	.decrypt = gcm_decrypt_aesni,
6729b1d8728SMark Johnston 	.finish = gcm_finish_aesni,
6739b1d8728SMark Johnston 	.tag = gcm_tag,
6749b1d8728SMark Johnston };
6759b1d8728SMark Johnston 
6769b1d8728SMark Johnston int ossl_aes_gcm_setkey_aesni(const unsigned char *key, int klen, void *_ctx);
6779b1d8728SMark Johnston 
6789b1d8728SMark Johnston int
ossl_aes_gcm_setkey_aesni(const unsigned char * key,int klen,void * _ctx)6799b1d8728SMark Johnston ossl_aes_gcm_setkey_aesni(const unsigned char *key, int klen,
6809b1d8728SMark Johnston     void *_ctx)
6819b1d8728SMark Johnston {
6829b1d8728SMark Johnston 	struct ossl_gcm_context *ctx;
6839b1d8728SMark Johnston 
6849b1d8728SMark Johnston 	ctx = _ctx;
6859b1d8728SMark Johnston 	ctx->ops = &gcm_ops_aesni;
6869b1d8728SMark Johnston 	gcm_init(ctx, key, klen);
6879b1d8728SMark Johnston 	return (0);
6889b1d8728SMark Johnston }
6899b1d8728SMark Johnston 
6909a3444d9SMark Johnston int ossl_aes_gcm_setkey_avx512(const unsigned char *key, int klen, void *_ctx);
6919a3444d9SMark Johnston 
6929a3444d9SMark Johnston int
ossl_aes_gcm_setkey_avx512(const unsigned char * key,int klen,void * _ctx)6939a3444d9SMark Johnston ossl_aes_gcm_setkey_avx512(const unsigned char *key, int klen,
6949a3444d9SMark Johnston     void *_ctx)
6959a3444d9SMark Johnston {
6969a3444d9SMark Johnston 	struct ossl_gcm_context *ctx;
6979a3444d9SMark Johnston 
6989a3444d9SMark Johnston 	ctx = _ctx;
6999a3444d9SMark Johnston 	ctx->ops = &gcm_ops_avx512;
7009a3444d9SMark Johnston 	gcm_init(ctx, key, klen);
7019a3444d9SMark Johnston 	return (0);
7029a3444d9SMark Johnston }
703