/****************************************************************************** * 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 * * 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 #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, ®val, 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, ®val, 1); } return ret; } /****************************************************************************** * Name: * * 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: * * 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: * * 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: * * 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); }