Add Broadcom / Netgear changes from RAXE 1.0.0.48
[project/bcm63xx/u-boot.git] / board / broadcom / bcmbca / board_secure_sdk.c
diff --git a/board/broadcom/bcmbca/board_secure_sdk.c b/board/broadcom/bcmbca/board_secure_sdk.c
new file mode 100644 (file)
index 0000000..bf3e3f8
--- /dev/null
@@ -0,0 +1,133 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2020 Broadcom Ltd.
+ */
+#include <common.h>
+#include <wdt.h>
+#include <fdtdec.h>
+#include <asm/types.h>
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include <asm/unaligned.h>
+#include <malloc.h>
+#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 <u-boot/sha256.h>
+#include <uboot_aes.h>
+#include <watchdog.h>
+
+#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;
+}