diff --git a/Documentation/applications/examples/rng90/index.rst b/Documentation/applications/examples/rng90/index.rst new file mode 100644 index 0000000000000..1f91ace7101ec --- /dev/null +++ b/Documentation/applications/examples/rng90/index.rst @@ -0,0 +1,118 @@ +============================= +``rng90`` RNG90 TRNG Example +============================= + +The ``rng90`` example is a simple NuttX application that opens an RNG90 device +node, reads random bytes, and prints them in hexadecimal format. + +RNG90 is a dedicated hardware random number generator IC from Microchip. It can +be used as a companion device for microcontrollers that do not provide native +true random number generation (TRNG). + +According to the Microchip RNG90 product page and linked validation artifacts, +the device is presented as a FIPS 140-3 compliant random number generator with +SP 800-90 A/B/C alignment, with references to NIST validation entries such as +entropy certificate E194 and DRBG validation A3013. + +Microchip also positions this device for disposable/ecosystem-control +applications, which makes it a practical choice for cost-sensitive designs. + +Configuration +============= + +Enable this application in ``menuconfig``: + +- ``Application Configuration -> Examples -> Microchip RNG90 TRNG example`` + +Required dependency: + +- Enable the driver in ``menuconfig``: + ``Device Drivers -> Cryptographic Device Drivers -> Enable Microchip RNG90 TRNG`` + (``CONFIG_DEV_RNG90``) + +Application options: + +- ``CONFIG_EXAMPLES_RNG90`` +- ``CONFIG_EXAMPLES_RNG90_PROGNAME`` (default: ``"rng90"``) +- ``CONFIG_EXAMPLES_RNG90_DEVPATH`` (default: ``"/dev/rng0"``) +- ``CONFIG_EXAMPLES_RNG90_PRIORITY`` +- ``CONFIG_EXAMPLES_RNG90_STACKSIZE`` + +Usage +===== + +From NSH:: + + rng90 [] [] + +Arguments: + +- ````: RNG90 device path (default from + ``CONFIG_EXAMPLES_RNG90_DEVPATH``) +- ````: number of random bytes to read (``1..32``, default ``32``) + +Examples:: + + rng90 + rng90 /dev/rng0 16 + +Expected output +=============== + +:: + + RNG90 example: device /dev/rng0 + Read 16 random byte(s): + 3f a1 7c ... + +Notes +===== + +- Opening the device wakes up RNG90. +- Closing the device puts RNG90 back to sleep. +- If ```` is outside ``1..32``, the app clamps it to ``32``. + +Hardware validation log +======================= + +The following session was executed on real hardware to validate this example. + +Test setup: + +- Host: macOS +- Board: ``esp32c3-devkit`` +- Serial port: ``/dev/cu.wchusbserial140`` +- Serial settings: ``115200 8N1`` + +Console transcript:: + + nsh> uname -a + NuttX 12.6.0-RC1 4130050287-dirty Jun 7 2026 22:11:21 risc-v esp32c3-devkit + nsh> ls /dev/rng0 + /dev/rng0 + nsh> rng90 + RNG90 example: device /dev/rng0 + Read 32 random byte(s): + 0d b2 71 d1 40 1f 3c 50 52 3d c6 2c a9 74 ec 60 + 44 ab 67 bb c4 34 1b ac 48 62 fe b9 fd 95 c9 cb + nsh> rng90 /dev/rng0 16 + RNG90 example: device /dev/rng0 + Read 16 random byte(s): + ef 82 5f b7 41 f1 48 13 5a 41 16 3a 67 1b 90 f2 + nsh> rng90 /dev/rng0 64 + Invalid count 64, clamping to 32 + RNG90 example: device /dev/rng0 + Read 32 random byte(s): + bb be 2f 20 7f c8 33 8d 18 90 c8 fb 94 db bc e6 + 84 41 17 6f 5a be 5a 06 c3 7b f1 30 ac f2 a6 f5 + nsh> + +References +========== + +- Microchip product page: + https://www.microchip.com/en-us/product/RNG90 +- NIST CMVP entropy certificate E194: + https://csrc.nist.gov/projects/cryptographic-module-validation-program/entropy-validations/certificate/194 +- NIST CAVP DRBG validation A3013: + https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/details?validation=35623 diff --git a/boards/risc-v/esp32c3/common/include/esp_board_rng90.h b/boards/risc-v/esp32c3/common/include/esp_board_rng90.h new file mode 100644 index 0000000000000..f316efe866b8e --- /dev/null +++ b/boards/risc-v/esp32c3/common/include/esp_board_rng90.h @@ -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 + +/**************************************************************************** + * 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 */ \ No newline at end of file diff --git a/boards/risc-v/esp32c3/common/src/CMakeLists.txt b/boards/risc-v/esp32c3/common/src/CMakeLists.txt index d8b1323adb38f..23feed738c04c 100644 --- a/boards/risc-v/esp32c3/common/src/CMakeLists.txt +++ b/boards/risc-v/esp32c3/common/src/CMakeLists.txt @@ -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() diff --git a/boards/risc-v/esp32c3/common/src/Make.defs b/boards/risc-v/esp32c3/common/src/Make.defs index 03d09271575a9..4f7a968440bc3 100644 --- a/boards/risc-v/esp32c3/common/src/Make.defs +++ b/boards/risc-v/esp32c3/common/src/Make.defs @@ -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 diff --git a/boards/risc-v/esp32c3/common/src/esp_board_rng90.c b/boards/risc-v/esp32c3/common/src/esp_board_rng90.c new file mode 100644 index 0000000000000..3d14b53806af1 --- /dev/null +++ b/boards/risc-v/esp32c3/common/src/esp_board_rng90.c @@ -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 + +#include + +#include +#include +#include +#include + +#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; +} + diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig new file mode 100644 index 0000000000000..170cbd0ecb183 --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/rng90/defconfig @@ -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 diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c index 942d6a1def09e..36023aa21c2ca 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c @@ -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 = { diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index f310ae115e5ce..3c93183635edc 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -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() diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 00b4d3f9155cd..e53927894a0ab 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -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. + diff --git a/drivers/crypto/Make.defs b/drivers/crypto/Make.defs index 240ba5ceab89a..e243bd916fa8e 100644 --- a/drivers/crypto/Make.defs +++ b/drivers/crypto/Make.defs @@ -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 diff --git a/drivers/crypto/rng90.c b/drivers/crypto/rng90.c new file mode 100644 index 0000000000000..3c7b065fe6979 --- /dev/null +++ b/drivers/crypto/rng90.c @@ -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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * 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; +} diff --git a/include/nuttx/crypto/rng90.h b/include/nuttx/crypto/rng90.h new file mode 100644 index 0000000000000..a83afd1db7b36 --- /dev/null +++ b/include/nuttx/crypto/rng90.h @@ -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 +#include + +#include + +/**************************************************************************** + * 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 */