11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */ 2bc420748SJens Wiklander /* 3bc420748SJens Wiklander * Copyright (c) 2015, Linaro Limited 4bc420748SJens Wiklander */ 5bc420748SJens Wiklander #ifndef SIGNED_HDR_H 6bc420748SJens Wiklander #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, 17*c34d0d91SJens 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 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 /** 69*c34d0d91SJens Wiklander * struct shdr_subkey - subkey header 70*c34d0d91SJens Wiklander * @uuid: UUID of the subkey 71*c34d0d91SJens Wiklander * @name_size: The size of a name field that follows right 72*c34d0d91SJens Wiklander * after this header, before the next signed header. 73*c34d0d91SJens Wiklander * @subkey_version: Version of the subkey 74*c34d0d91SJens Wiklander * @max_depth: Maximum depth supported below this subkey 75*c34d0d91SJens Wiklander * @algo: Algorithm, defined by public key algorithms TEE_ALG_* 76*c34d0d91SJens Wiklander * from TEE Internal API specification 77*c34d0d91SJens Wiklander * @attr_count: Number of attributes for the public key matching 78*c34d0d91SJens Wiklander * @algo. 79*c34d0d91SJens Wiklander * @attrs: Attributes for the public key matching @algo. 80*c34d0d91SJens Wiklander * @attrs[].id: Attribute ID TEE_ATTR_* from GlobalPlatform 81*c34d0d91SJens Wiklander * @attrs[].offs: Offset of the attribute value from start of 82*c34d0d91SJens Wiklander * struct shdr_subkey 83*c34d0d91SJens Wiklander * @attrs[].size: Attribute size 84*c34d0d91SJens Wiklander * 85*c34d0d91SJens Wiklander * The @uuid defines UUID URN Namespace (RFC4122), the next UUID after this 86*c34d0d91SJens Wiklander * header (another subkey or a TA) must be in the namespace of this UUID. 87*c34d0d91SJens Wiklander * This means that further subkeys or TAs have their UUID fixed in the 88*c34d0d91SJens Wiklander * hierarchy and cannot be moved up or below another subkey. 89*c34d0d91SJens Wiklander * 90*c34d0d91SJens Wiklander * If @name_size is non-zero it indicates that a name field of this size 91*c34d0d91SJens Wiklander * exists and is used to generate the UUID of the following TA or subkey. 92*c34d0d91SJens Wiklander * If it's zero the following TA or subkey must have a matching UUID. 93*c34d0d91SJens Wiklander * 94*c34d0d91SJens Wiklander * The @subkey_version field is used as a rollback measure. The version is 95*c34d0d91SJens Wiklander * checked against earlier saved values of this subkey. If the latest known 96*c34d0d91SJens Wiklander * version is less than this the stored value is updated. If the latest 97*c34d0d91SJens Wiklander * known version is larger than this then the subkey is refused. 98*c34d0d91SJens Wiklander * 99*c34d0d91SJens Wiklander * The @max_depth defines how many levels are allowed below this subkey, 100*c34d0d91SJens Wiklander * the value 0 means only TAs are allowed below. The value 1 means that 101*c34d0d91SJens Wiklander * eventual subkeys below must have the value 0 in their @max_depth field. 102*c34d0d91SJens Wiklander * 103*c34d0d91SJens Wiklander * Each attribute of @attrs must be within range of the image size of this 104*c34d0d91SJens Wiklander * header defined in the preceding struct shdr. 105*c34d0d91SJens Wiklander * 106*c34d0d91SJens Wiklander * The next struct shdr is found right after the indicated end of the 107*c34d0d91SJens Wiklander * previous struct shdr. Signature verification starts over with the 108*c34d0d91SJens Wiklander * next struct shdr using this subkey instead of the root key. 109*c34d0d91SJens Wiklander */ 110*c34d0d91SJens Wiklander struct shdr_subkey { 111*c34d0d91SJens Wiklander uint8_t uuid[sizeof(TEE_UUID)]; 112*c34d0d91SJens Wiklander uint32_t name_size; 113*c34d0d91SJens Wiklander uint32_t subkey_version; 114*c34d0d91SJens Wiklander uint32_t max_depth; 115*c34d0d91SJens Wiklander uint32_t algo; 116*c34d0d91SJens Wiklander uint32_t attr_count; 117*c34d0d91SJens Wiklander struct shdr_subkey_attr { 118*c34d0d91SJens Wiklander uint32_t id; 119*c34d0d91SJens Wiklander uint32_t offs; 120*c34d0d91SJens Wiklander uint32_t size; 121*c34d0d91SJens Wiklander } attrs[]; 122*c34d0d91SJens Wiklander }; 123*c34d0d91SJens Wiklander 124*c34d0d91SJens 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 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 */ 193064663e8SJens Wiklander static inline void shdr_free(struct shdr *shdr) 194064663e8SJens Wiklander { 195064663e8SJens Wiklander free(shdr); 196064663e8SJens Wiklander } 197064663e8SJens Wiklander 198*c34d0d91SJens Wiklander struct shdr_pub_key { 199*c34d0d91SJens Wiklander uint32_t main_algo; 200*c34d0d91SJens Wiklander uint8_t uuid[sizeof(TEE_UUID)]; 201*c34d0d91SJens Wiklander uint8_t next_uuid[sizeof(TEE_UUID)]; 202*c34d0d91SJens Wiklander uint32_t max_depth; 203*c34d0d91SJens Wiklander uint32_t name_size; 204*c34d0d91SJens Wiklander uint32_t version; 205*c34d0d91SJens Wiklander union { 206*c34d0d91SJens Wiklander struct rsa_public_key *rsa; 207*c34d0d91SJens Wiklander } pub_key; 208*c34d0d91SJens Wiklander }; 209*c34d0d91SJens Wiklander 210*c34d0d91SJens Wiklander TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs, 211*c34d0d91SJens Wiklander const uint8_t *ns_img, size_t ns_img_size, 212*c34d0d91SJens Wiklander const uint8_t next_uuid[sizeof(TEE_UUID)], 213*c34d0d91SJens Wiklander uint32_t max_depth, struct shdr_pub_key *key); 214*c34d0d91SJens Wiklander void shdr_free_pub_key(struct shdr_pub_key *key); 215*c34d0d91SJens Wiklander TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, 216*c34d0d91SJens Wiklander const struct shdr *shdr); 217*c34d0d91SJens 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 228064663e8SJens Wiklander #endif /*SIGNED_HDR_H*/ 229