/*
 *   AES-128 and AES-CMAC (RFC 4493).
 *
 *   Portions Copyright RISC OS Developments 2026, credited to the RISC OS One Project.
 *   Original implementation placed in the public domain.
 *   Updated comments Copyright (c) RISC OS Developments 2026,
 *   licensed under CDDL-1.0.
 *
 *   SMB 3.x signs with AES-CMAC rather than the HMAC-SHA256 that SMB 2.x
 *   uses, so only the encryption direction is needed - CMAC never
 *   decrypts - and only the 128 bit key size.  Nothing else here wants a
 *   block cipher. The forward round now uses a 1 KiB lookup table to
 *   reduce the cost of signing and encrypting SMB3 packets on RISC OS.
 */

#ifndef __AES_H
#define __AES_H

#include <stdlib.h>

#define AES_BLOCKLEN (16)
#define AES_KEYLEN   (16)       /* 128 bit keys only */
#define AES_ROUNDS   (10)

typedef struct
{
    unsigned int round_key[(AES_ROUNDS + 1) * AES_BLOCKLEN / 4];
} aes_key_t;

typedef struct
{
    aes_key_t key;
    unsigned char k1[AES_BLOCKLEN], k2[AES_BLOCKLEN];
} aes_cmac_context_t;

void AESSetKey(aes_key_t *k, const unsigned char key[AES_KEYLEN]);

void AESEncryptBlock(const aes_key_t *k,
                     const unsigned char in[AES_BLOCKLEN],
                     unsigned char out[AES_BLOCKLEN]);

void aes_cmac(const unsigned char key[AES_KEYLEN],
              const void *data, size_t len,
              unsigned char mac[AES_BLOCKLEN]);

void aes_cmac_init(aes_cmac_context_t *ctx,
                   const unsigned char key[AES_KEYLEN]);
void aes_cmac_compute(const aes_cmac_context_t *ctx,
                      const void *data, size_t len,
                      unsigned char mac[AES_BLOCKLEN]);

void aes_ccm_encrypt(const unsigned char key[AES_KEYLEN],
                     const unsigned char *nonce, size_t nonce_len,
                     const unsigned char *aad, size_t aad_len,
                     unsigned char *data, size_t len,
                     unsigned char tag[AES_BLOCKLEN]);
/*
    Encrypt data in place and produce the tag that authenticates both it
    and the additional data.  The nonce must be shorter than a block; SMB
    3.0 and 3.0.2 use eleven bytes.
*/

int aes_ccm_decrypt(const unsigned char key[AES_KEYLEN],
                    const unsigned char *nonce, size_t nonce_len,
                    const unsigned char *aad, size_t aad_len,
                    unsigned char *data, size_t len,
                    const unsigned char tag[AES_BLOCKLEN]);
/*
    The reverse.  Returns non-zero if the tag was right; on zero the
    buffer holds whatever the wrong key produced and must be discarded.
*/

#endif
