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