nuttx/drivers/wireless/spirit/lib/spirit_aes.c

363 lines
11 KiB
C

/******************************************************************************
* drivers/wireless/spirit/lib/spirit_aes.c
* Configuration and management of SPIRIT AES Engine.
*
* Copyright(c) 2015 STMicroelectronics
* Author: VMA division - AMS
* Version 3.2.2 08-July-2015
*
* Adapted for NuttX by:
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************/
/******************************************************************************
* Included Files
******************************************************************************/
#include <assert.h>
#include "spirit_aes.h"
#include "spirit_spi.h"
/******************************************************************************
* Public Functions
******************************************************************************/
/******************************************************************************
* Name: spirit_aes_enable
*
* Description:
* Enables or Disables the AES engine.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
* newstate new state for AES engine.
* This parameter can be: S_ENABLE or S_DISABLE.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_enable(FAR struct spirit_library_s *spirit,
enum spirit_functional_state_e newstate)
{
uint8_t regval = 0;
int ret;
/* Check the parameters */
DEBUGASSERT(IS_SPIRIT_FUNCTIONAL_STATE(newstate));
/* Modifies the register value */
ret = spirit_reg_read(spirit, ANA_FUNC_CONF0_BASE, &regval, 1);
if (ret >= 0)
{
if (newstate == S_ENABLE)
{
regval |= AES_MASK;
}
else
{
regval &= ~AES_MASK;
}
/* Write to the ANA_FUNC_CONF0 register to enable or disable the AES
* engine
*/
ret = spirit_reg_write(spirit, ANA_FUNC_CONF0_BASE, &regval, 1);
}
return ret;
}
/******************************************************************************
* Name: spirit_aes_write_datain
*
* Description:
* Writes the data to encrypt or decrypt, or the encryption key for the
* derive decryption key operation into the AES_DATA_IN registers.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
* buffer - Pointer to the user data buffer. The first byte of the array
* must be the MSB byte and it will be put in the AES_DATA_IN[0]
* register, while the last one must be the LSB and it will be
* put in the AES_DATA_IN[buflen-1] register. If data to write
* are less than 16 bytes the remaining AES_DATA_IN registers
* will be filled with bytes equal to 0.
* buflen - Length of data in bytes.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_write_datain(FAR struct spirit_library_s *spirit,
FAR const uint8_t *buffer, uint8_t buflen)
{
uint8_t datain[16];
uint8_t i;
/* Verifies that there are no more than 16 bytes */
(buflen > 16) ? (buflen = 16) : buflen;
/* Fill the datain with the data buffer, using padding */
for (i = 0; i < 16; i++)
{
if (i < (16 - buflen))
{
datain[i] = 0;
}
else
{
datain[i] = buffer[15 - i];
}
}
/* Writes the AES_DATA_IN registers */
return spirit_reg_write(spirit, AES_DATA_IN_15_BASE, datain, 16);
}
/******************************************************************************
* Name: spirit_aes_read_dataout
*
* Description:
* Returns the encrypted or decrypted data or the decription key from the
* AES_DATA_OUT register.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
* buffer - pointer to the user data buffer. The AES_DATA_OUT[0]
* register value will be put as first element of the buffer
* (MSB), while the AES_DAT_OUT[buflen-1] register value will be
* put as last element of the buffer (LSB).
* buflen - Length of data to read in bytes.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_read_dataout(FAR struct spirit_library_s *spirit,
FAR uint8_t *buffer, uint8_t buflen)
{
uint8_t dataout[16];
uint8_t address;
int ret;
/* Verifies that there are no more than 16 bytes */
if (buflen > 16)
{
buflen = 16;
}
/* Evaluates the address of AES_DATA_OUT from which start to read */
address = AES_DATA_OUT_15_BASE + 16 - buflen;
/* Reads the exact number of AES_DATA_OUT registers */
ret = spirit_reg_read(spirit, address, dataout, buflen);
if (ret >= 0)
{
int i;
/* Copy in the user buffer the read values changing the order */
for (i = buflen - 1; i >= 0; i--)
{
*buffer++ = dataout[i];
}
}
return ret;
}
/******************************************************************************
* Name: spirit_aes_write_key
*
* Description:
* Writes the encryption key into the AES_KEY_IN register.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
* key - Pointer to the buffer of 4 words containing the AES key.
* The first byte of the buffer must be the most significant byte
* AES_KEY_0 of the AES key. The last byte of the buffer must be
* the less significant byte AES_KEY_15 of the AES key.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_write_key(FAR struct spirit_library_s *spirit,
FAR const uint8_t *key)
{
uint8_t tmp[16];
int i;
for (i = 0; i < 16; i++)
{
tmp[15 - i] = key[i];
}
/* Write to the AES_DATA_IN registers */
return spirit_reg_write(spirit, AES_KEY_IN_15_BASE, tmp, 16);
}
/******************************************************************************
* Name: spirit_aes_read_key
*
* Description:
* Returns the encryption/decryption key from the AES_KEY_IN register.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
* key - Pointer to the buffer of 4 words (16 bytes) containing the AES
* key. The first byte of the buffer shall be the most
* significant byte AES_KEY_0 of the AES key.
* The last byte of the buffer shall be the less significant byte
* AES_KEY_15 of the AES key. This parameter is an uint8_t*.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_read_key(FAR struct spirit_library_s *spirit, FAR uint8_t *key)
{
uint8_t tmp[16];
int ret;
int i;
/* Reads the AES_DATA_IN registers */
ret = spirit_reg_read(spirit, AES_KEY_IN_15_BASE, tmp, 16);
if (ret >= 0)
{
for (i = 0; i < 16; i++)
{
key[i] = tmp[15 - i];
}
}
return ret;
}
/******************************************************************************
* Name: spirit_aes_enc2deckey
*
* Description:
* Derives the decryption key from a given encryption key.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_enc2deckey(FAR struct spirit_library_s *spirit)
{
/* Sends the COMMAND_AES_KEY command */
return spirit_command(spirit, COMMAND_AES_KEY);
}
/******************************************************************************
* Name: spirit_aes_encrypt
*
* Description:
* Executes the encryption operation.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_encrypt(FAR struct spirit_library_s *spirit)
{
/* Sends the COMMAND_AES_ENC command */
return spirit_command(spirit, COMMAND_AES_ENC);
}
/******************************************************************************
* Name: spirit_aes_decrypt
*
* Description:
* Executes the decryption operation.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_decrypt(FAR struct spirit_library_s *spirit)
{
/* Sends the COMMAND_AES_DEC command */
return spirit_command(spirit, COMMAND_AES_DEC);
}
/******************************************************************************
* Name: spirit_aes_derivekey_decrypt
*
* Description:
* Executes the key derivation and the decryption operation.
*
* Input Parameters:
* spirit - Reference to a Spirit library state structure instance
*
* Returned Value:
* Zero (OK) on success; a negated errno value on any failure.
*
******************************************************************************/
int spirit_aes_derivekey_decrypt(FAR struct spirit_library_s *spirit)
{
/* Sends the COMMAND_AES_KEY_DEC command */
return spirit_command(spirit, COMMAND_AES_KEY_DEC);
}