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