xref: /optee_os/core/include/signed_hdr.h (revision d50fee0321fe6853ac6352cf0fd548666457b407)
11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */
2bc420748SJens Wiklander /*
3bc420748SJens Wiklander  * Copyright (c) 2015, Linaro Limited
4bc420748SJens Wiklander  */
5*d50fee03SEtienne Carriere #ifndef __SIGNED_HDR_H
6*d50fee03SEtienne Carriere #define __SIGNED_HDR_H
7bc420748SJens Wiklander 
892ea2867SJens Wiklander #include <inttypes.h>
9064663e8SJens Wiklander #include <stdlib.h>
1040bb4a98SJens Wiklander #include <tee_api_types.h>
1140bb4a98SJens Wiklander #include <util.h>
12bc420748SJens Wiklander 
13bc420748SJens Wiklander enum shdr_img_type {
14bc420748SJens Wiklander 	SHDR_TA = 0,
1582b5346dSJens Wiklander 	SHDR_BOOTSTRAP_TA = 1,
16e1afc439SSumit Garg 	SHDR_ENCRYPTED_TA = 2,
17c34d0d91SJens Wiklander 	SHDR_SUBKEY = 3,
18bc420748SJens Wiklander };
19bc420748SJens Wiklander 
20bc420748SJens Wiklander #define SHDR_MAGIC	0x4f545348
21bc420748SJens Wiklander 
22bc420748SJens Wiklander /**
23bc420748SJens Wiklander  * struct shdr - signed header
24bc420748SJens Wiklander  * @magic:	magic number must match SHDR_MAGIC
25bc420748SJens Wiklander  * @img_type:	image type, values defined by enum shdr_img_type
26bc420748SJens Wiklander  * @img_size:	image size in bytes
27bc420748SJens Wiklander  * @algo:	algorithm, defined by public key algorithms TEE_ALG_*
28bc420748SJens Wiklander  *		from TEE Internal API specification
29bc420748SJens Wiklander  * @hash_size:	size of the signed hash
30bc420748SJens Wiklander  * @sig_size:	size of the signature
31bc420748SJens Wiklander  * @hash:	hash of an image
32bc420748SJens Wiklander  * @sig:	signature of @hash
33bc420748SJens Wiklander  */
34bc420748SJens Wiklander struct shdr {
35bc420748SJens Wiklander 	uint32_t magic;
36bc420748SJens Wiklander 	uint32_t img_type;
37bc420748SJens Wiklander 	uint32_t img_size;
38bc420748SJens Wiklander 	uint32_t algo;
39bc420748SJens Wiklander 	uint16_t hash_size;
40bc420748SJens Wiklander 	uint16_t sig_size;
41bc420748SJens Wiklander 	/*
42bc420748SJens Wiklander 	 * Commented out element used to visualize the layout dynamic part
43bc420748SJens Wiklander 	 * of the struct.
44bc420748SJens Wiklander 	 *
45bc420748SJens Wiklander 	 * hash is accessed through the macro SHDR_GET_HASH and
46bc420748SJens Wiklander 	 * signature is accessed through the macro SHDR_GET_SIG
47bc420748SJens Wiklander 	 *
48bc420748SJens Wiklander 	 * uint8_t hash[hash_size];
49bc420748SJens Wiklander 	 * uint8_t sig[sig_size];
50bc420748SJens Wiklander 	 */
51bc420748SJens Wiklander };
52bc420748SJens Wiklander 
shdr_get_size(const struct shdr * shdr)5340bb4a98SJens Wiklander static inline size_t shdr_get_size(const struct shdr *shdr)
5440bb4a98SJens Wiklander {
5540bb4a98SJens Wiklander 	size_t s = sizeof(*shdr);
5640bb4a98SJens Wiklander 
5740bb4a98SJens Wiklander 	if (ADD_OVERFLOW(s, shdr->hash_size, &s) ||
5840bb4a98SJens Wiklander 	    ADD_OVERFLOW(s, shdr->sig_size, &s))
5940bb4a98SJens Wiklander 		return 0;
6040bb4a98SJens Wiklander 
6140bb4a98SJens Wiklander 	return s;
6240bb4a98SJens Wiklander }
6340bb4a98SJens Wiklander 
6440bb4a98SJens Wiklander #define SHDR_GET_SIZE(x)	shdr_get_size((x))
65bc420748SJens Wiklander #define SHDR_GET_HASH(x)	(uint8_t *)(((struct shdr *)(x)) + 1)
66bc420748SJens Wiklander #define SHDR_GET_SIG(x)		(SHDR_GET_HASH(x) + (x)->hash_size)
67bc420748SJens Wiklander 
68b19db423SJens Wiklander /**
69c34d0d91SJens Wiklander  * struct shdr_subkey - subkey header
70c34d0d91SJens Wiklander  * @uuid:		UUID of the subkey
71c34d0d91SJens Wiklander  * @name_size:		The size of a name field that follows right
72c34d0d91SJens Wiklander  *			after this header, before the next signed header.
73c34d0d91SJens Wiklander  * @subkey_version:	Version of the subkey
74c34d0d91SJens Wiklander  * @max_depth:		Maximum depth supported below this subkey
75c34d0d91SJens Wiklander  * @algo:		Algorithm, defined by public key algorithms TEE_ALG_*
76c34d0d91SJens Wiklander  *			from TEE Internal API specification
77c34d0d91SJens Wiklander  * @attr_count:		Number of attributes for the public key matching
78c34d0d91SJens Wiklander  *			@algo.
79c34d0d91SJens Wiklander  * @attrs:		Attributes for the public key matching @algo.
80c34d0d91SJens Wiklander  * @attrs[].id:		Attribute ID TEE_ATTR_* from GlobalPlatform
81c34d0d91SJens Wiklander  * @attrs[].offs:	Offset of the attribute value from start of
82c34d0d91SJens Wiklander  *			struct shdr_subkey
83c34d0d91SJens Wiklander  * @attrs[].size:	Attribute size
84c34d0d91SJens Wiklander  *
85c34d0d91SJens Wiklander  * The @uuid defines UUID URN Namespace (RFC4122), the next UUID after this
86c34d0d91SJens Wiklander  * header (another subkey or a TA) must be in the namespace of this UUID.
87c34d0d91SJens Wiklander  * This means that further subkeys or TAs have their UUID fixed in the
88c34d0d91SJens Wiklander  * hierarchy and cannot be moved up or below another subkey.
89c34d0d91SJens Wiklander  *
90c34d0d91SJens Wiklander  * If @name_size is non-zero it indicates that a name field of this size
91c34d0d91SJens Wiklander  * exists and is used to generate the UUID of the following TA or subkey.
92c34d0d91SJens Wiklander  * If it's zero the following TA or subkey must have a matching UUID.
93c34d0d91SJens Wiklander  *
94c34d0d91SJens Wiklander  * The @subkey_version field is used as a rollback measure. The version is
95c34d0d91SJens Wiklander  * checked against earlier saved values of this subkey. If the latest known
96c34d0d91SJens Wiklander  * version is less than this the stored value is updated. If the latest
97c34d0d91SJens Wiklander  * known version is larger than this then the subkey is refused.
98c34d0d91SJens Wiklander  *
99c34d0d91SJens Wiklander  * The @max_depth defines how many levels are allowed below this subkey,
100c34d0d91SJens Wiklander  * the value 0 means only TAs are allowed below. The value 1 means that
101c34d0d91SJens Wiklander  * eventual subkeys below must have the value 0 in their @max_depth field.
102c34d0d91SJens Wiklander  *
103c34d0d91SJens Wiklander  * Each attribute of @attrs must be within range of the image size of this
104c34d0d91SJens Wiklander  * header defined in the preceding struct shdr.
105c34d0d91SJens Wiklander  *
106c34d0d91SJens Wiklander  * The next struct shdr is found right after the indicated end of the
107c34d0d91SJens Wiklander  * previous struct shdr. Signature verification starts over with the
108c34d0d91SJens Wiklander  * next struct shdr using this subkey instead of the root key.
109c34d0d91SJens Wiklander  */
110c34d0d91SJens Wiklander struct shdr_subkey {
111c34d0d91SJens Wiklander 	uint8_t uuid[sizeof(TEE_UUID)];
112c34d0d91SJens Wiklander 	uint32_t name_size;
113c34d0d91SJens Wiklander 	uint32_t subkey_version;
114c34d0d91SJens Wiklander 	uint32_t max_depth;
115c34d0d91SJens Wiklander 	uint32_t algo;
116c34d0d91SJens Wiklander 	uint32_t attr_count;
117c34d0d91SJens Wiklander 	struct shdr_subkey_attr {
118c34d0d91SJens Wiklander 		uint32_t id;
119c34d0d91SJens Wiklander 		uint32_t offs;
120c34d0d91SJens Wiklander 		uint32_t size;
121c34d0d91SJens Wiklander 	} attrs[];
122c34d0d91SJens Wiklander };
123c34d0d91SJens Wiklander 
124c34d0d91SJens Wiklander /**
125b19db423SJens Wiklander  * struct shdr_bootstrap_ta - bootstrap TA subheader
126b19db423SJens Wiklander  * @uuid:	UUID of the TA
127b19db423SJens Wiklander  * @ta_version:	Version of the TA
128b19db423SJens Wiklander  */
12982b5346dSJens Wiklander struct shdr_bootstrap_ta {
13082b5346dSJens Wiklander 	uint8_t uuid[sizeof(TEE_UUID)];
131a8f769f3SEtienne Carriere 	uint32_t ta_version;
13282b5346dSJens Wiklander };
13382b5346dSJens Wiklander 
134e1afc439SSumit Garg /**
135e1afc439SSumit Garg  * struct shdr_encrypted_ta - encrypted TA header
136e1afc439SSumit Garg  * @enc_algo:	authenticated encyption algorithm, defined by symmetric key
137e1afc439SSumit Garg  *		algorithms TEE_ALG_* from TEE Internal API
138e1afc439SSumit Garg  *		specification
139e1afc439SSumit Garg  * @flags:	authenticated encyption flags
140e1afc439SSumit Garg  * @iv_size:	size of the initialization vector
141e1afc439SSumit Garg  * @tag_size:	size of the authentication tag
142e1afc439SSumit Garg  * @iv:		initialization vector
143e1afc439SSumit Garg  * @tag:	authentication tag
144e1afc439SSumit Garg  */
145e1afc439SSumit Garg struct shdr_encrypted_ta {
146e1afc439SSumit Garg 	uint32_t enc_algo;
147e1afc439SSumit Garg 	uint32_t flags;
148e1afc439SSumit Garg 	uint16_t iv_size;
149e1afc439SSumit Garg 	uint16_t tag_size;
150e1afc439SSumit Garg 	/*
151e1afc439SSumit Garg 	 * Commented out element used to visualize the layout dynamic part
152e1afc439SSumit Garg 	 * of the struct.
153e1afc439SSumit Garg 	 *
154e1afc439SSumit Garg 	 * iv is accessed through the macro SHDR_ENC_GET_IV and
155e1afc439SSumit Garg 	 * tag is accessed through the macro SHDR_ENC_GET_TAG
156e1afc439SSumit Garg 	 *
157e1afc439SSumit Garg 	 * uint8_t iv[iv_size];
158e1afc439SSumit Garg 	 * uint8_t tag[tag_size];
159e1afc439SSumit Garg 	 */
160e1afc439SSumit Garg };
161e1afc439SSumit Garg 
162e1afc439SSumit Garg #define SHDR_ENC_KEY_TYPE_MASK	0x1
163e1afc439SSumit Garg 
164e1afc439SSumit Garg enum shdr_enc_key_type {
165e1afc439SSumit Garg 	SHDR_ENC_KEY_DEV_SPECIFIC = 0,
166e1afc439SSumit Garg 	SHDR_ENC_KEY_CLASS_WIDE = 1,
167e1afc439SSumit Garg };
168e1afc439SSumit Garg 
shdr_enc_get_size(const struct shdr_encrypted_ta * ehdr)1691b02ce1dSJens Wiklander static inline size_t shdr_enc_get_size(const struct shdr_encrypted_ta *ehdr)
1701b02ce1dSJens Wiklander {
1711b02ce1dSJens Wiklander 	size_t s = sizeof(*ehdr);
1721b02ce1dSJens Wiklander 
1731b02ce1dSJens Wiklander 	if (ADD_OVERFLOW(s, ehdr->iv_size, &s) ||
1741b02ce1dSJens Wiklander 	    ADD_OVERFLOW(s, ehdr->tag_size, &s))
1751b02ce1dSJens Wiklander 		return 0;
1761b02ce1dSJens Wiklander 
1771b02ce1dSJens Wiklander 	return s;
1781b02ce1dSJens Wiklander }
1791b02ce1dSJens Wiklander 
1801b02ce1dSJens Wiklander #define SHDR_ENC_GET_SIZE(x)	shdr_enc_get_size((x))
181e1afc439SSumit Garg #define SHDR_ENC_GET_IV(x)	((uint8_t *) \
182e1afc439SSumit Garg 				 (((struct shdr_encrypted_ta *)(x)) + 1))
183e1afc439SSumit Garg #define SHDR_ENC_GET_TAG(x)	({ typeof(x) _x = (x); \
184e1afc439SSumit Garg 				   (SHDR_ENC_GET_IV(_x) + _x->iv_size); })
185e1afc439SSumit Garg 
186064663e8SJens Wiklander /*
187064663e8SJens Wiklander  * Allocates a struct shdr large enough to hold the entire header,
188064663e8SJens Wiklander  * excluding a subheader like struct shdr_bootstrap_ta.
189064663e8SJens Wiklander  */
190ec1aa4faSJens Wiklander struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size);
191bc420748SJens Wiklander 
192064663e8SJens Wiklander /* Frees a previously allocated struct shdr */
shdr_free(struct shdr * shdr)193064663e8SJens Wiklander static inline void shdr_free(struct shdr *shdr)
194064663e8SJens Wiklander {
195064663e8SJens Wiklander 	free(shdr);
196064663e8SJens Wiklander }
197064663e8SJens Wiklander 
198c34d0d91SJens Wiklander struct shdr_pub_key {
199c34d0d91SJens Wiklander 	uint32_t main_algo;
200c34d0d91SJens Wiklander 	uint8_t uuid[sizeof(TEE_UUID)];
201c34d0d91SJens Wiklander 	uint8_t next_uuid[sizeof(TEE_UUID)];
202c34d0d91SJens Wiklander 	uint32_t max_depth;
203c34d0d91SJens Wiklander 	uint32_t name_size;
204c34d0d91SJens Wiklander 	uint32_t version;
205c34d0d91SJens Wiklander 	union {
206c34d0d91SJens Wiklander 		struct rsa_public_key *rsa;
207c34d0d91SJens Wiklander 	} pub_key;
208c34d0d91SJens Wiklander };
209c34d0d91SJens Wiklander 
210c34d0d91SJens Wiklander TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs,
211c34d0d91SJens Wiklander 			     const uint8_t *ns_img, size_t ns_img_size,
212c34d0d91SJens Wiklander 			     const uint8_t next_uuid[sizeof(TEE_UUID)],
213c34d0d91SJens Wiklander 			     uint32_t max_depth, struct shdr_pub_key *key);
214c34d0d91SJens Wiklander void shdr_free_pub_key(struct shdr_pub_key *key);
215c34d0d91SJens Wiklander TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
216c34d0d91SJens Wiklander 				  const struct shdr *shdr);
217c34d0d91SJens Wiklander 
218064663e8SJens Wiklander /*
219064663e8SJens Wiklander  * Verifies the signature in the @shdr.
220064663e8SJens Wiklander  *
221064663e8SJens Wiklander  * Note that the static part of struct shdr and payload still need to be
222064663e8SJens Wiklander  * checked against the hash contained in the header.
223064663e8SJens Wiklander  *
224064663e8SJens Wiklander  * Returns TEE_SUCCESS on success or TEE_ERROR_SECURITY on failure
225064663e8SJens Wiklander  */
226064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr);
227064663e8SJens Wiklander 
228*d50fee03SEtienne Carriere #endif /*__SIGNED_HDR_H*/
229