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