1*9a3444d9SMark Johnston /* 2*9a3444d9SMark Johnston * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved. 3*9a3444d9SMark Johnston * Copyright (c) 2021, Intel Corporation. All Rights Reserved. 4*9a3444d9SMark Johnston * 5*9a3444d9SMark Johnston * Licensed under the Apache License 2.0 (the "License"). You may not use 6*9a3444d9SMark Johnston * this file except in compliance with the License. You can obtain a copy 7*9a3444d9SMark Johnston * in the file LICENSE in the source distribution or at 8*9a3444d9SMark Johnston * https://www.openssl.org/source/license.html 9*9a3444d9SMark Johnston */ 10*9a3444d9SMark Johnston 11*9a3444d9SMark Johnston /* 12*9a3444d9SMark Johnston * This file contains a AES-GCM wrapper implementation from OpenSSL 3.1, 13*9a3444d9SMark Johnston * targeting amd64 VAES extensions. This was ported from 14*9a3444d9SMark Johnston * cipher_aes_gcm_hw_vaes_avx512.inc. 15*9a3444d9SMark Johnston */ 16*9a3444d9SMark Johnston 17*9a3444d9SMark Johnston #include <sys/endian.h> 18*9a3444d9SMark Johnston #include <sys/systm.h> 19*9a3444d9SMark Johnston 20*9a3444d9SMark Johnston #include <crypto/openssl/ossl.h> 21*9a3444d9SMark Johnston #include <crypto/openssl/ossl_aes_gcm.h> 22*9a3444d9SMark Johnston #include <crypto/openssl/ossl_cipher.h> 23*9a3444d9SMark Johnston 24*9a3444d9SMark Johnston #include <opencrypto/cryptodev.h> 25*9a3444d9SMark Johnston 26*9a3444d9SMark Johnston _Static_assert( 27*9a3444d9SMark Johnston sizeof(struct ossl_gcm_context) <= sizeof(struct ossl_cipher_context), 28*9a3444d9SMark Johnston "ossl_gcm_context too large"); 29*9a3444d9SMark Johnston 30*9a3444d9SMark Johnston void aesni_set_encrypt_key(const void *key, int bits, void *ctx); 31*9a3444d9SMark Johnston 32*9a3444d9SMark Johnston static void 33*9a3444d9SMark Johnston gcm_init(struct ossl_gcm_context *ctx, const void *key, size_t keylen) 34*9a3444d9SMark Johnston { 35*9a3444d9SMark Johnston KASSERT(keylen == 128 || keylen == 192 || keylen == 256, 36*9a3444d9SMark Johnston ("%s: invalid key length %zu", __func__, keylen)); 37*9a3444d9SMark Johnston 38*9a3444d9SMark Johnston memset(&ctx->gcm, 0, sizeof(ctx->gcm)); 39*9a3444d9SMark Johnston memset(&ctx->aes_ks, 0, sizeof(ctx->aes_ks)); 40*9a3444d9SMark Johnston aesni_set_encrypt_key(key, keylen, &ctx->aes_ks); 41*9a3444d9SMark Johnston ctx->ops->init(ctx, key, keylen); 42*9a3444d9SMark Johnston } 43*9a3444d9SMark Johnston 44*9a3444d9SMark Johnston static void 45*9a3444d9SMark Johnston gcm_tag(struct ossl_gcm_context *ctx, unsigned char *tag, size_t len) 46*9a3444d9SMark Johnston { 47*9a3444d9SMark Johnston (void)ctx->ops->finish(ctx, NULL, 0); 48*9a3444d9SMark Johnston memcpy(tag, ctx->gcm.Xi.c, len); 49*9a3444d9SMark Johnston } 50*9a3444d9SMark Johnston 51*9a3444d9SMark Johnston void ossl_gcm_gmult_avx512(uint64_t Xi[2], void *gcm128ctx); 52*9a3444d9SMark Johnston void ossl_aes_gcm_init_avx512(const void *ks, void *gcm128ctx); 53*9a3444d9SMark Johnston void ossl_aes_gcm_setiv_avx512(const void *ks, void *gcm128ctx, 54*9a3444d9SMark Johnston const unsigned char *iv, size_t ivlen); 55*9a3444d9SMark Johnston void ossl_aes_gcm_update_aad_avx512(void *gcm128ctx, const unsigned char *aad, 56*9a3444d9SMark Johnston size_t len); 57*9a3444d9SMark Johnston void ossl_aes_gcm_encrypt_avx512(const void *ks, void *gcm128ctx, 58*9a3444d9SMark Johnston unsigned int *pblocklen, const unsigned char *in, size_t len, 59*9a3444d9SMark Johnston unsigned char *out); 60*9a3444d9SMark Johnston void ossl_aes_gcm_decrypt_avx512(const void *ks, void *gcm128ctx, 61*9a3444d9SMark Johnston unsigned int *pblocklen, const unsigned char *in, size_t len, 62*9a3444d9SMark Johnston unsigned char *out); 63*9a3444d9SMark Johnston void ossl_aes_gcm_finalize_avx512(void *gcm128ctx, unsigned int pblocklen); 64*9a3444d9SMark Johnston 65*9a3444d9SMark Johnston static void 66*9a3444d9SMark Johnston gcm_init_avx512(struct ossl_gcm_context *ctx, const void *key, size_t keylen) 67*9a3444d9SMark Johnston { 68*9a3444d9SMark Johnston ossl_aes_gcm_init_avx512(&ctx->aes_ks, &ctx->gcm); 69*9a3444d9SMark Johnston } 70*9a3444d9SMark Johnston 71*9a3444d9SMark Johnston static void 72*9a3444d9SMark Johnston gcm_setiv_avx512(struct ossl_gcm_context *ctx, const unsigned char *iv, 73*9a3444d9SMark Johnston size_t len) 74*9a3444d9SMark Johnston { 75*9a3444d9SMark Johnston KASSERT(len == AES_GCM_IV_LEN, 76*9a3444d9SMark Johnston ("%s: invalid IV length %zu", __func__, len)); 77*9a3444d9SMark Johnston 78*9a3444d9SMark Johnston ctx->gcm.Yi.u[0] = 0; /* Current counter */ 79*9a3444d9SMark Johnston ctx->gcm.Yi.u[1] = 0; 80*9a3444d9SMark Johnston ctx->gcm.Xi.u[0] = 0; /* AAD hash */ 81*9a3444d9SMark Johnston ctx->gcm.Xi.u[1] = 0; 82*9a3444d9SMark Johnston ctx->gcm.len.u[0] = 0; /* AAD length */ 83*9a3444d9SMark Johnston ctx->gcm.len.u[1] = 0; /* Message length */ 84*9a3444d9SMark Johnston ctx->gcm.ares = 0; 85*9a3444d9SMark Johnston ctx->gcm.mres = 0; 86*9a3444d9SMark Johnston 87*9a3444d9SMark Johnston ossl_aes_gcm_setiv_avx512(&ctx->aes_ks, ctx, iv, len); 88*9a3444d9SMark Johnston } 89*9a3444d9SMark Johnston 90*9a3444d9SMark Johnston static int 91*9a3444d9SMark Johnston gcm_aad_avx512(struct ossl_gcm_context *ctx, const unsigned char *aad, 92*9a3444d9SMark Johnston size_t len) 93*9a3444d9SMark Johnston { 94*9a3444d9SMark Johnston uint64_t alen = ctx->gcm.len.u[0]; 95*9a3444d9SMark Johnston size_t lenblks; 96*9a3444d9SMark Johnston unsigned int ares; 97*9a3444d9SMark Johnston 98*9a3444d9SMark Johnston /* Bad sequence: call of AAD update after message processing */ 99*9a3444d9SMark Johnston if (ctx->gcm.len.u[1]) 100*9a3444d9SMark Johnston return -2; 101*9a3444d9SMark Johnston 102*9a3444d9SMark Johnston alen += len; 103*9a3444d9SMark Johnston /* AAD is limited by 2^64 bits, thus 2^61 bytes */ 104*9a3444d9SMark Johnston if (alen > (1ull << 61) || (sizeof(len) == 8 && alen < len)) 105*9a3444d9SMark Johnston return -1; 106*9a3444d9SMark Johnston ctx->gcm.len.u[0] = alen; 107*9a3444d9SMark Johnston 108*9a3444d9SMark Johnston ares = ctx->gcm.ares; 109*9a3444d9SMark Johnston /* Partial AAD block left from previous AAD update calls */ 110*9a3444d9SMark Johnston if (ares > 0) { 111*9a3444d9SMark Johnston /* 112*9a3444d9SMark Johnston * Fill partial block buffer till full block 113*9a3444d9SMark Johnston * (note, the hash is stored reflected) 114*9a3444d9SMark Johnston */ 115*9a3444d9SMark Johnston while (ares > 0 && len > 0) { 116*9a3444d9SMark Johnston ctx->gcm.Xi.c[15 - ares] ^= *(aad++); 117*9a3444d9SMark Johnston --len; 118*9a3444d9SMark Johnston ares = (ares + 1) % AES_BLOCK_LEN; 119*9a3444d9SMark Johnston } 120*9a3444d9SMark Johnston /* Full block gathered */ 121*9a3444d9SMark Johnston if (ares == 0) { 122*9a3444d9SMark Johnston ossl_gcm_gmult_avx512(ctx->gcm.Xi.u, ctx); 123*9a3444d9SMark Johnston } else { /* no more AAD */ 124*9a3444d9SMark Johnston ctx->gcm.ares = ares; 125*9a3444d9SMark Johnston return 0; 126*9a3444d9SMark Johnston } 127*9a3444d9SMark Johnston } 128*9a3444d9SMark Johnston 129*9a3444d9SMark Johnston /* Bulk AAD processing */ 130*9a3444d9SMark Johnston lenblks = len & ((size_t)(-AES_BLOCK_LEN)); 131*9a3444d9SMark Johnston if (lenblks > 0) { 132*9a3444d9SMark Johnston ossl_aes_gcm_update_aad_avx512(ctx, aad, lenblks); 133*9a3444d9SMark Johnston aad += lenblks; 134*9a3444d9SMark Johnston len -= lenblks; 135*9a3444d9SMark Johnston } 136*9a3444d9SMark Johnston 137*9a3444d9SMark Johnston /* Add remaining AAD to the hash (note, the hash is stored reflected) */ 138*9a3444d9SMark Johnston if (len > 0) { 139*9a3444d9SMark Johnston ares = (unsigned int)len; 140*9a3444d9SMark Johnston for (size_t i = 0; i < len; ++i) 141*9a3444d9SMark Johnston ctx->gcm.Xi.c[15 - i] ^= aad[i]; 142*9a3444d9SMark Johnston } 143*9a3444d9SMark Johnston 144*9a3444d9SMark Johnston ctx->gcm.ares = ares; 145*9a3444d9SMark Johnston 146*9a3444d9SMark Johnston return 0; 147*9a3444d9SMark Johnston } 148*9a3444d9SMark Johnston 149*9a3444d9SMark Johnston static int 150*9a3444d9SMark Johnston _gcm_encrypt_avx512(struct ossl_gcm_context *ctx, const unsigned char *in, 151*9a3444d9SMark Johnston unsigned char *out, size_t len, bool encrypt) 152*9a3444d9SMark Johnston { 153*9a3444d9SMark Johnston uint64_t mlen = ctx->gcm.len.u[1]; 154*9a3444d9SMark Johnston 155*9a3444d9SMark Johnston mlen += len; 156*9a3444d9SMark Johnston if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len)) 157*9a3444d9SMark Johnston return -1; 158*9a3444d9SMark Johnston 159*9a3444d9SMark Johnston ctx->gcm.len.u[1] = mlen; 160*9a3444d9SMark Johnston 161*9a3444d9SMark Johnston /* Finalize GHASH(AAD) if AAD partial blocks left unprocessed */ 162*9a3444d9SMark Johnston if (ctx->gcm.ares > 0) { 163*9a3444d9SMark Johnston ossl_gcm_gmult_avx512(ctx->gcm.Xi.u, ctx); 164*9a3444d9SMark Johnston ctx->gcm.ares = 0; 165*9a3444d9SMark Johnston } 166*9a3444d9SMark Johnston 167*9a3444d9SMark Johnston if (encrypt) { 168*9a3444d9SMark Johnston ossl_aes_gcm_encrypt_avx512(&ctx->aes_ks, ctx, &ctx->gcm.mres, 169*9a3444d9SMark Johnston in, len, out); 170*9a3444d9SMark Johnston } else { 171*9a3444d9SMark Johnston ossl_aes_gcm_decrypt_avx512(&ctx->aes_ks, ctx, &ctx->gcm.mres, 172*9a3444d9SMark Johnston in, len, out); 173*9a3444d9SMark Johnston } 174*9a3444d9SMark Johnston 175*9a3444d9SMark Johnston return 0; 176*9a3444d9SMark Johnston } 177*9a3444d9SMark Johnston 178*9a3444d9SMark Johnston static int 179*9a3444d9SMark Johnston gcm_encrypt_avx512(struct ossl_gcm_context *ctx, const unsigned char *in, 180*9a3444d9SMark Johnston unsigned char *out, size_t len) 181*9a3444d9SMark Johnston { 182*9a3444d9SMark Johnston return _gcm_encrypt_avx512(ctx, in, out, len, true); 183*9a3444d9SMark Johnston } 184*9a3444d9SMark Johnston 185*9a3444d9SMark Johnston static int 186*9a3444d9SMark Johnston gcm_decrypt_avx512(struct ossl_gcm_context *ctx, const unsigned char *in, 187*9a3444d9SMark Johnston unsigned char *out, size_t len) 188*9a3444d9SMark Johnston { 189*9a3444d9SMark Johnston return _gcm_encrypt_avx512(ctx, in, out, len, false); 190*9a3444d9SMark Johnston } 191*9a3444d9SMark Johnston 192*9a3444d9SMark Johnston static int 193*9a3444d9SMark Johnston gcm_finish_avx512(struct ossl_gcm_context *ctx, const unsigned char *tag, 194*9a3444d9SMark Johnston size_t len) 195*9a3444d9SMark Johnston { 196*9a3444d9SMark Johnston unsigned int *res = &ctx->gcm.mres; 197*9a3444d9SMark Johnston 198*9a3444d9SMark Johnston /* Finalize AAD processing */ 199*9a3444d9SMark Johnston if (ctx->gcm.ares > 0) 200*9a3444d9SMark Johnston res = &ctx->gcm.ares; 201*9a3444d9SMark Johnston 202*9a3444d9SMark Johnston ossl_aes_gcm_finalize_avx512(ctx, *res); 203*9a3444d9SMark Johnston 204*9a3444d9SMark Johnston ctx->gcm.ares = ctx->gcm.mres = 0; 205*9a3444d9SMark Johnston 206*9a3444d9SMark Johnston if (tag != NULL) 207*9a3444d9SMark Johnston return timingsafe_bcmp(ctx->gcm.Xi.c, tag, len); 208*9a3444d9SMark Johnston return 0; 209*9a3444d9SMark Johnston } 210*9a3444d9SMark Johnston 211*9a3444d9SMark Johnston static const struct ossl_aes_gcm_ops gcm_ops_avx512 = { 212*9a3444d9SMark Johnston .init = gcm_init_avx512, 213*9a3444d9SMark Johnston .setiv = gcm_setiv_avx512, 214*9a3444d9SMark Johnston .aad = gcm_aad_avx512, 215*9a3444d9SMark Johnston .encrypt = gcm_encrypt_avx512, 216*9a3444d9SMark Johnston .decrypt = gcm_decrypt_avx512, 217*9a3444d9SMark Johnston .finish = gcm_finish_avx512, 218*9a3444d9SMark Johnston .tag = gcm_tag, 219*9a3444d9SMark Johnston }; 220*9a3444d9SMark Johnston 221*9a3444d9SMark Johnston int ossl_aes_gcm_setkey_avx512(const unsigned char *key, int klen, void *_ctx); 222*9a3444d9SMark Johnston 223*9a3444d9SMark Johnston int 224*9a3444d9SMark Johnston ossl_aes_gcm_setkey_avx512(const unsigned char *key, int klen, 225*9a3444d9SMark Johnston void *_ctx) 226*9a3444d9SMark Johnston { 227*9a3444d9SMark Johnston struct ossl_gcm_context *ctx; 228*9a3444d9SMark Johnston 229*9a3444d9SMark Johnston ctx = _ctx; 230*9a3444d9SMark Johnston ctx->ops = &gcm_ops_avx512; 231*9a3444d9SMark Johnston gcm_init(ctx, key, klen); 232*9a3444d9SMark Johnston return (0); 233*9a3444d9SMark Johnston } 234