Dependencies: AccelSensor BLE_API mbed nRF51822
crypt.h@0:027b7829b46a, 2018-01-19 (annotated)
- Committer:
- fjaviercifuentes
- Date:
- Fri Jan 19 02:38:38 2018 +0000
- Revision:
- 0:027b7829b46a
Who changed what in which revision?
User | Revision | Line number | New 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 |