147549250SJit Loon Lim /* 247549250SJit Loon Lim * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 347549250SJit Loon Lim * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 4*cab83c34SJit Loon Lim * Copyright (c) 2024, Altera Corporation. All rights reserved. 547549250SJit Loon Lim * 647549250SJit Loon Lim * SPDX-License-Identifier: BSD-3-Clause 747549250SJit Loon Lim */ 847549250SJit Loon Lim 947549250SJit Loon Lim #include <assert.h> 1047549250SJit Loon Lim #include <errno.h> 1147549250SJit Loon Lim 1247549250SJit Loon Lim #include <arch_helpers.h> 1347549250SJit Loon Lim #include <common/debug.h> 1447549250SJit Loon Lim #include <common/tbbr/tbbr_img_def.h> 1547549250SJit Loon Lim #include <drivers/delay_timer.h> 1647549250SJit Loon Lim #include <lib/mmio.h> 1747549250SJit Loon Lim #include <lib/utils.h> 1847549250SJit Loon Lim #include <tools_share/firmware_image_package.h> 1947549250SJit Loon Lim 2047549250SJit Loon Lim #include "socfpga_mailbox.h" 2147549250SJit Loon Lim #include "socfpga_vab.h" 2247549250SJit Loon Lim 2347549250SJit Loon Lim static size_t get_img_size(uint8_t *img_buf, size_t img_buf_sz) 2447549250SJit Loon Lim { 2547549250SJit Loon Lim uint8_t *img_buf_end = img_buf + img_buf_sz; 2647549250SJit Loon Lim uint32_t cert_sz = get_unaligned_le32(img_buf_end - sizeof(uint32_t)); 2747549250SJit Loon Lim uint8_t *p = img_buf_end - cert_sz - sizeof(uint32_t); 2847549250SJit Loon Lim 2947549250SJit Loon Lim /* Ensure p is pointing within the img_buf */ 3047549250SJit Loon Lim if (p < img_buf || p > (img_buf_end - VAB_CERT_HEADER_SIZE)) 3147549250SJit Loon Lim return 0; 3247549250SJit Loon Lim 3347549250SJit Loon Lim if (get_unaligned_le32(p) == SDM_CERT_MAGIC_NUM) 3447549250SJit Loon Lim return (size_t)(p - img_buf); 3547549250SJit Loon Lim 3647549250SJit Loon Lim return 0; 3747549250SJit Loon Lim } 3847549250SJit Loon Lim 3947549250SJit Loon Lim 4047549250SJit Loon Lim 4147549250SJit Loon Lim int socfpga_vendor_authentication(void **p_image, size_t *p_size) 4247549250SJit Loon Lim { 4347549250SJit Loon Lim int retry_count = 20; 4447549250SJit Loon Lim uint8_t hash384[FCS_SHA384_WORD_SIZE]; 4547549250SJit Loon Lim uint64_t img_addr, mbox_data_addr; 4647549250SJit Loon Lim uint32_t img_sz, mbox_data_sz; 4747549250SJit Loon Lim uint8_t *cert_hash_ptr, *mbox_relocate_data_addr; 4847549250SJit Loon Lim uint32_t resp = 0, resp_len = 1; 4947549250SJit Loon Lim int ret = 0; 5047549250SJit Loon Lim 5147549250SJit Loon Lim img_addr = (uintptr_t)*p_image; 5247549250SJit Loon Lim img_sz = get_img_size((uint8_t *)img_addr, *p_size); 5347549250SJit Loon Lim 5447549250SJit Loon Lim if (!img_sz) { 5547549250SJit Loon Lim NOTICE("VAB certificate not found in image!\n"); 56*cab83c34SJit Loon Lim return -ENOVABCERT; 5747549250SJit Loon Lim } 5847549250SJit Loon Lim 5947549250SJit Loon Lim if (!IS_BYTE_ALIGNED(img_sz, sizeof(uint32_t))) { 6047549250SJit Loon Lim NOTICE("Image size (%d bytes) not aliged to 4 bytes!\n", img_sz); 6147549250SJit Loon Lim return -EIMGERR; 6247549250SJit Loon Lim } 6347549250SJit Loon Lim 6447549250SJit Loon Lim /* Generate HASH384 from the image */ 6547549250SJit Loon Lim /* TODO: This part need to cross check !!!!!! */ 6647549250SJit Loon Lim sha384_csum_wd((uint8_t *)img_addr, img_sz, hash384, CHUNKSZ_PER_WD_RESET); 6747549250SJit Loon Lim cert_hash_ptr = (uint8_t *)(img_addr + img_sz + 6847549250SJit Loon Lim VAB_CERT_MAGIC_OFFSET + VAB_CERT_FIT_SHA384_OFFSET); 6947549250SJit Loon Lim 7047549250SJit Loon Lim /* 7147549250SJit Loon Lim * Compare the SHA384 found in certificate against the SHA384 7247549250SJit Loon Lim * calculated from image 7347549250SJit Loon Lim */ 7447549250SJit Loon Lim if (memcmp(hash384, cert_hash_ptr, FCS_SHA384_WORD_SIZE)) { 7547549250SJit Loon Lim NOTICE("SHA384 does not match!\n"); 7647549250SJit Loon Lim return -EKEYREJECTED; 7747549250SJit Loon Lim } 7847549250SJit Loon Lim 7947549250SJit Loon Lim 8047549250SJit Loon Lim mbox_data_addr = img_addr + img_sz - sizeof(uint32_t); 8147549250SJit Loon Lim /* Size in word (32bits) */ 8247549250SJit Loon Lim mbox_data_sz = (BYTE_ALIGN(*p_size - img_sz, sizeof(uint32_t))) >> 2; 8347549250SJit Loon Lim 8447549250SJit Loon Lim NOTICE("mbox_data_addr = %lx mbox_data_sz = %d\n", mbox_data_addr, mbox_data_sz); 8547549250SJit Loon Lim 8647549250SJit Loon Lim /* TODO: This part need to cross check !!!!!! */ 8747549250SJit Loon Lim // mbox_relocate_data_addr = (uint8_t *)malloc(mbox_data_sz * sizeof(uint32_t)); 8847549250SJit Loon Lim // if (!mbox_relocate_data_addr) { 8947549250SJit Loon Lim // NOTICE("Cannot allocate memory for VAB certificate relocation!\n"); 9047549250SJit Loon Lim // return -ENOMEM; 9147549250SJit Loon Lim // } 9247549250SJit Loon Lim 9347549250SJit Loon Lim memcpy(mbox_relocate_data_addr, (uint8_t *)mbox_data_addr, mbox_data_sz * sizeof(uint32_t)); 9447549250SJit Loon Lim *(uint32_t *)mbox_relocate_data_addr = 0; 9547549250SJit Loon Lim 9647549250SJit Loon Lim do { 9747549250SJit Loon Lim /* Invoke SMC call to ATF to send the VAB certificate to SDM */ 9847549250SJit Loon Lim ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_VAB_SRC_CERT, 9947549250SJit Loon Lim (uint32_t *)mbox_relocate_data_addr, mbox_data_sz, 0, &resp, &resp_len); 10047549250SJit Loon Lim 10147549250SJit Loon Lim /* If SDM is not available, just delay 50ms and retry again */ 10247549250SJit Loon Lim /* 0x1FF = The device is busy */ 10347549250SJit Loon Lim if (ret == MBOX_RESP_ERR(0x1FF)) { 10447549250SJit Loon Lim mdelay(50); 10547549250SJit Loon Lim } else { 10647549250SJit Loon Lim break; 10747549250SJit Loon Lim } 10847549250SJit Loon Lim } while (--retry_count); 10947549250SJit Loon Lim 11047549250SJit Loon Lim /* Free the relocate certificate memory space */ 11147549250SJit Loon Lim zeromem((void *)&mbox_relocate_data_addr, sizeof(uint32_t)); 11247549250SJit Loon Lim 11347549250SJit Loon Lim 11447549250SJit Loon Lim /* Exclude the size of the VAB certificate from image size */ 11547549250SJit Loon Lim *p_size = img_sz; 11647549250SJit Loon Lim 11747549250SJit Loon Lim if (ret) { 11847549250SJit Loon Lim /* 11947549250SJit Loon Lim * Unsupported mailbox command or device not in the 12047549250SJit Loon Lim * owned/secure state 12147549250SJit Loon Lim */ 12247549250SJit Loon Lim /* 0x85 = Not allowed under current security setting */ 12347549250SJit Loon Lim if (ret == MBOX_RESP_ERR(0x85)) { 12447549250SJit Loon Lim /* SDM bypass authentication */ 12547549250SJit Loon Lim NOTICE("Image Authentication bypassed at address\n"); 12647549250SJit Loon Lim return 0; 12747549250SJit Loon Lim } 12847549250SJit Loon Lim NOTICE("VAB certificate authentication failed in SDM\n"); 12947549250SJit Loon Lim /* 0x1FF = The device is busy */ 13047549250SJit Loon Lim if (ret == MBOX_RESP_ERR(0x1FF)) { 13147549250SJit Loon Lim NOTICE("Operation timed out\n"); 13247549250SJit Loon Lim return -ETIMEOUT; 13347549250SJit Loon Lim } else if (ret == MBOX_WRONG_ID) { 13447549250SJit Loon Lim NOTICE("No such process\n"); 13547549250SJit Loon Lim return -EPROCESS; 13647549250SJit Loon Lim } 13747549250SJit Loon Lim } else { 13847549250SJit Loon Lim /* If Certificate Process Status has error */ 13947549250SJit Loon Lim if (resp) { 14047549250SJit Loon Lim NOTICE("VAB certificate execution format error\n"); 14147549250SJit Loon Lim return -EIMGERR; 14247549250SJit Loon Lim } 14347549250SJit Loon Lim } 14447549250SJit Loon Lim 14547549250SJit Loon Lim NOTICE("Image Authentication bypassed at address\n"); 14647549250SJit Loon Lim return ret; 14747549250SJit Loon Lim 14847549250SJit Loon Lim } 14947549250SJit Loon Lim 15047549250SJit Loon Lim static uint32_t get_unaligned_le32(const void *p) 15147549250SJit Loon Lim { 15247549250SJit Loon Lim /* TODO: Temp for testing */ 15347549250SJit Loon Lim //return le32_to_cpup((__le32 *)p); 15447549250SJit Loon Lim return 0; 15547549250SJit Loon Lim } 15647549250SJit Loon Lim 157*cab83c34SJit Loon Lim static void sha512_transform(uint64_t *state, const uint8_t *input) 158*cab83c34SJit Loon Lim { 159*cab83c34SJit Loon Lim uint64_t a, b, c, d, e, f, g, h, t1, t2; 160*cab83c34SJit Loon Lim 161*cab83c34SJit Loon Lim int i; 162*cab83c34SJit Loon Lim uint64_t W[16]; 163*cab83c34SJit Loon Lim 164*cab83c34SJit Loon Lim /* load the state into our registers */ 165*cab83c34SJit Loon Lim a = state[0]; b = state[1]; c = state[2]; d = state[3]; 166*cab83c34SJit Loon Lim e = state[4]; f = state[5]; g = state[6]; h = state[7]; 167*cab83c34SJit Loon Lim 168*cab83c34SJit Loon Lim /* now iterate */ 169*cab83c34SJit Loon Lim for (i = 0 ; i < 80; i += 8) { 170*cab83c34SJit Loon Lim if (!(i & 8)) { 171*cab83c34SJit Loon Lim int j; 172*cab83c34SJit Loon Lim 173*cab83c34SJit Loon Lim if (i < 16) { 174*cab83c34SJit Loon Lim /* load the input */ 175*cab83c34SJit Loon Lim for (j = 0; j < 16; j++) 176*cab83c34SJit Loon Lim LOAD_OP(i + j, W, input); 177*cab83c34SJit Loon Lim } else { 178*cab83c34SJit Loon Lim for (j = 0; j < 16; j++) { 179*cab83c34SJit Loon Lim BLEND_OP(i + j, W); 180*cab83c34SJit Loon Lim } 181*cab83c34SJit Loon Lim } 182*cab83c34SJit Loon Lim } 183*cab83c34SJit Loon Lim 184*cab83c34SJit Loon Lim t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i & 15)]; 185*cab83c34SJit Loon Lim t2 = e0(a) + Maj(a, b, c); d += t1; h = t1 + t2; 186*cab83c34SJit Loon Lim t1 = g + e1(d) + Ch(d, e, f) + sha512_K[i+1] + W[(i & 15) + 1]; 187*cab83c34SJit Loon Lim t2 = e0(h) + Maj(h, a, b); c += t1; g = t1 + t2; 188*cab83c34SJit Loon Lim t1 = f + e1(c) + Ch(c, d, e) + sha512_K[i+2] + W[(i & 15) + 2]; 189*cab83c34SJit Loon Lim t2 = e0(g) + Maj(g, h, a); b += t1; f = t1 + t2; 190*cab83c34SJit Loon Lim t1 = e + e1(b) + Ch(b, c, d) + sha512_K[i+3] + W[(i & 15) + 3]; 191*cab83c34SJit Loon Lim t2 = e0(f) + Maj(f, g, h); a += t1; e = t1 + t2; 192*cab83c34SJit Loon Lim t1 = d + e1(a) + Ch(a, b, c) + sha512_K[i+4] + W[(i & 15) + 4]; 193*cab83c34SJit Loon Lim t2 = e0(e) + Maj(e, f, g); h += t1; d = t1 + t2; 194*cab83c34SJit Loon Lim t1 = c + e1(h) + Ch(h, a, b) + sha512_K[i+5] + W[(i & 15) + 5]; 195*cab83c34SJit Loon Lim t2 = e0(d) + Maj(d, e, f); g += t1; c = t1 + t2; 196*cab83c34SJit Loon Lim t1 = b + e1(g) + Ch(g, h, a) + sha512_K[i+6] + W[(i & 15) + 6]; 197*cab83c34SJit Loon Lim t2 = e0(c) + Maj(c, d, e); f += t1; b = t1 + t2; 198*cab83c34SJit Loon Lim t1 = a + e1(f) + Ch(f, g, h) + sha512_K[i+7] + W[(i & 15) + 7]; 199*cab83c34SJit Loon Lim t2 = e0(b) + Maj(b, c, d); e += t1; a = t1 + t2; 200*cab83c34SJit Loon Lim } 201*cab83c34SJit Loon Lim 202*cab83c34SJit Loon Lim state[0] += a; state[1] += b; state[2] += c; state[3] += d; 203*cab83c34SJit Loon Lim state[4] += e; state[5] += f; state[6] += g; state[7] += h; 204*cab83c34SJit Loon Lim 205*cab83c34SJit Loon Lim /* erase our data */ 206*cab83c34SJit Loon Lim a = b = c = d = e = f = g = h = t1 = t2 = 0; 207*cab83c34SJit Loon Lim } 208*cab83c34SJit Loon Lim 209*cab83c34SJit Loon Lim static void sha512_block_fn(sha512_context *sst, const uint8_t *src, 210*cab83c34SJit Loon Lim int blocks) 211*cab83c34SJit Loon Lim { 212*cab83c34SJit Loon Lim while (blocks--) { 213*cab83c34SJit Loon Lim sha512_transform(sst->state, src); 214*cab83c34SJit Loon Lim src += SHA512_BLOCK_SIZE; 215*cab83c34SJit Loon Lim } 216*cab83c34SJit Loon Lim } 217*cab83c34SJit Loon Lim 218*cab83c34SJit Loon Lim 219*cab83c34SJit Loon Lim static void sha512_base_do_finalize(sha512_context *sctx) 220*cab83c34SJit Loon Lim { 221*cab83c34SJit Loon Lim const int bit_offset = SHA512_BLOCK_SIZE - sizeof(uint64_t[2]); 222*cab83c34SJit Loon Lim uint64_t *bits = (uint64_t *)(sctx->buf + bit_offset); 223*cab83c34SJit Loon Lim unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; 224*cab83c34SJit Loon Lim 225*cab83c34SJit Loon Lim sctx->buf[partial++] = 0x80; 226*cab83c34SJit Loon Lim if (partial > bit_offset) { 227*cab83c34SJit Loon Lim memset(sctx->buf + partial, 0x0, SHA512_BLOCK_SIZE - partial); 228*cab83c34SJit Loon Lim partial = 0; 229*cab83c34SJit Loon Lim 230*cab83c34SJit Loon Lim sha512_block_fn(sctx, sctx->buf, 1); 231*cab83c34SJit Loon Lim } 232*cab83c34SJit Loon Lim 233*cab83c34SJit Loon Lim memset(sctx->buf + partial, 0x0, bit_offset - partial); 234*cab83c34SJit Loon Lim //fixme bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); 235*cab83c34SJit Loon Lim //fixme bits[1] = cpu_to_be64(sctx->count[0] << 3); 236*cab83c34SJit Loon Lim bits[0] = (sctx->count[1] << 3 | sctx->count[0] >> 61); 237*cab83c34SJit Loon Lim bits[1] = (sctx->count[0] << 3); 238*cab83c34SJit Loon Lim sha512_block_fn(sctx, sctx->buf, 1); 239*cab83c34SJit Loon Lim } 240*cab83c34SJit Loon Lim 241*cab83c34SJit Loon Lim static void sha512_base_do_update(sha512_context *sctx, 242*cab83c34SJit Loon Lim const uint8_t *data, 243*cab83c34SJit Loon Lim unsigned int len) 244*cab83c34SJit Loon Lim { 245*cab83c34SJit Loon Lim unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE; 246*cab83c34SJit Loon Lim 247*cab83c34SJit Loon Lim sctx->count[0] += len; 248*cab83c34SJit Loon Lim if (sctx->count[0] < len) 249*cab83c34SJit Loon Lim sctx->count[1]++; 250*cab83c34SJit Loon Lim 251*cab83c34SJit Loon Lim if (((partial + len) >= SHA512_BLOCK_SIZE)) { 252*cab83c34SJit Loon Lim int blocks; 253*cab83c34SJit Loon Lim 254*cab83c34SJit Loon Lim if (partial) { 255*cab83c34SJit Loon Lim int p = SHA512_BLOCK_SIZE - partial; 256*cab83c34SJit Loon Lim 257*cab83c34SJit Loon Lim memcpy(sctx->buf + partial, data, p); 258*cab83c34SJit Loon Lim data += p; 259*cab83c34SJit Loon Lim len -= p; 260*cab83c34SJit Loon Lim 261*cab83c34SJit Loon Lim sha512_block_fn(sctx, sctx->buf, 1); 262*cab83c34SJit Loon Lim } 263*cab83c34SJit Loon Lim 264*cab83c34SJit Loon Lim blocks = len / SHA512_BLOCK_SIZE; 265*cab83c34SJit Loon Lim len %= SHA512_BLOCK_SIZE; 266*cab83c34SJit Loon Lim 267*cab83c34SJit Loon Lim if (blocks) { 268*cab83c34SJit Loon Lim sha512_block_fn(sctx, data, blocks); 269*cab83c34SJit Loon Lim data += blocks * SHA512_BLOCK_SIZE; 270*cab83c34SJit Loon Lim } 271*cab83c34SJit Loon Lim partial = 0; 272*cab83c34SJit Loon Lim } 273*cab83c34SJit Loon Lim if (len) 274*cab83c34SJit Loon Lim memcpy(sctx->buf + partial, data, len); 275*cab83c34SJit Loon Lim } 276*cab83c34SJit Loon Lim 277*cab83c34SJit Loon Lim void sha384_starts(sha512_context *ctx) 278*cab83c34SJit Loon Lim { 279*cab83c34SJit Loon Lim ctx->state[0] = SHA384_H0; 280*cab83c34SJit Loon Lim ctx->state[1] = SHA384_H1; 281*cab83c34SJit Loon Lim ctx->state[2] = SHA384_H2; 282*cab83c34SJit Loon Lim ctx->state[3] = SHA384_H3; 283*cab83c34SJit Loon Lim ctx->state[4] = SHA384_H4; 284*cab83c34SJit Loon Lim ctx->state[5] = SHA384_H5; 285*cab83c34SJit Loon Lim ctx->state[6] = SHA384_H6; 286*cab83c34SJit Loon Lim ctx->state[7] = SHA384_H7; 287*cab83c34SJit Loon Lim ctx->count[0] = ctx->count[1] = 0; 288*cab83c34SJit Loon Lim } 289*cab83c34SJit Loon Lim 290*cab83c34SJit Loon Lim void sha384_update(sha512_context *ctx, const uint8_t *input, uint32_t length) 291*cab83c34SJit Loon Lim { 292*cab83c34SJit Loon Lim sha512_base_do_update(ctx, input, length); 293*cab83c34SJit Loon Lim } 294*cab83c34SJit Loon Lim 295*cab83c34SJit Loon Lim void sha384_finish(sha512_context *ctx, uint8_t digest[SHA384_SUM_LEN]) 296*cab83c34SJit Loon Lim { 297*cab83c34SJit Loon Lim int i; 298*cab83c34SJit Loon Lim 299*cab83c34SJit Loon Lim sha512_base_do_finalize(ctx); 300*cab83c34SJit Loon Lim for (i = 0; i < SHA384_SUM_LEN / sizeof(uint64_t); i++) 301*cab83c34SJit Loon Lim PUT_UINT64_BE(ctx->state[i], digest, i * 8); 302*cab83c34SJit Loon Lim } 303*cab83c34SJit Loon Lim 30447549250SJit Loon Lim void sha384_csum_wd(const unsigned char *input, unsigned int ilen, 30547549250SJit Loon Lim unsigned char *output, unsigned int chunk_sz) 30647549250SJit Loon Lim { 307*cab83c34SJit Loon Lim sha512_context ctx; 308*cab83c34SJit Loon Lim // #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 309*cab83c34SJit Loon Lim // const unsigned char *end; 310*cab83c34SJit Loon Lim // unsigned char *curr; 311*cab83c34SJit Loon Lim // int chunk; 312*cab83c34SJit Loon Lim // #endif 313*cab83c34SJit Loon Lim 314*cab83c34SJit Loon Lim sha384_starts(&ctx); 315*cab83c34SJit Loon Lim 316*cab83c34SJit Loon Lim // #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) 317*cab83c34SJit Loon Lim // curr = (unsigned char *)input; 318*cab83c34SJit Loon Lim // end = input + ilen; 319*cab83c34SJit Loon Lim // while (curr < end) { 320*cab83c34SJit Loon Lim // chunk = end - curr; 321*cab83c34SJit Loon Lim // if (chunk > chunk_sz) 322*cab83c34SJit Loon Lim // chunk = chunk_sz; 323*cab83c34SJit Loon Lim // sha384_update(&ctx, curr, chunk); 324*cab83c34SJit Loon Lim // curr += chunk; 325*cab83c34SJit Loon Lim // schedule(); 326*cab83c34SJit Loon Lim // } 327*cab83c34SJit Loon Lim // #else 328*cab83c34SJit Loon Lim sha384_update(&ctx, input, ilen); 329*cab83c34SJit Loon Lim // #endif 330*cab83c34SJit Loon Lim 331*cab83c34SJit Loon Lim sha384_finish(&ctx, output); 33247549250SJit Loon Lim } 333