// SPDX-License-Identifier: ISC /* * Copyright (c) 2010 Mike Belopuhov * Copyright (c) 2017, Linaro Limited * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "aes-gcm-private.h" /* * gfmul() is based on ghash_gfmul() from * https://github.com/openbsd/src/blob/master/sys/crypto/gmac.c */ static void gfmul(const uint64_t X[2], const uint64_t Y[2], uint64_t product[2]) { uint64_t y[2]; uint64_t z[2] = { 0 }; const uint8_t *x = (const uint8_t *)X; uint32_t mul; size_t n; y[0] = TEE_U64_FROM_BIG_ENDIAN(Y[0]); y[1] = TEE_U64_FROM_BIG_ENDIAN(Y[1]); for (n = 0; n < TEE_AES_BLOCK_SIZE * 8; n++) { /* update Z */ if (x[n >> 3] & (1 << (~n & 7))) internal_aes_gcm_xor_block(z, y); /* update Y */ mul = y[1] & 1; y[1] = (y[0] << 63) | (y[1] >> 1); y[0] = (y[0] >> 1) ^ (0xe100000000000000 * mul); } product[0] = TEE_U64_TO_BIG_ENDIAN(z[0]); product[1] = TEE_U64_TO_BIG_ENDIAN(z[1]); } void internal_aes_gcm_ghash_update_block(struct internal_aes_gcm_state *state, const void *data) { void *y = state->hash_state; internal_aes_gcm_xor_block(y, data); gfmul((void *)state->hash_subkey, y, y); }