blob: 744ca835625a73946e9d20f4390736387e599484 [file] [log] [blame]
Sumit Garg617e2152019-11-15 15:34:55 +05301/*
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
26static uintptr_t backend_dev_handle;
27static uintptr_t backend_dev_spec;
28static uintptr_t backend_handle;
29static uintptr_t backend_image_spec;
30
31static io_dev_info_t enc_dev_info;
32
33/* Encrypted firmware driver functions */
34static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
35static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
36 io_entity_t *entity);
37static int enc_file_len(io_entity_t *entity, size_t *length);
38static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
39 size_t *length_read);
40static int enc_file_close(io_entity_t *entity);
41static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
42static int enc_dev_close(io_dev_info_t *dev_info);
43
44static 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
52static io_type_t device_type_enc(void)
53{
54 return IO_TYPE_ENCRYPTED;
55}
56
57static const io_dev_connector_t enc_dev_connector = {
58 .dev_open = enc_dev_open
59};
60
61static 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
73static 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
83static 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
100static 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
108static 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
128static 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
153static 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
220static 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 */
233int 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}