• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020, Linaro Limited. All rights reserved.
3  * Author: Sumit Garg <sumit.garg@linaro.org>
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <assert.h>
9 #include <errno.h>
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include <platform_def.h>
14 
15 #include <common/bl_common.h>
16 #include <common/debug.h>
17 #include <drivers/auth/crypto_mod.h>
18 #include <drivers/io/io_driver.h>
19 #include <drivers/io/io_encrypted.h>
20 #include <drivers/io/io_storage.h>
21 #include <lib/utils.h>
22 #include <plat/common/platform.h>
23 #include <tools_share/firmware_encrypted.h>
24 #include <tools_share/uuid.h>
25 
26 static uintptr_t backend_dev_handle;
27 static uintptr_t backend_dev_spec;
28 static uintptr_t backend_handle;
29 static uintptr_t backend_image_spec;
30 
31 static io_dev_info_t enc_dev_info;
32 
33 /* Encrypted firmware driver functions */
34 static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
35 static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
36 			  io_entity_t *entity);
37 static int enc_file_len(io_entity_t *entity, size_t *length);
38 static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
39 			  size_t *length_read);
40 static int enc_file_close(io_entity_t *entity);
41 static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
42 static int enc_dev_close(io_dev_info_t *dev_info);
43 
is_valid_header(struct fw_enc_hdr * header)44 static inline int is_valid_header(struct fw_enc_hdr *header)
45 {
46 	if (header->magic == ENC_HEADER_MAGIC)
47 		return 1;
48 	else
49 		return 0;
50 }
51 
device_type_enc(void)52 static io_type_t device_type_enc(void)
53 {
54 	return IO_TYPE_ENCRYPTED;
55 }
56 
57 static const io_dev_connector_t enc_dev_connector = {
58 	.dev_open = enc_dev_open
59 };
60 
61 static const io_dev_funcs_t enc_dev_funcs = {
62 	.type = device_type_enc,
63 	.open = enc_file_open,
64 	.seek = NULL,
65 	.size = enc_file_len,
66 	.read = enc_file_read,
67 	.write = NULL,
68 	.close = enc_file_close,
69 	.dev_init = enc_dev_init,
70 	.dev_close = enc_dev_close,
71 };
72 
enc_dev_open(const uintptr_t dev_spec,io_dev_info_t ** dev_info)73 static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info)
74 {
75 	assert(dev_info != NULL);
76 
77 	enc_dev_info.funcs = &enc_dev_funcs;
78 	*dev_info = &enc_dev_info;
79 
80 	return 0;
81 }
82 
enc_dev_init(io_dev_info_t * dev_info,const uintptr_t init_params)83 static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
84 {
85 	int result;
86 	unsigned int image_id = (unsigned int)init_params;
87 
88 	/* Obtain a reference to the image by querying the platform layer */
89 	result = plat_get_image_source(image_id, &backend_dev_handle,
90 				       &backend_dev_spec);
91 	if (result != 0) {
92 		WARN("Failed to obtain reference to image id=%u (%i)\n",
93 			image_id, result);
94 		return -ENOENT;
95 	}
96 
97 	return result;
98 }
99 
enc_dev_close(io_dev_info_t * dev_info)100 static int enc_dev_close(io_dev_info_t *dev_info)
101 {
102 	backend_dev_handle = (uintptr_t)NULL;
103 	backend_dev_spec = (uintptr_t)NULL;
104 
105 	return 0;
106 }
107 
enc_file_open(io_dev_info_t * dev_info,const uintptr_t spec,io_entity_t * entity)108 static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
109 			 io_entity_t *entity)
110 {
111 	int result;
112 
113 	assert(spec != 0);
114 	assert(entity != NULL);
115 
116 	backend_image_spec = spec;
117 
118 	result = io_open(backend_dev_handle, backend_image_spec,
119 			 &backend_handle);
120 	if (result != 0) {
121 		WARN("Failed to open backend device (%i)\n", result);
122 		result = -ENOENT;
123 	}
124 
125 	return result;
126 }
127 
enc_file_len(io_entity_t * entity,size_t * length)128 static int enc_file_len(io_entity_t *entity, size_t *length)
129 {
130 	int result;
131 
132 	assert(entity != NULL);
133 	assert(length != NULL);
134 
135 	result = io_size(backend_handle, length);
136 	if (result != 0) {
137 		WARN("Failed to read blob length (%i)\n", result);
138 		return -ENOENT;
139 	}
140 
141 	/*
142 	 * Encryption header is attached at the beginning of the encrypted file
143 	 * and is not considered a part of the payload.
144 	 */
145 	if (*length < sizeof(struct fw_enc_hdr))
146 		return -EIO;
147 
148 	*length -= sizeof(struct fw_enc_hdr);
149 
150 	return result;
151 }
152 
enc_file_read(io_entity_t * entity,uintptr_t buffer,size_t length,size_t * length_read)153 static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
154 			 size_t *length_read)
155 {
156 	int result;
157 	struct fw_enc_hdr header;
158 	enum fw_enc_status_t fw_enc_status;
159 	size_t bytes_read;
160 	uint8_t key[ENC_MAX_KEY_SIZE];
161 	size_t key_len = sizeof(key);
162 	unsigned int key_flags = 0;
163 	const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)backend_image_spec;
164 
165 	assert(entity != NULL);
166 	assert(length_read != NULL);
167 
168 	result = io_read(backend_handle, (uintptr_t)&header, sizeof(header),
169 			 &bytes_read);
170 	if (result != 0) {
171 		WARN("Failed to read encryption header (%i)\n", result);
172 		return -ENOENT;
173 	}
174 
175 	if (!is_valid_header(&header)) {
176 		WARN("Encryption header check failed.\n");
177 		return -ENOENT;
178 	}
179 
180 	VERBOSE("Encryption header looks OK.\n");
181 	fw_enc_status = header.flags & FW_ENC_STATUS_FLAG_MASK;
182 
183 	if ((header.iv_len > ENC_MAX_IV_SIZE) ||
184 	    (header.tag_len > ENC_MAX_TAG_SIZE)) {
185 		WARN("Incorrect IV or tag length\n");
186 		return -ENOENT;
187 	}
188 
189 	result = io_read(backend_handle, buffer, length, &bytes_read);
190 	if (result != 0) {
191 		WARN("Failed to read encrypted payload (%i)\n", result);
192 		return -ENOENT;
193 	}
194 
195 	*length_read = bytes_read;
196 
197 	result = plat_get_enc_key_info(fw_enc_status, key, &key_len, &key_flags,
198 				       (uint8_t *)&uuid_spec->uuid,
199 				       sizeof(uuid_t));
200 	if (result != 0) {
201 		WARN("Failed to obtain encryption key (%i)\n", result);
202 		return -ENOENT;
203 	}
204 
205 	result = crypto_mod_auth_decrypt(header.dec_algo,
206 					 (void *)buffer, *length_read, key,
207 					 key_len, key_flags, header.iv,
208 					 header.iv_len, header.tag,
209 					 header.tag_len);
210 	memset(key, 0, key_len);
211 
212 	if (result != 0) {
213 		ERROR("File decryption failed (%i)\n", result);
214 		return -ENOENT;
215 	}
216 
217 	return result;
218 }
219 
enc_file_close(io_entity_t * entity)220 static int enc_file_close(io_entity_t *entity)
221 {
222 	io_close(backend_handle);
223 
224 	backend_image_spec = (uintptr_t)NULL;
225 	entity->info = 0;
226 
227 	return 0;
228 }
229 
230 /* Exported functions */
231 
232 /* Register the Encrypted Firmware driver with the IO abstraction */
register_io_dev_enc(const io_dev_connector_t ** dev_con)233 int register_io_dev_enc(const io_dev_connector_t **dev_con)
234 {
235 	int result;
236 
237 	assert(dev_con != NULL);
238 
239 	result = io_register_device(&enc_dev_info);
240 	if (result == 0)
241 		*dev_con = &enc_dev_connector;
242 
243 	return result;
244 }
245