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