1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA.
3  * Copyright (c) 2024, Arm Limited. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * Derived from platform/ext/target/nordic_nrf/common/core/tfm_hal_its_encryption.c
20  */
21 
22 #include <stdint.h>
23 #include <string.h>
24 
25 
26 #include "config_tfm.h"
27 #include "platform/include/tfm_hal_its_encryption.h"
28 #include "platform/include/tfm_hal_its.h"
29 #include "platform/include/tfm_platform_system.h"
30 
31 #include "tfm_plat_crypto_keys.h"
32 #include "crypto_keys/tfm_builtin_key_ids.h"
33 #include "tfm_plat_otp.h"
34 #include "psa_manifest/pid.h"
35 #include "tfm_builtin_key_loader.h"
36 
37 
38 #ifndef ITS_CRYPTO_AEAD_ALG
39 #define ITS_CRYPTO_AEAD_ALG PSA_ALG_GCM
40 #endif
41 
42 /* The PSA key type used by this implementation */
43 #define ITS_KEY_TYPE PSA_KEY_TYPE_AES
44 /* The PSA key usage required by this implementation */
45 #define ITS_KEY_USAGE (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT)
46 
47 /* The PSA algorithm used by this implementation */
48 #define ITS_CRYPTO_ALG \
49     PSA_ALG_AEAD_WITH_SHORTENED_TAG(ITS_CRYPTO_AEAD_ALG, TFM_ITS_AUTH_TAG_LENGTH)
50 
51 static uint32_t g_enc_counter;
52 static uint8_t g_enc_nonce_seed[TFM_ITS_ENC_NONCE_LENGTH -
53                                 sizeof(g_enc_counter)];
54 
55 #if TFM_ITS_ENC_NONCE_LENGTH != 12
56 #error "This implementation only supports a ITS nonce of size 12"
57 #endif
58 
59 /* Copy PS solution */
its_crypto_setkey(psa_key_handle_t * its_key,const uint8_t * key_label,size_t key_label_len)60 static psa_status_t its_crypto_setkey(psa_key_handle_t *its_key,
61                                       const uint8_t *key_label,
62                                       size_t key_label_len)
63 {
64     psa_status_t status;
65     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
66     psa_key_derivation_operation_t op = PSA_KEY_DERIVATION_OPERATION_INIT;
67     psa_key_handle_t seed_key = mbedtls_svc_key_id_make(TFM_SP_ITS, TFM_BUILTIN_KEY_ID_HUK);
68 
69     if (key_label_len == 0 || key_label == NULL) {
70         return PSA_ERROR_INVALID_ARGUMENT;
71     }
72 
73     /* Set the key attributes for the storage key */
74     psa_set_key_usage_flags(&attributes, ITS_KEY_USAGE);
75     psa_set_key_algorithm(&attributes, ITS_CRYPTO_ALG);
76     psa_set_key_type(&attributes, ITS_KEY_TYPE);
77     psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(TFM_ITS_KEY_LENGTH));
78 
79     status = psa_key_derivation_setup(&op, PSA_ALG_HKDF(PSA_ALG_SHA_256));
80     if (status != PSA_SUCCESS) {
81         return status;
82     }
83 
84     /* Set up a key derivation operation with HUK  */
85     status = psa_key_derivation_input_key(&op, PSA_KEY_DERIVATION_INPUT_SECRET,
86                                           seed_key);
87     if (status != PSA_SUCCESS) {
88         goto err_release_op;
89     }
90 
91     /* Supply the ITS key label as an input to the key derivation */
92     status = psa_key_derivation_input_bytes(&op, PSA_KEY_DERIVATION_INPUT_INFO,
93                                             key_label,
94                                             key_label_len);
95     if (status != PSA_SUCCESS) {
96         goto err_release_op;
97     }
98 
99     /* Create the storage key from the key derivation operation */
100     status = psa_key_derivation_output_key(&attributes, &op, its_key);
101     if (status != PSA_SUCCESS) {
102         goto err_release_op;
103     }
104 
105     /* Free resources associated with the key derivation operation */
106     status = psa_key_derivation_abort(&op);
107     if (status != PSA_SUCCESS) {
108         goto err_release_key;
109     }
110 
111     return PSA_SUCCESS;
112 
113 err_release_key:
114     (void)psa_destroy_key(*its_key);
115 
116 err_release_op:
117     (void)psa_key_derivation_abort(&op);
118 
119     return PSA_ERROR_GENERIC_ERROR;
120 }
121 
tfm_hal_its_aead_generate_nonce(uint8_t * nonce,const size_t nonce_size)122 enum tfm_hal_status_t tfm_hal_its_aead_generate_nonce(uint8_t *nonce,
123                                                       const size_t nonce_size)
124 {
125     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
126     size_t output_length;
127 
128     if (nonce == NULL){
129         return TFM_HAL_ERROR_INVALID_INPUT;
130     }
131 
132     if (g_enc_counter ==  UINT32_MAX) {
133         return TFM_HAL_ERROR_GENERIC;
134     }
135 
136 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
137     if (g_enc_counter == 0) {
138         status = mbedtls_psa_external_get_random(NULL, &g_enc_nonce_seed[0],
139                                                  sizeof(g_enc_nonce_seed),
140                                                  &output_length);
141         if ((status != PSA_SUCCESS) || (sizeof(g_enc_nonce_seed) != output_length)) {
142             return TFM_HAL_ERROR_GENERIC;
143         }
144     }
145 #else
146     return TFM_HAL_ERROR_NOT_SUPPORTED;
147 #endif
148 
149     memcpy(nonce, g_enc_nonce_seed, sizeof(g_enc_nonce_seed));
150     memcpy(nonce + sizeof(g_enc_nonce_seed),
151                &g_enc_counter,
152                sizeof(g_enc_counter));
153 
154     g_enc_counter++;
155 
156     return TFM_HAL_SUCCESS;
157 }
158 
ctx_is_valid(struct tfm_hal_its_auth_crypt_ctx * ctx)159 static bool ctx_is_valid(struct tfm_hal_its_auth_crypt_ctx *ctx)
160 {
161     bool ret;
162 
163     if (ctx == NULL) {
164         return false;
165     }
166 
167     ret = (ctx->deriv_label == NULL && ctx->deriv_label_size != 0) ||
168           (ctx->aad == NULL && ctx->aad_size != 0) ||
169           (ctx->nonce == NULL && ctx->nonce_size != 0);
170 
171     return !ret;
172 }
173 
tfm_hal_its_aead_encrypt(struct tfm_hal_its_auth_crypt_ctx * ctx,const uint8_t * plaintext,const size_t plaintext_size,uint8_t * ciphertext,const size_t ciphertext_size,uint8_t * tag,const size_t tag_size)174 enum tfm_hal_status_t tfm_hal_its_aead_encrypt(
175                                         struct tfm_hal_its_auth_crypt_ctx *ctx,
176                                         const uint8_t *plaintext,
177                                         const size_t plaintext_size,
178                                         uint8_t *ciphertext,
179                                         const size_t ciphertext_size,
180                                         uint8_t *tag,
181                                         const size_t tag_size)
182 {
183 
184     psa_status_t status;
185     psa_key_handle_t its_key = PSA_KEY_HANDLE_INIT;
186     size_t ciphertext_length;
187 
188     if (!ctx_is_valid(ctx) || tag == NULL) {
189         return TFM_HAL_ERROR_INVALID_INPUT;
190     }
191 
192     if (plaintext_size > ciphertext_size) {
193         return TFM_HAL_ERROR_INVALID_INPUT;
194     }
195 
196     status = its_crypto_setkey(&its_key, ctx->deriv_label, ctx->deriv_label_size);
197     if (status != PSA_SUCCESS) {
198         return TFM_HAL_ERROR_GENERIC;
199     }
200 
201     status = psa_aead_encrypt(its_key, ITS_CRYPTO_ALG,
202                               ctx->nonce, ctx->nonce_size,
203                               ctx->aad, ctx->aad_size,
204                               plaintext, plaintext_size,
205                               ciphertext, ciphertext_size,
206                               &ciphertext_length);
207     if (status != PSA_SUCCESS) {
208         (void)psa_destroy_key(its_key);
209         return TFM_HAL_ERROR_GENERIC;
210     }
211 
212     /* Copy the tag out of the output buffer */
213     ciphertext_length -= TFM_ITS_AUTH_TAG_LENGTH;
214     (void)memcpy(tag, (ciphertext + ciphertext_length), tag_size);
215 
216     /* Destroy the transient key */
217     status = psa_destroy_key(its_key);
218     if (status != PSA_SUCCESS) {
219         return PSA_ERROR_GENERIC_ERROR;
220     }
221 
222     return TFM_HAL_SUCCESS;
223 }
224 
tfm_hal_its_aead_decrypt(struct tfm_hal_its_auth_crypt_ctx * ctx,const uint8_t * ciphertext,const size_t ciphertext_size,uint8_t * tag,const size_t tag_size,uint8_t * plaintext,const size_t plaintext_size)225 enum tfm_hal_status_t tfm_hal_its_aead_decrypt(
226                                         struct tfm_hal_its_auth_crypt_ctx *ctx,
227                                         const uint8_t *ciphertext,
228                                         const size_t ciphertext_size,
229                                         uint8_t *tag,
230                                         const size_t tag_size,
231                                         uint8_t *plaintext,
232                                         const size_t plaintext_size)
233 {
234     psa_status_t status;
235     psa_key_handle_t its_key = PSA_KEY_HANDLE_INIT;
236     size_t ciphertext_and_tag_size, out_len;
237 
238     if (!ctx_is_valid(ctx) || tag == NULL) {
239         return TFM_HAL_ERROR_INVALID_INPUT;
240     }
241 
242     if (plaintext_size < ciphertext_size) {
243         return TFM_HAL_ERROR_INVALID_INPUT;
244     }
245 
246     /* Copy the tag into the input buffer */
247     (void)memcpy((ciphertext + ciphertext_size), tag, TFM_ITS_AUTH_TAG_LENGTH);
248     ciphertext_and_tag_size = ciphertext_size + TFM_ITS_AUTH_TAG_LENGTH;
249 
250     status = its_crypto_setkey(&its_key, ctx->deriv_label, ctx->deriv_label_size);
251     if (status != PSA_SUCCESS) {
252         return TFM_HAL_ERROR_GENERIC;
253     }
254 
255     status = psa_aead_decrypt(its_key, ITS_CRYPTO_ALG,
256                               ctx->nonce, ctx->nonce_size,
257                               ctx->aad, ctx->aad_size,
258                               ciphertext, ciphertext_and_tag_size,
259                               plaintext, plaintext_size,
260                               &out_len);
261     if (status != PSA_SUCCESS) {
262         (void)psa_destroy_key(its_key);
263         return TFM_HAL_ERROR_GENERIC;
264     }
265 
266     /* Destroy the transient key */
267     status = psa_destroy_key(its_key);
268     if (status != PSA_SUCCESS) {
269         return PSA_ERROR_GENERIC_ERROR;
270     }
271 
272     return TFM_HAL_SUCCESS;
273 }
274 
275