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