added prescaler for 16 bit pwm in LPC1347 target

Fork of mbed-dev by mbed official

Revision:
144:ef7eb2e8f9f7
Parent:
50:a417edff4437
diff -r 423e1876dc07 -r ef7eb2e8f9f7 targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_aes.c
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_aes.c	Tue Aug 02 14:07:36 2016 +0000
+++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/emlib/src/em_aes.c	Fri Sep 02 15:07:44 2016 +0100
@@ -1,1387 +1,1387 @@
-/***************************************************************************//**
- * @file em_aes.c
- * @brief Advanced Encryption Standard (AES) accelerator peripheral API.
- * @version 4.2.1
- *******************************************************************************
- * @section License
- * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
- *******************************************************************************
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- *
- * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
- * obligation to support this Software. Silicon Labs is providing the
- * Software "AS IS", with no express or implied warranties of any kind,
- * including, but not limited to, any implied warranties of merchantability
- * or fitness for any particular purpose or warranties against infringement
- * of any proprietary rights of a third party.
- *
- * Silicon Labs will not be liable for any consequential, incidental, or
- * special damages, or any other relief, or for any claim by any third party,
- * arising from your use of this Software.
- *
- ******************************************************************************/
-
-#include "em_aes.h"
-#if defined(AES_COUNT) && (AES_COUNT > 0)
-
-#include "em_assert.h"
-/***************************************************************************//**
- * @addtogroup EM_Library
- * @{
- ******************************************************************************/
-
-/***************************************************************************//**
- * @addtogroup AES
- * @brief Advanced Encryption Standard Accelerator (AES) Peripheral API.
- * @details
- *   This API is intended for use on Silicon Labs target devices, and the
- *   following input/output notations should be noted:
- *
- *   @li Input/output data (plaintext, ciphertext, key etc) are treated as
- *     byte arrays, starting with most significant byte. Ie, 32 bytes of
- *     plaintext (B0...B31) is located in memory in the same order, with B0 at
- *     the lower address and B31 at the higher address.
- *
- *   @li Byte arrays must always be a multiple of AES block size, ie a multiple
- *     of 16. Padding, if required, is done at the end of the byte array.
- *
- *   @li Byte arrays should be word (32 bit) aligned for performance
- *     considerations, since the array is accessed with 32 bit access type.
- *     The Cortex-M supports unaligned accesses, but with a performance penalty.
- *
- *   @li It is possible to specify the same output buffer as input buffer
- *     as long as they point to the same address. In that case the provided input
- *     buffer is replaced with the encrypted/decrypted output. Notice that the
- *     buffers must be exactly overlapping. If partly overlapping, the
- *     behaviour is undefined.
- *
- *   It is up to the user to use a cipher mode according to its requirements
- *   in order to not break security. Please refer to specific cipher mode
- *   theory for details.
- *
- *   References:
- *   @li Wikipedia - Cipher modes, http://en.wikipedia.org/wiki/Cipher_modes
- *
- *   @li Recommendation for Block Cipher Modes of Operation,
- *      NIST Special Publication 800-38A, 2001 Edition,
- *      http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
- * @{
- ******************************************************************************/
-
-/*******************************************************************************
- *******************************   DEFINES   ***********************************
- ******************************************************************************/
-
-/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
-
-#define AES_BLOCKSIZE    16
-
-/** @endcond */
-
-/*******************************************************************************
- **************************   GLOBAL FUNCTIONS   *******************************
- ******************************************************************************/
-
-/***************************************************************************//**
- * @brief
- *   Cipher-block chaining (CBC) cipher mode encryption/decryption, 128 bit key.
- *
- * @details
- *   Encryption:
- * @verbatim
- *           Plaintext                  Plaintext
- *               |                          |
- *               V                          V
- * InitVector ->XOR        +-------------->XOR
- *               |         |                |
- *               V         |                V
- *       +--------------+  |        +--------------+
- * Key ->| Block cipher |  |  Key ->| Block cipher |
- *       |  encryption  |  |        |  encryption  |
- *       +--------------+  |        +--------------+
- *               |---------+                |
- *               V                          V
- *           Ciphertext                 Ciphertext
- * @endverbatim
- *   Decryption:
- * @verbatim
- *         Ciphertext                 Ciphertext
- *              |----------+                |
- *              V          |                V
- *       +--------------+  |        +--------------+
- * Key ->| Block cipher |  |  Key ->| Block cipher |
- *       |  decryption  |  |        |  decryption  |
- *       +--------------+  |        +--------------+
- *               |         |                |
- *               V         |                V
- * InitVector ->XOR        +-------------->XOR
- *               |                          |
- *               V                          V
- *           Plaintext                  Plaintext
- * @endverbatim
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   When doing encryption, this is the 128 bit encryption key. When doing
- *   decryption, this is the 128 bit decryption key. The decryption key may
- *   be generated from the encryption key with AES_DecryptKey128().
- *   On devices supporting key buffering this argument can be null, if so, the
- *   key will not be loaded, as it is assumed the key has been loaded
- *   into KEYHA previously.
- *
- * @param[in] iv
- *   128 bit initalization vector to use.
- *
- * @param[in] encrypt
- *   Set to true to encrypt, false to decrypt.
- ******************************************************************************/
-void AES_CBC128(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                const uint8_t *iv,
-                bool encrypt)
-{
-  int            i;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  const uint32_t *_iv  = (const uint32_t *)iv;
-  /* Need to buffer one block when decrypting in case 'out' replaces 'in' */
-  uint32_t       prev[4];
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  /* Number of blocks to process */
-  len /= AES_BLOCKSIZE;
-
-  #if defined( AES_CTRL_KEYBUFEN )
-  if (key)
-  {
-    /* Load key into high key for key buffer usage */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->KEYHA = __REV(_key[i]);
-    }
-  }
-  #endif
-
-  if (encrypt)
-  {
-    /* Enable encryption with auto start using XOR */
-    #if defined( AES_CTRL_KEYBUFEN )
-    AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_XORSTART;
-    #else
-    AES->CTRL = AES_CTRL_XORSTART;
-    #endif
-
-    /* Load initialization vector, since writing to DATA, it will */
-    /* not trigger encryption. */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->DATA = __REV(_iv[i]);
-    }
-
-    /* Encrypt data */
-    while (len--)
-    {
-      #if !defined( AES_CTRL_KEYBUFEN )
-      /* Load key */
-      for (i = 3; i >= 0; i--)
-      {
-        AES->KEYLA = __REV(_key[i]);
-      }
-      #endif
-
-      /* Load data and trigger encryption */
-      for (i = 3; i >= 0; i--)
-      {
-        AES->XORDATA = __REV(_in[i]);
-      }
-      _in += 4;
-
-      /* Wait for completion */
-      while (AES->STATUS & AES_STATUS_RUNNING)
-        ;
-
-      /* Save encrypted data */
-      for (i = 3; i >= 0; i--)
-      {
-        _out[i] = __REV(AES->DATA);
-      }
-      _out += 4;
-    }
-  }
-  else
-  {
-    /* Select decryption mode */
-    #if defined( AES_CTRL_KEYBUFEN )
-    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
-    #else
-    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_DATASTART;
-    #endif
-
-    /* Copy init vector to previous buffer to avoid special handling */
-    for (i = 0; i < 4; i++)
-    {
-      prev[i] = _iv[i];
-    }
-
-    /* Decrypt data */
-    while (len--)
-    {
-      #if !defined( AES_CTRL_KEYBUFEN )
-      /* Load key */
-      for (i = 3; i >= 0; i--)
-      {
-        AES->KEYLA = __REV(_key[i]);
-      }
-      #endif
-
-      /* Load data and trigger decryption */
-      for (i = 3; i >= 0; i--)
-      {
-        AES->DATA = __REV(_in[i]);
-      }
-
-      /* Wait for completion */
-      while (AES->STATUS & AES_STATUS_RUNNING)
-        ;
-
-      /* In order to avoid additional buffer, we use HW directly for XOR and buffer */
-      /* (Writing to XORDATA will not trigger encoding, triggering enabled on DATA.) */
-      for (i = 3; i >= 0; i--)
-      {
-        AES->XORDATA = __REV(prev[i]);
-        prev[i]      = _in[i];
-      }
-      _in += 4;
-
-      /* Then fetch decrypted data, we have to do it in a separate loop */
-      /* due to internal auto-shifting of words */
-      for (i = 3; i >= 0; i--)
-      {
-        _out[i] = __REV(AES->DATA);
-      }
-      _out += 4;
-    }
-  }
-}
-
-
-#if defined( AES_CTRL_AES256 )
-/***************************************************************************//**
- * @brief
- *   Cipher-block chaining (CBC) cipher mode encryption/decryption, 256 bit key.
- *
- * @details
- *   Please see AES_CBC128() for CBC figure.
- *
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   When doing encryption, this is the 256 bit encryption key. When doing
- *   decryption, this is the 256 bit decryption key. The decryption key may
- *   be generated from the encryption key with AES_DecryptKey256().
- *
- * @param[in] iv
- *   128 bit initalization vector to use.
- *
- * @param[in] encrypt
- *   Set to true to encrypt, false to decrypt.
- ******************************************************************************/
-void AES_CBC256(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                const uint8_t *iv,
-                bool encrypt)
-{
-  int            i;
-  int            j;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  const uint32_t *_iv  = (const uint32_t *)iv;
-  /* Need to buffer one block when decrypting in case output replaces input */
-  uint32_t       prev[4];
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  /* Number of blocks to process */
-  len /= AES_BLOCKSIZE;
-
-  if (encrypt)
-  {
-    /* Enable encryption with auto start using XOR */
-    AES->CTRL = AES_CTRL_AES256 | AES_CTRL_XORSTART;
-
-    /* Load initialization vector, since writing to DATA, it will */
-    /* not trigger encryption. */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->DATA = __REV(_iv[i]);
-    }
-
-    /* Encrypt data */
-    while (len--)
-    {
-      /* Load key and data and trigger encryption */
-      for (i = 3, j = 7; i >= 0; i--, j--)
-      {
-        AES->KEYLA = __REV(_key[j]);
-        AES->KEYHA = __REV(_key[i]);
-        /* Write data last, since will trigger encryption on last iteration */
-        AES->XORDATA = __REV(_in[i]);
-      }
-      _in += 4;
-
-      /* Wait for completion */
-      while (AES->STATUS & AES_STATUS_RUNNING)
-        ;
-
-      /* Save encrypted data */
-      for (i = 3; i >= 0; i--)
-      {
-        _out[i] = __REV(AES->DATA);
-      }
-      _out += 4;
-    }
-  }
-  else
-  {
-    /* Select decryption mode */
-    AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DECRYPT | AES_CTRL_DATASTART;
-
-    /* Copy init vector to previous buffer to avoid special handling */
-    for (i = 0; i < 4; i++)
-    {
-      prev[i] = _iv[i];
-    }
-
-    /* Decrypt data */
-    while (len--)
-    {
-      /* Load key and data and trigger decryption */
-      for (i = 3, j = 7; i >= 0; i--, j--)
-      {
-        AES->KEYLA = __REV(_key[j]);
-        AES->KEYHA = __REV(_key[i]);
-        /* Write data last, since will trigger encryption on last iteration */
-        AES->DATA = __REV(_in[i]);
-      }
-
-      /* Wait for completion */
-      while (AES->STATUS & AES_STATUS_RUNNING)
-        ;
-
-      /* In order to avoid additional buffer, we use HW directly for XOR and buffer */
-      for (i = 3; i >= 0; i--)
-      {
-        AES->XORDATA = __REV(prev[i]);
-        prev[i]      = _in[i];
-      }
-      _in += 4;
-
-      /* Then fetch decrypted data, we have to do it in a separate loop */
-      /* due to internal auto-shifting of words */
-      for (i = 3; i >= 0; i--)
-      {
-        _out[i] = __REV(AES->DATA);
-      }
-      _out += 4;
-    }
-  }
-}
-#endif
-
-
-/***************************************************************************//**
- * @brief
- *   Cipher feedback (CFB) cipher mode encryption/decryption, 128 bit key.
- *
- * @details
- *   Encryption:
- * @verbatim
- *           InitVector    +----------------+
- *               |         |                |
- *               V         |                V
- *       +--------------+  |        +--------------+
- * Key ->| Block cipher |  |  Key ->| Block cipher |
- *       |  encryption  |  |        |  encryption  |
- *       +--------------+  |        +--------------+
- *               |         |                |
- *               V         |                V
- *  Plaintext ->XOR        |   Plaintext ->XOR
- *               |---------+                |
- *               V                          V
- *           Ciphertext                 Ciphertext
- * @endverbatim
- *   Decryption:
- * @verbatim
- *          InitVector     +----------------+
- *               |         |                |
- *               V         |                V
- *       +--------------+  |        +--------------+
- * Key ->| Block cipher |  |  Key ->| Block cipher |
- *       |  encryption  |  |        |  encryption  |
- *       +--------------+  |        +--------------+
- *               |         |                |
- *               V         |                V
- *              XOR<- Ciphertext           XOR<- Ciphertext
- *               |                          |
- *               V                          V
- *           Plaintext                  Plaintext
- * @endverbatim
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   128 bit encryption key is used for both encryption and decryption modes.
- *
- * @param[in] iv
- *   128 bit initalization vector to use.
- *
- * @param[in] encrypt
- *   Set to true to encrypt, false to decrypt.
- ******************************************************************************/
-void AES_CFB128(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                const uint8_t *iv,
-                bool encrypt)
-{
-  int            i;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  const uint32_t *_iv  = (const uint32_t *)iv;
-  const uint32_t *data;
-  uint32_t       tmp[4];
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  #if defined( AES_CTRL_KEYBUFEN )
-  AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
-  #else
-  AES->CTRL = AES_CTRL_DATASTART;
-  #endif
-
-  #if defined( AES_CTRL_KEYBUFEN )
-  /* Load key into high key for key buffer usage */
-  for (i = 3; i >= 0; i--)
-  {
-    AES->KEYHA = __REV(_key[i]);
-  }
-  #endif
-
-  /* Encrypt/decrypt data */
-  data = _iv;
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    #if !defined( AES_CTRL_KEYBUFEN )
-    /* Load key */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->KEYLA = __REV(_key[i]);
-    }
-    #endif
-
-    /* Load data and trigger encryption */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->DATA = __REV(data[i]);
-    }
-
-    /* Do some required processing before waiting for completion */
-    if (encrypt)
-    {
-      data = _out;
-    }
-    else
-    {
-      /* Must copy current ciphertext block since it may be overwritten */
-      for (i = 0; i < 4; i++)
-      {
-        tmp[i] = _in[i];
-      }
-      data = tmp;
-    }
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA) ^ _in[i];
-    }
-    _out += 4;
-    _in  += 4;
-  }
-}
-
-
-#if defined( AES_CTRL_AES256 )
-/***************************************************************************//**
- * @brief
- *   Cipher feedback (CFB) cipher mode encryption/decryption, 256 bit key.
- *
- * @details
- *   Please see AES_CFB128() for CFB figure.
- *
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   256 bit encryption key is used for both encryption and decryption modes.
- *
- * @param[in] iv
- *   128 bit initalization vector to use.
- *
- * @param[in] encrypt
- *   Set to true to encrypt, false to decrypt.
- ******************************************************************************/
-void AES_CFB256(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                const uint8_t *iv,
-                bool encrypt)
-{
-  int            i;
-  int            j;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  const uint32_t *_iv  = (const uint32_t *)iv;
-  const uint32_t *data;
-  uint32_t       tmp[4];
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  /* Select encryption mode */
-  AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DATASTART;
-
-  /* Encrypt/decrypt data */
-  data = _iv;
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    /* Load key and block to be encrypted/decrypted */
-    for (i = 3, j = 7; i >= 0; i--, j--)
-    {
-      AES->KEYLA = __REV(_key[j]);
-      AES->KEYHA = __REV(_key[i]);
-      /* Write data last, since will trigger encryption on last iteration */
-      AES->DATA = __REV(data[i]);
-    }
-
-    /* Do some required processing before waiting for completion */
-    if (encrypt)
-    {
-      data = _out;
-    }
-    else
-    {
-      /* Must copy current ciphertext block since it may be overwritten */
-      for (i = 0; i < 4; i++)
-      {
-        tmp[i] = _in[i];
-      }
-      data = tmp;
-    }
-
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA) ^ _in[i];
-    }
-    _out += 4;
-    _in  += 4;
-  }
-}
-#endif
-
-
-/***************************************************************************//**
- * @brief
- *   Counter (CTR) cipher mode encryption/decryption, 128 bit key.
- *
- * @details
- *   Encryption:
- * @verbatim
- *           Counter                    Counter
- *              |                          |
- *              V                          V
- *       +--------------+           +--------------+
- * Key ->| Block cipher |     Key ->| Block cipher |
- *       |  encryption  |           |  encryption  |
- *       +--------------+           +--------------+
- *              |                          |
- * Plaintext ->XOR            Plaintext ->XOR
- *              |                          |
- *              V                          V
- *         Ciphertext                 Ciphertext
- * @endverbatim
- *   Decryption:
- * @verbatim
- *           Counter                    Counter
- *              |                          |
- *              V                          V
- *       +--------------+           +--------------+
- * Key ->| Block cipher |     Key ->| Block cipher |
- *       |  encryption  |           |  encryption  |
- *       +--------------+           +--------------+
- *               |                          |
- * Ciphertext ->XOR           Ciphertext ->XOR
- *               |                          |
- *               V                          V
- *           Plaintext                  Plaintext
- * @endverbatim
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   128 bit encryption key.
- *   On devices supporting key buffering this argument can be null, if so, the
- *   key will not be loaded, as it is assumed the key has been loaded
- *   into KEYHA previously.
- *
- * @param[in,out] ctr
- *   128 bit initial counter value. The counter is updated after each AES
- *   block encoding through use of @p ctrFunc.
- *
- * @param[in] ctrFunc
- *   Function used to update counter value.
- ******************************************************************************/
-void AES_CTR128(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                uint8_t *ctr,
-                AES_CtrFuncPtr_TypeDef ctrFunc)
-{
-  int            i;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  uint32_t       *_ctr = (uint32_t *)ctr;
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-  EFM_ASSERT(ctrFunc);
-
-  #if defined( AES_CTRL_KEYBUFEN )
-  AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
-  #else
-  AES->CTRL = AES_CTRL_DATASTART;
-  #endif
-
-  #if defined( AES_CTRL_KEYBUFEN )
-  if (key)
-  {
-    /* Load key into high key for key buffer usage */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->KEYHA = __REV(_key[i]);
-    }
-  }
-  #endif
-
-  /* Encrypt/decrypt data */
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    #if !defined( AES_CTRL_KEYBUFEN )
-    /* Load key */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->KEYLA = __REV(_key[i]);
-    }
-    #endif
-
-    /* Load ctr to be encrypted/decrypted */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->DATA = __REV(_ctr[i]);
-    }
-    /* Increment ctr for next use */
-    ctrFunc(ctr);
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA) ^ _in[i];
-    }
-    _out += 4;
-    _in  += 4;
-  }
-}
-
-
-#if defined( AES_CTRL_AES256 )
-/***************************************************************************//**
- * @brief
- *   Counter (CTR) cipher mode encryption/decryption, 256 bit key.
- *
- * @details
- *   Please see AES_CTR128() for CTR figure.
- *
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   256 bit encryption key.
- *
- * @param[in,out] ctr
- *   128 bit initial counter value. The counter is updated after each AES
- *   block encoding through use of @p ctrFunc.
- *
- * @param[in] ctrFunc
- *   Function used to update counter value.
- ******************************************************************************/
-void AES_CTR256(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                uint8_t *ctr,
-                AES_CtrFuncPtr_TypeDef ctrFunc)
-{
-  int            i;
-  int            j;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  uint32_t       *_ctr = (uint32_t *)ctr;
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-  EFM_ASSERT(ctrFunc);
-
-  /* Select encryption mode, with auto trigger */
-  AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DATASTART;
-
-  /* Encrypt/decrypt data */
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    /* Load key and block to be encrypted/decrypted */
-    for (i = 3, j = 7; i >= 0; i--, j--)
-    {
-      AES->KEYLA = __REV(_key[j]);
-      AES->KEYHA = __REV(_key[i]);
-      /* Write data last, since will trigger encryption on last iteration */
-      AES->DATA = __REV(_ctr[i]);
-    }
-    /* Increment ctr for next use */
-    ctrFunc(ctr);
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA) ^ _in[i];
-    }
-    _out += 4;
-    _in  += 4;
-  }
-}
-#endif
-
-
-/***************************************************************************//**
- * @brief
- *   Update last 32 bits of 128 bit counter, by incrementing with 1.
- *
- * @details
- *   Notice that no special consideration is given to possible wrap around. If
- *   32 least significant bits are 0xFFFFFFFF, they will be updated to 0x00000000,
- *   ignoring overflow.
- *
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[in,out] ctr
- *   Buffer holding 128 bit counter to be updated.
- ******************************************************************************/
-void AES_CTRUpdate32Bit(uint8_t *ctr)
-{
-  uint32_t *_ctr = (uint32_t *)ctr;
-
-  _ctr[3] = __REV(__REV(_ctr[3]) + 1);
-}
-
-
-/***************************************************************************//**
- * @brief
- *   Generate 128 bit decryption key from 128 bit encryption key. The decryption
- *   key is used for some cipher modes when decrypting.
- *
- * @details
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place 128 bit decryption key. Must be at least 16 bytes long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding 128 bit encryption key. Must be at least 16 bytes long.
- ******************************************************************************/
-void AES_DecryptKey128(uint8_t *out, const uint8_t *in)
-{
-  int            i;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-
-  /* Load key */
-  for (i = 3; i >= 0; i--)
-  {
-    AES->KEYLA = __REV(_in[i]);
-  }
-
-  /* Do dummy encryption to generate decrypt key */
-  AES->CTRL = 0;
-  AES_IntClear(AES_IF_DONE);
-  AES->CMD = AES_CMD_START;
-
-  /* Wait for completion */
-  while (AES->STATUS & AES_STATUS_RUNNING)
-    ;
-
-  /* Save decryption key */
-  for (i = 3; i >= 0; i--)
-  {
-    _out[i] = __REV(AES->KEYLA);
-  }
-}
-
-
-#if defined( AES_CTRL_AES256 )
-/***************************************************************************//**
- * @brief
- *   Generate 256 bit decryption key from 256 bit encryption key. The decryption
- *   key is used for some cipher modes when decrypting.
- *
- * @details
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place 256 bit decryption key. Must be at least 32 bytes long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding 256 bit encryption key. Must be at least 32 bytes long.
- ******************************************************************************/
-void AES_DecryptKey256(uint8_t *out, const uint8_t *in)
-{
-  int            i;
-  int            j;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-
-  /* Load key */
-  for (i = 3, j = 7; i >= 0; i--, j--)
-  {
-    AES->KEYLA = __REV(_in[j]);
-    AES->KEYHA = __REV(_in[i]);
-  }
-
-  /* Do dummy encryption to generate decrypt key */
-  AES->CTRL = AES_CTRL_AES256;
-  AES->CMD  = AES_CMD_START;
-
-  /* Wait for completion */
-  while (AES->STATUS & AES_STATUS_RUNNING)
-    ;
-
-  /* Save decryption key */
-  for (i = 3, j = 7; i >= 0; i--, j--)
-  {
-    _out[j] = __REV(AES->KEYLA);
-    _out[i] = __REV(AES->KEYHA);
-  }
-}
-#endif
-
-
-/***************************************************************************//**
- * @brief
- *   Electronic Codebook (ECB) cipher mode encryption/decryption, 128 bit key.
- *
- * @details
- *   Encryption:
- * @verbatim
- *          Plaintext                  Plaintext
- *              |                          |
- *              V                          V
- *       +--------------+           +--------------+
- * Key ->| Block cipher |     Key ->| Block cipher |
- *       |  encryption  |           |  encryption  |
- *       +--------------+           +--------------+
- *              |                          |
- *              V                          V
- *         Ciphertext                 Ciphertext
- * @endverbatim
- *   Decryption:
- * @verbatim
- *         Ciphertext                 Ciphertext
- *              |                          |
- *              V                          V
- *       +--------------+           +--------------+
- * Key ->| Block cipher |     Key ->| Block cipher |
- *       |  decryption  |           |  decryption  |
- *       +--------------+           +--------------+
- *              |                          |
- *              V                          V
- *          Plaintext                  Plaintext
- * @endverbatim
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   When doing encryption, this is the 128 bit encryption key. When doing
- *   decryption, this is the 128 bit decryption key. The decryption key may
- *   be generated from the encryption key with AES_DecryptKey128().
- *
- * @param[in] encrypt
- *   Set to true to encrypt, false to decrypt.
- ******************************************************************************/
-void AES_ECB128(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                bool encrypt)
-{
-  int            i;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  #if defined( AES_CTRL_KEYBUFEN )
-  /* Load key into high key for key buffer usage */
-  for (i = 3; i >= 0; i--)
-  {
-    AES->KEYHA = __REV(_key[i]);
-  }
-  #endif
-
-  if (encrypt)
-  {
-    /* Select encryption mode */
-    #if defined( AES_CTRL_KEYBUFEN )
-    AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
-    #else
-    AES->CTRL = AES_CTRL_DATASTART;
-    #endif
-  }
-  else
-  {
-    /* Select decryption mode */
-    #if defined( AES_CTRL_KEYBUFEN )
-    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
-    #else
-    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_DATASTART;
-    #endif
-  }
-
-  /* Encrypt/decrypt data */
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    #if !defined( AES_CTRL_KEYBUFEN )
-    /* Load key */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->KEYLA = __REV(_key[i]);
-    }
-    #endif
-
-    /* Load block to be encrypted/decrypted */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->DATA = __REV(_in[i]);
-    }
-    _in += 4;
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA);
-    }
-    _out += 4;
-  }
-}
-
-
-#if defined( AES_CTRL_AES256 )
-/***************************************************************************//**
- * @brief
- *   Electronic Codebook (ECB) cipher mode encryption/decryption, 256 bit key.
- *
- * @details
- *   Please see AES_ECB128() for ECB figure.
- *
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   When doing encryption, this is the 256 bit encryption key. When doing
- *   decryption, this is the 256 bit decryption key. The decryption key may
- *   be generated from the encryption key with AES_DecryptKey256().
- *
- * @param[in] encrypt
- *   Set to true to encrypt, false to decrypt.
- ******************************************************************************/
-void AES_ECB256(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                bool encrypt)
-{
-  int            i;
-  int            j;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  if (encrypt)
-  {
-    /* Select encryption mode */
-    AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DATASTART;
-  }
-  else
-  {
-    /* Select decryption mode */
-    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_AES256 | AES_CTRL_DATASTART;
-  }
-
-  /* Encrypt/decrypt data */
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    /* Load key and block to be encrypted/decrypted */
-    for (i = 3, j = 7; i >= 0; i--, j--)
-    {
-      AES->KEYLA = __REV(_key[j]);
-      AES->KEYHA = __REV(_key[i]);
-      /* Write data last, since will trigger encryption on last iteration */
-      AES->DATA = __REV(_in[i]);
-    }
-    _in += 4;
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA);
-    }
-    _out += 4;
-  }
-}
-#endif
-
-
-/***************************************************************************//**
- * @brief
- *   Output feedback (OFB) cipher mode encryption/decryption, 128 bit key.
- *
- * @details
- *   Encryption:
- * @verbatim
- *          InitVector    +----------------+
- *              |         |                |
- *              V         |                V
- *       +--------------+ |        +--------------+
- * Key ->| Block cipher | |  Key ->| Block cipher |
- *       |  encryption  | |        |  encryption  |
- *       +--------------+ |        +--------------+
- *              |         |                |
- *              |---------+                |
- *              V                          V
- * Plaintext ->XOR            Plaintext ->XOR
- *              |                          |
- *              V                          V
- *         Ciphertext                 Ciphertext
- * @endverbatim
- *   Decryption:
- * @verbatim
- *          InitVector    +----------------+
- *              |         |                |
- *              V         |                V
- *       +--------------+ |        +--------------+
- * Key ->| Block cipher | |  Key ->| Block cipher |
- *       |  encryption  | |        |  encryption  |
- *       +--------------+ |        +--------------+
- *              |         |                |
- *              |---------+                |
- *              V                          V
- * Ciphertext ->XOR           Ciphertext ->XOR
- *              |                          |
- *              V                          V
- *          Plaintext                  Plaintext
- * @endverbatim
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   128 bit encryption key.
- *
- * @param[in] iv
- *   128 bit initalization vector to use.
- ******************************************************************************/
-void AES_OFB128(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                const uint8_t *iv)
-{
-  int            i;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  const uint32_t *_iv  = (const uint32_t *)iv;
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  /* Select encryption mode, trigger explicitly by command */
-  #if defined( AES_CTRL_KEYBUFEN )
-  AES->CTRL = AES_CTRL_KEYBUFEN;
-  #else
-  AES->CTRL = 0;
-  #endif
-
-  /* Load key into high key for key buffer usage */
-  /* Load initialization vector */
-  for (i = 3; i >= 0; i--)
-  {
-    #if defined( AES_CTRL_KEYBUFEN )
-    AES->KEYHA = __REV(_key[i]);
-    #endif
-    AES->DATA  = __REV(_iv[i]);
-  }
-
-  /* Encrypt/decrypt data */
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    #if !defined( AES_CTRL_KEYBUFEN )
-    /* Load key */
-    for (i = 3; i >= 0; i--)
-    {
-      AES->KEYLA = __REV(_key[i]);
-    }
-    #endif
-
-    AES->CMD = AES_CMD_START;
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA) ^ _in[i];
-    }
-    _out += 4;
-    _in  += 4;
-  }
-}
-
-
-#if defined( AES_CTRL_AES256 )
-/***************************************************************************//**
- * @brief
- *   Output feedback (OFB) cipher mode encryption/decryption, 256 bit key.
- *
- * @details
- *   Please see AES_OFB128() for OFB figure.
- *
- *   Please refer to general comments on layout and byte ordering of parameters.
- *
- * @param[out] out
- *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
- *   may be set equal to @p in, in which case the input buffer is overwritten.
- *
- * @param[in] in
- *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
- *
- * @param[in] len
- *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
- *
- * @param[in] key
- *   256 bit encryption key.
- *
- * @param[in] iv
- *   128 bit initalization vector to use.
- ******************************************************************************/
-void AES_OFB256(uint8_t *out,
-                const uint8_t *in,
-                unsigned int len,
-                const uint8_t *key,
-                const uint8_t *iv)
-{
-  int            i;
-  int            j;
-  uint32_t       *_out = (uint32_t *)out;
-  const uint32_t *_in  = (const uint32_t *)in;
-  const uint32_t *_key = (const uint32_t *)key;
-  const uint32_t *_iv  = (const uint32_t *)iv;
-
-  EFM_ASSERT(!(len % AES_BLOCKSIZE));
-
-  /* Select encryption mode, trigger explicitly by command */
-  AES->CTRL = AES_CTRL_AES256;
-
-  /* Load initialization vector */
-  for (i = 3; i >= 0; i--)
-  {
-    AES->DATA = __REV(_iv[i]);
-  }
-
-  /* Encrypt/decrypt data */
-  len /= AES_BLOCKSIZE;
-  while (len--)
-  {
-    /* Load key */
-    for (i = 3, j = 7; i >= 0; i--, j--)
-    {
-      AES->KEYLA = __REV(_key[j]);
-      AES->KEYHA = __REV(_key[i]);
-    }
-
-    AES->CMD = AES_CMD_START;
-
-    /* Wait for completion */
-    while (AES->STATUS & AES_STATUS_RUNNING)
-      ;
-
-    /* Save encrypted/decrypted data */
-    for (i = 3; i >= 0; i--)
-    {
-      _out[i] = __REV(AES->DATA) ^ _in[i];
-    }
-    _out += 4;
-    _in  += 4;
-  }
-}
-#endif
-
-
-/** @} (end addtogroup AES) */
-/** @} (end addtogroup EM_Library) */
-#endif /* defined(AES_COUNT) && (AES_COUNT > 0) */
+/***************************************************************************//**
+ * @file em_aes.c
+ * @brief Advanced Encryption Standard (AES) accelerator peripheral API.
+ * @version 4.2.1
+ *******************************************************************************
+ * @section License
+ * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
+ *******************************************************************************
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
+ * obligation to support this Software. Silicon Labs is providing the
+ * Software "AS IS", with no express or implied warranties of any kind,
+ * including, but not limited to, any implied warranties of merchantability
+ * or fitness for any particular purpose or warranties against infringement
+ * of any proprietary rights of a third party.
+ *
+ * Silicon Labs will not be liable for any consequential, incidental, or
+ * special damages, or any other relief, or for any claim by any third party,
+ * arising from your use of this Software.
+ *
+ ******************************************************************************/
+
+#include "em_aes.h"
+#if defined(AES_COUNT) && (AES_COUNT > 0)
+
+#include "em_assert.h"
+/***************************************************************************//**
+ * @addtogroup EM_Library
+ * @{
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup AES
+ * @brief Advanced Encryption Standard Accelerator (AES) Peripheral API.
+ * @details
+ *   This API is intended for use on Silicon Labs target devices, and the
+ *   following input/output notations should be noted:
+ *
+ *   @li Input/output data (plaintext, ciphertext, key etc) are treated as
+ *     byte arrays, starting with most significant byte. Ie, 32 bytes of
+ *     plaintext (B0...B31) is located in memory in the same order, with B0 at
+ *     the lower address and B31 at the higher address.
+ *
+ *   @li Byte arrays must always be a multiple of AES block size, ie a multiple
+ *     of 16. Padding, if required, is done at the end of the byte array.
+ *
+ *   @li Byte arrays should be word (32 bit) aligned for performance
+ *     considerations, since the array is accessed with 32 bit access type.
+ *     The Cortex-M supports unaligned accesses, but with a performance penalty.
+ *
+ *   @li It is possible to specify the same output buffer as input buffer
+ *     as long as they point to the same address. In that case the provided input
+ *     buffer is replaced with the encrypted/decrypted output. Notice that the
+ *     buffers must be exactly overlapping. If partly overlapping, the
+ *     behaviour is undefined.
+ *
+ *   It is up to the user to use a cipher mode according to its requirements
+ *   in order to not break security. Please refer to specific cipher mode
+ *   theory for details.
+ *
+ *   References:
+ *   @li Wikipedia - Cipher modes, http://en.wikipedia.org/wiki/Cipher_modes
+ *
+ *   @li Recommendation for Block Cipher Modes of Operation,
+ *      NIST Special Publication 800-38A, 2001 Edition,
+ *      http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+ * @{
+ ******************************************************************************/
+
+/*******************************************************************************
+ *******************************   DEFINES   ***********************************
+ ******************************************************************************/
+
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
+
+#define AES_BLOCKSIZE    16
+
+/** @endcond */
+
+/*******************************************************************************
+ **************************   GLOBAL FUNCTIONS   *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @brief
+ *   Cipher-block chaining (CBC) cipher mode encryption/decryption, 128 bit key.
+ *
+ * @details
+ *   Encryption:
+ * @verbatim
+ *           Plaintext                  Plaintext
+ *               |                          |
+ *               V                          V
+ * InitVector ->XOR        +-------------->XOR
+ *               |         |                |
+ *               V         |                V
+ *       +--------------+  |        +--------------+
+ * Key ->| Block cipher |  |  Key ->| Block cipher |
+ *       |  encryption  |  |        |  encryption  |
+ *       +--------------+  |        +--------------+
+ *               |---------+                |
+ *               V                          V
+ *           Ciphertext                 Ciphertext
+ * @endverbatim
+ *   Decryption:
+ * @verbatim
+ *         Ciphertext                 Ciphertext
+ *              |----------+                |
+ *              V          |                V
+ *       +--------------+  |        +--------------+
+ * Key ->| Block cipher |  |  Key ->| Block cipher |
+ *       |  decryption  |  |        |  decryption  |
+ *       +--------------+  |        +--------------+
+ *               |         |                |
+ *               V         |                V
+ * InitVector ->XOR        +-------------->XOR
+ *               |                          |
+ *               V                          V
+ *           Plaintext                  Plaintext
+ * @endverbatim
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   When doing encryption, this is the 128 bit encryption key. When doing
+ *   decryption, this is the 128 bit decryption key. The decryption key may
+ *   be generated from the encryption key with AES_DecryptKey128().
+ *   On devices supporting key buffering this argument can be null, if so, the
+ *   key will not be loaded, as it is assumed the key has been loaded
+ *   into KEYHA previously.
+ *
+ * @param[in] iv
+ *   128 bit initalization vector to use.
+ *
+ * @param[in] encrypt
+ *   Set to true to encrypt, false to decrypt.
+ ******************************************************************************/
+void AES_CBC128(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                const uint8_t *iv,
+                bool encrypt)
+{
+  int            i;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  const uint32_t *_iv  = (const uint32_t *)iv;
+  /* Need to buffer one block when decrypting in case 'out' replaces 'in' */
+  uint32_t       prev[4];
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  /* Number of blocks to process */
+  len /= AES_BLOCKSIZE;
+
+  #if defined( AES_CTRL_KEYBUFEN )
+  if (key)
+  {
+    /* Load key into high key for key buffer usage */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->KEYHA = __REV(_key[i]);
+    }
+  }
+  #endif
+
+  if (encrypt)
+  {
+    /* Enable encryption with auto start using XOR */
+    #if defined( AES_CTRL_KEYBUFEN )
+    AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_XORSTART;
+    #else
+    AES->CTRL = AES_CTRL_XORSTART;
+    #endif
+
+    /* Load initialization vector, since writing to DATA, it will */
+    /* not trigger encryption. */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->DATA = __REV(_iv[i]);
+    }
+
+    /* Encrypt data */
+    while (len--)
+    {
+      #if !defined( AES_CTRL_KEYBUFEN )
+      /* Load key */
+      for (i = 3; i >= 0; i--)
+      {
+        AES->KEYLA = __REV(_key[i]);
+      }
+      #endif
+
+      /* Load data and trigger encryption */
+      for (i = 3; i >= 0; i--)
+      {
+        AES->XORDATA = __REV(_in[i]);
+      }
+      _in += 4;
+
+      /* Wait for completion */
+      while (AES->STATUS & AES_STATUS_RUNNING)
+        ;
+
+      /* Save encrypted data */
+      for (i = 3; i >= 0; i--)
+      {
+        _out[i] = __REV(AES->DATA);
+      }
+      _out += 4;
+    }
+  }
+  else
+  {
+    /* Select decryption mode */
+    #if defined( AES_CTRL_KEYBUFEN )
+    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
+    #else
+    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_DATASTART;
+    #endif
+
+    /* Copy init vector to previous buffer to avoid special handling */
+    for (i = 0; i < 4; i++)
+    {
+      prev[i] = _iv[i];
+    }
+
+    /* Decrypt data */
+    while (len--)
+    {
+      #if !defined( AES_CTRL_KEYBUFEN )
+      /* Load key */
+      for (i = 3; i >= 0; i--)
+      {
+        AES->KEYLA = __REV(_key[i]);
+      }
+      #endif
+
+      /* Load data and trigger decryption */
+      for (i = 3; i >= 0; i--)
+      {
+        AES->DATA = __REV(_in[i]);
+      }
+
+      /* Wait for completion */
+      while (AES->STATUS & AES_STATUS_RUNNING)
+        ;
+
+      /* In order to avoid additional buffer, we use HW directly for XOR and buffer */
+      /* (Writing to XORDATA will not trigger encoding, triggering enabled on DATA.) */
+      for (i = 3; i >= 0; i--)
+      {
+        AES->XORDATA = __REV(prev[i]);
+        prev[i]      = _in[i];
+      }
+      _in += 4;
+
+      /* Then fetch decrypted data, we have to do it in a separate loop */
+      /* due to internal auto-shifting of words */
+      for (i = 3; i >= 0; i--)
+      {
+        _out[i] = __REV(AES->DATA);
+      }
+      _out += 4;
+    }
+  }
+}
+
+
+#if defined( AES_CTRL_AES256 )
+/***************************************************************************//**
+ * @brief
+ *   Cipher-block chaining (CBC) cipher mode encryption/decryption, 256 bit key.
+ *
+ * @details
+ *   Please see AES_CBC128() for CBC figure.
+ *
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   When doing encryption, this is the 256 bit encryption key. When doing
+ *   decryption, this is the 256 bit decryption key. The decryption key may
+ *   be generated from the encryption key with AES_DecryptKey256().
+ *
+ * @param[in] iv
+ *   128 bit initalization vector to use.
+ *
+ * @param[in] encrypt
+ *   Set to true to encrypt, false to decrypt.
+ ******************************************************************************/
+void AES_CBC256(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                const uint8_t *iv,
+                bool encrypt)
+{
+  int            i;
+  int            j;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  const uint32_t *_iv  = (const uint32_t *)iv;
+  /* Need to buffer one block when decrypting in case output replaces input */
+  uint32_t       prev[4];
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  /* Number of blocks to process */
+  len /= AES_BLOCKSIZE;
+
+  if (encrypt)
+  {
+    /* Enable encryption with auto start using XOR */
+    AES->CTRL = AES_CTRL_AES256 | AES_CTRL_XORSTART;
+
+    /* Load initialization vector, since writing to DATA, it will */
+    /* not trigger encryption. */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->DATA = __REV(_iv[i]);
+    }
+
+    /* Encrypt data */
+    while (len--)
+    {
+      /* Load key and data and trigger encryption */
+      for (i = 3, j = 7; i >= 0; i--, j--)
+      {
+        AES->KEYLA = __REV(_key[j]);
+        AES->KEYHA = __REV(_key[i]);
+        /* Write data last, since will trigger encryption on last iteration */
+        AES->XORDATA = __REV(_in[i]);
+      }
+      _in += 4;
+
+      /* Wait for completion */
+      while (AES->STATUS & AES_STATUS_RUNNING)
+        ;
+
+      /* Save encrypted data */
+      for (i = 3; i >= 0; i--)
+      {
+        _out[i] = __REV(AES->DATA);
+      }
+      _out += 4;
+    }
+  }
+  else
+  {
+    /* Select decryption mode */
+    AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DECRYPT | AES_CTRL_DATASTART;
+
+    /* Copy init vector to previous buffer to avoid special handling */
+    for (i = 0; i < 4; i++)
+    {
+      prev[i] = _iv[i];
+    }
+
+    /* Decrypt data */
+    while (len--)
+    {
+      /* Load key and data and trigger decryption */
+      for (i = 3, j = 7; i >= 0; i--, j--)
+      {
+        AES->KEYLA = __REV(_key[j]);
+        AES->KEYHA = __REV(_key[i]);
+        /* Write data last, since will trigger encryption on last iteration */
+        AES->DATA = __REV(_in[i]);
+      }
+
+      /* Wait for completion */
+      while (AES->STATUS & AES_STATUS_RUNNING)
+        ;
+
+      /* In order to avoid additional buffer, we use HW directly for XOR and buffer */
+      for (i = 3; i >= 0; i--)
+      {
+        AES->XORDATA = __REV(prev[i]);
+        prev[i]      = _in[i];
+      }
+      _in += 4;
+
+      /* Then fetch decrypted data, we have to do it in a separate loop */
+      /* due to internal auto-shifting of words */
+      for (i = 3; i >= 0; i--)
+      {
+        _out[i] = __REV(AES->DATA);
+      }
+      _out += 4;
+    }
+  }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ *   Cipher feedback (CFB) cipher mode encryption/decryption, 128 bit key.
+ *
+ * @details
+ *   Encryption:
+ * @verbatim
+ *           InitVector    +----------------+
+ *               |         |                |
+ *               V         |                V
+ *       +--------------+  |        +--------------+
+ * Key ->| Block cipher |  |  Key ->| Block cipher |
+ *       |  encryption  |  |        |  encryption  |
+ *       +--------------+  |        +--------------+
+ *               |         |                |
+ *               V         |                V
+ *  Plaintext ->XOR        |   Plaintext ->XOR
+ *               |---------+                |
+ *               V                          V
+ *           Ciphertext                 Ciphertext
+ * @endverbatim
+ *   Decryption:
+ * @verbatim
+ *          InitVector     +----------------+
+ *               |         |                |
+ *               V         |                V
+ *       +--------------+  |        +--------------+
+ * Key ->| Block cipher |  |  Key ->| Block cipher |
+ *       |  encryption  |  |        |  encryption  |
+ *       +--------------+  |        +--------------+
+ *               |         |                |
+ *               V         |                V
+ *              XOR<- Ciphertext           XOR<- Ciphertext
+ *               |                          |
+ *               V                          V
+ *           Plaintext                  Plaintext
+ * @endverbatim
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   128 bit encryption key is used for both encryption and decryption modes.
+ *
+ * @param[in] iv
+ *   128 bit initalization vector to use.
+ *
+ * @param[in] encrypt
+ *   Set to true to encrypt, false to decrypt.
+ ******************************************************************************/
+void AES_CFB128(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                const uint8_t *iv,
+                bool encrypt)
+{
+  int            i;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  const uint32_t *_iv  = (const uint32_t *)iv;
+  const uint32_t *data;
+  uint32_t       tmp[4];
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  #if defined( AES_CTRL_KEYBUFEN )
+  AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
+  #else
+  AES->CTRL = AES_CTRL_DATASTART;
+  #endif
+
+  #if defined( AES_CTRL_KEYBUFEN )
+  /* Load key into high key for key buffer usage */
+  for (i = 3; i >= 0; i--)
+  {
+    AES->KEYHA = __REV(_key[i]);
+  }
+  #endif
+
+  /* Encrypt/decrypt data */
+  data = _iv;
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    #if !defined( AES_CTRL_KEYBUFEN )
+    /* Load key */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->KEYLA = __REV(_key[i]);
+    }
+    #endif
+
+    /* Load data and trigger encryption */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->DATA = __REV(data[i]);
+    }
+
+    /* Do some required processing before waiting for completion */
+    if (encrypt)
+    {
+      data = _out;
+    }
+    else
+    {
+      /* Must copy current ciphertext block since it may be overwritten */
+      for (i = 0; i < 4; i++)
+      {
+        tmp[i] = _in[i];
+      }
+      data = tmp;
+    }
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA) ^ _in[i];
+    }
+    _out += 4;
+    _in  += 4;
+  }
+}
+
+
+#if defined( AES_CTRL_AES256 )
+/***************************************************************************//**
+ * @brief
+ *   Cipher feedback (CFB) cipher mode encryption/decryption, 256 bit key.
+ *
+ * @details
+ *   Please see AES_CFB128() for CFB figure.
+ *
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   256 bit encryption key is used for both encryption and decryption modes.
+ *
+ * @param[in] iv
+ *   128 bit initalization vector to use.
+ *
+ * @param[in] encrypt
+ *   Set to true to encrypt, false to decrypt.
+ ******************************************************************************/
+void AES_CFB256(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                const uint8_t *iv,
+                bool encrypt)
+{
+  int            i;
+  int            j;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  const uint32_t *_iv  = (const uint32_t *)iv;
+  const uint32_t *data;
+  uint32_t       tmp[4];
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  /* Select encryption mode */
+  AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DATASTART;
+
+  /* Encrypt/decrypt data */
+  data = _iv;
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    /* Load key and block to be encrypted/decrypted */
+    for (i = 3, j = 7; i >= 0; i--, j--)
+    {
+      AES->KEYLA = __REV(_key[j]);
+      AES->KEYHA = __REV(_key[i]);
+      /* Write data last, since will trigger encryption on last iteration */
+      AES->DATA = __REV(data[i]);
+    }
+
+    /* Do some required processing before waiting for completion */
+    if (encrypt)
+    {
+      data = _out;
+    }
+    else
+    {
+      /* Must copy current ciphertext block since it may be overwritten */
+      for (i = 0; i < 4; i++)
+      {
+        tmp[i] = _in[i];
+      }
+      data = tmp;
+    }
+
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA) ^ _in[i];
+    }
+    _out += 4;
+    _in  += 4;
+  }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ *   Counter (CTR) cipher mode encryption/decryption, 128 bit key.
+ *
+ * @details
+ *   Encryption:
+ * @verbatim
+ *           Counter                    Counter
+ *              |                          |
+ *              V                          V
+ *       +--------------+           +--------------+
+ * Key ->| Block cipher |     Key ->| Block cipher |
+ *       |  encryption  |           |  encryption  |
+ *       +--------------+           +--------------+
+ *              |                          |
+ * Plaintext ->XOR            Plaintext ->XOR
+ *              |                          |
+ *              V                          V
+ *         Ciphertext                 Ciphertext
+ * @endverbatim
+ *   Decryption:
+ * @verbatim
+ *           Counter                    Counter
+ *              |                          |
+ *              V                          V
+ *       +--------------+           +--------------+
+ * Key ->| Block cipher |     Key ->| Block cipher |
+ *       |  encryption  |           |  encryption  |
+ *       +--------------+           +--------------+
+ *               |                          |
+ * Ciphertext ->XOR           Ciphertext ->XOR
+ *               |                          |
+ *               V                          V
+ *           Plaintext                  Plaintext
+ * @endverbatim
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   128 bit encryption key.
+ *   On devices supporting key buffering this argument can be null, if so, the
+ *   key will not be loaded, as it is assumed the key has been loaded
+ *   into KEYHA previously.
+ *
+ * @param[in,out] ctr
+ *   128 bit initial counter value. The counter is updated after each AES
+ *   block encoding through use of @p ctrFunc.
+ *
+ * @param[in] ctrFunc
+ *   Function used to update counter value.
+ ******************************************************************************/
+void AES_CTR128(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                uint8_t *ctr,
+                AES_CtrFuncPtr_TypeDef ctrFunc)
+{
+  int            i;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  uint32_t       *_ctr = (uint32_t *)ctr;
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+  EFM_ASSERT(ctrFunc);
+
+  #if defined( AES_CTRL_KEYBUFEN )
+  AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
+  #else
+  AES->CTRL = AES_CTRL_DATASTART;
+  #endif
+
+  #if defined( AES_CTRL_KEYBUFEN )
+  if (key)
+  {
+    /* Load key into high key for key buffer usage */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->KEYHA = __REV(_key[i]);
+    }
+  }
+  #endif
+
+  /* Encrypt/decrypt data */
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    #if !defined( AES_CTRL_KEYBUFEN )
+    /* Load key */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->KEYLA = __REV(_key[i]);
+    }
+    #endif
+
+    /* Load ctr to be encrypted/decrypted */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->DATA = __REV(_ctr[i]);
+    }
+    /* Increment ctr for next use */
+    ctrFunc(ctr);
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA) ^ _in[i];
+    }
+    _out += 4;
+    _in  += 4;
+  }
+}
+
+
+#if defined( AES_CTRL_AES256 )
+/***************************************************************************//**
+ * @brief
+ *   Counter (CTR) cipher mode encryption/decryption, 256 bit key.
+ *
+ * @details
+ *   Please see AES_CTR128() for CTR figure.
+ *
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   256 bit encryption key.
+ *
+ * @param[in,out] ctr
+ *   128 bit initial counter value. The counter is updated after each AES
+ *   block encoding through use of @p ctrFunc.
+ *
+ * @param[in] ctrFunc
+ *   Function used to update counter value.
+ ******************************************************************************/
+void AES_CTR256(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                uint8_t *ctr,
+                AES_CtrFuncPtr_TypeDef ctrFunc)
+{
+  int            i;
+  int            j;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  uint32_t       *_ctr = (uint32_t *)ctr;
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+  EFM_ASSERT(ctrFunc);
+
+  /* Select encryption mode, with auto trigger */
+  AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DATASTART;
+
+  /* Encrypt/decrypt data */
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    /* Load key and block to be encrypted/decrypted */
+    for (i = 3, j = 7; i >= 0; i--, j--)
+    {
+      AES->KEYLA = __REV(_key[j]);
+      AES->KEYHA = __REV(_key[i]);
+      /* Write data last, since will trigger encryption on last iteration */
+      AES->DATA = __REV(_ctr[i]);
+    }
+    /* Increment ctr for next use */
+    ctrFunc(ctr);
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA) ^ _in[i];
+    }
+    _out += 4;
+    _in  += 4;
+  }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ *   Update last 32 bits of 128 bit counter, by incrementing with 1.
+ *
+ * @details
+ *   Notice that no special consideration is given to possible wrap around. If
+ *   32 least significant bits are 0xFFFFFFFF, they will be updated to 0x00000000,
+ *   ignoring overflow.
+ *
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[in,out] ctr
+ *   Buffer holding 128 bit counter to be updated.
+ ******************************************************************************/
+void AES_CTRUpdate32Bit(uint8_t *ctr)
+{
+  uint32_t *_ctr = (uint32_t *)ctr;
+
+  _ctr[3] = __REV(__REV(_ctr[3]) + 1);
+}
+
+
+/***************************************************************************//**
+ * @brief
+ *   Generate 128 bit decryption key from 128 bit encryption key. The decryption
+ *   key is used for some cipher modes when decrypting.
+ *
+ * @details
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place 128 bit decryption key. Must be at least 16 bytes long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding 128 bit encryption key. Must be at least 16 bytes long.
+ ******************************************************************************/
+void AES_DecryptKey128(uint8_t *out, const uint8_t *in)
+{
+  int            i;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+
+  /* Load key */
+  for (i = 3; i >= 0; i--)
+  {
+    AES->KEYLA = __REV(_in[i]);
+  }
+
+  /* Do dummy encryption to generate decrypt key */
+  AES->CTRL = 0;
+  AES_IntClear(AES_IF_DONE);
+  AES->CMD = AES_CMD_START;
+
+  /* Wait for completion */
+  while (AES->STATUS & AES_STATUS_RUNNING)
+    ;
+
+  /* Save decryption key */
+  for (i = 3; i >= 0; i--)
+  {
+    _out[i] = __REV(AES->KEYLA);
+  }
+}
+
+
+#if defined( AES_CTRL_AES256 )
+/***************************************************************************//**
+ * @brief
+ *   Generate 256 bit decryption key from 256 bit encryption key. The decryption
+ *   key is used for some cipher modes when decrypting.
+ *
+ * @details
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place 256 bit decryption key. Must be at least 32 bytes long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding 256 bit encryption key. Must be at least 32 bytes long.
+ ******************************************************************************/
+void AES_DecryptKey256(uint8_t *out, const uint8_t *in)
+{
+  int            i;
+  int            j;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+
+  /* Load key */
+  for (i = 3, j = 7; i >= 0; i--, j--)
+  {
+    AES->KEYLA = __REV(_in[j]);
+    AES->KEYHA = __REV(_in[i]);
+  }
+
+  /* Do dummy encryption to generate decrypt key */
+  AES->CTRL = AES_CTRL_AES256;
+  AES->CMD  = AES_CMD_START;
+
+  /* Wait for completion */
+  while (AES->STATUS & AES_STATUS_RUNNING)
+    ;
+
+  /* Save decryption key */
+  for (i = 3, j = 7; i >= 0; i--, j--)
+  {
+    _out[j] = __REV(AES->KEYLA);
+    _out[i] = __REV(AES->KEYHA);
+  }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ *   Electronic Codebook (ECB) cipher mode encryption/decryption, 128 bit key.
+ *
+ * @details
+ *   Encryption:
+ * @verbatim
+ *          Plaintext                  Plaintext
+ *              |                          |
+ *              V                          V
+ *       +--------------+           +--------------+
+ * Key ->| Block cipher |     Key ->| Block cipher |
+ *       |  encryption  |           |  encryption  |
+ *       +--------------+           +--------------+
+ *              |                          |
+ *              V                          V
+ *         Ciphertext                 Ciphertext
+ * @endverbatim
+ *   Decryption:
+ * @verbatim
+ *         Ciphertext                 Ciphertext
+ *              |                          |
+ *              V                          V
+ *       +--------------+           +--------------+
+ * Key ->| Block cipher |     Key ->| Block cipher |
+ *       |  decryption  |           |  decryption  |
+ *       +--------------+           +--------------+
+ *              |                          |
+ *              V                          V
+ *          Plaintext                  Plaintext
+ * @endverbatim
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   When doing encryption, this is the 128 bit encryption key. When doing
+ *   decryption, this is the 128 bit decryption key. The decryption key may
+ *   be generated from the encryption key with AES_DecryptKey128().
+ *
+ * @param[in] encrypt
+ *   Set to true to encrypt, false to decrypt.
+ ******************************************************************************/
+void AES_ECB128(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                bool encrypt)
+{
+  int            i;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  #if defined( AES_CTRL_KEYBUFEN )
+  /* Load key into high key for key buffer usage */
+  for (i = 3; i >= 0; i--)
+  {
+    AES->KEYHA = __REV(_key[i]);
+  }
+  #endif
+
+  if (encrypt)
+  {
+    /* Select encryption mode */
+    #if defined( AES_CTRL_KEYBUFEN )
+    AES->CTRL = AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
+    #else
+    AES->CTRL = AES_CTRL_DATASTART;
+    #endif
+  }
+  else
+  {
+    /* Select decryption mode */
+    #if defined( AES_CTRL_KEYBUFEN )
+    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_KEYBUFEN | AES_CTRL_DATASTART;
+    #else
+    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_DATASTART;
+    #endif
+  }
+
+  /* Encrypt/decrypt data */
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    #if !defined( AES_CTRL_KEYBUFEN )
+    /* Load key */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->KEYLA = __REV(_key[i]);
+    }
+    #endif
+
+    /* Load block to be encrypted/decrypted */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->DATA = __REV(_in[i]);
+    }
+    _in += 4;
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA);
+    }
+    _out += 4;
+  }
+}
+
+
+#if defined( AES_CTRL_AES256 )
+/***************************************************************************//**
+ * @brief
+ *   Electronic Codebook (ECB) cipher mode encryption/decryption, 256 bit key.
+ *
+ * @details
+ *   Please see AES_ECB128() for ECB figure.
+ *
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   When doing encryption, this is the 256 bit encryption key. When doing
+ *   decryption, this is the 256 bit decryption key. The decryption key may
+ *   be generated from the encryption key with AES_DecryptKey256().
+ *
+ * @param[in] encrypt
+ *   Set to true to encrypt, false to decrypt.
+ ******************************************************************************/
+void AES_ECB256(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                bool encrypt)
+{
+  int            i;
+  int            j;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  if (encrypt)
+  {
+    /* Select encryption mode */
+    AES->CTRL = AES_CTRL_AES256 | AES_CTRL_DATASTART;
+  }
+  else
+  {
+    /* Select decryption mode */
+    AES->CTRL = AES_CTRL_DECRYPT | AES_CTRL_AES256 | AES_CTRL_DATASTART;
+  }
+
+  /* Encrypt/decrypt data */
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    /* Load key and block to be encrypted/decrypted */
+    for (i = 3, j = 7; i >= 0; i--, j--)
+    {
+      AES->KEYLA = __REV(_key[j]);
+      AES->KEYHA = __REV(_key[i]);
+      /* Write data last, since will trigger encryption on last iteration */
+      AES->DATA = __REV(_in[i]);
+    }
+    _in += 4;
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA);
+    }
+    _out += 4;
+  }
+}
+#endif
+
+
+/***************************************************************************//**
+ * @brief
+ *   Output feedback (OFB) cipher mode encryption/decryption, 128 bit key.
+ *
+ * @details
+ *   Encryption:
+ * @verbatim
+ *          InitVector    +----------------+
+ *              |         |                |
+ *              V         |                V
+ *       +--------------+ |        +--------------+
+ * Key ->| Block cipher | |  Key ->| Block cipher |
+ *       |  encryption  | |        |  encryption  |
+ *       +--------------+ |        +--------------+
+ *              |         |                |
+ *              |---------+                |
+ *              V                          V
+ * Plaintext ->XOR            Plaintext ->XOR
+ *              |                          |
+ *              V                          V
+ *         Ciphertext                 Ciphertext
+ * @endverbatim
+ *   Decryption:
+ * @verbatim
+ *          InitVector    +----------------+
+ *              |         |                |
+ *              V         |                V
+ *       +--------------+ |        +--------------+
+ * Key ->| Block cipher | |  Key ->| Block cipher |
+ *       |  encryption  | |        |  encryption  |
+ *       +--------------+ |        +--------------+
+ *              |         |                |
+ *              |---------+                |
+ *              V                          V
+ * Ciphertext ->XOR           Ciphertext ->XOR
+ *              |                          |
+ *              V                          V
+ *          Plaintext                  Plaintext
+ * @endverbatim
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   128 bit encryption key.
+ *
+ * @param[in] iv
+ *   128 bit initalization vector to use.
+ ******************************************************************************/
+void AES_OFB128(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                const uint8_t *iv)
+{
+  int            i;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  const uint32_t *_iv  = (const uint32_t *)iv;
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  /* Select encryption mode, trigger explicitly by command */
+  #if defined( AES_CTRL_KEYBUFEN )
+  AES->CTRL = AES_CTRL_KEYBUFEN;
+  #else
+  AES->CTRL = 0;
+  #endif
+
+  /* Load key into high key for key buffer usage */
+  /* Load initialization vector */
+  for (i = 3; i >= 0; i--)
+  {
+    #if defined( AES_CTRL_KEYBUFEN )
+    AES->KEYHA = __REV(_key[i]);
+    #endif
+    AES->DATA  = __REV(_iv[i]);
+  }
+
+  /* Encrypt/decrypt data */
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    #if !defined( AES_CTRL_KEYBUFEN )
+    /* Load key */
+    for (i = 3; i >= 0; i--)
+    {
+      AES->KEYLA = __REV(_key[i]);
+    }
+    #endif
+
+    AES->CMD = AES_CMD_START;
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA) ^ _in[i];
+    }
+    _out += 4;
+    _in  += 4;
+  }
+}
+
+
+#if defined( AES_CTRL_AES256 )
+/***************************************************************************//**
+ * @brief
+ *   Output feedback (OFB) cipher mode encryption/decryption, 256 bit key.
+ *
+ * @details
+ *   Please see AES_OFB128() for OFB figure.
+ *
+ *   Please refer to general comments on layout and byte ordering of parameters.
+ *
+ * @param[out] out
+ *   Buffer to place encrypted/decrypted data. Must be at least @p len long. It
+ *   may be set equal to @p in, in which case the input buffer is overwritten.
+ *
+ * @param[in] in
+ *   Buffer holding data to encrypt/decrypt. Must be at least @p len long.
+ *
+ * @param[in] len
+ *   Number of bytes to encrypt/decrypt. Must be a multiple of 16.
+ *
+ * @param[in] key
+ *   256 bit encryption key.
+ *
+ * @param[in] iv
+ *   128 bit initalization vector to use.
+ ******************************************************************************/
+void AES_OFB256(uint8_t *out,
+                const uint8_t *in,
+                unsigned int len,
+                const uint8_t *key,
+                const uint8_t *iv)
+{
+  int            i;
+  int            j;
+  uint32_t       *_out = (uint32_t *)out;
+  const uint32_t *_in  = (const uint32_t *)in;
+  const uint32_t *_key = (const uint32_t *)key;
+  const uint32_t *_iv  = (const uint32_t *)iv;
+
+  EFM_ASSERT(!(len % AES_BLOCKSIZE));
+
+  /* Select encryption mode, trigger explicitly by command */
+  AES->CTRL = AES_CTRL_AES256;
+
+  /* Load initialization vector */
+  for (i = 3; i >= 0; i--)
+  {
+    AES->DATA = __REV(_iv[i]);
+  }
+
+  /* Encrypt/decrypt data */
+  len /= AES_BLOCKSIZE;
+  while (len--)
+  {
+    /* Load key */
+    for (i = 3, j = 7; i >= 0; i--, j--)
+    {
+      AES->KEYLA = __REV(_key[j]);
+      AES->KEYHA = __REV(_key[i]);
+    }
+
+    AES->CMD = AES_CMD_START;
+
+    /* Wait for completion */
+    while (AES->STATUS & AES_STATUS_RUNNING)
+      ;
+
+    /* Save encrypted/decrypted data */
+    for (i = 3; i >= 0; i--)
+    {
+      _out[i] = __REV(AES->DATA) ^ _in[i];
+    }
+    _out += 4;
+    _in  += 4;
+  }
+}
+#endif
+
+
+/** @} (end addtogroup AES) */
+/** @} (end addtogroup EM_Library) */
+#endif /* defined(AES_COUNT) && (AES_COUNT > 0) */