1 /*
2  * Copyright (c) 2019-2020, ARM Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include <drivers/arm/cryptocell/cc_rotpk.h>
12 #include <plat/arm/common/plat_arm.h>
13 #include <plat/common/common_def.h>
14 #include <plat/common/platform.h>
15 
16 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
17 
18 static unsigned char rotpk_hash_der[ARM_ROTPK_HEADER_LEN + ARM_ROTPK_HASH_LEN];
19 
20 extern unsigned char arm_rotpk_header[];
21 
22 /*
23  * Return the ROTPK hash stored in the registers of Juno board.
24  */
juno_get_rotpk_info_regs(void ** key_ptr,unsigned int * key_len,unsigned int * flags)25 static int juno_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len,
26 			unsigned int *flags)
27 {
28 	uint8_t *dst;
29 	uint32_t *src, tmp;
30 	unsigned int words, i;
31 
32 	assert(key_ptr != NULL);
33 	assert(key_len != NULL);
34 	assert(flags != NULL);
35 
36 	/* Copy the DER header */
37 	memcpy(rotpk_hash_der, arm_rotpk_header, ARM_ROTPK_HEADER_LEN);
38 	dst = (uint8_t *)&rotpk_hash_der[ARM_ROTPK_HEADER_LEN];
39 
40 
41 	/*
42 	 * Append the hash from Trusted Root-Key Storage registers. The hash has
43 	 * not been written linearly into the registers, so we have to do a bit
44 	 * of byte swapping:
45 	 *
46 	 *     0x00    0x04    0x08    0x0C    0x10    0x14    0x18    0x1C
47 	 * +---------------------------------------------------------------+
48 	 * | Reg0  | Reg1  | Reg2  | Reg3  | Reg4  | Reg5  | Reg6  | Reg7  |
49 	 * +---------------------------------------------------------------+
50 	 *  | ...                    ... |   | ...                   ...  |
51 	 *  |       +--------------------+   |                    +-------+
52 	 *  |       |                        |                    |
53 	 *  +----------------------------+   +----------------------------+
54 	 *          |                    |                        |       |
55 	 *  +-------+                    |   +--------------------+       |
56 	 *  |                            |   |                            |
57 	 *  v                            v   v                            v
58 	 * +---------------------------------------------------------------+
59 	 * |                               |                               |
60 	 * +---------------------------------------------------------------+
61 	 *  0                           15  16                           31
62 	 *
63 	 * Additionally, we have to access the registers in 32-bit words
64 	 */
65 	words = ARM_ROTPK_HASH_LEN >> 3;
66 
67 	/* Swap bytes 0-15 (first four registers) */
68 	src = (uint32_t *)TZ_PUB_KEY_HASH_BASE;
69 	for (i = 0 ; i < words ; i++) {
70 		tmp = src[words - 1 - i];
71 		/* Words are read in little endian */
72 		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
73 		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
74 		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
75 		*dst++ = (uint8_t)(tmp & 0xFF);
76 	}
77 
78 	/* Swap bytes 16-31 (last four registers) */
79 	src = (uint32_t *)(TZ_PUB_KEY_HASH_BASE + ARM_ROTPK_HASH_LEN / 2);
80 	for (i = 0 ; i < words ; i++) {
81 		tmp = src[words - 1 - i];
82 		*dst++ = (uint8_t)((tmp >> 24) & 0xFF);
83 		*dst++ = (uint8_t)((tmp >> 16) & 0xFF);
84 		*dst++ = (uint8_t)((tmp >> 8) & 0xFF);
85 		*dst++ = (uint8_t)(tmp & 0xFF);
86 	}
87 
88 	*key_ptr = (void *)rotpk_hash_der;
89 	*key_len = (unsigned int)sizeof(rotpk_hash_der);
90 	*flags = ROTPK_IS_HASH;
91 	return 0;
92 }
93 
94 #endif
95 
96 /*
97  * Return the ROTPK hash in the following ASN.1 structure in DER format:
98  *
99  * AlgorithmIdentifier  ::=  SEQUENCE  {
100  *     algorithm         OBJECT IDENTIFIER,
101  *     parameters        ANY DEFINED BY algorithm OPTIONAL
102  * }
103  *
104  * DigestInfo ::= SEQUENCE {
105  *     digestAlgorithm   AlgorithmIdentifier,
106  *     digest            OCTET STRING
107  * }
108  */
plat_get_rotpk_info(void * cookie,void ** key_ptr,unsigned int * key_len,unsigned int * flags)109 int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
110 			unsigned int *flags)
111 {
112 #if ARM_CRYPTOCELL_INTEG
113 	return arm_get_rotpk_info_cc(key_ptr, key_len, flags);
114 #else
115 
116 #if (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_RSA_ID) || \
117     (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_DEVEL_ECDSA_ID)
118 	return arm_get_rotpk_info_dev(key_ptr, key_len, flags);
119 #elif (ARM_ROTPK_LOCATION_ID == ARM_ROTPK_REGS_ID)
120 	return juno_get_rotpk_info_regs(key_ptr, key_len, flags);
121 #else
122 	return 1;
123 #endif
124 
125 #endif /* ARM_CRYPTOCELL_INTEG */
126 }
127