xtensa/esp32: ESP32 SPI Flash encryption supports 16-bytes align writing

This commit is contained in:
Dong Heng 2023-01-04 14:38:37 +08:00 committed by Xiang Xiao
parent a491d07061
commit 67ccee2c4f
2 changed files with 224 additions and 4 deletions

View File

@ -47,6 +47,7 @@
#include "hardware/esp32_soc.h"
#include "hardware/esp32_spi.h"
#include "hardware/esp32_dport.h"
#include "hardware/efuse_reg.h"
#ifdef CONFIG_ESP32_SPIRAM
#include "esp32_spiram.h"
@ -73,6 +74,8 @@
#define SPI_FLASH_ENCRYPT_WORDS (32 / 4)
#define SPI_FLASH_ERASED_STATE (0xff)
#define SPI_FLASH_ENCRYPT_MIN_SIZE (16)
#define MTD2PRIV(_dev) ((struct esp32_spiflash_s *)_dev)
#define MTD_SIZE(_priv) ((_priv)->chip->chip_size)
#define MTD_BLKSIZE(_priv) ((_priv)->chip->page_size)
@ -242,8 +245,10 @@ static ssize_t esp32_bread_decrypt(struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks,
uint8_t *buffer);
#ifdef CONFIG_MTD_BYTE_WRITE
static ssize_t esp32_write(struct mtd_dev_s *dev, off_t offset,
size_t nbytes, const uint8_t *buffer);
#endif
static ssize_t esp32_bwrite(struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, const uint8_t *buffer);
static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev,
@ -252,6 +257,8 @@ static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev,
const uint8_t *buffer);
static int esp32_ioctl(struct mtd_dev_s *dev, int cmd,
unsigned long arg);
static int esp32_ioctl_encrypt(struct mtd_dev_s *dev, int cmd,
unsigned long arg);
/****************************************************************************
* Private Data
@ -289,7 +296,7 @@ static struct esp32_spiflash_s g_esp32_spiflash1_encrypt =
.bread = esp32_bread_decrypt,
.bwrite = esp32_bwrite_encrypt,
.read = esp32_read_decrypt,
.ioctl = esp32_ioctl,
.ioctl = esp32_ioctl_encrypt,
#ifdef CONFIG_MTD_BYTE_WRITE
.write = NULL,
#endif
@ -1731,6 +1738,7 @@ static ssize_t esp32_bread_decrypt(struct mtd_dev_s *dev,
*
****************************************************************************/
#ifdef CONFIG_MTD_BYTE_WRITE
static ssize_t esp32_write(struct mtd_dev_s *dev, off_t offset,
size_t nbytes, const uint8_t *buffer)
{
@ -1770,6 +1778,7 @@ static ssize_t esp32_write(struct mtd_dev_s *dev, off_t offset,
return ret;
}
#endif
/****************************************************************************
* Name: esp32_bwrite
@ -1839,9 +1848,21 @@ static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev,
const uint8_t *buffer)
{
ssize_t ret;
ssize_t n;
off_t addr;
uint8_t *wbuf;
uint8_t *rbuf;
uint8_t tmp_buf[SPI_FLASH_ENCRYPT_UNIT_SIZE];
size_t wbytes = 0;
struct esp32_spiflash_s *priv = MTD2PRIV(dev);
uint32_t addr = MTD_BLK2SIZE(priv, startblock);
uint32_t size = MTD_BLK2SIZE(priv, nblocks);
uint32_t offset = MTD_BLK2SIZE(priv, startblock);
uint32_t nbytes = MTD_BLK2SIZE(priv, nblocks);
if ((offset % SPI_FLASH_ENCRYPT_MIN_SIZE) ||
(nbytes % SPI_FLASH_ENCRYPT_MIN_SIZE))
{
return -EINVAL;
}
#ifdef CONFIG_ESP32_SPIFLASH_DEBUG
finfo("esp32_bwrite_encrypt(%p, 0x%x, %d, %p)\n",
@ -1854,7 +1875,77 @@ static ssize_t esp32_bwrite_encrypt(struct mtd_dev_s *dev,
return ret;
}
ret = esp32_writedata_encrypted(priv, addr, buffer, size);
while (nbytes)
{
if (offset % SPI_FLASH_ENCRYPT_UNIT_SIZE)
{
wbuf = tmp_buf;
rbuf = tmp_buf;
addr = offset - SPI_FLASH_ENCRYPT_MIN_SIZE;
n = SPI_FLASH_ENCRYPT_MIN_SIZE;
ret = esp32_readdata_encrypted(priv, addr, rbuf, n);
if (ret < 0)
{
ferr("esp32_readdata_encrypted failed ret=%d\n", ret);
break;
}
memcpy(wbuf + n, buffer, n);
}
else if (nbytes % SPI_FLASH_ENCRYPT_UNIT_SIZE)
{
wbuf = tmp_buf;
if (offset % SPI_FLASH_ENCRYPT_UNIT_SIZE)
{
rbuf = tmp_buf;
addr = offset - SPI_FLASH_ENCRYPT_MIN_SIZE;
}
else
{
rbuf = tmp_buf + SPI_FLASH_ENCRYPT_MIN_SIZE;
addr = offset;
}
n = SPI_FLASH_ENCRYPT_MIN_SIZE;
ret = esp32_readdata_encrypted(priv, addr, rbuf, n);
if (ret < 0)
{
ferr("esp32_readdata_encrypted failed ret=%d\n", ret);
break;
}
if (offset % SPI_FLASH_ENCRYPT_UNIT_SIZE)
{
memcpy(wbuf + n, buffer, n);
}
else
{
memcpy(wbuf, buffer, n);
}
}
else
{
n = SPI_FLASH_ENCRYPT_UNIT_SIZE;
wbuf = (uint8_t *)buffer;
addr = offset;
}
ret = esp32_writedata_encrypted(priv, addr, wbuf,
SPI_FLASH_ENCRYPT_UNIT_SIZE);
if (ret < 0)
{
ferr("esp32_writedata_encrypted failed ret=%d\n", ret);
break;
}
offset += n;
nbytes -= n;
buffer += n;
wbytes += n;
}
nxmutex_unlock(&g_lock);
if (ret == OK)
@ -1943,6 +2034,82 @@ static int esp32_ioctl(struct mtd_dev_s *dev, int cmd,
return ret;
}
/****************************************************************************
* Name: esp32_ioctl_encrypt
*
* Description:
* Set/Get option to/from ESP32 SPI Flash Hardware Encryption MTD
* device data.
*
* Input Parameters:
* dev - ESP32 MTD device data
* cmd - operation command
* arg - operation argument
*
* Returned Value:
* 0 if success or a negative value if fail.
*
****************************************************************************/
static int esp32_ioctl_encrypt(struct mtd_dev_s *dev, int cmd,
unsigned long arg)
{
int ret = -EINVAL;
struct esp32_spiflash_s *priv = MTD2PRIV(dev);
finfo("cmd: %d\n", cmd);
switch (cmd)
{
case MTDIOC_GEOMETRY:
{
struct mtd_geometry_s *geo = (struct mtd_geometry_s *)arg;
if (geo)
{
geo->blocksize = SPI_FLASH_ENCRYPT_MIN_SIZE;
geo->erasesize = MTD_ERASESIZE(priv);
geo->neraseblocks = MTD_SIZE(priv) / geo->erasesize;
ret = OK;
finfo("blocksize: %d erasesize: %d neraseblocks: %d\n",
geo->blocksize, geo->erasesize, geo->neraseblocks);
}
}
break;
case BIOC_PARTINFO:
{
struct partition_info_s *info =
(struct partition_info_s *)arg;
if (info != NULL)
{
info->sectorsize = SPI_FLASH_ENCRYPT_MIN_SIZE;
info->numsectors = MTD_SIZE(priv) / info->sectorsize;
info->startsector = 0;
info->parent[0] = '\0';
ret = OK;
}
}
break;
case MTDIOC_ERASESTATE:
{
uint8_t *result = (uint8_t *)arg;
*result = SPI_FLASH_ERASED_STATE;
ret = OK;
}
break;
default:
ret = -ENOTTY;
break;
}
finfo("return %d\n", ret);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -2065,4 +2232,41 @@ struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void)
return &priv->mtd;
}
/****************************************************************************
* Name: esp32_flash_encryption_enabled
*
* Description:
* Check if ESP32 enables SPI Flash encryption.
*
* Input Parameters:
* None
*
* Returned Value:
* True: SPI Flash encryption is enable, False if not.
*
****************************************************************************/
bool esp32_flash_encryption_enabled(void)
{
bool enabled = false;
uint32_t regval;
uint32_t flash_crypt_cnt;
regval = getreg32(EFUSE_BLK0_RDATA0_REG);
flash_crypt_cnt = (regval >> EFUSE_RD_FLASH_CRYPT_CNT_S) &
EFUSE_RD_FLASH_CRYPT_CNT_V;
while (flash_crypt_cnt)
{
if (flash_crypt_cnt & 1)
{
enabled = !enabled;
}
flash_crypt_cnt >>= 1;
}
return enabled;
}
#endif /* CONFIG_ESP32_SPIFLASH */

View File

@ -101,6 +101,22 @@ struct mtd_dev_s *esp32_spiflash_get_mtd(void);
struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void);
/****************************************************************************
* Name: esp32_flash_encryption_enabled
*
* Description:
* Check if ESP32 enables SPI Flash encryption.
*
* Input Parameters:
* None
*
* Returned Value:
* True: SPI Flash encryption is enable, False if not.
*
****************************************************************************/
bool esp32_flash_encryption_enabled(void);
#ifdef __cplusplus
}
#endif