Hi Ard, On 07/10/22 20:51, Ard Biesheuvel wrote: > Implement a minimal library version of GCM based on the existing library > implementations of AES and multiplication in GF(2^128). Using these > primitives, GCM can be implemented in a straight-forward manner. > > GCM has a couple of sharp edges, i.e., the amount of input data > processed with the same initialization vector (IV) should be capped to > protect the counter from 32-bit rollover (or carry), and the size of the > authentication tag should be fixed for a given key. [0] > > The former concern is addressed trivially, given that the function call > API uses 32-bit signed types for the input lengths. It is still up to > the caller to avoid IV reuse in general, but this is not something we > can police at the implementation level. > > As for the latter concern, let's make the authentication tag size part > of the key schedule, and only permit it to be configured as part of the > key expansion routine. > > Note that table based AES implementations are susceptible to known > plaintext timing attacks on the encryption key. The AES library already > attempts to mitigate this to some extent, but given that the counter > mode encryption used by GCM operates exclusively on known plaintext by > construction (the IV and therefore the initial counter value are known > to an attacker), let's take some extra care to mitigate this, by calling > the AES library with interrupts disabled. > > [0] https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38d.pdf > > Cc: "Nikunj A. Dadhania" <nikunj@xxxxxxx> > Link: https://lore.kernel.org/all/c6fb9b25-a4b6-2e4a-2dd1-63adda055a49@xxxxxxx/ > Signed-off-by: Ard Biesheuvel <ardb@xxxxxxxxxx> > --- > +/** > + * gcm_decrypt - Perform GCM decryption on a block of data > + * @ctx: The GCM key schedule > + * @dst: Pointer to the plaintext output buffer > + * @src: Pointer the ciphertext (may equal @dst for decryption in place) > + * @crypt_len: The size in bytes of the plaintext and ciphertext. > + * @assoc: Pointer to the associated data, > + * @assoc_len: The size in bytes of the associated data > + * @iv: The initialization vector (IV) to use for this block of data > + * (must be 12 bytes in size as per the GCM spec recommendation) > + * @authtag: The address of the buffer in memory where the authentication > + * tag is stored. > + * > + * Returns 0 on success, or -EBADMSG if the ciphertext failed authentication. > + * On failure, no plaintext will be returned. > + */ > +int __must_check gcm_decrypt(const struct gcm_ctx *ctx, u8 *dst, const u8 *src, > + int crypt_len, const u8 *assoc, int assoc_len, > + const u8 iv[GCM_AES_IV_SIZE], const u8 *authtag) > +{ > + u8 tagbuf[AES_BLOCK_SIZE]; > + __be32 ctr[4]; > + > + memcpy(ctr, iv, GCM_AES_IV_SIZE); > + > + gcm_mac(ctx, src, crypt_len, assoc, assoc_len, ctr, tagbuf); > + if (crypto_memneq(authtag, tagbuf, ctx->authsize)) { > + memzero_explicit(tagbuf, sizeof(tagbuf)); > + return -EBADMSG; > + } The gcm_mac computation seems to be broken in this version. When I receive the encrypted packet back from the security processor the authtag does not match. Will debug further and report back. > + gcm_crypt(ctx, dst, src, crypt_len, ctr); > + return 0; > +} > +EXPORT_SYMBOL(gcm_decrypt); > + > +MODULE_DESCRIPTION("Generic GCM library"); > +MODULE_AUTHOR("Ard Biesheuvel <ardb@xxxxxxxxxx>"); > +MODULE_LICENSE("GPL"); Regards Nikunj