/* SPDX-License-Identifier: GPL-2.0 */


#ifndef _CRYPTO_AES_H
#define _CRYPTO_AES_H

#include <linux/types.h>
#include <linux/crypto.h>

#define AES_MIN_KEY_SIZE	16
#define AES_MAX_KEY_SIZE	32
#define AES_KEYSIZE_128		16
#define AES_KEYSIZE_192		24
#define AES_KEYSIZE_256		32
#define AES_BLOCK_SIZE		16
#define AES_MAX_KEYLENGTH	(15 * 16)
#define AES_MAX_KEYLENGTH_U32	(AES_MAX_KEYLENGTH / sizeof(u32))


struct p8_aes_key {
	u32 rndkeys[AES_MAX_KEYLENGTH_U32];
	int nrounds;
};

union aes_enckey_arch {
	u32 rndkeys[AES_MAX_KEYLENGTH_U32];
#ifdef CONFIG_CRYPTO_LIB_AES_ARCH
#if defined(CONFIG_PPC) && defined(CONFIG_SPE)
	
	u32 spe_enc_key[AES_MAX_KEYLENGTH_U32] __aligned(8);
#elif defined(CONFIG_PPC)
	
	struct p8_aes_key p8;
#elif defined(CONFIG_S390)
	
	u8 raw_key[AES_MAX_KEY_SIZE];
#elif defined(CONFIG_SPARC64)
	
	u64 sparc_rndkeys[AES_MAX_KEYLENGTH / sizeof(u64)];
#endif
#endif 
};

union aes_invkey_arch {
	u32 inv_rndkeys[AES_MAX_KEYLENGTH_U32];
#ifdef CONFIG_CRYPTO_LIB_AES_ARCH
#if defined(CONFIG_PPC) && defined(CONFIG_SPE)
	
	u32 spe_dec_key[AES_MAX_KEYLENGTH_U32] __aligned(8);
#elif defined(CONFIG_PPC)
	
	struct p8_aes_key p8;
#endif
#endif 
};


struct aes_enckey {
	u32 len;
	u32 nrounds;
	u32 padding[2];
	union aes_enckey_arch k;
};


struct aes_key {
	struct aes_enckey; 
	union aes_invkey_arch inv_k;
};


struct crypto_aes_ctx {
	u32 key_enc[AES_MAX_KEYLENGTH_U32];
	u32 key_dec[AES_MAX_KEYLENGTH_U32];
	u32 key_length;
};


static inline int aes_check_keylen(size_t keylen)
{
	switch (keylen) {
	case AES_KEYSIZE_128:
	case AES_KEYSIZE_192:
	case AES_KEYSIZE_256:
		break;
	default:
		return -EINVAL;
	}

	return 0;
}


int aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
		  unsigned int key_len);


#ifdef CONFIG_ARM64
int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
		     unsigned int key_len);
#elif defined(CONFIG_PPC)
void ppc_expand_key_128(u32 *key_enc, const u8 *key);
void ppc_expand_key_192(u32 *key_enc, const u8 *key);
void ppc_expand_key_256(u32 *key_enc, const u8 *key);
void ppc_generate_decrypt_key(u32 *key_dec, u32 *key_enc, unsigned int key_len);
void ppc_encrypt_ecb(u8 *out, const u8 *in, u32 *key_enc, u32 rounds,
		     u32 bytes);
void ppc_decrypt_ecb(u8 *out, const u8 *in, u32 *key_dec, u32 rounds,
		     u32 bytes);
void ppc_encrypt_cbc(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes,
		     u8 *iv);
void ppc_decrypt_cbc(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, u32 bytes,
		     u8 *iv);
void ppc_crypt_ctr(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes,
		   u8 *iv);
void ppc_encrypt_xts(u8 *out, const u8 *in, u32 *key_enc, u32 rounds, u32 bytes,
		     u8 *iv, u32 *key_twk);
void ppc_decrypt_xts(u8 *out, const u8 *in, u32 *key_dec, u32 rounds, u32 bytes,
		     u8 *iv, u32 *key_twk);
int aes_p8_set_encrypt_key(const u8 *userKey, const int bits,
			   struct p8_aes_key *key);
int aes_p8_set_decrypt_key(const u8 *userKey, const int bits,
			   struct p8_aes_key *key);
void aes_p8_encrypt(const u8 *in, u8 *out, const struct p8_aes_key *key);
void aes_p8_decrypt(const u8 *in, u8 *out, const struct p8_aes_key *key);
void aes_p8_cbc_encrypt(const u8 *in, u8 *out, size_t len,
			const struct p8_aes_key *key, u8 *iv, const int enc);
void aes_p8_ctr32_encrypt_blocks(const u8 *in, u8 *out, size_t len,
				 const struct p8_aes_key *key, const u8 *iv);
void aes_p8_xts_encrypt(const u8 *in, u8 *out, size_t len,
			const struct p8_aes_key *key1,
			const struct p8_aes_key *key2, u8 *iv);
void aes_p8_xts_decrypt(const u8 *in, u8 *out, size_t len,
			const struct p8_aes_key *key1,
			const struct p8_aes_key *key2, u8 *iv);
#elif defined(CONFIG_SPARC64)
void aes_sparc64_key_expand(const u32 *in_key, u64 *output_key,
			    unsigned int key_len);
void aes_sparc64_load_encrypt_keys_128(const u64 *key);
void aes_sparc64_load_encrypt_keys_192(const u64 *key);
void aes_sparc64_load_encrypt_keys_256(const u64 *key);
void aes_sparc64_load_decrypt_keys_128(const u64 *key);
void aes_sparc64_load_decrypt_keys_192(const u64 *key);
void aes_sparc64_load_decrypt_keys_256(const u64 *key);
void aes_sparc64_ecb_encrypt_128(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len);
void aes_sparc64_ecb_encrypt_192(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len);
void aes_sparc64_ecb_encrypt_256(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len);
void aes_sparc64_ecb_decrypt_128(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len);
void aes_sparc64_ecb_decrypt_192(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len);
void aes_sparc64_ecb_decrypt_256(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len);
void aes_sparc64_cbc_encrypt_128(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len, u64 *iv);
void aes_sparc64_cbc_encrypt_192(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len, u64 *iv);
void aes_sparc64_cbc_encrypt_256(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len, u64 *iv);
void aes_sparc64_cbc_decrypt_128(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len, u64 *iv);
void aes_sparc64_cbc_decrypt_192(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len, u64 *iv);
void aes_sparc64_cbc_decrypt_256(const u64 *key, const u64 *input, u64 *output,
				 unsigned int len, u64 *iv);
void aes_sparc64_ctr_crypt_128(const u64 *key, const u64 *input, u64 *output,
			       unsigned int len, u64 *iv);
void aes_sparc64_ctr_crypt_192(const u64 *key, const u64 *input, u64 *output,
			       unsigned int len, u64 *iv);
void aes_sparc64_ctr_crypt_256(const u64 *key, const u64 *input, u64 *output,
			       unsigned int len, u64 *iv);
#endif


int aes_preparekey(struct aes_key *key, const u8 *in_key, size_t key_len);


int aes_prepareenckey(struct aes_enckey *key, const u8 *in_key, size_t key_len);

typedef union {
	const struct aes_enckey *enc_key;
	const struct aes_key *full_key;
} aes_encrypt_arg __attribute__ ((__transparent_union__));


void aes_encrypt(aes_encrypt_arg key, u8 out[at_least AES_BLOCK_SIZE],
		 const u8 in[at_least AES_BLOCK_SIZE]);


void aes_decrypt(const struct aes_key *key, u8 out[at_least AES_BLOCK_SIZE],
		 const u8 in[at_least AES_BLOCK_SIZE]);

extern const u8 crypto_aes_sbox[];
extern const u8 crypto_aes_inv_sbox[];
extern const u32 aes_enc_tab[256];
extern const u32 aes_dec_tab[256];

void aescfb_encrypt(const struct aes_enckey *key, u8 *dst, const u8 *src,
		    int len, const u8 iv[AES_BLOCK_SIZE]);
void aescfb_decrypt(const struct aes_enckey *key, u8 *dst, const u8 *src,
		    int len, const u8 iv[AES_BLOCK_SIZE]);

#endif
