#ifndef _CIPHER_AES_H_
#define _CIPHER_AES_H_

#include <sys/types.h>
#include <string.h>

#include <sys/cdefs.h>

__BEGIN_DECLS

// Note: When changing this, also update aes-asm.h
struct aes {
  uint32 aes_key[64];	// The key in internal format
  uint32 aes_keysize;	// Size of key (Number of 32-bit words)
  uint32 aes_iv[4];	// Initialization vector for the CBC based modes
};

//
// Setup this instance for encryption or decryption respectively
//
void aes_setup_encrypt(struct aes *aes, const void *key, unsigned int keybits);
void aes_setup_decrypt(struct aes *aes, const void *key, unsigned int keybits);

//
// Initialization vector for CBC and padded modes (Array of 16 bytes.)
//
static inline void aes_set_iv(struct aes *aes, const void *iv) { memcpy(aes->aes_iv, iv, 16); }
static inline void aes_clear_iv(struct aes *aes)               { memset(aes->aes_iv, 0, 16);  }
static inline const void *aes_get_iv(const struct aes *aes)    { return aes->aes_iv;          }

//
// Plain single block mangling
//

void aes_encrypt(struct aes *aes, const uint32 *plaintext,  uint32 *ciphertext);
void aes_decrypt(struct aes *aes, const uint32 *ciphertext, uint32 *plaintext);

//
// Convert several blocks in CBC mode.
//

// Value of <byte_count> must be a multiple of 16 bytes.
void aes_cbc_encrypt(struct aes *aes, const uint32 *plaintext,  uint32 *ciphertext, size_t byte_count);
void aes_cbc_decrypt(struct aes *aes, const uint32 *ciphertext, uint32 *plaintext,  size_t byte_count);

//
// Convert several blocks in padded CBC mode.
//

// Output buffer must be 32 bytes larger than byte count. Returns number of bytes placed into output buffer.
size_t aes_pad_encrypt(struct aes *aes, const uint32 *plaintext,  uint32 *ciphertext, size_t byte_count);

// Returns number of bytes placed into output buffer or 0 on failure.
size_t aes_pad_decrypt(struct aes *aes, const uint32 *ciphertext, uint32 *plaintext, size_t byte_count);

__END_DECLS

#endif
