1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <errno.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_helpers.h> 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <common/tbbr/tbbr_img_def.h> 14*91f16700Schasinglulu #include <drivers/delay_timer.h> 15*91f16700Schasinglulu #include <lib/mmio.h> 16*91f16700Schasinglulu #include <lib/utils.h> 17*91f16700Schasinglulu #include <tools_share/firmware_image_package.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include "socfpga_mailbox.h" 20*91f16700Schasinglulu #include "socfpga_vab.h" 21*91f16700Schasinglulu 22*91f16700Schasinglulu static size_t get_img_size(uint8_t *img_buf, size_t img_buf_sz) 23*91f16700Schasinglulu { 24*91f16700Schasinglulu uint8_t *img_buf_end = img_buf + img_buf_sz; 25*91f16700Schasinglulu uint32_t cert_sz = get_unaligned_le32(img_buf_end - sizeof(uint32_t)); 26*91f16700Schasinglulu uint8_t *p = img_buf_end - cert_sz - sizeof(uint32_t); 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* Ensure p is pointing within the img_buf */ 29*91f16700Schasinglulu if (p < img_buf || p > (img_buf_end - VAB_CERT_HEADER_SIZE)) 30*91f16700Schasinglulu return 0; 31*91f16700Schasinglulu 32*91f16700Schasinglulu if (get_unaligned_le32(p) == SDM_CERT_MAGIC_NUM) 33*91f16700Schasinglulu return (size_t)(p - img_buf); 34*91f16700Schasinglulu 35*91f16700Schasinglulu return 0; 36*91f16700Schasinglulu } 37*91f16700Schasinglulu 38*91f16700Schasinglulu 39*91f16700Schasinglulu 40*91f16700Schasinglulu int socfpga_vendor_authentication(void **p_image, size_t *p_size) 41*91f16700Schasinglulu { 42*91f16700Schasinglulu int retry_count = 20; 43*91f16700Schasinglulu uint8_t hash384[FCS_SHA384_WORD_SIZE]; 44*91f16700Schasinglulu uint64_t img_addr, mbox_data_addr; 45*91f16700Schasinglulu uint32_t img_sz, mbox_data_sz; 46*91f16700Schasinglulu uint8_t *cert_hash_ptr, *mbox_relocate_data_addr; 47*91f16700Schasinglulu uint32_t resp = 0, resp_len = 1; 48*91f16700Schasinglulu int ret = 0; 49*91f16700Schasinglulu 50*91f16700Schasinglulu img_addr = (uintptr_t)*p_image; 51*91f16700Schasinglulu img_sz = get_img_size((uint8_t *)img_addr, *p_size); 52*91f16700Schasinglulu 53*91f16700Schasinglulu if (!img_sz) { 54*91f16700Schasinglulu NOTICE("VAB certificate not found in image!\n"); 55*91f16700Schasinglulu return -ENOVABIMG; 56*91f16700Schasinglulu } 57*91f16700Schasinglulu 58*91f16700Schasinglulu if (!IS_BYTE_ALIGNED(img_sz, sizeof(uint32_t))) { 59*91f16700Schasinglulu NOTICE("Image size (%d bytes) not aliged to 4 bytes!\n", img_sz); 60*91f16700Schasinglulu return -EIMGERR; 61*91f16700Schasinglulu } 62*91f16700Schasinglulu 63*91f16700Schasinglulu /* Generate HASH384 from the image */ 64*91f16700Schasinglulu /* TODO: This part need to cross check !!!!!! */ 65*91f16700Schasinglulu sha384_csum_wd((uint8_t *)img_addr, img_sz, hash384, CHUNKSZ_PER_WD_RESET); 66*91f16700Schasinglulu cert_hash_ptr = (uint8_t *)(img_addr + img_sz + 67*91f16700Schasinglulu VAB_CERT_MAGIC_OFFSET + VAB_CERT_FIT_SHA384_OFFSET); 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* 70*91f16700Schasinglulu * Compare the SHA384 found in certificate against the SHA384 71*91f16700Schasinglulu * calculated from image 72*91f16700Schasinglulu */ 73*91f16700Schasinglulu if (memcmp(hash384, cert_hash_ptr, FCS_SHA384_WORD_SIZE)) { 74*91f16700Schasinglulu NOTICE("SHA384 does not match!\n"); 75*91f16700Schasinglulu return -EKEYREJECTED; 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu 79*91f16700Schasinglulu mbox_data_addr = img_addr + img_sz - sizeof(uint32_t); 80*91f16700Schasinglulu /* Size in word (32bits) */ 81*91f16700Schasinglulu mbox_data_sz = (BYTE_ALIGN(*p_size - img_sz, sizeof(uint32_t))) >> 2; 82*91f16700Schasinglulu 83*91f16700Schasinglulu NOTICE("mbox_data_addr = %lx mbox_data_sz = %d\n", mbox_data_addr, mbox_data_sz); 84*91f16700Schasinglulu 85*91f16700Schasinglulu /* TODO: This part need to cross check !!!!!! */ 86*91f16700Schasinglulu // mbox_relocate_data_addr = (uint8_t *)malloc(mbox_data_sz * sizeof(uint32_t)); 87*91f16700Schasinglulu // if (!mbox_relocate_data_addr) { 88*91f16700Schasinglulu // NOTICE("Cannot allocate memory for VAB certificate relocation!\n"); 89*91f16700Schasinglulu // return -ENOMEM; 90*91f16700Schasinglulu // } 91*91f16700Schasinglulu 92*91f16700Schasinglulu memcpy(mbox_relocate_data_addr, (uint8_t *)mbox_data_addr, mbox_data_sz * sizeof(uint32_t)); 93*91f16700Schasinglulu *(uint32_t *)mbox_relocate_data_addr = 0; 94*91f16700Schasinglulu 95*91f16700Schasinglulu do { 96*91f16700Schasinglulu /* Invoke SMC call to ATF to send the VAB certificate to SDM */ 97*91f16700Schasinglulu ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_VAB_SRC_CERT, 98*91f16700Schasinglulu (uint32_t *)mbox_relocate_data_addr, mbox_data_sz, 0, &resp, &resp_len); 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* If SDM is not available, just delay 50ms and retry again */ 101*91f16700Schasinglulu /* 0x1FF = The device is busy */ 102*91f16700Schasinglulu if (ret == MBOX_RESP_ERR(0x1FF)) { 103*91f16700Schasinglulu mdelay(50); 104*91f16700Schasinglulu } else { 105*91f16700Schasinglulu break; 106*91f16700Schasinglulu } 107*91f16700Schasinglulu } while (--retry_count); 108*91f16700Schasinglulu 109*91f16700Schasinglulu /* Free the relocate certificate memory space */ 110*91f16700Schasinglulu zeromem((void *)&mbox_relocate_data_addr, sizeof(uint32_t)); 111*91f16700Schasinglulu 112*91f16700Schasinglulu 113*91f16700Schasinglulu /* Exclude the size of the VAB certificate from image size */ 114*91f16700Schasinglulu *p_size = img_sz; 115*91f16700Schasinglulu 116*91f16700Schasinglulu if (ret) { 117*91f16700Schasinglulu /* 118*91f16700Schasinglulu * Unsupported mailbox command or device not in the 119*91f16700Schasinglulu * owned/secure state 120*91f16700Schasinglulu */ 121*91f16700Schasinglulu /* 0x85 = Not allowed under current security setting */ 122*91f16700Schasinglulu if (ret == MBOX_RESP_ERR(0x85)) { 123*91f16700Schasinglulu /* SDM bypass authentication */ 124*91f16700Schasinglulu NOTICE("Image Authentication bypassed at address\n"); 125*91f16700Schasinglulu return 0; 126*91f16700Schasinglulu } 127*91f16700Schasinglulu NOTICE("VAB certificate authentication failed in SDM\n"); 128*91f16700Schasinglulu /* 0x1FF = The device is busy */ 129*91f16700Schasinglulu if (ret == MBOX_RESP_ERR(0x1FF)) { 130*91f16700Schasinglulu NOTICE("Operation timed out\n"); 131*91f16700Schasinglulu return -ETIMEOUT; 132*91f16700Schasinglulu } else if (ret == MBOX_WRONG_ID) { 133*91f16700Schasinglulu NOTICE("No such process\n"); 134*91f16700Schasinglulu return -EPROCESS; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu } else { 137*91f16700Schasinglulu /* If Certificate Process Status has error */ 138*91f16700Schasinglulu if (resp) { 139*91f16700Schasinglulu NOTICE("VAB certificate execution format error\n"); 140*91f16700Schasinglulu return -EIMGERR; 141*91f16700Schasinglulu } 142*91f16700Schasinglulu } 143*91f16700Schasinglulu 144*91f16700Schasinglulu NOTICE("Image Authentication bypassed at address\n"); 145*91f16700Schasinglulu return ret; 146*91f16700Schasinglulu 147*91f16700Schasinglulu } 148*91f16700Schasinglulu 149*91f16700Schasinglulu static uint32_t get_unaligned_le32(const void *p) 150*91f16700Schasinglulu { 151*91f16700Schasinglulu /* TODO: Temp for testing */ 152*91f16700Schasinglulu //return le32_to_cpup((__le32 *)p); 153*91f16700Schasinglulu return 0; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu void sha384_csum_wd(const unsigned char *input, unsigned int ilen, 157*91f16700Schasinglulu unsigned char *output, unsigned int chunk_sz) 158*91f16700Schasinglulu { 159*91f16700Schasinglulu /* TODO: Update sha384 start, update and finish */ 160*91f16700Schasinglulu } 161