1 /*
2  * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <string.h>
9 
10 #include "flash_fs/its_flash_fs.h"
11 #include "flash/its_flash.h"
12 #include "its_utils.h"
13 #include "psa_manifest/pid.h"
14 #include "tfm_hal_its_encryption.h"
15 #include "tfm_hal_ps.h"
16 #include "tfm_internal_trusted_storage.h"
17 #include "tfm_its_defs.h"
18 #include "tfm_sp_log.h"
19 
20 /**
21  * \brief Fills the AEAD additional data used for the encryption/decryption
22  *
23  * \details The additional data are not encypted their integrity is checked.
24  *          For the ITS encryption we use the file id, the file flags and the
25  *          data size of the file as addditional data.
26  *
27  * \param[out]  add       Additional data
28  * \param[in]   add_size  Additional data size in bytes
29  * \param[in]   fid       Identifier of the file
30  * \param[in]   fid_size  Identifier of the file size in bytes
31  * \param[in]   flags     Flags of the file
32  * \param[in]   data_size Data size in bytes
33  *
34  * \retval PSA_SUCCESS                On success
35  * \retval PSA_ERROR_INVALID_ARGUMENT When the addditional data buffer does not
36  *                                    have the correct size of the add/fid
37  *                                    buffers are NULL
38  *
39  */
tfm_its_fill_enc_add(uint8_t * add,const size_t add_size,const uint8_t * fid,const size_t fid_size,const uint32_t flags,const size_t data_size)40 static psa_status_t tfm_its_fill_enc_add(uint8_t *add,
41                                          const size_t add_size,
42                                          const uint8_t *fid,
43                                          const size_t fid_size,
44                                          const uint32_t flags,
45                                          const size_t data_size)
46 
47 {
48     /* Only the user flags are populated in the function which
49      * gets the file info from ITS (see its_flash_fs_file_get_info).
50      * We use the same flags for conformity.
51      */
52     uint32_t user_flags = flags & ITS_FLASH_FS_USER_FLAGS_MASK;
53 
54     /* The additional data consist of the file id, the flags and the
55      * data size of the file.
56      */
57     size_t add_expected_size = ITS_FILE_ID_SIZE +
58                                sizeof(user_flags) +
59                                sizeof(data_size);
60 
61     if (add_size != add_expected_size || add == NULL || fid == NULL) {
62         return PSA_ERROR_INVALID_ARGUMENT;
63     }
64 
65     memcpy(add, fid, fid_size);
66     memcpy(add + fid_size, &user_flags, sizeof(user_flags));
67     memcpy(add + fid_size + sizeof(user_flags),
68                &data_size,
69                sizeof(data_size));
70 
71     return PSA_SUCCESS;
72 }
73 
tfm_hal_to_psa_error(enum tfm_hal_status_t tfm_hal_err)74 static psa_status_t tfm_hal_to_psa_error(enum tfm_hal_status_t tfm_hal_err)
75 {
76     switch (tfm_hal_err) {
77     case TFM_HAL_SUCCESS:
78         return PSA_SUCCESS;
79     case TFM_HAL_ERROR_INVALID_INPUT:
80         return PSA_ERROR_INVALID_ARGUMENT;
81     default:
82         return PSA_ERROR_GENERIC_ERROR;
83     }
84 }
85 
tfm_its_crypt_file(struct its_flash_fs_file_info_t * finfo,uint8_t * fid,const size_t fid_size,const uint8_t * input,const size_t input_size,uint8_t * output,const size_t output_size,const bool is_encrypt)86 psa_status_t tfm_its_crypt_file(struct its_flash_fs_file_info_t *finfo,
87                                 uint8_t *fid,
88                                 const size_t fid_size,
89                                 const uint8_t *input,
90                                 const size_t input_size,
91                                 uint8_t *output,
92                                 const size_t output_size,
93                                 const bool is_encrypt)
94 {
95     struct tfm_hal_its_auth_crypt_ctx aead_ctx = {0};
96     enum tfm_hal_status_t err;
97     size_t file_size;
98 
99     if (finfo == NULL) {
100         return PSA_ERROR_INVALID_ARGUMENT;
101     }
102 
103     /* The file size is not known yet when encrypting */
104     if (is_encrypt) {
105         file_size = input_size;
106     } else {
107         file_size = finfo->size_current;
108     }
109 
110     err =  tfm_its_fill_enc_add(finfo->aad,
111                                 sizeof(finfo->aad),
112                                 fid,
113                                 fid_size,
114                                 finfo->flags,
115                                 file_size);
116     if (err != TFM_HAL_SUCCESS) {
117         return tfm_hal_to_psa_error(err);
118     }
119 
120     if (is_encrypt) {
121         err = tfm_hal_its_aead_generate_nonce(finfo->nonce,
122                                               sizeof(finfo->nonce));
123 
124         if (err != TFM_HAL_SUCCESS) {
125             return tfm_hal_to_psa_error(err);
126         }
127     }
128 
129     /* Set all required parameters for the aead operation context */
130     aead_ctx.nonce = finfo->nonce;
131     aead_ctx.nonce_size = sizeof(finfo->nonce);
132     aead_ctx.deriv_label = fid;
133     aead_ctx.deriv_label_size = fid_size;
134     aead_ctx.aad = finfo->aad;
135     aead_ctx.aad_size = sizeof(finfo->aad);
136 
137 
138     if (is_encrypt) {
139         err = tfm_hal_its_aead_encrypt(&aead_ctx,
140                                        input,
141                                        input_size,
142                                        output,
143                                        output_size,
144                                        finfo->tag,
145                                        sizeof(finfo->tag));
146     } else {
147         err = tfm_hal_its_aead_decrypt(&aead_ctx,
148                                        input,
149                                        input_size,
150                                        finfo->tag,
151                                        sizeof(finfo->tag),
152                                        output,
153                                        output_size);
154     }
155 
156     if (err != TFM_HAL_SUCCESS) {
157         return tfm_hal_to_psa_error(err);
158     }
159 
160     if (is_encrypt) {
161         finfo->size_max = input_size;
162     }
163 
164     return PSA_SUCCESS;
165 }
166 
167