diff --git a/boards/rapidsilicon/virgo_proto/virgo_proto.dts b/boards/rapidsilicon/virgo_proto/virgo_proto.dts index a116964a01762..6f6fe852be2c0 100644 --- a/boards/rapidsilicon/virgo_proto/virgo_proto.dts +++ b/boards/rapidsilicon/virgo_proto/virgo_proto.dts @@ -7,6 +7,7 @@ /dts-v1/; #include + / { model = "Rapid Silicon Virgo Proto"; @@ -50,6 +51,14 @@ status = "okay"; }; + &pufs_otp { + status = "okay"; + }; + + &pufs { + status = "okay"; + }; + &spi0 { status = "okay"; clock-frequency = <26666667>; diff --git a/boards/rapidsilicon/virgo_proto/virgo_proto_defconfig b/boards/rapidsilicon/virgo_proto/virgo_proto_defconfig index f43104211eb1c..484687bbd6b06 100644 --- a/boards/rapidsilicon/virgo_proto/virgo_proto_defconfig +++ b/boards/rapidsilicon/virgo_proto/virgo_proto_defconfig @@ -34,4 +34,32 @@ CONFIG_HWINFO_ANDES=n # CONFIG_SOC_ANDES_V5_EXECIT=y # Sys Clock HW Cycles for Virgo Proto used by mtimer -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=13333333 \ No newline at end of file +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=13333333 + +# Enabling the SPI Peripheral +CONFIG_SPI=y +CONFIG_SPI_NOR=y + +# Enabling the Crypto Peripheral +CONFIG_CRYPTO=y +CONFIG_PUFCC_SECURITY=y +CONFIG_CRYPTO_PUF_SECURITY=y +CONFIG_CRYPTO_PUF_SECURITY_OTP=y + +# Enabling the DMA Peripheral +CONFIG_DMA=y +CONFIG_DMA_ANDES_ATCDMAC100=y + +# Enabling the SPI and Flash Peripheral +CONFIG_FLASH=y +CONFIG_SPI_NOR_SFDP_DEVICETREE=y +CONFIG_SPI_ANDES_ATCSPI200=y +CONFIG_ANDES_SPI_DMA_MODE=n + +# Enabling the Counter Peripheral +CONFIG_COUNTER=y +CONFIG_COUNTER_ANDES_ATCPIT100=y + +# Enabling the Sensor Peripheral +CONFIG_SENSOR=y +CONFIG_DTI_PVT=y diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index 68b63aef6ee9a..d76295c58742e 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -12,4 +12,7 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCHP_XEC_SYMCR crypto_mchp_xec_symcr.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c) +zephyr_library_sources_ifdef(CONFIG_PUFCC_SECURITY pufcc.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_PUF_SECURITY crypto_pufs.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_PUF_SECURITY_OTP crypto_pufs_otp.c) zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5342441038e66..24dd8a23c4f37 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -77,6 +77,7 @@ source "drivers/crypto/Kconfig.stm32" source "drivers/crypto/Kconfig.nrf_ecb" source "drivers/crypto/Kconfig.intel" source "drivers/crypto/Kconfig.npcx" +source "drivers/crypto/Kconfig.pufs" source "drivers/crypto/Kconfig.xec" source "drivers/crypto/Kconfig.it8xxx2" source "drivers/crypto/Kconfig.mcux_dcp" diff --git a/drivers/crypto/Kconfig.pufs b/drivers/crypto/Kconfig.pufs new file mode 100644 index 0000000000000..0170695c1d874 --- /dev/null +++ b/drivers/crypto/Kconfig.pufs @@ -0,0 +1,34 @@ +# PUF Security Cryptographic Accelerator configuration options + +# Copyright (c) 2024 Muhammad Junaid Aslam +# SPDX-License-Identifier: Apache-2.0 + +menuconfig PUFCC_SECURITY + bool "PUF Security Hardware" + depends on DT_HAS_PUFSECURITY_PUFCC_ENABLED + help + Enable PUF Security Hardware. + + if PUFCC_SECURITY + + config RS_RTOS_PORT + bool + + config CRYPTO_PUF_SECURITY + bool "PUF security Cryptographic Accelerator driver" + default n + depends on DT_HAS_PUFSECURITY_PUFCC_ENABLED + select RS_RTOS_PORT + help + Enable PUF Security based Cryptographic Accelerator driver. + + config CRYPTO_PUF_SECURITY_OTP + bool "PUF security One Time Programmable Memory" + default n + depends on DT_HAS_PUFSECURITY_OTP_ENABLED + select RS_RTOS_PORT + help + Enable PUF Security based One Time Programmable Memory. + + endif + \ No newline at end of file diff --git a/drivers/crypto/crypto_pufs.c b/drivers/crypto/crypto_pufs.c new file mode 100644 index 0000000000000..b69e76e5715bb --- /dev/null +++ b/drivers/crypto/crypto_pufs.c @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2024 Rapid Silicon + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include "crypto_pufs.h" + +#include + +#include +#include + +#define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL +#include +LOG_MODULE_REGISTER(crypto_puf_security); + +#if DT_HAS_COMPAT_STATUS_OKAY(pufsecurity_pufcc) + #define DT_DRV_COMPAT pufsecurity_pufcc +#else + #error No PUF Security HW Crypto Accelerator in device tree +#endif + +#define PUFS_HW_CAP (CAP_RAW_KEY | CAP_INPLACE_OPS | \ + CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS | \ + CAP_NO_IV_PREFIX | CAP_NO_ENCRYPTION | CAP_NO_SIGNING) + +static char *session_to_str(enum pufs_session_type inSession) { + return ((inSession == PUFS_SESSION_HASH_CALCULATION)?"Hash":\ + ((inSession == PUFS_SESSION_DECRYPTION)?"Decryption":\ + ((inSession == PUFS_SESSION_SIGN_VERIFICATION)?"Sign_Verification":"Unknown"))); +} + +uint8_t __pufcc_descriptors[BUFFER_SIZE]; + +static int pufs_query_hw_caps(const struct device *dev); + +static int fill_rs_crypto_hash_addr(struct hash_pkt *pkt, struct rs_crypto_addr *data_addr) { + uint8_t desc_count = 0; + + if((pkt == NULL) || (data_addr == NULL)) { + LOG_ERR("%s(%d) NULL pointer(s)\n", __func__, __LINE__); + return -EBADFD; + } + + // Set SGDMA descriptors input data + while(true) { + + data_addr[desc_count].read_addr = (uint32_t)pkt->in_buf; + data_addr[desc_count].len = pkt->in_len; + data_addr[desc_count].periph_rw = false; + + if((desc_count * sizeof(struct pufcc_sg_dma_desc)) < BUFFER_SIZE){ + pkt = pkt->next; + } else { + break; + } + if(pkt != NULL) { + data_addr[desc_count].next = &data_addr[desc_count+1]; + } else { + data_addr[desc_count].next = NULL; + break; + } + desc_count++; + } + + if (pkt) { + // No enough descriptors available + LOG_ERR("%s(%d) Not More Than %d Elements Allowed. Count:%d\n", \ + __func__, __LINE__, (BUFFER_SIZE/sizeof(struct pufcc_sg_dma_desc)), desc_count+1); + return -ENOTEMPTY; + } + + return PUFCC_SUCCESS; +} + +static int fill_rs_crypto_sign_addr(struct sign_pkt *pkt, struct rs_crypto_addr *data_addr) { + + uint8_t desc_count = 0; + + if((pkt == NULL) || (data_addr == NULL)) { + LOG_ERR("%s(%d) NULL pointer(s)\n", __func__, __LINE__); + return -EBADFD; + } + + while(true) { + + data_addr[desc_count].read_addr = (uint32_t)pkt->in_buf; + data_addr[desc_count].len = pkt->in_len; + + if((desc_count * sizeof(struct pufcc_sg_dma_desc)) < BUFFER_SIZE){ + pkt = pkt->next; + } else { + break; + } + if(pkt != NULL) { + data_addr[desc_count].next = &data_addr[desc_count+1]; + } else { + data_addr[desc_count].next = NULL; + break; + } + desc_count++; + } + + if (pkt) { + // No enough descriptors available + LOG_ERR("%s(%d) Not More Than %d Elements Allowed. Count:%d\n", \ + __func__, __LINE__, (BUFFER_SIZE/sizeof(struct pufcc_sg_dma_desc)), desc_count+1); + return -ENOTEMPTY; + } + + return PUFCC_SUCCESS; +} + +static int crypto_pufs_init(const struct device *dev) { + + // Initialize base addresses of different PUFcc modules + enum pufcc_status lvStatus = pufcc_init(((struct pufs_config*)dev->config)->base); + + if(lvStatus == PUFCC_SUCCESS) { + // Connect the IRQ + ((struct pufs_config*)dev->config)->irq_init(); + } else { + return -ENODEV; + } + + return PUFCC_SUCCESS; +} + +static void pufs_irq_handler(const struct device *dev) { + + // Clear and disable the interrupts from the pufcc register map + int status = pufcc_clear_and_disable_intr(); + + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + if((pufs_query_hw_caps(dev) & CAP_ASYNC_OPS) == CAP_ASYNC_OPS) + { + switch(lvPufsData->pufs_session_type) { + case(PUFS_SESSION_SIGN_VERIFICATION): { + if(lvPufsData->pufs_session_callback.sign_cb != NULL) { + lvPufsData->pufs_session_callback.sign_cb(lvPufsData->pufs_pkt.sign_pkt, status); + } + } break; + case(PUFS_SESSION_HASH_CALCULATION): { + if(lvPufsData->pufs_session_callback.hash_cb != NULL) { + lvPufsData->pufs_session_callback.hash_cb(lvPufsData->pufs_pkt.hash_pkt, status); + } + } break; + case(PUFS_SESSION_DECRYPTION): { + if(lvPufsData->pufs_session_callback.cipher_cb != NULL) { + lvPufsData->pufs_session_callback.cipher_cb(lvPufsData->pufs_pkt.cipher_pkt, status); + } + } break; + case(PUFS_SESSION_UNDEFINED): { + LOG_ERR("%s(%d) Unsupported Session %d\n", __func__, __LINE__, lvPufsData->pufs_session_type); + } break; + } + } + + // After execution of a callback, the irq is disabled. + irq_disable(((struct pufs_config *)dev->config)->irq_num); +} + +static void pufs_irq_Init(void) { + IRQ_CONNECT( + DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + pufs_irq_handler, + DEVICE_DT_INST_GET(0), + 0 + ); + + /** + * IRQ for PUFcc will be abled inside the + * interfaces which enable asynch operation + * callback registeration. When the IRQ is + * received, then that will be disabled inside + * the pufs_irq_hander. + */ +} + +/******************************************************** + * Following set of APIs are in compliance with the + * Zephyr user level Crypto API. These APIs will then + * subsequently call local functions for performing + * various crypto related operations. +*********************************************************/ + +/** + * Query the driver capabilities + * Not all the Modules of PUFs support all flags. + * Please Check individual cipher/hash/sign_begin_session + * interfaces to get the information of supported flags. + * */ +static int pufs_query_hw_caps(const struct device *dev) +{ + return PUFS_HW_CAP; +} + +static int pufs_ctr_op(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uint8_t *ctr) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + enum pufcc_dma_rw_type write_type; + + ((struct pufs_data*)ctx->device->data)->pufs_pkt.cipher_pkt = pkt; + ((struct pufs_data*)ctx->device->data)->pufs_ctx.cipher_ctx = ctx; + + if(pkt->auto_increment) { + write_type = AUTO_INCREMENT; + } else { + write_type = FIXED_RW; + } + + lvStatus = pufcc_decrypt_aes( + (uint32_t)pkt->out_buf, (uint32_t)pkt->in_buf, + (uint32_t)pkt->in_len, pkt->prev_len, ctx->key_source, + (uint32_t)ctx->key.bit_stream, ctx->keylen, (uint32_t)ctr, + (uint32_t)ctx->mode_params.ctr_info.ctr_len, + write_type, ctx->mode_params.ctr_info.readback_ctr + ); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) PUFcc Error Code:%d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return 0; +} + +static int pufs_cipher_begin_session(const struct device *dev, struct cipher_ctx *ctx, + enum cipher_algo algo, enum cipher_mode mode, + enum cipher_op op_type) +{ + ctx->device = dev; + + ((struct pufs_data *)dev->data)->pufs_ctx.cipher_ctx = ctx; + + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + uint16_t lvHashFlagsMask = ( + CAP_NO_ENCRYPTION | CAP_SYNC_OPS | + CAP_NO_IV_PREFIX | + CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS + ); + + if(algo != CRYPTO_CIPHER_ALGO_AES) { + LOG_ERR("%s(%d) UnSupported Algo. Only AES Supported\n", __func__, __LINE__); + return -ENOTSUP; + } + + if(mode != CRYPTO_CIPHER_MODE_CTR) { + LOG_ERR("%s(%d) UnSupported Algo. Only CTR Mode Supported\n", __func__, __LINE__); + return -ENOTSUP; + } else { + ctx->ops.ctr_crypt_hndlr = pufs_ctr_op; + } + + if(op_type != CRYPTO_CIPHER_OP_DECRYPT) { + LOG_ERR("%s(%d) UnSupported Operation. Only Decryption Supported\n", __func__, __LINE__); + return -ENOTSUP; + } + + if(ctx->flags & (~lvHashFlagsMask)) { + LOG_ERR("%s(%d) UnSupported Flags. Supported Flags_Mask:%d\n", __func__, __LINE__, lvHashFlagsMask); + return -ENOTSUP; + } + + if(lvPufsData->pufs_session_type != PUFS_SESSION_UNDEFINED) { + LOG_ERR("%s(%d) An Existing %s Session in Progress\n", __func__, __LINE__, \ + session_to_str(lvPufsData->pufs_session_type)); + return -ENOTSUP; + } else { + lvPufsData->pufs_session_type = PUFS_SESSION_DECRYPTION; + } + + ctx->ops.cipher_mode = mode; + + return PUFCC_SUCCESS; +} + +/* Tear down an established session */ +static int pufs_cipher_free_session(const struct device *dev, struct cipher_ctx *ctx) +{ + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + ctx->device = NULL; + + ctx->flags = 0x00; + + ctx->ops.block_crypt_hndlr = NULL; + ctx->ops.cbc_crypt_hndlr = NULL; + ctx->ops.ctr_crypt_hndlr = NULL; + ctx->ops.ccm_crypt_hndlr = NULL; + ctx->ops.gcm_crypt_hndlr = NULL; + + ctx->key.bit_stream = NULL; + ctx->key.handle = NULL; + + ctx->drv_sessn_state = NULL; + + ctx->app_sessn_state = NULL; + + if(lvPufsData->pufs_session_type != PUFS_SESSION_DECRYPTION) { + LOG_ERR("%s(%d) Cannot Free %s Session\n", __func__, __LINE__, \ + session_to_str(lvPufsData->pufs_session_type)); + return -ENOEXEC; + } else { + lvPufsData->pufs_session_type = PUFS_SESSION_UNDEFINED; + lvPufsData->pufs_session_callback.cipher_cb = NULL; + lvPufsData->pufs_ctx.cipher_ctx = NULL; + lvPufsData->pufs_pkt.cipher_pkt = NULL; + } + + return PUFCC_SUCCESS; +} + +/* Register async crypto op completion callback with the driver */ +static int pufs_cipher_async_callback_set(const struct device *dev, cipher_completion_cb cb) +{ + if((pufs_query_hw_caps(dev) & CAP_ASYNC_OPS) != CAP_ASYNC_OPS) { + LOG_ERR("%s(%d) Session:%s Does not Support Async Ops\n", __func__, __LINE__, \ + session_to_str(((struct pufs_data *)dev->data)->pufs_session_type)); + return -ENOTSUP; + } + + ((struct pufs_data*)dev->data)->pufs_session_callback.cipher_cb = cb; + + irq_enable(((struct pufs_config *)dev->config)->irq_num); + + return PUFCC_SUCCESS; +} + +static int pufs_hash_op(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + ((struct pufs_data*)ctx->device->data)->pufs_pkt.hash_pkt = pkt; + ((struct pufs_data*)ctx->device->data)->pufs_ctx.hash_ctx = ctx; + + if(!ctx->started) { // started flag indicates if chunkwise hash calculation was started + + struct rs_crypto_addr data_addr = { + .read_addr = (uint32_t)pkt->in_buf, + .write_addr = (uint32_t)pkt->out_buf, + .len = pkt->in_len + }; + + struct rs_crypto_hash hash_out = {0}; + + lvStatus = pufcc_calc_sha256_hash(&data_addr, &hash_out); + + /* Copy output hash values calculated by PUFcc */ + memcpy((void*)pkt->out_buf, (void*)hash_out.val, hash_out.len); + pkt->out_len = hash_out.len; + + } else { + + struct rs_crypto_addr lvHash_Data_Addr[(BUFFER_SIZE/sizeof(struct rs_crypto_addr))] = {0}; + struct hash_pkt *lvPkt = &pkt[0]; + int error = fill_rs_crypto_hash_addr(pkt, lvHash_Data_Addr); + + if(error != PUFCC_SUCCESS) { + return error; + } + + struct rs_crypto_hash hash_in = {0}; + + hash_in.len = lvPkt->in_hash_len; + + if(lvPkt->in_hash != NULL) { + /* Copy input hash values for operating upon */ + memcpy((void*)hash_in.val, (void*)lvPkt->in_hash, hash_in.len); + } + + struct rs_crypto_hash hash_out = {0}; + + lvStatus = pufcc_calc_sha256_hash_sg( + (struct rs_crypto_addr*)lvHash_Data_Addr, + lvPkt->head, + lvPkt->tail, + lvPkt->prev_len, + &hash_in, + &hash_out + ); + + if(lvStatus == PUFCC_SUCCESS) { + /* Copy output hash values calculated by PUFcc */ + memcpy((void*)lvPkt->out_buf, (void*)hash_out.val, (size_t)hash_out.len); + lvPkt->out_len = hash_out.len; + } + } + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) PUFs Error Code:%d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +/* Setup a hash session */ +static int pufs_hash_begin_session(const struct device *dev, struct hash_ctx *ctx, enum hash_algo algo) +{ + ctx->device = dev; + + ((struct pufs_data *)dev->data)->pufs_ctx.hash_ctx = ctx; + + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + uint16_t lvHashFlagsMask = (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS); + + if(algo != CRYPTO_HASH_ALGO_SHA256) { + LOG_ERR("%s(%d) UnSupported Hash Algo. Only SHA256 Supported\n", __func__, __LINE__); + return -ENOTSUP; + } + + if((ctx->flags & (~lvHashFlagsMask))) { + LOG_ERR("%s(%d) UnSupported Flags. Supported Flags_Mask:%d\n", __func__, __LINE__, lvHashFlagsMask); + return -ENOTSUP; + } + + if(lvPufsData->pufs_session_type != PUFS_SESSION_UNDEFINED) { + LOG_ERR("%s(%d) An Existing %s Session in Progress\n", __func__, __LINE__, \ + session_to_str(lvPufsData->pufs_session_type)); + return -ENOTSUP; + } else { + lvPufsData->pufs_session_type = PUFS_SESSION_HASH_CALCULATION; + } + + ctx->hash_hndlr = pufs_hash_op; + + return PUFCC_SUCCESS; +} + +/* Tear down an established hash session */ +static int pufs_hash_free_session(const struct device *dev, struct hash_ctx *ctx) +{ + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + ctx->device = NULL; + + ctx->started = false; + + ctx->flags = 0x00; + + ctx->hash_hndlr = NULL; + + if(lvPufsData->pufs_session_type != PUFS_SESSION_HASH_CALCULATION) { + LOG_ERR("%s(%d) Cannot Free %s Session\n", __func__, __LINE__, \ + session_to_str(lvPufsData->pufs_session_type)); + return -ENOEXEC; + } else { + lvPufsData->pufs_session_type = PUFS_SESSION_UNDEFINED; + lvPufsData->pufs_session_callback.hash_cb = NULL; + lvPufsData->pufs_ctx.hash_ctx = NULL; + lvPufsData->pufs_pkt.hash_pkt = NULL; + } + + return PUFCC_SUCCESS; +} + +/* Register async hash op completion callback with the driver */ +static int pufs_hash_async_callback_set(const struct device *dev, hash_completion_cb cb) +{ + if((pufs_query_hw_caps(dev) & CAP_ASYNC_OPS) != CAP_ASYNC_OPS) { + LOG_ERR("%s(%d) Session:%s Does not Support Async Ops\n", __func__, __LINE__, \ + session_to_str(((struct pufs_data *)dev->data)->pufs_session_type)); + return -ENOTSUP; + } + + ((struct pufs_data*)dev->data)->pufs_session_callback.hash_cb = cb; + + irq_enable(((struct pufs_config *)dev->config)->irq_num); + + return PUFCC_SUCCESS; +} + +/////////////////////////////////////////////////////////////// +int pufs_sign_rsa_op(struct sign_ctx *ctx, struct sign_pkt *pkt) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + int error = 0; + + ((struct pufs_data*)ctx->device->data)->pufs_pkt.sign_pkt = pkt; + ((struct pufs_data*)ctx->device->data)->pufs_ctx.sign_ctx = ctx; + + struct rs_crypto_addr msg_addr[(BUFFER_SIZE/sizeof(struct rs_crypto_addr))] = {0}; + + error = fill_rs_crypto_sign_addr(pkt, msg_addr); + + if(error != PUFCC_SUCCESS) { + return error; + } + + lvStatus = pufcc_rsa2048_sign_verify( + (uint8_t *)ctx->sig, + msg_addr, + (struct rs_crypto_rsa2048_puk *)ctx->pub_key + ); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) PUFs Error Code:%d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +int pufs_sign_ecdsa_op(struct sign_ctx *ctx, struct sign_pkt *pkt) +{ + int error = 0; + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + ((struct pufs_data*)ctx->device->data)->pufs_pkt.sign_pkt = pkt; + ((struct pufs_data*)ctx->device->data)->pufs_ctx.sign_ctx = ctx; + + struct rs_crypto_addr msg_addr[(BUFFER_SIZE/sizeof(struct rs_crypto_addr))] = {0}; + + error = fill_rs_crypto_sign_addr(pkt, msg_addr); + + if(error != PUFCC_SUCCESS) { + return error; + } + + lvStatus = pufcc_ecdsa256_sign_verify( + (struct rs_crypto_ec256_sig *)ctx->sig, + msg_addr, + (struct rs_crypto_ec256_puk *)ctx->pub_key + ); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) PUFs Error Code:%d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +/* Setup a signature session */ +static int pufs_sign_begin_session(const struct device *dev, struct sign_ctx *ctx, + enum sign_algo algo) +{ + ctx->device = dev; + + ((struct pufs_data *)dev->data)->pufs_ctx.sign_ctx = ctx; + + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + uint16_t lvHashFlagsMask = (CAP_INPLACE_OPS | CAP_SYNC_OPS); + + if((algo != CRYPTO_SIGN_ALGO_ECDSA256) && (algo != CRYPTO_SIGN_ALGO_RSA2048)) { + LOG_ERR("%s(%d) Unupported Algo:%d. Supported Algo \n", __func__, __LINE__, algo); + return -ENOTSUP; + } else { + if(algo == CRYPTO_SIGN_ALGO_ECDSA256) { + ctx->ops.signing_algo = CRYPTO_SIGN_ALGO_ECDSA256; + ctx->ops.ecdsa_crypt_hndlr = pufs_sign_ecdsa_op; + } else { + ctx->ops.signing_algo = CRYPTO_SIGN_ALGO_RSA2048; + ctx->ops.rsa_crypt_hndlr = pufs_sign_rsa_op; + } + } + + if((ctx->flags & (~lvHashFlagsMask))) { + LOG_ERR("%s(%d) UnSupported Flags. Supported Flags_Mask:%d\n", __func__, __LINE__, lvHashFlagsMask); + return -ENOTSUP; + } + + if(ctx->ops.signing_mode != CRYPTO_SIGN_VERIFY) { + LOG_ERR("%s(%d) UnSupported Signing Action. Only Sign Verification Supported\n", __func__, __LINE__); + return -ENOTSUP; + } + + if(lvPufsData->pufs_session_type != PUFS_SESSION_UNDEFINED) { + LOG_ERR("%s(%d) An Existing %s Session in Progress\n", __func__, __LINE__, \ + session_to_str(lvPufsData->pufs_session_type)); + return -ENOTSUP; + } else { + lvPufsData->pufs_session_type = PUFS_SESSION_SIGN_VERIFICATION; + } + + return PUFCC_SUCCESS; +} + +/* Tear down an established signature session */ +static int pufs_sign_free_session(const struct device *dev, struct sign_ctx *ctx) +{ + struct pufs_data *lvPufsData = (struct pufs_data*)dev->data; + + ctx->device = NULL; + + ctx->flags = 0x00; + + ctx->ops.rsa_crypt_hndlr = NULL; + + ctx->ops.ecdsa_crypt_hndlr = NULL; + + ctx->pub_key = NULL; + + ctx->sig = NULL; + + ctx->drv_sessn_state = NULL; + + ctx->app_sessn_state = NULL; + + if(lvPufsData->pufs_session_type != PUFS_SESSION_SIGN_VERIFICATION) { + LOG_ERR("%s(%d) Cannot Free %s Session\n", __func__, __LINE__, \ + session_to_str(lvPufsData->pufs_session_type)); + return -ENOEXEC; + } else { + lvPufsData->pufs_session_type = PUFS_SESSION_UNDEFINED; + lvPufsData->pufs_session_callback.sign_cb = NULL; + lvPufsData->pufs_ctx.sign_ctx = NULL; + lvPufsData->pufs_pkt.sign_pkt = NULL; + } + + return PUFCC_SUCCESS; +} + +/* Register async signature op completion callback with the driver */ +static int pufs_sign_async_callback_set(const struct device *dev, sign_completion_cb cb) +{ + if((pufs_query_hw_caps(dev) & CAP_ASYNC_OPS) != CAP_ASYNC_OPS) { + LOG_ERR("%s(%d) Session:%s Does not Support Async Ops\n", __func__, __LINE__, \ + session_to_str(((struct pufs_data *)dev->data)->pufs_session_type)); + return -ENOTSUP; + } + + ((struct pufs_data*)dev->data)->pufs_session_callback.sign_cb = cb; + + irq_enable(((struct pufs_config *)dev->config)->irq_num); + + return PUFCC_SUCCESS; +} + +static struct crypto_driver_api s_crypto_funcs = { + .cipher_begin_session = pufs_cipher_begin_session, + .cipher_free_session = pufs_cipher_free_session, + .cipher_async_callback_set = pufs_cipher_async_callback_set, + .hash_begin_session = pufs_hash_begin_session, + .hash_free_session = pufs_hash_free_session, + .hash_async_callback_set = pufs_hash_async_callback_set, + .sign_begin_session = pufs_sign_begin_session, + .sign_free_session = pufs_sign_free_session, + .sign_async_callback_set = pufs_sign_async_callback_set, + .query_hw_caps = pufs_query_hw_caps +}; + +static struct pufs_data s_pufs_session_data = { + .pufs_session_type = PUFS_SESSION_UNDEFINED, + .pufs_session_callback = {NULL}, + .pufs_ctx = {NULL}, + .pufs_pkt = {NULL} +}; + +static const struct pufs_config s_pufs_configuration = { + .base = DT_INST_REG_ADDR(0), + .irq_init = pufs_irq_Init, + .irq_num = DT_INST_IRQN(0) +}; + +DEVICE_DT_INST_DEFINE(0, crypto_pufs_init, NULL, + &s_pufs_session_data, + &s_pufs_configuration, POST_KERNEL, + CONFIG_CRYPTO_INIT_PRIORITY, (void *)&s_crypto_funcs); diff --git a/drivers/crypto/crypto_pufs.h b/drivers/crypto/crypto_pufs.h new file mode 100644 index 0000000000000..0f19c4d4d0ba8 --- /dev/null +++ b/drivers/crypto/crypto_pufs.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 Rapid Silicon + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef ZEPHYR_DRIVERS_CRYPTO_PUFS_H_ +#define ZEPHYR_DRIVERS_CRYPTO_PUFS_H_ + +#include "pufcc.h" +#include + +#define BUFFER_SIZE 512 + +extern uint8_t __pufcc_descriptors[BUFFER_SIZE]; + +enum pufs_session_type { + PUFS_SESSION_SIGN_VERIFICATION = 0, + PUFS_SESSION_HASH_CALCULATION, + PUFS_SESSION_DECRYPTION, + PUFS_SESSION_UNDEFINED +}; + +/* Generic Callback Signature for different Sessions */ +struct crypto_callbacks { + cipher_completion_cb cipher_cb; + hash_completion_cb hash_cb; + sign_completion_cb sign_cb; +}; + +/* Cipher, Hash and Sign session contexts */ +struct pufs_crypto_ctx { + struct hash_ctx *hash_ctx; + struct cipher_ctx *cipher_ctx; + struct sign_ctx *sign_ctx; +}; + +/* Cipher, Hash and Sign pkts */ +struct pufs_crypto_pkt { + struct hash_pkt *hash_pkt; + struct cipher_pkt *cipher_pkt; + struct sign_pkt *sign_pkt; +}; + +/* Device constant configuration parameters */ +struct pufs_data { + enum pufs_session_type pufs_session_type; + struct crypto_callbacks pufs_session_callback; + struct pufs_crypto_ctx pufs_ctx; + struct pufs_crypto_pkt pufs_pkt; +}; + +/* Device constant configuration parameters */ +struct pufs_config { + void (*irq_init)(void); + uint32_t base; + uint32_t irq_num; +}; + +#endif /* ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_PRIV_H_ */ diff --git a/drivers/crypto/crypto_pufs_otp.c b/drivers/crypto/crypto_pufs_otp.c new file mode 100644 index 0000000000000..7f918591cd8a9 --- /dev/null +++ b/drivers/crypto/crypto_pufs_otp.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2024 Rapid Silicon + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#include "pufcc.h" +#include + +#include + +#include +#include + +#define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL +#include +LOG_MODULE_REGISTER(crypto_puf_security_otp); + +#if DT_HAS_COMPAT_STATUS_OKAY(pufsecurity_otp) + #define DT_DRV_COMPAT pufsecurity_otp +#else + #error No PUF Security HW Crypto OTP in device tree +#endif + +#define OTP_HW_CAP (CAP_READ_OTP | CAP_WRITE_OTP | \ + CAP_LOCK_OTP | CAP_ZEROIZ_OTP | CAP_SYNC_OPS) + +/* Device constant configuration parameters */ +struct pufs_otp_config { + uint32_t base; +}; + +/** + * Query the driver capabilities + * Not all the Modules of PUFs support all flags. + * Please Check individual cipher/hash/sign_begin_session + * interfaces to get the information of supported flags. + * */ +static int crypto_pufs_otp_query_hw_caps(const struct device *dev) +{ + return OTP_HW_CAP; +} + +static int crypto_pufs_otp_init(const struct device *dev) { + + // Initialize base addresses of different PUFcc modules + enum pufcc_status lvStatus = pufcc_init(((struct pufs_otp_config*)dev->config)->base); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) Error\n", __func__, __LINE__); + return -ENODEV; + } + + return PUFCC_SUCCESS; +} + +static int crypto_pufs_otp_info( + const struct device *dev, + uint16_t *totalSlots, + uint16_t *bytesPerSlot + ) +{ + *totalSlots = PUFCC_TOTAL_SLOTS; + *bytesPerSlot = (PUFCC_OTP_LEN / PUFCC_OTP_KEY_LEN); + return PUFCC_SUCCESS; +} + +static int crypto_pufs_otp_read( + const struct device *dev, + uint16_t otp_slot, + uint8_t *data, + uint32_t len + ) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + lvStatus = pufcc_read_otp(data, len, otp_slot); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) Error: %d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +static int crypto_pufs_otp_write( + const struct device *dev, + uint16_t otp_slot, + uint8_t *data, + uint32_t len + ) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + lvStatus = pufcc_program_otp((const uint8_t *)data, len, otp_slot); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) Error: %d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +static int crypto_pufs_otp_zeroize( + const struct device *dev, + uint16_t otp_slot + ) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + lvStatus = pufcc_zeroize_otp(otp_slot); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) Error: %d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +static int crypto_pufs_otp_set_lock( + const struct device *dev, + uint16_t otp_slot, + uint16_t len, + enum crypto_otp_lock lock + ) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + lvStatus = pufcc_lock_otp(otp_slot, len, lock); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) Error: %d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +static int crypto_pufs_otp_get_lock( + const struct device *dev, + uint16_t otp_slot, + enum crypto_otp_lock *lock + ) +{ + enum pufcc_status lvStatus = PUFCC_SUCCESS; + + lvStatus = pufcc_get_otp_rwlck(otp_slot, (enum pufcc_otp_lock*)lock); + + if(lvStatus != PUFCC_SUCCESS) { + LOG_ERR("%s(%d) Error: %d\n", __func__, __LINE__, lvStatus); + return -ECANCELED; + } + + return PUFCC_SUCCESS; +} + +static struct otp_driver_api s_crypto_otp_funcs = { + .otp_hw_caps = crypto_pufs_otp_query_hw_caps, + .otp_get_lock = crypto_pufs_otp_get_lock, + .otp_info = crypto_pufs_otp_info, + .otp_read = crypto_pufs_otp_read, + .otp_set_lock = crypto_pufs_otp_set_lock, + .otp_write = crypto_pufs_otp_write, + .otp_zeroize = crypto_pufs_otp_zeroize +}; + +static const struct pufs_otp_config s_pufs_otp_configuration = { + .base = DT_REG_ADDR(DT_PARENT(DT_DRV_INST(0))), +}; + +DEVICE_DT_INST_DEFINE(0, crypto_pufs_otp_init, NULL, + NULL, + &s_pufs_otp_configuration, POST_KERNEL, + CONFIG_CRYPTO_INIT_PRIORITY, (void *)&s_crypto_otp_funcs); diff --git a/drivers/crypto/pufcc.c b/drivers/crypto/pufcc.c new file mode 100644 index 0000000000000..c44c77bf5f64d --- /dev/null +++ b/drivers/crypto/pufcc.c @@ -0,0 +1,1480 @@ +#include "pufcc.h" + +#include + +#if CONFIG_RS_RTOS_PORT + #include + #include + #include "crypto_pufs.h" + #include + static volatile bool s_Asynch_Operation = false; + void pufcc_set_asynch_ops_flag(bool Val) {s_Asynch_Operation = Val;} + bool pufcc_get_asynch_ops_flag(void) {return s_Asynch_Operation;} +#else + #include "profiling_util.h" + #include "rs_crypto.h" + #include "rs_util.h" +#endif + +/***************************************************************************** + * Macros + ****************************************************************************/ +#define SG_DMA_MAX_DSCS_SIZE (512 - 8) // Enough for 15 descriptors +#if !CONFIG_RS_RTOS_PORT + #define BUFFER_SIZE 512 +#endif +#define PUFCC_MAX_BUSY_COUNT 8000000 // Max busy count for processing 10MB data +#define CTR_MODE_BLOCK_SIZE 16 + +/***************************************************************************** + * Local variable declarations + ****************************************************************************/ +#if CONFIG_RS_RTOS_PORT + static struct pufcc_sg_dma_desc *sg_dma_descs = + (struct pufcc_sg_dma_desc *)__pufcc_descriptors; +#else + extern uint32_t __pufcc_descriptors; + static struct pufcc_sg_dma_desc *sg_dma_descs = + (struct pufcc_sg_dma_desc *)&__pufcc_descriptors; +#endif + + +static uint8_t pufcc_buffer[BUFFER_SIZE]; + +// PUFcc microprogram for RSA2048 +static uint32_t rsa_2048_mprog[] = { + 0x33cdac81, 0x6817434e, 0x4283ad5d, 0x27499978, 0x8a000040, 0x0a1080c0, + 0xc3800b00, 0x081810c6, 0xfc000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000}; + +// PUFcc microprogram for ECDSA256 +static uint32_t p256_ecdsa_mprog[] = { + 0xb1703302, 0x0f91d3f8, 0x004ae67d, 0x8f7093c5, 0x8a000068, 0x0a014088, + 0xc3000000, 0xa0624000, 0x43000100, 0x20824000, 0x0a014090, 0xc3000000, + 0x20624800, 0x43000100, 0xa0824800, 0x0a014090, 0xc3000600, 0x8900101e, + 0x8e000028, 0x8a000068, 0x8a014800, 0x8a028070, 0x43000400, 0x0901101e, + 0x8e000028, 0x8a000068, 0x8a014800, 0x0a028088, 0x43000400, 0x0902101e, + 0x8e000048, 0x8a028058, 0x0a03c060, 0x92050020, 0x8a064808, 0x41801600, + 0x8900101e, 0x09011028, 0x8e000048, 0x0a028078, 0x8a03c080, 0x92050020, + 0x8a064810, 0x41801600, 0x0902101e, 0x89031028, 0x8e000048, 0x8a028800, + 0x0a03c808, 0x0a050810, 0x0a064818, 0xc1000700, 0x20a25000, 0x8900101e, + 0x8e000028, 0x8a000068, 0x8a014800, 0x43000200, 0x8900101e, 0x1c110800, + 0x18025800, 0xfc000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000}; + +// EC NIST-P256 parameters +struct pufcc_ecc_param ecc_param_nistp256 = { + "\xff\xff\xff\xff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff", // prime + "\xff\xff\xff\xff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xfc", // a + "\x5a\xc6\x35\xd8\xaa\x3a\x93\xe7\xb3\xeb\xbd\x55\x76\x98\x86" + "\xbc\x65\x1d\x06\xb0\xcc\x53\xb0\xf6\x3b\xce\x3c\x3e\x27\xd2" + "\x60\x4b", // b + "\x6b\x17\xd1\xf2\xe1\x2c\x42\x47\xf8\xbc\xe6\xe5\x63\xa4\x40" + "\xf2\x77\x03\x7d\x81\x2d\xeb\x33\xa0\xf4\xa1\x39\x45\xd8\x98" + "\xc2\x96", // px + "\x4f\xe3\x42\xe2\xfe\x1a\x7f\x9b\x8e\xe7\xeb\x4a\x7c\x0f\x9e" + "\x16\x2b\xce\x33\x57\x6b\x31\x5e\xce\xcb\xb6\x40\x68\x37\xbf" + "\x51\xf5", // py + "\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff" + "\xff\xbc\xe6\xfa\xad\xa7\x17\x9e\x84\xf3\xb9\xca\xc2\xfc\x63" + "\x25\x51" // order +}; + +// Base register addresses of different PUFcc modules +static volatile struct pufcc_dma_regs *dma_regs; +static volatile struct pufcc_rt_regs *rt_regs; +static volatile struct pufcc_otp_mem *otp_mem; +static volatile struct pufcc_hmac_regs *hmac_regs; +static volatile struct pufcc_crypto_regs *crypto_regs; +static volatile struct pufcc_sp38a_regs *sp38a_regs; +static volatile struct pufcc_pkc_regs *pkc_regs; + +/***************************************************************************** + * Local function declarations + ****************************************************************************/ +static enum pufcc_status rsa_p1v15_verify(const uint8_t *dec_msg, + struct rs_crypto_addr *msg_addr); +static enum pufcc_status otp_range_check(uint32_t addr, uint32_t len); +static int rwlck_index_get(uint32_t idx); +static void reverse(uint8_t *dst, const uint8_t *src, size_t len); +static uint32_t be2le(uint32_t var); +static enum pufcc_status busy_wait(volatile uint32_t *status_reg_addr, + uint32_t error_mask); + +/***************************************************************************** + * API functions + ****************************************************************************/ +/** + * @fn pufcc_calc_sha256_hash + * @brief Calculates SHA256 hash + * + * @param[in] data_addr Data address info + * @param[in] hash Pointer to hash strcut to return hash value in + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_calc_sha256_hash(struct rs_crypto_addr *data_addr, + struct rs_crypto_hash *hash) { + enum pufcc_status status; + struct pufcc_intrpt_reg intrpt_reg = {0}; + struct pufcc_dma_cfg_0_reg dma_cfg_0_reg = {0}; + struct pufcc_dma_dsc_cfg_4_reg dma_dsc_cfg_4_reg = {0}; + struct pufcc_dma_key_cfg0_reg dma_key_cfg0_reg = {0}; + struct pufcc_start_reg start_reg = {0}; + + // Set 'intrpt' register values + intrpt_reg.intrpt_st = 1; // Write 1 to clear interrupt + intrpt_reg.intrpt_en = 0; // Disable interrupt + + // Set dma_dsc_cfg_4 reg values + dma_dsc_cfg_4_reg.head = 1; + dma_dsc_cfg_4_reg.tail = 1; + + // set values for key_cfg_0 register + dma_key_cfg0_reg.key_dst = PUFCC_DMA_KEY_DST_HASH; + + // Set values for start register + start_reg.start_p = 1; // Start operation bit + + // Set values for HMAC config register + struct pufcc_hmac_config_reg hmac_config_reg = { + .variant = PUFCC_HMAC_VARIANT_SHA256, // Shah 256 + .function = PUFCC_HMAC_FUNCTION_HASH, // Hash + }; + + /*** Configure DMA registers ***/ + // Set dma_cfg_0 register + REG_WRITE_32(&dma_regs->cfg_0, &dma_cfg_0_reg); + + // Set data source address in dsc_cfg_0 register + dma_regs->dsc_cfg_0 = data_addr->read_addr; + + // Set data length in dsc_cfg_2 register + dma_regs->dsc_cfg_2 = data_addr->len; + + // Set the dsc_cfg_4 register to values defined above + REG_WRITE_32(&dma_regs->dsc_cfg_4, &dma_dsc_cfg_4_reg); + + // Set the key_cfg_0 register to values defined above + REG_WRITE_32(&dma_regs->key_cfg_0, &dma_key_cfg0_reg); + + // Write intrpt register to values defined above + REG_WRITE_32(&dma_regs->interrupt, &intrpt_reg); + + /** Configure HMAC registers **/ + // Set the config register to values defined above + REG_WRITE_32(&hmac_regs->cfg, &hmac_config_reg); + + // Write previous length in HMAC plen register + hmac_regs->plen = hmac_regs->alen; + + // Write intrpt register to values defined above + REG_WRITE_32(&hmac_regs->interrupt, &intrpt_reg); + + // Start the DMA operation by writing to its start register + REG_WRITE_32(&dma_regs->start, &start_reg); + + // Poll on busy status + status = busy_wait(&dma_regs->status_0, PUFCC_DMA_ERROR_MASK); + + if (status != PUFCC_SUCCESS) { + return status; + } + + if (hmac_regs->status) { + return PUFCC_E_ERROR; + } + + // Read the calculated hash + for (uint8_t i = 0; i < (PUFCC_SHA_256_LEN / PUFCC_WORD_SIZE); i++) { + ((uint32_t *)hash->val)[i] = be2le(crypto_regs->dgst_out[i]); + } + + hash->len = PUFCC_SHA_256_LEN; + + return PUFCC_SUCCESS; +} + +/** + * @fn pufcc_calc_sha256_hash_sg + * @brief Calculates SHA256 hash of non-contiguous data. + * All non contiguous data addresses can be passed in as a single linked + * list in the form of 'rs_crypto_addr' struct as 'data_addr' parameter + * or this function can be invoked multiple times with partial data + * address info in the linked list by setting the 'first' and 'last' + * params accordingly as detailed below against each param. In case of + * partial data address info and hence multiple invocations, we also need + * to pass in previously calculated hash values to every invocation + * after the first one and the accumulated length of all previous + * messages/data. + * + * Note: In case of multiple data chunks either in a single linked list + * or as partial linked lists using multiple invocations the sizes of all + * chunks must be multiples of 64 bytes except the last chunk. + * + * @param[in] data_addr A linked list of data address info + * @param[in] first Boolean to indicate if 'data_addr' contains the first + * data block + * @param[in] last Boolean to indicate if 'data_addr' contains the last + * data block + * Note: 'first' and 'last' can both be true if + * 'data_addr' linked list contains both first and last + * data blocks or if it contains a single data block that + * is both first as well last. + * @param[in] prev_len Pointer to accumulated length of previously processed + * data; 0 for first invocation. Currently processed data + * length will be added to this value. + * @param[in] hash_in Hash of the data bocks processed already; can be NULL + * for first invocation. + * @param[out] hash_out Pointer to hash strcut to return hash value in + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_calc_sha256_hash_sg(struct rs_crypto_addr *data_addr, + bool first, bool last, + uint32_t *prev_len, + struct rs_crypto_hash *hash_in, + struct rs_crypto_hash *hash_out) { + enum pufcc_status status; + uint32_t plen = 0; + uint8_t desc_count = 0; + struct rs_crypto_addr *curr_addr = data_addr; + struct pufcc_dma_cfg_0_reg dma_cfg_0_reg = {0}; + struct pufcc_dma_dsc_cfg_4_reg dma_dsc_cfg_4_reg = {0}; + struct pufcc_dma_key_cfg0_reg dma_key_cfg0_reg = {0}; + struct pufcc_intrpt_reg intrpt_reg = {0}; + struct pufcc_start_reg start_reg = {0}; + struct pufcc_hmac_config_reg hmac_config_reg = {0}; + + if (!first) plen = *prev_len; + + // Set DMA 'intrpt' register values + intrpt_reg.intrpt_st = 1; // Write 1 to clear interrupt + intrpt_reg.intrpt_en = 0; // Disable interrupt + + // Set values for start register + start_reg.start_p = 1; // Start operation + + // Set values for HMAC config register + hmac_config_reg.variant = PUFCC_HMAC_VARIANT_SHA256; + hmac_config_reg.function = PUFCC_HMAC_FUNCTION_HASH; + + // Set key_cfg_0 for hash calculation + dma_key_cfg0_reg.key_dst = PUFCC_DMA_KEY_DST_HASH; + + // Set previous hash value if it's not the first data block + if (!first) { + for (uint8_t i = 0; i < (PUFCC_SHA_256_LEN / PUFCC_WORD_SIZE); i++) { + crypto_regs->dgst_in[i] = be2le(((uint32_t *)hash_in->val)[i]); + } + } + + // Set SGDMA descriptors + do { + sg_dma_descs[desc_count].read_addr = be2le(curr_addr->read_addr); + sg_dma_descs[desc_count].length = be2le(curr_addr->len); + sg_dma_descs[desc_count].next = + be2le((uint32_t)&sg_dma_descs[desc_count + 1]); + + sg_dma_descs[desc_count].key_cfg = be2le(*(uint32_t *)&dma_key_cfg0_reg); + sg_dma_descs[desc_count].cypt_cfg[0] = be2le(*(uint32_t *)&hmac_config_reg); + sg_dma_descs[desc_count].cypt_cfg[1] = be2le(plen); + + *(uint32_t *)&dma_dsc_cfg_4_reg = 0; + dma_dsc_cfg_4_reg.offset = plen % 16; + + plen += curr_addr->len; + curr_addr = curr_addr->next; + + if (!desc_count && first) { + dma_dsc_cfg_4_reg.head = 1; + } + + // Mark this descriptor as last if there is no more data + if (!curr_addr) { + dma_dsc_cfg_4_reg.dn_pause = 1; + if (last) { + dma_dsc_cfg_4_reg.tail = 1; + } + } + + sg_dma_descs[desc_count].dsc_cfg_4 = be2le(*(uint32_t *)&dma_dsc_cfg_4_reg); + desc_count++; + } while (curr_addr && ((desc_count * sizeof(struct pufcc_sg_dma_desc)) < + SG_DMA_MAX_DSCS_SIZE)); + + if (curr_addr) { + // No enough descriptors available + return PUFCC_E_OVERFLOW; + } + + // Update accumulated data length + *prev_len = plen; + + /*** Configure DMA registers ***/ + // Enable SGDMA in dma_cfg_0 register + dma_cfg_0_reg.sg_en = 1; + REG_WRITE_32(&dma_regs->cfg_0, &dma_cfg_0_reg); + + // Set dsc_cfg_2 register to indicate it's an SGDMA operation + dma_regs->dsc_cfg_2 = PUFCC_DMA_DSC_CFG2_SGDMA_VAL; + + // Set starting address of SGDMA descriptors in dma_dsc_cfg3 register + dma_regs->dsc_cfg_3 = (uint32_t)sg_dma_descs; + + // Clear and disable DMA and HMAC interrupts + REG_WRITE_32(&dma_regs->interrupt, &intrpt_reg); + REG_WRITE_32(&hmac_regs->interrupt, &intrpt_reg); + + // Start the DMA operation by writing to its start register + REG_WRITE_32(&dma_regs->start, &start_reg); + + // Poll on busy status + status = busy_wait(&dma_regs->status_0, PUFCC_DMA_ERROR_MASK); + + if (status != PUFCC_SUCCESS) { + return status; + } + + if (hmac_regs->status) { + return PUFCC_E_ERROR; + } + + // Read the calculated hash value + for (uint8_t i = 0; i < (PUFCC_SHA_256_LEN / PUFCC_WORD_SIZE); i++) { + ((uint32_t *)hash_out->val)[i] = be2le(crypto_regs->dgst_out[i]); + } + + hash_out->len = PUFCC_SHA_256_LEN; + return PUFCC_SUCCESS; +} + +/** + * @fn pufcc_decrypt_aes + * @brief Decrypt passed in data using AES decryption algorithm + * + * @param[in] out_addr Address to write decrypted data to + * @param[in] in_addr Address of the encrypted data + * @param[in] in_len Length of the input data in bytes + * @param[in] prev_len Length of the previously decrypted data in case + * decrypting data in chunks; 0 for first or single + * chunk + * @param[in] key_type Key type i.e. SW or OTP + * @param[in] key_addr Address or OTP slot of the decryption key + * @param[in] key_len Length of the decryption key + * @param[in] iv_addr IV address + * @param[in] iv_len IV length + * @param[in] write_type Write type i.e. write decrypted data to fixed address + * or auto-increment the destination address + * @param[in] readback_iv If true, read back updated IV value corresponding to + * number of processed data blocks into passed in + * iv_addr buffer. In this case iv_addr buffer must be + * writable. + * + * @return PUFCC_SUCCESS on success, otherwise an error code + */ +enum pufcc_status pufcc_decrypt_aes(uint32_t out_addr, uint32_t in_addr, + uint32_t in_len, uint32_t prev_len, + enum pufcc_key_type key_type, + uint32_t key_addr, uint32_t key_len, + uint32_t iv_addr, uint32_t iv_len, + enum pufcc_dma_rw_type write_type, + bool readback_iv) { + enum pufcc_status status; + uint32_t temp32; + + // Configure DMA intrpt register + temp32 = 0; + struct pufcc_intrpt_reg *intrpt_reg = (struct pufcc_intrpt_reg *)&temp32; + intrpt_reg->intrpt_st = 1; // Write 1 to clear interrupt + REG_WRITE_32(&dma_regs->interrupt, intrpt_reg); + + // Set dma_cfg_0 register + temp32 = 0; + REG_WRITE_32(&dma_regs->cfg_0, &temp32); + + struct pufcc_dma_cfg_1_reg *cfg_1_reg = (struct pufcc_dma_cfg_1_reg *)&temp32; + cfg_1_reg->rbst_max = 0xF; + cfg_1_reg->rbst_min = 0xF; + cfg_1_reg->wbst_max = 0xF; + cfg_1_reg->wbst_min = 0xF; + REG_WRITE_32(&dma_regs->cfg_1, cfg_1_reg); + + // Set data source address in dsc_cfg_0 register + REG_WRITE_32(&dma_regs->dsc_cfg_0, &in_addr); + + // Set decrypted data destination address in dsc_cfg_1 register + REG_WRITE_32(&dma_regs->dsc_cfg_1, &out_addr); + + // Set data length in dsc_cfg_2 register + REG_WRITE_32(&dma_regs->dsc_cfg_2, &in_len); + + // Configure dma_dsc_cfg_4 register + temp32 = 0; + struct pufcc_dma_dsc_cfg_4_reg *dsc_cfg_4_reg = + (struct pufcc_dma_dsc_cfg_4_reg *)&temp32; + dsc_cfg_4_reg->fw = write_type; + dsc_cfg_4_reg->fr = AUTO_INCREMENT; // Autoincrement source address + dsc_cfg_4_reg->offset = prev_len % CTR_MODE_BLOCK_SIZE; + REG_WRITE_32(&dma_regs->dsc_cfg_4, dsc_cfg_4_reg); + + // Configure key_cfg_0 register + struct pufcc_dma_key_cfg0_reg *key_cfg_0_reg = + (struct pufcc_dma_key_cfg0_reg *)&temp32; + key_cfg_0_reg->key_src = key_type; + key_cfg_0_reg->key_dst = PUFCC_DMA_KEY_DST_SP38A; // SP38a + key_cfg_0_reg->key_size = key_len * 8; // Key length in bits + + // Configure the decryption key + if (key_type == PUFCC_SW_KEY) { + for (uint32_t i = 0; i < (key_len / PUFCC_WORD_SIZE); i++) { + crypto_regs->sw_key[i] = be2le(((uint32_t *)key_addr)[i]); + } + } else { + key_cfg_0_reg->key_idx = (enum pufcc_key_type)key_addr; + } + + REG_WRITE_32(&dma_regs->key_cfg_0, key_cfg_0_reg); + + // Configure IV + for (uint32_t i = 0; i < (iv_len / PUFCC_WORD_SIZE); i++) { + crypto_regs->iv[i] = be2le(((uint32_t *)iv_addr)[i]); + } + + // Configure SP38a intrpt register + temp32 = 0; + intrpt_reg = (struct pufcc_intrpt_reg *)&temp32; + intrpt_reg->intrpt_st = 1; // Clear interrupt by writing 1 + REG_WRITE_32(&sp38a_regs->interrupt, intrpt_reg); + + // Configure SP38a config register + struct pufcc_sp38a_config_reg *sp38a_config_reg = + (struct pufcc_sp38a_config_reg *)&temp32; + sp38a_config_reg->variant = + (key_len == PUFCC_CRYPTO_AES128_KEY_LEN ? PUFCC_AES128 : PUFCC_AES256); + sp38a_config_reg->mode = PUFCC_CTR128; + sp38a_config_reg->enc_dec = 0; // Decryption + REG_WRITE_32(&sp38a_regs->cfg, sp38a_config_reg); + + // Start DMA operation + struct pufcc_start_reg *start_reg = (struct pufcc_start_reg *)&temp32; + start_reg->start_p = 1; + REG_WRITE_32(&dma_regs->start, start_reg); + + // Poll on busy status + status = busy_wait(&dma_regs->status_0, PUFCC_DMA_ERROR_MASK); + + if (status != PUFCC_SUCCESS) { + return status; + } + + if (sp38a_regs->status & PUFCC_SP38A_STATUS_ERROR_MASK) { + return PUFCC_E_ERROR; + } + + // Read back updated IV + if (readback_iv) { + for (uint8_t i = 0; i < iv_len / PUFCC_WORD_SIZE; i++) { + ((uint32_t *)iv_addr)[i] = be2le(crypto_regs->iv[i]); + } + } + + return PUFCC_SUCCESS; +} + +/** + * @fn pufcc_rsa2048_sign_verify + * @brief Verify RSA2048 signature of the input message data + * + * @param[in] sig Address of the message signature + * @param[in] msg_addr Address of the message data + * @param[in] pub_key RSA2048 public key + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_rsa2048_sign_verify( + uint8_t *sig, struct rs_crypto_addr *msg_addr, + struct rs_crypto_rsa2048_puk *pub_key) { + enum pufcc_status status = PUFCC_SUCCESS; + uint32_t temp32; + uint8_t dec_msg[PUFCC_RSA_2048_LEN]; + // Configure signature scheme + temp32 = 0; + + struct pufcc_pkc_ecp_ec_reg *ecp_ec_reg = + (struct pufcc_pkc_ecp_ec_reg *)&temp32; + ecp_ec_reg->field = PUFCC_RSA_2048; + REG_WRITE_32(&pkc_regs->ecp_ec, ecp_ec_reg); + + // Reverse public key modulus + reverse(pufcc_buffer, pub_key->n, PUFCC_RSA_2048_LEN); + + #if !CONFIG_RS_RTOS_PORT + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_RSA2048_MODULUS_OFFSET, + pufcc_buffer, PUFCC_RSA_2048_LEN); + #else + uint32_t *ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_RSA2048_MODULUS_OFFSET/4; + uint32_t *buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_RSA_2048_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #endif + + // Write public key exponent to ecp_e_short register + REG_WRITE_32(&pkc_regs->ecp_e_short, &pub_key->e); + + // Reverse signature + reverse(pufcc_buffer, sig, PUFCC_RSA_2048_LEN); + + // Write reversed signature to ECP data field at proper offset + #if !CONFIG_RS_RTOS_PORT + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_RSA2048_SIGN_OFFSET, + pufcc_buffer, PUFCC_RSA_2048_LEN); + #else + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_RSA2048_SIGN_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_RSA_2048_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #endif + + // Write microprogram for RSA2048 + #if !CONFIG_RS_RTOS_PORT + memcpy((void *)&pkc_regs->ecp_mac, rsa_2048_mprog, sizeof(rsa_2048_mprog)); + #else + ptr = (uint32_t*)&pkc_regs->ecp_mac; + buf_ptr = (uint32_t*)rsa_2048_mprog; + for(int i = 0; i < sizeof(rsa_2048_mprog)/4; i++) { + *ptr++ = *buf_ptr++; + } + #endif + + temp32 = 0; + struct pufcc_intrpt_reg *intrpt_reg = (struct pufcc_intrpt_reg *)&temp32; + intrpt_reg->intrpt_st = 1; + REG_WRITE_32(&pkc_regs->interrupt, intrpt_reg); + + // Start PKC operation + struct pufcc_start_reg *start_reg = (struct pufcc_start_reg *)&temp32; + start_reg->start_p = 1; + REG_WRITE_32(&pkc_regs->start, start_reg); + + // Poll on busy status + status = busy_wait(&pkc_regs->status, PUFCC_PKC_ERROR_MASK); + + if (status != PUFCC_SUCCESS) { + return status; + } + + // Read decrypted message from proper offset in ECP data field and reverse it + memcpy(pufcc_buffer, + (uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_RSA2048_SIGN_OFFSET, + PUFCC_RSA_2048_LEN); + reverse(dec_msg, pufcc_buffer, PUFCC_RSA_2048_LEN); + + status = rsa_p1v15_verify(dec_msg, msg_addr); + + return status; +} + +/** + * @fn pufcc_ecdsa256_sign_verify + * @brief Verify ECDSA256 signature of the input message data + * + * @param[in] sig Address of the message signature + * @param[in] msg_addr Address of the message data + * @param[in] pub_key ECDSA256 public key + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_ecdsa256_sign_verify( + struct rs_crypto_ec256_sig *sig, struct rs_crypto_addr *msg_addr, + struct rs_crypto_ec256_puk *pub_key) { + uint32_t temp32, prev_len = 0; + enum pufcc_status status; + struct rs_crypto_hash hash; + + // Calculate hash of the message + if (pufcc_calc_sha256_hash_sg(msg_addr, true, true, &prev_len, NULL, &hash) != + PUFCC_SUCCESS) { + return PUFCC_E_ERROR; + } + +#if !CONFIG_RS_RTOS_PORT + RS_PROFILE_CHECKPOINT("msg hash calc"); +#endif + + // Set the EC NIST P256 parameters after reversing them + reverse(pufcc_buffer, ecc_param_nistp256.prime, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + uint32_t *ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PRIME_OFFSET/4; + uint32_t *buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PRIME_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, ecc_param_nistp256.a, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_EC_A_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_EC_A_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, ecc_param_nistp256.b, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_EC_B_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_EC_B_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, ecc_param_nistp256.px, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PX_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PX_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, ecc_param_nistp256.py, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PY_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PY_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, ecc_param_nistp256.order, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_ORDER_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_ORDER_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + // Configure signature scheme + temp32 = 0; + struct pufcc_pkc_ecp_ec_reg *ecp_ec_reg = + (struct pufcc_pkc_ecp_ec_reg *)&temp32; + ecp_ec_reg->field = PUFCC_ECDSA256; + ecp_ec_reg->h = 1; // EC cofactor h + REG_WRITE_32(&pkc_regs->ecp_ec, ecp_ec_reg); + + // Write microprogram for ECDSA 256 + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_mac; + buf_ptr = (uint32_t*)p256_ecdsa_mprog; + for(int i = 0; i < sizeof(p256_ecdsa_mprog)/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((void *)&pkc_regs->ecp_mac, p256_ecdsa_mprog, + sizeof(p256_ecdsa_mprog)); + #endif + + // Set the hash, public key & signature in PKC module after reversing each + reverse(pufcc_buffer, hash.val, PUFCC_SHA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_HASH_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_HASH_OFFSET, + pufcc_buffer, PUFCC_SHA_256_LEN); + #endif + + reverse(pufcc_buffer, pub_key->x, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PUBX_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PUBX_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, pub_key->y, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PUBY_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_PUBY_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, sig->r, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_SIG_R_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_SIG_R_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + + reverse(pufcc_buffer, sig->s, PUFCC_ECDSA_256_LEN); + #if CONFIG_RS_RTOS_PORT + ptr = (uint32_t*)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_SIG_S_OFFSET/4; + buf_ptr = (uint32_t*)pufcc_buffer; + for(int i = 0; i < PUFCC_ECDSA_256_LEN/4; i++) { + *ptr++ = *buf_ptr++; + } + #else + memcpy((uint8_t *)&pkc_regs->ecp_data + PUFCC_DATA_ECDSA_SIG_S_OFFSET, + pufcc_buffer, PUFCC_ECDSA_256_LEN); + #endif + +#if !CONFIG_RS_RTOS_PORT + RS_PROFILE_CHECKPOINT("misc verif ops"); +#endif + + // Clear and disable PKC interrupt + temp32 = 0; + struct pufcc_intrpt_reg *intrpt_reg = (struct pufcc_intrpt_reg *)&temp32; + intrpt_reg->intrpt_st = 1; + REG_WRITE_32(&pkc_regs->interrupt, intrpt_reg); + + // Start PKC operation + struct pufcc_start_reg *start_reg = (struct pufcc_start_reg *)&temp32; + start_reg->start_p = 1; + REG_WRITE_32(&pkc_regs->start, start_reg); + + // Poll on busy status + status = busy_wait(&pkc_regs->status, PUFCC_PKC_ERROR_MASK); + +#if !CONFIG_RS_RTOS_PORT + RS_PROFILE_CHECKPOINT("PKC op"); +#endif + + return status; +} + +#if !CONFIG_RS_RTOS_PORT + + /** + * @fn pufcc_dma_transfer + * @brief Transfer data using PUFcc DMA + * + * @param[in] src_addr Source data address + * @param[in] dest_addr Destination data address + * @param[in] len Length of the data to be transferred + * @param[in] fixed_read Read data from a fixed address + * @param[in] fixed_write Write data to a fixed address + * @return PUFCC_SUCCESS on success, otherwise an error code + */ + enum pufcc_status pufcc_dma_transfer(uint32_t src_addr, uint32_t dest_addr, + uint32_t len, bool fixed_read, + bool fixed_write) { + enum pufcc_status status; + uint32_t temp32 = 0; + + // Configure DMA intrpt register + struct pufcc_intrpt_reg *intrpt_reg = (struct pufcc_intrpt_reg *)&temp32; + intrpt_reg->intrpt_st = 1; // Write 1 to clear interrupt + REG_WRITE_32(&dma_regs->interrupt, intrpt_reg); + + // Set dma_cfg_0 register + temp32 = 0; // rng_en = 0, sg_en = 0 + REG_WRITE_32(&dma_regs->cfg_0, &temp32); + + struct pufcc_dma_cfg_1_reg *cfg_1_reg = (struct pufcc_dma_cfg_1_reg *)&temp32; + cfg_1_reg->rbst_max = 0xF; + cfg_1_reg->rbst_min = 0xF; + cfg_1_reg->wbst_max = 0xF; + cfg_1_reg->wbst_min = 0xF; + REG_WRITE_32(&dma_regs->cfg_1, cfg_1_reg); + + // Set data source address in dsc_cfg_0 register + REG_WRITE_32(&dma_regs->dsc_cfg_0, &src_addr); + + // Set decrypted data destination address in dsc_cfg_1 register + REG_WRITE_32(&dma_regs->dsc_cfg_1, &dest_addr); + + // Set data length in dsc_cfg_2 register + REG_WRITE_32(&dma_regs->dsc_cfg_2, &len); + + // Configure dma_dsc_cfg_4 register + temp32 = 0; + struct pufcc_dma_dsc_cfg_4_reg *dsc_cfg_4_reg = + (struct pufcc_dma_dsc_cfg_4_reg *)&temp32; + dsc_cfg_4_reg->fw = fixed_write; + dsc_cfg_4_reg->fr = fixed_read; + dsc_cfg_4_reg->no_cypt = true; // Bypass crypto modules + REG_WRITE_32(&dma_regs->dsc_cfg_4, dsc_cfg_4_reg); + + // Start DMA operation + struct pufcc_start_reg *start_reg = (struct pufcc_start_reg *)&temp32; + start_reg->start_p = 1; + REG_WRITE_32(&dma_regs->start, start_reg); + + // Poll on busy status + status = busy_wait(&dma_regs->status_0, PUFCC_DMA_ERROR_MASK); + + return status; + } + +#endif + +/** + * @fn pufcc_otp_setup_wait + * @brief Wait for the PUFrt module setup during power on + * + * @return PUFCC_SUCCESS if OTP is setup successfully, otherwise an error code + */ +enum pufcc_status pufcc_otp_setup_wait(void) { + enum pufcc_status status = busy_wait(&rt_regs->status, PUFCC_RT_ERROR_MASK); + + return status; +} + +/** + * @fn pufcc_program_otp + * @brief Write data to an OTP slot. + * PUFcc OTP memory contains 1024 bytes and is divided into 32 + * individual slots of 32 bytes each. + * + * @param[in] in_buf Buffer containing data to be written to OTP + * @param[in] len Length of the input buffer + * @param[in] otp_slot OTP slot; PUFCC_OTPKEY_0 ~ PUFCC_OTPKEY_31 + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_program_otp(const uint8_t *in_buf, uint32_t len, + enum pufcc_otp_slot otp_slot) { + enum pufcc_status check; + uint16_t addr = otp_slot * PUFCC_OTP_KEY_LEN; + uint32_t start_index = addr / PUFCC_WORD_SIZE; + enum pufcc_otp_lock lock; + + if ((check = otp_range_check(addr, len)) != PUFCC_SUCCESS) return check; + + // Return error if write access is locked + pufcc_get_otp_rwlck(otp_slot, &lock); + if (lock != PUFCC_OTP_RW) return PUFCC_E_DENY; + + // Program the OTP slot + for (uint32_t i = 0; i < len; i += 4) { + union { + uint32_t word; + uint8_t byte[4]; + } otp_word; + for (int8_t j = 3; j >= 0; j--) // reserve, default 0xff + otp_word.byte[j] = ((i + 3 - j) < len) ? in_buf[i + 3 - j] : 0xff; + + otp_mem->otp[start_index + (i / 4)] = otp_word.word; + } + + return PUFCC_SUCCESS; +} + +/** + * @fn pufcc_read_otp + * @brief Read data from an OTP slot. + * PUFcc OTP memory contains 1024 bytes and is divided into 32 + * individual slots of 32 bytes each. + * + * @param[in] out_buf Buffer to read data into + * @param[in] len Length of the data to read + * @param[in] otp_slot OTP slot; PUFCC_OTPKEY_0 ~ PUFCC_OTPKEY_31 + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_read_otp(uint8_t *out_buf, uint32_t len, + enum pufcc_otp_slot otp_slot) { + enum pufcc_status check; + uint16_t addr = otp_slot * PUFCC_OTP_KEY_LEN; + uint32_t word, start_index, wlen; + enum pufcc_otp_lock lock = PUFCC_OTP_RW; // default value + + if ((check = otp_range_check(addr, len)) != PUFCC_SUCCESS) return check; + + // Return error if read access is locked + pufcc_get_otp_rwlck(otp_slot, &lock); + if (lock == PUFCC_OTP_NA) return PUFCC_E_DENY; + + wlen = len / PUFCC_WORD_SIZE; + start_index = addr / PUFCC_WORD_SIZE; + + if (wlen > 0) { + memcpy(out_buf, (void *)(otp_mem->otp + start_index), + wlen * PUFCC_WORD_SIZE); + + uint32_t *out32 = (uint32_t *)out_buf; + for (size_t i = 0; i < wlen; ++i) *(out32 + i) = be2le(*(out32 + i)); + } + + if (len % PUFCC_WORD_SIZE != 0) { + out_buf += wlen * PUFCC_WORD_SIZE; + word = be2le(*(otp_mem->otp + start_index + wlen)); + memcpy(out_buf, &word, len % PUFCC_WORD_SIZE); + } + + return PUFCC_SUCCESS; +} + +/** + * @fn pufcc_lock_otp + * @brief Lock an OTP key slot according to passed-in lock value. + * + * @param[in] otp_slot OTP slot; PUFCC_OTPKEY_0 ~ PUFCC_OTPKEY_31 + * @param[in] len Length of the OTP slot to be locked + * @param[in] lock Value of the lock to be placed + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_lock_otp(enum pufcc_otp_slot otp_slot, uint32_t len, + enum pufcc_otp_lock lock) { + enum pufcc_status check; + uint32_t lock_val = lock, shift = 0, start = 0, end = 0, mask = 0, val32 = 0; + int rwlock_index; + uint16_t addr = otp_slot * PUFCC_OTP_KEY_LEN; + + if ((check = otp_range_check(addr, len)) != PUFCC_SUCCESS) return check; + + // Set end and start indices of OTP words + end = (len + 3) / 4; + start = addr / PUFCC_WORD_SIZE; + + for (uint32_t i = 0; i < end; i++) { + int idx = start + i; + + // Get the index of RWLCK register corresponding to current OTP word index + if ((rwlock_index = rwlck_index_get(idx)) == -1) { + return PUFCC_E_ERROR; + } + + // Get shift size for lock value to be written to RWLCK register according + // to OTP word index + shift = (idx % PUFCC_OTP_WORDS_PER_RWLCK_REG) * + PUFCC_OTP_RWLCK_REG_BITS_PER_OTP_WORD; + // Update lock value for current 'rwlock_index' + val32 |= lock_val << shift; + // Update mask value for current 'rwlock_index' + mask |= 0xF << shift; + + // If we have fully utilized RWLCK register at 'rwlock_index' or this is + // the end of OTP range that we are locking then write the lock value in + // RWLCK register at 'rwlock_index' + if (shift == 28 || i == end - 1) { + // Read modify write + val32 |= (rt_regs->pif[rwlock_index] & (~mask)); + rt_regs->pif[rwlock_index] = val32; + + // Clear values for next iteration + val32 = 0; + mask = 0; + } + } + + return PUFCC_SUCCESS; +} + +/** + * @fn pufcc_zeroize_otp + * @brief Zeroize an OTP key slot (32 bytes) permanently. + * + * @param[in] otp_slot OTP slot; PUFCC_OTPKEY_0 ~ PUFCC_OTPKEY_31 + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +enum pufcc_status pufcc_zeroize_otp(enum pufcc_otp_slot otp_slot) { + enum pufcc_status status; + + if (otp_slot < PUFCC_OTPKEY_0 || otp_slot > PUFCC_OTPKEY_31) { + status = PUFCC_E_INVALID; + } else { + uint32_t zeroize_cmd = + (otp_slot - PUFCC_OTPKEY_0) + PUFCC_OTP_ZEROIZE_BASE_CMD; + + rt_regs->otp_zeroize = zeroize_cmd; + + // Wait on busy status + status = busy_wait(&rt_regs->status, PUFCC_RT_ERROR_MASK); + } + + return status; +} + +/** + * @fn pufcc_get_otp_rwlck + * @brief Get the read write lock value of passed-in OTP slot. This function + * assumes that the lock value of all the words of an OTP is same as that + * of the first word of that slot + * + * @param[in] otp_slot OTP slot; PUFCC_OTPKEY_0 ~ PUFCC_OTPKEY_31 + * @param[out] lock_val Lock address to return the lock value in + * @return PUFCC_SUCCESS on success, otherwise and error code + */ +enum pufcc_status pufcc_get_otp_rwlck(enum pufcc_otp_slot otp_slot, + enum pufcc_otp_lock *lock_val) { + enum pufcc_status check; + uint16_t addr = otp_slot * PUFCC_OTP_KEY_LEN; + + if ((check = otp_range_check(addr, 4)) != PUFCC_SUCCESS) return check; + + // Get OTP word index + int index = addr / PUFCC_WORD_SIZE; + + // Get offset of the lock value within RWLCK register corresponding to this + // OTP word + int rwlck_offset = (index % PUFCC_OTP_WORDS_PER_RWLCK_REG) * + PUFCC_OTP_RWLCK_REG_BITS_PER_OTP_WORD; + + // Get the index of RWLCK register corresponding to current OTP word index + // read lock value at that index + index = rwlck_index_get(index); + uint32_t lck = (rt_regs->pif[index] >> rwlck_offset) & PUFCC_PIF_RWLCK_MASK; + + switch (lck) { + // Read write access + case PUFCC_OTP_RWLCK_RW_0: + case PUFCC_OTP_RWLCK_RW_1: + case PUFCC_OTP_RWLCK_RW_2: + case PUFCC_OTP_RWLCK_RW_3: + case PUFCC_OTP_RWLCK_RW_4: + *lock_val = PUFCC_OTP_RW; + break; + + // Read only access + case PUFCC_OTP_RWLCK_RO_0: + case PUFCC_OTP_RWLCK_RO_1: + case PUFCC_OTP_RWLCK_RO_2: + *lock_val = PUFCC_OTP_RO; + break; + + // All other values indicate no access + default: + *lock_val = PUFCC_OTP_NA; + break; + } + + return PUFCC_SUCCESS; +} + +#if CONFIG_RS_RTOS_PORT + + int pufcc_clear_and_disable_intr(void) { + int status = (dma_regs->status_0 & PUFCC_DMA_ERROR_MASK ? -1 : 0); + struct pufcc_intrpt_reg *intrpt_reg_ptr = + (struct pufcc_intrpt_reg *)&dma_regs->interrupt; + + // Clear and disable interrupt + intrpt_reg_ptr->intrpt_st = 1; // Set to clear + intrpt_reg_ptr->intrpt_en = 0; + + return status; + } + +#else + + int pufcc_dma_request_channel(struct pufcc_dma_dev *dev) { + if (dev->is_dev_free) { + dev->is_dev_free = false; + return 0; + } + + return -1; + } + + void pufcc_dma_release_channel(struct pufcc_dma_dev *dev, int channel) { + (void)channel; + dev->is_dev_free = true; + } + + enum rs_status pufcc_dma_config_descriptor_memory(struct pufcc_dma_dev *dev, + int channel, uintptr_t addr, + size_t max_descriptors) { + // Check that channel is valid and is in use + if ((channel != 0) || (dev->is_dev_free)) { + return ERROR; + } + + dev->dma_descs = (struct pufcc_sg_dma_desc *)addr; + dev->num_descriptors = max_descriptors; + return OK; + } + + enum rs_status pufcc_dma_config_xfer(struct pufcc_dma_dev *dev, int channel, + struct rs_dma_config *config) { + uint8_t desc_count = 0; + struct rs_dma_block_config *current_block = config->head_block; + struct pufcc_dma_cfg_0_reg dma_cfg_0_reg = {0}; + struct pufcc_dma_cfg_1_reg cfg_1_reg = {0}; + struct pufcc_dma_dsc_cfg_4_reg dma_dsc_cfg_4_reg = {0}; + struct pufcc_intrpt_reg intrpt_reg = {0}; + + // Check that channel is valid and is in use and required descriptors for this + // transactions are available + if ((channel != 0) || (dev->is_dev_free) || + (config->block_count > dev->num_descriptors)) { + return ERROR; + } + + // Write 1 to clear interrupt + intrpt_reg.intrpt_st = 1; + + // Setup interrupt + if (config->complete_callback_en) { + intrpt_reg.intrpt_en = 1; + } else { + intrpt_reg.intrpt_en = 0; + } + + // Set SGDMA descriptors + do { + dev->dma_descs[desc_count].read_addr = + be2le((uint32_t)current_block->src_addr); + dev->dma_descs[desc_count].write_addr = + be2le((uint32_t)current_block->dst_addr); + dev->dma_descs[desc_count].length = be2le(current_block->block_size); + dev->dma_descs[desc_count].next = + be2le((uint32_t)&dev->dma_descs[desc_count + 1]); + + dev->dma_descs[desc_count].key_cfg = 0; + dev->dma_descs[desc_count].cypt_cfg[0] = 0; + dev->dma_descs[desc_count].cypt_cfg[1] = 0; + + *(uint32_t *)&dma_dsc_cfg_4_reg = 0; + if (current_block->src_addr_adjust == RS_DMA_ADDR_ADJUST_FIXED) { + dma_dsc_cfg_4_reg.fr = 1; + } else if (current_block->src_addr_adjust != RS_DMA_ADDR_ADJUST_INCREMENT) { + return ERROR; + } + + if (current_block->dst_addr_adjust == RS_DMA_ADDR_ADJUST_FIXED) { + dma_dsc_cfg_4_reg.fw = 1; + } else if (current_block->dst_addr_adjust != RS_DMA_ADDR_ADJUST_INCREMENT) { + return ERROR; + } + + // Bypass crypto modules + dma_dsc_cfg_4_reg.no_cypt = true; + + if (!desc_count) { + dma_dsc_cfg_4_reg.head = true; + } + + current_block = current_block->next_block; + + // Mark this descriptor as last if there is no more data + if (!current_block) { + dma_dsc_cfg_4_reg.dn_pause = true; + dma_dsc_cfg_4_reg.tail = true; + + if (config->complete_callback_en) { + dma_dsc_cfg_4_reg.dn_intrpt = true; + } + } + + dev->dma_descs[desc_count].dsc_cfg_4 = + be2le(*(uint32_t *)&dma_dsc_cfg_4_reg); + + desc_count++; + } while (current_block && (desc_count < dev->num_descriptors)); + + if (current_block) { + // No enough descriptors available + return ERROR; + } + + /*** Configure DMA registers ***/ + // Enable SGDMA in dma_cfg_0 register + dma_cfg_0_reg.sg_en = 1; + REG_WRITE_32(&dev->regs->cfg_0, &dma_cfg_0_reg); + + cfg_1_reg.rbst_max = 0xF; + cfg_1_reg.rbst_min = 0xF; + cfg_1_reg.wbst_max = 0xF; + cfg_1_reg.wbst_min = 0xF; + REG_WRITE_32(&dev->regs->cfg_1, &cfg_1_reg); + + // Set dsc_cfg_2 register to indicate it's an SGDMA operation + dev->regs->dsc_cfg_2 = PUFCC_DMA_DSC_CFG2_SGDMA_VAL; + + // Set starting address of SGDMA descriptors in dma_dsc_cfg3 register + dev->regs->dsc_cfg_3 = (uint32_t)dev->dma_descs; + + // Write interrupt register with values populated above + REG_WRITE_32(&dev->regs->interrupt, &intrpt_reg); + + // Set up call backs + dev->callback = config->callback; + dev->callback_args = config->callback_args; + + return OK; + } + + enum rs_status pufcc_dma_start_xfer(struct pufcc_dma_dev *dev, int channel) { + struct pufcc_start_reg start_reg = {0}; + + // Check that channel number is valid and the channel has been requested + if ((channel != 0) || (dev->is_dev_free)) { + return ERROR; + } + + // Start the DMA operation by writing to its start register + start_reg.start_p = 1; + REG_WRITE_32(&dev->regs->start, &start_reg); + + return OK; + } + + enum rs_status pufcc_dma_stop_xfer(struct pufcc_dma_dev *dev, int channel) { + struct pufcc_sg_dma_desc *next_desc_ptr; + struct pufcc_dma_dsc_cfg_4_reg dma_dsc_cfg_4_reg = {0}; + + // check the channel number is valid and the channel has been requested + if ((channel != 0) || dev->is_dev_free) { + return ERROR; + } + + // Get pointer to next descriptor in queue + next_desc_ptr = (struct pufcc_sg_dma_desc *)dev->regs->dsc_cur_3; + + // Make sure that this descriptor lies within descriptor memory; it will lie + // outside the memory if last descriptor is already being processed + if (((uint32_t)next_desc_ptr > (uint32_t)dev->dma_descs) && + ((uint32_t)next_desc_ptr < + ((uint32_t)dev->dma_descs + + (dev->num_descriptors * sizeof(struct pufcc_sg_dma_desc))))) { + // Set up descriptor to stop DMA operation + *(uint32_t *)&dma_dsc_cfg_4_reg = next_desc_ptr->dsc_cfg_4; + dma_dsc_cfg_4_reg.dn_pause = true; + dma_dsc_cfg_4_reg.tail = true; + } + + return OK; + } + + void pufcc_dma_irq_handler(struct pufcc_dma_dev *dev) { + int status = (dev->regs->status_0 & PUFCC_DMA_ERROR_MASK ? -1 : 0); + struct pufcc_intrpt_reg *intrpt_reg_ptr = + (struct pufcc_intrpt_reg *)&dev->regs->interrupt; + + // Clear and disable interrupt + intrpt_reg_ptr->intrpt_st = 1; // Set to clear + intrpt_reg_ptr->intrpt_en = 0; + + dev->callback(dev->callback_args, 0, status); + } + +#endif + +/** + * @fn rsa_p1v15_verify + * @brief Verify input RSA2048 decrypted message according to PKCS#1 v1.5 RSA + * verification standard. + * @param[in] dec_msg Input RSA decrypted message + * @param[in] msg_addr Address of the original data that was RSA signed + * @return PUFCC_SUCCESS on success, otherwise an error code. + */ +static enum pufcc_status rsa_p1v15_verify(const uint8_t *dec_msg, + struct rs_crypto_addr *msg_addr) { + uint32_t i, prev_len = 0; + struct rs_crypto_hash hash; + uint8_t pret[19] = {0x30, 0, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0, 0x05, 0x00, 0x04, 0}; + + if ((dec_msg[0] != 0x00) || (dec_msg[1] != 0x01)) { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_VERFAIL; + } + + for (i = 2; i < PUFCC_RSA_2048_LEN; i++) { + if (dec_msg[i] != 0xff) { + break; + } + } + + if (dec_msg[i++] != 0x00) { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_VERFAIL; + } + + // Verify that decrypted message has SHA256 hash + if (dec_msg[i + 14] == 1) { + pret[1] = 0x31; + pret[14] = 0x01; + pret[18] = 0x20; + } else { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_INVALID; + } + + if ((memcmp(dec_msg + i, pret, 19) != 0) || + ((i + 19 + pret[18]) != PUFCC_RSA_2048_LEN)) { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_VERFAIL; + } + + // Calculate hash of the message + if (pufcc_calc_sha256_hash_sg(msg_addr, true, true, &prev_len, NULL, &hash) != + PUFCC_SUCCESS) { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_ERROR; + } + + if (memcmp(dec_msg + i + 19, hash.val, hash.len) != 0) { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_VERFAIL; + } + + return PUFCC_SUCCESS; +} + +/** + * @fn rwlck_index_get + * @brief Get the index of RWLCK register corresponding to passed-in OTP word + * index. + * + * @param[in] idx OTP word index for which to get the RWLCK register index for + * @return Index of the RWLCK register + */ +static int rwlck_index_get(uint32_t idx) { + uint32_t rwlck_idx = idx / PUFCC_OTP_WORDS_PER_RWLCK_REG; + + if (rwlck_idx >= PUFCC_PIF_MAX_RWLOCK_REGS) return -1; + + // Return the actual index of RWCLK register in PIF registers group + return PUFCC_PIF_RWLCK_START_INDEX + rwlck_idx; +} + +/** + * @fn reverse + * @brief Reverse input byte array. + * + * @param[in] dst Destination address of the reversed byte array + * @param[in] src Address of the input byte array + * @param[in] len Length of the input byte array to be reversed + */ +static void reverse(uint8_t *dst, const uint8_t *src, size_t len) { + for (size_t i = 0, j = len - 1; i < len; i++, j--) { + dst[i] = src[j]; + } +} + +/** + * @fn be2le + * @brief Reverse endianness of the input 4 byte word + * + * @param[in] var Input 4 byte variable + * @return 4 byte word with reversed endianness + */ +static uint32_t be2le(uint32_t var) { + return (((0xff000000 & var) >> 24) | ((0x00ff0000 & var) >> 8) | + ((0x0000ff00 & var) << 8) | ((0x000000ff & var) << 24)); +} + +/** + * @fn otp_range_check + * @brief Check range validity of the input OTP address + * + * @param[in] addr OTP address + * @param[in] len Length of OTP after OTP address + * @return 4 byte word with reversed endianness + * @return PUFCC_SUCCESS if OTP address and range is valid, otherwise + * an error code. + */ +static enum pufcc_status otp_range_check(uint32_t addr, uint32_t len) { + // word-aligned OTP address check + if ((addr % PUFCC_WORD_SIZE) != 0) return PUFCC_E_ALIGN; + // OTP boundary check + if ((len > PUFCC_OTP_LEN) || (addr > (PUFCC_OTP_LEN - len))) + return PUFCC_E_OVERFLOW; + return PUFCC_SUCCESS; +} + +/** + * @fn busy_wait + * @brief Waits on busy bit of the passed-in status register till it gets + * cleared or it times out. + * + * @param[in] status_reg_addr Status register's address + * @param[in] error_mask Bitmask of error bits in passed-in status register + * @return PUFCC_SUCCESS if busy bit gets cleared without an + * error, otherwise an error code. + */ +static enum pufcc_status busy_wait(volatile uint32_t *status_reg_addr, + uint32_t error_mask) { + uint32_t status; + int32_t busy_count = PUFCC_MAX_BUSY_COUNT; + + do { + #if CONFIG_RS_RTOS_PORT + status = sys_read32((mem_addr_t)status_reg_addr); + #else + status = read_reg(status_reg_addr); + #endif + busy_count--; + } while ((status & PUFCC_BUSY_BIT_MASK) && (busy_count > 0)); + + if (status & PUFCC_BUSY_BIT_MASK) { + printf("%s(%d)\r\n", __func__,__LINE__); + return PUFCC_E_TIMEOUT; + } else if (status & error_mask) { + printf("%s(%d) status 0x%08x ecp_err_code:0x%x\r\n", \ + __func__,__LINE__, status, pkc_regs->ecp_err_code); + return PUFCC_E_ERROR; + } + + return PUFCC_SUCCESS; +} + +enum pufcc_status pufcc_init(uint32_t base_addr) { + enum pufcc_status status; + + // Initialize base addresses of different PUFcc modules + dma_regs = (struct pufcc_dma_regs *)base_addr; + rt_regs = (struct pufcc_rt_regs *)(base_addr + PUFCC_RT_OFFSET); + otp_mem = (struct pufcc_otp_mem *)(base_addr + PUFCC_RT_OFFSET + + PUFCC_RT_OTP_OFFSET); + hmac_regs = (struct pufcc_hmac_regs *)(base_addr + PUFCC_HMAC_OFFSET); + crypto_regs = (struct pufcc_crypto_regs *)(base_addr + PUFCC_CRYPTO_OFFSET); + sp38a_regs = (struct pufcc_sp38a_regs *)(base_addr + PUFCC_SP38A_OFFSET); + pkc_regs = (struct pufcc_pkc_regs *)(base_addr + PUFCC_PKC_OFFSET); + + // Wait for OTP setup + status = pufcc_otp_setup_wait(); + + return status; +} diff --git a/drivers/crypto/pufcc.h b/drivers/crypto/pufcc.h new file mode 100644 index 0000000000000..a53a56522cc2c --- /dev/null +++ b/drivers/crypto/pufcc.h @@ -0,0 +1,644 @@ +#ifndef _PUFCC_H_ +#define _PUFCC_H_ + +#include + +#if CONFIG_RS_RTOS_PORT + #include + #include +#else + #include "rs_crypto.h" + #include "rs_dma.h" +#endif + +/*** Generic PUFcc defines ***/ +#define PUFCC_WORD_SIZE 4 +#define PUFCC_BUSY_BIT_MASK 0x00000001 + +/*** RT and OTP defines ***/ +#define PUFCC_RT_OFFSET 0x3000 +#define PUFCC_RT_OTP_OFFSET 0x400 +#define PUFCC_RT_ERROR_MASK 0x0000001e +#define PUFCC_OTP_LEN 1024 +#define PUFCC_OTP_KEY_LEN 32 +#define PUFCC_OTP_ZEROIZE_BASE_CMD 0x80 + +// One read/write lock register controls 8 OTP words +#define PUFCC_OTP_WORDS_PER_RWLCK_REG 8 + +// 4 bits are reserved for lock value of one OTP word in read/write lock +// register +#define PUFCC_OTP_RWLCK_REG_BITS_PER_OTP_WORD 4 +#define PUFCC_PIF_RWLCK_MASK 0xF +#define PUFCC_PIF_MAX_RWLOCK_REGS \ + (PUFCC_OTP_LEN / PUFCC_WORD_SIZE / PUFCC_OTP_WORDS_PER_RWLCK_REG) + +// Start index of the RWLCK register in PIF registers group +#define PUFCC_PIF_RWLCK_START_INDEX 32 + +// Define all possible OTP lock values +#define PUFCC_OTP_RWLCK_RW_0 0x0 // Read Write access +#define PUFCC_OTP_RWLCK_RW_1 0x1 // Read Write access +#define PUFCC_OTP_RWLCK_RW_2 0x2 // Read Write access +#define PUFCC_OTP_RWLCK_RW_3 0x4 // Read Write access +#define PUFCC_OTP_RWLCK_RW_4 0x8 // Read Write access +#define PUFCC_OTP_RWLCK_RO_0 0x3 // Read Only access +#define PUFCC_OTP_RWLCK_RO_1 0x7 // Read Only access +#define PUFCC_OTP_RWLCK_RO_2 0xb // Read Only access + +/*** DMA defines ***/ +#define PUFCC_DMA_KEY_DST_HASH 0x1 +#define PUFCC_DMA_KEY_DST_SP38A 0x8 +#define PUFCC_DMA_DSC_CFG2_SGDMA_VAL 0x20 +#define PUFCC_DMA_ERROR_MASK 0xFFFFFFFE + +/*** HMAC defines ***/ +#define PUFCC_HMAC_OFFSET 0x0800 +#define PUFCC_HMAC_SW_KEY_MAXLEN 64 +#define PUFCC_SHA_256_LEN 32 +#define PUFCC_HMAC_FUNCTION_HASH 0x0 +#define PUFCC_HMAC_VARIANT_SHA256 0x03 + +/*** Crypto defines ***/ +#define PUFCC_CRYPTO_OFFSET 0x0100 +#define PUFCC_CRYPTO_SW_KEY_MAXLEN 64 // The byte length of CRYPTO_SW_KEY_ADDR +#define PUFCC_CRYPTO_DGST_LEN 64 // The byte length of CRYPTO_DGST field +#define PUFCC_CRYPTO_IV_MAXLEN 16 +#define PUFCC_CRYPTO_AES128_KEY_LEN 16 +#define PUFCC_CRYPTO_AES256_KEY_LEN 32 + +/*** SP38a defines ***/ +#define PUFCC_SP38A_OFFSET 0x0200 +#define PUFCC_SP38A_STATUS_ERROR_MASK 0xfffff0c0 + +/*** PKC defines ***/ +#define PUFCC_PKC_OFFSET 0x1000 +#define PUFCC_RSA_2048_LEN 256 +#define PUFCC_ECDSA_256_LEN 32 +#define PUFCC_DATA_RSA2048_MODULUS_OFFSET 256 +#define PUFCC_DATA_RSA2048_SIGN_OFFSET 768 +#define PUFCC_DATA_ECDSA_PRIME_OFFSET 256 +#define PUFCC_PKC_ERROR_MASK 0xFFFFFFFE +#define PUFCC_DATA_ECDSA_EC_A_OFFSET \ + (PUFCC_DATA_ECDSA_PRIME_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_EC_B_OFFSET \ + (PUFCC_DATA_ECDSA_EC_A_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_PX_OFFSET \ + (PUFCC_DATA_ECDSA_EC_B_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_PY_OFFSET \ + (PUFCC_DATA_ECDSA_PX_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_ORDER_OFFSET \ + (PUFCC_DATA_ECDSA_PY_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_HASH_OFFSET \ + (PUFCC_DATA_ECDSA_ORDER_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_PUBX_OFFSET \ + (PUFCC_DATA_ECDSA_HASH_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_PUBY_OFFSET \ + (PUFCC_DATA_ECDSA_PUBX_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_SIG_R_OFFSET \ + (PUFCC_DATA_ECDSA_PUBY_OFFSET + PUFCC_ECDSA_256_LEN) + +#define PUFCC_DATA_ECDSA_SIG_S_OFFSET \ + (PUFCC_DATA_ECDSA_SIG_R_OFFSET + PUFCC_ECDSA_256_LEN) + +// PUFcc status codes +enum pufcc_status { + PUFCC_SUCCESS, // Success. + PUFCC_E_ALIGN, // Address alignment mismatch. + PUFCC_E_OVERFLOW, // Space overflow. + PUFCC_E_UNDERFLOW, // Size too small. + PUFCC_E_INVALID, // Invalid argument. + PUFCC_E_BUSY, // Resource is occupied. + PUFCC_E_UNAVAIL, // Resource is unavailable. + PUFCC_E_FIRMWARE, // Firmware error. + PUFCC_E_VERFAIL, // Invalid public key or digital signature. + PUFCC_E_ECMPROG, // Invalid ECC microprogram. + PUFCC_E_DENY, // Access denied. + PUFCC_E_UNSUPPORT, // Not support. + PUFCC_E_INFINITY, // Point at infinity. + PUFCC_E_ERROR, // Unspecific error. + PUFCC_E_TIMEOUT, // Operation timed out. +}; + +// PUFcc key slots; 32 slots of 256 bits each +enum pufcc_otp_slot { + PUFCC_OTPKEY_0, // OTP key slot 0, 256 bits + PUFCC_OTPKEY_1, // OTP key slot 1, 256 bits + PUFCC_OTPKEY_2, // OTP key slot 2, 256 bits + PUFCC_OTPKEY_3, // OTP key slot 3, 256 bits + PUFCC_OTPKEY_4, // OTP key slot 4, 256 bits + PUFCC_OTPKEY_5, // OTP key slot 5, 256 bits + PUFCC_OTPKEY_6, // OTP key slot 6, 256 bits + PUFCC_OTPKEY_7, // OTP key slot 7, 256 bits + PUFCC_OTPKEY_8, // OTP key slot 8, 256 bits + PUFCC_OTPKEY_9, // OTP key slot 9, 256 bits + PUFCC_OTPKEY_10, // OTP key slot 10, 256 bits + PUFCC_OTPKEY_11, // OTP key slot 11, 256 bits + PUFCC_OTPKEY_12, // OTP key slot 12, 256 bits + PUFCC_OTPKEY_13, // OTP key slot 13, 256 bits + PUFCC_OTPKEY_14, // OTP key slot 14, 256 bits + PUFCC_OTPKEY_15, // OTP key slot 15, 256 bits + PUFCC_OTPKEY_16, // OTP key slot 16, 256 bits + PUFCC_OTPKEY_17, // OTP key slot 17, 256 bits + PUFCC_OTPKEY_18, // OTP key slot 18, 256 bits + PUFCC_OTPKEY_19, // OTP key slot 19, 256 bits + PUFCC_OTPKEY_20, // OTP key slot 20, 256 bits + PUFCC_OTPKEY_21, // OTP key slot 21, 256 bits + PUFCC_OTPKEY_22, // OTP key slot 22, 256 bits + PUFCC_OTPKEY_23, // OTP key slot 23, 256 bits + PUFCC_OTPKEY_24, // OTP key slot 24, 256 bits + PUFCC_OTPKEY_25, // OTP key slot 25, 256 bits + PUFCC_OTPKEY_26, // OTP key slot 26, 256 bits + PUFCC_OTPKEY_27, // OTP key slot 27, 256 bits + PUFCC_OTPKEY_28, // OTP key slot 28, 256 bits + PUFCC_OTPKEY_29, // OTP key slot 29, 256 bits + PUFCC_OTPKEY_30, // OTP key slot 30, 256 bits + PUFCC_OTPKEY_31, // OTP key slot 31, 256 bits +#if CONFIG_RS_RTOS_PORT + PUFCC_TOTAL_SLOTS // OTP Number of slots. +#endif +}; + +// OTP lock types +enum pufcc_otp_lock { + PUFCC_OTP_NA = 0xF, // No-Access + PUFCC_OTP_RO = 0x3, // Read-Only + PUFCC_OTP_RW = 0x0, // Read-Write +}; + +// PUFcc read/write types +enum pufcc_dma_rw_type { AUTO_INCREMENT, FIXED_RW }; + +// PUFcc key types +enum pufcc_key_type { PUFCC_SW_KEY, PUFCC_OTP_KEY }; + +// PUFcc SP38a variants +enum pufcc_sp38a_variant { + PUFCC_AES128, + PUFCC_AES192, + PUFCC_AES256, + PUFCC_SM4 +}; + +// PUFcc PKC schemes +enum pufcc_pkc_scheme { PUFCC_RSA_2048 = 0x86, PUFCC_ECDSA256 = 0x82 }; + +// PUFcc SP38a modes +enum pufcc_sp38a_mode { + PUFCC_ECB_CLR, + PUFCC_CFB, + PUFCC_OFB, + PUFCC_CBC_CLR, + PUFCC_CBC_CTS1, + PUFCC_CBC_CTS2, + PUFCC_CBC_CTS3, + PUFCC_CTR32, + PUFCC_CTR64, + PUFCC_CTR128 +}; + +// Scatter gather DMA descriptor struct +struct pufcc_sg_dma_desc { + uint32_t read_addr; + uint32_t write_addr; + uint32_t length; + uint32_t next; + uint32_t dsc_cfg_4; + uint32_t key_cfg; + uint32_t cypt_cfg[2]; +}; + +/***************************************************************************** + * Register structures + ****************************************************************************/ +// General register structs +struct pufcc_intrpt_reg { + uint32_t intrpt_st : 1; + uint32_t reserved1 : 15; + uint32_t intrpt_en : 1; + uint32_t reserved2 : 15; +}; + +struct pufcc_start_reg { + uint32_t start_p : 1; + uint32_t reserved : 31; +}; + +// DMA register structs +struct pufcc_dma_cfg_0_reg { + uint32_t rng_en : 1; + uint32_t sg_en : 1; + uint32_t reserved : 30; +}; + +struct pufcc_dma_cfg_1_reg { + uint8_t rbst_max; + uint8_t wbst_max; + uint8_t rbst_min; + uint8_t wbst_min; +}; + +struct pufcc_dma_dsc_cfg_4_reg { + uint32_t wprot : 8; + uint32_t rprot : 8; + uint32_t fw : 1; + uint32_t fr : 1; + uint32_t reserved : 5; + uint32_t no_cypt : 1; + uint32_t offset : 4; + uint32_t dn_pause : 1; + uint32_t dn_intrpt : 1; + uint32_t tail : 1; + uint32_t head : 1; +}; + +struct pufcc_dma_key_cfg0_reg { + uint32_t key_src : 4; + uint32_t key_dst : 4; + uint32_t key_size : 11; + uint32_t reserved1 : 5; + uint32_t key_idx : 5; + uint32_t reserved2 : 3; +}; + +// HMAC register structs +struct pufcc_hmac_config_reg { + uint32_t variant : 4; + uint32_t reserved : 4; + uint32_t function : 1; + uint32_t reserved2 : 23; +}; + +// PUFcc SP38a register structs +struct pufcc_sp38a_config_reg { + uint32_t variant : 2; + uint32_t reserved1 : 2; + uint32_t mode : 4; + uint32_t enc_dec : 1; + uint32_t reserved2 : 23; +}; + +// PKC register register structs +struct pufcc_pkc_ecp_ec_reg { + uint32_t reserved1 : 8; + uint32_t field : 8; // PKC scheme + uint32_t h : 4; // EC cofactor h + uint32_t reserved2 : 12; +}; + +// ECC parameters structure +struct pufcc_ecc_param { + const void *prime; // Field modulus + const void *a; // EC parameter a + const void *b; // EC parameter b + const void *px; // x-coordinate of base point P + const void *py; // y-coordinate of base point P + const void *order; // Subgroup order +}; + +/***************************************************************************** + * PUFcc register maps + ****************************************************************************/ +// OTP memory map +struct pufcc_otp_mem { + uint32_t otp[256]; +}; + +struct pufcc_rt_regs { + volatile uint32_t pif[64]; + uint32_t _pad1[64]; + volatile uint32_t ptr[16]; + volatile uint32_t ptc[16]; + volatile uint32_t ptm[2]; + uint32_t _pad2[6]; + volatile uint32_t rn; + volatile uint32_t rn_status; + volatile uint32_t healthcfg; + volatile uint32_t feature; + volatile uint32_t interrupt; + volatile uint32_t otp_psmsk[2]; + volatile uint32_t puf_psmsk; + volatile uint32_t version; + volatile uint32_t status; + volatile uint32_t cfg; + volatile uint32_t set_pin; + volatile uint32_t auto_repair; + volatile uint32_t ini_off_chk; + volatile uint32_t repair_pgn; + volatile uint32_t repair_reg; + volatile uint32_t puf_qty_chk; + volatile uint32_t puf_enroll; + volatile uint32_t puf_zeroize; + volatile uint32_t set_flag; + volatile uint32_t otp_zeroize; + uint32_t _pad3[3]; + volatile uint32_t puf[64]; + volatile uint32_t otp[256]; +}; + +// DMA module register map +struct pufcc_dma_regs { + volatile uint32_t version; + volatile uint32_t interrupt; + volatile uint32_t feature; + uint32_t _pad1; + volatile uint32_t status_0; + volatile uint32_t status_1; + uint32_t _pad2[2]; + volatile uint32_t start; + volatile uint32_t cfg_0; + volatile uint32_t cfg_1; + uint32_t _pad3[2]; + volatile uint32_t dsc_cfg_0; + volatile uint32_t dsc_cfg_1; + volatile uint32_t dsc_cfg_2; + volatile uint32_t dsc_cfg_3; + volatile uint32_t dsc_cfg_4; + uint32_t _pad4[2]; + volatile uint32_t dsc_cur_0; + volatile uint32_t dsc_cur_1; + volatile uint32_t dsc_cur_2; + volatile uint32_t dsc_cur_3; + volatile uint32_t dsc_cur_4; + uint32_t _pad5[2]; + volatile uint32_t key_cfg_0; + volatile uint32_t cl_cfg_0; +}; + +// HMAC module register map +struct pufcc_hmac_regs { + volatile uint32_t version; + volatile uint32_t interrupt; + volatile uint32_t feature; + uint32_t _pad1; + volatile uint32_t status; + uint32_t _pad2; + volatile uint32_t cfg; + uint32_t _pad3; + volatile uint32_t plen; + uint32_t _pad4[3]; + volatile uint32_t alen; + uint32_t _pad5[3]; + volatile uint8_t sw_key[PUFCC_HMAC_SW_KEY_MAXLEN]; +}; + +// Crypto module register map +struct pufcc_crypto_regs { + volatile uint32_t version; + volatile uint32_t interrupt; + volatile uint32_t feature; + uint32_t _pad1[5]; + volatile uint32_t iv_out[PUFCC_CRYPTO_IV_MAXLEN / PUFCC_WORD_SIZE]; + volatile uint32_t iv[PUFCC_CRYPTO_IV_MAXLEN / PUFCC_WORD_SIZE]; + volatile uint32_t sw_key[PUFCC_CRYPTO_SW_KEY_MAXLEN / PUFCC_WORD_SIZE]; + volatile uint32_t dgst_in[PUFCC_CRYPTO_DGST_LEN / PUFCC_WORD_SIZE]; + volatile uint32_t dgst_out[PUFCC_CRYPTO_DGST_LEN / PUFCC_WORD_SIZE]; +}; + +// SP38a module register map +struct pufcc_sp38a_regs { + volatile uint32_t version; + volatile uint32_t interrupt; + volatile uint32_t feature; + uint32_t _pad1; + volatile uint32_t status; + uint32_t _pad2; + volatile uint32_t cfg; +}; + +// PKC module register map +struct pufcc_pkc_regs { + volatile uint32_t version; + volatile uint32_t interrupt; + volatile uint32_t start; + volatile uint32_t status; + volatile uint32_t ecp_err_code; + volatile uint32_t ecp_err_pc; + volatile uint32_t ecp_err_cmd; + volatile uint32_t mp_version; + volatile uint32_t _pad1[56]; + volatile uint32_t ecp_ec; + volatile uint32_t ecp_keysel; + volatile uint32_t ecp_otpkba; + volatile uint32_t ecp_key_usage; + volatile uint32_t ecp_e_short; + volatile uint32_t _pad2[55]; + volatile uint32_t ecp_mac[4]; + volatile uint32_t ecp_data[512]; +}; + +#if !CONFIG_RS_RTOS_PORT + struct pufcc_dma_dev { + struct pufcc_dma_regs *regs; + bool is_dev_free; + struct pufcc_sg_dma_desc *dma_descs; + uint32_t num_descriptors; + void *callback_args; + rs_dma_callback_t callback; + }; +#endif + +#if CONFIG_RS_RTOS_PORT + + /** + * @enum rs_crypto_tfr_type + * @brief Types of secure transfer type in case of peripherals + */ + enum rs_crypto_tfr_type { + RS_SECURE_TX, // Write to peripheral + RS_SECURE_RX // Read from peripheral + }; + + /** + * @struct rs_crypto_addr + * @brief Address info for cryptographic operations + */ + struct rs_crypto_addr { + uint32_t read_addr; + uint32_t write_addr; + uint32_t len; + enum rs_crypto_tfr_type tfr_type; // Transfer type (read or write) in case of + // peripherals, otherwise don't care + bool periph_rw; // Indicates if data transfer involves a peripheral + struct rs_crypto_addr *next; // In case data lies at multiple locations + }; + + /* + The following macro can be used to write register values. + REG_WRITE_32(Destination_Addr, Source_Addr) + */ + #define REG_WRITE_32(Destination_Addr, Source_Addr) \ + *(uint32_t *)Destination_Addr = *(uint32_t *)Source_Addr; + + /** + * @brief SHA lengths + */ + #define RS_SHA_MAX_LEN 64 + #define RS_SHA256_LEN 32 + + /** + * @brief ECDSA256 quadrant and key lengths + */ + #define RS_EC256_QLEN 32 + #define RS_EC256_KEY_LEN (32 * 2) + + /** + * @brief RSA 2048 public key modulus length + * + */ + #define RS_RSA_2048_LEN 256 + + /** + * @brief RSA 2048 public key exponent length + */ + #define RS_RSA_E_LEN 4 + + /** + * @brief RSA 2048 public key length + */ + #define RS_RSA_2048_KEY_LEN (RS_RSA_2048_LEN + RS_RSA_E_LEN) + + /** + * @brief IV length for AES-CTR128 + */ + #define RS_AES_CTR128_IV_EN 16 + + /** + * @brief Key length for AES128 + */ + #define RS_AES16_KEY_LEN 16 + + /** + * @brief Key length for AES256 + */ + #define RS_AES32_KEY_LEN 32 + + enum rs_status { + OK = 0, + WOULD_BLOCK = 1, + ERROR = 2 + }; + + /** + * @struct rs_crypto_rsa2048_puk + * @brief RSA 2048 public key structure + */ + struct rs_crypto_rsa2048_puk { + uint8_t n[RS_RSA_2048_LEN]; // Modulus + uint32_t e; // Exponent + }; + + /** + * @struct rs_crypto_ec256_puk + * @brief ECDSA256 public key + */ + struct rs_crypto_ec256_puk { + uint8_t x[RS_EC256_QLEN]; + uint8_t y[RS_EC256_QLEN]; + }; + + /** + * @struct rs_crypto_ec256_sig + * @brief ECDSA256 signature + */ + struct rs_crypto_ec256_sig { + uint8_t r[RS_EC256_QLEN]; + uint8_t s[RS_EC256_QLEN]; + }; + + /** + * @struct rs_crypto_hash + * @brief Hash structure + */ + struct rs_crypto_hash { + uint8_t val[RS_SHA_MAX_LEN]; + uint32_t len; + }; + +#endif + +/***************************************************************************** + * API declarations + ****************************************************************************/ +enum pufcc_status pufcc_calc_sha256_hash(struct rs_crypto_addr *data_addr, + struct rs_crypto_hash *hash); + +enum pufcc_status pufcc_calc_sha256_hash_sg(struct rs_crypto_addr *data_addr, + bool first, bool last, + uint32_t *prev_len, + struct rs_crypto_hash *hash_in, + struct rs_crypto_hash *hash_out); + +enum pufcc_status pufcc_decrypt_aes(uint32_t out_addr, uint32_t in_addr, + uint32_t in_len, uint32_t prev_len, + enum pufcc_key_type key_type, + uint32_t key_addr, uint32_t key_len, + uint32_t iv_addr, uint32_t iv_len, + enum pufcc_dma_rw_type write_type, + bool readback_iv); + +enum pufcc_status pufcc_rsa2048_sign_verify( + uint8_t *sig, struct rs_crypto_addr *msg_addr, + struct rs_crypto_rsa2048_puk *pub_key); + +enum pufcc_status pufcc_ecdsa256_sign_verify( + struct rs_crypto_ec256_sig *sig, struct rs_crypto_addr *msg_addr, + struct rs_crypto_ec256_puk *pub_key); + +#if CONFIG_RS_RTOS_PORT + bool pufcc_get_asynch_ops_flag(void); + void pufcc_set_asynch_ops_flag(bool Val); +#else + enum pufcc_status pufcc_dma_transfer(uint32_t src_addr, uint32_t dest_addr, + uint32_t len, bool fixed_read, + bool fixed_write); +#endif + +enum pufcc_status pufcc_otp_setup_wait(void); + +enum pufcc_status pufcc_program_otp(const uint8_t *in_buf, uint32_t len, + enum pufcc_otp_slot otp_slot); + +enum pufcc_status pufcc_read_otp(uint8_t *out_buf, uint32_t len, + enum pufcc_otp_slot otp_slot); + +enum pufcc_status pufcc_lock_otp(enum pufcc_otp_slot otp_slot, uint32_t len, + enum pufcc_otp_lock lock); + +enum pufcc_status pufcc_zeroize_otp(enum pufcc_otp_slot otp_slot); + +enum pufcc_status pufcc_get_otp_rwlck(enum pufcc_otp_slot otp_slot, + enum pufcc_otp_lock *lock_val); + +#if CONFIG_RS_RTOS_PORT + int pufcc_clear_and_disable_intr(void); +#else + int pufcc_dma_request_channel(struct pufcc_dma_dev *dev); + + void pufcc_dma_release_channel(struct pufcc_dma_dev *dev, int channel); + + enum rs_status pufcc_dma_config_descriptor_memory(struct pufcc_dma_dev *dev, + int channel, uintptr_t addr, + size_t max_descriptors); + + enum rs_status pufcc_dma_config_xfer(struct pufcc_dma_dev *dev, int channel, + struct rs_dma_config *config); + + enum rs_status pufcc_dma_start_xfer(struct pufcc_dma_dev *dev, int channel); + + enum rs_status pufcc_dma_stop_xfer(struct pufcc_dma_dev *dev, int channel); + + void pufcc_dma_irq_handler(struct pufcc_dma_dev *dev); +#endif + +enum pufcc_status pufcc_init(uint32_t base_addr); + +#endif // _PUFCC_H_ diff --git a/dts/bindings/crypto/pufsecurity,otp.yaml b/dts/bindings/crypto/pufsecurity,otp.yaml new file mode 100644 index 0000000000000..5c139483a2b4d --- /dev/null +++ b/dts/bindings/crypto/pufsecurity,otp.yaml @@ -0,0 +1,10 @@ +# Copyright (c) 2024, Rapid Silicon +# SPDX-License-Identifier: Apache-2.0 + +description: | + PUF security IP PUFcc also contains the one time programmable + memory region. That region can be accessed using this driver. + +compatible: "pufsecurity,otp" + +include: [base.yaml] diff --git a/dts/bindings/syscon/rapidsi,scu.yaml b/dts/bindings/syscon/rapidsi,scu.yaml new file mode 100644 index 0000000000000..697db9d5aed4e --- /dev/null +++ b/dts/bindings/syscon/rapidsi,scu.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Rapid Silicon +# SPDX-License-Identifier: Apache-2.0 + +description: System Controller Registers R/W + +compatible: "rapidsi,scu" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/riscv/rapidsilicon/rapidsi_virgo.dtsi b/dts/riscv/rapidsilicon/rapidsi_virgo.dtsi index 1dd6b4ea998b9..061e0d86f3ea1 100644 --- a/dts/riscv/rapidsilicon/rapidsi_virgo.dtsi +++ b/dts/riscv/rapidsilicon/rapidsi_virgo.dtsi @@ -181,12 +181,18 @@ status = "disabled"; }; - pufcc: pufcc@A0130000 { + pufs: pufcc@A0130000 { compatible = "pufsecurity,pufcc"; reg = <0xA0130000 DT_SIZE_K(64)>; interrupts = <33 3>; interrupt-parent = < &eclic >; - status = "disabled"; + status = "disabled"; + + pufs_otp: pufcc_otp { + compatible = "pufsecurity,otp"; + status = "disabled"; + }; + }; fpga_cfg: cfg-ctrl@A0710000 { diff --git a/include/zephyr/crypto/cipher.h b/include/zephyr/crypto/cipher.h index 71d8e590b41be..f022f1bae4229 100644 --- a/include/zephyr/crypto/cipher.h +++ b/include/zephyr/crypto/cipher.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. + * 2024 Rapid Silicon. * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +25,13 @@ * @{ */ +/** + * Encryption Key Source + */ +enum cipher_key_source { + CRYPTO_KEY_SW = 0, + CRYPTO_KEY_OTP = 1 +}; /** Cipher Algorithm */ enum cipher_algo { @@ -90,10 +98,23 @@ struct ccm_params { }; struct ctr_params { + /* + This is a pointer to the IV (initialization vector) + provided as input to the counter mode cipher API. + */ + uint8_t *iv; /* CTR mode counter is a split counter composed of iv and counter * such that ivlen + ctr_len = keylen */ uint32_t ctr_len; + + /** + * Check whether we want to readback the ctr (iv) + * for the cases where we might be doing chunk wise + * decryption and each chunk could be encrypted with + * a separate IV for strengthening the security. + */ + bool readback_ctr; }; struct gcm_params { @@ -125,6 +146,12 @@ struct cipher_ctx { void *handle; } key; + /* + * This indicates if the encryption key will be provided by + * software or it has to be fetched from secure (OTP) memory. + */ + enum cipher_key_source key_source; + /** The device driver instance this crypto context relates to. Will be * populated by the begin_session() API. */ @@ -191,6 +218,11 @@ struct cipher_pkt { */ uint8_t *out_buf; + /** + * Should the destination address be auto incrementing + */ + bool auto_increment; + /** Size of the out_buf area allocated by the application. Drivers * should not write past the size of output buffer. */ @@ -201,6 +233,12 @@ struct cipher_pkt { */ int out_len; + /** + * Bytes previously operated upon. This information is useful + * if the decryption is performed in chunks. + * */ + uint32_t prev_len; + /** Context this packet relates to. This can be useful to get the * session details, especially for async ops. Will be populated by the * cipher_xxx_op() API based on the ctx parameter. diff --git a/include/zephyr/crypto/crypto.h b/include/zephyr/crypto/crypto.h index b2e0b0f6e4439..163f5a9c3d664 100644 --- a/include/zephyr/crypto/crypto.h +++ b/include/zephyr/crypto/crypto.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. + * 2024 Rapid Silicon. * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +23,7 @@ #include #include #include +#include #include "cipher.h" /** @@ -40,14 +42,14 @@ * supported config during the session setup. */ #define CAP_OPAQUE_KEY_HNDL BIT(0) -#define CAP_RAW_KEY BIT(1) +#define CAP_RAW_KEY BIT(1) /* TBD to define */ #define CAP_KEY_LOADING_API BIT(2) /** Whether the output is placed in separate buffer or not */ #define CAP_INPLACE_OPS BIT(3) -#define CAP_SEPARATE_IO_BUFS BIT(4) +#define CAP_SEPARATE_IO_BUFS BIT(4) /** * These denotes if the output (completion of a cipher_xxx_op) is conveyed @@ -62,6 +64,18 @@ /** Don't prefix IV to cipher blocks */ #define CAP_NO_IV_PREFIX BIT(8) +/** Whether the driver supports encryption or not */ +#define CAP_NO_ENCRYPTION BIT(9) + +/** Whether the driver supports decryption or not */ +#define CAP_NO_DECRYPTION BIT(10) + +/** Whether the driver supports signing or not */ +#define CAP_NO_SIGNING BIT(11) + +/** Whether the driver supports sign verification or not */ +#define CAP_NO_SIGN_VERIFY BIT(12) + /* More flags to be added as necessary */ /** @brief Crypto driver API definition. */ @@ -88,6 +102,15 @@ __subsystem struct crypto_driver_api { /* Register async hash op completion callback with the driver */ int (*hash_async_callback_set)(const struct device *dev, hash_completion_cb cb); + + /* Setup a signature session */ + int (*sign_begin_session)(const struct device *dev, struct sign_ctx *ctx, + enum sign_algo algo); + /* Tear down an established signature session */ + int (*sign_free_session)(const struct device *dev, struct sign_ctx *ctx); + /* Register async signature op completion callback with the driver */ + int (*sign_async_callback_set)(const struct device *dev, + sign_completion_cb cb); }; /* Following are the public API a user app may call. @@ -302,7 +325,6 @@ static inline int cipher_ctr_op(struct cipher_ctx *ctx, { __ASSERT(ctx->ops.cipher_mode == CRYPTO_CIPHER_MODE_CTR, "CTR mode " "session invoking a different mode handler"); - pkt->ctx = ctx; return ctx->ops.ctr_crypt_hndlr(ctx, pkt, iv); } @@ -456,7 +478,7 @@ static inline int hash_callback_set(const struct device *dev, } /** - * @brief Perform a cryptographic hash function. + * @brief Perform a cryptographic hash function. * * @param ctx Pointer to the hash context of this op. * @param pkt Structure holding the input/output. @@ -471,7 +493,7 @@ static inline int hash_compute(struct hash_ctx *ctx, struct hash_pkt *pkt) } /** - * @brief Perform a cryptographic multipart hash operation. + * @brief Perform a cryptographic multipart hash operation. * * This function can be called zero or more times, passing a slice of the * the data. The hash is calculated using all the given pieces. @@ -493,4 +515,123 @@ static inline int hash_update(struct hash_ctx *ctx, struct hash_pkt *pkt) * @} */ +/** + * @brief Setup a signing / sign_verification session + * + * Initializes one time parameters, like the algorithm which may + * remain constant for all operations in the session. The state may be + * cached in hardware and/or driver data state variables. + * + * @param dev Pointer to the device structure for the driver instance. + * @param ctx Pointer to the context structure. Various one time + * parameters like session capabilities and algorithm are + * supplied via this structure. The structure documentation + * specifies which fields are to be populated by the app + * before making this call. + * @param algo The algorithm to be used in this session. e.g RSA2048 or ECDSA256 + * + * @return 0 on success, negative errno code on fail. + */ +static inline int sign_begin_session(const struct device *dev, + struct sign_ctx *ctx, + enum sign_algo algo) +{ + uint32_t flags; + struct crypto_driver_api *api; + + api = (struct crypto_driver_api *) dev->api; + ctx->device = dev; + + flags = (ctx->flags & (CAP_INPLACE_OPS | CAP_SEPARATE_IO_BUFS)); + __ASSERT(flags != 0U, "IO buffer type missing"); + __ASSERT(flags != (CAP_INPLACE_OPS | CAP_SEPARATE_IO_BUFS), + "conflicting options for IO buffer type"); + + flags = (ctx->flags & (CAP_SYNC_OPS | CAP_ASYNC_OPS)); + __ASSERT(flags != 0U, "sync/async type missing"); + __ASSERT(flags != (CAP_SYNC_OPS | CAP_ASYNC_OPS), + "conflicting options for sync/async"); + + + return api->sign_begin_session(dev, ctx, algo); +} + +/** + * @brief Cleanup a signing / sign_verification session + * + * Clears the hardware and/or driver state of a session. @see sign_begin_session + * + * @param dev Pointer to the device structure for the driver instance. + * @param ctx Pointer to the crypto signing / sign_verification context structure of the session + * to be freed. + * + * @return 0 on success, negative errno code on fail. + */ +static inline int sign_free_session(const struct device *dev, + struct sign_ctx *ctx) +{ + struct crypto_driver_api *api; + + api = (struct crypto_driver_api *) dev->api; + + return api->sign_free_session(dev, ctx); +} + +/** + * @brief Registers an async signing / sign_verification completion callback with the driver + * + * The application can register an async signing / sign_verification completion callback + * handler to be invoked by the driver, on completion of a prior request submitted via + * sign_op_handler. Based on crypto device hardware semantics, this is likely to + * be invoked from an ISR context. + * + * @param dev Pointer to the device structure for the driver instance. + * @param cb Pointer to application callback to be called by the driver. + * + * @return 0 on success, -ENOTSUP if the driver does not support async op, + * negative errno code on other error. + */ +static inline int sign_callback_set(const struct device *dev, + sign_completion_cb cb) +{ + struct crypto_driver_api *api; + + api = (struct crypto_driver_api *) dev->api; + + if (api->sign_async_callback_set) { + return api->sign_async_callback_set(dev, cb); + } + + return -ENOTSUP; +} + +/** + * @brief Perform a cryptographic signing / verification operation. + * + * @param ctx Pointer to the sign context of this op. + * @param pkt Structure holding the input. + * @return 0 on success, negative errno code on fail. + */ +static inline int sign_op_handler(struct sign_ctx *ctx, struct sign_pkt *pkt) +{ + pkt->ctx = ctx; + + if(ctx->ops.signing_algo == CRYPTO_SIGN_ALGO_RSA2048) { + pkt->ctx = ctx; + if(ctx->ops.rsa_crypt_hndlr == NULL) { + return -EBADFD; + } + return ctx->ops.rsa_crypt_hndlr(ctx, pkt); + } + else if(ctx->ops.signing_algo == CRYPTO_SIGN_ALGO_ECDSA256) { + if(ctx->ops.ecdsa_crypt_hndlr == NULL) { + return -EBADFD; + } + return ctx->ops.ecdsa_crypt_hndlr(ctx, pkt); + } + + return -ENOTSUP; + +} + #endif /* ZEPHYR_INCLUDE_CRYPTO_H_ */ diff --git a/include/zephyr/crypto/crypto_otp_mem.h b/include/zephyr/crypto/crypto_otp_mem.h new file mode 100644 index 0000000000000..13a806014c6b0 --- /dev/null +++ b/include/zephyr/crypto/crypto_otp_mem.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2024 Rapid Silicon. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Crypto Engine's OTP (One Time Programmable) Memory APIs. + * + * + * This file contains the Crypto Engine's OTP memory APIs + * for reading, writing, zeroizing and locking the OTP + * memory contents. + * + * [Experimental] Users should note that the APIs can change + * as a part of ongoing development. + */ + +#ifndef ZEPHYR_INCLUDE_CRYPTO_OTP_MEM_H_ +#define ZEPHYR_INCLUDE_CRYPTO_OTP_MEM_H_ + +#include +#include +#include +#include +#include +#include + +/** + * @brief Crypto OTP Mem APIs + * @defgroup crypto OTP Mem + * @since 1.7 + * @version 1.0.0 + * @ingroup os_services + * @{ + */ + +/* ctx.flags values. Not all drivers support all flags. + * A user app can query the supported hw / driver + * capabilities via provided API (crypto_query_hwcaps()), and choose a + * supported config during the session setup. + */ +#define CAP_READ_OTP BIT(0) +#define CAP_WRITE_OTP BIT(1) + +#define CAP_LOCK_OTP BIT(2) + +/** Whether to permanently zeroiz the OTP */ +#define CAP_ZEROIZ_OTP BIT(3) + +/** + * These denotes if the output is conveyed + * by the op function returning, or it is conveyed by an async notification + */ +#define CAP_SYNC_OPS BIT(5) +#define CAP_ASYNC_OPS BIT(6) + +/* More flags to be added as necessary */ + +// OTP lock types +enum crypto_otp_lock { + CRYPTO_OTP_RW = 0x0, // Read-Write + CRYPTO_OTP_RO = 0x3, // Read-Only + CRYPTO_OTP_NA = 0xF, // No-Access +}; + +/** @brief Crypto OTP Memory driver API definition. */ +__subsystem struct otp_driver_api { + /* Get the driver capability flags for OTP Memory operations */ + int (*otp_hw_caps)(const struct device *dev); + + /** + * otp_info API returns the total number of slots + * and number of bytes per slot. + */ + int (*otp_info)( + const struct device *dev, + uint16_t *totalSlots, + uint16_t *bytesPerSlot + ); + + /** + * otp_read API returns the number of bytes + * from the selected OTP Slot. Use otp_info + * to get total number of slots and bytes per slot. + */ + int (*otp_read)( + const struct device *dev, + uint16_t otp_slot, + uint8_t *data, + uint32_t len + ); + + /** + * otp_write API writes the number of bytes + * to the selected OTP Slot. Use otp_info + * to get total number of slots and bytes per slot. + */ + int (*otp_write)( + const struct device *dev, + uint16_t otp_slot, + uint8_t *data, + uint32_t len + ); + + /** + * otp_zeroize API zeroize the selected OTP Slot + * Permanently. Use otp_info to get total number + * of slots and bytes per slot. + */ + int (*otp_zeroize)( + const struct device *dev, + uint16_t otp_slot + ); + + /** + * otp_set_lock API locks the selected OTP slot as per + * the crypto_otp_lock. Use otp_info to get total + * number of slots and bytes per slot. + */ + int (*otp_set_lock)( + const struct device *dev, + uint16_t otp_slot, + uint16_t len, + enum crypto_otp_lock lock + ); + + /** + * otp_get_lock API gets the selected OTP Slots's + * lock status. + */ + int (*otp_get_lock)( + const struct device *dev, + uint16_t otp_slot, + enum crypto_otp_lock *lock + ); +}; + +/* Following are the public API a user app may call. */ + +/** + * @brief Query the crypto otp driver capabilities + * + * This API is used by the app to query the capabilities supported by the + * crypto otp memory driver. Based on this the app can specify a subset of + * the supported options to be honored for a session during cipher_begin_session(). + * + * @param dev Pointer to the device structure for the driver instance. + * + * @return bitmask of supported options. + */ + +static inline int otp_query_hw_aps(const struct device *dev) +{ + struct otp_driver_api *api; + int tmp; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_hw_caps == NULL) { + return -ENOSYS; + } + + tmp = api->otp_hw_caps(dev); + + __ASSERT((tmp & (CAP_READ_OTP | CAP_WRITE_OTP)) != 0, + "Driver should support at least Read or Write to the OTP Memory"); + + __ASSERT((tmp & (CAP_SYNC_OPS | CAP_ASYNC_OPS)) != 0, + "Driver should support at least Synch or Asynch operation"); + + return tmp; + +} + +/** + * @brief Query the crypto otp information. + * + * This API is used by the app to query the otp memory information. + * It provides the total number of slots available in the otp and the + * number of bytes per slot. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * @param[out] totalSlots total number of available otp slots. + * @param[out] bytesPerSlot number of bytes per slot. + * + * @return error code. + */ +static inline int otp_info( + const struct device *dev, + uint16_t *totalSlots, + uint16_t *bytesPerSlot + ) +{ + struct otp_driver_api *api; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_info == NULL) { + return -ENOSYS; + } + + return api->otp_info(dev, totalSlots, bytesPerSlot); +} + +/** + * @brief Read the crypto otp slot + * + * This API is used to read a certain number of bytes from an otp slot. + * + * @param dev Pointer to the device structure for the driver instance. + * @param[in] otp_slot the slot number of the otp to read from. + * @param[out] data The bytes returned. + * @param[in] len The number of bytes to read. + * + * @return error code. + */ +static inline int otp_read( + const struct device *dev, + uint16_t otp_slot, + uint8_t *data, + uint32_t len + ) +{ + struct otp_driver_api *api; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_read == NULL) { + return -ENOSYS; + } + + return api->otp_read(dev, otp_slot, data, len); +} + +/** + * @brief Write to the crypto otp slot + * + * This API is used to write a certain number of bytes to an otp slot. + * + * @param dev Pointer to the device structure for the driver instance. + * @param[in] otp_slot the slot number of the otp to write to. + * @param[out] data The bytes written to the selected otp slot. + * @param[in] len The number of bytes to read. + * + * @return error code. + */ +static inline int otp_write( + const struct device *dev, + uint16_t otp_slot, + uint8_t *data, + uint32_t len + ) +{ + struct otp_driver_api *api; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_write == NULL) { + return -ENOSYS; + } + + return api->otp_write(dev, otp_slot, data, len); +} + +/** + * @brief Zeroize the crypto otp slot + * + * This API is used to zeroize a an otp slot. + * + * @param dev Pointer to the device structure for the driver instance. + * @param[in] otp_slot the slot number to zeroize. + * + * @return error code. + */ +static inline int otp_zeoirze( + const struct device *dev, + uint16_t otp_slot + ) +{ + struct otp_driver_api *api; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_zeroize == NULL) { + return -ENOSYS; + } + + return api->otp_zeroize(dev, otp_slot); +} + +/** + * @brief Set the crypto otp slot a particular lock value. The lock + * value can be referenced from crypto_otp_lock enumeration. + * + * This API is used to set a lock value to an otp slot. + * + * @param dev Pointer to the device structure for the driver instance. + * @param[in] otp_slot the slot number to lock. + * @param[in] lock The lock value to assign to an otp slot. + * + * @return error code. + */ +static inline int otp_set_lock( + const struct device *dev, + uint16_t otp_slot, + uint16_t len, + enum crypto_otp_lock lock + ) +{ + struct otp_driver_api *api; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_set_lock == NULL) { + return -ENOSYS; + } + + return api->otp_set_lock(dev, otp_slot, len, lock); +} + +/** + * @brief Get the lock value of a particular crypto otp slot. The lock + * value can be referenced from crypto_otp_lock enumeration. + * + * This API is used to get a lock value of an otp slot. + * + * @param dev Pointer to the device structure for the driver instance. + * @param[in] otp_slot the slot number to lock. + * @param[out] lock The current lock value of an otp slot. + * + * @return error code. + */ +static inline int otp_get_lock( + const struct device *dev, + uint16_t otp_slot, + enum crypto_otp_lock *lock + ) +{ + struct otp_driver_api *api; + + api = (struct otp_driver_api *) dev->api; + + if (api->otp_get_lock == NULL) { + return -ENOSYS; + } + + return api->otp_get_lock(dev, otp_slot, lock); +} + +#endif /* ZEPHYR_INCLUDE_CRYPTO_OTP_MEM_H_ */ diff --git a/include/zephyr/crypto/hash.h b/include/zephyr/crypto/hash.h index c2f548406c86f..b0a2da0c71447 100644 --- a/include/zephyr/crypto/hash.h +++ b/include/zephyr/crypto/hash.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Intel Corporation. + * 2024 Rapid Silicon. * * SPDX-License-Identifier: Apache-2.0 */ @@ -83,7 +84,8 @@ struct hash_ctx { * operation. * * The fields which has not been explicitly called out has to - * be filled up by the app before calling hash_compute(). + * be filled up by the app before calling hash_compute() or + * hash_update(). */ struct hash_pkt { @@ -93,16 +95,69 @@ struct hash_pkt { /** Bytes to be operated upon */ size_t in_len; + /** Start address of previously calculated hash / digest. + * It is useful where hash is calculated in chunks. + * This will be filled only once in the very first + * element of struct hash_pkt type linkedlist. + */ + uint8_t *in_hash; + /** + * Length of previously calculated hash + * This will be filled only once in the very first + * element of struct hash_pkt type linkedlist. + * */ + size_t in_hash_len; + + /** Bytes previously operated upon + * This will be filled only once in the very first + * element of struct hash_pkt type linkedlist. + */ + uint32_t *prev_len; + /** * Start of the output buffer, to be allocated by * the application. Can be NULL for in-place ops. To be populated * with contents by the driver on return from op / async callback. + * In case of a multipart hash calculation, the output hash + * shall be placed in the memory pointed by the out_buf pointer of + * the first element of the struct hash_pkt type linkedlist. */ uint8_t *out_buf; + /** Bytes in returned hash (out_buf) + * In case of a multipart hash calculation, the output hash + * shall be placed in the memory pointed by the out_buf pointer of + * the first element of the struct hash_pkt type linkedlist. + */ + size_t out_len; + + /** + * The pointer is for creating a linkedlist of + * incoming data in case the hash is calculated in chunks + * where data might be coming from different places. + */ + struct hash_pkt *next; + + /** + * Whether this linkedlist contains head or not. + * This boolean shall be initialized only once in + * the first element of every new linkedlist. + */ + bool head; + + /** + * Whether this linkedlist contains tail or not. + * This boolean shall be initialized only once in + * the first element of every new linkedlist. + */ + bool tail; + /** * Context this packet relates to. This can be useful to get the * session details, especially for async ops. + * In case of a multipart hash calculation, the output hash + * shall be placed in the memory pointed by the out_buf pointer of + * the first element of the struct hash_pkt type linkedlist. */ struct hash_ctx *ctx; }; diff --git a/include/zephyr/crypto/sign.h b/include/zephyr/crypto/sign.h new file mode 100644 index 0000000000000..33c5cacfe5da1 --- /dev/null +++ b/include/zephyr/crypto/sign.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2024 Rapid Silicon. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Crypto Signature APIs + * + * This file contains the Crypto Abstraction layer APIs. + */ +#ifndef ZEPHYR_INCLUDE_CRYPTO_SIGN_H_ +#define ZEPHYR_INCLUDE_CRYPTO_SIGN_H_ + + +/** + * @addtogroup crypto_sign + * @{ + */ + + +/** + * Signing algorithm + */ +enum sign_algo { + CRYPTO_SIGN_ALGO_RSA2048 = 0, + CRYPTO_SIGN_ALGO_ECDSA256 = 1 +}; + +/** + * Signing Mode + */ +enum sign_mode { + CRYPTO_SIGN_COMPUTE = 0, + CRYPTO_SIGN_VERIFY = 1 +}; + +/* Forward declarations */ +struct sign_ctx; +struct sign_pkt; + +/* Function signatures for sign verification using standard signing algorithms + * like RSA2048, ECDSA256. These will be filled up by the driver for later + * calls as per the algorithm type. + */ +typedef int (*rsa_op_t)(struct sign_ctx *ctx, struct sign_pkt *pkt); +typedef int (*ecdsa_op_t)(struct sign_ctx *ctx, struct sign_pkt *pkt); + +struct sign_ops { + + /* + The signing algorithm and mode shall be set by the User. + */ + enum sign_algo signing_algo; + enum sign_mode signing_mode; + + // This anonymous union members are to be set by the driver. + union { + rsa_op_t rsa_crypt_hndlr; + ecdsa_op_t ecdsa_crypt_hndlr; + }; +}; + +/** + * Structure encoding session parameters. + * + * Refer to comments for individual fields to know the contract + * in terms of who fills what and when w.r.t begin_session() call. + */ +struct sign_ctx { + + /** Place for driver to return function pointers to be invoked per + * sign operation. To be populated by crypto driver on return from + * begin_session() based on the algo/mode chosen by the app. + */ + struct sign_ops ops; + + /** + * To be populated by the app before calling begin_session() + * In case of ecdsa, the public key should have {x, y} + * coordinates respectively. In case of RSA2048, the public key + * should have the modulus and exponent {n, e} respectively. + * */ + const uint8_t *pub_key; + + /** + * To be populated by the app before calling begin_session() + * In case of ecdsa, the signature should be constituted of two + * integer arrays of {r, s} respectively. In case of RSA2048 the signature + * is a normal array of integer values. + */ + const uint8_t *sig; + + /** The device driver instance this crypto context relates to. Will be + * populated by the begin_session() API. + */ + const struct device *device; + + /** If the driver supports multiple simultaneously crypto sessions, this + * will identify the specific driver state this crypto session relates + * to. Since dynamic memory allocation is not possible, it is + * suggested that at build time drivers allocate space for the + * max simultaneous sessions they intend to support. To be populated + * by the driver on return from begin_session(). + */ + void *drv_sessn_state; + + /** Place for the user app to put info relevant stuff for resuming when + * completion callback happens for async ops. Totally managed by the + * app. + */ + void *app_sessn_state; + + /** Cryptographic keylength in bytes. To be populated by the app + * before calling begin_session() + */ + uint16_t pub_key_len; + + /** Signature length in bytes. To be populated by the app + * before calling begin_session() + */ + uint16_t sign_len; + + /** How certain fields are to be interpreted for this session. + * (A bitmask of CAP_* below.) + * To be populated by the app before calling begin_session(). + * An app can obtain the capability flags supported by a hw/driver + * by calling crypto_query_hwcaps(). + */ + uint16_t flags; +}; + +/** + * Structure encoding IO parameters of one cryptographic + * operation like encrypt/decrypt. + * + * The fields which has not been explicitly called out has to + * be filled up by the app before making the sign_xxx_op() + * call. + */ +struct sign_pkt { + + /** Start address of input buffer */ + const uint8_t *in_buf; + + /** Bytes to be operated upon */ + int in_len; + + /** Start of the output buffer, to be allocated by + * the application. Can be NULL for in-place ops. To be populated + * with contents by the driver on return from op / async callback. + */ + uint8_t *out_buf; + + /** Size of the out_buf area allocated by the application. Drivers + * should not write past the size of output buffer. + */ + int out_buf_max; + + /** To be populated by driver on return from sign_xxx_op() and + * holds the size of the actual result. + */ + int out_len; + + /** + * The pointer is for creating a linkedlist of + * incoming data in case the sign is calculated / verified + * in chunks where data might be coming from different places. + */ + struct sign_pkt *next; + + /** Context this packet relates to. This can be useful to get the + * session details, especially for async ops. Will be populated by the + * sign_xxx_op() API based on the ctx parameter. + */ + struct sign_ctx *ctx; +}; + +/* Prototype for the application function to be invoked by the crypto driver + * on completion of an async request. The app may get the session context + * via the pkt->ctx field. + */ +typedef void (*sign_completion_cb)(struct sign_pkt *completed, int status); + + +/** + * @} + */ +#endif /* ZEPHYR_INCLUDE_CRYPTO_SIGN_H_ */ diff --git a/samples/hello_world/src/main.c b/samples/hello_world/src/main.c index 071e84822a5c2..4977e19e9925a 100644 --- a/samples/hello_world/src/main.c +++ b/samples/hello_world/src/main.c @@ -9,217 +9,243 @@ #include #include #include +#include +#include + #include -#define ATTR_INF "\x1b[32;1m" // ANSI_COLOR_GREEN -#define ATTR_ERR "\x1b[31;1m" // ANSI_COLOR_RED -#define ATTR_RST "\x1b[37;1m" // ANSI_COLOR_RESET +#define ATTR_INF "\x1b[32;1m" // ANSI_COLOR_GREEN +#define ATTR_ERR "\x1b[31;1m" // ANSI_COLOR_RED +#define ATTR_RST "\x1b[37;1m" // ANSI_COLOR_RESET +#define ATTR_HIL "\x1b[33;1m" // ANSI_COLOR_HIGHLIGHT -#define FLASH_RW_SIZE 255 -#define FLASH_BASE_ADDR 0xB0000000 +#if (CONFIG_SPI_ANDES_ATCSPI200 && CONFIG_SPI_NOR) + #define FLASH_RW_SIZE 255 + #define FLASH_BASE_ADDR 0xB0000000 -void Flash_Test(const struct device *flash, const struct device *dma, uint32_t FLASH_ADDR, uint8_t EVEN_ODD_MUL, uint8_t FORMATTER) { - int errorcode = 0; - uint8_t flash_data_write[FLASH_RW_SIZE] = {0}; - uint8_t flash_data_read[FLASH_RW_SIZE] = {0}; - errorcode = flash_read(flash, FLASH_ADDR, flash_data_read, FLASH_RW_SIZE); - if(errorcode < 0) { - printf("%s Error reading from flash with code:%d%s\n", ATTR_ERR, errorcode,ATTR_RST); - } - else { - printf("%s Reading Back Before Erasing Flash%s\n", ATTR_INF,ATTR_RST); - // for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - // printf("%s %d%s", ATTR_INF, flash_data_read[i],i%FORMATTER==0?"\n":""); - // } printf("\n"); - } - errorcode = flash_erase(flash, FLASH_ADDR, 0x1000); - if(errorcode < 0) { - printf("%s\nError Erasing the flash at 0x%08x offset errorcode:%d%s\n", ATTR_ERR, FLASH_ADDR, errorcode, ATTR_RST); - } else { - printf("%s\nSuccessfully Erased Flash\n", ATTR_RST); + void Flash_Test(const struct device *flash, const struct device *dma, uint32_t FLASH_ADDR, + uint8_t EVEN_ODD_MUL, uint8_t FORMATTER) + { + int errorcode = 0; + uint8_t flash_data_write[FLASH_RW_SIZE] = {0}; + uint8_t flash_data_read[FLASH_RW_SIZE] = {0}; errorcode = flash_read(flash, FLASH_ADDR, flash_data_read, FLASH_RW_SIZE); - if(errorcode < 0) { - printf("%s Error reading from flash with code:%d%s\n", ATTR_ERR, errorcode,ATTR_RST); + if (errorcode < 0) { + printf("%s Error reading from flash with code:%d%s\n", ATTR_ERR, errorcode, + ATTR_RST); } else { - printf("%s Reading Back After Erasing Area of Flash%s\n", ATTR_INF,ATTR_RST); - for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - if(flash_data_read[i] != 0xff) { - errorcode = -1; - } - } - } - if(errorcode == -1) { - printf("%s\nFlash erase at 0x%08x did not produce correct results%s\n", ATTR_ERR, FLASH_ADDR,ATTR_RST); + printf("%s Reading Back Before Erasing Flash%s\n", ATTR_INF, ATTR_RST); // for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - // printf("%s 0x%02x%s", ATTR_INF, flash_data_read[i],i%FORMATTER==0?"\n":""); + // printf("%s %d%s", ATTR_INF, flash_data_read[i],i%FORMATTER==0?"\n":""); // } printf("\n"); - } else { - printf("%s\nSuccessfully performed erase to flash with code:%d%s\n", ATTR_INF, errorcode,ATTR_RST); } - errorcode = 0; - } - - if(errorcode == 0) { - printf("%s Writing the following data After Erasing Flash%s\n", ATTR_INF,ATTR_RST); - for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - flash_data_write[i] = ((rand() % (FLASH_RW_SIZE - 1 + 1)) + 1)+((rand() % (FLASH_RW_SIZE - 1 + 1)) + 1); - printf("%s %d%s", ATTR_INF, flash_data_write[i],i%FORMATTER==0?"\n":""); - } - printf("\n"); - errorcode = flash_write(flash, FLASH_ADDR, flash_data_write, FLASH_RW_SIZE); - } - - if(errorcode < 0) { - printf("%s \nError writing to flash with code:%d%s\n", ATTR_ERR, errorcode,ATTR_RST); - } else { - printf("%s \nSuccessfully written to flash with code:%d Resetting the reading buffer....%s\n", ATTR_INF, errorcode,ATTR_RST); - memset(flash_data_read, 0, FLASH_RW_SIZE); - errorcode = flash_read(flash, FLASH_ADDR, flash_data_read, FLASH_RW_SIZE); - if(errorcode < 0) { - printf("%s Error reading from flash with code:%d%s\n", ATTR_ERR, errorcode,ATTR_RST); + errorcode = flash_erase(flash, FLASH_ADDR, 0x1000); + if (errorcode < 0) { + printf("%s\nError Erasing the flash at 0x%08x offset errorcode:%d%s\n", ATTR_ERR, + FLASH_ADDR, errorcode, ATTR_RST); } else { - printf("%s Successfully Read from flash with code:%d%s\n", ATTR_INF, errorcode,ATTR_RST); - bool Data_Validated = true; uint8_t Mismatch_count = 0; - for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - if(flash_data_read[i] != flash_data_write[i]) { - Data_Validated = false; Mismatch_count++; - printf("%s %d - Read:%d != Write:%d%s\n", ATTR_ERR, i, flash_data_read[i], flash_data_write[i],ATTR_RST); - } + printf("%s\nSuccessfully Erased Flash\n", ATTR_RST); + errorcode = flash_read(flash, FLASH_ADDR, flash_data_read, FLASH_RW_SIZE); + if (errorcode < 0) { + printf("%s Error reading from flash with code:%d%s\n", ATTR_ERR, errorcode, + ATTR_RST); + } else { + printf("%s Reading Back After Erasing Area of Flash%s\n", ATTR_INF, + ATTR_RST); + for (uint8_t i = 0; i < FLASH_RW_SIZE; i++) { + if (flash_data_read[i] != 0xff) { + errorcode = -1; + } + } } - if(!Data_Validated) { - printf("%s Flash Integrity Check Failed With %d Mismatched Entries%s\n", ATTR_ERR,Mismatch_count,ATTR_RST); - } else{ - printf("%s Flash Integrity Check Passed!!!%s\n", ATTR_INF,ATTR_RST); + if (errorcode == -1) { + printf("%s\nFlash erase at 0x%08x did not produce correct results%s\n", + ATTR_ERR, FLASH_ADDR, ATTR_RST); + // for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { + // printf("%s 0x%02x%s", ATTR_INF, + // flash_data_read[i],i%FORMATTER==0?"\n":""); } printf("\n"); + } else { + printf("%s\nSuccessfully performed erase to flash with code:%d%s\n", + ATTR_INF, errorcode, ATTR_RST); } + errorcode = 0; } - } - if(errorcode == 0) - { - uint8_t *MemMapReadAddr = (uint8_t*)(FLASH_BASE_ADDR + FLASH_ADDR); - uint8_t MemMapReadDestAddr[FLASH_RW_SIZE]; - { - printf("CPU Memory Mapped Reading Test from address:%p\n", MemMapReadAddr); - bool memmaptestfail = false; - for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - if(MemMapReadAddr[i] != flash_data_write[i]) { - printf("%s %d%s", ATTR_ERR, MemMapReadAddr[i],i%FORMATTER==0?"\n":""); - memmaptestfail = true; - } - else { - printf("%s %d%s", ATTR_INF, MemMapReadAddr[i],i%FORMATTER==0?"\n":""); - } - } printf("\n"); - if(memmaptestfail) { - printf("%s CPU Memory mapped read failed\n", ATTR_ERR); - } else { - printf("%s CPU Memory mapped read passed\n", ATTR_INF); - } - } - - if(dma != NULL) { - printf("%s DMA Memory Mapped Reading Test from address:%p\n", ATTR_RST, MemMapReadAddr); - // Configure DMA Block - struct dma_block_config lv_dma_block_config = { - .block_size = FLASH_RW_SIZE, - .dest_addr_adj = DMA_ADDR_ADJ_INCREMENT, - .dest_address = (uint32_t)&MemMapReadDestAddr[0], - .dest_reload_en = 0, - .dest_scatter_count = 0, - .dest_scatter_en = 0, - .dest_scatter_interval = 0, - .fifo_mode_control = 0, - .flow_control_mode = 0, - .next_block = NULL, - .source_addr_adj = DMA_ADDR_ADJ_INCREMENT, - .source_address = (uint32_t)&MemMapReadAddr[0], - .source_gather_count = 0, - .source_gather_en = 0, - .source_gather_interval = 0, - .source_reload_en = 0, - ._reserved = 0 - }; - // Configure DMA - struct dma_config lv_Dma_Config = { - .block_count = 1, - .channel_direction = MEMORY_TO_MEMORY, - .channel_priority = 1, - .complete_callback_en = 0, - .cyclic = 0, - .dest_burst_length = 1, - .dest_chaining_en = 0, - .dest_data_size = 1, - .dest_handshake = 1, - .dma_callback = NULL, - .dma_slot = 0, - .error_callback_dis = 1, - .head_block = &lv_dma_block_config, - .linked_channel = 0, - .source_burst_length = 1, - .source_chaining_en = 0, - .source_data_size = 1, - .user_data = NULL - }; - struct dma_status stat = {0}; - printf("%s DMA Configuration...\n", ATTR_RST); - int dma_error = dma_config(dma, 1, &lv_Dma_Config); - k_msleep(10); - if(dma_error) { - printf("%s Error %d Configuration...\n", ATTR_RST, dma_error); - } else { - // Call DMA Read - printf("%s DMA Starting...\n", ATTR_INF); - dma_error = dma_start(dma, 1); - k_msleep(10); + if (errorcode == 0) { + printf("%s Writing the following data After Erasing Flash%s\n", ATTR_INF, ATTR_RST); + for (uint8_t i = 0; i < FLASH_RW_SIZE; i++) { + flash_data_write[i] = ((rand() % (FLASH_RW_SIZE - 1 + 1)) + 1) + + ((rand() % (FLASH_RW_SIZE - 1 + 1)) + 1); + // printf("%s %d%s", ATTR_INF, flash_data_write[i],i%FORMATTER==0?"\n":""); } - (void)dma_get_status(dma, 1, &stat); - while(stat.pending_length > 1) { - dma_error = dma_get_status(dma, 1, &stat); - if(dma_error) { - printf("Error %d dma_status...\n", dma_error); - break; + // printf("\n"); + errorcode = flash_write(flash, FLASH_ADDR, flash_data_write, FLASH_RW_SIZE); + } + + if (errorcode < 0) { + printf("%s \nError writing to flash with code:%d%s\n", ATTR_ERR, errorcode, + ATTR_RST); + } else { + printf("%s \nSuccessfully written to flash with code:%d Resetting the reading " + "buffer....%s\n", + ATTR_INF, errorcode, ATTR_RST); + memset(flash_data_read, 0, FLASH_RW_SIZE); + errorcode = flash_read(flash, FLASH_ADDR, flash_data_read, FLASH_RW_SIZE); + if (errorcode < 0) { + printf("%s Error reading from flash with code:%d%s\n", ATTR_ERR, errorcode, + ATTR_RST); + } else { + printf("%s Successfully Read from flash with code:%d%s\n", ATTR_INF, + errorcode, ATTR_RST); + bool Data_Validated = true; + uint8_t Mismatch_count = 0; + for (uint8_t i = 0; i < FLASH_RW_SIZE; i++) { + if (flash_data_read[i] != flash_data_write[i]) { + Data_Validated = false; + Mismatch_count++; + printf("%s %d - Read:%d != Write:%d%s\n", ATTR_ERR, i, + flash_data_read[i], flash_data_write[i], ATTR_RST); + } + } + if (!Data_Validated) { + printf("%s Flash Integrity Check Failed With %d Mismatched " + "Entries%s\n", + ATTR_ERR, Mismatch_count, ATTR_RST); } else { - printf("dma_pending_length:%d \n", stat.pending_length); + printf("%s Flash Integrity Check Passed!!!%s\n", ATTR_INF, + ATTR_RST); } } + } - if(!dma_error) { + if (errorcode == 0) { + uint8_t *MemMapReadAddr = (uint8_t *)(FLASH_BASE_ADDR + FLASH_ADDR); + uint8_t MemMapReadDestAddr[FLASH_RW_SIZE]; + { + printf("CPU Memory Mapped Reading Test from address:%p\n", MemMapReadAddr); bool memmaptestfail = false; - for(uint8_t i = 0; i < FLASH_RW_SIZE; i++) { - if(MemMapReadDestAddr[i] != flash_data_write[i]) { - printf("%s %d%s", ATTR_ERR, MemMapReadDestAddr[i],i%FORMATTER==0?"\n":""); + for (uint8_t i = 0; i < FLASH_RW_SIZE; i++) { + if (MemMapReadAddr[i] != flash_data_write[i]) { + printf("%s %d%s", ATTR_ERR, MemMapReadAddr[i], + i % FORMATTER == 0 ? "\n" : ""); memmaptestfail = true; - } - else { - printf("%s %d%s", ATTR_INF, MemMapReadDestAddr[i],i%FORMATTER==0?"\n":""); } - } + // else { + // printf("%s %d%s", ATTR_INF, + // MemMapReadAddr[i],i%FORMATTER==0?"\n":""); + // } + } printf("\n"); - if(memmaptestfail) { - printf("%s DMA Memory mapped read failed\n", ATTR_ERR); + if (memmaptestfail) { + printf("%s CPU Memory mapped read failed\n", ATTR_ERR); } else { - printf("%s DMA Memory mapped read passed\n", ATTR_INF); + printf("%s CPU Memory mapped read passed\n", ATTR_INF); + } + } + + if (dma != NULL) { + printf("%s DMA Memory Mapped Reading Test from address:%p\n", ATTR_RST, + MemMapReadAddr); + // Configure DMA Block + struct dma_block_config lv_dma_block_config = { + .block_size = FLASH_RW_SIZE, + .dest_addr_adj = DMA_ADDR_ADJ_INCREMENT, + .dest_address = (uint32_t)&MemMapReadDestAddr[0], + .dest_reload_en = 0, + .dest_scatter_count = 0, + .dest_scatter_en = 0, + .dest_scatter_interval = 0, + .fifo_mode_control = 0, + .flow_control_mode = 0, + .next_block = NULL, + .source_addr_adj = DMA_ADDR_ADJ_INCREMENT, + .source_address = (uint32_t)&MemMapReadAddr[0], + .source_gather_count = 0, + .source_gather_en = 0, + .source_gather_interval = 0, + .source_reload_en = 0, + ._reserved = 0}; + // Configure DMA + struct dma_config lv_Dma_Config = {.block_count = 1, + .channel_direction = MEMORY_TO_MEMORY, + .channel_priority = 1, + .complete_callback_en = 0, + .cyclic = 0, + .dest_burst_length = 1, + .dest_chaining_en = 0, + .dest_data_size = 1, + .dest_handshake = 1, + .dma_callback = NULL, + .dma_slot = 0, + .error_callback_dis = 1, + .head_block = &lv_dma_block_config, + .linked_channel = 0, + .source_burst_length = 1, + .source_chaining_en = 0, + .source_data_size = 1, + .user_data = NULL}; + struct dma_status stat = {0}; + printf("%s DMA Configuration...\n", ATTR_RST); + int dma_error = dma_config(dma, 1, &lv_Dma_Config); + k_msleep(10); + if (dma_error) { + printf("%s Error %d Configuration...\n", ATTR_RST, dma_error); + } else { + // Call DMA Read + printf("%s DMA Starting...\n", ATTR_INF); + dma_error = dma_start(dma, 1); + k_msleep(10); + } + (void)dma_get_status(dma, 1, &stat); + while (stat.pending_length > 1) { + dma_error = dma_get_status(dma, 1, &stat); + if (dma_error) { + printf("Error %d dma_status...\n", dma_error); + break; + } else { + printf("dma_pending_length:%d \n", stat.pending_length); + } + } + + if (!dma_error) { + bool memmaptestfail = false; + for (uint8_t i = 0; i < FLASH_RW_SIZE; i++) { + if (MemMapReadDestAddr[i] != flash_data_write[i]) { + printf("%s %d%s", ATTR_ERR, MemMapReadDestAddr[i], + i % FORMATTER == 0 ? "\n" : ""); + memmaptestfail = true; + } + // else { + // printf("%s %d%s", ATTR_INF, + // MemMapReadDestAddr[i],i%FORMATTER==0?"\n":""); + // } + } + printf("\n"); + if (memmaptestfail) { + printf("%s DMA Memory mapped read failed\n", ATTR_ERR); + } else { + printf("%s DMA Memory mapped read passed\n", ATTR_INF); + } + } else { + printf("Error %d DMA Start...\n", dma_error); } - } else { - printf("Error %d DMA Start...\n", dma_error); } } } -} +#endif +#if CONFIG_COUNTER_ANDES_ATCPIT100 void CounterCallBack(const struct device *dev, void *UserData) { - uint32_t *lvData = ((uint32_t*)UserData); - printf("andestech_atcpit100 %s # %d\n", __func__, *lvData); + uint32_t *lvData = ((uint32_t *)UserData); + printf("\nandestech_atcpit100 %s # %d\n", __func__, *lvData); *lvData += 1; } -void CounterAlarmCallBack(const struct device *dev, - uint8_t chan_id, uint32_t ticks, - void *UserData) +void CounterAlarmCallBack(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *UserData) { - uint32_t *lvData = ((uint32_t*)UserData); - printf("andestech_atcpit100 %s # %d\n", __func__, *lvData); + uint32_t *lvData = ((uint32_t *)UserData); + printf("\nandestech_atcpit100 %s # %d\n", __func__, *lvData); } static uint32_t s_CallBackData = 0; @@ -230,23 +256,23 @@ void CounterTest(const struct device *pit) lvCntAlarmCfg.callback = CounterAlarmCallBack; lvCntAlarmCfg.flags = COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE; lvCntAlarmCfg.ticks = 24000; - lvCntAlarmCfg.user_data = (void*)&s_CallBackData; + lvCntAlarmCfg.user_data = (void *)&s_CallBackData; struct counter_top_cfg lvCntTopCfg = {0}; lvCntTopCfg.callback = CounterCallBack; - lvCntTopCfg.user_data = (void*)&s_CallBackData; + lvCntTopCfg.user_data = (void *)&s_CallBackData; lvCntTopCfg.flags = COUNTER_TOP_CFG_DONT_RESET; lvCntTopCfg.ticks = 6000; int lvErrorCode = 0; - /* + lvErrorCode = counter_set_channel_alarm(pit, 0, &lvCntAlarmCfg); - if(lvErrorCode < 0) { - printf("%s%s(%d) counter Alarm set error code:%d %s\n", \ - ATTR_ERR,__func__,__LINE__,lvErrorCode,ATTR_RST); - } - */ + if (lvErrorCode < 0) { + printf("%s%s(%d) counter Alarm set error code:%d %s\n", ATTR_ERR, __func__, + __LINE__, lvErrorCode, ATTR_RST); + } + /* lvErrorCode = counter_set_top_value(pit, &lvCntTopCfg); if(lvErrorCode < 0) { printf("%s%s(%d) counter setting top error code:%d %s\n", \ @@ -258,70 +284,727 @@ void CounterTest(const struct device *pit) ATTR_ERR,__func__,__LINE__,lvErrorCode,ATTR_RST); } } + */ } +#endif -int main(void) +#if CONFIG_CRYPTO_PUF_SECURITY_OTP +void pufs_otp_test(const struct device *pufs_otp) { - int Cnt = 0; - uint8_t chip_id = 0, vendor_id = 0; + uint8_t slot_data[32] = {0}; + enum crypto_otp_lock lvLock = CRYPTO_OTP_RW; + uint16_t totalSlots = 0, bytesPerSlot = 0; - printf( - "%s SPI_(%d)_IRQ_Reg_Val:[0x%08x]; DMA_(%d)_IRQ_Reg_Val:[0x%08x]\n", ATTR_RST, \ - IRQ_ID_SPI, scu_get_irq_reg_val(IRQ_ID_SPI), \ - IRQ_ID_SYSTEM_DMA, scu_get_irq_reg_val(IRQ_ID_SYSTEM_DMA) - ); + if (otp_info(pufs_otp, &totalSlots, &bytesPerSlot) != 0) { + printf("%s%s(%d) OTP_Info Failed%s\n", ATTR_ERR, __func__, __LINE__, ATTR_RST); + } else { + printf("%s%s(%d) OTP_Info... Slots:%d Bytes Per Slot:%d%s\n", ATTR_INF, __func__, + __LINE__, totalSlots, bytesPerSlot, ATTR_RST); + } - soc_get_id(&chip_id, &vendor_id); + if (otp_get_lock(pufs_otp, 12, &lvLock) != 0) { + printf("%s%s(%d) otp_get_lock Failed%s\n", ATTR_ERR, __func__, __LINE__, ATTR_RST); + } else { + printf("%s%s(%d) otp_lock: %d %s\n", ATTR_INF, __func__, __LINE__, lvLock, + ATTR_RST); + } - int errorcode = 0; - struct sensor_value lvTemp = {0}, lvVolt = {0}; - const struct device *pvt = DEVICE_DT_GET(DT_NODELABEL(pvt0)); - const struct device *spi = DEVICE_DT_GET(DT_NODELABEL(spi0)); - const struct device *flash = DEVICE_DT_GET(DT_NODELABEL(m25p32)); - const struct device *dma = DEVICE_DT_GET(DT_NODELABEL(dma0)); - const struct device *pit = DEVICE_DT_GET(DT_NODELABEL(pit0)); - - if((pvt == NULL) || (!device_is_ready(pvt))) { - printf("%s pvt has status disabled or driver is not initialized...%s\n", ATTR_ERR, ATTR_RST); + for (uint8_t i = 0; i < bytesPerSlot; i++) { + slot_data[i] = (i + i) * 2; + } + if (otp_write(pufs_otp, 12, slot_data, 18) != 0) { + if (lvLock != CRYPTO_OTP_RW) { + printf("%s%s(%d) otp_write Failed as Expected %s\n", ATTR_RST, __func__, + __LINE__, ATTR_RST); + } else { + printf("%s%s(%d) otp_write Failed unExpectedly %s\n", ATTR_ERR, __func__, + __LINE__, ATTR_RST); + } + } else { + printf("%s%s(%d) otp_write Passed %s\n", ATTR_RST, __func__, __LINE__, ATTR_RST); + memset(slot_data, 0, bytesPerSlot); + if (otp_read(pufs_otp, 12, slot_data, 18) != 0) { + if (lvLock == CRYPTO_OTP_NA) { + printf("%s%s(%d) otp_read Failed as Expected %s\n", ATTR_RST, + __func__, __LINE__, ATTR_RST); + } else { + printf("%s%s(%d) otp_read Failed unExpectedly %s\n", ATTR_ERR, + __func__, __LINE__, ATTR_RST); + } + } else { + printf("%s", ATTR_INF); + for (uint8_t i = 0; i < bytesPerSlot; i++) { + printf("%d ", slot_data[i]); + } + printf("\n"); + printf("%s", ATTR_RST); + } + } + if (otp_set_lock(pufs_otp, 12, 18, CRYPTO_OTP_RO) != 0) { + printf("%s%s(%d) otp_set_lock Failed%s\n", ATTR_ERR, __func__, __LINE__, ATTR_RST); } else { - printf("%s pvt Object is Created %s\n", ATTR_INF, ATTR_RST); - errorcode = sensor_channel_get(pvt, SENSOR_CHAN_DIE_TEMP, &lvTemp); - if(errorcode == 0) { - printf("%s Error fetching temperature value. Error code:%u%s\n", ATTR_ERR, errorcode,ATTR_RST); + if (otp_get_lock(pufs_otp, 12, &lvLock) != 0) { + printf("%s%s(%d) otp_get_lock Failed%s\n", ATTR_ERR, __func__, __LINE__, + ATTR_RST); + } else { + printf("%s%s(%d) otp_lock: %d %s\n", ATTR_INF, __func__, __LINE__, lvLock, + ATTR_RST); } - errorcode = sensor_channel_get(pvt, SENSOR_CHAN_VOLTAGE, &lvVolt); - if(errorcode == 0) { - printf("%s Error fetching Voltage value. Error code:%u%s\n", ATTR_ERR, errorcode,ATTR_RST); + for (uint8_t i = 0; i < bytesPerSlot; i++) { + slot_data[i] = (i + i) * 2; + } + if (otp_write(pufs_otp, 12, slot_data, 18) != 0) { + if (lvLock != CRYPTO_OTP_RW) { + printf("%s%s(%d) otp_write Failed as Expected %s\n", ATTR_RST, + __func__, __LINE__, ATTR_RST); + } else { + printf("%s%s(%d) otp_write Failed unExpectedly %s\n", ATTR_ERR, + __func__, __LINE__, ATTR_RST); + } + } else { + printf("%s%s(%d) otp_write Passed UnExpectedly %s\n", ATTR_ERR, __func__, + __LINE__, ATTR_RST); } - printf("%s Die Temperature:%d Voltage:%d%s\n", ATTR_INF, lvTemp.val1, lvVolt.val1,ATTR_RST); } +} +#endif +#if CONFIG_CRYPTO_PUF_SECURITY +void pufs_hash_sg_test(const struct device *pufs) +{ + int status = 0; + static uint8_t pufs_sample_data1[] = { + "My name is Junaid and I work at the Rapid Silicon and WorkFromH."}; + static uint8_t pufs_sample_data2[] = { + "My name is Junaid and I work at the Rapid Silicon and WorkFromH."}; + static uint8_t pufs_sample_data3[] = {"123456789123456789"}; + + static uint8_t pufs_sample_data_sha256_out[32] = {0}; + static const uint8_t pufs_sample_data_sha256[] = { + 0xb2, 0x69, 0xec, 0xc6, 0x0f, 0x13, 0x37, 0xf3, 0xf3, 0xf8, 0x29, + 0xc1, 0x0e, 0xc5, 0x83, 0xa6, 0x82, 0x25, 0x97, 0x32, 0x71, 0x78, + 0xd1, 0xb8, 0xe5, 0x95, 0x05, 0xd1, 0xbe, 0xe7, 0x43, 0xca}; + const uint8_t pufs_sample_data1_len = strlen(pufs_sample_data1); + const uint8_t pufs_sample_data2_len = strlen(pufs_sample_data2); + const uint8_t pufs_sample_data3_len = strlen(pufs_sample_data3); + + printf("%s%s(%d) Length of sample data to operate on:%d %s\n", ATTR_INF, __func__, __LINE__, + pufs_sample_data1_len + pufs_sample_data2_len + pufs_sample_data3_len, ATTR_RST); + + struct hash_ctx lvHashCtx = {.device = pufs, + .drv_sessn_state = NULL, + .flags = CAP_SYNC_OPS | CAP_SEPARATE_IO_BUFS, + .started = true}; + + struct hash_pkt lvHashPkt1 = {0}, lvHashPkt2 = {0}, lvHashPkt3 = {0}; + + lvHashPkt1.ctx = &lvHashCtx; + lvHashPkt1.head = true; + lvHashPkt1.tail = true; + lvHashPkt1.in_buf = pufs_sample_data1; + lvHashPkt1.in_hash = NULL; + lvHashPkt1.in_hash_len = 0; + lvHashPkt1.in_len = pufs_sample_data1_len; + lvHashPkt1.next = &lvHashPkt2; + lvHashPkt1.out_buf = pufs_sample_data_sha256_out; + lvHashPkt1.out_len = 0; + lvHashPkt1.prev_len = 0; + + lvHashPkt2.ctx = &lvHashCtx; + lvHashPkt2.head = true; + lvHashPkt2.tail = true; + lvHashPkt2.in_buf = pufs_sample_data2; + lvHashPkt2.in_hash = NULL; + lvHashPkt2.in_hash_len = 0; + lvHashPkt2.in_len = pufs_sample_data2_len; + lvHashPkt2.next = &lvHashPkt3; + lvHashPkt2.out_buf = pufs_sample_data_sha256_out; + lvHashPkt2.out_len = 0; + lvHashPkt2.prev_len = 0; + + lvHashPkt3.ctx = &lvHashCtx; + lvHashPkt3.head = true; + lvHashPkt3.tail = true; + lvHashPkt3.in_buf = pufs_sample_data3; + lvHashPkt3.in_hash = NULL; + lvHashPkt3.in_hash_len = 0; + lvHashPkt3.in_len = pufs_sample_data3_len; + lvHashPkt3.next = NULL; + lvHashPkt3.out_buf = pufs_sample_data_sha256_out; + lvHashPkt3.out_len = 0; + lvHashPkt3.prev_len = 0; - if(spi == NULL) { - printf("%s spi has status disabled...%s\n", ATTR_ERR,ATTR_RST); - } else { - printf("%s spi Object is Created. Test Via DMA\n", ATTR_INF); - if(flash == NULL) { - printf("%s flash has status disabled or not initialized properly...%s\n", ATTR_ERR,ATTR_RST); + printf("Pkt1.rd_addr:0x%08x Pkt2.rd_addr:0x%08x Pkt3.rd_addr:0x%08x\r\n", + (uint32_t)lvHashPkt1.in_buf, (uint32_t)lvHashPkt2.in_buf, + (uint32_t)lvHashPkt3.in_buf); + printf("Size struct hash pkt:%d\r\n", sizeof(struct hash_pkt)); + printf("data1_size:%d data2_size:%d data3_size:%d\r\n", pufs_sample_data1_len, + pufs_sample_data2_len, pufs_sample_data3_len); + + status = hash_begin_session(pufs, &lvHashCtx, CRYPTO_HASH_ALGO_SHA256); + if (status != 0) { + printf("%s%s(%d) hash_begin_session status = %d %s\n", ATTR_ERR, __func__, __LINE__, + status, ATTR_RST); + } else { + status = hash_compute(&lvHashCtx, &lvHashPkt1); + } + if (status != 0) { + printf("%s%s(%d) hash_compute status = %d %s\n", ATTR_ERR, __func__, __LINE__, + status, ATTR_RST); + } else { + for (uint8_t i = 0; i < lvHashPkt1.out_len; i++) { + if (lvHashPkt1.out_buf[i] != pufs_sample_data_sha256[i]) { + // printf("%s%s(%d) out_buf[%d]0x%02x != in_buf[%d]:0x%02x %s\n", + // ATTR_ERR,__func__,__LINE__, + // i,lvHashPkt1.out_buf[i],i,pufs_sample_data_sha256[i],ATTR_RST); + status = -EINVAL; + } else { + // printf("%s%s(%d) out_buf[%d]0x%02x == in_buf[%d]:0x%02x %s\n", + // ATTR_INF,__func__,__LINE__, + // i,lvHashPkt1.out_buf[i],i,pufs_sample_data_sha256[i],ATTR_RST); + } + } + if (status != 0) { + printf("%s%s(%d) hash_comparison failed%s\n", ATTR_ERR, __func__, __LINE__, + ATTR_RST); + } else { + printf("%s%s(%d) hash_comparison Passed = %d %s\n", ATTR_INF, __func__, + __LINE__, status, ATTR_RST); + } + status = hash_free_session(pufs, &lvHashCtx); + if (status != 0) { + printf("%s%s(%d) hash_free_session status = %d %s\n", ATTR_ERR, __func__, + __LINE__, status, ATTR_RST); } else { - printf("%s flash Object is Created. Initialize to Test Via DMA%s\n", ATTR_INF,ATTR_RST); - Flash_Test(flash, dma, 0x1000, 0, 20); + printf("%s%s(%d) hash_free_session Passed = %d %s\n", ATTR_INF, __func__, + __LINE__, status, ATTR_RST); } } +} + +void pufs_hash_test(const struct device *pufs) +{ + int status = 0; + static uint8_t *pufs_sample_data = "This is Rapid Silicon'z Zephyr Port"; + static uint8_t pufs_sample_data_sha256_out[32] = {0}; + static const uint8_t pufs_sample_data_sha256[] = { + 0xfa, 0x71, 0xc2, 0x19, 0xea, 0x58, 0x4d, 0xac, 0x36, 0xd5, 0x3e, + 0xca, 0xe4, 0x2a, 0x8c, 0x14, 0x4b, 0xc1, 0xc0, 0x03, 0xfd, 0x36, + 0x3f, 0x71, 0xd9, 0x30, 0x96, 0xc4, 0xaa, 0x64, 0xe0, 0x4c}; + const uint8_t pufs_sample_data_len = strlen(pufs_sample_data); + printf("%s%s(%d) Length of sample data to operate on:%d %s\n", ATTR_INF, __func__, __LINE__, + pufs_sample_data_len, ATTR_RST); + struct hash_ctx lvHashCtx = {.device = pufs, + .drv_sessn_state = NULL, + .flags = CAP_SYNC_OPS | CAP_SEPARATE_IO_BUFS, + .started = false}; - if((pit == NULL) || !device_is_ready(pit)) { - printf("%s flash has status disabled or driver is not initialized...%s\n", ATTR_ERR,ATTR_RST); + struct hash_pkt lvHashPkt = {.ctx = &lvHashCtx, + .head = true, + .tail = true, + .in_buf = pufs_sample_data, + .in_hash = NULL, + .in_len = pufs_sample_data_len, + .next = NULL, + .out_buf = pufs_sample_data_sha256_out, + .prev_len = 0, + .out_len = 0}; + status = hash_begin_session(pufs, &lvHashCtx, CRYPTO_HASH_ALGO_SHA256); + if (status != 0) { + printf("%s%s(%d) hash_begin_session status = %d %s\n", ATTR_ERR, __func__, __LINE__, + status, ATTR_RST); } else { - CounterTest(pit); + status = hash_compute(&lvHashCtx, &lvHashPkt); } + if (status != 0) { + printf("%s%s(%d) hash_compute status = %d %s\n", ATTR_ERR, __func__, __LINE__, + status, ATTR_RST); + } else { + for (uint8_t i = 0; i < lvHashPkt.out_len; i++) { + if (lvHashPkt.out_buf[i] != pufs_sample_data_sha256[i]) { + // printf("%s%s(%d) out_buf[%d]0x%02x != in_buf[%d]:0x%02x %s\n", + // ATTR_ERR,__func__,__LINE__, + // i,lvHashPkt.out_buf[i],i,pufs_sample_data_sha256[i],ATTR_RST); + status = -EINVAL; + } else { + // printf("%s%s(%d) out_buf[%d]0x%02x == in_buf[%d]:0x%02x %s\n", + // ATTR_INF,__func__,__LINE__, + // i,lvHashPkt.out_buf[i],i,pufs_sample_data_sha256[i],ATTR_RST); + } + } + if (status != 0) { + printf("%s%s(%d) hash_comparison failed%s\n", ATTR_ERR, __func__, __LINE__, + ATTR_RST); + } else { + printf("%s%s(%d) hash_comparison Passed = %d %s\n", ATTR_INF, __func__, + __LINE__, status, ATTR_RST); + } + status = hash_free_session(pufs, &lvHashCtx); + if (status != 0) { + printf("%s%s(%d) hash_free_session status = %d %s\n", ATTR_ERR, __func__, + __LINE__, status, ATTR_RST); + } else { + printf("%s%s(%d) hash_free_session Passed = %d %s\n", ATTR_INF, __func__, + __LINE__, status, ATTR_RST); + } + } +} + +void pufs_decryption_test(const struct device *pufs) +{ + int lvStatus = 0; + + struct cipher_ctx lvCipherCtx = {0}; + struct cipher_pkt lvCipherPkt = {0}; + + uint8_t enc32_key[] = {0x30, 0x13, 0x53, 0x33, 0x44, 0x12, 0xff, 0x22, 0x31, 0x53, 0xbb, + 0x13, 0x07, 0x19, 0x84, 0x0d, 0xd5, 0x3c, 0x3f, 0xc0, 0x09, 0x83, + 0x11, 0x35, 0x30, 0x2d, 0xdc, 0xc0, 0x0b, 0xb9, 0x4e, 0x30}; + uint8_t iv[] = {0xaa, 0x34, 0x55, 0x32, 0xe9, 0x58, 0xaa, 0xf3, + 0xc0, 0xde, 0x20, 0xa6, 0xa9, 0x21, 0x44, 0xe8}; + + uint8_t cipher_text[] = { + 0xd0, 0x07, 0x29, 0x7b, 0x56, 0x2c, 0x2c, 0xa7, 0x43, 0x24, 0x68, 0xd8, 0x58, + 0xb4, 0xc1, 0x9f, 0x7c, 0x05, 0x7c, 0x98, 0x03, 0x28, 0x19, 0x9d, 0x93, 0xff, + 0x85, 0xd7, 0xdb, 0x8f, 0xf1, 0x07, 0x18, 0xa5, 0x1f, 0x99, 0x04, 0x73, 0x84, + 0x4f, 0x4f, 0x79, 0xba, 0x2e, 0x70, 0x82, 0xb1, 0x39, 0x5d, 0x3f, 0x3e, 0xf8, + 0x44, 0x81, 0xf6, 0x89, 0x17, 0x3a, 0x29, 0x43, 0x0a, 0x41, 0x24, 0xff, 0x57, + 0xa8, 0xbb, 0x0b, 0x0e, 0xcf, 0xb3, 0xed, 0x8e, 0x1d, 0x49, 0x03, 0x86, 0x77, + 0x61, 0x68, 0x59, 0x7c, 0xf0, 0x61, 0x98, 0x11, 0x1b, 0xe5, 0xe3, 0x95, 0x6d, + 0x81, 0x49, 0xdc, 0xa0, 0x4b, 0x97, 0xb4, 0xe6, 0x40, 0xd5, 0x26, 0xb6, 0xb7, + 0xd8, 0xab, 0x61, 0xc1, 0xa7, 0x5a, 0xdc, 0x5e, 0xa9, 0x25, 0x6f, 0xcd, 0x25, + 0xb6, 0xd0, 0x42, 0xa1, 0xd8, 0xd5, 0xdc, 0xcf, 0xc6, 0xaa, 0xdf}; + + uint8_t *plain_text = + "Plain Text: This is Junaid Aslam from Rapid Silicon doing Decryption Test...\n"; + uint8_t decrypted_text[256] = {0}; + + lvCipherCtx.app_sessn_state = NULL; + lvCipherCtx.device = pufs; + lvCipherCtx.flags = (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS | CAP_NO_IV_PREFIX | + CAP_NO_ENCRYPTION); + lvCipherCtx.key.bit_stream = enc32_key; + lvCipherCtx.key_source = CRYPTO_KEY_SW; + lvCipherCtx.keylen = 32; + lvCipherCtx.mode_params.ctr_info.ctr_len = 16; + lvCipherCtx.mode_params.ctr_info.readback_ctr = false; + lvCipherCtx.ops.cipher_mode = CRYPTO_CIPHER_MODE_CTR; + + lvCipherPkt.auto_increment = true; + lvCipherPkt.ctx = &lvCipherCtx; + lvCipherPkt.in_buf = cipher_text; + lvCipherPkt.in_len = (sizeof(cipher_text) / sizeof(cipher_text[0])); + lvCipherPkt.out_buf = decrypted_text; + lvCipherPkt.prev_len = 0; + + printf("%s Decrypting %d bytes %s\n", ATTR_INF, lvCipherPkt.in_len, ATTR_RST); + + lvStatus = cipher_begin_session(pufs, &lvCipherCtx, CRYPTO_CIPHER_ALGO_AES, + CRYPTO_CIPHER_MODE_CTR, CRYPTO_CIPHER_OP_DECRYPT); + if (lvStatus != 0) { + printf("%s cipher_begin_session Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%s cipher_begin_session Success! %s\n", ATTR_INF, ATTR_RST); + lvStatus = cipher_ctr_op(&lvCipherCtx, &lvCipherPkt, (uint8_t *)iv); + } + + if (lvStatus != 0) { + printf("%s cipher_ctr_op Failed! Status:%d %s\n", ATTR_ERR, lvStatus, ATTR_RST); + } else { + printf("%s cipher_ctr_op Success! %s\n", ATTR_INF, ATTR_RST); + printf("%s Original: %s%s", ATTR_HIL, plain_text, ATTR_RST); + printf("%s Result: %s%s", ATTR_HIL, lvCipherPkt.out_buf, ATTR_RST); + bool comparison_ok = true; + for (int i = 0; i < strlen(lvCipherPkt.out_buf); i++) { + if (lvCipherPkt.out_buf[i] != plain_text[i]) { + // printf("Orig[%d]:0x%02x(%c) != Res[%d]:0x%02x(%c)\n", i, + // plain_text[i], plain_text[i], i, lvCipherPkt.out_buf[i], + // lvCipherPkt.out_buf[i]); + comparison_ok = false; + break; + } + // else { + // printf("Orig[%d]:0x%02x(%c) == Res[%d]:0x%02x(%c)\n", i, plain_text[i], + // plain_text[i], i, lvCipherPkt.out_buf[i], lvCipherPkt.out_buf[i]); + // } + } + if (!comparison_ok) { + printf("%s cipher decryption Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%s cipher decryption Passed! %s\n", ATTR_INF, ATTR_RST); + } + } + + lvStatus = cipher_free_session(pufs, &lvCipherCtx); + if (lvStatus != 0) { + printf("%s cipher_free_session Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%s cipher_free_session Success! %s\n", ATTR_INF, ATTR_RST); + } +} + +const uint32_t bop_ec256_image_addr[] = { + 0x4c425346, 0x00010001, 0x00000001, 0x00000540, 0xa020005c, 0xa020005c, 0x00000040, + 0x00000000, 0x00000010, 0x00000040, 0x00000040, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x5bef0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x5a41e854, 0xbd7831f5, 0x8a722abc, 0x0f194645, 0xfca0b124, + 0x4c32ac0f, 0x119da725, 0x017d57f0, 0xc3c72358, 0xf5a403c4, 0x35f48b62, 0xe3bcf592, + 0xe0ae8930, 0xe0ef26dc, 0xad99438b, 0xbc0b8b9e, 0xf746712e, 0x36b64de7, 0x1b2dd12b, + 0x016f428d, 0xa6375c54, 0xb19e1329, 0x29abce2e, 0x01d2ef46, 0x4522360f, 0x4646a2b0, + 0x4b9e632d, 0x65bd20b3, 0xa9a48e98, 0x78cdc0d2, 0xb80be124, 0x72e406e9}; + +const uint32_t bop_rsa_image_addr[] = { + 0x4c425346, 0x00010001, 0x00000001, 0x00000540, 0xa020005c, 0xa020005c, 0x00000040, + 0x00000000, 0x00000020, 0x00000104, 0x00000100, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x467b0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x37c2cac9, 0x8c32e765, 0xa15e1200, 0x25c486b2, 0x8734d7b4, + 0xfa26c29d, 0x2ff972ae, 0x0adebf22, 0xff6f29e6, 0x3c50778d, 0xfa02d8da, 0x78600d02, + 0xbca88565, 0x163ca9be, 0x73f0da10, 0x3ed20b1c, 0xcce46d11, 0x2a49278f, 0x12248db6, + 0xe50b6755, 0xa431193c, 0x6c308699, 0xe0c41dbf, 0x50c791fe, 0xd3f876b9, 0x7cf1df93, + 0x16941322, 0xaa1ead8f, 0xe3753f54, 0xc9bb7bcc, 0x79200bff, 0x7d76c2d4, 0xa7acc7f7, + 0xff567a99, 0xbfa4f5dc, 0x064238c8, 0xe9699208, 0xa6b5daf3, 0xa3a2ad30, 0x32bafe37, + 0x54e1dacb, 0xda540799, 0x95547760, 0x302cd650, 0x9d428238, 0x62bbdadd, 0xe531a353, + 0x282e8f7d, 0x973e7ba1, 0x0dd65973, 0x4ab77a02, 0x53ca63ae, 0x176010c2, 0x58bc890d, + 0x025f55f8, 0x0e1e579b, 0xe19cdb04, 0x4bb6caf5, 0xad438b2c, 0xeda4466b, 0x3cabf8dc, + 0x0785aca7, 0xd0350f09, 0x79cac3c1, 0x00010001, 0x00000000, 0x00000000, 0x00000000, + 0xebe1a78f, 0x2e6e03ed, 0x4ee1354e, 0x2052aa4d, 0xbb4cb958, 0x230e0232, 0x862cb015, + 0x58dee9e7, 0xfde8f54e, 0xc96e44be, 0x607271f8, 0x983ecea7, 0xe8770c08, 0x0dc7599b, + 0x590e8ff8, 0x690188e6, 0x66dfaf5e, 0xf6335a68, 0x2c0b118f, 0x3733a790, 0x9c938f42, + 0x3ce28852, 0x2c74cda7, 0x7dad40de, 0xe7a80299, 0xa3e92677, 0x4b328cd7, 0x760976e1, + 0x92a152e4, 0x4225f6c3, 0xb3d87236, 0x43a9be7e, 0xbbb12076, 0x66433975, 0x353e3019, + 0x010926e2, 0x00d08453, 0x045cfcd6, 0xc763d656, 0xe873faee, 0xb1fc2dc1, 0x0530f6e3, + 0x7064e3ff, 0xc6062a2f, 0xe1a3d120, 0xf728ad4f, 0xa7159b1e, 0x8f3e3a92, 0x97be047f, + 0x75a4d27b, 0x5fc4d749, 0x194d52ce, 0x0199ccba, 0x0de3e3ec, 0x830b6dd5, 0xff35543e, + 0x5b0b9d15, 0x8258edb7, 0xfee5009e, 0xed692f55, 0x5fbe279a, 0x9fa66ee6, 0x3913674d, + 0x671285c3}; + +struct rs_bop_header { + uint32_t bop_id; + uint16_t bop_hdr_version; + uint16_t sign_tool_version; + uint32_t binary_version; + uint32_t binary_len; + uint32_t load_addr; + uint32_t entry_addr; + uint32_t offset_to_binary; + uint32_t offset_to_next_header; + uint8_t sig_algo; + uint8_t option; + uint8_t enc_algo; + uint8_t iv_len; + uint16_t pub_key_len; + uint16_t enc_key_len; + uint16_t sig_len; + uint8_t compression_algo; + uint8_t bin_pad_bytes; // Number of padding bytes in the payload binary or + // bitstream + uint16_t xcb_header_size; + uint8_t padding[16]; // To make BOP header 64 bytes for scatter gather hash + // calculation + uint16_t crc_16; +}; + +void pufs_rsa2048_verify_test(const struct device *pufs) +{ + int lvStatus = 0; + + struct sign_ctx lvSignCtx = {0}; + struct sign_pkt lvSignPkt = {0}; + + uint32_t pub_key_padding = 12; + + struct rs_bop_header *bop_hdr = (struct rs_bop_header *)bop_rsa_image_addr; + + uint8_t *pub_key = (uint8_t *)bop_rsa_image_addr + bop_hdr->offset_to_binary + + bop_hdr->binary_len + bop_hdr->iv_len; + uint8_t *sig = (uint8_t *)pub_key + bop_hdr->pub_key_len + pub_key_padding; + + lvSignCtx.app_sessn_state = NULL; + lvSignCtx.device = pufs; + lvSignCtx.drv_sessn_state = NULL; + lvSignCtx.flags = (CAP_INPLACE_OPS | CAP_SYNC_OPS); + lvSignCtx.pub_key = pub_key; + lvSignCtx.sig = sig; + lvSignCtx.ops.signing_algo = CRYPTO_SIGN_ALGO_RSA2048; + lvSignCtx.ops.signing_mode = CRYPTO_SIGN_VERIFY; + + lvSignPkt.ctx = &lvSignCtx; + lvSignPkt.in_buf = (uint8_t *)bop_hdr; + lvSignPkt.in_len = bop_hdr->binary_len + sizeof(struct rs_bop_header) + 272; + lvSignPkt.next = NULL; + + lvStatus = sign_begin_session(pufs, &lvSignCtx, CRYPTO_SIGN_ALGO_RSA2048); + if (lvStatus != 0) { + printf("\n%ssign_begin_session RSA2048 Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%ssign_begin_session RSA2048 Success! %s\n", ATTR_INF, ATTR_RST); + lvStatus = sign_op_handler(&lvSignCtx, &lvSignPkt); + } + + if (lvStatus != 0) { + printf("%s sign_op_handler RSA2048 Failed! Status:%d %s\n", ATTR_ERR, lvStatus, ATTR_RST); + } else { + printf("%s sign_op_handler RSA2048 Success! %s\n", ATTR_INF, ATTR_RST); + } + + lvStatus = sign_free_session(pufs, &lvSignCtx); + if (lvStatus != 0) { + printf("%s sign_free_session RSA2048 Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%s sign_free_session RSA2048 Success! %s\n", ATTR_INF, ATTR_RST); + } +} + +void pufs_ecdsa256_verify_test(const struct device *pufs) +{ + int lvStatus = 0; + + struct sign_ctx lvSignCtx = {0}; + struct sign_pkt lvSignPkt = {0}; + + struct rs_bop_header *bop_hdr = (struct rs_bop_header *)bop_ec256_image_addr; + + uint8_t *pub_key = (uint8_t *)bop_ec256_image_addr + bop_hdr->offset_to_binary + + bop_hdr->binary_len + bop_hdr->iv_len; + uint8_t *sig = (uint8_t *)pub_key + bop_hdr->pub_key_len; + + lvSignCtx.app_sessn_state = NULL; + lvSignCtx.device = pufs; + lvSignCtx.drv_sessn_state = NULL; + lvSignCtx.flags = (CAP_INPLACE_OPS | CAP_SYNC_OPS); + lvSignCtx.pub_key = pub_key; + lvSignCtx.sig = sig; + lvSignCtx.ops.signing_algo = CRYPTO_SIGN_ALGO_ECDSA256; + lvSignCtx.ops.signing_mode = CRYPTO_SIGN_VERIFY; + + lvSignPkt.ctx = &lvSignCtx; + lvSignPkt.in_buf = (uint8_t *)bop_hdr; + lvSignPkt.in_len = bop_hdr->binary_len + sizeof(struct rs_bop_header) + 64; // 64 = public key x(32) + y(32) + lvSignPkt.next = NULL; + + lvStatus = sign_begin_session(pufs, &lvSignCtx, CRYPTO_SIGN_ALGO_ECDSA256); + if (lvStatus != 0) { + printf("\n%ssign_begin_session ECDSA256 Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%ssign_begin_session ECDSA256 Success! %s\n", ATTR_INF, ATTR_RST); + lvStatus = sign_op_handler(&lvSignCtx, &lvSignPkt); + } + + if (lvStatus != 0) { + printf("%s sign_op_handler ECDSA256 Failed! Status:%d %s\n", ATTR_ERR, lvStatus, ATTR_RST); + } else { + printf("%s sign_op_handler ECDSA256 Success! %s\n", ATTR_INF, ATTR_RST); + } + + lvStatus = sign_free_session(pufs, &lvSignCtx); + if (lvStatus != 0) { + printf("%s sign_free_session ECDSA256 Failed! %s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%s sign_free_session ECDSA256 Success! %s\n", ATTR_INF, ATTR_RST); + } +} +#endif + +int main(void) +{ + int Cnt = 0; + uint8_t chip_id = 0, vendor_id = 0; + + #if DT_HAS_RAPIDSI_SCU_ENABLED + printf("%s SPI_(%d)_IRQ_Reg_Val:[0x%08x]; DMA_(%d)_IRQ_Reg_Val:[0x%08x]\n", ATTR_RST, + IRQ_ID_SPI, scu_get_irq_reg_val(IRQ_ID_SPI), IRQ_ID_SYSTEM_DMA, + scu_get_irq_reg_val(IRQ_ID_SYSTEM_DMA)); + + soc_get_id(&chip_id, &vendor_id); + scu_assert_reset(); + #endif + + int errorcode = 0; + struct sensor_value lvTemp = {0}, lvVolt = {0}; + #if CONFIG_DTI_PVT + const struct device *pvt = DEVICE_DT_GET(DT_NODELABEL(pvt0)); + #endif + #if (CONFIG_SPI_ANDES_ATCSPI200 && CONFIG_SPI_NOR) + const struct device *spi = DEVICE_DT_GET(DT_NODELABEL(spi0)); + const struct device *flash = DEVICE_DT_GET(DT_NODELABEL(m25p32)); + #endif + #if CONFIG_DMA_ANDES_ATCDMAC100 + const struct device *dma = DEVICE_DT_GET(DT_NODELABEL(dma0)); + #endif + #if CONFIG_COUNTER_ANDES_ATCPIT100 + const struct device *pit = DEVICE_DT_GET(DT_NODELABEL(pit0)); + #endif + #if CONFIG_CRYPTO_PUF_SECURITY + const struct device *pufs = DEVICE_DT_GET(DT_NODELABEL(pufs)); + #endif + #if CONFIG_CRYPTO_PUF_SECURITY_OTP + const struct device *pufs_otp = DEVICE_DT_GET(DT_NODELABEL(pufs_otp)); + #endif + + #if CONFIG_CRYPTO_PUF_SECURITY + if ((pufs == NULL) || (!device_is_ready(pufs))) { + printf("%s pufs has status disabled or driver is not initialized...%s\n", ATTR_ERR, + ATTR_RST); + } else { + printf("%s pufs Object is Created %s\n", ATTR_INF, ATTR_RST); + pufs_decryption_test(pufs); + pufs_hash_test(pufs); + pufs_hash_sg_test(pufs); + pufs_rsa2048_verify_test(pufs); + pufs_ecdsa256_verify_test(pufs); + } + #endif + + #if CONFIG_CRYPTO_PUF_SECURITY_OTP + if ((pufs_otp == NULL) || (!device_is_ready(pufs_otp))) { + printf("%s pufs_otp has status disabled or driver is not initialized...%s\n", + ATTR_ERR, ATTR_RST); + } else { + printf("%s pufs_otp Object is Created %s\n", ATTR_INF, ATTR_RST); + pufs_otp_test(pufs_otp); + } + #endif + #if CONFIG_DTI_PVT + if ((pvt == NULL) || (!device_is_ready(pvt))) { + printf("%s pvt has status disabled or driver is not initialized...%s\n", ATTR_ERR, + ATTR_RST); + } else { + printf("%s pvt Object is Created %s\n", ATTR_INF, ATTR_RST); + errorcode = sensor_channel_get(pvt, SENSOR_CHAN_DIE_TEMP, &lvTemp); + if (errorcode == 0) { + printf("%s Error fetching temperature value. Error code:%u%s\n", ATTR_ERR, + errorcode, ATTR_RST); + } + errorcode = sensor_channel_get(pvt, SENSOR_CHAN_VOLTAGE, &lvVolt); + if (errorcode == 0) { + printf("%s Error fetching Voltage value. Error code:%u%s\n", ATTR_ERR, + errorcode, ATTR_RST); + } + printf("%s Die Temperature:%d Voltage:%d%s\n", ATTR_INF, lvTemp.val1, lvVolt.val1, + ATTR_RST); + } + #endif + #if (CONFIG_SPI_ANDES_ATCSPI200 && CONFIG_SPI_NOR) + if (spi == NULL) { + printf("%s spi has status disabled...%s\n", ATTR_ERR, ATTR_RST); + } else { + printf("%s spi Object is Created. Test Via DMA\n", ATTR_INF); + if (flash == NULL) { + printf("%s flash has status disabled or not initialized properly...%s\n", + ATTR_ERR, ATTR_RST); + } else { + printf("%s flash Object is Created. Initialize to Test Via DMA%s\n", + ATTR_INF, ATTR_RST); + Flash_Test(flash, dma, 0x1000, 0, 20); + } + } + #endif + #if CONFIG_COUNTER_ANDES_ATCPIT100 + if ((pit == NULL) || !device_is_ready(pit)) { + printf("%s pit has status disabled or driver is not initialized...%s\n", ATTR_ERR, + ATTR_RST); + } else { + CounterTest(pit); + } + #endif - while(true) { - printf( - "%s%d - %s [CHIP_ID:0x%02x VENDOR_ID:0x%02x] Build[Date:%s Time:%s]\n", - ATTR_RST, Cnt++, - CONFIG_BOARD_TARGET, - chip_id, vendor_id, - __DATE__, __TIME__ - ); + while (true) { + printf("%s%d - %s [CHIP_ID:0x%02x VENDOR_ID:0x%02x] Build[Date:%s Time:%s]\r", + ATTR_RST, Cnt++, CONFIG_BOARD_TARGET, chip_id, vendor_id, __DATE__, + __TIME__); k_msleep(1000); } diff --git a/soc/rapidsilicon/virgo/Kconfig b/soc/rapidsilicon/virgo/Kconfig index 428b56f7e5cbf..2fdbbd380b702 100644 --- a/soc/rapidsilicon/virgo/Kconfig +++ b/soc/rapidsilicon/virgo/Kconfig @@ -27,9 +27,6 @@ if GEN_IRQ_VECTOR_TABLE default IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS endchoice - config RISCV_MCAUSE_EXCEPTION_MASK - default 0x1F - endif config SOC_ANDES_V5_EXECIT diff --git a/soc/rapidsilicon/virgo/Kconfig.defconfig b/soc/rapidsilicon/virgo/Kconfig.defconfig index 7e05011ae8502..4a11fd26a7d32 100644 --- a/soc/rapidsilicon/virgo/Kconfig.defconfig +++ b/soc/rapidsilicon/virgo/Kconfig.defconfig @@ -25,22 +25,22 @@ config RISCV_SOC_INTERRUPT_INIT config RISCV_GP default y +config RISCV_MCAUSE_EXCEPTION_MASK + default 0xFFF + config NUM_2ND_LEVEL_AGGREGATORS default 1 config 2ND_LVL_ISR_TBL_OFFSET - default 16 + default 0 config 2ND_LVL_INTR_00_OFFSET - default 16 + default 0 config MAX_IRQ_PER_AGGREGATOR - default 16 - -config 2ND_LEVEL_INTERRUPT_BITS - default 8 + default 52 config NUM_IRQS - default 32 + default 52 endif # SOC_SERIES_VIRGO \ No newline at end of file diff --git a/soc/rapidsilicon/virgo/scu.c b/soc/rapidsilicon/virgo/scu.c index 871a3525aff1c..55580486222ae 100644 --- a/soc/rapidsilicon/virgo/scu.c +++ b/soc/rapidsilicon/virgo/scu.c @@ -8,7 +8,8 @@ typedef struct { volatile uint32_t idrev; /* 0x00 */ - volatile uint32_t reserved[10]; /* 0x04 - 0x28 */ + volatile uint32_t sw_rst_control; /* 0x04 */ + volatile uint32_t reserved[9]; /* 0x08 - 0x28 */ volatile uint32_t irq_map_mask[32]; /* 0x2C - 0xA8 */ } scu_registers_t; @@ -19,6 +20,15 @@ typedef struct { static volatile scu_registers_t *s_scu_regs = NULL; #endif +void scu_assert_reset(void) +{ + uint32_t reset_flags = + (VIRGO_SCU_SW_RST_CTRL_MSK_BUS | VIRGO_SCU_SW_RST_CTRL_MSK_PER | + VIRGO_SCU_SW_RST_CTRL_MSK_FPGA0 | VIRGO_SCU_SW_RST_CTRL_MSK_FPGA1 | + VIRGO_SCU_SW_RST_CTRL_MSK_DMA); + s_scu_regs->sw_rst_control |= reset_flags; +} + void soc_get_id(uint8_t *chip_id, uint8_t *vendor_id) { *chip_id = ((s_scu_regs->idrev & SCU_CHIP_ID_MASK) >> SCU_CHIP_ID_OFFSET); diff --git a/soc/rapidsilicon/virgo/scu.h b/soc/rapidsilicon/virgo/scu.h index 13b538b6dd3c2..c8357d2c2b98c 100644 --- a/soc/rapidsilicon/virgo/scu.h +++ b/soc/rapidsilicon/virgo/scu.h @@ -23,6 +23,16 @@ #define SCU_IRQ_MAP_TO_FPGA 0x4 #define SCU_IRQ_MAP_MASK 0x7 +/// Software reset control +enum virgo_scu_sw_rst_ctrl_msk { + VIRGO_SCU_SW_RST_CTRL_MSK_SYSTEM = (0x1UL << 0), + VIRGO_SCU_SW_RST_CTRL_MSK_BUS = (0x1UL << 1), + VIRGO_SCU_SW_RST_CTRL_MSK_PER = (0x1UL << 4), + VIRGO_SCU_SW_RST_CTRL_MSK_FPGA0 = (0x1UL << 5), + VIRGO_SCU_SW_RST_CTRL_MSK_FPGA1 = (0x1UL << 6), + VIRGO_SCU_SW_RST_CTRL_MSK_DMA = (0x1UL << 10), +}; + /********************************* * The following table is aligned * with respect to the scu map and @@ -73,6 +83,8 @@ void scu_irq_enable(enum map_mask_control_irq_id IRQn); void scu_irq_disable(enum map_mask_control_irq_id IRQn); uint32_t scu_get_irq_reg_val(enum map_mask_control_irq_id IRQn); +void scu_assert_reset(void); + #define SCU_CHIP_ID_OFFSET 16 #define SCU_CHIP_ID_MASK 0x00FF0000