#include "secboot.h" #include #include #include #include #include "reg.h" #include "secboot.h" #include "ptable.h" #include "loadtable.h" #include "fip.h" #include "mbtlib.h" #if 0 extern int check_integrity(void *img, unsigned int img_len); extern int get_auth_param(const auth_param_type_desc_t *type_desc, void *img, unsigned int img_len, void **param, unsigned int *param_len); extern int verify_signature(void *data_ptr, unsigned int data_len, void *sig_ptr, unsigned int sig_len, void *sig_alg, unsigned int sig_alg_len, void *pk_ptr, unsigned int pk_len ); extern int verify_hash(void *data_ptr, unsigned int data_len, void *digest_info_ptr, unsigned int digest_info_len); #else #define MBEDTLS_IO_BUF_MAX (64 * 1024) tls_handle g_tls_handle = NULL; static fip_handle g_secboot_fh; uint32_t my_pk_len = 0; void *g_io_read_buf = NULL; /* * boot33: * alloc big heap space for io read buffer, emmc will read use DMA. */ int tls_io_read(uint64_t addr, void **data, size_t *size) { int ret; /*image data total length */ size_t ilen = *size; if (addr == 0 || data == NULL || size == NULL) { return -1; } /*alloc io buf <= 64K and aligned with 8 byte needed by dma*/ uint32_t cnt = (ilen > MBEDTLS_IO_BUF_MAX) ? MBEDTLS_IO_BUF_MAX : ilen; if (g_io_read_buf == NULL) { g_io_read_buf = (void *)calloc(sizeof(uint64_t), cnt); memset(g_io_read_buf, 0, cnt); } if (!g_io_read_buf) { ret = 0; goto cleanup; } if (IOT_ERR_SUCCESS != read_data_from_memory(addr, cnt, g_io_read_buf)) { ret = 0; goto cleanup; } *data = g_io_read_buf; *size = cnt; ret = cnt; cleanup: return ret; } /* * secboot: * Encapsulation of tls interfaces for transplantation. */ static int check_integrity(void *img, unsigned int img_len) { if (g_tls_handle == NULL) { return -1; } return tls_x509_check_integrity(g_tls_handle, img, img_len); } static int get_auth_param(const tls_auth_param_type_desc_t *type_desc, void *img, unsigned int img_len, void **param, unsigned int *param_len) { if (g_tls_handle == NULL) { return -1; } return tls_x509_get_auth_param(g_tls_handle, type_desc, img, img_len, param, param_len); } static int verify_signature(void *data_ptr, unsigned int data_len, void *sig_ptr, unsigned int sig_len, void *sig_alg, unsigned int sig_alg_len, void *pk_ptr, unsigned int pk_len) { if (g_tls_handle == NULL) { return -1; } return tls_verify_signature(g_tls_handle, data_ptr, data_len, sig_ptr, sig_len, sig_alg, sig_alg_len, pk_ptr, pk_len); } static int verify_hash(void *data_ptr, unsigned int data_len, void *digest_info_ptr, unsigned int digest_info_len) { int ret = 0; if (g_tls_handle == NULL) { return -1; } //uart_printf("[%s][%d]\r\n",__func__,__LINE__); ret = tls_verify_hash_from_io_dev(g_tls_handle, data_ptr, data_len, digest_info_ptr, digest_info_len, NULL); if (g_io_read_buf != NULL) { free(g_io_read_buf); g_io_read_buf = NULL; } return ret; } unsigned int get_my_pk_len(void) { SECBOOT_DBG("[SECBOOT][%s]=%d\r\n", __func__, (int)my_pk_len); return my_pk_len; } int secboot_is_fuse_enabled(void) { char *value = asr_property_get("bl1.secureboot"); if(value && (strncmp("1",value,1)==0)){ return 1; }else{ return 0; } //return 1; } #endif //static sb_issue_item_list static const sb_issue_item_map_t sb_issue_item_list[] = { {ITEM_CP ,"CP" ,ASR_OS_CP_KEY_CERT_ID ,ASR_OS_CP_IMAGE_ID ,NON_TRUSTED_CP_HASH_OID } ,{ITEM_DSP ,"DSP" ,ASR_OS_DSP_KEY_CERT_ID ,ASR_OS_DSP_IMAGE_ID ,NON_TRUSTED_DSP_HASH_OID } ,{ITEM_APP ,"APP" ,ASR_OS_APP_KEY_CERT_ID ,ASR_OS_APP_IMAGE_ID ,NON_TRUSTED_APP_HASH_OID } ,{ITEM_USER1,"USER1",ASR_OS_USER1_KEY_CERT_ID ,ASR_OS_USER1_IMAGE_ID ,NON_TRUSTED_USER1_HASH_OID } ,{ITEM_USER2,"USER2",ASR_OS_USER2_KEY_CERT_ID ,ASR_OS_USER2_IMAGE_ID ,NON_TRUSTED_USER2_HASH_OID } ,{ITEM_USER3,"USER3",ASR_OS_USER3_KEY_CERT_ID ,ASR_OS_USER3_IMAGE_ID ,NON_TRUSTED_USER3_HASH_OID } ,{ITEM_LOGO ,"LOGO" ,ASR_OS_LOGO_KEY_CERT_ID ,ASR_OS_LOGO_IMAGE_ID ,NON_TRUSTED_LOGO_HASH_OID } ,{ITEM_UPDATER ,"UPDATER" ,ASR_OS_UPDATER_KEY_CERT_ID ,ASR_OS_UPDATER_IMAGE_ID ,NON_TRUSTED_UPDATER_HASH_OID } }; extern unsigned int Load$$IMG_END$$Base; #define IMG_END_ADDR ((unsigned int)&(Load$$IMG_END$$Base)) extern unsigned int Image$$SEC_KEY_BUF$$Base; #define SEC_KEY_ADDR ((unsigned int)&(Image$$SEC_KEY_BUF$$Base)) #define M_HEAP_SIZE 1024*16 static char m_heap[M_HEAP_SIZE]={0}; void secboot_init(const char *pname) { //_rt_heap init _init_alloc(m_heap,m_heap+M_HEAP_SIZE); if (g_tls_handle == NULL) { SECBOOT_DBG("[SECBOOT]tls_init\r\n"); g_tls_handle = tls_init(calloc, free); if (g_tls_handle == NULL) { SECBOOT_DBG("[SECBOOT]tls_init fail\r\n"); goto secboot_fip_error; } } SECBOOT_DBG("[SECBOOT]SEC_KEY_ADDR=[%x]\r\n",SEC_KEY_ADDR); //parser the fwcerts.bin setup fip_image_t of image & certification contents struct ptentry *fipEntry = ptable_find_entry(pname); g_secboot_fh = fip_open((void *)(fipEntry->vstart)); if (g_secboot_fh == NULL) { SECBOOT_DBG("[SECBOOT]fip_open fail\r\n"); goto secboot_fip_error; } return 0; secboot_fip_error: SECBOOT_DBG("[SECBOOT][%s]secboot fip open FAILED\r\n", pname); /*PMIC_PowerDown(); */ return 1; } void secboot_deinit(void) { if (g_tls_handle) { SECBOOT_DBG("[SECBOOT]secboot_deinit\r\n"); tls_deinit(g_tls_handle); g_tls_handle = NULL; } return; } void secboot_item_get_img_addr_size(sb_issue_item_id_t item_id_idx,fip_image_handle item_fih) { int rc = 0; uint32_t start = 0, offset = 0, size = 0; SECBOOT_DBG("[SECBOOT][%s][%d] \r\n",__func__,item_id_idx); //parse the sb_issue_item sb_issue_item_map_t * m_sb_item_ptr = sb_issue_item_list; do{ if(m_sb_item_ptr->item_id >= ITEM_END) goto secboot_error_mark; if(m_sb_item_ptr->item_id == item_id_idx) break; m_sb_item_ptr++; }while(1); rc = fip_get_image_info(g_secboot_fh, m_sb_item_ptr->item_img_id, &start, &offset, &size); if (rc != FIP_SUCCEED){ goto secboot_error_mark; } item_fih->id = m_sb_item_ptr->item_img_id; item_fih->start = start; item_fih->offset = offset; item_fih->size = size; item_fih->read = g_secboot_fh->read; #if 0 SECBOOT_DBG("[SECBOOT]item_fih->id = [0x%0.8x]\r\n",item_fih->id); SECBOOT_DBG("[SECBOOT]item_fih->start = [0x%0.8x]\r\n",item_fih->start); SECBOOT_DBG("[SECBOOT]item_fih->offset = [0x%0.8x]\r\n",item_fih->offset); SECBOOT_DBG("[SECBOOT]item_fih->size = [0x%0.8x]\r\n",item_fih->size); #endif return; secboot_error_mark: SECBOOT_DBG("[SECBOOT][%s][%s]FAILED\r\n",m_sb_item_ptr->item_name,__func__); PMIC_SW_RESET(); return; } /* * secboot: * emmc need alloc new memory to store the cert, xip device read it address directly. * */ uint32_t secboot_read_cert(uint32_t addr, uint32_t size) { /*buffer aligned with 8 byte needed by dma read*/ uint8_t *p_cert = (uint8_t *)calloc(sizeof(uint64_t), size); memset(p_cert, 0, size); if (read_data_from_memory(addr, size, p_cert) != IOT_ERR_SUCCESS) { free((void *)p_cert); return 0; } else { return (uint32_t)p_cert; } } void secboot_free_cert(uint32_t cert_addr) { free((void *)cert_addr); } /* * secboot_item_check: * verify signature of certificate and verify image by hash from certificate. * * input: * item_id_idx: index of image item * */ void secboot_item_check(sb_issue_item_id_t item_id_idx) { unsigned long startTime,endTime; int rc = 0; uint32_t start = 0, offset = 0, size = 0; startTime = GetTimer0CNT(); uint32_t cert_addr = 0; SECBOOT_DBG("[SECBOOT]sb_item item_id = [%d] check\r\n",item_id_idx); //parse the sb_issue_item sb_issue_item_map_t * m_sb_item_ptr = sb_issue_item_list; do{ if(m_sb_item_ptr->item_id >= ITEM_END){ SECBOOT_DBG("[SECBOOT]sb_item [%d][%d][%d] index error \r\n", item_id_idx,m_sb_item_ptr->item_id,ITEM_END); goto secboot_error; } if(m_sb_item_ptr->item_id == item_id_idx){ //bingo SECBOOT_DBG("[SECBOOT]sb_item [%d][%s][%d][%d][%s]\r\n", m_sb_item_ptr->item_id, m_sb_item_ptr->item_name, m_sb_item_ptr->item_cert_id, m_sb_item_ptr->item_img_id, m_sb_item_ptr->item_hash_oid ); break; } m_sb_item_ptr++; }while(1); //certification fip image parser setup fip_image_t cert_toc_fip; fip_image_handle cert_toc_fih = &cert_toc_fip; rc = fip_get_image_info(g_secboot_fh, m_sb_item_ptr->item_cert_id, &start, &offset, &size); if (rc == FIP_ERR_IMG_MISS) { SECBOOT_DBG("[SECBOOT]fip_get_image_info [%d] with FIP_ERR_IMG_MISS, just skip", m_sb_item_ptr->item_cert_id); return; }else if (rc != FIP_SUCCEED){ goto secboot_error; } cert_toc_fih->id = m_sb_item_ptr->item_img_id; cert_toc_fih->start = (uint32_t)start; cert_toc_fih->offset = (uint32_t)offset; cert_toc_fih->size = (uint32_t)size; cert_toc_fih->read = g_secboot_fh->read; //image fip image parser setup fip_image_t img_toc_fip; fip_image_handle img_toc_fih = &img_toc_fip; rc = fip_get_image_info(g_secboot_fh, m_sb_item_ptr->item_img_id, &start, &offset, &size); if (rc != FIP_SUCCEED) { goto secboot_error; } img_toc_fip.id = m_sb_item_ptr->item_img_id; img_toc_fip.start = (uint32_t)start; img_toc_fip.offset = (uint32_t)offset; img_toc_fip.size = (uint32_t)size; img_toc_fip.read = g_secboot_fh->read; cert_addr = secboot_read_cert((cert_toc_fih->start + cert_toc_fih->offset), cert_toc_fih->size); if (cert_addr == 0) { goto secboot_error; } #if 0 SECBOOT_DBG("[SECBOOT]cert_toc_fih->id = [0x%0.8x]\r\n",cert_toc_fih->id); SECBOOT_DBG("[SECBOOT]cert_toc_fih->start = [0x%0.8x]\r\n",cert_toc_fih->start); SECBOOT_DBG("[SECBOOT]cert_toc_fih->offset = [0x%0.8x]\r\n",cert_toc_fih->offset); SECBOOT_DBG("[SECBOOT]cert_toc_fih->size = [0x%0.8x]\r\n",cert_toc_fih->size); SECBOOT_DBG("[SECBOOT]img_toc_fih->id = [0x%0.8x]\r\n",img_toc_fih->id); SECBOOT_DBG("[SECBOOT]img_toc_fih->start = [0x%0.8x]\r\n",img_toc_fih->start); SECBOOT_DBG("[SECBOOT]img_toc_fih->offset = [0x%0.8x]\r\n",img_toc_fih->offset); SECBOOT_DBG("[SECBOOT]img_toc_fih->size = [0x%0.8x]\r\n",img_toc_fih->size); #endif //STEP2 //check integrity of the certification content SECBOOT_DBG("[SECBOOT][%s]cert check_integrity start\r\n",m_sb_item_ptr->item_name); rc = check_integrity((void *)cert_addr, cert_toc_fih->size); SECBOOT_DBG("[SECBOOT][%s]cert check_integrity done rc = %d\r\n",m_sb_item_ptr->item_name,rc); if(rc) goto secboot_error; //STEP3 /*verify signature */ tls_auth_param_type_desc_t sig_param_desc = { AROM_TLS_AUTH_PARAM_SIG, 0 }; char *sig_ptr; unsigned int sig_len; get_auth_param(&sig_param_desc, NULL, 0, (void **)&sig_ptr, &sig_len); #if 0 SECBOOT_DBG("[SECBOOT]DUMP SIG\r\n"); display_binary(sig_ptr,sig_len); #endif tls_auth_param_type_desc_t sig_alg_param_desc = { AROM_TLS_AUTH_PARAM_SIG_ALG, 0 }; char *sig_alg_ptr; unsigned int sig_alg_len; get_auth_param(&sig_alg_param_desc, NULL, 0, (void **)&sig_alg_ptr, &sig_alg_len); #if 0 SECBOOT_DBG("[SECBOOT]DUMP SIG_ALG\r\n"); display_binary(sig_alg_ptr,sig_alg_len); #endif tls_auth_param_type_desc_t pk_param_desc = { AROM_TLS_AUTH_PARAM_PUB_KEY, 0 }; char *pk_ptr; unsigned int pk_len; get_auth_param(&pk_param_desc, NULL, 0, (void **)&pk_ptr, &pk_len); //20201204. for fwcert auth workaround if(memcmp(pk_ptr,SEC_KEY_ADDR,pk_len) != 0) { SECBOOT_DBG("[SECBOOT]PK UNMATCH \r\n"); my_pk_len = pk_len; goto secboot_error; } else { /*for PK passby to updater to append */ SECBOOT_DBG("[SECBOOT]PK MATCH!pk_len=%d\r\n", pk_len); my_pk_len = pk_len; } tls_auth_param_type_desc_t tbs_param_desc = { AROM_TLS_AUTH_PARAM_RAW_DATA, 0 }; char *tbs_ptr; unsigned int tbs_len; get_auth_param(&tbs_param_desc, NULL, 0, (void **)&tbs_ptr, &tbs_len); #if 0 SECBOOT_DBG("[SECBOOT]DUMP TBS\r\n"); display_binary(tbs_ptr,tbs_len); #endif rc = verify_signature((void*)tbs_ptr,tbs_len, sig_ptr,sig_len, sig_alg_ptr,sig_alg_len, pk_ptr,pk_len ); if (rc) { SECBOOT_DBG("[SECBOOT] verify_signature failed with rc=[%d]\r\n", rc); goto secboot_error; } //STEP4 //verify image tls_auth_param_type_desc_t img_auth_param_desc = { AROM_TLS_AUTH_PARAM_HASH, (void *)m_sb_item_ptr->item_hash_oid }; char *img_hash_ptr; unsigned int img_hash_len; get_auth_param(&img_auth_param_desc, NULL, 0, (void **)&img_hash_ptr, &img_hash_len); #if 0 SECBOOT_DBG("[SECBOOT]DUMP EXT hash_oid[]\r\n"); display_binary(img_hash_ptr,img_hash_len); #endif SECBOOT_DBG("[SECBOOT][%s]img_content verify_hash start\r\n",m_sb_item_ptr->item_name); uint32_t image_addr = img_toc_fih->start+ img_toc_fih->offset; uint32_t image_size = img_toc_fih->size; #ifdef SPINOR_SUPPORT if((image_addr & SPI_FLASH_BASE) == SPI_FLASH_BASE) { uint8_t *pFlashBuf = (uint8_t *)(SEC_KEY_ADDR+0x400);//load ext flash data to psram //if(pFlashBuf == NULL){ // SECBOOT_DBG("[SECBOOT]img_content verify_hash malloc fail, image_size = [0x%0.8x]\r\n",image_size); // goto secboot_error; //} //memset(pFlashBuf, 0, size); crane_ext_spi_read(image_addr - SPI_FLASH_BASE, pFlashBuf, image_size); rc = verify_hash((void*)pFlashBuf,image_size, img_hash_ptr,img_hash_len); //free((void *)pFlashBuf); } else #endif { rc = verify_hash((void*)image_addr,image_size, img_hash_ptr,img_hash_len); } SECBOOT_DBG("[SECBOOT][%s]img_content verify_hash done rc = %d\r\n",m_sb_item_ptr->item_name,rc); if(rc) goto secboot_error; endTime = GetTimer0CNT(); SECBOOT_DBG("[SECBOOT][%s]secboot check done SUCCEED\r\n",m_sb_item_ptr->item_name); SECBOOT_DBG("[SECBOOT][%s]secboot time consumption = %ld ms\r\n", m_sb_item_ptr->item_name,Timer0IntervalInMilli(startTime,endTime)); if (cert_addr != 0) { secboot_free_cert(cert_addr); } return; secboot_error: if (cert_addr != 0) { secboot_free_cert(cert_addr); } endTime = GetTimer0CNT(); SECBOOT_DBG("[SECBOOT][%s]secboot check done FAILED\r\n",m_sb_item_ptr->item_name); SECBOOT_DBG("[SECBOOT][%s]secboot time consumption = %ld ms\r\n", m_sb_item_ptr->item_name,Timer0IntervalInMilli(startTime,endTime)); PMIC_SW_RESET(); return; } /* * secboot_get_signature: * get signature from fip content * * input: * item_id_idx: index of image item corresponding to the signature. * psig_ptr: pointer to signature content pointer, * the signature memory allocated in this function and should be relased after used. * psig_len: pointer to store signature length. * * return: * if success return 0, else return -1 */ static int secboot_get_signature(sb_issue_item_id_t item_id_idx, char **psig_ptr, uint32_t *psig_len) { int rc = 0; uint32_t start = 0, offset = 0, size = 0; const sb_issue_item_map_t *m_sb_item_ptr = sb_issue_item_list; uint32_t cert_addr = 0; if (item_id_idx > ITEM_END) { return -1; } if (psig_ptr == NULL) { return -1; } if (psig_len == NULL) { return -1; } /*find sb_issue_item by item_id */ do { if (m_sb_item_ptr->item_id >= ITEM_END) { SECBOOT_DBG("[SECBOOT]sb_item [%d][%d][%d] index error ", item_id_idx, m_sb_item_ptr->item_id, ITEM_END); goto error; } if (m_sb_item_ptr->item_id == item_id_idx) { /*bingo */ SECBOOT_DBG("[SECBOOT]sb_item [%d][%s][%d][%d][%s]", m_sb_item_ptr->item_id, m_sb_item_ptr->item_name, m_sb_item_ptr->item_cert_id, m_sb_item_ptr->item_img_id, m_sb_item_ptr->item_hash_oid); break; } m_sb_item_ptr++; } while (1); /*read cert from fip */ static fip_image_t cert_toc_fip; static fip_image_handle cert_toc_fih = &cert_toc_fip; rc = fip_get_image_info(g_secboot_fh, m_sb_item_ptr->item_cert_id, &start, &offset, &size); if (rc == FIP_ERR_IMG_MISS) { SECBOOT_DBG("[SECBOOT]fip_get_image_info [%d] with FIP_ERR_IMG_MISS, just skip", m_sb_item_ptr->item_cert_id); return rc; } else if (rc != FIP_SUCCEED) { goto error; } cert_toc_fih->id = m_sb_item_ptr->item_img_id; cert_toc_fih->start = (uint32_t)start; /*not use */ cert_toc_fih->offset = (uint32_t)offset; cert_toc_fih->size = (uint32_t)size; cert_toc_fih->read = g_secboot_fh->read; cert_addr = secboot_read_cert((cert_toc_fih->start + cert_toc_fih->offset), cert_toc_fih->size); if (cert_addr == 0) { goto error; } /*parse certification content */ rc = check_integrity((void *)(cert_addr), cert_toc_fih->size); if (rc) { goto error; } /*get signature */ tls_auth_param_type_desc_t sig_param_desc = { AROM_TLS_AUTH_PARAM_SIG, 0 }; char *sig_ptr; unsigned int sig_len; get_auth_param(&sig_param_desc, NULL, 0, (void **)&sig_ptr, &sig_len); /*get sig_ptr */ *psig_len = sig_len; *psig_ptr = calloc(1, sig_len); if (*psig_ptr == NULL) { goto error; } memcpy(*psig_ptr, sig_ptr, sig_len); if (cert_addr != 0) { secboot_free_cert(cert_addr); } return rc; error: if (cert_addr != 0) { secboot_free_cert(cert_addr); } return -1; }