mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
drivers/crypto: add Microchip RNG90 driver
Add Microchip RNG90 TRNG driver with board integration for esp32c3 and rng90 defconfig support. Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
This commit is contained in:
parent
03685825c9
commit
e5d8959128
11 changed files with 697 additions and 0 deletions
74
boards/risc-v/esp32c3/common/include/esp_board_rng90.h
Normal file
74
boards/risc-v/esp32c3/common/include/esp_board_rng90.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/****************************************************************************
|
||||
* boards/risc-v/esp32c3/common/include/esp_board_rng90.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_RNG90_H
|
||||
#define __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_RNG90_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_rng90_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize and register the RNG90 True Random Number Generator driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devno - The device number, used to build the device path as /dev/rngN
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEV_RNG90
|
||||
int board_rng90_initialize(int devno);
|
||||
#endif /* CONFIG_DEV_RNG90 */
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_RNG90_H */
|
||||
|
|
@ -76,6 +76,10 @@ if(CONFIG_ARCH_BOARD_COMMON)
|
|||
list(APPEND SRCS esp_board_bmp280.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DEV_RNG90)
|
||||
list(APPEND SRCS esp_board_rng90.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_MMCSD_SPI)
|
||||
list(APPEND SRCS esp_board_mmcsd.c)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ ifeq ($(CONFIG_SENSORS_BMP280),y)
|
|||
CSRCS += esp_board_bmp280.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEV_RNG90),y)
|
||||
CSRCS += esp_board_rng90.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MMCSD_SPI),y)
|
||||
CSRCS += esp_board_mmcsd.c
|
||||
endif
|
||||
|
|
|
|||
95
boards/risc-v/esp32c3/common/src/esp_board_rng90.c
Normal file
95
boards/risc-v/esp32c3/common/src/esp_board_rng90.c
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/****************************************************************************
|
||||
* boards/risc-v/esp32c3/common/src/esp_board_rng90.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/crypto/rng90.h>
|
||||
#include <nuttx/debug.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#ifndef CONFIG_ESPRESSIF_I2C_BITBANG
|
||||
# include "espressif/esp_i2c.h"
|
||||
#else
|
||||
# include "espressif/esp_i2c_bitbang.h"
|
||||
#endif
|
||||
|
||||
#include "esp_board_rng90.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_rng90_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize and register the RNG90 True Random Number Generator driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devno - The device number, used to build the device path as /dev/rngN
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
****************************************************************************/
|
||||
|
||||
int board_rng90_initialize(int devno)
|
||||
{
|
||||
struct i2c_master_s *i2c;
|
||||
char devpath[16];
|
||||
int ret;
|
||||
|
||||
sninfo("Initializing RNG90\n");
|
||||
|
||||
/* Initialize I2C */
|
||||
|
||||
#ifndef CONFIG_ESPRESSIF_I2C_BITBANG
|
||||
i2c = esp_i2cbus_initialize(ESPRESSIF_I2C0);
|
||||
#else
|
||||
i2c = esp_i2cbus_bitbang_initialize();
|
||||
#endif
|
||||
|
||||
if (i2c == NULL)
|
||||
{
|
||||
snerr("ERROR: Failed to initialize I2C for RNG90\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Register the RNG90 driver at "/dev/rngN" */
|
||||
|
||||
snprintf(devpath, sizeof(devpath), "/dev/rng%d", devno);
|
||||
ret = rng90_register(devpath, i2c, RNG90_I2C_ADDR);
|
||||
if (ret < 0)
|
||||
{
|
||||
snerr("ERROR: Failed to register RNG90 driver: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
51
boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig
Normal file
51
boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||
#
|
||||
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||
# modifications.
|
||||
#
|
||||
# CONFIG_NSH_ARGCAT is not set
|
||||
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||
CONFIG_ARCH="risc-v"
|
||||
CONFIG_ARCH_BOARD="esp32c3-devkit"
|
||||
CONFIG_ARCH_BOARD_COMMON=y
|
||||
CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
|
||||
CONFIG_ARCH_CHIP="esp32c3"
|
||||
CONFIG_ARCH_CHIP_ESP32C3=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=1536
|
||||
CONFIG_ARCH_IRQ_TO_NDX=y
|
||||
CONFIG_ARCH_MINIMAL_VECTORTABLE_DYNAMIC=y
|
||||
CONFIG_ARCH_NUSER_INTERRUPTS=17
|
||||
CONFIG_ARCH_RISCV=y
|
||||
CONFIG_ARCH_STACKDUMP=y
|
||||
CONFIG_BOARDCTL_RESET=y
|
||||
CONFIG_BOARD_LOOPSPERMSEC=15000
|
||||
CONFIG_BUILTIN=y
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_DEV_RNG90=y
|
||||
CONFIG_ESPRESSIF_I2C0=y
|
||||
CONFIG_EXAMPLES_RNG90=y
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=2048
|
||||
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||
CONFIG_INTELHEX_BINARY=y
|
||||
CONFIG_LIBC_PERROR_STDOUT=y
|
||||
CONFIG_LIBC_STRERROR=y
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_FILEIOSIZE=512
|
||||
CONFIG_NSH_READLINE=y
|
||||
CONFIG_NSH_STRERROR=y
|
||||
CONFIG_PREALLOC_TIMERS=0
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_BACKTRACE=y
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_START_DAY=29
|
||||
CONFIG_START_MONTH=11
|
||||
CONFIG_START_YEAR=2019
|
||||
CONFIG_SYSTEM_DUMPSTACK=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_TESTING_GETPRIME=y
|
||||
CONFIG_TESTING_OSTEST=y
|
||||
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||
|
|
@ -41,6 +41,10 @@
|
|||
#include "esp_board_i2c.h"
|
||||
#include "esp_board_bmp180.h"
|
||||
|
||||
#ifdef CONFIG_DEV_RNG90
|
||||
# include "esp_board_rng90.h"
|
||||
#endif
|
||||
|
||||
#include "espressif/esp_start.h"
|
||||
|
||||
#ifdef CONFIG_ESPRESSIF_ADC
|
||||
|
|
@ -404,6 +408,15 @@ int esp_bringup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEV_RNG90
|
||||
ret = board_rng90_initialize(0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize RNG90 driver: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_SDM
|
||||
struct esp_sdm_chan_config_s config =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,3 +23,7 @@
|
|||
if(CONFIG_DEV_URANDOM AND NOT CONFIG_DEV_URANDOM_ARCH)
|
||||
target_sources(drivers PRIVATE dev_urandom.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DEV_RNG90)
|
||||
target_sources(drivers PRIVATE rng90.c)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -137,3 +137,13 @@ config SE05X_LOG_DEBUG
|
|||
endchoice # SE05x debug log level
|
||||
|
||||
endif #DEV_SE05X
|
||||
|
||||
config DEV_RNG90
|
||||
bool "Enable Microchip RNG90 TRNG"
|
||||
depends on I2C
|
||||
depends on CRYPTO
|
||||
default n
|
||||
---help---
|
||||
Enable support for /dev/rng90 random number generator provided by
|
||||
Microchip RNG90 TRNG.
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ ifeq ($(CONFIG_DEV_SE05X),y)
|
|||
include crypto/pnt/Make.defs
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEV_RNG90),y)
|
||||
CSRCS += rng90.c
|
||||
endif
|
||||
|
||||
# Include crypto device driver build support
|
||||
|
||||
DEPPATH += --dep-path crypto
|
||||
|
|
|
|||
372
drivers/crypto/rng90.c
Normal file
372
drivers/crypto/rng90.c
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
/****************************************************************************
|
||||
* drivers/crypto/rng90.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/debug.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/crypto/rng90.h>
|
||||
#include <nuttx/fs/fs.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define RNG90_WAKE_I2C_ADDR 0x00
|
||||
#define RNG90_WAKE_I2C_MAXFREQ 100000
|
||||
#define RNG90_WAKE_RETRIES 3
|
||||
#define RNG90_WAKE_DELAY_MS 5
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct rng90_dev_s
|
||||
{
|
||||
FAR struct i2c_master_s *i2c;
|
||||
uint8_t addr;
|
||||
mutex_t lock;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static bool rng90_wakeup(FAR struct rng90_dev_s *priv);
|
||||
static bool rng90_sleep(FAR struct rng90_dev_s *priv);
|
||||
static void rng90_send_wake_token(FAR struct rng90_dev_s *priv);
|
||||
static void rng90_i2c_config(FAR struct i2c_config_s *config,
|
||||
uint32_t frequency, uint8_t address);
|
||||
static bool rng90_genrnd(FAR struct rng90_dev_s *priv, FAR uint8_t *buffer,
|
||||
size_t buflen);
|
||||
|
||||
/* Character driver methods */
|
||||
|
||||
static int rng90_open(FAR struct file *filep);
|
||||
static int rng90_close(FAR struct file *filep);
|
||||
static ssize_t rng90_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int rng90_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_rng90_fops =
|
||||
{
|
||||
rng90_open, rng90_close, rng90_read, NULL,
|
||||
NULL, rng90_ioctl, NULL
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int rng90_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct rng90_dev_s *priv = inode->i_private;
|
||||
|
||||
/* The close path puts the device into explicit sleep, so wake it here. */
|
||||
|
||||
nxmutex_lock(&priv->lock);
|
||||
if (!rng90_wakeup(priv))
|
||||
{
|
||||
crypterr("ERROR: Failed to wake rng90 device\n");
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->lock);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int rng90_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct rng90_dev_s *priv = inode->i_private;
|
||||
|
||||
nxmutex_lock(&priv->lock);
|
||||
if (!rng90_sleep(priv))
|
||||
{
|
||||
crypterr("ERROR: Failed to put rng90 device to sleep\n");
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static ssize_t rng90_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct rng90_dev_s *priv = inode->i_private;
|
||||
bool ret;
|
||||
|
||||
nxmutex_lock(&priv->lock);
|
||||
ret = rng90_genrnd(priv, (FAR uint8_t *)buffer, buflen);
|
||||
nxmutex_unlock(&priv->lock);
|
||||
|
||||
/* rng90 always returns 32 bytes */
|
||||
|
||||
return ret ? (ssize_t)MIN(buflen, 32u) : -EIO;
|
||||
}
|
||||
|
||||
static int rng90_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct rng90_dev_s *priv = inode->i_private;
|
||||
int ret;
|
||||
|
||||
ret = nxmutex_lock(&priv->lock);
|
||||
if (ret != 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case RNG90_IOC_WAKEUP:
|
||||
ret = rng90_wakeup(priv) ? OK : ERROR;
|
||||
break;
|
||||
|
||||
case RNG90_IOC_SLEEP:
|
||||
ret = rng90_sleep(priv) ? OK : ERROR;
|
||||
break;
|
||||
|
||||
case RNG90_IOC_GENRND:
|
||||
ret = rng90_genrnd(priv, (FAR uint8_t *)arg, 32) ? OK : ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
crypterr("ERROR: Unrecognized cmd: %d\n", cmd);
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rng90_i2c_config(FAR struct i2c_config_s *config,
|
||||
uint32_t frequency, uint8_t address)
|
||||
{
|
||||
config->frequency = frequency;
|
||||
config->address = address;
|
||||
config->addrlen = 7;
|
||||
}
|
||||
|
||||
static bool rng90_is_wake_response(FAR const uint8_t *response)
|
||||
{
|
||||
return response[0] == 0x04 && response[1] == 0x11 &&
|
||||
response[2] == 0x33 && response[3] == 0x43;
|
||||
}
|
||||
|
||||
static void rng90_send_wake_token(FAR struct rng90_dev_s *priv)
|
||||
{
|
||||
struct i2c_config_s config;
|
||||
uint8_t wake_token = 0x01;
|
||||
uint32_t wake_freq;
|
||||
|
||||
/* Wake is an SDA-low pulse, not a normal transaction with an ACK. */
|
||||
|
||||
wake_freq = MIN(RNG90_I2C_FREQ, RNG90_WAKE_I2C_MAXFREQ);
|
||||
rng90_i2c_config(&config, wake_freq, RNG90_WAKE_I2C_ADDR);
|
||||
i2c_write(priv->i2c, &config, &wake_token, 1);
|
||||
up_mdelay(RNG90_WAKE_DELAY_MS);
|
||||
}
|
||||
|
||||
static bool rng90_wakeup(FAR struct rng90_dev_s *priv)
|
||||
{
|
||||
struct i2c_config_s config;
|
||||
uint8_t response[4];
|
||||
int attempt;
|
||||
int ret;
|
||||
|
||||
for (attempt = 0; attempt < RNG90_WAKE_RETRIES; attempt++)
|
||||
{
|
||||
rng90_send_wake_token(priv);
|
||||
|
||||
rng90_i2c_config(&config, RNG90_I2C_FREQ, priv->addr);
|
||||
ret = i2c_read(priv->i2c, &config, response, sizeof(response));
|
||||
if (ret >= 0 && rng90_is_wake_response(response))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool rng90_sleep(FAR struct rng90_dev_s *priv)
|
||||
{
|
||||
struct i2c_config_s config;
|
||||
uint8_t word_address = 0x01;
|
||||
int ret;
|
||||
|
||||
rng90_i2c_config(&config, RNG90_I2C_FREQ, priv->addr);
|
||||
|
||||
/* Sleep sequence: device address + word address 0x01 + Stop condition */
|
||||
|
||||
ret = i2c_write(priv->i2c, &config, &word_address, 1);
|
||||
return (ret >= 0);
|
||||
}
|
||||
|
||||
static uint16_t rng90_crc16(FAR const uint8_t *data, size_t len)
|
||||
{
|
||||
uint16_t crc = 0x0000;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
uint8_t byte = data[i];
|
||||
uint8_t shift;
|
||||
|
||||
for (shift = 0x01; shift != 0; shift <<= 1)
|
||||
{
|
||||
bool dbit = (byte & shift) != 0;
|
||||
bool cbit = (crc & 0x8000) != 0;
|
||||
|
||||
crc <<= 1;
|
||||
if (dbit != cbit)
|
||||
{
|
||||
crc ^= 0x8005;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
static bool rng90_genrnd(FAR struct rng90_dev_s *priv, FAR uint8_t *buffer,
|
||||
size_t buflen)
|
||||
{
|
||||
struct i2c_config_s config;
|
||||
uint8_t response[35];
|
||||
int ret;
|
||||
int attempt;
|
||||
|
||||
/* Random command packet (datasheet section 6.2) */
|
||||
|
||||
uint8_t pkt[28];
|
||||
uint16_t crc;
|
||||
|
||||
pkt[0] = 0x03; /* word address: command */
|
||||
pkt[1] = 27; /* count */
|
||||
pkt[2] = 0x16; /* opcode: Random */
|
||||
pkt[3] = 0x00; /* param1 */
|
||||
pkt[4] = 0x00; /* param2 lo */
|
||||
pkt[5] = 0x00; /* param2 hi */
|
||||
|
||||
/* data: 20 bytes, any value */
|
||||
|
||||
memset(&pkt[6], 0x00, 20);
|
||||
|
||||
/* CRC over count + packet (pkt[1] through pkt[25]) */
|
||||
|
||||
crc = rng90_crc16(&pkt[1], 25);
|
||||
pkt[26] = (uint8_t)(crc & 0xff); /* CRC lo */
|
||||
pkt[27] = (uint8_t)(crc >> 8); /* CRC hi */
|
||||
|
||||
rng90_i2c_config(&config, RNG90_I2C_FREQ, priv->addr);
|
||||
|
||||
for (attempt = 0; attempt < 2; attempt++)
|
||||
{
|
||||
if (attempt > 0)
|
||||
{
|
||||
rng90_wakeup(priv);
|
||||
}
|
||||
|
||||
ret = i2c_write(priv->i2c, &config, pkt, sizeof(pkt));
|
||||
if (ret < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Wait for command execution (datasheet section 5.6.2) */
|
||||
|
||||
up_mdelay(72);
|
||||
|
||||
/* Response: [count=35][32 random bytes][crc_lo][crc_hi] */
|
||||
|
||||
ret = i2c_read(priv->i2c, &config, response, sizeof(response));
|
||||
if (ret >= 0)
|
||||
{
|
||||
memcpy(buffer, &response[1], MIN(buflen, 32u));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int rng90_register(FAR const char *devpath, FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr)
|
||||
{
|
||||
int ret;
|
||||
FAR struct rng90_dev_s *priv;
|
||||
|
||||
/* Sanity check */
|
||||
|
||||
DEBUGASSERT(devpath != NULL);
|
||||
DEBUGASSERT(i2c != NULL);
|
||||
|
||||
/* Initialize the device's structure */
|
||||
|
||||
priv = (FAR struct rng90_dev_s *)kmm_malloc(sizeof(*priv));
|
||||
if (priv == NULL)
|
||||
{
|
||||
crypterr("ERROR: Failed to allocate instance\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->i2c = i2c;
|
||||
priv->addr = addr;
|
||||
nxmutex_init(&priv->lock);
|
||||
|
||||
/* Register the character driver */
|
||||
|
||||
ret = register_driver(devpath, &g_rng90_fops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
crypterr("ERROR: Failed to register driver: %d\n", ret);
|
||||
nxmutex_destroy(&priv->lock);
|
||||
kmm_free(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
66
include/nuttx/crypto/rng90.h
Normal file
66
include/nuttx/crypto/rng90.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/****************************************************************************
|
||||
* include/nuttx/crypto/rng90.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_CRYPTO_RNG90_H
|
||||
#define __INCLUDE_NUTTX_CRYPTO_RNG90_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_I2C) && defined(CONFIG_DEV_RNG90)
|
||||
|
||||
#define RNG90_I2C_ADDR 0x40
|
||||
#define RNG90_I2C_FREQ 400000
|
||||
|
||||
#define _RNG90IOCBASE (0x3b00) /* RNG90 ioctl base */
|
||||
#define _RNG90IOC(nr) _IOC(_RNG90IOCBASE, nr)
|
||||
|
||||
#define RNG90_IOC_WAKEUP _RNG90IOC(0x01)
|
||||
#define RNG90_IOC_SLEEP _RNG90IOC(0x02)
|
||||
#define RNG90_IOC_GENRND _RNG90IOC(0x03)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct i2c_master_s;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int rng90_register(FAR const char *devpath,
|
||||
FAR struct i2c_master_s *i2c,
|
||||
uint8_t addr);
|
||||
|
||||
#endif /* CONFIG_I2C && CONFIG_DEV_RNG90 */
|
||||
#endif /* __INCLUDE_NUTTX_CRYPTO_RNG90_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue