blob: b9bc9de0f73c9c2963c2ef31a7db926f38210c98 [file] [log] [blame]
Manish V Badarkhe39317ab2020-07-23 10:43:57 +01001/*
laurenw-arm02e09252024-01-09 20:38:10 -06002 * Copyright (c) 2020-2024, Arm Limited. All rights reserved.
Manish V Badarkhe39317ab2020-07-23 10:43:57 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <stddef.h>
9
Govindraj Raja9c7dfb02023-01-11 18:34:58 +000010#include <mbedtls/version.h>
11
Manish V Badarkhe39317ab2020-07-23 10:43:57 +010012#include <common/fdt_wrappers.h>
Govindraj Raja9c7dfb02023-01-11 18:34:58 +000013#include <common/tbbr/cot_def.h>
Manish V Badarkhe39317ab2020-07-23 10:43:57 +010014#include <drivers/auth/auth_mod.h>
15#include <lib/fconf/fconf.h>
16#include <lib/object_pool.h>
17#include <libfdt.h>
18
19#include <tools_share/tbbr_oid.h>
20
21/* static structures used during authentication process */
22static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
23 AUTH_PARAM_SIG, 0);
24static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
25 AUTH_PARAM_SIG_ALG, 0);
26static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
27 AUTH_PARAM_RAW_DATA, 0);
28
29/* pointers to an array of CoT descriptors */
30static const auth_img_desc_t *cot_desc[MAX_NUMBER_IDS];
31/* array of CoT descriptors */
32static auth_img_desc_t auth_img_descs[MAX_NUMBER_IDS];
33
34/* array of authentication methods structures */
35static auth_method_desc_t auth_methods[MAX_NUMBER_IDS * AUTH_METHOD_NUM];
36static OBJECT_POOL_ARRAY(auth_methods_pool, auth_methods);
37
38/* array of authentication params structures */
39static auth_param_desc_t auth_params[MAX_NUMBER_IDS * COT_MAX_VERIFIED_PARAMS];
40static OBJECT_POOL_ARRAY(auth_params_pool, auth_params);
41
42/* array of authentication param type structures */
43static auth_param_type_desc_t auth_param_type_descs[MAX_NUMBER_IDS];
44static OBJECT_POOL_ARRAY(auth_param_type_descs_pool, auth_param_type_descs);
45
46/*
47 * array of OIDs
48 * Object IDs are used to search hash, pk, counter values in certificate.
49 * As per binding we have below 2 combinations:
50 * 1. Certificates are validated using nv-cntr and pk
51 * 2. Raw images are authenticated using hash
52 * Hence in worst case, there are maximum 2 OIDs per image/certificate
53 */
54static unsigned char oids[(MAX_NUMBER_IDS * 2)][MAX_OID_NAME_LEN];
55static OBJECT_POOL_ARRAY(oid_pool, oids);
56
57/* An array of auth buffer which holds hashes and pk
58 * ToDo: Size decided with the current number of images and
59 * certificates which are available in CoT. Size of these buffers bound to
60 * increase in the future on the addition of images/certificates.
61 */
62static unsigned char hash_auth_bufs[20][HASH_DER_LEN];
63static OBJECT_POOL_ARRAY(hash_auth_buf_pool, hash_auth_bufs);
64static unsigned char pk_auth_bufs[12][PK_DER_LEN];
65static OBJECT_POOL_ARRAY(pk_auth_buf_pool, pk_auth_bufs);
66
67/*******************************************************************************
68 * update_parent_auth_data() - Update authentication data structure
69 * @auth_desc[in]: Pointer to the auth image descriptor
70 * @type_desc[in]: Pointer to authentication parameter
71 * @auth_buf_size[in]: Buffer size to hold pk or hash
72 *
73 * Return 0 on success or an error value otherwise.
74 ******************************************************************************/
75static int update_parent_auth_data(const auth_img_desc_t *auth_desc,
76 auth_param_type_desc_t *type_desc,
77 unsigned int auth_buf_size)
78{
79 unsigned int i;
80 auth_param_desc_t *auth_data = &auth_desc->authenticated_data[0];
81 unsigned char *auth_buf;
82
83 for (i = 0U; i < COT_MAX_VERIFIED_PARAMS; i++) {
84 if (auth_data[i].type_desc == type_desc) {
85 return 0;
86 }
87 if (auth_data[i].type_desc == NULL) {
88 break;
89 }
90 }
91
92 if (auth_buf_size == HASH_DER_LEN) {
93 auth_buf = pool_alloc(&hash_auth_buf_pool);
94 } else if (auth_buf_size == PK_DER_LEN) {
95 auth_buf = pool_alloc(&pk_auth_buf_pool);
96 } else {
97 return -1;
98 }
99
100 if (i < COT_MAX_VERIFIED_PARAMS) {
101 auth_data[i].type_desc = type_desc;
102 auth_data[i].data.ptr = auth_buf;
103 auth_data[i].data.len = auth_buf_size;
104 } else {
105 ERROR("Out of authentication data array\n");
106 return -1;
107 }
108
109 return 0;
110}
111
112/*******************************************************************************
113 * get_auth_param_type_desc() - Get pointer of authentication parameter
114 * @img_id[in]: Image Id
115 * @type_desc[out]: Pointer to authentication parameter
116 * @buf_size[out]: Buffer size which hold hash/pk
117 *
118 * Return 0 on success or an error value otherwise.
119 ******************************************************************************/
120static int get_auth_param_type_desc(unsigned int img_id,
121 auth_param_type_desc_t **type_desc,
122 unsigned int *buf_size)
123{
124 auth_method_desc_t *img_auth_method = NULL;
125 img_type_t type = auth_img_descs[img_id].img_type;
126
127 if (type == IMG_CERT) {
128 img_auth_method =
129 &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_SIG];
130 *type_desc = img_auth_method->param.sig.pk;
131 *buf_size = PK_DER_LEN;
132 } else if (type == IMG_RAW) {
133 img_auth_method =
134 &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_HASH];
135 *type_desc = img_auth_method->param.hash.hash;
136 *buf_size = HASH_DER_LEN;
137 } else {
138 return -1;
139 }
140
141 return 0;
142}
143
144/*******************************************************************************
145 * set_auth_method() - Update global auth image descriptors with authentication
146 * method data
147 * @auth_method_type[in]: Type of authentication method
148 * @oid[in]: Object Idetifier for pk/hash search
149 * @auth_method[in]: Pointer to authentication method to set
150 ******************************************************************************/
151static void set_auth_method(auth_method_type_t auth_method_type, char *oid,
152 auth_method_desc_t *auth_method)
153{
154 auth_param_type_t auth_param_type = AUTH_PARAM_NONE;
155 auth_param_type_desc_t *auth_param_type_desc;
156
157 assert(auth_method != NULL);
158
159 auth_param_type_desc = pool_alloc(&auth_param_type_descs_pool);
160 auth_method->type = auth_method_type;
161
162 if (auth_method_type == AUTH_METHOD_SIG) {
163 auth_param_type = AUTH_PARAM_PUB_KEY;
164 auth_method->param.sig.sig = &sig;
165 auth_method->param.sig.alg = &sig_alg;
166 auth_method->param.sig.data = &raw_data;
167 auth_method->param.sig.pk = auth_param_type_desc;
168 } else if (auth_method_type == AUTH_METHOD_HASH) {
169 auth_param_type = AUTH_PARAM_HASH;
170 auth_method->param.hash.data = &raw_data;
171 auth_method->param.hash.hash = auth_param_type_desc;
172 } else if (auth_method_type == AUTH_METHOD_NV_CTR) {
173 auth_param_type = AUTH_PARAM_NV_CTR;
174 auth_method->param.nv_ctr.cert_nv_ctr = auth_param_type_desc;
175 auth_method->param.nv_ctr.plat_nv_ctr = auth_param_type_desc;
176 }
177
178 auth_param_type_desc->type = auth_param_type;
179 auth_param_type_desc->cookie = (void *)oid;
180}
181
182/*******************************************************************************
183 * get_oid() - get object identifier from device tree
184 * @dtb[in]: Pointer to the device tree blob in memory
185 * @node[in]: Offset of the node
186 * @prop[in]: Property to read from the given node
187 * @oid[out]: Object Indentifier of key/hash/nv-counter in certificate
188 *
189 * Return 0 on success or an error value otherwise.
190 ******************************************************************************/
191static int get_oid(const void *dtb, int node, const char *prop, char **oid)
192{
193 uint32_t phandle;
194 int rc;
195
196 rc = fdt_read_uint32(dtb, node, prop, &phandle);
197 if (rc < 0) {
198 return rc;
199 }
200
201 node = fdt_node_offset_by_phandle(dtb, phandle);
202 if (node < 0) {
203 return node;
204 }
205
206 *oid = pool_alloc(&oid_pool);
207 rc = fdtw_read_string(dtb, node, "oid", *oid, MAX_OID_NAME_LEN);
208
209 return rc;
210}
211
212/*******************************************************************************
213 * populate_and_set_auth_methods() - Populate auth method parameters from
214 * device tree and set authentication method
215 * structure.
216 * @dtb[in]: Pointer to the device tree blob in memory
217 * @node[in]: Offset of the node
218 * @img_id[in]: Image identifier
219 * @type[in]: Type of image
220 * @root_certificate[in]:Root certificate (authenticated by ROTPK)
221 *
222 * Return 0 on success or an error value otherwise.
223 ******************************************************************************/
224static int populate_and_set_auth_methods(const void *dtb, int node,
225 unsigned int img_id, img_type_t type,
226 bool root_certificate)
227{
228 auth_method_type_t auth_method_type = AUTH_METHOD_NONE;
229 int rc;
230 char *oid = NULL;
231
232 auth_method_desc_t *auth_method = pool_alloc_n(&auth_methods_pool,
233 AUTH_METHOD_NUM);
234
235 /*
236 * This is as per binding document where certificates are
237 * verified by signature and images are verified by hash.
238 */
239 if (type == IMG_CERT) {
laurenw-arm02e09252024-01-09 20:38:10 -0600240 rc = get_oid(dtb, node, "signing-key", &oid);
241 if (rc < 0) {
242 /*
243 * The signing-key property is optional in root
244 * certificates, mandatory otherwise.
245 */
246 if (root_certificate) {
247 oid = NULL;
248 } else {
Manish V Badarkhe39317ab2020-07-23 10:43:57 +0100249 ERROR("FCONF: Can't read %s property\n",
laurenw-arm02e09252024-01-09 20:38:10 -0600250 "signing-key");
Manish V Badarkhe39317ab2020-07-23 10:43:57 +0100251 return rc;
252 }
253 }
254 auth_method_type = AUTH_METHOD_SIG;
255 } else if (type == IMG_RAW) {
256 rc = get_oid(dtb, node, "hash", &oid);
257 if (rc < 0) {
258 ERROR("FCONF: Can't read %s property\n",
259 "hash");
260 return rc;
261 }
262 auth_method_type = AUTH_METHOD_HASH;
263 } else {
264 return -1;
265 }
266
267 set_auth_method(auth_method_type, oid,
268 &auth_method[auth_method_type]);
269
270 /* Retrieve the optional property */
271 rc = get_oid(dtb, node, "antirollback-counter", &oid);
272 if (rc == 0) {
273 auth_method_type = AUTH_METHOD_NV_CTR;
274 set_auth_method(auth_method_type, oid,
275 &auth_method[auth_method_type]);
276 }
277
278 auth_img_descs[img_id].img_auth_methods = &auth_method[0];
279
280 return 0;
281}
282
283/*******************************************************************************
284 * get_parent_img_id() - Get parent image id for given child node
285 * @dtb[in]: Pointer to the device tree blob in memory
286 * @node[in]: Offset of the child node
287 * @parent_img_id[out]: Image id of parent
288 *
289 * Return 0 on success or an error value otherwise.
290 ******************************************************************************/
291static int get_parent_img_id(const void *dtb, int node,
292 unsigned int *parent_img_id)
293{
294 uint32_t phandle;
295 int err;
296
297 err = fdt_read_uint32(dtb, node, "parent", &phandle);
298 if (err < 0) {
299 ERROR("FCONF: Could not read %s property in node\n",
300 "parent");
301 return err;
302 }
303
304 node = fdt_node_offset_by_phandle(dtb, phandle);
305 if (node < 0) {
306 ERROR("FCONF: Failed to locate node using its phandle\n");
307 return node;
308 }
309
310 err = fdt_read_uint32(dtb, node, "image-id", parent_img_id);
311 if (err < 0) {
312 ERROR("FCONF: Could not read %s property in node\n",
313 "image-id");
314 }
315
316 return err;
317}
318
319/*******************************************************************************
320 * set_desc_data() - Update data in descriptor's structure
321 * @dtb[in]: Pointer to the device tree blob in memory
322 * @node[in]: Offset of the node
323 * @type[in]: Type of image (RAW/CERT)
324 *
325 * Return 0 on success or an error value otherwise.
326 ******************************************************************************/
327static int set_desc_data(const void *dtb, int node, img_type_t type)
328{
329 int rc;
330 bool root_certificate = false;
331 unsigned int img_id, parent_img_id;
332
333 rc = fdt_read_uint32(dtb, node, "image-id", &img_id);
334 if (rc < 0) {
335 ERROR("FCONF: Can't find property %s in node\n",
336 "image-id");
337 return rc;
338 }
339
340 if (fdt_getprop(dtb, node, "root-certificate",
341 NULL) != NULL) {
342 root_certificate = true;
343 }
344
345 if (!root_certificate) {
346 rc = get_parent_img_id(dtb, node, &parent_img_id);
347 if (rc < 0) {
348 return rc;
349 }
350 auth_img_descs[img_id].parent = &auth_img_descs[parent_img_id];
351 }
352
353 auth_img_descs[img_id].img_id = img_id;
354 auth_img_descs[img_id].img_type = type;
355
356 rc = populate_and_set_auth_methods(dtb, node, img_id, type,
357 root_certificate);
358 if (rc < 0) {
359 return rc;
360 }
361
362 if (type == IMG_CERT) {
363 auth_param_desc_t *auth_param =
364 pool_alloc_n(&auth_params_pool,
365 COT_MAX_VERIFIED_PARAMS);
366 auth_img_descs[img_id].authenticated_data = &auth_param[0];
367 }
368
369 cot_desc[img_id] = &auth_img_descs[img_id];
370
371 return rc;
372}
373
374/*******************************************************************************
375 * populate_manifest_descs() - Populate CoT descriptors and update global
376 * certificate structures
377 * @dtb[in]: Pointer to the device tree blob in memory
378 *
379 * Return 0 on success or an error value otherwise.
380 ******************************************************************************/
381static int populate_manifest_descs(const void *dtb)
382{
383 int node, child;
384 int rc;
385
386 /*
387 * Assert the node offset points to "arm, cert-descs"
388 * compatible property
389 */
390 const char *compatible_str = "arm, cert-descs";
391
392 node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
393 if (node < 0) {
394 ERROR("FCONF: Can't find %s compatible in node\n",
395 compatible_str);
396 return node;
397 }
398
399 fdt_for_each_subnode(child, dtb, node) {
400 rc = set_desc_data(dtb, child, IMG_CERT);
401 if (rc < 0) {
402 return rc;
403 }
404 }
405
406 return 0;
407}
408
409/*******************************************************************************
410 * populate_image_descs() - Populate CoT descriptors and update global
411 * image descriptor structures.
412 * @dtb[in]: Pointer to the device tree blob in memory
413 *
414 * Return 0 on success or an error value otherwise.
415 ******************************************************************************/
416static int populate_image_descs(const void *dtb)
417{
418 int node, child;
419 int rc;
420
421 /*
422 * Assert the node offset points to "arm, img-descs"
423 * compatible property
424 */
425 const char *compatible_str = "arm, img-descs";
426
427 node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
428 if (node < 0) {
429 ERROR("FCONF: Can't find %s compatible in node\n",
430 compatible_str);
431 return node;
432 }
433
434 fdt_for_each_subnode(child, dtb, node) {
435 rc = set_desc_data(dtb, child, IMG_RAW);
436 if (rc < 0) {
437 return rc;
438 }
439 }
440
441 return 0;
442}
443
444/*******************************************************************************
445 * fconf_populate_cot_descs() - Populate CoT descriptors and update global
446 * structures
447 * @config[in]: Pointer to the device tree blob in memory
448 *
449 * Return 0 on success or an error value otherwise.
450 ******************************************************************************/
451static int fconf_populate_cot_descs(uintptr_t config)
452{
453 auth_param_type_desc_t *type_desc = NULL;
454 unsigned int auth_buf_size = 0U;
455 int rc;
456
457 /* As libfdt uses void *, we can't avoid this cast */
458 const void *dtb = (void *)config;
459
460 /* populate manifest descs information */
461 rc = populate_manifest_descs(dtb);
462 if (rc < 0) {
463 ERROR("FCONF: population of %s descs failed %d\n",
464 "manifest", rc);
465 return rc;
466 }
467
468 /* populate image descs information */
469 rc = populate_image_descs(dtb);
470 if (rc < 0) {
471 ERROR("FCONF: population of %s descs failed %d\n",
472 "images", rc);
473 return rc;
474 }
475
476 /* update parent's authentication data */
477 for (unsigned int i = 0U; i < MAX_NUMBER_IDS; i++) {
478 if (auth_img_descs[i].parent != NULL) {
479 rc = get_auth_param_type_desc(i,
480 &type_desc,
481 &auth_buf_size);
482 if (rc < 0) {
483 ERROR("FCONF: failed to get auth data %d\n",
484 rc);
485 return rc;
486 }
487
488 rc = update_parent_auth_data(auth_img_descs[i].parent,
489 type_desc,
490 auth_buf_size);
491 if (rc < 0) {
492 ERROR("FCONF: auth data update failed %d\n",
493 rc);
494 return rc;
495 }
496 }
497 }
498
499 return rc;
500}
501
502FCONF_REGISTER_POPULATOR(TB_FW, cot_desc, fconf_populate_cot_descs);
503REGISTER_COT(cot_desc);