javier cifuentes / Mbed 2 deprecated IMOB_with_encryption

Dependencies:   AccelSensor BLE_API mbed nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers crypt.h Source File

crypt.h

00001 #include "nrf_soc.h"
00002 #include "nrf_delay.h"
00003 #include "app_error.h"
00004 
00005 #define ECB_KEY_LEN            (16UL)
00006 #define COUNTER_BYTE_LEN       (4UL)
00007 #define NONCE_RAND_BYTE_LEN    (12UL)
00008 
00009 // The RNG wait values are typical and not guaranteed. See Product Specifications for more info.
00010 #ifdef NRF51
00011 #define RNG_BYTE_WAIT_US       (677UL)
00012 #elif defined NRF52
00013 #define RNG_BYTE_WAIT_US       (124UL)
00014 #else
00015 #error "Either NRF51 or NRF52 must be defined."
00016 #endif
00017 
00018 /**
00019  * @brief Uses the RNG to write a 12-byte nonce to a buffer
00020  * @details The 12 bytes will be written to the buffer starting at index 4 to leave
00021  *          space for the 4-byte counter value.
00022  *
00023  * @param[in]    p_buf    An array of length 16
00024  */
00025 void nonce_generate(uint8_t * p_buf)
00026 {
00027     uint8_t i         = COUNTER_BYTE_LEN;
00028     uint8_t remaining = NONCE_RAND_BYTE_LEN;
00029 
00030     // The random number pool may not contain enough bytes at the moment so
00031     // a busy wait may be necessary.
00032     while(0 != remaining)
00033     {
00034         uint32_t err_code;
00035         uint8_t  available = 0;
00036 
00037         err_code = sd_rand_application_bytes_available_get(&available);
00038         APP_ERROR_CHECK(err_code);
00039 
00040         available = ((available > remaining) ? remaining : available);
00041         if (0 != available)
00042         {
00043             err_code = sd_rand_application_vector_get((p_buf + i), available);
00044             APP_ERROR_CHECK(err_code);
00045 
00046             i         += available;
00047             remaining -= available;
00048         }
00049 
00050         if (0 != remaining)
00051         {
00052             nrf_delay_us(RNG_BYTE_WAIT_US * remaining);
00053         }
00054     }    
00055 }
00056 
00057 static bool m_initialized = false;
00058 
00059 // NOTE: The ECB data must be located in RAM or a HardFault will be triggered.
00060 static nrf_ecb_hal_data_t m_ecb_data;
00061 
00062 /**
00063  * @brief Initializes the module with the given nonce and key
00064  * @details The nonce will be copied to an internal buffer so it does not need to
00065  *          be retained after the function returns. Additionally, a 32-bit counter
00066  *          will be initialized to zero and placed into the least-significant 4 bytes
00067  *          of the internal buffer. The nonce value should be generated in a
00068  *          reasonable manner (e.g. using this module's nonce_generate function).
00069  *
00070  * @param[in]    p_nonce    An array of length 16 containing 12 random bytes
00071  *                          starting at index 4
00072  * @param[in]    p_ecb_key  An array of length 16 containing the ECB key
00073  */
00074 void ctr_init(const uint8_t * p_nonce, const uint8_t * p_ecb_key)
00075 {
00076     m_initialized = true;
00077 
00078     // Save the key.
00079     memcpy(&m_ecb_data.key[0], p_ecb_key, ECB_KEY_LEN);
00080 
00081     // Copy the nonce.
00082     memcpy(&m_ecb_data.cleartext[COUNTER_BYTE_LEN],
00083               &p_nonce[COUNTER_BYTE_LEN],
00084               NONCE_RAND_BYTE_LEN);
00085 
00086     // Zero the counter value.
00087     memset(&m_ecb_data.cleartext[0], 0x00, COUNTER_BYTE_LEN);
00088 }
00089 
00090 static uint32_t crypt(uint8_t * buf)
00091 {
00092     uint8_t  i;
00093     uint32_t err_code;
00094 
00095     if (!m_initialized)
00096     {
00097         return NRF_ERROR_INVALID_STATE;
00098     }
00099 
00100     err_code = sd_ecb_block_encrypt(&m_ecb_data);
00101     if (NRF_SUCCESS != err_code)
00102     {
00103         return err_code;
00104     }
00105 
00106     for (i=0; i < ECB_KEY_LEN; i++)
00107     {
00108         buf[i] ^= m_ecb_data.ciphertext[i];
00109     }
00110 
00111     // Increment the counter.
00112     (*((uint32_t*) m_ecb_data.cleartext))++;
00113 
00114     return NRF_SUCCESS;
00115 }
00116 
00117 /**
00118  * @brief Encrypts the given buffer in-situ
00119  * @details The encryption step is done separately (using the nonce, counter, and
00120  *          key) and then the result from the encryption is XOR'd with the given
00121  *          buffer in-situ. The counter will be incremented only if no error occurs.
00122  *
00123  * @param[in]    p_clear_text    An array of length 16 containing the clear text
00124  *
00125  * @retval    NRF_SUCCESS                         Success
00126  * @retval    NRF_ERROR_INVALID_STATE             Module has not been initialized
00127  * @retval    NRF_ERROR_SOFTDEVICE_NOT_ENABLED    SoftDevice is present, but not enabled
00128  */
00129 uint32_t ctr_encrypt(uint8_t * p_clear_text)
00130 {
00131     return crypt(p_clear_text);
00132 }
00133 
00134 /**
00135  * @brief Decrypts the given buffer in-situ
00136  * @details The encryption step is done separately (using the nonce, counter, and
00137  *          key) and then the result from the encryption is XOR'd with the given
00138  *          buffer in-situ. The counter will be incremented only if no error occurs.
00139  *
00140  * @param[in]    p_cipher_text    An array of length 16 containing the cipher text
00141  *
00142  * @retval    NRF_SUCCESS                         Succeess
00143  * @retval    NRF_ERROR_INVALID_STATE             Module has not been initialized
00144  * @retval    NRF_ERROR_SOFTDEVICE_NOT_ENABLED    SoftDevice is present, but not enabled
00145  */
00146 uint32_t ctr_decrypt(uint8_t * p_cipher_text)
00147 {
00148     return crypt(p_cipher_text);
00149 }
00150