Path: blob/main/sys/crypto/openssl/arm/ossl_aes_gcm_neon.c
39488 views
/*1* Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <sys/types.h>10#include <sys/endian.h>11#include <sys/systm.h>1213#include <crypto/openssl/ossl.h>14#include <crypto/openssl/ossl_arm.h>15#include <crypto/openssl/ossl_aes_gcm.h>16#include <crypto/openssl/ossl_cipher.h>17#include <crypto/openssl/arm_arch.h>1819#include <opencrypto/cryptodev.h>2021_Static_assert(22sizeof(struct ossl_gcm_context) <= sizeof(struct ossl_cipher_context),23"ossl_gcm_context too large");2425void AES_encrypt(const void *in, void *out, const void *ks);26void AES_set_encrypt_key(const void *key, int keylen, void *ks);2728void gcm_init_neon(__uint128_t Htable[16], const uint64_t Xi[2]);29void gcm_gmult_neon(uint64_t Xi[2], const __uint128_t Htable[16]);30void gcm_ghash_neon(uint64_t Xi[2], const __uint128_t Htable[16],31const void *in, size_t len);3233void ossl_bsaes_ctr32_encrypt_blocks(const unsigned char *in,34unsigned char *out, size_t blocks, void *ks, const unsigned char *iv);3536static void37gcm_init(struct ossl_gcm_context *ctx, const void *key, size_t keylen)38{39memset(&ctx->gcm, 0, sizeof(ctx->gcm));40memset(&ctx->aes_ks, 0, sizeof(ctx->aes_ks));4142AES_set_encrypt_key(key, keylen, &ctx->aes_ks);43AES_encrypt(ctx->gcm.H.c, ctx->gcm.H.c, &ctx->aes_ks);4445#if BYTE_ORDER == LITTLE_ENDIAN46ctx->gcm.H.u[0] = bswap64(ctx->gcm.H.u[0]);47ctx->gcm.H.u[1] = bswap64(ctx->gcm.H.u[1]);48#endif4950gcm_init_neon(ctx->gcm.Htable, ctx->gcm.H.u);51}5253static void54gcm_setiv(struct ossl_gcm_context *ctx, const unsigned char *iv, size_t len)55{56uint32_t ctr;5758KASSERT(len == AES_GCM_IV_LEN,59("%s: invalid IV length %zu", __func__, len));6061ctx->gcm.len.u[0] = 0;62ctx->gcm.len.u[1] = 0;63ctx->gcm.ares = ctx->gcm.mres = 0;6465memcpy(ctx->gcm.Yi.c, iv, len);66ctx->gcm.Yi.c[12] = 0;67ctx->gcm.Yi.c[13] = 0;68ctx->gcm.Yi.c[14] = 0;69ctx->gcm.Yi.c[15] = 1;70ctr = 1;7172ctx->gcm.Xi.u[0] = 0;73ctx->gcm.Xi.u[1] = 0;7475AES_encrypt(ctx->gcm.Yi.c, ctx->gcm.EK0.c, &ctx->aes_ks);76ctr++;7778#if BYTE_ORDER == LITTLE_ENDIAN79ctx->gcm.Yi.d[3] = bswap32(ctr);80#else81ctx->gcm.Yi.d[3] = ctr;82#endif83}8485static int86gcm_finish(struct ossl_gcm_context *ctx, const unsigned char *tag, size_t len)87{88uint64_t alen = ctx->gcm.len.u[0] << 3;89uint64_t clen = ctx->gcm.len.u[1] << 3;9091if (ctx->gcm.mres || ctx->gcm.ares)92gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);9394#if BYTE_ORDER == LITTLE_ENDIAN95alen = bswap64(alen);96clen = bswap64(clen);97#endif9899ctx->gcm.Xi.u[0] ^= alen;100ctx->gcm.Xi.u[1] ^= clen;101gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);102103ctx->gcm.Xi.u[0] ^= ctx->gcm.EK0.u[0];104ctx->gcm.Xi.u[1] ^= ctx->gcm.EK0.u[1];105106if (tag != NULL)107return timingsafe_bcmp(ctx->gcm.Xi.c, tag, len);108return 0;109}110111static int112gcm_aad(struct ossl_gcm_context *ctx, const unsigned char *aad, size_t len)113{114size_t i;115unsigned int n;116uint64_t alen = ctx->gcm.len.u[0];117118if (ctx->gcm.len.u[1])119return -2;120121alen += len;122if (alen > ((uint64_t)1 << 61) || (sizeof(len) == 8 && alen < len))123return -1;124ctx->gcm.len.u[0] = alen;125126n = ctx->gcm.ares;127if (n) {128while (n && len) {129ctx->gcm.Xi.c[n] ^= *(aad++);130--len;131n = (n + 1) % 16;132}133if (n == 0)134gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);135else {136ctx->gcm.ares = n;137return 0;138}139}140if ((i = (len & (size_t)-AES_BLOCK_LEN))) {141gcm_ghash_neon(ctx->gcm.Xi.u, ctx->gcm.Htable, aad, i);142aad += i;143len -= i;144}145if (len) {146n = (unsigned int)len;147for (i = 0; i < len; ++i)148ctx->gcm.Xi.c[i] ^= aad[i];149}150151ctx->gcm.ares = n;152return 0;153}154155static int156gcm_encrypt(struct ossl_gcm_context *ctx, const unsigned char *in,157unsigned char *out, size_t len)158{159struct bsaes_key bsks;160unsigned int n, ctr, mres;161size_t i;162uint64_t mlen = ctx->gcm.len.u[1];163164mlen += len;165if (mlen > (((uint64_t)1 << 36) - 32) ||166(sizeof(len) == 8 && mlen < len))167return -1;168ctx->gcm.len.u[1] = mlen;169170mres = ctx->gcm.mres;171172if (ctx->gcm.ares) {173/* First call to encrypt finalizes GHASH(AAD) */174gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);175ctx->gcm.ares = 0;176}177178#if BYTE_ORDER == LITTLE_ENDIAN179ctr = bswap32(ctx->gcm.Yi.d[3]);180#else181ctr = ctx->gcm.Yi.d[3];182#endif183184n = mres % 16;185if (n) {186while (n && len) {187ctx->gcm.Xi.c[n] ^= *(out++) = *(in++) ^ ctx->gcm.EKi.c[n];188--len;189n = (n + 1) % 16;190}191if (n == 0) {192gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);193mres = 0;194} else {195ctx->gcm.mres = n;196return 0;197}198}199if ((i = (len & (size_t)-16))) {200size_t j = i / 16;201202memcpy(&bsks.ks, &ctx->aes_ks, sizeof(bsks.ks));203bsks.converted = 0;204ossl_bsaes_ctr32_encrypt_blocks(in, out, j, &bsks,205ctx->gcm.Yi.c);206ctr += (unsigned int)j;207#if BYTE_ORDER == LITTLE_ENDIAN208ctx->gcm.Yi.d[3] = bswap32(ctr);209#else210ctx->gcm.Yi.d[3] = ctr;211#endif212in += i;213len -= i;214while (j--) {215for (i = 0; i < 16; ++i)216ctx->gcm.Xi.c[i] ^= out[i];217gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);218out += 16;219}220}221if (len) {222AES_encrypt(ctx->gcm.Yi.c, ctx->gcm.EKi.c, &ctx->aes_ks);223++ctr;224#if BYTE_ORDER == LITTLE_ENDIAN225ctx->gcm.Yi.d[3] = bswap32(ctr);226#else227ctx->gcm.Yi.d[3] = ctr;228#endif229while (len--) {230ctx->gcm.Xi.c[mres++] ^= out[n] = in[n] ^ ctx->gcm.EKi.c[n];231++n;232}233}234235ctx->gcm.mres = mres;236return 0;237}238239static int240gcm_decrypt(struct ossl_gcm_context *ctx, const unsigned char *in,241unsigned char *out, size_t len)242{243struct bsaes_key bsks;244unsigned int n, ctr, mres;245size_t i;246uint64_t mlen = ctx->gcm.len.u[1];247248mlen += len;249if (mlen > ((1ull << 36) - 32) || (sizeof(len) == 8 && mlen < len))250return -1;251ctx->gcm.len.u[1] = mlen;252253mres = ctx->gcm.mres;254255if (ctx->gcm.ares) {256/* First call to decrypt finalizes GHASH(AAD) */257gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);258ctx->gcm.ares = 0;259}260261#if BYTE_ORDER == LITTLE_ENDIAN262ctr = bswap32(ctx->gcm.Yi.d[3]);263#else264ctr = ctx->gcm.Yi.d[3];265#endif266267n = mres % 16;268if (n) {269while (n && len) {270uint8_t c = *(in++);271*(out++) = c ^ ctx->gcm.EKi.c[n];272ctx->gcm.Xi.c[n] ^= c;273--len;274n = (n + 1) % 16;275}276if (n == 0) {277gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);278mres = 0;279} else {280ctx->gcm.mres = n;281return 0;282}283}284if ((i = (len & (size_t)-16))) {285size_t j = i / 16;286287while (j--) {288size_t k;289for (k = 0; k < 16; ++k)290ctx->gcm.Xi.c[k] ^= in[k];291gcm_gmult_neon(ctx->gcm.Xi.u, ctx->gcm.Htable);292in += 16;293}294j = i / 16;295in -= i;296memcpy(&bsks.ks, &ctx->aes_ks, sizeof(bsks.ks));297bsks.converted = 0;298ossl_bsaes_ctr32_encrypt_blocks(in, out, j, &bsks,299ctx->gcm.Yi.c);300ctr += (unsigned int)j;301#if BYTE_ORDER == LITTLE_ENDIAN302ctx->gcm.Yi.d[3] = bswap32(ctr);303#else304ctx->gcm.Yi.d[3] = ctr;305#endif306out += i;307in += i;308len -= i;309}310if (len) {311AES_encrypt(ctx->gcm.Yi.c, ctx->gcm.EKi.c, &ctx->aes_ks);312++ctr;313#if BYTE_ORDER == LITTLE_ENDIAN314ctx->gcm.Yi.d[3] = bswap32(ctr);315#else316ctx->gcm.Yi.d[3] = ctr;317#endif318while (len--) {319uint8_t c = in[n];320ctx->gcm.Xi.c[mres++] ^= c;321out[n] = c ^ ctx->gcm.EKi.c[n];322++n;323}324}325326ctx->gcm.mres = mres;327return 0;328}329330static void331gcm_tag(struct ossl_gcm_context *ctx, unsigned char *tag, size_t len)332{333gcm_finish(ctx, NULL, 0);334memcpy(tag, ctx->gcm.Xi.c, len);335}336337static const struct ossl_aes_gcm_ops gcm_ops_neon = {338.init = gcm_init,339.setiv = gcm_setiv,340.aad = gcm_aad,341.encrypt = gcm_encrypt,342.decrypt = gcm_decrypt,343.finish = gcm_finish,344.tag = gcm_tag,345};346347int ossl_aes_gcm_setkey(const unsigned char *key, int klen, void *_ctx);348349int350ossl_aes_gcm_setkey(const unsigned char *key, int klen, void *_ctx)351{352struct ossl_gcm_context *ctx;353354ctx = _ctx;355ctx->ops = &gcm_ops_neon;356gcm_init(ctx, key, klen);357return (0);358}359360361