1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "drv_osal_lib.h"
20 #include "hal_efuse.h"
21 #include "hal_otp.h"
22 #include "drv_cipher_kapi.h"
23 #include "drv_klad.h"
24 #include "securec.h"
25
26 #define KLAD_REG_BASE_ADDR g_cipher_klad_base
27 #define KLAD_BASE_BUF_SIZE 0x100
28 #define KLAD_REG_KLAD_CTRL (KLAD_REG_BASE_ADDR + 0x00)
29 #define KLAD_REG_DAT_IN (KLAD_REG_BASE_ADDR + 0x10)
30 #define KLAD_REG_ENC_OUT (KLAD_REG_BASE_ADDR + 0x20)
31
32 #define CIPHER_WAIT_IDLE_TIMES 1000
33
34 static hi_u8 *g_cipher_klad_base = HI_NULL;
35
hal_cipher_klad_config(hi_u32 chn_id,hi_u32 opt_id,hi_cipher_klad_target target,hi_bool is_decrypt)36 hi_s32 hal_cipher_klad_config(hi_u32 chn_id, hi_u32 opt_id, hi_cipher_klad_target target, hi_bool is_decrypt)
37 {
38 hi_s32 ret;
39 klad_ctrl ctrl;
40
41 /* Load efuse or OTP key to KLAD */
42 ret = hal_efuse_otp_load_cipher_key(chn_id, opt_id);
43 if (ret != HI_SUCCESS) {
44 hi_log_print_func_err(hal_efuse_otp_load_cipher_key, ret);
45 return ret;
46 }
47
48 ctrl.u32 = 0;
49 ctrl.bits.klad2ci_addr = chn_id;
50 ctrl.bits.type = target;
51 ctrl.bits.decrypt = is_decrypt;
52 ctrl.bits.start = KLAD_CTRL_NOT_START;
53
54 (hi_void)hal_cipher_write_reg(KLAD_REG_KLAD_CTRL, ctrl.u32);
55 return HI_SUCCESS;
56 }
57
hal_cipher_start_klad(hi_u32 block_num)58 hi_void hal_cipher_start_klad(hi_u32 block_num)
59 {
60 klad_ctrl ctrl;
61
62 ctrl.u32 = 0;
63 hal_cipher_read_reg(KLAD_REG_KLAD_CTRL, &ctrl.u32);
64
65 /* High 128bits is just meaningful for loading cipher 256 bits key, and meaningless to rsa. */
66 if (block_num == KLAD_HIGH_128BIT_BLOCK) {
67 ctrl.bits.high_low_128bit_flag = KLAD_CTRL_HIGH_128BIT_FLAG;
68 } else {
69 ctrl.bits.high_low_128bit_flag = KLAD_CTRL_LOW_128BIT_FLAG;
70 }
71
72 /* start */
73 ctrl.bits.start = KLAD_CTRL_START;
74 hal_cipher_write_reg(KLAD_REG_KLAD_CTRL, ctrl.u32);
75 }
76
hal_cipher_set_klad_data(const hi_u32 * data_in,hi_u32 data_len_in_word)77 hi_void hal_cipher_set_klad_data(const hi_u32 *data_in, hi_u32 data_len_in_word)
78 {
79 hi_u32 i;
80
81 /* The length of klad input key is 16 bytes. */
82 for (i = 0; i < data_len_in_word; i++) {
83 (hi_void)hal_cipher_write_reg(KLAD_REG_DAT_IN + i * WORD_WIDTH, data_in[i]);
84 }
85 }
86
hal_cipher_get_klad_data(hi_u32 * data_out,hi_u32 data_len_in_word)87 hi_void hal_cipher_get_klad_data(hi_u32 *data_out, hi_u32 data_len_in_word)
88 {
89 hi_u32 i;
90
91 /* The length of klad output key is 16 bytes. */
92 for (i = 0; i < data_len_in_word; i++) {
93 (hi_void)hal_cipher_read_reg(KLAD_REG_ENC_OUT + i * WORD_WIDTH, &data_out[i]);
94 }
95 }
96
hal_cipher_wait_klad_done(hi_void)97 hi_s32 hal_cipher_wait_klad_done(hi_void)
98 {
99 hi_s32 i;
100 klad_ctrl ctrl;
101
102 for (i = 0; i < CIPHER_WAIT_IDLE_TIMES; i++) {
103 ctrl.u32 = 0;
104 hal_cipher_read_reg(KLAD_REG_KLAD_CTRL, &ctrl.u32);
105 if (ctrl.bits.start == KLAD_CTRL_NOT_START) {
106 return HI_SUCCESS;
107 }
108 }
109
110 if (i >= CIPHER_WAIT_IDLE_TIMES) {
111 hi_log_error("Klad wait time out!\n");
112 return HI_ERR_CIPHER_TIMEOUT;
113 }
114
115 return HI_SUCCESS;
116 }
117
hal_cipher_klad_init(hi_void)118 static hi_void hal_cipher_klad_init(hi_void)
119 {
120 hi_u32 crg_value = 0;
121 hi_u32 *sys_addr = HI_NULL;
122
123 sys_addr = crypto_ioremap_nocache(KLAD_CRG_ADDR_PHY, KLAD_BASE_BUF_SIZE);
124 if (sys_addr == HI_NULL) {
125 hi_log_error("ERROR: sys_addr ioremap with nocache failed!!\n");
126 return;
127 }
128
129 hal_cipher_read_reg(sys_addr, &crg_value);
130 crg_value |= KLAD_CRG_RESET_BIT; /* reset */
131 crg_value |= KLAD_CRG_CLOCK_BIT; /* set the bit 1, clock opened */
132 hal_cipher_write_reg(sys_addr, crg_value);
133
134 /* clock select and cancel reset 0x30100. */
135 crg_value &= (~KLAD_CRG_RESET_BIT); /* cancel reset */
136 crg_value |= KLAD_CRG_CLOCK_BIT; /* set the bit 1, clock opened */
137 hal_cipher_write_reg(sys_addr, crg_value);
138
139 crypto_iounmap(sys_addr, KLAD_BASE_BUF_SIZE);
140 }
141
drv_cipher_klad_init(hi_void)142 hi_s32 drv_cipher_klad_init(hi_void)
143 {
144 hi_s32 ret;
145
146 g_cipher_klad_base = crypto_ioremap_nocache(KLAD_REG_BASE_ADDR_PHY, KLAD_BASE_BUF_SIZE);
147 if (g_cipher_klad_base == HI_NULL) {
148 hi_log_error("ERROR: osal_ioremap_nocache for KLAD failed!!\n");
149 return HI_ERR_CIPHER_FAILED_MEM;
150 }
151
152 ret = hal_efuse_otp_init();
153 if (ret != HI_SUCCESS) {
154 crypto_iounmap(g_cipher_klad_base, KLAD_BASE_BUF_SIZE);
155 return ret;
156 }
157
158 hal_cipher_klad_init();
159
160 return HI_SUCCESS;
161 }
162
drv_cipher_klad_deinit(hi_void)163 hi_void drv_cipher_klad_deinit(hi_void)
164 {
165 hi_u8 *local_efuse_otp_reg_base = HI_NULL;
166
167 if (g_cipher_klad_base != HI_NULL) {
168 crypto_iounmap(g_cipher_klad_base, KLAD_BASE_BUF_SIZE);
169 g_cipher_klad_base = HI_NULL;
170 }
171
172 local_efuse_otp_reg_base = hal_efuse_otp_get_reg_base();
173 if (local_efuse_otp_reg_base != HI_NULL) {
174 crypto_iounmap(local_efuse_otp_reg_base, KLAD_BASE_BUF_SIZE);
175 local_efuse_otp_reg_base = HI_NULL;
176 hal_efuse_otp_set_reg_base(local_efuse_otp_reg_base);
177 }
178
179 return;
180 }
181
drv_cipher_inverse_data(hi_u8 * data,hi_u32 len)182 static hi_void drv_cipher_inverse_data(hi_u8 *data, hi_u32 len)
183 {
184 hi_u32 i;
185 hi_u8 ch;
186
187 for (i = 0; i < len / MUL_VAL_2; i++) {
188 ch = data[i];
189 data[i] = data[len - i - BOUND_VAL_1];
190 data[len - i - BOUND_VAL_1] = ch;
191 }
192 }
193
194 /* load aes or rsa clean key to klad. */
drv_cipher_klad_load_key(hi_u32 chn_id,hi_cipher_ca_type root_key,hi_cipher_klad_target target,const hi_u8 * data_in,hi_u32 key_len)195 hi_s32 drv_cipher_klad_load_key(hi_u32 chn_id,
196 hi_cipher_ca_type root_key, hi_cipher_klad_target target, const hi_u8 *data_in, hi_u32 key_len)
197 {
198 hi_s32 ret;
199 hi_u32 i, otp_id;
200 hi_u32 key[AES_BLOCK_SIZE / WORD_WIDTH] = {0};
201
202 hi_log_chk_param_return((root_key < HI_CIPHER_KEY_SRC_KLAD_1) || (root_key > HI_CIPHER_KEY_SRC_KLAD_3));
203 hi_log_chk_param_return(target >= HI_CIPHER_KLAD_TARGET_BUTT);
204 hi_log_chk_param_return(data_in == HI_NULL);
205 hi_log_chk_param_return(((key_len % AES_BLOCK_SIZE) != 0) || (key_len == 0));
206
207 otp_id = root_key - HI_CIPHER_KEY_SRC_KLAD_1 + BOUND_VAL_1;
208
209 ret = hal_cipher_klad_config(chn_id, otp_id, target, HI_TRUE);
210 if (ret != HI_SUCCESS) {
211 hi_log_error("Error: cipher klad config failed!\n");
212 return ret;
213 }
214
215 for (i = 0; i < key_len / AES_BLOCK_SIZE; i++) {
216 if (memcpy_s(key, sizeof(key), data_in + i * AES_BLOCK_SIZE, AES_BLOCK_SIZE) != EOK) {
217 hi_log_print_func_err(memcpy_s, HI_ERR_CIPHER_MEMCPY_S_FAILED);
218 return HI_ERR_CIPHER_MEMCPY_S_FAILED;
219 }
220 hal_cipher_set_klad_data(key, sizeof(key) / WORD_WIDTH);
221 hal_cipher_start_klad(i);
222 ret = hal_cipher_wait_klad_done();
223 if (ret != HI_SUCCESS) {
224 hi_log_error("Error: cipher klad wait done failed!\n");
225 (hi_void)memset_s(key, sizeof(key), 0, sizeof(key));
226 return ret;
227 }
228 }
229
230 (hi_void)memset_s(key, sizeof(key), 0, sizeof(key));
231 return HI_SUCCESS;
232 }
233
drv_cipher_klad_encrypt_key(hi_cipher_ca_type root_key,hi_cipher_klad_target target,hi_u8 * clean_key,hi_u8 * encrypt_key,hi_u32 key_len)234 hi_s32 drv_cipher_klad_encrypt_key(hi_cipher_ca_type root_key,
235 hi_cipher_klad_target target, hi_u8 *clean_key, hi_u8 *encrypt_key, hi_u32 key_len)
236 {
237 hi_s32 ret;
238 hi_u32 otp_id;
239
240 hi_log_chk_param_return((root_key < HI_CIPHER_KEY_SRC_KLAD_1) || (root_key >= HI_CIPHER_KEY_SRC_BUTT));
241 hi_log_chk_param_return(target >= HI_CIPHER_KLAD_TARGET_BUTT);
242 hi_log_chk_param_return((clean_key == HI_NULL) || (encrypt_key == HI_NULL));
243 hi_log_chk_param_return(key_len != AES_BLOCK_SIZE);
244
245 otp_id = root_key - HI_CIPHER_KEY_SRC_KLAD_1 + BOUND_VAL_1;
246
247 ret = hal_cipher_klad_config(0, otp_id, HI_CIPHER_KLAD_TARGET_AES, HI_FALSE);
248 if (ret != HI_SUCCESS) {
249 hi_log_error("Error: cipher klad config failed!\n");
250 return ret;
251 }
252
253 if (target == HI_CIPHER_KLAD_TARGET_RSA) {
254 drv_cipher_inverse_data(clean_key, key_len);
255 }
256
257 hal_cipher_set_klad_data((hi_u32 *)clean_key, key_len / WORD_WIDTH);
258 hal_cipher_start_klad(0);
259 ret = hal_cipher_wait_klad_done();
260 if (ret != HI_SUCCESS) {
261 hi_log_error("Error: cipher klad wait done failed!\n");
262 return ret;
263 }
264 hal_cipher_get_klad_data((hi_u32 *)encrypt_key, key_len / WORD_WIDTH);
265
266 return HI_SUCCESS;
267 }
268
269