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