1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2015, Linaro Limited
4  */
5 #ifndef SIGNED_HDR_H
6 #define SIGNED_HDR_H
7 
8 #include <inttypes.h>
9 #include <stdlib.h>
10 #include <tee_api_types.h>
11 #include <util.h>
12 
13 enum shdr_img_type {
14 	SHDR_TA = 0,
15 	SHDR_BOOTSTRAP_TA = 1,
16 	SHDR_ENCRYPTED_TA = 2,
17 };
18 
19 #define SHDR_MAGIC	0x4f545348
20 
21 /**
22  * struct shdr - signed header
23  * @magic:	magic number must match SHDR_MAGIC
24  * @img_type:	image type, values defined by enum shdr_img_type
25  * @img_size:	image size in bytes
26  * @algo:	algorithm, defined by public key algorithms TEE_ALG_*
27  *		from TEE Internal API specification
28  * @hash_size:	size of the signed hash
29  * @sig_size:	size of the signature
30  * @hash:	hash of an image
31  * @sig:	signature of @hash
32  */
33 struct shdr {
34 	uint32_t magic;
35 	uint32_t img_type;
36 	uint32_t img_size;
37 	uint32_t algo;
38 	uint16_t hash_size;
39 	uint16_t sig_size;
40 	/*
41 	 * Commented out element used to visualize the layout dynamic part
42 	 * of the struct.
43 	 *
44 	 * hash is accessed through the macro SHDR_GET_HASH and
45 	 * signature is accessed through the macro SHDR_GET_SIG
46 	 *
47 	 * uint8_t hash[hash_size];
48 	 * uint8_t sig[sig_size];
49 	 */
50 };
51 
shdr_get_size(const struct shdr * shdr)52 static inline size_t shdr_get_size(const struct shdr *shdr)
53 {
54 	size_t s = sizeof(*shdr);
55 
56 	if (ADD_OVERFLOW(s, shdr->hash_size, &s) ||
57 	    ADD_OVERFLOW(s, shdr->sig_size, &s))
58 		return 0;
59 
60 	return s;
61 }
62 
63 #define SHDR_GET_SIZE(x)	shdr_get_size((x))
64 #define SHDR_GET_HASH(x)	(uint8_t *)(((struct shdr *)(x)) + 1)
65 #define SHDR_GET_SIG(x)		(SHDR_GET_HASH(x) + (x)->hash_size)
66 
67 /**
68  * struct shdr_bootstrap_ta - bootstrap TA subheader
69  * @uuid:	UUID of the TA
70  * @ta_version:	Version of the TA
71  */
72 struct shdr_bootstrap_ta {
73 	uint8_t uuid[sizeof(TEE_UUID)];
74 	uint32_t ta_version;
75 };
76 
77 /**
78  * struct shdr_encrypted_ta - encrypted TA header
79  * @enc_algo:	authenticated encyption algorithm, defined by symmetric key
80  *		algorithms TEE_ALG_* from TEE Internal API
81  *		specification
82  * @flags:	authenticated encyption flags
83  * @iv_size:	size of the initialization vector
84  * @tag_size:	size of the authentication tag
85  * @iv:		initialization vector
86  * @tag:	authentication tag
87  */
88 struct shdr_encrypted_ta {
89 	uint32_t enc_algo;
90 	uint32_t flags;
91 	uint16_t iv_size;
92 	uint16_t tag_size;
93 	/*
94 	 * Commented out element used to visualize the layout dynamic part
95 	 * of the struct.
96 	 *
97 	 * iv is accessed through the macro SHDR_ENC_GET_IV and
98 	 * tag is accessed through the macro SHDR_ENC_GET_TAG
99 	 *
100 	 * uint8_t iv[iv_size];
101 	 * uint8_t tag[tag_size];
102 	 */
103 };
104 
105 #define SHDR_ENC_KEY_TYPE_MASK	0x1
106 
107 enum shdr_enc_key_type {
108 	SHDR_ENC_KEY_DEV_SPECIFIC = 0,
109 	SHDR_ENC_KEY_CLASS_WIDE = 1,
110 };
111 
shdr_enc_get_size(const struct shdr_encrypted_ta * ehdr)112 static inline size_t shdr_enc_get_size(const struct shdr_encrypted_ta *ehdr)
113 {
114 	size_t s = sizeof(*ehdr);
115 
116 	if (ADD_OVERFLOW(s, ehdr->iv_size, &s) ||
117 	    ADD_OVERFLOW(s, ehdr->tag_size, &s))
118 		return 0;
119 
120 	return s;
121 }
122 
123 #define SHDR_ENC_GET_SIZE(x)	shdr_enc_get_size((x))
124 #define SHDR_ENC_GET_IV(x)	((uint8_t *) \
125 				 (((struct shdr_encrypted_ta *)(x)) + 1))
126 #define SHDR_ENC_GET_TAG(x)	({ typeof(x) _x = (x); \
127 				   (SHDR_ENC_GET_IV(_x) + _x->iv_size); })
128 
129 /*
130  * Allocates a struct shdr large enough to hold the entire header,
131  * excluding a subheader like struct shdr_bootstrap_ta.
132  */
133 struct shdr *shdr_alloc_and_copy(const struct shdr *img, size_t img_size);
134 
135 /* Frees a previously allocated struct shdr */
shdr_free(struct shdr * shdr)136 static inline void shdr_free(struct shdr *shdr)
137 {
138 	free(shdr);
139 }
140 
141 /*
142  * Verifies the signature in the @shdr.
143  *
144  * Note that the static part of struct shdr and payload still need to be
145  * checked against the hash contained in the header.
146  *
147  * Returns TEE_SUCCESS on success or TEE_ERROR_SECURITY on failure
148  */
149 TEE_Result shdr_verify_signature(const struct shdr *shdr);
150 
151 #endif /*SIGNED_HDR_H*/
152