Dependencies:   AccelSensor BLE_API mbed nRF51822

Committer:
fjaviercifuentes
Date:
Fri Jan 19 02:38:38 2018 +0000
Revision:
0:027b7829b46a

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fjaviercifuentes 0:027b7829b46a 1 #include "nrf_soc.h"
fjaviercifuentes 0:027b7829b46a 2 #include "nrf_delay.h"
fjaviercifuentes 0:027b7829b46a 3 #include "app_error.h"
fjaviercifuentes 0:027b7829b46a 4
fjaviercifuentes 0:027b7829b46a 5 #define ECB_KEY_LEN (16UL)
fjaviercifuentes 0:027b7829b46a 6 #define COUNTER_BYTE_LEN (4UL)
fjaviercifuentes 0:027b7829b46a 7 #define NONCE_RAND_BYTE_LEN (12UL)
fjaviercifuentes 0:027b7829b46a 8
fjaviercifuentes 0:027b7829b46a 9 // The RNG wait values are typical and not guaranteed. See Product Specifications for more info.
fjaviercifuentes 0:027b7829b46a 10 #ifdef NRF51
fjaviercifuentes 0:027b7829b46a 11 #define RNG_BYTE_WAIT_US (677UL)
fjaviercifuentes 0:027b7829b46a 12 #elif defined NRF52
fjaviercifuentes 0:027b7829b46a 13 #define RNG_BYTE_WAIT_US (124UL)
fjaviercifuentes 0:027b7829b46a 14 #else
fjaviercifuentes 0:027b7829b46a 15 #error "Either NRF51 or NRF52 must be defined."
fjaviercifuentes 0:027b7829b46a 16 #endif
fjaviercifuentes 0:027b7829b46a 17
fjaviercifuentes 0:027b7829b46a 18 /**
fjaviercifuentes 0:027b7829b46a 19 * @brief Uses the RNG to write a 12-byte nonce to a buffer
fjaviercifuentes 0:027b7829b46a 20 * @details The 12 bytes will be written to the buffer starting at index 4 to leave
fjaviercifuentes 0:027b7829b46a 21 * space for the 4-byte counter value.
fjaviercifuentes 0:027b7829b46a 22 *
fjaviercifuentes 0:027b7829b46a 23 * @param[in] p_buf An array of length 16
fjaviercifuentes 0:027b7829b46a 24 */
fjaviercifuentes 0:027b7829b46a 25 void nonce_generate(uint8_t * p_buf)
fjaviercifuentes 0:027b7829b46a 26 {
fjaviercifuentes 0:027b7829b46a 27 uint8_t i = COUNTER_BYTE_LEN;
fjaviercifuentes 0:027b7829b46a 28 uint8_t remaining = NONCE_RAND_BYTE_LEN;
fjaviercifuentes 0:027b7829b46a 29
fjaviercifuentes 0:027b7829b46a 30 // The random number pool may not contain enough bytes at the moment so
fjaviercifuentes 0:027b7829b46a 31 // a busy wait may be necessary.
fjaviercifuentes 0:027b7829b46a 32 while(0 != remaining)
fjaviercifuentes 0:027b7829b46a 33 {
fjaviercifuentes 0:027b7829b46a 34 uint32_t err_code;
fjaviercifuentes 0:027b7829b46a 35 uint8_t available = 0;
fjaviercifuentes 0:027b7829b46a 36
fjaviercifuentes 0:027b7829b46a 37 err_code = sd_rand_application_bytes_available_get(&available);
fjaviercifuentes 0:027b7829b46a 38 APP_ERROR_CHECK(err_code);
fjaviercifuentes 0:027b7829b46a 39
fjaviercifuentes 0:027b7829b46a 40 available = ((available > remaining) ? remaining : available);
fjaviercifuentes 0:027b7829b46a 41 if (0 != available)
fjaviercifuentes 0:027b7829b46a 42 {
fjaviercifuentes 0:027b7829b46a 43 err_code = sd_rand_application_vector_get((p_buf + i), available);
fjaviercifuentes 0:027b7829b46a 44 APP_ERROR_CHECK(err_code);
fjaviercifuentes 0:027b7829b46a 45
fjaviercifuentes 0:027b7829b46a 46 i += available;
fjaviercifuentes 0:027b7829b46a 47 remaining -= available;
fjaviercifuentes 0:027b7829b46a 48 }
fjaviercifuentes 0:027b7829b46a 49
fjaviercifuentes 0:027b7829b46a 50 if (0 != remaining)
fjaviercifuentes 0:027b7829b46a 51 {
fjaviercifuentes 0:027b7829b46a 52 nrf_delay_us(RNG_BYTE_WAIT_US * remaining);
fjaviercifuentes 0:027b7829b46a 53 }
fjaviercifuentes 0:027b7829b46a 54 }
fjaviercifuentes 0:027b7829b46a 55 }
fjaviercifuentes 0:027b7829b46a 56
fjaviercifuentes 0:027b7829b46a 57 static bool m_initialized = false;
fjaviercifuentes 0:027b7829b46a 58
fjaviercifuentes 0:027b7829b46a 59 // NOTE: The ECB data must be located in RAM or a HardFault will be triggered.
fjaviercifuentes 0:027b7829b46a 60 static nrf_ecb_hal_data_t m_ecb_data;
fjaviercifuentes 0:027b7829b46a 61
fjaviercifuentes 0:027b7829b46a 62 /**
fjaviercifuentes 0:027b7829b46a 63 * @brief Initializes the module with the given nonce and key
fjaviercifuentes 0:027b7829b46a 64 * @details The nonce will be copied to an internal buffer so it does not need to
fjaviercifuentes 0:027b7829b46a 65 * be retained after the function returns. Additionally, a 32-bit counter
fjaviercifuentes 0:027b7829b46a 66 * will be initialized to zero and placed into the least-significant 4 bytes
fjaviercifuentes 0:027b7829b46a 67 * of the internal buffer. The nonce value should be generated in a
fjaviercifuentes 0:027b7829b46a 68 * reasonable manner (e.g. using this module's nonce_generate function).
fjaviercifuentes 0:027b7829b46a 69 *
fjaviercifuentes 0:027b7829b46a 70 * @param[in] p_nonce An array of length 16 containing 12 random bytes
fjaviercifuentes 0:027b7829b46a 71 * starting at index 4
fjaviercifuentes 0:027b7829b46a 72 * @param[in] p_ecb_key An array of length 16 containing the ECB key
fjaviercifuentes 0:027b7829b46a 73 */
fjaviercifuentes 0:027b7829b46a 74 void ctr_init(const uint8_t * p_nonce, const uint8_t * p_ecb_key)
fjaviercifuentes 0:027b7829b46a 75 {
fjaviercifuentes 0:027b7829b46a 76 m_initialized = true;
fjaviercifuentes 0:027b7829b46a 77
fjaviercifuentes 0:027b7829b46a 78 // Save the key.
fjaviercifuentes 0:027b7829b46a 79 memcpy(&m_ecb_data.key[0], p_ecb_key, ECB_KEY_LEN);
fjaviercifuentes 0:027b7829b46a 80
fjaviercifuentes 0:027b7829b46a 81 // Copy the nonce.
fjaviercifuentes 0:027b7829b46a 82 memcpy(&m_ecb_data.cleartext[COUNTER_BYTE_LEN],
fjaviercifuentes 0:027b7829b46a 83 &p_nonce[COUNTER_BYTE_LEN],
fjaviercifuentes 0:027b7829b46a 84 NONCE_RAND_BYTE_LEN);
fjaviercifuentes 0:027b7829b46a 85
fjaviercifuentes 0:027b7829b46a 86 // Zero the counter value.
fjaviercifuentes 0:027b7829b46a 87 memset(&m_ecb_data.cleartext[0], 0x00, COUNTER_BYTE_LEN);
fjaviercifuentes 0:027b7829b46a 88 }
fjaviercifuentes 0:027b7829b46a 89
fjaviercifuentes 0:027b7829b46a 90 static uint32_t crypt(uint8_t * buf)
fjaviercifuentes 0:027b7829b46a 91 {
fjaviercifuentes 0:027b7829b46a 92 uint8_t i;
fjaviercifuentes 0:027b7829b46a 93 uint32_t err_code;
fjaviercifuentes 0:027b7829b46a 94
fjaviercifuentes 0:027b7829b46a 95 if (!m_initialized)
fjaviercifuentes 0:027b7829b46a 96 {
fjaviercifuentes 0:027b7829b46a 97 return NRF_ERROR_INVALID_STATE;
fjaviercifuentes 0:027b7829b46a 98 }
fjaviercifuentes 0:027b7829b46a 99
fjaviercifuentes 0:027b7829b46a 100 err_code = sd_ecb_block_encrypt(&m_ecb_data);
fjaviercifuentes 0:027b7829b46a 101 if (NRF_SUCCESS != err_code)
fjaviercifuentes 0:027b7829b46a 102 {
fjaviercifuentes 0:027b7829b46a 103 return err_code;
fjaviercifuentes 0:027b7829b46a 104 }
fjaviercifuentes 0:027b7829b46a 105
fjaviercifuentes 0:027b7829b46a 106 for (i=0; i < ECB_KEY_LEN; i++)
fjaviercifuentes 0:027b7829b46a 107 {
fjaviercifuentes 0:027b7829b46a 108 buf[i] ^= m_ecb_data.ciphertext[i];
fjaviercifuentes 0:027b7829b46a 109 }
fjaviercifuentes 0:027b7829b46a 110
fjaviercifuentes 0:027b7829b46a 111 // Increment the counter.
fjaviercifuentes 0:027b7829b46a 112 (*((uint32_t*) m_ecb_data.cleartext))++;
fjaviercifuentes 0:027b7829b46a 113
fjaviercifuentes 0:027b7829b46a 114 return NRF_SUCCESS;
fjaviercifuentes 0:027b7829b46a 115 }
fjaviercifuentes 0:027b7829b46a 116
fjaviercifuentes 0:027b7829b46a 117 /**
fjaviercifuentes 0:027b7829b46a 118 * @brief Encrypts the given buffer in-situ
fjaviercifuentes 0:027b7829b46a 119 * @details The encryption step is done separately (using the nonce, counter, and
fjaviercifuentes 0:027b7829b46a 120 * key) and then the result from the encryption is XOR'd with the given
fjaviercifuentes 0:027b7829b46a 121 * buffer in-situ. The counter will be incremented only if no error occurs.
fjaviercifuentes 0:027b7829b46a 122 *
fjaviercifuentes 0:027b7829b46a 123 * @param[in] p_clear_text An array of length 16 containing the clear text
fjaviercifuentes 0:027b7829b46a 124 *
fjaviercifuentes 0:027b7829b46a 125 * @retval NRF_SUCCESS Success
fjaviercifuentes 0:027b7829b46a 126 * @retval NRF_ERROR_INVALID_STATE Module has not been initialized
fjaviercifuentes 0:027b7829b46a 127 * @retval NRF_ERROR_SOFTDEVICE_NOT_ENABLED SoftDevice is present, but not enabled
fjaviercifuentes 0:027b7829b46a 128 */
fjaviercifuentes 0:027b7829b46a 129 uint32_t ctr_encrypt(uint8_t * p_clear_text)
fjaviercifuentes 0:027b7829b46a 130 {
fjaviercifuentes 0:027b7829b46a 131 return crypt(p_clear_text);
fjaviercifuentes 0:027b7829b46a 132 }
fjaviercifuentes 0:027b7829b46a 133
fjaviercifuentes 0:027b7829b46a 134 /**
fjaviercifuentes 0:027b7829b46a 135 * @brief Decrypts the given buffer in-situ
fjaviercifuentes 0:027b7829b46a 136 * @details The encryption step is done separately (using the nonce, counter, and
fjaviercifuentes 0:027b7829b46a 137 * key) and then the result from the encryption is XOR'd with the given
fjaviercifuentes 0:027b7829b46a 138 * buffer in-situ. The counter will be incremented only if no error occurs.
fjaviercifuentes 0:027b7829b46a 139 *
fjaviercifuentes 0:027b7829b46a 140 * @param[in] p_cipher_text An array of length 16 containing the cipher text
fjaviercifuentes 0:027b7829b46a 141 *
fjaviercifuentes 0:027b7829b46a 142 * @retval NRF_SUCCESS Succeess
fjaviercifuentes 0:027b7829b46a 143 * @retval NRF_ERROR_INVALID_STATE Module has not been initialized
fjaviercifuentes 0:027b7829b46a 144 * @retval NRF_ERROR_SOFTDEVICE_NOT_ENABLED SoftDevice is present, but not enabled
fjaviercifuentes 0:027b7829b46a 145 */
fjaviercifuentes 0:027b7829b46a 146 uint32_t ctr_decrypt(uint8_t * p_cipher_text)
fjaviercifuentes 0:027b7829b46a 147 {
fjaviercifuentes 0:027b7829b46a 148 return crypt(p_cipher_text);
fjaviercifuentes 0:027b7829b46a 149 }
fjaviercifuentes 0:027b7829b46a 150