#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/types.h>
#if defined(WOLFSSL_NRF51) || defined(WOLFSSL_NRF5x)
#include "bsp.h"
#include "nrf_delay.h"
#include "app_uart.h"
#include "app_error.h"
#include "nrf_drv_rng.h"
#include "nrf_drv_rtc.h"
#include "nrf_drv_clock.h"
#include "nrf_ecb.h"
#ifdef SOFTDEVICE_PRESENT
#include "softdevice_handler.h"
#include "nrf_soc.h"
#endif
#ifndef NO_CRYPT_BENCHMARK
static volatile byte mRtcInitDone = 0;
static volatile int mRtcSec = 0;
const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(0);
#endif
#if !defined(NO_AES) && defined(WOLFSSL_NRF51_AES) && !defined(SOFTDEVICE_PRESENT)
static volatile byte mAesInitDone = 0;
#endif
int nrf51_random_generate(byte* output, word32 size)
{
word32 remaining = size;
word32 pos = 0;
uint8_t length;
uint8_t available;
uint32_t err_code;
err_code = nrf_drv_rng_init(NULL);
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
return -1;
}
err_code = NRF_SUCCESS;
while (remaining > 0) {
available = 0;
nrf_drv_rng_bytes_available(&available);
length = (remaining < (word32)available) ? (uint8_t)remaining :
available;
if (length > 0) {
err_code = nrf_drv_rng_rand(&output[pos], length);
if (err_code != NRF_SUCCESS) {
break;
}
remaining -= length;
pos += length;
}
else {
nrf_delay_us(100);
}
}
return (err_code == NRF_SUCCESS) ? 0 : -1;
}
#if !defined(NO_AES) && defined(WOLFSSL_NRF51_AES)
#ifdef SOFTDEVICE_PRESENT
static const byte* nRF51AesKey = NULL;
#endif
int nrf51_aes_set_key(const byte* key)
{
#ifdef SOFTDEVICE_PRESENT
nRF51AesKey = key;
#else
if (!mAesInitDone) {
nrf_ecb_init();
mAesInitDone = 1;
}
nrf_ecb_set_key(key);
#endif
return 0;
}
int nrf51_aes_encrypt(const byte* in, const byte* key, word32 rounds, byte* out)
{
int ret;
#ifdef SOFTDEVICE_PRESENT
uint32_t err_code = 0;
nrf_ecb_hal_data_t ecb_hal_data;
#endif
(void)rounds;
ret = nrf51_aes_set_key(key);
if (ret != 0) {
return ret;
}
#ifdef SOFTDEVICE_PRESENT
XMEMCPY(ecb_hal_data.key, nRF51AesKey, SOC_ECB_KEY_LENGTH);
XMEMCPY(ecb_hal_data.cleartext, in, SOC_ECB_CLEARTEXT_LENGTH);
XMEMSET(ecb_hal_data.ciphertext, 0, SOC_ECB_CIPHERTEXT_LENGTH);
err_code = sd_ecb_block_encrypt(&ecb_hal_data);
if (err_code != NRF_SUCCESS) {
return -1;
}
XMEMCPY(out, ecb_hal_data.ciphertext, SOC_ECB_CIPHERTEXT_LENGTH);
#else
if (nrf_ecb_crypt(out, in))
ret = 0;
else
ret = -1;
#endif
return ret;
}
#endif
#ifndef NO_CRYPT_BENCHMARK
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
if (int_type == NRF_DRV_RTC_INT_COMPARE0) {
mRtcSec++;
nrf_drv_rtc_counter_clear(&rtc);
nrf_drv_rtc_int_enable(&rtc, RTC_CHANNEL_INT_MASK(0));
#ifdef BSP_LED_0
nrf_gpio_pin_toggle(BSP_LED_0);
#endif
}
}
#ifndef RTC0_CONFIG_FREQUENCY
#define RTC0_CONFIG_FREQUENCY 32768
#endif
static void rtc_config(void)
{
uint32_t err_code;
#if defined(NRF52) || defined(NRF52_SERIES)
err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
nrf_drv_clock_lfclk_request(NULL);
#else
err_code = nrf_drv_clock_init(NULL);
APP_ERROR_CHECK(err_code);
nrf_drv_clock_lfclk_request();
#endif
err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_rtc_tick_enable(&rtc, false);
err_code = nrf_drv_rtc_cc_set(&rtc, 0, RTC0_CONFIG_FREQUENCY, true);
APP_ERROR_CHECK(err_code);
nrf_drv_rtc_enable(&rtc);
}
static int rtc_get_ms(void)
{
uint32_t frequency = (32768 / (rtc_prescaler_get(rtc.p_reg) + 1));
uint32_t counter = nrf_drv_rtc_counter_get(&rtc);
return (int)((((uint64_t)counter * 1000) + (frequency / 2)) / frequency);
}
double current_time(int reset)
{
double time;
int sec;
(void)reset;
if (!mRtcInitDone) {
rtc_config();
mRtcInitDone = 1;
}
do {
sec = mRtcSec;
time = sec + ((double)rtc_get_ms() / 1000);
} while (sec != mRtcSec);
return time;
}
#endif
#endif