blob: 76aa714fc2f78254a89c91efed43bc41be709b80 [file] [log] [blame]
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -08001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <string.h>
30#include <endian.h>
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -080031#include <debug.h>
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080032#include <reg.h>
33#include <platform/iomap.h>
34#include "crypto_eng.h"
35#include "crypto_hash.h"
36
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -080037/*
38 * Function to reset the crypto engine.
39 */
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080040
41void crypto_eng_reset(void)
42{
Ajay Dudanib01e5062011-12-03 23:23:42 -080043 wr_ce(SW_RST, CRYPTO3_CONFIG);
Channagoud Kadabi9268f4c2012-04-27 11:31:04 +053044 dmb();
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080045}
46
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -080047/*
48 * Function to initialize the crypto engine for a new session. It enables the
49 * auto shutdown feature of CRYPTO3 and mask various interrupts since we use
50 * polling. We are not using DMOV now.
51 */
52
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080053void crypto_eng_init(void)
54{
Ajay Dudanib01e5062011-12-03 23:23:42 -080055 unsigned int val;
56 val = (AUTO_SHUTDOWN_EN | MASK_ERR_INTR | MASK_AUTH_DONE_INTR |
57 MASK_DIN_INTR | MASK_DOUT_INTR | HIGH_SPD_IN_EN_N |
58 HIGH_SPD_OUT_EN_N | HIGH_SPD_HASH_EN_N);
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080059
Ajay Dudanib01e5062011-12-03 23:23:42 -080060 wr_ce(val, CRYPTO3_CONFIG);
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080061}
62
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -080063/*
64 * Function to set various SHAx registers in CRYPTO3 based on algorithm type.
65 */
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080066
Ajay Dudanib01e5062011-12-03 23:23:42 -080067void
68crypto_set_sha_ctx(void *ctx_ptr, unsigned int bytes_to_write,
69 crypto_auth_alg_type auth_alg, bool first, bool last)
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080070{
Ajay Dudanib01e5062011-12-03 23:23:42 -080071 crypto_SHA1_ctx *sha1_ctx = (crypto_SHA1_ctx *) ctx_ptr;
72 crypto_SHA256_ctx *sha256_ctx = (crypto_SHA256_ctx *) ctx_ptr;
73 unsigned int i = 0;
74 unsigned int iv_len = 0;
75 unsigned int *auth_iv;
76 unsigned int seg_cfg_val;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080077
Ajay Dudanib01e5062011-12-03 23:23:42 -080078 seg_cfg_val = SEG_CFG_AUTH_ALG_SHA;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080079
Ajay Dudanib01e5062011-12-03 23:23:42 -080080 if (auth_alg == CRYPTO_AUTH_ALG_SHA1) {
81 seg_cfg_val |= SEG_CFG_AUTH_SIZE_SHA1;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -080082
Ajay Dudanib01e5062011-12-03 23:23:42 -080083 if ((first) || ((sha1_ctx->saved_buff_indx != 0) &&
84 (sha1_ctx->auth_bytecnt[0] != 0
85 || sha1_ctx->auth_bytecnt[1] != 0))) {
86 seg_cfg_val |= SEG_CFG_FIRST;
87 }
88 if (last) {
89 seg_cfg_val |= SEG_CFG_LAST;
90 }
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -080091
Ajay Dudanib01e5062011-12-03 23:23:42 -080092 iv_len = SHA1_INIT_VECTOR_SIZE;
93 auth_iv = sha1_ctx->auth_iv;
94 } else if (auth_alg == CRYPTO_AUTH_ALG_SHA256) {
95 seg_cfg_val |= SEG_CFG_AUTH_SIZE_SHA256;
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -080096
Ajay Dudanib01e5062011-12-03 23:23:42 -080097 if ((first) || ((sha256_ctx->saved_buff_indx != 0) &&
98 (sha256_ctx->auth_bytecnt[0] != 0
99 || sha256_ctx->auth_bytecnt[1] != 0))) {
100 seg_cfg_val |= SEG_CFG_FIRST;
101 }
102 if (last) {
103 seg_cfg_val |= SEG_CFG_LAST;
104 }
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800105
Ajay Dudanib01e5062011-12-03 23:23:42 -0800106 iv_len = SHA256_INIT_VECTOR_SIZE;
107 auth_iv = sha256_ctx->auth_iv;
108 } else {
109 dprintf(CRITICAL,
110 "crypto_set_sha_ctx invalid auth algorithm\n");
111 return;
112 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800113
Ajay Dudanib01e5062011-12-03 23:23:42 -0800114 for (i = 0; i < iv_len; i++) {
115 wr_ce(*(auth_iv + i), CRYPTO3_AUTH_IVn(i));
116 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800117
Ajay Dudanib01e5062011-12-03 23:23:42 -0800118 wr_ce(seg_cfg_val, CRYPTO3_SEG_CFG);
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800119
Ajay Dudanib01e5062011-12-03 23:23:42 -0800120 /* Typecast with crypto_SHA1_ctx because offset of auth_bytecnt in both
121 crypto_SHA1_ctx and crypto_SHA256_ctx are same */
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800122
Ajay Dudanib01e5062011-12-03 23:23:42 -0800123 wr_ce(((crypto_SHA1_ctx *) ctx_ptr)->auth_bytecnt[0],
124 CRYPTO3_AUTH_BYTECNTn(0));
125 wr_ce(((crypto_SHA1_ctx *) ctx_ptr)->auth_bytecnt[1],
126 CRYPTO3_AUTH_BYTECNTn(1));
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800127
Ajay Dudanib01e5062011-12-03 23:23:42 -0800128 wr_ce((bytes_to_write << AUTH_SEG_CFG_AUTH_SIZE), CRYPTO3_AUTH_SEG_CFG);
129 wr_ce(bytes_to_write, CRYPTO3_SEG_SIZE);
130 wr_ce(GOPROC_GO, CRYPTO3_GOPROC);
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800131
Ajay Dudanib01e5062011-12-03 23:23:42 -0800132 return;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800133}
134
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800135/*
136 * Function to send data to CRYPTO3. This is non-DMOV implementation and uses
137 * polling to send the requested amount of data.
138 */
139
Ajay Dudanib01e5062011-12-03 23:23:42 -0800140void
141crypto_send_data(void *ctx_ptr, unsigned char *data_ptr,
142 unsigned int buff_size, unsigned int bytes_to_write,
143 unsigned int *ret_status)
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800144{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800145 crypto_SHA1_ctx *sha1_ctx = (crypto_SHA1_ctx *) ctx_ptr;
146 unsigned int bytes_left = 0;
147 unsigned int i = 0;
148 unsigned int ce_status = 0;
149 unsigned int ce_err_bmsk = 0;
150 unsigned int is_not_aligned = FALSE;
151 unsigned char data[4];
152 unsigned char *buff_ptr = data_ptr;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800153
Ajay Dudanib01e5062011-12-03 23:23:42 -0800154 /* Check if the buff_ptr is aligned */
155 if (!(IS_ALIGNED(buff_ptr))) {
156 is_not_aligned = TRUE;
157 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800158
Ajay Dudanib01e5062011-12-03 23:23:42 -0800159 /* Fill the saved_buff with data from buff_ptr. First we have to write
160 all the data from the saved_buff and then we will write data from
161 buff_ptr. We will update bytes_left and buff_ptr in the while loop
162 once are done writing all the data from saved_buff. */
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800163
Ajay Dudanib01e5062011-12-03 23:23:42 -0800164 if (sha1_ctx->saved_buff_indx != 0) {
165 memcpy(sha1_ctx->saved_buff + sha1_ctx->saved_buff_indx,
166 buff_ptr,
167 (((buff_size + sha1_ctx->saved_buff_indx) <=
168 CRYPTO_SHA_BLOCK_SIZE)
169 ? buff_size : (CRYPTO_SHA_BLOCK_SIZE -
170 sha1_ctx->saved_buff_indx)));
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800171
Ajay Dudanib01e5062011-12-03 23:23:42 -0800172 if (bytes_to_write >= CRYPTO_SHA_BLOCK_SIZE) {
173 bytes_left = CRYPTO_SHA_BLOCK_SIZE;
174 } else {
175 bytes_left = bytes_to_write;
176 }
177 } else {
178 bytes_left = bytes_to_write;
179 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800180
Ajay Dudanib01e5062011-12-03 23:23:42 -0800181 /* Error bitmask to check crypto engine status */
182 ce_err_bmsk = (SW_ERR | DIN_RDY | DIN_SIZE_AVAIL);
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800183
Ajay Dudanib01e5062011-12-03 23:23:42 -0800184 while (bytes_left >= 4) {
185 ce_status = rd_ce(CRYPTO3_STATUS);
186 ce_status &= ce_err_bmsk;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800187
Ajay Dudanib01e5062011-12-03 23:23:42 -0800188 if (ce_status & SW_ERR) {
189 /* If there is SW_ERR, reset the engine */
190 crypto_eng_reset();
191 *ret_status = CRYPTO_ERR_FAIL;
192 dprintf(CRITICAL, "crypto_send_data sw error\n");
193 return;
194 }
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800195
Ajay Dudanib01e5062011-12-03 23:23:42 -0800196 /* We can write data now - 4 bytes at a time in network byte order */
197 if ((ce_status & DIN_RDY)
198 && ((ce_status & DIN_SIZE_AVAIL) >= 4)) {
199 if (sha1_ctx->saved_buff_indx != 0) {
200 /* Write from saved_buff */
201 wr_ce(htonl
202 (*
203 ((unsigned int *)(sha1_ctx->saved_buff) +
204 i)), CRYPTO3_DATA_IN);
205 } else {
206 if (!is_not_aligned) {
207 /* Write from buff_ptr aligned */
208 wr_ce(htonl
209 (*((unsigned int *)buff_ptr + i)),
210 CRYPTO3_DATA_IN);
211 } else {
212 /* If buff_ptr is not aligned write byte by byte */
213 data[0] = *(buff_ptr + i);
214 data[1] = *(buff_ptr + i + 1);
215 data[2] = *(buff_ptr + i + 2);
216 data[3] = *(buff_ptr + i + 3);
217 /* i will incremented by 1 in outside block */
218 i += 3;
219 wr_ce(htonl(*(unsigned int *)data),
220 CRYPTO3_DATA_IN);
221 memset(data, 0, 4);
222 }
223 }
224 i++;
225 bytes_left -= 4;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800226
Ajay Dudanib01e5062011-12-03 23:23:42 -0800227 /* Check if we have written from saved_buff. Adjust buff_ptr and
228 bytes_left accordingly */
229 if ((sha1_ctx->saved_buff_indx != 0)
230 && (bytes_left == 0)
231 && (bytes_to_write > CRYPTO_SHA_BLOCK_SIZE)) {
232 bytes_left =
233 (bytes_to_write - CRYPTO_SHA_BLOCK_SIZE);
234 buff_ptr =
235 (unsigned char *)((unsigned char *)data_ptr
236 + CRYPTO_SHA_BLOCK_SIZE -
237 sha1_ctx->
238 saved_buff_indx);
239 i = 0;
240 sha1_ctx->saved_buff_indx = 0;
241 if (!(IS_ALIGNED(buff_ptr))) {
242 is_not_aligned = TRUE;
243 }
244 }
245 }
246 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800247
Ajay Dudanib01e5062011-12-03 23:23:42 -0800248 /* We might have bytes_left < 4. Write them now if available */
249 if (bytes_left) {
250 memset(data, 0, sizeof(unsigned int));
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800251
Ajay Dudanib01e5062011-12-03 23:23:42 -0800252 if (sha1_ctx->saved_buff_indx)
253 buff_ptr = (sha1_ctx->saved_buff + bytes_to_write - 1);
254 else
255 buff_ptr =
256 (((unsigned char *)data_ptr) + buff_size - 1);
Subbaraman Narayanamurthy22d53c62011-04-12 18:15:50 -0700257
Ajay Dudanib01e5062011-12-03 23:23:42 -0800258 for (i = 0; i < bytes_left; i++) {
259 data[3 - i] = *(buff_ptr - bytes_left + i + 1);
260 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800261
Ajay Dudanib01e5062011-12-03 23:23:42 -0800262 ce_status = rd_ce(CRYPTO3_STATUS);
263 ce_status &= ce_err_bmsk;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800264
Ajay Dudanib01e5062011-12-03 23:23:42 -0800265 if (ce_status & SW_ERR) {
266 crypto_eng_reset();
267 *ret_status = CRYPTO_ERR_FAIL;
268 dprintf(CRITICAL, "crypto_send_data sw error 2\n");
269 return;
270 }
271 if ((ce_status & DIN_RDY)
272 && ((ce_status & DIN_SIZE_AVAIL) >= 4)) {
273 wr_ce(*(unsigned int *)data, CRYPTO3_DATA_IN);
274 }
275 }
276 *ret_status = CRYPTO_ERR_NONE;
277 return;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800278}
279
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800280/*
281 * Function to get digest from CRYPTO3. We poll for AUTH_DONE from CRYPTO3.
282 */
283
Ajay Dudanib01e5062011-12-03 23:23:42 -0800284void
285crypto_get_digest(unsigned char *digest_ptr, unsigned int *ret_status,
286 crypto_auth_alg_type auth_alg, bool last)
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800287{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800288 unsigned int ce_status = 0;
289 unsigned int ce_err_bmsk = (AUTH_DONE | SW_ERR);
290 unsigned int i = 0;
291 unsigned int digest_len = 0;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800292
Ajay Dudanib01e5062011-12-03 23:23:42 -0800293 do {
294 ce_status = rd_ce(CRYPTO3_STATUS);
295 ce_status &= ce_err_bmsk;
296 }
297 while (ce_status == 0);
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800298
Ajay Dudanib01e5062011-12-03 23:23:42 -0800299 if (ce_status & SW_ERR) {
300 crypto_eng_reset();
301 *ret_status = CRYPTO_ERR_FAIL;
302 dprintf(CRITICAL, "crypto_get_digest sw error\n");
303 return;
304 }
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800305
Ajay Dudanib01e5062011-12-03 23:23:42 -0800306 /* Digest length depends on auth_alg */
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800307
Ajay Dudanib01e5062011-12-03 23:23:42 -0800308 if (auth_alg == CRYPTO_AUTH_ALG_SHA1) {
309 digest_len = SHA1_INIT_VECTOR_SIZE;
310 } else if (auth_alg == CRYPTO_AUTH_ALG_SHA256) {
311 digest_len = SHA256_INIT_VECTOR_SIZE;
312 }
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800313
Ajay Dudanib01e5062011-12-03 23:23:42 -0800314 /* Retrieve digest from CRYPTO3 */
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800315
Ajay Dudanib01e5062011-12-03 23:23:42 -0800316 for (i = 0; i < digest_len; i++) {
317 unsigned int auth_iv = rd_ce(CRYPTO3_AUTH_IVn(i));
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800318
Ajay Dudanib01e5062011-12-03 23:23:42 -0800319 if (last) {
320 *((unsigned int *)digest_ptr + i) = htonl(auth_iv);
321 } else {
322 *((unsigned int *)digest_ptr + i) = auth_iv;
323 }
324 }
325 *ret_status = CRYPTO_ERR_NONE;
326 return;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800327}
328
Subbaraman Narayanamurthy8fcccbd2011-01-28 13:26:00 -0800329/* Function to restore auth_bytecnt registers for ctx_ptr */
330
331void crypto_get_ctx(void *ctx_ptr)
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800332{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800333 ((crypto_SHA1_ctx *) ctx_ptr)->auth_bytecnt[0] =
334 rd_ce(CRYPTO3_AUTH_BYTECNTn(0));
335 ((crypto_SHA1_ctx *) ctx_ptr)->auth_bytecnt[1] =
336 rd_ce(CRYPTO3_AUTH_BYTECNTn(1));
337 return;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800338}