blob: 89db4507e3e32d420761740a751925bd1c2e1c4b [file] [log] [blame]
David Huc0427932020-04-09 23:03:49 +08001#################################################
2Symmetric key algorithm based Initial Attestation
3#################################################
4
Anton Komlev19b90712021-10-19 16:28:02 +01005:Author: David Hu
David Huc0427932020-04-09 23:03:49 +08006:Organization: Arm Limited
7:Contact: david.hu@arm.com
8
9************
10Introduction
11************
12
13This document proposes a design of symmetric key algorithm based Initial
14Attestation in TF-M.
15
16Symmetric key algorithm based Initial Attestation
17(*symmetric Initial Attestation* for short) signs and verifies Initial
Edison Aif7990c82020-07-16 18:31:48 +080018Attestation Token (IAT) with a symmetric cryptography signature scheme, such as
David Huc0427932020-04-09 23:03:49 +080019HMAC.
20It can reduce TF-M binary size and memory footprint on ultra-constrained devices
21without integrating asymmetric ciphers.
22
23This proposal follows PSA Attestation API document [1]_.
24
25.. note ::
26
27 As pointed out by PSA Attestation API [1]_, the use cases of Initial
28 Attestation based on symmetric key algorithms can be limited due to
29 the associated infrastructure costs for key management and operational
30 complexities. It may also restrict the ability to interoperate with
31 scenarios that involve third parties.
32
33***************
34Design overview
35***************
36
37The symmetric Initial Attestation follows the existing IAT generation sequence
38for Initial Attestation based on asymmetric key algorithm
39(*asymmetric Initial Attestation* for short).
40
41As Profile Small design [2]_ requests, a configuration flag
42``SYMMETRIC_INITIAL_ATTESTATION`` selects symmetric initial attestation during
43build.
44
45The top-level design is shown in :ref:`overall-diagram-figure` below.
46
47.. _overall-diagram-figure:
48
Anton Komlevb3f64662023-01-28 11:53:05 +000049.. figure:: /design_docs/media/symmetric_initial_attest/overall_diagram.png
David Huc0427932020-04-09 23:03:49 +080050 :align: center
51
52 Overall design diagram
53
54Symmetric Initial Attestation adds its own implementations of some steps in IAT
55generation in Initial Attestation secure service. More details are covered in
56`IAT generation in Initial Attestation secure service`_.
57
58The interfaces and procedures of Initial Attestation secure service are not
59affected. Refer to Initial Attestation Service Integration Guide [3]_ for
60details of the implementation of Initial Attestation secure service.
61
62Symmetric Initial Attestation invokes ``t_cose`` library to build up
David Vinczea7bcb8a2023-08-09 14:35:32 +020063``COSE_Mac0`` structure. ``COSE_Mac0`` support was originally added to the
64``t_cose`` library fork in TF-M, however, since ``t_cose 2.0`` the upstream
65library [6]_ also supports it. The design of ``COSE_Mac0`` support is covered in
66`COSE_Mac0 support in t_cose`_.
David Huc0427932020-04-09 23:03:49 +080067
68.. note ::
69
David Vinczea7bcb8a2023-08-09 14:35:32 +020070 The ``COSE_Mac0`` implementation in this proposal is a prototype, describing
71 the original Proof of Concept and not the official ``COSE_Mac0`` support in
72 ``t_cose`` in which there may be differences since the support was
73 upstreamed.
David Huc0427932020-04-09 23:03:49 +080074
75Several HAL APIs are defined to fetch platform specific assets required by
76Symmetric Initial Attestation. For example, ``tfm_plat_get_symmetric_iak()``
77fetches symmetric Initial Attestation Key (IAK). Those HAL APIs are summarized
78in `HAL APIs`_.
79
80Decoding and verification of symmetric Initial Attestation is also included in
81this proposal for regression test.
82The test suites and IAT decoding are discussed in `TF-M Test suite`_.
83
84``QCBOR`` library and Crypto service are also invoked. But this proposal doesn't
85require any modification to either ``QCBOR`` or Crypto service. Therefore,
86descriptions of ``QCBOR`` and Crypto service are skipped in this document.
87
88****************************************************
89IAT generation in Initial Attestation secure service
90****************************************************
91
92The sequence of IAT generation of symmetric Initial Attestation is shown in
Raef Colesb3adfeb2022-03-02 14:00:57 +000093:ref:`ia-service-figure` below. Note that the ``Register symmetric IAK`` stage
94is no longer required due to changes in the Crypto partition
95(``attest_symmetric_key.c`` is now responsible only for calculating the instance
96ID).
David Huc0427932020-04-09 23:03:49 +080097
98.. _ia-service-figure:
99
Anton Komlevb3f64662023-01-28 11:53:05 +0000100.. figure:: /design_docs/media/symmetric_initial_attest/ia_service_flow.png
David Huc0427932020-04-09 23:03:49 +0800101 :align: center
102
103 Symmetric IAT generation flow in Initial Attestation secure service
104
105In Initial Attestation secure service, symmetric Initial Attestation implements
106the following steps in ``attest_create_token()``, which are different from those
107of asymmetric Initial Attestation.
108
David Huc0427932020-04-09 23:03:49 +0800109 - ``attest_token_start()``
110 - Instance ID claims
111 - ``attest_token_finish()``
112
113If ``SYMMETRIC_INITIAL_ATTESTATION`` is selected, symmetric Initial Attestation
114dedicated implementations of those steps are included in build.
115Otherwise, asymmetric Initial Attestation dedicated implementations are included
116instead.
117
118Symmetric Initial Attestation implementation resides a new file
Raef Colesb3adfeb2022-03-02 14:00:57 +0000119``attest_symmetric_key.c`` to handle symmetric Instance ID related operations.
David Huc0427932020-04-09 23:03:49 +0800120Symmetric Initial Attestation dedicated ``attest_token_start()`` and
121``attest_token_finish()`` are added in ``attestation_token.c``.
122
123The details are covered in following sections.
124
Raef Colesb3adfeb2022-03-02 14:00:57 +0000125Symmetric Instance ID
126=====================
David Huc0427932020-04-09 23:03:49 +0800127
Raef Colesb3adfeb2022-03-02 14:00:57 +0000128Symmetric Initial Attestation dedicated ``attest_symmetric_key.c`` implements
129the ``attest_get_instance_id()`` function. This function returns the Instance ID
130value, calculating it if it has not already been calculated. Refer to
131`Instance ID claim_` for more details.
David Huc0427932020-04-09 23:03:49 +0800132
133.. note ::
134
135 Only symmetric IAK for HMAC algorithm is allowed so far.
136
137Instance ID calculation
138-----------------------
139
Raef Colesb3adfeb2022-03-02 14:00:57 +0000140In symmetric Initial Attestation, Instance ID is also calculated the first time
141it is requested. It can protect critical symmetric IAK from being frequently
142fetched, which increases the risk of asset disclosure.
David Huc0427932020-04-09 23:03:49 +0800143
144The Instance ID value is the output of hashing symmetric IAK raw data *twice*,
145as requested in PSA Attestation API [1]_. HMAC-SHA256 may be hard-coded as the
146hash algorithm of Instance ID calculation.
147
148.. note ::
149
150 According to RFC2104 [4]_, if a HMAC key is longer than the HMAC block size,
151 the key will be first hashed. The hash output is used as the key in HMAC
152 computation.
153
154 In current design, HMAC is used to calculate the authentication tag of
155 ``COSE_Mac0``. Assume that symmetric IAK is longer than HMAC block size
156 (HMAC-SHA256 by default), the Instance ID is actually the HMAC key for
157 ``COSE_Mac0`` authentication tag generation, if Instance ID value is the
158 output of hashing IAK only *once*.
159 Therefore, attackers may request an valid IAT from device and fake malicious
160 ones by using Instance ID to calculate valid authentication tags, to cheat
161 others.
162
163 As a result, symmetric IAK raw data should be hashed *twice* to generate the
164 Instance ID value.
165
166The Instance ID calculation result is stored in a static buffer.
167Token generation process can call ``attest_get_instance_id()`` to
168fetch the data from that static buffer.
169
170attest_token_start()
171====================
172
173Symmetric Initial Attestation dedicated ``attest_token_start()`` initializes the
David Vinczea7bcb8a2023-08-09 14:35:32 +0200174``COSE_Mac0`` computation context and builds up the ``COSE_Mac0`` Header.
David Huc0427932020-04-09 23:03:49 +0800175
176The workflow inside ``attest_token_start()`` is shown in
177:ref:`attest-token-start-figure` below.
178
179.. _attest-token-start-figure:
180
Anton Komlevb3f64662023-01-28 11:53:05 +0000181.. figure:: /design_docs/media/symmetric_initial_attest/attest_token_start.png
David Huc0427932020-04-09 23:03:49 +0800182 :align: center
183
184 Workflow in symmetric Initial Attestation ``attest_token_start()``
185
186Descriptions of each step are listed below:
187
188#. ``t_cose_mac0_sign_init()`` is invoked to initialize ``COSE_Mac0`` signing
189 context in ``t_cose``.
190
David Huc0427932020-04-09 23:03:49 +0800191#. The symmetric IAK handle is set into ``COSE_Mac0`` signing context via
192 ``t_cose_mac0_set_signing_key()``.
193
194#. Initialize ``QCBOR`` encoder.
195
196#. The header parameters are encoded into ``COSE_Mac0`` structure in
197 ``t_cose_mac0_encode_parameters()``.
198
199#. ``QCBOREncode_OpenMap()`` prepares for encoding the ``COSE_Mac0`` payload,
200 which is filled with IAT claims.
201
202All the ``COSE_Mac0`` functionalities in ``t_cose`` are covered in
203`COSE_Mac0 support in t_cose`_.
204
205Instance ID claim
206=================
207
208Symmetric Initial Attestation also implements Instance ID claims in
209``attest_add_instance_id_claim()``.
210
211The Instance ID value is fetched via ``attest_get_instance_id()``.
212The value has already been calculated during symmetric IAK registration. See
213`Instance ID calculation`_ for details.
214
215The other steps are the same as those in asymmetric Initial Attestation
216implementation. The UEID type byte is set to 0x01.
217
218attest_token_finish()
219=====================
220
221Symmetric Initial Attestation dedicated ``attest_token_finish()`` calls
222``t_cose_mac0_encode_tag()`` to calculate and encode the authentication tag of
223``COSE_Mac0`` structure.
224
225The whole COSE and CBOR encoding are completed in ``attest_token_finish()``.
226
227The simplified flow in ``attest_token_finish()`` is shown in
228:ref:`attest-token-finish-figure` below.
229
230.. _attest-token-finish-figure:
231
Anton Komlevb3f64662023-01-28 11:53:05 +0000232.. figure:: /design_docs/media/symmetric_initial_attest/attest_token_finish.png
David Huc0427932020-04-09 23:03:49 +0800233 :align: center
234
235 Workflow in symmetric Initial Attestation ``attest_token_finish()``
236
237***************************
238COSE_Mac0 support in t_cose
239***************************
240
David Vinczea7bcb8a2023-08-09 14:35:32 +0200241``COSE_Mac0`` supports in ``t_cose`` include the following major
David Huc0427932020-04-09 23:03:49 +0800242functionalities:
243
244 - Encoding ``COSE_Mac0`` structure
David Vinczea7bcb8a2023-08-09 14:35:32 +0200245 - Decoding and validating ``COSE_Mac0`` structure
246 - HMAC computation to generate and validate authentication tag
David Huc0427932020-04-09 23:03:49 +0800247
248According to RFC8152 [5]_, ``COSE_Mac0`` and ``COSE_Sign1`` have similar
David Vinczea7bcb8a2023-08-09 14:35:32 +0200249structures. Therefore, the prototype in TF-M followed ``COSE_Sign1``
250implementation to build up ``COSE_Mac0`` file structure and implement
251``COSE_Mac0`` encoding and decoding.
David Huc0427932020-04-09 23:03:49 +0800252
253Although ``COSE_Mac0`` can share lots of data types, APIs and encoding/decoding
David Vinczea7bcb8a2023-08-09 14:35:32 +0200254steps with ``COSE_Sign1`` in implementation, the prototype separated
255``COSE_Mac0`` implementation from ``COSE_Sign1``. ``COSE_Mac0`` owned and owns
256its dedicated signing/verification contexts, APIs and encoding/decoding process.
257The original purposes of separating ``COSE_Mac0`` and ``COSE_Sign1`` are listed
258below
David Huc0427932020-04-09 23:03:49 +0800259
David Vinczea7bcb8a2023-08-09 14:35:32 +0200260- It could keep changes to ``COSE_Sign1`` as small as possible and avoid
261 conflicts with development in ``COSE_Sign1```. It decreased conflicts when
262 the fork in TF-M was synchronized with original ``t_cose`` repository.
David Huc0427932020-04-09 23:03:49 +0800263- ``COSE_Mac0`` and ``COSE_Sign1`` are exclusive in TF-M use cases.
264 It cannot decrease TF-M memory footprint by extracting the common components
David Vinczea7bcb8a2023-08-09 14:35:32 +0200265 shared by ``COSE_Mac0`` and ``COSE_Sign1`` but could make the design
David Huc0427932020-04-09 23:03:49 +0800266 over-complicated.
267
268.. note ::
269
David Vinczea7bcb8a2023-08-09 14:35:32 +0200270 Only HMAC was supported in the ``COSE_Mac0`` prototype.
David Huc0427932020-04-09 23:03:49 +0800271
David Vinczea7bcb8a2023-08-09 14:35:32 +0200272File structure (deprecated)
273===========================
David Huc0427932020-04-09 23:03:49 +0800274
275New files are added to implement the functionalities listed above. The structure
276of files is shown in the table below.
277
278.. table:: New files in ``t_cose``
279 :widths: auto
280 :align: center
281
282 +---------------------+--------------------------------+----------------------------------------------+
283 | Directory | Files | Descriptions |
284 +=====================+================================+==============================================+
285 | ``src`` | ``t_cose_mac0_sign.c`` | Encode ``COSE_Mac0`` structure |
286 | +--------------------------------+----------------------------------------------+
287 | | ``t_cose_mac0_verify.c`` | Decode and verify ``COSE_Mac0`` structure. |
288 +---------------------+--------------------------------+----------------------------------------------+
289 | ``inc`` | ``t_cose_mac0_sign.h`` | Data type definitions and function |
290 | | | declarations of encoding and signing |
291 | | | ``COSE_Mac0`` message. |
292 | +--------------------------------+----------------------------------------------+
293 | | ``t_cose_mac0_verify.h`` | Data type definitions and function |
294 | | | declarations of verifying ``COSE_Mac0`` |
295 | | | message. |
296 +---------------------+--------------------------------+----------------------------------------------+
297
298Other ``t_cose`` files may also be changed to add ``COSE_Mac0`` associated data
299types and function declarations.
300
301HMAC operations are added in ``crypto_adapters/t_cose_psa_crypto.c``.
302Preprocessor flags are added to select corresponding crypto for COSE message
303signing and verification.
304
305 - ``T_COSE_ENABLE_SIGN1`` selects ECDSA and Hash operations for
306 ``COSE_Sign1``.
307 - ``T_COSE_ENABLE_MAC0`` selects HMAC operations for ``COSE_Mac0``.
308
David Vinczea7bcb8a2023-08-09 14:35:32 +0200309Encoding COSE_Mac0 (deprecated)
310===============================
David Huc0427932020-04-09 23:03:49 +0800311
312Following ``COSE_Sign1`` implementation, ``COSE_Mac0`` encoding exports similar
313functions to Initial Attestation secure service.
314The major functions are listed below.
315
316Initialize signing context
317--------------------------
318
319``t_cose_mac0_sign_init()`` initializes ``COSE_Mac0`` signing context and
320configures option flags and algorithm used in signing.
321
322.. code-block:: c
323
324 static void
325 t_cose_mac0_sign_init(struct t_cose_mac0_sign_ctx *me,
326 int32_t option_flags,
327 int32_t cose_algorithm_id);
328
329The ``COSE_Mac0`` signing context is defined as
330
331.. code-block:: c
332
333 struct t_cose_mac0_sign_ctx {
334 /* Private data structure */
335 uint8_t protected_parameters_buffer[
336 T_COSE_MAC0_MAX_SIZE_PROTECTED_PARAMETERS];
337 struct q_useful_buf_c protected_parameters; /* The encoded protected parameters */
338 int32_t cose_algorithm_id;
339 struct t_cose_key signing_key;
340 int32_t option_flags;
341 struct q_useful_buf_c kid;
342 ...
343 };
344
345Set signing key
346---------------
347
348``t_cose_mac0_set_signing_key()`` sets the key used in ``COSE_Mac0`` signing.
Antonio de Angelis9d496a52025-01-07 21:18:00 +0000349Optional ``kid``, as a key identifier, will be encoded into ``COSE_Mac0`` Header
David Huc0427932020-04-09 23:03:49 +0800350unprotected bucket.
351
352.. code-block:: c
353
354 static void
355 t_cose_mac0_set_signing_key(struct t_cose_mac0_sign_ctx *me,
356 struct t_cose_key signing_key,
357 struct q_useful_buf_c kid);
358
359Encode Header parameters
360------------------------
361
362``t_cose_mac0_encode_parameters()`` encodes the ``COSE_Mac0`` Header parameters
363and outputs the encoded context to ``cbor_encode_ctx``.
364
365.. code-block:: c
366
367 enum t_cose_err_t
368 t_cose_mac0_encode_parameters(struct t_cose_mac0_sign_ctx *context,
369 QCBOREncodeContext *cbor_encode_ctx);
370
371Calculate and add authentication tag
372------------------------------------
373
374``t_cose_mac0_encode_tag()`` calculates the authentication tag and finishes the
375``COSE_Mac0`` message.
376
377.. code-block:: c
378
379 enum t_cose_err_t
380 t_cose_mac0_encode_tag(struct t_cose_mac0_sign_ctx *context,
381 QCBOREncodeContext *cbor_encode_ctx);
382
David Vinczea7bcb8a2023-08-09 14:35:32 +0200383Decoding COSE_Mac0 (deprecated)
384===============================
David Huc0427932020-04-09 23:03:49 +0800385
386Following ``COSE_Sign1`` implementation, ``COSE_Mac0`` decoding exports similar
387functions to test suite of Initial Attestation.
388The major functions are listed below.
389
390Initialize verification context
391-------------------------------
392
393``t_cose_mac0_verify_init()`` initializes ``COSE_Mac0`` verification context and
394configures option flags in verification.
395
396.. code-block:: c
397
398 static void
399 t_cose_mac0_verify_init(struct t_cose_mac0_verify_ctx *context,
400 int32_t option_flags);
401
402The ``COSE_Mac0`` verification context is defined as
403
404.. code-block:: c
405
406 struct t_cose_mac0_verify_ctx {
407 /* Private data structure */
408 struct t_cose_key verification_key;
409 int32_t option_flags;
410 };
411
412Set verification key
413--------------------
414
415``t_cose_mac0_set_verify_key()`` sets the key for verifying ``COSE_Mac0``
416authentication tag.
417
418.. code-block:: c
419
420 static void
421 t_cose_mac0_set_verify_key(struct t_cose_mac0_verify_ctx *context,
422 struct t_cose_key verify_key);
423
424Decode and verify COSE_Mac0
425---------------------------
426
427``t_cose_mac0_verify()`` decodes the ``COSE_Mac0`` structure and verifies the
428authentication tag.
429
430.. code-block:: c
431
432 enum t_cose_err_t
433 t_cose_mac0_verify(struct t_cose_mac0_verify_ctx *context,
434 struct q_useful_buf_c cose_mac0,
435 struct q_useful_buf_c *payload,
436 struct t_cose_parameters *parameters);
437
David Huc0427932020-04-09 23:03:49 +0800438***************
439TF-M Test suite
440***************
441
442Symmetric Initial Attestation adds dedicated non-secure and secure test suites.
443The test suites also follow asymmetric Initial Attestation test suites
444implementation but optimize the memory footprint.
445Symmetric Initial Attestation non-secure and secure test suites request Initial
446Attestation secure service to generate IATs. After IATs are generated
447successfully, test suites decode IATs and parse the claims.
448Secure test suite also verifies the authentication tag in ``COSE_Mac0``
449structure.
450
451Symmetric Initial Attestation implements its dedicated
452``attest_token_decode_validate_token()`` in ``attest_symmetric_iat_decoded.c``
453to perform IAT decoding required by test suites.
454If ``SYMMETRIC_INITIAL_ATTESTATION`` is selected,
455``attest_symmetric_iat_decoded.c`` is included in build.
456Otherwise, asymmetric Initial Attestation dedicated implementations are included
457instead.
458
459The workflow of symmetric Initial Attestation dedicated
460``attest_token_decode_validate_token()`` is shown below.
461
462.. _iat-decode-figure:
463
Anton Komlevb3f64662023-01-28 11:53:05 +0000464.. figure:: /design_docs/media/symmetric_initial_attest/iat_decode.png
David Huc0427932020-04-09 23:03:49 +0800465 :align: center
466
467 Workflow in symmetric Initial Attestation ``attest_token_decode_validate_token()``
468
469If the decoding is required from secure test suite,
470``attest_token_decode_validate_token()`` will fetch symmetric IAK to verify the
471authentication tag in ``COSE_Mac0`` structure.
472If the decoding is required from non-secure test suite,
473``attest_token_decode_validate_token()`` will decode ``COSE_Mac0`` only by
474setting ``T_COSE_OPT_DECODE_ONLY`` option flag. Non-secure must not access the
475symmetric IAK.
476
477********
478HAL APIs
479********
480
481HAL APIs are summarized below.
482
483Fetch device symmetric IAK
484==========================
485
486``tfm_plat_get_symmetric_iak()`` fetches device symmetric IAK.
487
488 .. code-block:: c
489
490 enum tfm_plat_err_t tfm_plat_get_symmetric_iak(uint8_t *key_buf,
491 size_t buf_len,
492 size_t *key_len,
493 psa_algorithm_t *key_alg);
494
495 **Parameters:**
496
497 +-------------+-----------------------------------------------------------+
498 | ``key_buf`` | Buffer to store the symmetric IAK. |
499 +-------------+-----------------------------------------------------------+
500 | ``buf_len`` | The length of ``key_buf``. |
501 +-------------+-----------------------------------------------------------+
502 | ``key_len`` | The length of the symmetric IAK. |
503 +-------------+-----------------------------------------------------------+
504 | ``key_alg`` | The key algorithm. Only HMAC SHA-256 is supported so far. |
505 +-------------+-----------------------------------------------------------+
506
507It returns error code specified in ``enum tfm_plat_err_t``.
508
509Get symmetric IAK key identifier
510================================
511
512``attest_plat_get_symmetric_iak_id()`` gets the key identifier of the symmetric
513IAK as the ``kid`` parameter in COSE Header.
514
515Optional if device doesn't install a key identifier for symmetric IAK.
516
517 .. code-block:: c
518
519 enum tfm_plat_err_t attest_plat_get_symmetric_iak_id(void *kid_buf,
520 size_t buf_len,
521 size_t *kid_len);
522
523 **Parameters:**
524
525 +-------------+-------------------------------------+
526 | ``kid_buf`` | Buffer to store the IAK identifier. |
527 +-------------+-------------------------------------+
528 | ``buf_len`` | The length of ``kid_buf``. |
529 +-------------+-------------------------------------+
530 | ``kid_len`` | The length of the IAK identifier. |
531 +-------------+-------------------------------------+
532
533It returns error code specified in ``enum tfm_plat_err_t``.
534
535*********
536Reference
537*********
538
539.. [1] `PSA Attestation API 1.0 (ARM IHI 0085) <https://developer.arm.com/-/media/Files/pdf/PlatformSecurityArchitecture/Implement/IHI0085-PSA_Attestation_API-1.0.2.pdf?revision=eef78753-c77e-4b24-bcf0-65596213b4c1&la=en&hash=E5E0353D612077AFDCE3F2F3708A50C77A74B2A3>`_
540
Anton Komlevaffe14f2022-11-01 00:07:41 +0000541.. [2] :doc:`Trusted Firmware-M Profile Small Design </configuration/profiles/tfm_profile_small>`
David Huc0427932020-04-09 23:03:49 +0800542
Anton Komlev3356ba32022-03-31 22:02:11 +0100543.. [3] :doc:`Initial Attestation Service Integration Guide </integration_guide/services/tfm_attestation_integration_guide>`
David Huc0427932020-04-09 23:03:49 +0800544
545.. [4] `HMAC: Keyed-Hashing for Message Authentication <https://tools.ietf.org/html/rfc2104>`_
546
547.. [5] `CBOR Object Signing and Encryption (COSE) <https://tools.ietf.org/html/rfc8152>`_
548
David Vinczea7bcb8a2023-08-09 14:35:32 +0200549.. [6] `t_cose library <https://github.com/laurencelundblade/t_cose>`_
550
David Huc0427932020-04-09 23:03:49 +0800551----------------
552
David Vinczea7bcb8a2023-08-09 14:35:32 +0200553*Copyright (c) 2020-2024 Arm Limited. All Rights Reserved.*