/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright 2020 Broadcom Ltd. */ #include #include #include #include #include #include #include #include #include "tpl_params.h" #include "spl_env.h" #include "bcm_secure.h" #include "bcm_otp.h" #include "u-boot/rsa.h" #include "u-boot/rsa-mod-exp.h" #include #include #include #define NODE_NAME_LEN 128 static int sec_key_ctrl(bcm_sec_t *sec, bcm_sec_ctrl_t ctrl, void* arg) { int rc = 0; switch(ctrl) { case SEC_CTRL_KEY_GET: { if ( !(sec->state & SEC_STATE_SECURE)) { u8* env_key = bcm_util_env_var2bin("brcm_pub_testkey", RSA2048_BYTES); /* We've got test key; try to authenticate with it * Only works in non-secure mode * */ if (!env_key) { debug("No Key in environment \n"); } else { memcpy(sec->key.rsa_pub, env_key, RSA2048_BYTES); sec->key.pub = sec->key.rsa_pub; } } } break; case SEC_CTRL_KEY_CHAIN_RSA: if(sec->state & SEC_STATE_SECURE) { int len = 0; u8 * k; int off; off = fdt_path_offset(arg, "/trust/brcm_pub_key"); if (off < 0) { printf("ERROR: Can't find /trust/brcm_pub_key node in boot DTB!\n"); } k = (char*)(fdt_getprop(arg, off, "value", &len)); if (!k || len != RSA2048_BYTES) { rc = -1; printf("ERROR: length %d \n", len); break ; } else { memcpy(sec->key.rsa_pub, k, RSA2048_BYTES); sec->key.pub = sec->key.rsa_pub; } } break; case SEC_CTRL_KEY_CHAIN_AES: if(sec->state & SEC_STATE_SECURE) { int len = 0, alloc_len = 0; char *_keys_prop[2] = {FIT_AES1, FIT_AES2}; bcm_sec_key_arg_t *aes_arg; int off; u8* aes1,aes2; char key_node[NODE_NAME_LEN]; /* Get aes1 */ snprintf(key_node,NODE_NAME_LEN, "/trust/%s", _keys_prop[0]); off = fdt_path_offset(arg, key_node); if (off < 0) { printf("INFO: Can't find %s node in boot DTB!\n", key_node); break; } aes1 = (char*)(fdt_getprop(arg, off, "value", &len)); if (aes1 && len != BCM_SECBT_AES_CBC128_EK_LEN*2) { break; } /* Get aes2 */ snprintf(key_node,NODE_NAME_LEN, "/trust/%s", _keys_prop[1]); off = fdt_path_offset(arg, key_node); if (off < 0) { printf("INFO: Can't find %s node in boot DTB!\n", key_node); break; } aes2 = (char*)(fdt_getprop(arg, off, "value", &len)); if (aes2 && len != BCM_SECBT_AES_CBC128_EK_LEN*2) { break; } alloc_len = sizeof(bcm_sec_key_arg_t) + (aes1 && aes2) ? sizeof(bcm_sec_key_aes_arg_t)*2 : sizeof(bcm_sec_key_aes_arg_t); aes_arg = malloc(alloc_len); if (!aes_arg) { break; } memset(aes_arg, 0, alloc_len); if (aes1) { //printf("Got %s 0x%x\n" , _keys_prop[0], *(u32*)aes1); strcpy(aes_arg->aes[aes_arg->len].id,_keys_prop[0]); memcpy(aes_arg->aes[aes_arg->len].key, aes1, BCM_SECBT_AES_CBC128_EK_LEN*2); aes_arg->len++; } if (aes2) { strcpy(aes_arg->aes[aes_arg->len].id, _keys_prop[1]); memcpy(aes_arg->aes[aes_arg->len].key, aes2, BCM_SECBT_AES_CBC128_EK_LEN*2); //printf("Got %s 0x%x\n" , _keys_prop[1], *(u32*)aes2); aes_arg->len++; } sec->key.ch_ek = aes_arg; } break; case SEC_CTRL_KEY_CLEAN_ALL: bcm_sec_clean_keys(sec); break; default: break; } return rc; } void bcm_sec_cb_init(bcm_sec_t* sec) { sec->cb[SEC_CTRL_ARG_KEY].cb = sec_key_ctrl; }