Commit 9719e19a authored by Joanna Farley's avatar Joanna Farley Committed by TrustedFirmware Code Review
Browse files

Merge changes I500ddbe9,I9c10dac9,I53bfff85,I06f7594d,I24bff8d4, ... into integration

* changes:
  nxp lx2160a-aqds: new plat based on soc lx2160a
  NXP lx2160a-rdb: new plat based on SoC lx2160a
  nxp lx2162aqds: new plat based on soc lx2160a
  nxp: errata handling at soc level for lx2160a
  nxp: make file for loading additional ddr image
  nxp: adding support of soc lx2160a
  nxp: deflt hdr files for soc & their platforms
  nxp: platform files for bl2 and bl31 setup
  nxp: warm reset support to retain ddr content
  nxp: nv storage api on platforms
  nxp: supports two mode of trusted board boot
  nxp: fip-handler for additional fip_fuse.bin
  nxp: fip-handler for additional ddr-fip.bin
  nxp: image loader for loading fip image
  nxp: svp & sip smc handling
  nxp: psci platform functions used by lib/psci
  nxp: helper function used by plat & common code
  nxp: add data handler used by bl31
  nxp: adding the driver.mk file
  nxp-tool: for creating pbl file from bl2
  nxp: adding the smmu driver
  nxp: cot using nxp internal and mbedtls
  nxp:driver for crypto h/w accelerator caam
  nxp:add driver support for sd and emmc
  nxp:add qspi driver
  nxp: add flexspi driver support
  nxp: adding gic apis for nxp soc
  nxp: gpio driver support
  nxp: added csu driver
  nxp: driver pmu for nxp soc
  nxp: ddr driver enablement for nxp layerscape soc
  nxp: i2c driver support.
  NXP: Driver for NXP Security Monitor
  NXP: SFP driver support for NXP SoC
  NXP: Interconnect API based on ARM CCN-CCI driver
  NXP: TZC API to configure ddr region
  NXP: Timer API added to enable ARM generic timer
  nxp: add dcfg driver
  nxp:add console driver for nxp platform
  tools: add mechanism to allow platform specific image UUID
  tbbr-cot: conditional definition for the macro
  tbbr-cot: fix the issue of compiling time define
  cert_create: updated tool for platform defined certs, keys & extensions
  tbbr-tools: enable override TRUSTED_KEY_CERT
parents b59444ea f359a382
/*
* Copyright 2018-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef CAAM_IO_H
#define CAAM_IO_H
#include <endian.h>
#include <lib/mmio.h>
typedef unsigned long long phys_addr_t;
typedef unsigned long long phys_size_t;
/* Return higher 32 bits of physical address */
#define PHYS_ADDR_HI(phys_addr) \
(uint32_t)(((uint64_t)phys_addr) >> 32)
/* Return lower 32 bits of physical address */
#define PHYS_ADDR_LO(phys_addr) \
(uint32_t)(((uint64_t)phys_addr) & 0xFFFFFFFF)
#ifdef NXP_SEC_BE
#define sec_in32(a) bswap32(mmio_read_32((uintptr_t)(a)))
#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v))
#define sec_in64(addr) ( \
((uint64_t)sec_in32((uintptr_t)(addr)) << 32) | \
(sec_in32(((uintptr_t)(addr)) + 4)))
#define sec_out64(addr, val) ({ \
sec_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32)); \
sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); })
#elif defined(NXP_SEC_LE)
#define sec_in32(a) mmio_read_32((uintptr_t)(a))
#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), (v))
#define sec_in64(addr) ( \
((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) | \
(sec_in32((uintptr_t)(addr))))
#define sec_out64(addr, val) ({ \
sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)((val) >> 32)); \
sec_out32(((uintptr_t)(addr)), (uint32_t)(val)); })
#else
#error Please define CCSR SEC register endianness
#endif
static inline void *ptov(phys_addr_t *ptr)
{
return (void *)ptr;
}
static inline phys_addr_t *vtop(void *ptr)
{
return (phys_addr_t *)ptr;
}
#endif /* CAAM_IO_H */
/*
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __HASH_H__
#define __HASH_H__
#include <stdbool.h>
/* List of hash algorithms */
enum hash_algo {
SHA1 = 0,
SHA256
};
/* number of bytes in the SHA256-256 digest */
#define SHA256_DIGEST_SIZE 32
/*
* number of words in the digest - Digest is kept internally
* as 8 32-bit words
*/
#define _SHA256_DIGEST_LENGTH 8
/*
* block length - A block, treated as a sequence of
* 32-bit words
*/
#define SHA256_BLOCK_LENGTH 16
/* number of bytes in the block */
#define SHA256_DATA_SIZE 64
#define MAX_SG 12
struct sg_entry {
#if defined(NXP_SEC_LE)
uint32_t addr_lo; /* Memory Address - lo */
uint32_t addr_hi; /* Memory Address of start of buffer - hi */
#else
uint32_t addr_hi; /* Memory Address of start of buffer - hi */
uint32_t addr_lo; /* Memory Address - lo */
#endif
uint32_t len_flag; /* Length of the data in the frame */
#define SG_ENTRY_LENGTH_MASK 0x3FFFFFFF
#define SG_ENTRY_EXTENSION_BIT 0x80000000
#define SG_ENTRY_FINAL_BIT 0x40000000
uint32_t bpid_offset;
#define SG_ENTRY_BPID_MASK 0x00FF0000
#define SG_ENTRY_BPID_SHIFT 16
#define SG_ENTRY_OFFSET_MASK 0x00001FFF
#define SG_ENTRY_OFFSET_SHIFT 0
};
/*
* SHA256-256 context
* contain the following fields
* State
* count low
* count high
* block data buffer
* index to the buffer
*/
struct hash_ctx {
struct sg_entry sg_tbl[MAX_SG];
uint32_t hash_desc[64];
uint8_t hash[SHA256_DIGEST_SIZE];
uint32_t sg_num;
uint32_t len;
uint8_t *data;
enum hash_algo algo;
bool active;
};
int hash_init(enum hash_algo algo, void **ctx);
int hash_update(enum hash_algo algo, void *context, void *data_ptr,
unsigned int data_len);
int hash_final(enum hash_algo algo, void *context, void *hash_ptr,
unsigned int hash_len);
#endif
/*
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef __JOBDESC_H
#define __JOBDESC_H
#include <rsa.h>
#define DESC_LEN_MASK 0x7f
#define DESC_START_SHIFT 16
#define KEY_BLOB_SIZE 32
#define MAC_SIZE 16
#define KEY_IDNFR_SZ_BYTES 16
#define CLASS_SHIFT 25
#define CLASS_2 (0x02 << CLASS_SHIFT)
#define CMD_SHIFT 27
#define CMD_OPERATION (U(0x10) << CMD_SHIFT)
#define OP_TYPE_SHIFT 24
#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
#define OP_PCLID_SHIFT 16
#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
#define BLOB_PROTO_INFO 0x00000002
uint32_t desc_length(uint32_t *desc);
int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle,
uint32_t *add_inp, uint32_t add_ip_len,
uint8_t *out_data, uint32_t len);
int cnstr_rng_instantiate_jobdesc(uint32_t *desc);
/* Construct descriptor to generate hw key blob */
int cnstr_hw_encap_blob_jobdesc(uint32_t *desc,
uint8_t *key_idnfr, uint32_t key_sz,
uint32_t key_class, uint8_t *plain_txt,
uint32_t in_sz, uint8_t *enc_blob,
uint32_t out_sz, uint32_t operation);
void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz,
uint8_t *digest);
void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
struct pk_in_params *pkin, uint8_t *out,
uint32_t out_siz);
#endif
/*
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef _JR_DRIVER_CONFIG_H_
#define _JR_DRIVER_CONFIG_H_
/* Helper defines */
/* Define used for setting a flag on */
#define ON 1
/* Define used for setting a flag off */
#define OFF 0
/* SEC is configured to start work in polling mode, */
#define SEC_STARTUP_POLLING_MODE 0
/*
* SEC is configured to start work in interrupt mode,
* when configured for NAPI notification style.
*/
#define SEC_STARTUP_INTERRUPT_MODE 1
/*
* SEC driver will use ONLY interrupts to receive notifications
* for processed packets from SEC engine hardware.
*/
#define SEC_NOTIFICATION_TYPE_IRQ 1
/*
* SEC driver will use ONLY polling to receive notifications
* for processed packets from SEC engine hardware.
*/
#define SEC_NOTIFICATION_TYPE_POLL 2
/*
* Determines how SEC user space driver will receive notifications
* for processed packets from SEC engine.
* Valid values are: #SEC_NOTIFICATION_TYPE_POLL, #SEC_NOTIFICATION_TYPE_IRQ
*/
#define SEC_NOTIFICATION_TYPE SEC_NOTIFICATION_TYPE_POLL
/* Maximum number of job rings supported by SEC hardware */
#define MAX_SEC_JOB_RINGS 1
/*
* Size of cryptographic context that is used directly in communicating
* with SEC device.
* SEC device works only with physical addresses. This is the maximum size
* for a SEC descriptor ( = 64 words).
*/
#define SEC_CRYPTO_DESCRIPTOR_SIZE 256
/*
* Size of job descriptor submitted to SEC device for each packet to be
* processed.
* Job descriptor contains 3 DMA address pointers:
* - to shared descriptor, to input buffer and to output buffer.
* The job descriptor contains other SEC specific commands as well:
* - HEADER command, SEQ IN PTR command SEQ OUT PTR command and opaque
* data, each measuring 4 bytes.
* Job descriptor size, depending on physical address representation:
* - 32 bit - size is 28 bytes - cacheline-aligned size is 64 bytes
* - 36 bit - size is 40 bytes - cacheline-aligned size is 64 bytes
* @note: Job descriptor must be cacheline-aligned to ensure efficient memory
* access.
* @note: If other format is used for job descriptor, then the size must be
* revised.
*/
#define SEC_JOB_DESCRIPTOR_SIZE 64
/*
* Size of one entry in the input ring of a job ring.
* Input ring contains pointers to job descriptors.
* The memory used for an input ring and output ring must be physically
* contiguous.
*/
#define SEC_JOB_INPUT_RING_ENTRY_SIZE sizeof(phys_addr_t)
/*
* Size of one entry in the output ring of a job ring.
* Output ring entry is a pointer to a job descriptor followed by a 4 byte
* status word.
* The memory used for an input ring and output ring must be physically
* contiguous.
* @note If desired to use also the optional SEQ OUT indication in output
* ring entries, then 4 more bytes must be added to the size.
*/
#define SEC_JOB_OUTPUT_RING_ENTRY_SIZE (SEC_JOB_INPUT_RING_ENTRY_SIZE + 4)
/* DMA memory required for an input ring of a job ring. */
#define SEC_DMA_MEM_INPUT_RING_SIZE \
((SEC_JOB_INPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE))
/*
* DMA memory required for an output ring of a job ring.
* Required extra 4 byte for status word per each entry.
*/
#define SEC_DMA_MEM_OUTPUT_RING_SIZE \
((SEC_JOB_OUTPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE))
/* DMA memory required for descriptors of a job ring. */
#define SEC_DMA_MEM_DESCRIPTORS \
((SEC_CRYPTO_DESCRIPTOR_SIZE)*(SEC_JOB_RING_SIZE))
/* DMA memory required for a job ring, including both input output rings. */
#define SEC_DMA_MEM_JOB_RING_SIZE \
((SEC_DMA_MEM_INPUT_RING_SIZE) + \
(SEC_DMA_MEM_OUTPUT_RING_SIZE))
/*
* When calling sec_init() UA will provide an area of virtual memory
* of size #SEC_DMA_MEMORY_SIZE to be used internally by the driver
* to allocate data (like SEC descriptors) that needs to be passed to
* SEC device in physical addressing and later on retrieved from SEC device.
* At initialization the UA provides specialized ptov/vtop functions/macros to
* translate addresses allocated from this memory area.
*/
#define SEC_DMA_MEMORY_SIZE \
((SEC_DMA_MEM_JOB_RING_SIZE) * (MAX_SEC_JOB_RINGS))
/*
* SEC DEVICE related configuration.
* Enable/Disable logging support at compile time.
* Valid values:
* ON - enable logging
* OFF - disable logging
* The messages are logged at stdout.
*/
#define SEC_DRIVER_LOGGING OFF
/*
* Configure logging level at compile time.
* Valid values:
* SEC_DRIVER_LOG_ERROR - log only errors
* SEC_DRIVER_LOG_INFO - log errors and info messages
* SEC_DRIVER_LOG_DEBUG - log errors, info and debug messages
*/
#define SEC_DRIVER_LOGGING_LEVEL SEC_DRIVER_LOG_DEBUG
/*
* SEC JOB RING related configuration.
* Configure the size of the JOB RING.
* The maximum size of the ring is hardware limited to 1024.
* However the number of packets in flight in a time interval of
* 1ms can be calculated
* from the traffic rate (Mbps) and packet size.
* Here it was considered a packet size of 40 bytes.
* @note Round up to nearest power of 2 for optimized update
* of producer/consumer indexes of each job ring
* \todo Should set to 750, according to the calculation above, but
* the JR size must be power of 2, thus the next closest value must
* be chosen (i.e. 512 since 1024 is not available)
* For firmware choose this to be 16
*/
#define SEC_JOB_RING_SIZE 16
/*
* Interrupt coalescing related configuration.
* NOTE: SEC hardware enabled interrupt
* coalescing is not supported on SEC version 3.1!
* SEC version 4.4 has support for interrupt
* coalescing.
*/
#if SEC_NOTIFICATION_TYPE != SEC_NOTIFICATION_TYPE_POLL
#define SEC_INT_COALESCING_ENABLE ON
/*
* Interrupt Coalescing Descriptor Count Threshold.
* While interrupt coalescing is enabled (ICEN=1), this value determines
* how many Descriptors are completed before raising an interrupt.
* Valid values for this field are from 0 to 255.
* Note that a value of 1 functionally defeats the advantages of interrupt
* coalescing since the threshold value is reached each time that a
* Job Descriptor is completed. A value of 0 is treated in the same
* manner as a value of 1.
*
*/
#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH 10
/*
* Interrupt Coalescing Timer Threshold.
* While interrupt coalescing is enabled (ICEN=1), this value determines the
* maximum amount of time after processing a Descriptor before raising an
* interrupt.
* The threshold value is represented in units equal to 64 CAAM interface
* clocks. Valid values for this field are from 1 to 65535.
* A value of 0 results in behavior identical to that when interrupt
* coalescing is disabled.
*/
#define SEC_INTERRUPT_COALESCING_TIMER_THRESH 100
#endif /* SEC_NOTIFICATION_TYPE_POLL */
#endif /* _JR_DRIVER_CONFIG_H_ */
/*
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef _RSA_H__
#define _RSA_H__
/* RSA key size defines */
#define RSA_4K_KEY_SZ 4096
#define RSA_4K_KEY_SZ_BYTES (RSA_4K_KEY_SZ/8)
#define RSA_2K_KEY_SZ 2048
#define RSA_2K_KEY_SZ_BYTES (RSA_2K_KEY_SZ/8)
#define RSA_1K_KEY_SZ 1024
#define RSA_1K_KEY_SZ_BYTES (RSA_1K_KEY_SZ/8)
#define SHA256_BYTES (256/8)
struct pk_in_params {
uint8_t *e;
uint32_t e_siz;
uint8_t *n;
uint32_t n_siz;
uint8_t *a;
uint32_t a_siz;
uint8_t *b;
uint32_t b_siz;
};
struct rsa_context {
struct pk_in_params pkin;
};
int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
void *sig_ptr, unsigned int sig_len,
void *pk_ptr, unsigned int pk_len);
#endif
/*
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef _SEC_HW_SPECIFIC_H_
#define _SEC_HW_SPECIFIC_H_
#include "caam.h"
#include "sec_jr_driver.h"
/* DEFINES AND MACROS */
/* Used to retry resetting a job ring in SEC hardware. */
#define SEC_TIMEOUT 100000
/*
* Offset to the registers of a job ring.
*Is different for each job ring.
*/
#define CHAN_BASE(jr) ((phys_addr_t)(jr)->register_base_addr)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define SEC_JOB_RING_IS_FULL(pi, ci, ring_max_size, ring_threshold) \
((((pi) + 1 + ((ring_max_size) - (ring_threshold))) & \
(ring_max_size - 1)) == ((ci)))
#define SEC_CIRCULAR_COUNTER(x, max) (((x) + 1) & (max - 1))
/* Struct representing various job ring registers */
struct jobring_regs {
#ifdef NXP_SEC_BE
unsigned int irba_h;
unsigned int irba_l;
#else
unsigned int irba_l;
unsigned int irba_h;
#endif
unsigned int rsvd1;
unsigned int irs;
unsigned int rsvd2;
unsigned int irsa;
unsigned int rsvd3;
unsigned int irja;
#ifdef NXP_SEC_BE
unsigned int orba_h;
unsigned int orba_l;
#else
unsigned int orba_l;
unsigned int orba_h;
#endif
unsigned int rsvd4;
unsigned int ors;
unsigned int rsvd5;
unsigned int orjr;
unsigned int rsvd6;
unsigned int orsf;
unsigned int rsvd7;
unsigned int jrsta;
unsigned int rsvd8;
unsigned int jrint;
unsigned int jrcfg0;
unsigned int jrcfg1;
unsigned int rsvd9;
unsigned int irri;
unsigned int rsvd10;
unsigned int orwi;
unsigned int rsvd11;
unsigned int jrcr;
};
/* Offsets representing common SEC Registers */
#define SEC_REG_MCFGR_OFFSET 0x0004
#define SEC_REG_SCFGR_OFFSET 0x000C
#define SEC_REG_JR0ICIDR_MS_OFFSET 0x0010
#define SEC_REG_JR0ICIDR_LS_OFFSET 0x0014
#define SEC_REG_JR1ICIDR_MS_OFFSET 0x0018
#define SEC_REG_JR1ICIDR_LS_OFFSET 0x001C
#define SEC_REG_JR2ICIDR_MS_OFFSET 0x0020
#define SEC_REG_JR2ICIDR_LS_OFFSET 0x0024
#define SEC_REG_JR3ICIDR_MS_OFFSET 0x0028
#define SEC_REG_JR3ICIDR_LS_OFFSET 0x002C
#define SEC_REG_JRSTARTR_OFFSET 0x005C
#define SEC_REG_CTPR_MS_OFFSET 0x0FA8
/* Offsets representing various RNG registers */
#define RNG_REG_RTMCTL_OFFSET 0x0600
#define RNG_REG_RTSDCTL_OFFSET 0x0610
#define RNG_REG_RTFRQMIN_OFFSET 0x0618
#define RNG_REG_RTFRQMAX_OFFSET 0x061C
#define RNG_REG_RDSTA_OFFSET 0x06C0
#define ALG_AAI_SH_SHIFT 4
/* SEC Registers Bitmasks */
#define MCFGR_PS_SHIFT 16
#define MCFGR_AWCACHE_SHIFT 8
#define MCFGR_AWCACHE_MASK (0xF << MCFGR_AWCACHE_SHIFT)
#define MCFGR_ARCACHE_SHIFT 12
#define MCFGR_ARCACHE_MASK (0xF << MCFGR_ARCACHE_SHIFT)
#define SCFGR_RNGSH0 0x00000200
#define SCFGR_VIRT_EN 0x00008000
#define JRICID_MS_LICID 0x80000000
#define JRICID_MS_LAMTD 0x00020000
#define JRICID_MS_AMTDT 0x00010000
#define JRICID_MS_TZ 0x00008000
#define JRICID_LS_SDID_MASK 0x00000FFF
#define JRICID_LS_NSEQID_MASK 0x0FFF0000
#define JRICID_LS_NSEQID_SHIFT 16
#define JRICID_LS_SEQID_MASK 0x00000FFF
#define JRSTARTR_STARTJR0 0x00000001
#define JRSTARTR_STARTJR1 0x00000002
#define JRSTARTR_STARTJR2 0x00000004
#define JRSTARTR_STARTJR3 0x00000008
#define CTPR_VIRT_EN_POR 0x00000002
#define CTPR_VIRT_EN_INC 0x00000001
/* RNG RDSTA bitmask */
#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001
#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
/* use von Neumann data in both entropy shifter and statistical checker */
#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0
/* use raw data in both entropy shifter and statistical checker */
#define RTMCTL_SAMP_MODE_RAW_ES_SC 1
/* use von Neumann data in entropy shifter, raw data in statistical checker */
#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_RAW_SC 2
/* invalid combination */
#define RTMCTL_SAMP_MODE_INVALID 3
#define RTSDCTL_ENT_DLY_MIN 3200
#define RTSDCTL_ENT_DLY_MAX 12800
#define RTSDCTL_ENT_DLY_SHIFT 16
#define RTSDCTL_ENT_DLY_MASK (U(0xffff) << RTSDCTL_ENT_DLY_SHIFT)
#define RTFRQMAX_DISABLE (1 << 20)
/* Constants for error handling on job ring */
#define JR_REG_JRINT_ERR_TYPE_SHIFT 8
#define JR_REG_JRINT_ERR_ORWI_SHIFT 16
#define JR_REG_JRINIT_JRE_SHIFT 1
#define JRINT_JRE (1 << JR_REG_JRINIT_JRE_SHIFT)
#define JRINT_ERR_WRITE_STATUS (1 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_BAD_INPUT_BASE (3 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_BAD_OUTPUT_BASE (4 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_WRITE_2_IRBA (5 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_WRITE_2_ORBA (6 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_RES_B4_HALT (7 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_REM_TOO_MANY (8 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_ADD_TOO_MANY (9 << JR_REG_JRINT_ERR_TYPE_SHIFT)
#define JRINT_ERR_HALT_MASK 0x0C
#define JRINT_ERR_HALT_INPROGRESS 0x04
#define JRINT_ERR_HALT_COMPLETE 0x08
#define JR_REG_JRCR_VAL_RESET 0x00000001
#define JR_REG_JRCFG_LO_ICTT_SHIFT 0x10
#define JR_REG_JRCFG_LO_ICDCT_SHIFT 0x08
#define JR_REG_JRCFG_LO_ICEN_EN 0x02
#define JR_REG_JRCFG_LO_IMSK_EN 0x01
/* Constants for Descriptor Processing errors */
#define SEC_HW_ERR_SSRC_NO_SRC 0x00
#define SEC_HW_ERR_SSRC_CCB_ERR 0x02
#define SEC_HW_ERR_SSRC_JMP_HALT_U 0x03
#define SEC_HW_ERR_SSRC_DECO 0x04
#define SEC_HW_ERR_SSRC_JR 0x06
#define SEC_HW_ERR_SSRC_JMP_HALT_COND 0x07
#define SEC_HW_ERR_DECO_HFN_THRESHOLD 0xF1
#define SEC_HW_ERR_CCB_ICV_CHECK_FAIL 0x0A
/* Macros for extracting error codes for the job ring */
#define JR_REG_JRINT_ERR_TYPE_EXTRACT(value) \
((value) & 0x00000F00)
#define JR_REG_JRINT_ERR_ORWI_EXTRACT(value) \
(((value) & 0x3FFF0000) >> \
JR_REG_JRINT_ERR_ORWI_SHIFT)
#define JR_REG_JRINT_JRE_EXTRACT(value) \
((value) & JRINT_JRE)
/* Macros for manipulating JR registers */
typedef union {
uint64_t m_whole;
struct {
#ifdef NXP_SEC_BE
uint32_t high;
uint32_t low;
#else
uint32_t low;
uint32_t high;
#endif
} m_halves;
} ptr_addr_t;
#if defined(CONFIG_PHYS_64BIT)
#define sec_read_addr(a) sec_in64((a))
#define sec_write_addr(a, v) sec_out64((a), (v))
#else
#define sec_read_addr(a) sec_in32((a))
#define sec_write_addr(a, v) sec_out32((a), (v))
#endif
#define JR_REG(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET)
#define JR_REG_LO(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET_LO)
#define GET_JR_REG(name, jr) (sec_in32(JR_REG(name, (jr))))
#define GET_JR_REG_LO(name, jr) (sec_in32(JR_REG_LO(name, (jr))))
#define SET_JR_REG(name, jr, val) \
(sec_out32(JR_REG(name, (jr)), (val)))
#define SET_JR_REG_LO(name, jr, val) \
(sec_out32(JR_REG_LO(name, (jr)), (val)))
/* STRUCTURES AND OTHER TYPEDEFS */
/* Lists the possible states for a job ring. */
typedef enum sec_job_ring_state_e {
SEC_JOB_RING_STATE_STARTED, /* Job ring is initialized */
SEC_JOB_RING_STATE_RESET, /* Job ring reset is in progres */
} sec_job_ring_state_t;
struct sec_job_ring_t {
/*
* Consumer index for job ring (jobs array).
* @note: cidx and pidx are accessed from
* different threads.
* Place the cidx and pidx inside the structure
* so that they lay on different cachelines, to
* avoid false sharing between threads when the
* threads run on different cores!
*/
uint32_t cidx;
/* Producer index for job ring (jobs array) */
uint32_t pidx;
/* Ring of input descriptors. Size of array is power of 2 to allow
* fast update of producer/consumer indexes with bitwise operations.
*/
phys_addr_t *input_ring;
/* Ring of output descriptors. */
struct sec_outring_entry *output_ring;
/* The file descriptor used for polling for interrupts notifications */
uint32_t irq_fd;
/* Model used by SEC Driver to receive notifications from SEC.
* Can be either of the three:
* #SEC_NOTIFICATION_TYPE_IRQ or
* #SEC_NOTIFICATION_TYPE_POLL
*/
uint32_t jr_mode;
/* Base address for SEC's register memory for this job ring. */
void *register_base_addr;
/* notifies if coelescing is enabled for the job ring */
uint8_t coalescing_en;
/* The state of this job ring */
sec_job_ring_state_t jr_state;
};
/* Forward structure declaration */
typedef struct sec_job_ring_t sec_job_ring_t;
struct sec_outring_entry {
phys_addr_t desc; /* Pointer to completed descriptor */
uint32_t status; /* Status for completed descriptor */
} __packed;
/* Lists the states possible for the SEC user space driver. */
typedef enum sec_driver_state_e {
SEC_DRIVER_STATE_IDLE, /*< Driver not initialized */
SEC_DRIVER_STATE_STARTED, /*< Driver initialized and */
SEC_DRIVER_STATE_RELEASE, /*< Driver release is in progress */
} sec_driver_state_t;
/* Union describing the possible error codes that */
/* can be set in the descriptor status word */
union hw_error_code {
uint32_t error;
union {
struct {
uint32_t ssrc:4;
uint32_t ssed_val:28;
} __packed value;
struct {
uint32_t ssrc:4;
uint32_t res:28;
} __packed no_status_src;
struct {
uint32_t ssrc:4;
uint32_t jmp:1;
uint32_t res:11;
uint32_t desc_idx:8;
uint32_t cha_id:4;
uint32_t err_id:4;
} __packed ccb_status_src;
struct {
uint32_t ssrc:4;
uint32_t jmp:1;
uint32_t res:11;
uint32_t desc_idx:8;
uint32_t offset:8;
} __packed jmp_halt_user_src;
struct {
uint32_t ssrc:4;
uint32_t jmp:1;
uint32_t res:11;
uint32_t desc_idx:8;
uint32_t desc_err:8;
} __packed deco_src;
struct {
uint32_t ssrc:4;
uint32_t res:17;
uint32_t naddr:3;
uint32_t desc_err:8;
} __packed jr_src;
struct {
uint32_t ssrc:4;
uint32_t jmp:1;
uint32_t res:11;
uint32_t desc_idx:8;
uint32_t cond:8;
} __packed jmp_halt_cond_src;
} __packed error_desc;
} __packed;
/* FUNCTION PROTOTYPES */
/*
* @brief Initialize a job ring/channel in SEC device.
* Write configuration register/s to properly initialize a job ring.
*
* @param [in] job_ring The job ring
*
* @retval 0 for success
* @retval other for error
*/
int hw_reset_job_ring(sec_job_ring_t *job_ring);
/*
* @brief Reset a job ring/channel in SEC device.
* Write configuration register/s to reset a job ring.
*
* @param [in] job_ring The job ring
*
* @retval 0 for success
* @retval -1 in case job ring reset failed
*/
int hw_shutdown_job_ring(sec_job_ring_t *job_ring);
/*
* @brief Handle a job ring/channel error in SEC device.
* Identify the error type and clear error bits if required.
*
* @param [in] job_ring The job ring
* @param [in] sec_error_code error code as first read from SEC engine
*/
void hw_handle_job_ring_error(sec_job_ring_t *job_ring,
uint32_t sec_error_code);
/*
* @brief Handle a job ring error in the device.
* Identify the error type and printout a explanatory
* messages.
*
* @param [in] job_ring The job ring
*
*/
int hw_job_ring_error(sec_job_ring_t *job_ring);
/* @brief Set interrupt coalescing parameters on the Job Ring.
* @param [in] job_ring The job ring
* @param [in] irq_coalesing_timer
* Interrupt coalescing timer threshold.
* This value determines the maximum
* amount of time after processing a descriptor
* before raising an interrupt.
* @param [in] irq_coalescing_count
* Interrupt coalescing count threshold.
* This value determines how many descriptors
* are completed before raising an interrupt.
*/
int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring,
uint16_t irq_coalescing_timer,
uint8_t irq_coalescing_count);
/* @brief Enable interrupt coalescing on a job ring
* @param [in] job_ring The job ring
*/
int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring);
/*
* @brief Disable interrupt coalescing on a job ring
* @param [in] job_ring The job ring
*/
int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring);
/*
* @brief Poll the HW for already processed jobs in the JR
* and notify the available jobs to UA.
*
* @param [in] job_ring The job ring to poll.
* @param [in] limit The maximum number of jobs to notify.
* If set to negative value, all available
* jobs are notified.
*
* @retval >=0 for No of jobs notified to UA.
* @retval -1 for error
*/
int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit);
/* @brief Poll the HW for already processed jobs in the JR
* and silently discard the available jobs or notify them to UA
* with indicated error code.
* @param [in,out] job_ring The job ring to poll.
* @param [in] do_notify Can be #TRUE or #FALSE.
* Indicates if descriptors to be discarded
* or notified to UA with given error_code.
* @param [in] error_code The detailed SEC error code.
* @param [out] notified_descs Number of notified descriptors.
* Can be NULL if do_notify is #FALSE
*/
void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
uint32_t do_notify,
uint32_t error_code, uint32_t *notified_descs);
/*
* @brief Flush job rings of any processed descs.
* The processed descs are silently dropped,
* WITHOUT being notified to UA.
*/
void flush_job_rings(void);
/*
* @brief Handle desc that generated error in SEC engine.
* Identify the exact type of error and handle the error.
* Depending on the error type, the job ring could be reset.
* All descs that are submitted for processing on this job ring
* are notified to User Application with error status and detailed error code.
* @param [in] job_ring Job ring
* @param [in] sec_error_code Error code read from job ring's Channel
* Status Register
* @param [out] notified_descs Number of notified descs. Can be NULL if
* do_notify is #FALSE
* @param [out] do_driver_shutdown If set to #TRUE, then UA is returned code
* #SEC_PROCESSING_ERROR
* which is indication that UA must call
* sec_release() after this.
*/
void sec_handle_desc_error(struct sec_job_ring_t *job_ring,
uint32_t sec_error_code,
uint32_t *notified_descs,
uint32_t *do_driver_shutdown);
/*
* @brief Release the software and hardware resources tied to a job ring.
* @param [in] job_ring The job ring
* @retval 0 for success
* @retval -1 for error
*/
int shutdown_job_ring(struct sec_job_ring_t *job_ring);
/*
* @brief Enable irqs on associated job ring.
* @param [in] job_ring The job ring
* @retval 0 for success
* @retval -1 for error
*/
int jr_enable_irqs(struct sec_job_ring_t *job_ring);
/*
* @brief Disable irqs on associated job ring.
* @param [in] job_ring The job ring
* @retval 0 for success
* @retval -1 for error
*/
int jr_disable_irqs(struct sec_job_ring_t *job_ring);
/*
* IRJA - Input Ring Jobs Added Register shows
* how many new jobs were added to the Input Ring.
*/
static inline void hw_enqueue_desc_on_job_ring(struct jobring_regs *regs,
int num)
{
sec_out32(&regs->irja, num);
}
#endif /* _SEC_HW_SPECIFIC_H_ */
/*
* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef _JR_DRIVER_H_
#define _JR_DRIVER_H_
#include "jr_driver_config.h"
/* The maximum size of a SEC descriptor, in WORDs (32 bits). */
#define MAX_DESC_SIZE_WORDS 64
#define CAAM_TIMEOUT 200000 /* ms */
/* Return codes for JR user space driver APIs */
typedef enum sec_return_code_e {
SEC_SUCCESS = 0,
SEC_INVALID_INPUT_PARAM,
SEC_OUT_OF_MEMORY,
SEC_DESCRIPTOR_IN_FLIGHT,
SEC_LAST_DESCRIPTOR_IN_FLIGHT,
SEC_PROCESSING_ERROR,
SEC_DESC_PROCESSING_ERROR,
SEC_JR_IS_FULL,
SEC_DRIVER_RELEASE_IN_PROGRESS,
SEC_DRIVER_ALREADY_INITIALIZED,
SEC_DRIVER_NOT_INITIALIZED,
SEC_JOB_RING_RESET_IN_PROGRESS,
SEC_RESET_ENGINE_FAILED,
SEC_ENABLE_IRQS_FAILED,
SEC_DISABLE_IRQS_FAILED,
SEC_RETURN_CODE_MAX_VALUE,
} sec_return_code_t;
/* STRUCTURES AND OTHER TYPEDEFS */
/*
* @brief Function called by JR User Space driver to notify every processed
* descriptor.
*
* Callback provided by the User Application.
* Callback is invoked by JR User Space driver for each descriptor processed by
* SEC
* @param [in] status Status word indicating processing result for
* this descriptor.
* @param [in] arg Opaque data passed by User Application
* It is opaque from JR driver's point of view.
* @param [in] job_ring The job ring handle on which the processed
* descriptor word was enqueued
*/
typedef void (*user_callback) (uint32_t *desc, uint32_t status,
void *arg, void *job_ring);
/*
* Structure encompassing a job descriptor which is to be processed
* by SEC. User should also initialise this structure with the callback
* function pointer which will be called by driver after recieving proccessed
* descriptor from SEC. User data is also passed in this data structure which
* will be sent as an argument to the user callback function.
*/
struct job_descriptor {
uint32_t desc[MAX_DESC_SIZE_WORDS];
void *arg;
user_callback callback;
};
/*
* @brief Initialize the JR User Space driver.
* This function will handle initialization of sec library
* along with registering platform specific callbacks,
* as well as local data initialization.
* Call once during application startup.
* @note Global SEC initialization is done in SEC kernel driver.
* @note The hardware IDs of the initialized Job Rings are opaque to the UA.
* The exact Job Rings used by this library are decided between SEC user
* space driver and SEC kernel driver. A static partitioning of Job Rings is
* assumed, configured in DTS(device tree specification) file.
* @param [in] platform_cb Registering the platform specific
* callbacks with driver
* @retval ::0 for successful execution
* @retval ::-1 failure
*/
int sec_jr_lib_init(void);
/*
* @brief Initialize the software and hardware resources tied to a job ring.
* @param [in] jr_mode; Model to be used by SEC Driver to receive
* notifications from SEC. Can be either
* SEC_NOTIFICATION_TYPE_IRQ or
* SEC_NOTIFICATION_TYPE_POLL
* @param [in] irq_coalescing_timer This value determines the maximum
* amount of time after processing a
* descriptor before raising an interrupt.
* @param [in] irq_coalescing_count This value determines how many
* descriptors are completed before
* raising an interrupt.
* @param [in] reg_base_addr The job ring base address register
* @param [in] irq_id The job ring interrupt identification number.
* @retval job_ring_handle for successful job ring configuration
* @retval NULL on error
*/
void *init_job_ring(uint8_t jr_mode,
uint16_t irq_coalescing_timer,
uint8_t irq_coalescing_count,
void *reg_base_addr, uint32_t irq_id);
/*
* @brief Release the resources used by the JR User Space driver.
* Reset and release SEC's job rings indicated by the User Application at
* init_job_ring() and free any memory allocated internally.
* Call once during application tear down.
* @note In case there are any descriptors in-flight (descriptors received by
* JR driver for processing and for which no response was yet provided to UA),
* the descriptors are discarded without any notifications to User Application.
* @retval ::0 is returned for a successful execution
* @retval ::-1 is returned if JR driver release is in progress
*/
int sec_release(void);
/*
* @brief Submit a descriptor for SEC processing.
* This function creates a "job" which is meant to instruct SEC HW
* to perform the processing on the input buffer. The "job" is enqueued
* in the Job Ring associated. The function will return after the "job"
* enqueue is finished. The function will not wait for SEC to
* start or/and finish the "job" processing.
* After the processing is finished the SEC HW writes the processing result
* to the provided output buffer.
* The Caller must poll JR driver using jr_dequeue()
* to receive notifications of the processing completion
* status. The notifications are received by caller by means of callback
* (see ::user_callback).
* @param [in] job_ring_handle The handle of the job ring on which
* descriptor is to be enqueued
* @param [in] job_descriptor The job descriptor structure of type
* struct job_descriptor. This structure
* should be filled with job descriptor along
* with callback function to be called after
* processing of descriptor and some
* opaque data passed to be passed to the
* callback function
*
* @retval ::0 is returned for successful execution
* @retval ::-1 is returned if there is some enqueue failure
*/
int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr);
/*
* @brief Polls for available descriptors processed by SEC on a specific
* Job Ring
* This function polls the SEC Job Rings and delivers processed descriptors
* Each processed descriptor has a user_callback registered.
* This user_callback is invoked for each processed descriptor.
* The polling is stopped when "limit" descriptors are notified or when
* there are no more descriptors to notify.
* @note The dequeue_jr() API cannot be called from within a user_callback
* function
* @param [in] job_ring_handle The Job Ring handle.
* @param [in] limit This value represents the maximum number
* of processed descriptors that can be
* notified API call on this Job Ring.
* Note that fewer descriptors may be notified
* if enough processed descriptors are not
* available.
* If limit has a negative value, then all
* ready descriptors will be notified.
*
* @retval :: >=0 is returned where retval is the total
* Number of descriptors notified
* during this function call.
* @retval :: -1 is returned in case of some error
*/
int dequeue_jr(void *job_ring_handle, int32_t limit);
#endif /* _JR_DRIVER_H_ */
#
# Copyright 2018-2020 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
#
SEC_DRIVERS_PATH := drivers/nxp/crypto/caam
ifeq (${TRUSTED_BOARD_BOOT},1)
AUTH_SOURCES += $(wildcard $(SEC_DRIVERS_PATH)/src/auth/*.c)
endif
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arch_helpers.h>
#include "caam.h"
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include "hash.h"
#include "jobdesc.h"
#include "sec_hw_specific.h"
/* Since no Allocator is available . Taking a global static ctx.
* This would mean that only one active ctx can be there at a time.
*/
static struct hash_ctx glbl_ctx;
static void hash_done(uint32_t *desc, uint32_t status, void *arg,
void *job_ring)
{
INFO("Hash Desc SUCCESS with status %x\n", status);
}
/***************************************************************************
* Function : hash_init
* Arguments : ctx - SHA context
* Return : init,
* Description : This function initializes the context for SHA calculation
***************************************************************************/
int hash_init(enum hash_algo algo, void **ctx)
{
if (glbl_ctx.active == false) {
memset(&glbl_ctx, 0, sizeof(struct hash_ctx));
glbl_ctx.active = true;
glbl_ctx.algo = algo;
*ctx = &glbl_ctx;
return 0;
} else {
return -1;
}
}
/***************************************************************************
* Function : hash_update
* Arguments : ctx - SHA context
* buffer - Data
* length - Length
* Return : -1 on error
* 0 on SUCCESS
* Description : This function creates SG entry of the data provided
***************************************************************************/
int hash_update(enum hash_algo algo, void *context, void *data_ptr,
unsigned int data_len)
{
struct hash_ctx *ctx = context;
/* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */
if (ctx->sg_num >= MAX_SG) {
ERROR("Reached limit for calling %s\n", __func__);
ctx->active = false;
return -EINVAL;
}
if (ctx->algo != algo) {
ERROR("ctx for algo not correct\n");
ctx->active = false;
return -EINVAL;
}
#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
flush_dcache_range((uintptr_t)data_ptr, data_len);
dmbsy();
#endif
#ifdef CONFIG_PHYS_64BIT
sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi,
(uint32_t) ((uintptr_t) data_ptr >> 32));
#else
sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0);
#endif
sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr);
sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
(data_len & SG_ENTRY_LENGTH_MASK));
ctx->sg_num++;
ctx->len += data_len;
return 0;
}
/***************************************************************************
* Function : hash_final
* Arguments : ctx - SHA context
* Return : SUCCESS or FAILURE
* Description : This function sets the final bit and enqueues the decriptor
***************************************************************************/
int hash_final(enum hash_algo algo, void *context, void *hash_ptr,
unsigned int hash_len)
{
int ret = 0;
struct hash_ctx *ctx = context;
uint32_t final = 0U;
struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);
jobdesc.arg = NULL;
jobdesc.callback = hash_done;
if (ctx->algo != algo) {
ERROR("ctx for algo not correct\n");
ctx->active = false;
return -EINVAL;
}
final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) |
SG_ENTRY_FINAL_BIT;
sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final);
dsb();
/* create the hw_rng descriptor */
cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl,
ctx->len, hash_ptr);
#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
flush_dcache_range((uintptr_t)ctx->sg_tbl,
(sizeof(struct sg_entry) * MAX_SG));
inv_dcache_range((uintptr_t)hash_ptr, hash_len);
dmbsy();
#endif
/* Finally, generate the requested random data bytes */
ret = run_descriptor_jr(&jobdesc);
if (ret != 0) {
ERROR("Error in running descriptor\n");
ret = -1;
}
ctx->active = false;
return ret;
}
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <stddef.h>
#include <string.h>
#include "caam.h"
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include "hash.h"
#include "rsa.h"
#define LIB_NAME "NXP crypto"
/*
* Initialize the library and export the descriptor
*/
static void init(void)
{
/* Initialize NXP crypto library`:*/
NOTICE("Initializing & configuring SEC block.\n");
if (config_sec_block() < 0) {
ERROR("Init & config failure for caam.\n");
}
}
/*
* Verify a signature.
*
* For IMG_PLAT - data points to a PKCS#1.5 encoded HASH
* sig_alg will be RSA or ECC
* Parameters are passed using the DER encoding format following the ASN.1
* structures detailed above.
*/
static int verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sign_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
int ret = CRYPTO_SUCCESS;
enum sig_alg alg = *(enum sig_alg *)sign_alg;
switch (alg) {
case RSA:
NOTICE("Verifying RSA\n");
ret = rsa_verify_signature(data_ptr, data_len, sig_ptr, sig_len,
pk_ptr, pk_len);
break;
case ECC:
default:
ret = CRYPTO_ERR_SIGNATURE;
break;
}
if (ret != 0) {
ERROR("RSA verification Failed\n");
}
return ret;
}
/*
* Match a hash
*
* Digest info is passed as a table of SHA-26 hashes and digest_info_len
* is number of entries in the table
* This implementation is very specific to the CSF header parser ROTPK
* comparison.
*/
static int verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len)
{
void *ctx = NULL;
int i = 0, ret = 0;
enum hash_algo algo = SHA256;
uint8_t hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE) = {0};
uint32_t digest_size = SHA256_BYTES;
uint8_t *hash_tbl = digest_info_ptr;
NOTICE("Verifying hash\n");
ret = hash_init(algo, &ctx);
if (ret != 0) {
return CRYPTO_ERR_HASH;
}
/* Update hash with that of SRK table */
ret = hash_update(algo, ctx, data_ptr, data_len);
if (ret != 0) {
return CRYPTO_ERR_HASH;
}
/* Copy hash at destination buffer */
ret = hash_final(algo, ctx, hash, digest_size);
if (ret != 0) {
return CRYPTO_ERR_HASH;
}
VERBOSE("%s Calculated hash\n", __func__);
for (i = 0; i < SHA256_BYTES/4; i++) {
VERBOSE("%x\n", *((uint32_t *)hash + i));
}
for (i = 0; i < digest_info_len; i++) {
if (memcmp(hash, (hash_tbl + (i * digest_size)),
digest_size) == 0) {
return CRYPTO_SUCCESS;
}
}
return CRYPTO_ERR_HASH;
}
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arch_helpers.h>
#include "caam.h"
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include "jobdesc.h"
#include "rsa.h"
#include "sec_hw_specific.h"
/* This array contains DER value for SHA-256 */
static const uint8_t hash_identifier[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
0x04, 0x20
};
static void rsa_done(uint32_t *desc, uint32_t status, void *arg,
void *job_ring)
{
INFO("RSA Desc SUCCESS with status %x\n", status);
}
static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to,
uint8_t *rsa_pub_key, uint32_t klen)
{
int ret = 0;
struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE);
struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);
jobdesc.arg = NULL;
jobdesc.callback = rsa_done;
memset(&ctx, 0, sizeof(struct rsa_context));
ctx.pkin.a = sign;
ctx.pkin.a_siz = klen;
ctx.pkin.n = rsa_pub_key;
ctx.pkin.n_siz = klen;
ctx.pkin.e = rsa_pub_key + klen;
ctx.pkin.e_siz = klen;
cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen);
#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
flush_dcache_range((uintptr_t)sign, klen);
flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen);
flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin));
inv_dcache_range((uintptr_t)to, klen);
dmbsy();
dsbsy();
isb();
#endif
/* Finally, generate the requested random data bytes */
ret = run_descriptor_jr(&jobdesc);
if (ret != 0) {
ERROR("Error in running descriptor\n");
ret = -1;
}
#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
inv_dcache_range((uintptr_t)to, klen);
dmbsy();
dsbsy();
isb();
#endif
return ret;
}
/*
* Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
* pointers for padding, DER value and hash. And finally, constructs EM'
* which includes hash of complete CSF header and ESBC image. If SG flag
* is on, hash of SG table and entries is also included.
*/
static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len,
uint8_t *encoded_hash_second,
unsigned int key_len)
{
/*
* RSA PKCSv1.5 encoding format for encoded message is below
* EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
* PS is Padding String
* DER is DER value for SHA-256
* Hash is SHA-256 hash
* *********************************************************
* representative points to first byte of EM initially and is
* filled with 0x0
* representative is incremented by 1 and second byte is filled
* with 0x1
* padding points to third byte of EM
* digest points to full length of EM - 32 bytes
* hash_id (DER value) points to 19 bytes before pDigest
* separator is one byte which separates padding and DER
*/
unsigned int len;
uint8_t *representative;
uint8_t *padding, *digest;
uint8_t *hash_id, *separator;
int i;
int ret = 0;
if (hash_len != SHA256_BYTES) {
return -1;
}
/* Key length = Modulus length */
len = (key_len / 2U) - 1U;
representative = encoded_hash_second;
representative[0] = 0U;
representative[1] = 1U; /* block type 1 */
padding = &representative[2];
digest = &representative[1] + len - 32;
hash_id = digest - sizeof(hash_identifier);
separator = hash_id - 1;
/* fill padding area pointed by padding with 0xff */
memset(padding, 0xff, separator - padding);
/* fill byte pointed by separator */
*separator = 0U;
/* fill SHA-256 DER value pointed by HashId */
memcpy(hash_id, hash_identifier, sizeof(hash_identifier));
/* fill hash pointed by Digest */
for (i = 0; i < SHA256_BYTES; i++) {
digest[i] = hash[i];
}
return ret;
}
int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
void *sig_ptr, unsigned int sig_len,
void *pk_ptr, unsigned int pk_len)
{
uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES];
uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
int ret = 0;
ret = construct_img_encoded_hash_second(hash_ptr, hash_len,
img_encoded_hash_second,
pk_len);
if (ret != 0) {
ERROR("Encoded Hash Failure\n");
return CRYPTO_ERR_SIGNATURE;
}
ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2);
if (ret != 0) {
ERROR("RSA signature Failure\n");
return CRYPTO_ERR_SIGNATURE;
}
ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len);
if (ret != 0) {
ERROR("Comparison Failure\n");
return CRYPTO_ERR_SIGNATURE;
}
return CRYPTO_SUCCESS;
}
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arch_helpers.h>
#include "caam.h"
#include <common/debug.h>
#include "jobdesc.h"
#include "sec_hw_specific.h"
static uintptr_t g_nxp_caam_addr;
static void *job_ring;
uintptr_t get_caam_addr(void)
{
if (g_nxp_caam_addr == 0) {
ERROR("Sec Init is not done.\n");
panic();
}
return g_nxp_caam_addr;
}
/* This function sets the TZ bit for the Job ring number passed as @num */
static void config_tz(int num)
{
uint32_t jricid;
/* Setting TZ bit of job ring */
switch (num) {
case 0:
jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET);
sec_out32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET,
jricid | JRICID_MS_TZ);
break;
case 1:
jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET);
sec_out32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET,
jricid | JRICID_MS_TZ);
break;
case 2:
jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET);
sec_out32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET,
jricid | JRICID_MS_TZ);
break;
case 3:
jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET);
sec_out32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET,
jricid | JRICID_MS_TZ);
break;
default:
break;
}
}
/* This function checks if Virtualization is enabled for JR and
* accordingly sets the bot for starting JR<num> in JRSTARTR register
*/
static inline void start_jr(int num)
{
uint32_t ctpr = sec_in32((g_nxp_caam_addr + SEC_REG_CTPR_MS_OFFSET));
uint32_t tmp = sec_in32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET));
uint32_t scfgr = sec_in32((g_nxp_caam_addr + SEC_REG_SCFGR_OFFSET));
bool start = false;
if ((ctpr & CTPR_VIRT_EN_INC) != 0U) {
if (((ctpr & CTPR_VIRT_EN_POR) != 0U) ||
((scfgr & SCFGR_VIRT_EN) != 0U)) {
start = true;
}
} else {
if ((ctpr & CTPR_VIRT_EN_POR) != 0U) {
start = true;
}
}
if (start == true) {
switch (num) {
case 0:
tmp |= JRSTARTR_STARTJR0;
break;
case 1:
tmp |= JRSTARTR_STARTJR1;
break;
case 2:
tmp |= JRSTARTR_STARTJR2;
break;
case 3:
tmp |= JRSTARTR_STARTJR3;
break;
default:
break;
}
}
sec_out32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET), tmp);
}
/* This functions configures the Job Ring
* JR3 is reserved for use by Secure world
*/
static int configure_jr(int num)
{
int ret;
void *reg_base_addr;
switch (num) {
case 0:
reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR0_OFFSET);
break;
case 1:
reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR1_OFFSET);
break;
case 2:
reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR2_OFFSET);
break;
case 3:
reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR3_OFFSET);
break;
default:
break;
}
/* Initialize the JR library */
ret = sec_jr_lib_init();
if (ret != 0) {
ERROR("Error in sec_jr_lib_init");
return -1;
}
start_jr(num);
/* Do HW configuration of the JR */
job_ring = init_job_ring(SEC_NOTIFICATION_TYPE_POLL, 0, 0,
reg_base_addr, 0);
if (job_ring == NULL) {
ERROR("Error in init_job_ring");
return -1;
}
return ret;
}
/* TBD - Configures and locks the ICID values for various JR */
static inline void configure_icid(void)
{
}
/* TBD configures the TZ settings of RTIC */
static inline void configure_rtic(void)
{
}
int sec_init(uintptr_t nxp_caam_addr)
{
g_nxp_caam_addr = nxp_caam_addr;
return config_sec_block();
}
/* This function configure SEC block:
* - It does basic parameter setting
* - Configures the default Job ring assigned to TZ /secure world
* - Instantiates the RNG
*/
int config_sec_block(void)
{
int ret = 0;
uint32_t mcfgr;
if (g_nxp_caam_addr == 0) {
ERROR("Sec Init is not done.\n");
return -1;
} else if (job_ring != NULL) {
NOTICE("Sec is already initialized and configured.\n");
return ret;
}
mcfgr = sec_in32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET);
/* Modify CAAM Read/Write attributes
* AXI Write - Cacheable, WB and WA
* AXI Read - Cacheable, RA
*/
#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS2088A)
mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0xb << MCFGR_AWCACHE_SHIFT);
mcfgr = (mcfgr & ~MCFGR_ARCACHE_MASK) | (0x6 << MCFGR_ARCACHE_SHIFT);
#else
mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT);
#endif
/* Set PS bit to 1 */
#ifdef CONFIG_PHYS_64BIT
mcfgr |= (1 << MCFGR_PS_SHIFT);
#endif
sec_out32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET, mcfgr);
/* Asssign ICID to all Job rings and lock them for usage */
configure_icid();
/* Configure the RTIC */
configure_rtic();
/* Configure the default JR for usage */
ret = configure_jr(DEFAULT_JR);
if (ret != 0) {
ERROR("\nFSL_JR: configuration failure\n");
return -1;
}
/* Do TZ configuration of default JR for sec firmware */
config_tz(DEFAULT_JR);
#ifdef CONFIG_RNG_INIT
/* Instantiate the RNG */
ret = hw_rng_instantiate();
if (ret != 0) {
ERROR("\nRNG Instantiation failure\n");
return -1;
}
#endif
return ret;
}
/* This function is used for sumbitting job to the Job Ring
* [param] [in] - jobdesc to be submitted
* Return - -1 in case of error and 0 in case of SUCCESS
*/
int run_descriptor_jr(struct job_descriptor *jobdesc)
{
int i = 0, ret = 0;
uint32_t *desc_addr = jobdesc->desc;
uint32_t desc_len = desc_length(jobdesc->desc);
uint32_t desc_word;
for (i = 0; i < desc_len; i++) {
desc_word = desc_addr[i];
VERBOSE("%x\n", desc_word);
sec_out32((uint32_t *)&desc_addr[i], desc_word);
}
dsb();
#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
flush_dcache_range((uintptr_t)desc_addr, desc_len * 4);
dmbsy();
dsbsy();
isb();
#endif
ret = enq_jr_desc(job_ring, jobdesc);
if (ret == 0) {
VERBOSE("JR enqueue done...\n");
} else {
ERROR("Error in Enqueue\n");
return ret;
}
VERBOSE("Dequeue in progress");
ret = dequeue_jr(job_ring, -1);
if (ret >= 0) {
VERBOSE("Dequeue of %x desc success\n", ret);
ret = 0;
} else {
ERROR("deq_ret %x\n", ret);
ret = -1;
}
return ret;
}
/* this function returns a random number using HW RNG Algo
* In case of failure, random number returned is 0
* prngWidth = 0 - 32 bit random number
* prngWidth > 0 means 64 bit random number
*/
unsigned long long get_random(int rngWidth)
{
unsigned long long result = 0;
uint8_t rand_byte[64] __aligned(CACHE_WRITEBACK_GRANULE);
uint8_t rand_byte_swp[8];
int bytes = 0;
int i = 0;
int ret = 0;
#ifdef CAAM_TEST
rand_byte[0] = U(0x12);
rand_byte[1] = U(0x34);
rand_byte[2] = U(0x56);
rand_byte[3] = U(0x78);
rand_byte[4] = U(0x9a);
rand_byte[5] = U(0xbc);
rand_byte[6] = U(0xde);
rand_byte[7] = U(0xf1);
#endif
if (rngWidth == 0U) {
bytes = 4;
} else {
bytes = 8;
}
memset(rand_byte, 0, 64);
ret = get_rand_bytes_hw(rand_byte, bytes);
for (i = 0; i < bytes; i++) {
if (ret != 0) {
/* Return 0 in case of failure */
rand_byte_swp[i] = 0;
} else {
rand_byte_swp[i] = rand_byte[bytes - i - 1];
result = (result << 8) | rand_byte_swp[i];
}
}
INFO("result %llx\n", result);
return result;
} /* _get_RNG() */
unsigned int _get_hw_unq_key(uint64_t hw_key_phy_addr, unsigned int size)
{
int ret = 0;
uint8_t *hw_key = (uint8_t *) ptov((phys_addr_t *) hw_key_phy_addr);
ret = get_hw_unq_key_blob_hw(hw_key, size);
return ret;
}
/*
* Copyright 2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "caam.h"
#include <common/debug.h>
#include "jobdesc.h"
#include "sec_hw_specific.h"
/* Callback function after Instantiation decsriptor is submitted to SEC
*/
static void blob_done(uint32_t *desc, uint32_t status, void *arg,
void *job_ring)
{
INFO("Blob Desc SUCCESS with status %x\n", status);
}
/* @brief Submit descriptor to create blob
* @retval 0 on success
* @retval -1 on error
*/
int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size)
{
int ret = 0;
int i = 0;
uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
uint8_t key_data[KEY_IDNFR_SZ_BYTES];
uint8_t in_data[16];
uint8_t out_data[16 + KEY_BLOB_SIZE + MAC_SIZE];
struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
struct job_descriptor *jobdesc = &desc;
uint32_t in_sz = 16U;
/* Output blob will have 32 bytes key blob in beginning and
* 16 byte HMAC identifier at end of data blob
*/
uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
uint32_t operation = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL |
OP_PCLID_BLOB | BLOB_PROTO_INFO;
memset(key_data, 0xff, KEY_IDNFR_SZ_BYTES);
memset(in_data, 0x00, in_sz);
memset(out_data, 0x00, in_sz);
jobdesc->arg = NULL;
jobdesc->callback = blob_done;
INFO("\nGenerating Master Key Verification Blob.\n");
/* Create the hw_rng descriptor */
ret = cnstr_hw_encap_blob_jobdesc(jobdesc->desc, key_data, key_sz,
CLASS_2, in_data, in_sz, out_data,
out_sz, operation);
/* Finally, generate the blob. */
ret = run_descriptor_jr(jobdesc);
if (ret != 0) {
ERROR("Error in running hw unq key blob descriptor\n");
return -1;
}
/* Copying alternate bytes of the Master Key Verification Blob.
*/
for (i = 0; i < size; i++) {
hw_key[i] = out_data[2 * i];
}
return ret;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <endian.h>
#include <common/debug.h>
#include <csu.h>
#include <lib/mmio.h>
void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev,
uint32_t num, uintptr_t nxp_csu_addr)
{
uint32_t *base = (uint32_t *)nxp_csu_addr;
uint32_t *reg;
uint32_t val;
int i;
for (i = 0; i < num; i++) {
reg = base + csu_ns_dev[i].ind / 2U;
val = be32toh(mmio_read_32((uintptr_t)reg));
if (csu_ns_dev[i].ind % 2U == 0U) {
val &= 0x0000ffffU;
val |= csu_ns_dev[i].val << 16U;
} else {
val &= 0xffff0000U;
val |= csu_ns_dev[i].val;
}
mmio_write_32((uintptr_t)reg, htobe32(val));
}
}
/*
* Copyright 2020 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef CSU_H
#define CSU_H
#define CSU_SEC_ACCESS_REG_OFFSET (0x0021CU)
/* Macros defining access permissions to configure
* the regions controlled by Central Security Unit.
*/
enum csu_cslx_access {
CSU_NS_SUP_R = (0x8U),
CSU_NS_SUP_W = (0x80U),
CSU_NS_SUP_RW = (0x88U),
CSU_NS_USER_R = (0x4U),
CSU_NS_USER_W = (0x40U),
CSU_NS_USER_RW = (0x44U),
CSU_S_SUP_R = (0x2U),
CSU_S_SUP_W = (0x20U),
CSU_S_SUP_RW = (0x22U),
CSU_S_USER_R = (0x1U),
CSU_S_USER_W = (0x10U),
CSU_S_USER_RW = (0x11U),
CSU_ALL_RW = (0xffU),
};
struct csu_ns_dev_st {
uintptr_t ind;
uint32_t val;
};
void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev,
uint32_t num, uintptr_t nxp_csu_addr);
#endif
#
# Copyright 2020 NXP
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-----------------------------------------------------------------------------
ifeq (${CSU_ADDED},)
CSU_ADDED := 1
CSU_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/csu
PLAT_INCLUDES += -I$(CSU_DRIVERS_PATH)
CSU_SOURCES += $(CSU_DRIVERS_PATH)/csu.c
ifeq (${BL_COMM_CSU_NEEDED},yes)
BL_COMMON_SOURCES += ${CSU_SOURCES}
else
ifeq (${BL2_CSU_NEEDED},yes)
BL2_SOURCES += ${CSU_SOURCES}
endif
ifeq (${BL31_CSU_NEEDED},yes)
BL31_SOURCES += ${CSU_SOURCES}
endif
endif
endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment