1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022, STMicroelectronics - All Rights Reserved 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu #include <assert.h> 7*91f16700Schasinglulu #include <endian.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <drivers/clk.h> 12*91f16700Schasinglulu #include <drivers/delay_timer.h> 13*91f16700Schasinglulu #include <drivers/st/stm32_saes.h> 14*91f16700Schasinglulu #include <drivers/st/stm32mp_reset.h> 15*91f16700Schasinglulu #include <lib/mmio.h> 16*91f16700Schasinglulu #include <lib/utils_def.h> 17*91f16700Schasinglulu #include <libfdt.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include <platform_def.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #define UINT8_BIT 8U 22*91f16700Schasinglulu #define AES_BLOCK_SIZE_BIT 128U 23*91f16700Schasinglulu #define AES_BLOCK_SIZE (AES_BLOCK_SIZE_BIT / UINT8_BIT) 24*91f16700Schasinglulu 25*91f16700Schasinglulu #define AES_KEYSIZE_128 16U 26*91f16700Schasinglulu #define AES_KEYSIZE_256 32U 27*91f16700Schasinglulu #define AES_IVSIZE 16U 28*91f16700Schasinglulu 29*91f16700Schasinglulu /* SAES control register */ 30*91f16700Schasinglulu #define _SAES_CR 0x0U 31*91f16700Schasinglulu /* SAES status register */ 32*91f16700Schasinglulu #define _SAES_SR 0x04U 33*91f16700Schasinglulu /* SAES data input register */ 34*91f16700Schasinglulu #define _SAES_DINR 0x08U 35*91f16700Schasinglulu /* SAES data output register */ 36*91f16700Schasinglulu #define _SAES_DOUTR 0x0CU 37*91f16700Schasinglulu /* SAES key registers [0-3] */ 38*91f16700Schasinglulu #define _SAES_KEYR0 0x10U 39*91f16700Schasinglulu #define _SAES_KEYR1 0x14U 40*91f16700Schasinglulu #define _SAES_KEYR2 0x18U 41*91f16700Schasinglulu #define _SAES_KEYR3 0x1CU 42*91f16700Schasinglulu /* SAES initialization vector registers [0-3] */ 43*91f16700Schasinglulu #define _SAES_IVR0 0x20U 44*91f16700Schasinglulu #define _SAES_IVR1 0x24U 45*91f16700Schasinglulu #define _SAES_IVR2 0x28U 46*91f16700Schasinglulu #define _SAES_IVR3 0x2CU 47*91f16700Schasinglulu /* SAES key registers [4-7] */ 48*91f16700Schasinglulu #define _SAES_KEYR4 0x30U 49*91f16700Schasinglulu #define _SAES_KEYR5 0x34U 50*91f16700Schasinglulu #define _SAES_KEYR6 0x38U 51*91f16700Schasinglulu #define _SAES_KEYR7 0x3CU 52*91f16700Schasinglulu /* SAES suspend registers [0-7] */ 53*91f16700Schasinglulu #define _SAES_SUSPR0 0x40U 54*91f16700Schasinglulu #define _SAES_SUSPR1 0x44U 55*91f16700Schasinglulu #define _SAES_SUSPR2 0x48U 56*91f16700Schasinglulu #define _SAES_SUSPR3 0x4CU 57*91f16700Schasinglulu #define _SAES_SUSPR4 0x50U 58*91f16700Schasinglulu #define _SAES_SUSPR5 0x54U 59*91f16700Schasinglulu #define _SAES_SUSPR6 0x58U 60*91f16700Schasinglulu #define _SAES_SUSPR7 0x5CU 61*91f16700Schasinglulu /* SAES Interrupt Enable Register */ 62*91f16700Schasinglulu #define _SAES_IER 0x300U 63*91f16700Schasinglulu /* SAES Interrupt Status Register */ 64*91f16700Schasinglulu #define _SAES_ISR 0x304U 65*91f16700Schasinglulu /* SAES Interrupt Clear Register */ 66*91f16700Schasinglulu #define _SAES_ICR 0x308U 67*91f16700Schasinglulu 68*91f16700Schasinglulu /* SAES control register fields */ 69*91f16700Schasinglulu #define _SAES_CR_RESET_VALUE 0x0U 70*91f16700Schasinglulu #define _SAES_CR_IPRST BIT(31) 71*91f16700Schasinglulu #define _SAES_CR_KEYSEL_MASK GENMASK(30, 28) 72*91f16700Schasinglulu #define _SAES_CR_KEYSEL_SHIFT 28U 73*91f16700Schasinglulu #define _SAES_CR_KEYSEL_SOFT 0x0U 74*91f16700Schasinglulu #define _SAES_CR_KEYSEL_DHUK 0x1U 75*91f16700Schasinglulu #define _SAES_CR_KEYSEL_BHK 0x2U 76*91f16700Schasinglulu #define _SAES_CR_KEYSEL_BHU_XOR_BH_K 0x4U 77*91f16700Schasinglulu #define _SAES_CR_KEYSEL_TEST 0x7U 78*91f16700Schasinglulu #define _SAES_CR_KSHAREID_MASK GENMASK(27, 26) 79*91f16700Schasinglulu #define _SAES_CR_KSHAREID_SHIFT 26U 80*91f16700Schasinglulu #define _SAES_CR_KSHAREID_CRYP 0x0U 81*91f16700Schasinglulu #define _SAES_CR_KEYMOD_MASK GENMASK(25, 24) 82*91f16700Schasinglulu #define _SAES_CR_KEYMOD_SHIFT 24U 83*91f16700Schasinglulu #define _SAES_CR_KEYMOD_NORMAL 0x0U 84*91f16700Schasinglulu #define _SAES_CR_KEYMOD_WRAPPED 0x1U 85*91f16700Schasinglulu #define _SAES_CR_KEYMOD_SHARED 0x2U 86*91f16700Schasinglulu #define _SAES_CR_NPBLB_MASK GENMASK(23, 20) 87*91f16700Schasinglulu #define _SAES_CR_NPBLB_SHIFT 20U 88*91f16700Schasinglulu #define _SAES_CR_KEYPROT BIT(19) 89*91f16700Schasinglulu #define _SAES_CR_KEYSIZE BIT(18) 90*91f16700Schasinglulu #define _SAES_CR_GCMPH_MASK GENMASK(14, 13) 91*91f16700Schasinglulu #define _SAES_CR_GCMPH_SHIFT 13U 92*91f16700Schasinglulu #define _SAES_CR_GCMPH_INIT 0U 93*91f16700Schasinglulu #define _SAES_CR_GCMPH_HEADER 1U 94*91f16700Schasinglulu #define _SAES_CR_GCMPH_PAYLOAD 2U 95*91f16700Schasinglulu #define _SAES_CR_GCMPH_FINAL 3U 96*91f16700Schasinglulu #define _SAES_CR_DMAOUTEN BIT(12) 97*91f16700Schasinglulu #define _SAES_CR_DMAINEN BIT(11) 98*91f16700Schasinglulu #define _SAES_CR_CHMOD_MASK (BIT(16) | GENMASK(6, 5)) 99*91f16700Schasinglulu #define _SAES_CR_CHMOD_SHIFT 5U 100*91f16700Schasinglulu #define _SAES_CR_CHMOD_ECB 0x0U 101*91f16700Schasinglulu #define _SAES_CR_CHMOD_CBC 0x1U 102*91f16700Schasinglulu #define _SAES_CR_CHMOD_CTR 0x2U 103*91f16700Schasinglulu #define _SAES_CR_CHMOD_GCM 0x3U 104*91f16700Schasinglulu #define _SAES_CR_CHMOD_GMAC 0x3U 105*91f16700Schasinglulu #define _SAES_CR_CHMOD_CCM 0x800U 106*91f16700Schasinglulu #define _SAES_CR_MODE_MASK GENMASK(4, 3) 107*91f16700Schasinglulu #define _SAES_CR_MODE_SHIFT 3U 108*91f16700Schasinglulu #define _SAES_CR_MODE_ENC 0U 109*91f16700Schasinglulu #define _SAES_CR_MODE_KEYPREP 1U 110*91f16700Schasinglulu #define _SAES_CR_MODE_DEC 2U 111*91f16700Schasinglulu #define _SAES_CR_DATATYPE_MASK GENMASK(2, 1) 112*91f16700Schasinglulu #define _SAES_CR_DATATYPE_SHIFT 1U 113*91f16700Schasinglulu #define _SAES_CR_DATATYPE_NONE 0U 114*91f16700Schasinglulu #define _SAES_CR_DATATYPE_HALF_WORD 1U 115*91f16700Schasinglulu #define _SAES_CR_DATATYPE_BYTE 2U 116*91f16700Schasinglulu #define _SAES_CR_DATATYPE_BIT 3U 117*91f16700Schasinglulu #define _SAES_CR_EN BIT(0) 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* SAES status register fields */ 120*91f16700Schasinglulu #define _SAES_SR_KEYVALID BIT(7) 121*91f16700Schasinglulu #define _SAES_SR_BUSY BIT(3) 122*91f16700Schasinglulu #define _SAES_SR_WRERR BIT(2) 123*91f16700Schasinglulu #define _SAES_SR_RDERR BIT(1) 124*91f16700Schasinglulu #define _SAES_SR_CCF BIT(0) 125*91f16700Schasinglulu 126*91f16700Schasinglulu /* SAES interrupt registers fields */ 127*91f16700Schasinglulu #define _SAES_I_RNG_ERR BIT(3) 128*91f16700Schasinglulu #define _SAES_I_KEY_ERR BIT(2) 129*91f16700Schasinglulu #define _SAES_I_RW_ERR BIT(1) 130*91f16700Schasinglulu #define _SAES_I_CC BIT(0) 131*91f16700Schasinglulu 132*91f16700Schasinglulu #define SAES_TIMEOUT_US 100000U 133*91f16700Schasinglulu #define TIMEOUT_US_1MS 1000U 134*91f16700Schasinglulu #define SAES_RESET_DELAY 20U 135*91f16700Schasinglulu 136*91f16700Schasinglulu #define IS_CHAINING_MODE(mod, cr) \ 137*91f16700Schasinglulu (((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT)) 138*91f16700Schasinglulu 139*91f16700Schasinglulu #define SET_CHAINING_MODE(mod, cr) \ 140*91f16700Schasinglulu mmio_clrsetbits_32((cr), _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT) 141*91f16700Schasinglulu 142*91f16700Schasinglulu static struct stm32_saes_platdata saes_pdata; 143*91f16700Schasinglulu 144*91f16700Schasinglulu static int stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata) 145*91f16700Schasinglulu { 146*91f16700Schasinglulu int node; 147*91f16700Schasinglulu struct dt_node_info info; 148*91f16700Schasinglulu void *fdt; 149*91f16700Schasinglulu 150*91f16700Schasinglulu if (fdt_get_address(&fdt) == 0) { 151*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 152*91f16700Schasinglulu } 153*91f16700Schasinglulu 154*91f16700Schasinglulu node = dt_get_node(&info, -1, DT_SAES_COMPAT); 155*91f16700Schasinglulu if (node < 0) { 156*91f16700Schasinglulu ERROR("No SAES entry in DT\n"); 157*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 158*91f16700Schasinglulu } 159*91f16700Schasinglulu 160*91f16700Schasinglulu if (info.status == DT_DISABLED) { 161*91f16700Schasinglulu return -FDT_ERR_NOTFOUND; 162*91f16700Schasinglulu } 163*91f16700Schasinglulu 164*91f16700Schasinglulu if ((info.base == 0U) || (info.clock < 0) || (info.reset < 0)) { 165*91f16700Schasinglulu return -FDT_ERR_BADVALUE; 166*91f16700Schasinglulu } 167*91f16700Schasinglulu 168*91f16700Schasinglulu pdata->base = (uintptr_t)info.base; 169*91f16700Schasinglulu pdata->clock_id = (unsigned long)info.clock; 170*91f16700Schasinglulu pdata->reset_id = (unsigned int)info.reset; 171*91f16700Schasinglulu 172*91f16700Schasinglulu return 0; 173*91f16700Schasinglulu } 174*91f16700Schasinglulu 175*91f16700Schasinglulu static bool does_chaining_mode_need_iv(uint32_t cr) 176*91f16700Schasinglulu { 177*91f16700Schasinglulu return !(IS_CHAINING_MODE(ECB, cr)); 178*91f16700Schasinglulu } 179*91f16700Schasinglulu 180*91f16700Schasinglulu static bool is_encrypt(uint32_t cr) 181*91f16700Schasinglulu { 182*91f16700Schasinglulu return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT); 183*91f16700Schasinglulu } 184*91f16700Schasinglulu 185*91f16700Schasinglulu static bool is_decrypt(uint32_t cr) 186*91f16700Schasinglulu { 187*91f16700Schasinglulu return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT); 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu static int wait_computation_completed(uintptr_t base) 191*91f16700Schasinglulu { 192*91f16700Schasinglulu uint64_t timeout = timeout_init_us(SAES_TIMEOUT_US); 193*91f16700Schasinglulu 194*91f16700Schasinglulu while ((mmio_read_32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) { 195*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 196*91f16700Schasinglulu WARN("%s: timeout\n", __func__); 197*91f16700Schasinglulu return -ETIMEDOUT; 198*91f16700Schasinglulu } 199*91f16700Schasinglulu } 200*91f16700Schasinglulu 201*91f16700Schasinglulu return 0; 202*91f16700Schasinglulu } 203*91f16700Schasinglulu 204*91f16700Schasinglulu static void clear_computation_completed(uintptr_t base) 205*91f16700Schasinglulu { 206*91f16700Schasinglulu mmio_setbits_32(base + _SAES_ICR, _SAES_I_CC); 207*91f16700Schasinglulu } 208*91f16700Schasinglulu 209*91f16700Schasinglulu static int saes_start(struct stm32_saes_context *ctx) 210*91f16700Schasinglulu { 211*91f16700Schasinglulu uint64_t timeout; 212*91f16700Schasinglulu 213*91f16700Schasinglulu /* Reset IP */ 214*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); 215*91f16700Schasinglulu udelay(SAES_RESET_DELAY); 216*91f16700Schasinglulu mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); 217*91f16700Schasinglulu 218*91f16700Schasinglulu timeout = timeout_init_us(SAES_TIMEOUT_US); 219*91f16700Schasinglulu while ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) == _SAES_SR_BUSY) { 220*91f16700Schasinglulu if (timeout_elapsed(timeout)) { 221*91f16700Schasinglulu WARN("%s: timeout\n", __func__); 222*91f16700Schasinglulu return -ETIMEDOUT; 223*91f16700Schasinglulu } 224*91f16700Schasinglulu } 225*91f16700Schasinglulu 226*91f16700Schasinglulu return 0; 227*91f16700Schasinglulu } 228*91f16700Schasinglulu 229*91f16700Schasinglulu static void saes_end(struct stm32_saes_context *ctx, int prev_error) 230*91f16700Schasinglulu { 231*91f16700Schasinglulu if (prev_error != 0) { 232*91f16700Schasinglulu /* Reset IP */ 233*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); 234*91f16700Schasinglulu udelay(SAES_RESET_DELAY); 235*91f16700Schasinglulu mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); 236*91f16700Schasinglulu } 237*91f16700Schasinglulu 238*91f16700Schasinglulu /* Disable the SAES peripheral */ 239*91f16700Schasinglulu mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 240*91f16700Schasinglulu } 241*91f16700Schasinglulu 242*91f16700Schasinglulu static void saes_write_iv(struct stm32_saes_context *ctx) 243*91f16700Schasinglulu { 244*91f16700Schasinglulu /* If chaining mode need to restore IV */ 245*91f16700Schasinglulu if (does_chaining_mode_need_iv(ctx->cr)) { 246*91f16700Schasinglulu uint8_t i; 247*91f16700Schasinglulu 248*91f16700Schasinglulu /* Restore the _SAES_IVRx */ 249*91f16700Schasinglulu for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) { 250*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]); 251*91f16700Schasinglulu } 252*91f16700Schasinglulu } 253*91f16700Schasinglulu 254*91f16700Schasinglulu } 255*91f16700Schasinglulu 256*91f16700Schasinglulu static void saes_write_key(struct stm32_saes_context *ctx) 257*91f16700Schasinglulu { 258*91f16700Schasinglulu /* Restore the _SAES_KEYRx if SOFTWARE key */ 259*91f16700Schasinglulu if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == (_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT)) { 260*91f16700Schasinglulu uint8_t i; 261*91f16700Schasinglulu 262*91f16700Schasinglulu for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) { 263*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]); 264*91f16700Schasinglulu } 265*91f16700Schasinglulu 266*91f16700Schasinglulu if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) { 267*91f16700Schasinglulu for (i = 0U; i < (AES_KEYSIZE_256 / 2U) / sizeof(uint32_t); i++) { 268*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t), 269*91f16700Schasinglulu ctx->key[i + 4U]); 270*91f16700Schasinglulu } 271*91f16700Schasinglulu } 272*91f16700Schasinglulu } 273*91f16700Schasinglulu } 274*91f16700Schasinglulu 275*91f16700Schasinglulu static int saes_prepare_key(struct stm32_saes_context *ctx) 276*91f16700Schasinglulu { 277*91f16700Schasinglulu /* Disable the SAES peripheral */ 278*91f16700Schasinglulu mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 279*91f16700Schasinglulu 280*91f16700Schasinglulu /* Set key size */ 281*91f16700Schasinglulu if ((ctx->cr & _SAES_CR_KEYSIZE) != 0U) { 282*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); 283*91f16700Schasinglulu } else { 284*91f16700Schasinglulu mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); 285*91f16700Schasinglulu } 286*91f16700Schasinglulu 287*91f16700Schasinglulu saes_write_key(ctx); 288*91f16700Schasinglulu 289*91f16700Schasinglulu /* For ECB/CBC decryption, key preparation mode must be selected to populate the key */ 290*91f16700Schasinglulu if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) && 291*91f16700Schasinglulu is_decrypt(ctx->cr)) { 292*91f16700Schasinglulu int ret; 293*91f16700Schasinglulu 294*91f16700Schasinglulu /* Select Mode 2 */ 295*91f16700Schasinglulu mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, 296*91f16700Schasinglulu _SAES_CR_MODE_KEYPREP << _SAES_CR_MODE_SHIFT); 297*91f16700Schasinglulu 298*91f16700Schasinglulu /* Enable SAES */ 299*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 300*91f16700Schasinglulu 301*91f16700Schasinglulu /* Wait Computation completed */ 302*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 303*91f16700Schasinglulu if (ret != 0) { 304*91f16700Schasinglulu return ret; 305*91f16700Schasinglulu } 306*91f16700Schasinglulu 307*91f16700Schasinglulu clear_computation_completed(ctx->base); 308*91f16700Schasinglulu 309*91f16700Schasinglulu /* Set Mode 3 */ 310*91f16700Schasinglulu mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, 311*91f16700Schasinglulu _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT); 312*91f16700Schasinglulu } 313*91f16700Schasinglulu 314*91f16700Schasinglulu return 0; 315*91f16700Schasinglulu } 316*91f16700Schasinglulu 317*91f16700Schasinglulu static int save_context(struct stm32_saes_context *ctx) 318*91f16700Schasinglulu { 319*91f16700Schasinglulu if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_CCF) != 0U) { 320*91f16700Schasinglulu /* Device should not be in a processing phase */ 321*91f16700Schasinglulu return -EINVAL; 322*91f16700Schasinglulu } 323*91f16700Schasinglulu 324*91f16700Schasinglulu /* Save CR */ 325*91f16700Schasinglulu ctx->cr = mmio_read_32(ctx->base + _SAES_CR); 326*91f16700Schasinglulu 327*91f16700Schasinglulu /* If chaining mode need to save current IV */ 328*91f16700Schasinglulu if (does_chaining_mode_need_iv(ctx->cr)) { 329*91f16700Schasinglulu uint8_t i; 330*91f16700Schasinglulu 331*91f16700Schasinglulu /* Save IV */ 332*91f16700Schasinglulu for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) { 333*91f16700Schasinglulu ctx->iv[i] = mmio_read_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t)); 334*91f16700Schasinglulu } 335*91f16700Schasinglulu } 336*91f16700Schasinglulu 337*91f16700Schasinglulu /* Disable the SAES peripheral */ 338*91f16700Schasinglulu mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 339*91f16700Schasinglulu 340*91f16700Schasinglulu return 0; 341*91f16700Schasinglulu } 342*91f16700Schasinglulu 343*91f16700Schasinglulu /* To resume the processing of a message */ 344*91f16700Schasinglulu static int restore_context(struct stm32_saes_context *ctx) 345*91f16700Schasinglulu { 346*91f16700Schasinglulu int ret; 347*91f16700Schasinglulu 348*91f16700Schasinglulu /* IP should be disabled */ 349*91f16700Schasinglulu if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) { 350*91f16700Schasinglulu VERBOSE("%s: Device is still enabled\n", __func__); 351*91f16700Schasinglulu return -EINVAL; 352*91f16700Schasinglulu } 353*91f16700Schasinglulu 354*91f16700Schasinglulu /* Reset internal state */ 355*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST); 356*91f16700Schasinglulu 357*91f16700Schasinglulu /* Restore the _SAES_CR */ 358*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_CR, ctx->cr); 359*91f16700Schasinglulu 360*91f16700Schasinglulu /* Preparation decrypt key */ 361*91f16700Schasinglulu ret = saes_prepare_key(ctx); 362*91f16700Schasinglulu if (ret != 0) { 363*91f16700Schasinglulu return ret; 364*91f16700Schasinglulu } 365*91f16700Schasinglulu 366*91f16700Schasinglulu saes_write_iv(ctx); 367*91f16700Schasinglulu 368*91f16700Schasinglulu /* Enable the SAES peripheral */ 369*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 370*91f16700Schasinglulu 371*91f16700Schasinglulu return 0; 372*91f16700Schasinglulu } 373*91f16700Schasinglulu 374*91f16700Schasinglulu /** 375*91f16700Schasinglulu * @brief Initialize SAES driver. 376*91f16700Schasinglulu * @param None. 377*91f16700Schasinglulu * @retval 0 if OK; negative value else. 378*91f16700Schasinglulu */ 379*91f16700Schasinglulu int stm32_saes_driver_init(void) 380*91f16700Schasinglulu { 381*91f16700Schasinglulu int err; 382*91f16700Schasinglulu 383*91f16700Schasinglulu err = stm32_saes_parse_fdt(&saes_pdata); 384*91f16700Schasinglulu if (err != 0) { 385*91f16700Schasinglulu return err; 386*91f16700Schasinglulu } 387*91f16700Schasinglulu 388*91f16700Schasinglulu clk_enable(saes_pdata.clock_id); 389*91f16700Schasinglulu if (stm32mp_reset_assert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) { 390*91f16700Schasinglulu panic(); 391*91f16700Schasinglulu } 392*91f16700Schasinglulu 393*91f16700Schasinglulu udelay(SAES_RESET_DELAY); 394*91f16700Schasinglulu if (stm32mp_reset_deassert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) { 395*91f16700Schasinglulu panic(); 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu return 0; 399*91f16700Schasinglulu } 400*91f16700Schasinglulu 401*91f16700Schasinglulu /** 402*91f16700Schasinglulu * @brief Start a AES computation. 403*91f16700Schasinglulu * @param ctx: SAES process context 404*91f16700Schasinglulu * @param is_dec: true if decryption, false if encryption 405*91f16700Schasinglulu * @param ch_mode: define the chaining mode 406*91f16700Schasinglulu * @param key_select: define where the key comes from. 407*91f16700Schasinglulu * @param key: pointer to key (if key_select is KEY_SOFT, else unused) 408*91f16700Schasinglulu * @param key_size: key size 409*91f16700Schasinglulu * @param iv: pointer to initialization vectore (unsed if ch_mode is ECB) 410*91f16700Schasinglulu * @param iv_size: iv size 411*91f16700Schasinglulu * @note this function doesn't access to hardware but store in ctx the values 412*91f16700Schasinglulu * 413*91f16700Schasinglulu * @retval 0 if OK; negative value else. 414*91f16700Schasinglulu */ 415*91f16700Schasinglulu int stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec, 416*91f16700Schasinglulu enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select, 417*91f16700Schasinglulu const void *key, size_t key_size, const void *iv, size_t iv_size) 418*91f16700Schasinglulu { 419*91f16700Schasinglulu unsigned int i; 420*91f16700Schasinglulu const uint32_t *iv_u32; 421*91f16700Schasinglulu const uint32_t *key_u32; 422*91f16700Schasinglulu 423*91f16700Schasinglulu ctx->assoc_len = 0U; 424*91f16700Schasinglulu ctx->load_len = 0U; 425*91f16700Schasinglulu 426*91f16700Schasinglulu ctx->base = saes_pdata.base; 427*91f16700Schasinglulu ctx->cr = _SAES_CR_RESET_VALUE; 428*91f16700Schasinglulu 429*91f16700Schasinglulu /* We want buffer to be u32 aligned */ 430*91f16700Schasinglulu assert((uintptr_t)key % __alignof__(uint32_t) == 0); 431*91f16700Schasinglulu assert((uintptr_t)iv % __alignof__(uint32_t) == 0); 432*91f16700Schasinglulu 433*91f16700Schasinglulu iv_u32 = iv; 434*91f16700Schasinglulu key_u32 = key; 435*91f16700Schasinglulu 436*91f16700Schasinglulu if (is_dec) { 437*91f16700Schasinglulu /* Save Mode 3 = decrypt */ 438*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK, 439*91f16700Schasinglulu _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT); 440*91f16700Schasinglulu } else { 441*91f16700Schasinglulu /* Save Mode 1 = crypt */ 442*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK, 443*91f16700Schasinglulu _SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT); 444*91f16700Schasinglulu } 445*91f16700Schasinglulu 446*91f16700Schasinglulu /* Save chaining mode */ 447*91f16700Schasinglulu switch (ch_mode) { 448*91f16700Schasinglulu case STM32_SAES_MODE_ECB: 449*91f16700Schasinglulu SET_CHAINING_MODE(ECB, (uintptr_t)&(ctx->cr)); 450*91f16700Schasinglulu break; 451*91f16700Schasinglulu case STM32_SAES_MODE_CBC: 452*91f16700Schasinglulu SET_CHAINING_MODE(CBC, (uintptr_t)&(ctx->cr)); 453*91f16700Schasinglulu break; 454*91f16700Schasinglulu case STM32_SAES_MODE_CTR: 455*91f16700Schasinglulu SET_CHAINING_MODE(CTR, (uintptr_t)&(ctx->cr)); 456*91f16700Schasinglulu break; 457*91f16700Schasinglulu case STM32_SAES_MODE_GCM: 458*91f16700Schasinglulu SET_CHAINING_MODE(GCM, (uintptr_t)&(ctx->cr)); 459*91f16700Schasinglulu break; 460*91f16700Schasinglulu case STM32_SAES_MODE_CCM: 461*91f16700Schasinglulu SET_CHAINING_MODE(CCM, (uintptr_t)&(ctx->cr)); 462*91f16700Schasinglulu break; 463*91f16700Schasinglulu default: 464*91f16700Schasinglulu return -EINVAL; 465*91f16700Schasinglulu } 466*91f16700Schasinglulu 467*91f16700Schasinglulu /* We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data. 468*91f16700Schasinglulu * so we won't need to 469*91f16700Schasinglulu * htobe32(data) before write to DINR 470*91f16700Schasinglulu * nor 471*91f16700Schasinglulu * be32toh after reading from DOUTR 472*91f16700Schasinglulu * 473*91f16700Schasinglulu * But note that wrap key only accept _SAES_CR_DATATYPE_NONE 474*91f16700Schasinglulu */ 475*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK, 476*91f16700Schasinglulu _SAES_CR_DATATYPE_BYTE << _SAES_CR_DATATYPE_SHIFT); 477*91f16700Schasinglulu 478*91f16700Schasinglulu /* Configure keysize */ 479*91f16700Schasinglulu switch (key_size) { 480*91f16700Schasinglulu case AES_KEYSIZE_128: 481*91f16700Schasinglulu mmio_clrbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE); 482*91f16700Schasinglulu break; 483*91f16700Schasinglulu case AES_KEYSIZE_256: 484*91f16700Schasinglulu mmio_setbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE); 485*91f16700Schasinglulu break; 486*91f16700Schasinglulu default: 487*91f16700Schasinglulu return -EINVAL; 488*91f16700Schasinglulu } 489*91f16700Schasinglulu 490*91f16700Schasinglulu /* Configure key */ 491*91f16700Schasinglulu switch (key_select) { 492*91f16700Schasinglulu case STM32_SAES_KEY_SOFT: 493*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, 494*91f16700Schasinglulu _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT); 495*91f16700Schasinglulu /* Save key */ 496*91f16700Schasinglulu switch (key_size) { 497*91f16700Schasinglulu case AES_KEYSIZE_128: 498*91f16700Schasinglulu /* First 16 bytes == 4 u32 */ 499*91f16700Schasinglulu for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) { 500*91f16700Schasinglulu mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[3 - i])); 501*91f16700Schasinglulu /* /!\ we save the key in HW byte order 502*91f16700Schasinglulu * and word order : key[i] is for _SAES_KEYRi 503*91f16700Schasinglulu */ 504*91f16700Schasinglulu } 505*91f16700Schasinglulu break; 506*91f16700Schasinglulu case AES_KEYSIZE_256: 507*91f16700Schasinglulu for (i = 0U; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) { 508*91f16700Schasinglulu mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[7 - i])); 509*91f16700Schasinglulu /* /!\ we save the key in HW byte order 510*91f16700Schasinglulu * and word order : key[i] is for _SAES_KEYRi 511*91f16700Schasinglulu */ 512*91f16700Schasinglulu } 513*91f16700Schasinglulu break; 514*91f16700Schasinglulu default: 515*91f16700Schasinglulu return -EINVAL; 516*91f16700Schasinglulu } 517*91f16700Schasinglulu 518*91f16700Schasinglulu break; 519*91f16700Schasinglulu case STM32_SAES_KEY_DHU: 520*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, 521*91f16700Schasinglulu _SAES_CR_KEYSEL_DHUK << _SAES_CR_KEYSEL_SHIFT); 522*91f16700Schasinglulu break; 523*91f16700Schasinglulu case STM32_SAES_KEY_BH: 524*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, 525*91f16700Schasinglulu _SAES_CR_KEYSEL_BHK << _SAES_CR_KEYSEL_SHIFT); 526*91f16700Schasinglulu break; 527*91f16700Schasinglulu case STM32_SAES_KEY_BHU_XOR_BH: 528*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, 529*91f16700Schasinglulu _SAES_CR_KEYSEL_BHU_XOR_BH_K << _SAES_CR_KEYSEL_SHIFT); 530*91f16700Schasinglulu break; 531*91f16700Schasinglulu case STM32_SAES_KEY_WRAPPED: 532*91f16700Schasinglulu mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK, 533*91f16700Schasinglulu _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT); 534*91f16700Schasinglulu break; 535*91f16700Schasinglulu 536*91f16700Schasinglulu default: 537*91f16700Schasinglulu return -EINVAL; 538*91f16700Schasinglulu } 539*91f16700Schasinglulu 540*91f16700Schasinglulu /* Save IV */ 541*91f16700Schasinglulu if (ch_mode != STM32_SAES_MODE_ECB) { 542*91f16700Schasinglulu if ((iv == NULL) || (iv_size != AES_IVSIZE)) { 543*91f16700Schasinglulu return -EINVAL; 544*91f16700Schasinglulu } 545*91f16700Schasinglulu 546*91f16700Schasinglulu for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) { 547*91f16700Schasinglulu mmio_write_32((uintptr_t)(ctx->iv + i), htobe32(iv_u32[3 - i])); 548*91f16700Schasinglulu /* /!\ We save the iv in HW byte order */ 549*91f16700Schasinglulu } 550*91f16700Schasinglulu } 551*91f16700Schasinglulu 552*91f16700Schasinglulu return saes_start(ctx); 553*91f16700Schasinglulu } 554*91f16700Schasinglulu 555*91f16700Schasinglulu /** 556*91f16700Schasinglulu * @brief Update (or start) a AES authentificate process of associated data (CCM or GCM). 557*91f16700Schasinglulu * @param ctx: SAES process context 558*91f16700Schasinglulu * @param last_block: true if last assoc data block 559*91f16700Schasinglulu * @param data: pointer to associated data 560*91f16700Schasinglulu * @param data_size: data size 561*91f16700Schasinglulu * 562*91f16700Schasinglulu * @retval 0 if OK; negative value else. 563*91f16700Schasinglulu */ 564*91f16700Schasinglulu int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block, 565*91f16700Schasinglulu uint8_t *data, size_t data_size) 566*91f16700Schasinglulu { 567*91f16700Schasinglulu int ret; 568*91f16700Schasinglulu uint32_t *data_u32; 569*91f16700Schasinglulu unsigned int i = 0U; 570*91f16700Schasinglulu 571*91f16700Schasinglulu /* We want buffers to be u32 aligned */ 572*91f16700Schasinglulu assert((uintptr_t)data % __alignof__(uint32_t) == 0); 573*91f16700Schasinglulu data_u32 = (uint32_t *)data; 574*91f16700Schasinglulu 575*91f16700Schasinglulu /* Init phase */ 576*91f16700Schasinglulu ret = restore_context(ctx); 577*91f16700Schasinglulu if (ret != 0) { 578*91f16700Schasinglulu goto out; 579*91f16700Schasinglulu } 580*91f16700Schasinglulu 581*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 582*91f16700Schasinglulu if (ret != 0) { 583*91f16700Schasinglulu return ret; 584*91f16700Schasinglulu } 585*91f16700Schasinglulu 586*91f16700Schasinglulu clear_computation_completed(ctx->base); 587*91f16700Schasinglulu 588*91f16700Schasinglulu if ((data == NULL) || (data_size == 0U)) { 589*91f16700Schasinglulu /* No associated data */ 590*91f16700Schasinglulu /* ret already = 0 */ 591*91f16700Schasinglulu goto out; 592*91f16700Schasinglulu } 593*91f16700Schasinglulu 594*91f16700Schasinglulu /* There is an header/associated data phase */ 595*91f16700Schasinglulu mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, 596*91f16700Schasinglulu _SAES_CR_GCMPH_HEADER << _SAES_CR_GCMPH_SHIFT); 597*91f16700Schasinglulu 598*91f16700Schasinglulu /* Enable the SAES peripheral */ 599*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 600*91f16700Schasinglulu 601*91f16700Schasinglulu while (i < round_down(data_size, AES_BLOCK_SIZE)) { 602*91f16700Schasinglulu unsigned int w; /* Word index */ 603*91f16700Schasinglulu 604*91f16700Schasinglulu w = i / sizeof(uint32_t); 605*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 606*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 0U]); 607*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 1U]); 608*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 2U]); 609*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 3U]); 610*91f16700Schasinglulu 611*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 612*91f16700Schasinglulu if (ret != 0) { 613*91f16700Schasinglulu goto out; 614*91f16700Schasinglulu } 615*91f16700Schasinglulu 616*91f16700Schasinglulu clear_computation_completed(ctx->base); 617*91f16700Schasinglulu 618*91f16700Schasinglulu /* Process next block */ 619*91f16700Schasinglulu i += AES_BLOCK_SIZE; 620*91f16700Schasinglulu ctx->assoc_len += AES_BLOCK_SIZE_BIT; 621*91f16700Schasinglulu } 622*91f16700Schasinglulu 623*91f16700Schasinglulu /* Manage last block if not a block size multiple */ 624*91f16700Schasinglulu if ((last_block) && (i < data_size)) { 625*91f16700Schasinglulu /* We don't manage unaligned last block yet */ 626*91f16700Schasinglulu ret = -ENODEV; 627*91f16700Schasinglulu goto out; 628*91f16700Schasinglulu } 629*91f16700Schasinglulu 630*91f16700Schasinglulu out: 631*91f16700Schasinglulu if (ret != 0) { 632*91f16700Schasinglulu saes_end(ctx, ret); 633*91f16700Schasinglulu } 634*91f16700Schasinglulu 635*91f16700Schasinglulu return ret; 636*91f16700Schasinglulu } 637*91f16700Schasinglulu 638*91f16700Schasinglulu /** 639*91f16700Schasinglulu * @brief Update (or start) a AES authenticate and de/encrypt with payload data (CCM or GCM). 640*91f16700Schasinglulu * @param ctx: SAES process context 641*91f16700Schasinglulu * @param last_block: true if last payload data block 642*91f16700Schasinglulu * @param data_in: pointer to payload 643*91f16700Schasinglulu * @param data_out: pointer where to save de/encrypted payload 644*91f16700Schasinglulu * @param data_size: payload size 645*91f16700Schasinglulu * 646*91f16700Schasinglulu * @retval 0 if OK; negative value else. 647*91f16700Schasinglulu */ 648*91f16700Schasinglulu int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block, 649*91f16700Schasinglulu uint8_t *data_in, uint8_t *data_out, size_t data_size) 650*91f16700Schasinglulu { 651*91f16700Schasinglulu int ret = 0; 652*91f16700Schasinglulu uint32_t *data_in_u32; 653*91f16700Schasinglulu uint32_t *data_out_u32; 654*91f16700Schasinglulu unsigned int i = 0U; 655*91f16700Schasinglulu uint32_t prev_cr; 656*91f16700Schasinglulu 657*91f16700Schasinglulu /* We want buffers to be u32 aligned */ 658*91f16700Schasinglulu assert((uintptr_t)data_in % __alignof__(uint32_t) == 0); 659*91f16700Schasinglulu assert((uintptr_t)data_out % __alignof__(uint32_t) == 0); 660*91f16700Schasinglulu data_in_u32 = (uint32_t *)data_in; 661*91f16700Schasinglulu data_out_u32 = (uint32_t *)data_out; 662*91f16700Schasinglulu 663*91f16700Schasinglulu prev_cr = mmio_read_32(ctx->base + _SAES_CR); 664*91f16700Schasinglulu 665*91f16700Schasinglulu if ((data_in == NULL) || (data_size == 0U)) { 666*91f16700Schasinglulu /* there is no data */ 667*91f16700Schasinglulu goto out; 668*91f16700Schasinglulu } 669*91f16700Schasinglulu 670*91f16700Schasinglulu /* There is a load phase */ 671*91f16700Schasinglulu mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, 672*91f16700Schasinglulu _SAES_CR_GCMPH_PAYLOAD << _SAES_CR_GCMPH_SHIFT); 673*91f16700Schasinglulu 674*91f16700Schasinglulu if ((prev_cr & _SAES_CR_GCMPH_MASK) == 675*91f16700Schasinglulu (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) { 676*91f16700Schasinglulu /* Still in initialization phase, no header 677*91f16700Schasinglulu * We need to enable the SAES peripheral 678*91f16700Schasinglulu */ 679*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 680*91f16700Schasinglulu } 681*91f16700Schasinglulu 682*91f16700Schasinglulu while (i < round_down(data_size, AES_BLOCK_SIZE)) { 683*91f16700Schasinglulu unsigned int w; /* Word index */ 684*91f16700Schasinglulu 685*91f16700Schasinglulu w = i / sizeof(uint32_t); 686*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 687*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]); 688*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]); 689*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]); 690*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]); 691*91f16700Schasinglulu 692*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 693*91f16700Schasinglulu if (ret != 0) { 694*91f16700Schasinglulu goto out; 695*91f16700Schasinglulu } 696*91f16700Schasinglulu 697*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 698*91f16700Schasinglulu data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR); 699*91f16700Schasinglulu data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR); 700*91f16700Schasinglulu data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR); 701*91f16700Schasinglulu data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR); 702*91f16700Schasinglulu 703*91f16700Schasinglulu clear_computation_completed(ctx->base); 704*91f16700Schasinglulu 705*91f16700Schasinglulu /* Process next block */ 706*91f16700Schasinglulu i += AES_BLOCK_SIZE; 707*91f16700Schasinglulu ctx->load_len += AES_BLOCK_SIZE_BIT; 708*91f16700Schasinglulu } 709*91f16700Schasinglulu /* Manage last block if not a block size multiple */ 710*91f16700Schasinglulu if ((last_block) && (i < data_size)) { 711*91f16700Schasinglulu uint32_t block_in[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0}; 712*91f16700Schasinglulu uint32_t block_out[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0}; 713*91f16700Schasinglulu 714*91f16700Schasinglulu memcpy(block_in, data_in + i, data_size - i); 715*91f16700Schasinglulu 716*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 717*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, block_in[0U]); 718*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, block_in[1U]); 719*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, block_in[2U]); 720*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, block_in[3U]); 721*91f16700Schasinglulu 722*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 723*91f16700Schasinglulu if (ret != 0) { 724*91f16700Schasinglulu VERBOSE("%s %d\n", __func__, __LINE__); 725*91f16700Schasinglulu goto out; 726*91f16700Schasinglulu } 727*91f16700Schasinglulu 728*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 729*91f16700Schasinglulu block_out[0U] = mmio_read_32(ctx->base + _SAES_DOUTR); 730*91f16700Schasinglulu block_out[1U] = mmio_read_32(ctx->base + _SAES_DOUTR); 731*91f16700Schasinglulu block_out[2U] = mmio_read_32(ctx->base + _SAES_DOUTR); 732*91f16700Schasinglulu block_out[3U] = mmio_read_32(ctx->base + _SAES_DOUTR); 733*91f16700Schasinglulu 734*91f16700Schasinglulu clear_computation_completed(ctx->base); 735*91f16700Schasinglulu 736*91f16700Schasinglulu memcpy(data_out + i, block_out, data_size - i); 737*91f16700Schasinglulu 738*91f16700Schasinglulu ctx->load_len += (data_size - i) * UINT8_BIT; 739*91f16700Schasinglulu } 740*91f16700Schasinglulu 741*91f16700Schasinglulu out: 742*91f16700Schasinglulu if (ret != 0) { 743*91f16700Schasinglulu saes_end(ctx, ret); 744*91f16700Schasinglulu } 745*91f16700Schasinglulu 746*91f16700Schasinglulu return ret; 747*91f16700Schasinglulu } 748*91f16700Schasinglulu 749*91f16700Schasinglulu /** 750*91f16700Schasinglulu * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM). 751*91f16700Schasinglulu * @param ctx: SAES process context 752*91f16700Schasinglulu * @param tag: pointer where to save the tag 753*91f16700Schasinglulu * @param data_size: tag size 754*91f16700Schasinglulu * 755*91f16700Schasinglulu * @retval 0 if OK; negative value else. 756*91f16700Schasinglulu */ 757*91f16700Schasinglulu int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, 758*91f16700Schasinglulu size_t tag_size) 759*91f16700Schasinglulu { 760*91f16700Schasinglulu int ret; 761*91f16700Schasinglulu uint32_t tag_u32[4]; 762*91f16700Schasinglulu uint32_t prev_cr; 763*91f16700Schasinglulu 764*91f16700Schasinglulu prev_cr = mmio_read_32(ctx->base + _SAES_CR); 765*91f16700Schasinglulu 766*91f16700Schasinglulu mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, 767*91f16700Schasinglulu _SAES_CR_GCMPH_FINAL << _SAES_CR_GCMPH_SHIFT); 768*91f16700Schasinglulu 769*91f16700Schasinglulu if ((prev_cr & _SAES_CR_GCMPH_MASK) == (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) { 770*91f16700Schasinglulu /* Still in initialization phase, no header 771*91f16700Schasinglulu * We need to enable the SAES peripheral 772*91f16700Schasinglulu */ 773*91f16700Schasinglulu mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN); 774*91f16700Schasinglulu } 775*91f16700Schasinglulu 776*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 777*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, 0); 778*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, ctx->assoc_len); 779*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, 0); 780*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, ctx->load_len); 781*91f16700Schasinglulu 782*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 783*91f16700Schasinglulu if (ret != 0) { 784*91f16700Schasinglulu goto out; 785*91f16700Schasinglulu } 786*91f16700Schasinglulu 787*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 788*91f16700Schasinglulu tag_u32[0] = mmio_read_32(ctx->base + _SAES_DOUTR); 789*91f16700Schasinglulu tag_u32[1] = mmio_read_32(ctx->base + _SAES_DOUTR); 790*91f16700Schasinglulu tag_u32[2] = mmio_read_32(ctx->base + _SAES_DOUTR); 791*91f16700Schasinglulu tag_u32[3] = mmio_read_32(ctx->base + _SAES_DOUTR); 792*91f16700Schasinglulu 793*91f16700Schasinglulu clear_computation_completed(ctx->base); 794*91f16700Schasinglulu 795*91f16700Schasinglulu memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size)); 796*91f16700Schasinglulu 797*91f16700Schasinglulu out: 798*91f16700Schasinglulu saes_end(ctx, ret); 799*91f16700Schasinglulu 800*91f16700Schasinglulu return ret; 801*91f16700Schasinglulu } 802*91f16700Schasinglulu 803*91f16700Schasinglulu /** 804*91f16700Schasinglulu * @brief Update (or start) a AES de/encrypt process (ECB, CBC or CTR). 805*91f16700Schasinglulu * @param ctx: SAES process context 806*91f16700Schasinglulu * @param last_block: true if last payload data block 807*91f16700Schasinglulu * @param data_in: pointer to payload 808*91f16700Schasinglulu * @param data_out: pointer where to save de/encrypted payload 809*91f16700Schasinglulu * @param data_size: payload size 810*91f16700Schasinglulu * 811*91f16700Schasinglulu * @retval 0 if OK; negative value else. 812*91f16700Schasinglulu */ 813*91f16700Schasinglulu int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block, 814*91f16700Schasinglulu uint8_t *data_in, uint8_t *data_out, size_t data_size) 815*91f16700Schasinglulu { 816*91f16700Schasinglulu int ret; 817*91f16700Schasinglulu uint32_t *data_in_u32; 818*91f16700Schasinglulu uint32_t *data_out_u32; 819*91f16700Schasinglulu unsigned int i = 0U; 820*91f16700Schasinglulu 821*91f16700Schasinglulu /* We want buffers to be u32 aligned */ 822*91f16700Schasinglulu assert((uintptr_t)data_in % __alignof__(uint32_t) == 0); 823*91f16700Schasinglulu assert((uintptr_t)data_out % __alignof__(uint32_t) == 0); 824*91f16700Schasinglulu data_in_u32 = (uint32_t *)data_in; 825*91f16700Schasinglulu data_out_u32 = (uint32_t *)data_out; 826*91f16700Schasinglulu 827*91f16700Schasinglulu if ((!last_block) && 828*91f16700Schasinglulu (round_down(data_size, AES_BLOCK_SIZE) != data_size)) { 829*91f16700Schasinglulu ERROR("%s: non last block must be multiple of 128 bits\n", 830*91f16700Schasinglulu __func__); 831*91f16700Schasinglulu ret = -EINVAL; 832*91f16700Schasinglulu goto out; 833*91f16700Schasinglulu } 834*91f16700Schasinglulu 835*91f16700Schasinglulu /* In CBC encryption we need to manage specifically last 2 128bits 836*91f16700Schasinglulu * blocks if total size in not a block size aligned 837*91f16700Schasinglulu * work TODO. Currently return ENODEV. 838*91f16700Schasinglulu * Morevoer as we need to know last 2 block, if unaligned and 839*91f16700Schasinglulu * call with less than two block, return -EINVAL. 840*91f16700Schasinglulu */ 841*91f16700Schasinglulu if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) && 842*91f16700Schasinglulu (round_down(data_size, AES_BLOCK_SIZE) != data_size)) { 843*91f16700Schasinglulu if (data_size < AES_BLOCK_SIZE * 2U) { 844*91f16700Schasinglulu ERROR("if CBC, last part size should be at least 2 * AES_BLOCK_SIZE\n"); 845*91f16700Schasinglulu ret = -EINVAL; 846*91f16700Schasinglulu goto out; 847*91f16700Schasinglulu } 848*91f16700Schasinglulu /* Moreover the CBC specific padding for encrypt is not yet implemented */ 849*91f16700Schasinglulu ret = -ENODEV; 850*91f16700Schasinglulu goto out; 851*91f16700Schasinglulu } 852*91f16700Schasinglulu 853*91f16700Schasinglulu ret = restore_context(ctx); 854*91f16700Schasinglulu if (ret != 0) { 855*91f16700Schasinglulu goto out; 856*91f16700Schasinglulu } 857*91f16700Schasinglulu 858*91f16700Schasinglulu while (i < round_down(data_size, AES_BLOCK_SIZE)) { 859*91f16700Schasinglulu unsigned int w; /* Word index */ 860*91f16700Schasinglulu 861*91f16700Schasinglulu w = i / sizeof(uint32_t); 862*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 863*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]); 864*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]); 865*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]); 866*91f16700Schasinglulu mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]); 867*91f16700Schasinglulu 868*91f16700Schasinglulu ret = wait_computation_completed(ctx->base); 869*91f16700Schasinglulu if (ret != 0) { 870*91f16700Schasinglulu goto out; 871*91f16700Schasinglulu } 872*91f16700Schasinglulu 873*91f16700Schasinglulu /* No need to htobe() as we configure the HW to swap bytes */ 874*91f16700Schasinglulu data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR); 875*91f16700Schasinglulu data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR); 876*91f16700Schasinglulu data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR); 877*91f16700Schasinglulu data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR); 878*91f16700Schasinglulu 879*91f16700Schasinglulu clear_computation_completed(ctx->base); 880*91f16700Schasinglulu 881*91f16700Schasinglulu /* Process next block */ 882*91f16700Schasinglulu i += AES_BLOCK_SIZE; 883*91f16700Schasinglulu } 884*91f16700Schasinglulu /* Manage last block if not a block size multiple */ 885*91f16700Schasinglulu 886*91f16700Schasinglulu if ((last_block) && (i < data_size)) { 887*91f16700Schasinglulu /* In and out buffer have same size so should be AES_BLOCK_SIZE multiple */ 888*91f16700Schasinglulu ret = -ENODEV; 889*91f16700Schasinglulu goto out; 890*91f16700Schasinglulu } 891*91f16700Schasinglulu 892*91f16700Schasinglulu if (!last_block) { 893*91f16700Schasinglulu ret = save_context(ctx); 894*91f16700Schasinglulu } 895*91f16700Schasinglulu 896*91f16700Schasinglulu out: 897*91f16700Schasinglulu /* If last block or error, end of SAES process */ 898*91f16700Schasinglulu if (last_block || (ret != 0)) { 899*91f16700Schasinglulu saes_end(ctx, ret); 900*91f16700Schasinglulu } 901*91f16700Schasinglulu 902*91f16700Schasinglulu return ret; 903*91f16700Schasinglulu } 904