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