| /* |
| * Copyright (c) 2019-2020, ARM Limited. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <assert.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include <plat/arm/common/plat_arm.h> |
| #include <plat/common/common_def.h> |
| #include <plat/common/platform.h> |
| |
| #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) |
| |
| static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN]; |
| |
| extern unsigned char arm_rotpk_header[]; |
| |
| /* |
| * Return the ROTPK hash stored in the registers of Juno board. |
| */ |
| static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, |
| unsigned int *flags) |
| { |
| uint8_t *dst; |
| uint32_t *src, tmp; |
| unsigned int words, i; |
| |
| assert(key_ptr != NULL); |
| assert(key_len != NULL); |
| assert(flags != NULL); |
| |
| /* Copy the DER header */ |
| memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN); |
| dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN]; |
| |
| |
| /* |
| * Append the hash from Trusted Root-Key Storage registers. The hash has |
| * not been written linearly into the registers, so we have to do a bit |
| * of byte swapping: |
| * |
| * 0x00 0x04 0x08 0x0C 0x10 0x14 0x18 0x1C |
| * +---------------------------------------------------------------+ |
| * | Reg0 | Reg1 | Reg2 | Reg3 | Reg4 | Reg5 | Reg6 | Reg7 | |
| * +---------------------------------------------------------------+ |
| * | ... ... | | ... ... | |
| * | +--------------------+ | +-------+ |
| * | | | | |
| * +----------------------------+ +----------------------------+ |
| * | | | | |
| * +-------+ | +--------------------+ | |
| * | | | | |
| * v v v v |
| * +---------------------------------------------------------------+ |
| * | | | |
| * +---------------------------------------------------------------+ |
| * 0 15 16 31 |
| * |
| * Additionally, we have to access the registers in 32-bit words |
| */ |
| words = ARM_ROTPK_HASH_LEN >> 3; |
| |
| /* Swap bytes 0-15 (first four registers) */ |
| src = (uint32_t *)TZ_PUB_KEY_HASH_BASE; |
| for (i = 0 ; i < words ; i++) { |
| tmp = src[words - 1 - i]; |
| /* Words are read in little endian */ |
| *dst++ = (uint8_t)((tmp >> 24) & 0xFF); |
| *dst++ = (uint8_t)((tmp >> 16) & 0xFF); |
| *dst++ = (uint8_t)((tmp >> 8) & 0xFF); |
| *dst++ = (uint8_t)(tmp & 0xFF); |
| } |
| |
| /* Swap bytes 16-31 (last four registers) */ |
| src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2); |
| for (i = 0 ; i < words ; i++) { |
| tmp = src[words - 1 - i]; |
| *dst++ = (uint8_t)((tmp >> 24) & 0xFF); |
| *dst++ = (uint8_t)((tmp >> 16) & 0xFF); |
| *dst++ = (uint8_t)((tmp >> 8) & 0xFF); |
| *dst++ = (uint8_t)(tmp & 0xFF); |
| } |
| |
| *key_ptr = (void *)rotpk_hash_der; |
| *key_len = (unsigned int)sizeof(rotpk_hash_der); |
| *flags = ROTPK_IS_HASH; |
| return 0; |
| } |
| |
| #endif |
| |
| /* |
| * Return the ROTPK hash in the following ASN.1 structure in DER format: |
| * |
| * AlgorithmIdentifier ::= SEQUENCE { |
| * algorithm OBJECT IDENTIFIER, |
| * parameters ANY DEFINED BY algorithm OPTIONAL |
| * } |
| * |
| * DigestInfo ::= SEQUENCE { |
| * digestAlgorithm AlgorithmIdentifier, |
| * digest OCTET STRING |
| * } |
| */ |
| int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, |
| unsigned int *flags) |
| { |
| #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \ |
| (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID) |
| return arm_get_rotpk_info_dev(key_ptr, key_len, flags); |
| #elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID) |
| return juno_get_rotpk_info_regs(key_ptr, key_len, flags); |
| #else |
| return 1; |
| #endif |
| } |