1 /*
2  * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "crypto.h"
9 
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include "region_defs.h"
14 #include "device_definition.h"
15 #include "otp.h"
16 #include "fih.h"
17 #include "cc3xx_drv.h"
18 #include "kmu_drv.h"
19 
20 #define KEY_DERIVATION_MAX_BUF_SIZE 128
21 
bl1_sha256_init(void)22 fih_int bl1_sha256_init(void)
23 {
24     fih_int fih_rc = FIH_FAILURE;
25 
26     fih_rc = fih_int_encode_zero_equality(cc3xx_lowlevel_hash_init(CC3XX_HASH_ALG_SHA256));
27     if(fih_not_eq(fih_rc, FIH_SUCCESS)) {
28         FIH_RET(FIH_FAILURE);
29     }
30 
31     return FIH_SUCCESS;
32 }
33 
bl1_sha256_finish(uint8_t * hash)34 fih_int bl1_sha256_finish(uint8_t *hash)
35 {
36     uint32_t tmp_buf[32 / sizeof(uint32_t)];
37 
38     cc3xx_lowlevel_hash_finish(tmp_buf, 32);
39 
40     memcpy(hash, tmp_buf, sizeof(tmp_buf));
41 
42     return FIH_SUCCESS;
43 }
44 
bl1_sha256_update(uint8_t * data,size_t data_length)45 fih_int bl1_sha256_update(uint8_t *data, size_t data_length)
46 {
47     fih_int fih_rc = FIH_FAILURE;
48 
49     fih_rc = fih_int_encode_zero_equality(cc3xx_lowlevel_hash_update(data,
50                                                                      data_length));
51     if(fih_not_eq(fih_rc, FIH_SUCCESS)) {
52         FIH_RET(FIH_FAILURE);
53     }
54 
55     return FIH_SUCCESS;
56 }
57 
bl1_sha256_compute(const uint8_t * data,size_t data_length,uint8_t * hash)58 fih_int bl1_sha256_compute(const uint8_t *data,
59                            size_t data_length,
60                            uint8_t *hash)
61 {
62     uint32_t tmp_buf[32 / sizeof(uint32_t)];
63     fih_int fih_rc = FIH_FAILURE;
64 
65     if (data == NULL || hash == NULL) {
66         FIH_RET(FIH_FAILURE);
67     }
68 
69     fih_rc = fih_int_encode_zero_equality(cc3xx_lowlevel_hash_init(CC3XX_HASH_ALG_SHA256));
70     if(fih_not_eq(fih_rc, FIH_SUCCESS)) {
71         FIH_RET(FIH_FAILURE);
72     }
73 
74     fih_rc = fih_int_encode_zero_equality(cc3xx_lowlevel_hash_update(data,
75                                                                      data_length));
76     if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
77         FIH_RET(FIH_FAILURE);
78     }
79     cc3xx_lowlevel_hash_finish(tmp_buf, 32);
80 
81     memcpy(hash, tmp_buf, sizeof(tmp_buf));
82 
83     FIH_RET(FIH_SUCCESS);
84 }
85 
bl1_key_to_kmu_key(enum tfm_bl1_key_id_t key_id,enum kmu_hardware_keyslot_t * cc3xx_key_type,uint8_t ** key_buf,size_t key_buf_size)86 static int32_t bl1_key_to_kmu_key(enum tfm_bl1_key_id_t key_id,
87                                     enum kmu_hardware_keyslot_t *cc3xx_key_type,
88                                     uint8_t **key_buf, size_t key_buf_size)
89 {
90     int32_t rc;
91 
92     switch(key_id) {
93     case TFM_BL1_KEY_HUK:
94         *cc3xx_key_type = KMU_HW_SLOT_HUK;
95         *key_buf = NULL;
96         break;
97     case TFM_BL1_KEY_GUK:
98         *cc3xx_key_type = KMU_HW_SLOT_GUK;
99         *key_buf = NULL;
100         break;
101     default:
102         rc = bl1_otp_read_key(key_id, *key_buf);
103         if (rc) {
104             memset(*key_buf, 0, key_buf_size);
105             return rc;
106         }
107         break;
108     }
109 
110     return 0;
111 }
112 
bl1_aes_256_ctr_decrypt(enum tfm_bl1_key_id_t key_id,const uint8_t * key_material,uint8_t * counter,const uint8_t * ciphertext,size_t ciphertext_length,uint8_t * plaintext)113 int32_t bl1_aes_256_ctr_decrypt(enum tfm_bl1_key_id_t key_id,
114                                 const uint8_t *key_material,
115                                 uint8_t *counter,
116                                 const uint8_t *ciphertext,
117                                 size_t ciphertext_length,
118                                 uint8_t *plaintext)
119 {
120     enum kmu_hardware_keyslot_t kmu_key_slot;
121     uint32_t key_buf[32 / sizeof(uint32_t)];
122     int32_t rc = 0;
123     uint8_t *input_key = (uint8_t *)key_buf;
124     cc3xx_err_t err;
125 
126     if (ciphertext_length == 0) {
127         return 0;
128     }
129 
130     if (counter == NULL || ciphertext == NULL || plaintext == NULL) {
131         return -1;
132     }
133 
134     if ((uintptr_t)counter & 0x3) {
135         return -1;
136     }
137 
138     if (key_material == NULL) {
139         rc = bl1_key_to_kmu_key(key_id, &kmu_key_slot, &input_key,
140                                 sizeof(key_buf));
141         if (rc) {
142             return rc;
143         }
144     } else {
145         input_key = (uint8_t *)key_material;
146     }
147 
148     err = cc3xx_lowlevel_aes_init(CC3XX_AES_DIRECTION_DECRYPT, CC3XX_AES_MODE_CTR,
149                                   kmu_key_slot, (uint32_t *)input_key,
150                                   CC3XX_AES_KEYSIZE_256, (uint32_t *)counter, 16);
151     if (err != CC3XX_ERR_SUCCESS) {
152         return 1;
153     }
154 
155     cc3xx_lowlevel_aes_set_output_buffer(plaintext, ciphertext_length);
156     cc3xx_lowlevel_aes_update(ciphertext, ciphertext_length);
157     cc3xx_lowlevel_aes_finish(NULL, NULL);
158 
159     return 0;
160 }
161 
bl1_derive_key(enum tfm_bl1_key_id_t key_id,const uint8_t * label,size_t label_length,const uint8_t * context,size_t context_length,uint8_t * output_key,size_t output_length)162 int32_t bl1_derive_key(enum tfm_bl1_key_id_t key_id, const uint8_t *label,
163                        size_t label_length, const uint8_t *context,
164                        size_t context_length, uint8_t *output_key,
165                        size_t output_length)
166 {
167     enum kmu_hardware_keyslot_t kmu_key_slot;
168     uint32_t key_buf[32 / sizeof(uint32_t)];
169     uint8_t *input_key = (uint8_t *)key_buf;
170     int32_t rc = 0;
171     cc3xx_err_t err;
172 
173     rc = bl1_key_to_kmu_key(key_id, &kmu_key_slot, &input_key, sizeof(key_buf));
174     if (rc) {
175         return rc;
176     }
177 
178     err = cc3xx_lowlevel_kdf_cmac(kmu_key_slot, (uint32_t *)input_key,
179                                   CC3XX_AES_KEYSIZE_256, label, label_length, context,
180                                   context_length, (uint32_t *)output_key, output_length);
181     if (err != CC3XX_ERR_SUCCESS) {
182         return 1;
183     }
184 
185     return 0;
186 }
187