diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/ap.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-tegra/cpu.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/crypto.c | 184 | ||||
-rw-r--r-- | arch/arm/mach-tegra/fuse.c | 63 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra114/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra124/bct.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra20/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra20/bct.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra20/warmboot.c | 117 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra30/Kconfig | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra30/bct.c | 20 |
12 files changed, 177 insertions, 273 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index c3c352eceb1..32cdfebfc01 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -17,7 +17,9 @@ config TEGRA_CLKRST config TEGRA_CRYPTO bool "Tegra AES128 crypto module" + select DM_AES select AES + select TEGRA_AES config TEGRA_GP_PADCTRL bool diff --git a/arch/arm/mach-tegra/ap.c b/arch/arm/mach-tegra/ap.c index f35bdba4d48..a7938ed7910 100644 --- a/arch/arm/mach-tegra/ap.c +++ b/arch/arm/mach-tegra/ap.c @@ -37,6 +37,14 @@ int tegra_get_chip(void) return rev; } +u32 tegra_get_major_version(void) +{ + struct apb_misc_gp_ctlr *gp = + (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; + + return (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> HIDREV_MAJORPREV_SHIFT; +} + int tegra_get_sku_info(void) { int sku_id; diff --git a/arch/arm/mach-tegra/cpu.h b/arch/arm/mach-tegra/cpu.h index 006aae3d070..5477423f4d0 100644 --- a/arch/arm/mach-tegra/cpu.h +++ b/arch/arm/mach-tegra/cpu.h @@ -71,6 +71,7 @@ void powerup_cpu(void); void reset_A9_cpu(int reset); void start_cpu(u32 reset_vector); int tegra_get_chip(void); +u32 tegra_get_major_version(void); int tegra_get_sku_info(void); int tegra_get_chip_sku(void); void adjust_pllp_out_freqs(void); diff --git a/arch/arm/mach-tegra/crypto.c b/arch/arm/mach-tegra/crypto.c index 49e6a45243a..1005c815b36 100644 --- a/arch/arm/mach-tegra/crypto.c +++ b/arch/arm/mach-tegra/crypto.c @@ -4,164 +4,68 @@ * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> */ +#include <dm.h> #include <log.h> #include <linux/errno.h> #include <asm/arch-tegra/crypto.h> #include "uboot_aes.h" -static u8 zero_key[16]; - -#define AES_CMAC_CONST_RB 0x87 /* from RFC 4493, Figure 2.2 */ - -enum security_op { - SECURITY_SIGN = 1 << 0, /* Sign the data */ - SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */ - SECURITY_DECRYPT = 1 << 2, /* Dectypt the data */ -}; - -/** - * Shift a vector left by one bit - * - * \param in Input vector - * \param out Output vector - * \param size Length of vector in bytes - */ -static void left_shift_vector(u8 *in, u8 *out, int size) +int sign_data_block(u8 *source, unsigned int length, u8 *signature) { - int carry = 0; - int i; - - for (i = size - 1; i >= 0; i--) { - out[i] = (in[i] << 1) | carry; - carry = in[i] >> 7; /* get most significant bit */ + struct udevice *dev; + int ret; + + /* Only one AES engine should be present */ + ret = uclass_get_device(UCLASS_AES, 0, &dev); + if (ret) { + log_err("%s: failed to get tegra_aes: %d\n", __func__, ret); + return ret; } -} - -/** - * Sign a block of data, putting the result into dst. - * - * \param key Input AES key, length AES128_KEY_LENGTH - * \param key_schedule Expanded key to use - * \param src Source data of length 'num_aes_blocks' blocks - * \param dst Destination buffer, length AES128_KEY_LENGTH - * \param num_aes_blocks Number of AES blocks to encrypt - */ -static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, - u32 num_aes_blocks) -{ - u8 tmp_data[AES128_KEY_LENGTH]; - u8 iv[AES128_KEY_LENGTH] = {0}; - u8 left[AES128_KEY_LENGTH]; - u8 k1[AES128_KEY_LENGTH]; - u8 *cbc_chain_data; - unsigned int i; - cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ + ret = dm_aes_select_key_slot(dev, 128, TEGRA_AES_SLOT_SBK); + if (ret) + return ret; - /* compute K1 constant needed by AES-CMAC calculation */ - for (i = 0; i < AES128_KEY_LENGTH; i++) - tmp_data[i] = 0; - - aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, - tmp_data, left, 1); - - left_shift_vector(left, k1, sizeof(left)); - - if ((left[0] >> 7) != 0) /* get MSB of L */ - k1[AES128_KEY_LENGTH - 1] ^= AES_CMAC_CONST_RB; - - /* compute the AES-CMAC value */ - for (i = 0; i < num_aes_blocks; i++) { - /* Apply the chain data */ - aes_apply_cbc_chain_data(cbc_chain_data, src, tmp_data); - - /* for the final block, XOR K1 into the IV */ - if (i == num_aes_blocks - 1) - aes_apply_cbc_chain_data(tmp_data, k1, tmp_data); - - /* encrypt the AES block */ - aes_encrypt(AES128_KEY_LENGTH, tmp_data, - key_schedule, dst); - - debug("sign_obj: block %d of %d\n", i, num_aes_blocks); - - /* Update pointers for next loop. */ - cbc_chain_data = dst; - src += AES128_KEY_LENGTH; - } + return dm_aes_cmac(dev, source, signature, + DIV_ROUND_UP(length, AES_BLOCK_LENGTH)); } -/** - * Decrypt, encrypt or sign a block of data (depending on security mode). - * - * \param key Input AES key, length AES128_KEY_LENGTH - * \param oper Security operations mask to perform (enum security_op) - * \param src Source data - * \param length Size of source data - * \param sig_dst Destination address for signature, AES128_KEY_LENGTH bytes - */ -static int tegra_crypto_core(u8 *key, enum security_op oper, u8 *src, - u32 length, u8 *sig_dst) +int encrypt_data_block(u8 *source, u8 *dest, unsigned int length) { - u32 num_aes_blocks; - u8 key_schedule[AES128_EXPAND_KEY_LENGTH]; - u8 iv[AES128_KEY_LENGTH] = {0}; - - debug("%s: length = %d\n", __func__, length); - - aes_expand_key(key, AES128_KEY_LENGTH, key_schedule); - - num_aes_blocks = (length + AES128_KEY_LENGTH - 1) / AES128_KEY_LENGTH; - - if (oper & SECURITY_DECRYPT) { - /* Perform this in place, resulting in src being decrypted. */ - debug("%s: begin decryption\n", __func__); - aes_cbc_decrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src, - src, num_aes_blocks); - debug("%s: end decryption\n", __func__); - } - - if (oper & SECURITY_ENCRYPT) { - /* Perform this in place, resulting in src being encrypted. */ - debug("%s: begin encryption\n", __func__); - aes_cbc_encrypt_blocks(AES128_KEY_LENGTH, key_schedule, iv, src, - src, num_aes_blocks); - debug("%s: end encryption\n", __func__); - } - - if (oper & SECURITY_SIGN) { - /* encrypt the data, overwriting the result in signature. */ - debug("%s: begin signing\n", __func__); - sign_object(key, key_schedule, src, sig_dst, num_aes_blocks); - debug("%s: end signing\n", __func__); + struct udevice *dev; + int ret; + + /* Only one AES engine should be present */ + ret = uclass_get_device(UCLASS_AES, 0, &dev); + if (ret) { + log_err("%s: failed to get tegra_aes: %d\n", __func__, ret); + return ret; } - return 0; -} + ret = dm_aes_select_key_slot(dev, 128, TEGRA_AES_SLOT_SBK); + if (ret) + return ret; -/** - * Tegra crypto group - */ -int sign_data_block(u8 *source, unsigned int length, u8 *signature) -{ - return tegra_crypto_core(zero_key, SECURITY_SIGN, source, - length, signature); + return dm_aes_cbc_encrypt(dev, (u8 *)AES_ZERO_BLOCK, source, dest, + DIV_ROUND_UP(length, AES_BLOCK_LENGTH)); } -int sign_enc_data_block(u8 *source, unsigned int length, u8 *signature, u8 *key) +int decrypt_data_block(u8 *source, u8 *dest, unsigned int length) { - return tegra_crypto_core(key, SECURITY_SIGN, source, - length, signature); -} + struct udevice *dev; + int ret; + + /* Only one AES engine should be present */ + ret = uclass_get_device(UCLASS_AES, 0, &dev); + if (ret) { + log_err("%s: failed to get tegra_aes: %d\n", __func__, ret); + return ret; + } -int encrypt_data_block(u8 *source, unsigned int length, u8 *key) -{ - return tegra_crypto_core(key, SECURITY_ENCRYPT, source, - length, NULL); -} + ret = dm_aes_select_key_slot(dev, 128, TEGRA_AES_SLOT_SBK); + if (ret) + return ret; -int decrypt_data_block(u8 *source, unsigned int length, u8 *key) -{ - return tegra_crypto_core(key, SECURITY_DECRYPT, source, - length, NULL); + return dm_aes_cbc_decrypt(dev, (u8 *)AES_ZERO_BLOCK, source, dest, + DIV_ROUND_UP(length, AES_BLOCK_LENGTH)); } diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index e9b5259ac70..abdf6504161 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -39,7 +39,7 @@ static u32 tegra_fuse_readl(unsigned long offset) return readl(NV_PA_FUSE_BASE + offset); } -static void tegra_fuse_init(void) +void tegra_fuse_init(void) { u32 reg; @@ -49,8 +49,11 @@ static void tegra_fuse_init(void) * this bit fuse region will not work. */ reg = readl_relaxed(NV_PA_CLK_RST_BASE + 0x48); - reg |= BIT(28); - writel(reg, NV_PA_CLK_RST_BASE + 0x48); + + if (reg & BIT(28)) + return; + + writel(reg | BIT(28), NV_PA_CLK_RST_BASE + 0x48); clock_enable(PERIPH_ID_FUSE); udelay(2); @@ -148,3 +151,57 @@ unsigned long long tegra_chip_uid(void) return uid; } + +static int tegra_is_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->production_mode); +} + +static int tegra_is_odm_production_mode_fuse_set(struct fuse_regs *fuse) +{ + return readl(&fuse->security_mode); +} + +static int tegra_is_failure_analysis_mode(struct fuse_regs *fuse) +{ + return readl(&fuse->fa); +} + +static int tegra_is_sbk_zeroes(struct fuse_regs *fuse) +{ + int i; + + for (i = 0; i < 4; i++) + if (readl(&fuse->sbk[i])) + return 0; + + return 1; +} + +static int tegra_is_production_mode(struct fuse_regs *fuse) +{ + if (!tegra_get_major_version()) + return 1; + + return !tegra_is_failure_analysis_mode(fuse) && + tegra_is_production_mode_fuse_set(fuse); +} + +enum fuse_operating_mode tegra_fuse_get_operation_mode(void) +{ + struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; + + tegra_fuse_init(); + + if (tegra_is_production_mode(fuse)) { + if (!tegra_is_odm_production_mode_fuse_set(fuse)) + return MODE_PRODUCTION; + else + if (tegra_is_sbk_zeroes(fuse)) + return MODE_ODM_PRODUCTION_OPEN; + else + return MODE_ODM_PRODUCTION_SECURE; + } + + return MODE_UNDEFINED; +} diff --git a/arch/arm/mach-tegra/tegra114/Kconfig b/arch/arm/mach-tegra/tegra114/Kconfig index 98f1d0e71c1..43dd59fb113 100644 --- a/arch/arm/mach-tegra/tegra114/Kconfig +++ b/arch/arm/mach-tegra/tegra114/Kconfig @@ -8,6 +8,10 @@ config TARGET_DALMORE bool "NVIDIA Tegra114 Dalmore evaluation board" select BOARD_LATE_INIT +config TARGET_SURFACE_2 + bool "Microsoft Surface 2" + select BOARD_LATE_INIT + config TARGET_TEGRATAB bool "NVIDIA Tegra114 TegraTab evaluation board" select BOARD_LATE_INIT @@ -22,6 +26,7 @@ config SYS_SOC default "tegra114" source "board/nvidia/dalmore/Kconfig" +source "board/microsoft/surface-2/Kconfig" source "board/nvidia/tegratab/Kconfig" source "board/asus/transformer-t114/Kconfig" diff --git a/arch/arm/mach-tegra/tegra124/bct.c b/arch/arm/mach-tegra/tegra124/bct.c index 4dc4b7138ab..676b68dc5de 100644 --- a/arch/arm/mach-tegra/tegra124/bct.c +++ b/arch/arm/mach-tegra/tegra124/bct.c @@ -9,12 +9,10 @@ #include <vsprintf.h> #include <linux/string.h> #include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> #include "bct.h" #include "uboot_aes.h" -/* Device with "sbk burned: false" will expose zero key */ -const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; - /* * @param bct boot config table start in RAM * @param ect bootloader start in RAM @@ -26,29 +24,25 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) struct nvboot_config_table *bct_tbl = NULL; u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; u8 bct_hash[AES128_KEY_LENGTH] = { 0 }; - u8 sbk[AES128_KEY_LENGTH] = { 0 }; u8 *sbct = bct + UBCT_LENGTH; bool encrypted; int ret; ebt_size = roundup(ebt_size, EBT_ALIGNMENT); - memcpy(sbk, (u8 *)(bct + UBCT_LENGTH + SBCT_LENGTH), - NVBOOT_CMAC_AES_HASH_LENGTH * 4); - - encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + encrypted = tegra_fuse_get_operation_mode() == MODE_ODM_PRODUCTION_SECURE; if (encrypted) { - ret = decrypt_data_block(sbct, SBCT_LENGTH, sbk); + ret = decrypt_data_block(sbct, sbct, SBCT_LENGTH); if (ret) return 1; - ret = encrypt_data_block(ebt, ebt_size, sbk); + ret = encrypt_data_block(ebt, ebt, ebt_size); if (ret) return 1; } - ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + ret = sign_data_block(ebt, ebt_size, ebt_hash); if (ret) return 1; @@ -61,12 +55,12 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) bct_tbl->bootloader[0].length = ebt_size; if (encrypted) { - ret = encrypt_data_block(sbct, SBCT_LENGTH, sbk); + ret = encrypt_data_block(sbct, sbct, SBCT_LENGTH); if (ret) return 1; } - ret = sign_enc_data_block(sbct, SBCT_LENGTH, bct_hash, sbk); + ret = sign_data_block(sbct, SBCT_LENGTH, bct_hash); if (ret) return 1; diff --git a/arch/arm/mach-tegra/tegra20/Kconfig b/arch/arm/mach-tegra/tegra20/Kconfig index bedbedade7b..b07b5a15585 100644 --- a/arch/arm/mach-tegra/tegra20/Kconfig +++ b/arch/arm/mach-tegra/tegra20/Kconfig @@ -54,6 +54,10 @@ config TARGET_SEABOARD select TEGRA_LP0 select TEGRA_PMU +config TARGET_SAMSUNG_N1 + bool "Samsung Tegra20 N1 board" + select BOARD_LATE_INIT + config TARGET_STAR bool "LG Tegra20 Star board" select BOARD_LATE_INIT @@ -92,6 +96,7 @@ source "board/compal/paz00/Kconfig" source "board/acer/picasso/Kconfig" source "board/avionic-design/plutux/Kconfig" source "board/nvidia/seaboard/Kconfig" +source "board/samsung/n1/Kconfig" source "board/lg/star/Kconfig" source "board/avionic-design/tec/Kconfig" source "board/asus/transformer-t20/Kconfig" diff --git a/arch/arm/mach-tegra/tegra20/bct.c b/arch/arm/mach-tegra/tegra20/bct.c index 253cb243676..0270cf592c1 100644 --- a/arch/arm/mach-tegra/tegra20/bct.c +++ b/arch/arm/mach-tegra/tegra20/bct.c @@ -9,12 +9,10 @@ #include <vsprintf.h> #include <linux/string.h> #include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> #include "bct.h" #include "uboot_aes.h" -/* Device with "sbk burned: false" will expose zero key */ -const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; - /* * @param bct boot config table start in RAM * @param ect bootloader start in RAM @@ -25,7 +23,6 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) { struct nvboot_config_table *bct_tbl = NULL; u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; - u8 sbk[AES128_KEY_LENGTH] = { 0 }; u8 *bct_hash = bct; bool encrypted; int ret; @@ -34,22 +31,19 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) ebt_size = roundup(ebt_size, EBT_ALIGNMENT); - memcpy(sbk, (u8 *)(bct + BCT_LENGTH), - NVBOOT_CMAC_AES_HASH_LENGTH * 4); - - encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + encrypted = tegra_fuse_get_operation_mode() == MODE_ODM_PRODUCTION_SECURE; if (encrypted) { - ret = decrypt_data_block(bct, BCT_LENGTH, sbk); + ret = decrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; - ret = encrypt_data_block(ebt, ebt_size, sbk); + ret = encrypt_data_block(ebt, ebt, ebt_size); if (ret) return 1; } - ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + ret = sign_data_block(ebt, ebt_size, ebt_hash); if (ret) return 1; @@ -62,12 +56,12 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) bct_tbl->bootloader[0].length = ebt_size; if (encrypted) { - ret = encrypt_data_block(bct, BCT_LENGTH, sbk); + ret = encrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; } - ret = sign_enc_data_block(bct, BCT_LENGTH, bct_hash, sbk); + ret = sign_data_block(bct, BCT_LENGTH, bct_hash); if (ret) return 1; diff --git a/arch/arm/mach-tegra/tegra20/warmboot.c b/arch/arm/mach-tegra/tegra20/warmboot.c index 18034c83a1c..3fd39fe3c1a 100644 --- a/arch/arm/mach-tegra/tegra20/warmboot.c +++ b/arch/arm/mach-tegra/tegra20/warmboot.c @@ -19,6 +19,7 @@ #include <asm/arch-tegra/pmc.h> #include <asm/arch-tegra/fuse.h> #include <asm/arch-tegra/warmboot.h> +#include <asm/arch-tegra/crypto.h> DECLARE_GLOBAL_DATA_PTR; @@ -182,98 +183,36 @@ int warmboot_save_sdram_params(void) return 0; } -static u32 get_major_version(void) +static void determine_crypto_options(int *is_encrypted, int *is_signed) { - u32 major_id; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; - - major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> - HIDREV_MAJORPREV_SHIFT; - return major_id; -} - -static int is_production_mode_fuse_set(struct fuse_regs *fuse) -{ - return readl(&fuse->production_mode); -} - -static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) -{ - return readl(&fuse->security_mode); -} - -static int is_failure_analysis_mode(struct fuse_regs *fuse) -{ - return readl(&fuse->fa); -} - -static int ap20_is_odm_production_mode(void) -{ - struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; - - if (!is_failure_analysis_mode(fuse) && - is_odm_production_mode_fuse_set(fuse)) - return 1; - else - return 0; -} - -static int ap20_is_production_mode(void) -{ - struct fuse_regs *fuse = (struct fuse_regs *)NV_PA_FUSE_BASE; - - if (get_major_version() == 0) - return 1; - - if (!is_failure_analysis_mode(fuse) && - is_production_mode_fuse_set(fuse) && - !is_odm_production_mode_fuse_set(fuse)) - return 1; - else - return 0; -} - -static enum fuse_operating_mode fuse_get_operation_mode(void) -{ - u32 chip_id; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE; - - chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> - HIDREV_CHIPID_SHIFT; - if (chip_id == CHIPID_TEGRA20) { - if (ap20_is_odm_production_mode()) { - printf("!! odm_production_mode is not supported !!\n"); - return MODE_UNDEFINED; - } else - if (ap20_is_production_mode()) - return MODE_PRODUCTION; - else - return MODE_UNDEFINED; - } - return MODE_UNDEFINED; -} - -static void determine_crypto_options(int *is_encrypted, int *is_signed, - int *use_zero_key) -{ - switch (fuse_get_operation_mode()) { + switch (tegra_fuse_get_operation_mode()) { + case MODE_ODM_PRODUCTION_SECURE: + *is_encrypted = 1; + *is_signed = 1; + break; + case MODE_ODM_PRODUCTION_OPEN: case MODE_PRODUCTION: *is_encrypted = 0; *is_signed = 1; - *use_zero_key = 1; break; case MODE_UNDEFINED: default: *is_encrypted = 0; *is_signed = 0; - *use_zero_key = 0; break; } } -static int sign_wb_code(u32 start, u32 length, int use_zero_key) +static int encrypt_wb_code(u8 *source, u8 *destination, u32 length) +{ + source += offsetof(struct wb_header, random_aes_block); + destination += offsetof(struct wb_header, random_aes_block); + length -= offsetof(struct wb_header, random_aes_block); + + return encrypt_data_block(source, destination, length); +} + +static int sign_wb_code(u32 start, u32 length) { int err; u8 *source; /* Pointer to source */ @@ -295,10 +234,9 @@ int warmboot_prepare_code(u32 seg_address, u32 seg_length) struct wb_header *dst_header; /* Pointer to dest WB header */ int is_encrypted; /* Segment is encrypted */ int is_signed; /* Segment is signed */ - int use_zero_key; /* Use key of all zeros */ /* Determine crypto options. */ - determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key); + determine_crypto_options(&is_encrypted, &is_signed); /* Get the actual code limits. */ length = roundup(((u32)wb_end - (u32)wb_start), 16); @@ -346,18 +284,15 @@ int warmboot_prepare_code(u32 seg_address, u32 seg_length) dst_header->entry_point = NV_WB_RUN_ADDRESS; dst_header->code_length = length; - if (is_encrypted) { - printf("!!!! Encryption is not supported !!!!\n"); - dst_header->length_insecure = 0; - err = -EACCES; - goto fail; - } else - /* copy the wb code directly following dst_header. */ - memcpy((char *)(dst_header+1), (char *)wb_start, length); + if (is_encrypted) + encrypt_wb_code((u8 *)wb_start, (u8 *)dst_header, + length + sizeof(struct wb_header)); + else + /* copy the wb code directly following dst_header */ + memcpy((char *)(dst_header + 1), (char *)wb_start, length); if (is_signed) - err = sign_wb_code(seg_address, dst_header->length_insecure, - use_zero_key); + err = sign_wb_code(seg_address, dst_header->length_insecure); fail: if (err) diff --git a/arch/arm/mach-tegra/tegra30/Kconfig b/arch/arm/mach-tegra/tegra30/Kconfig index b5099ce67fc..4da67b19990 100644 --- a/arch/arm/mach-tegra/tegra30/Kconfig +++ b/arch/arm/mach-tegra/tegra30/Kconfig @@ -16,6 +16,10 @@ config TARGET_CARDHU bool "NVIDIA Tegra30 Cardhu evaluation board" select BOARD_LATE_INIT +config TARGET_CHAGALL + bool "Pegatron Tegra30 Chagall board" + select BOARD_LATE_INIT + config TARGET_COLIBRI_T30 bool "Toradex Colibri T30 board" select BOARD_LATE_INIT @@ -64,6 +68,7 @@ config SYS_SOC source "board/toradex/apalis_t30/Kconfig" source "board/nvidia/beaver/Kconfig" source "board/nvidia/cardhu/Kconfig" +source "board/pegatron/chagall/Kconfig" source "board/toradex/colibri_t30/Kconfig" source "board/htc/endeavoru/Kconfig" source "board/asus/grouper/Kconfig" diff --git a/arch/arm/mach-tegra/tegra30/bct.c b/arch/arm/mach-tegra/tegra30/bct.c index 398ba1de386..de668214517 100644 --- a/arch/arm/mach-tegra/tegra30/bct.c +++ b/arch/arm/mach-tegra/tegra30/bct.c @@ -9,12 +9,10 @@ #include <vsprintf.h> #include <linux/string.h> #include <asm/arch-tegra/crypto.h> +#include <asm/arch-tegra/fuse.h> #include "bct.h" #include "uboot_aes.h" -/* Device with "sbk burned: false" will expose zero key */ -const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; - /* * @param bct boot config table start in RAM * @param ect bootloader start in RAM @@ -25,7 +23,6 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) { struct nvboot_config_table *bct_tbl = NULL; u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; - u8 sbk[AES128_KEY_LENGTH] = { 0 }; u8 *bct_hash = bct; bool encrypted; int ret; @@ -34,22 +31,19 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) ebt_size = roundup(ebt_size, EBT_ALIGNMENT); - memcpy(sbk, (u8 *)(bct + BCT_LENGTH), - NVBOOT_CMAC_AES_HASH_LENGTH * 4); - - encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + encrypted = tegra_fuse_get_operation_mode() == MODE_ODM_PRODUCTION_SECURE; if (encrypted) { - ret = decrypt_data_block(bct, BCT_LENGTH, sbk); + ret = decrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; - ret = encrypt_data_block(ebt, ebt_size, sbk); + ret = encrypt_data_block(ebt, ebt, ebt_size); if (ret) return 1; } - ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + ret = sign_data_block(ebt, ebt_size, ebt_hash); if (ret) return 1; @@ -62,12 +56,12 @@ static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) bct_tbl->bootloader[0].length = ebt_size; if (encrypted) { - ret = encrypt_data_block(bct, BCT_LENGTH, sbk); + ret = encrypt_data_block(bct, bct, BCT_LENGTH); if (ret) return 1; } - ret = sign_enc_data_block(bct, BCT_LENGTH, bct_hash, sbk); + ret = sign_data_block(bct, BCT_LENGTH, bct_hash); if (ret) return 1; |