1 /* caam_sha.c
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <wolfssl/wolfcrypt/settings.h>
27
28 #if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH)
29
30 #include <wolfssl/wolfcrypt/logging.h>
31 #include <wolfssl/wolfcrypt/error-crypt.h>
32
33 #ifdef NO_INLINE
34 #include <wolfssl/wolfcrypt/misc.h>
35 #else
36 #define WOLFSSL_MISC_INCLUDED
37 #include <wolfcrypt/src/misc.c>
38 #endif
39
40
41 #if defined(__INTEGRITY) || defined(INTEGRITY)
42 #include <INTEGRITY.h>
43 #endif
44 #include <wolfssl/wolfcrypt/port/caam/caam_driver.h>
45 #include <wolfssl/wolfcrypt/port/caam/wolfcaam.h>
46
47 #if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
48 #include <stdio.h>
49 #endif
50
51 #ifndef NO_SHA
52 #include <wolfssl/wolfcrypt/sha.h>
53 #endif
54
55 #if !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
56 #include <wolfssl/wolfcrypt/sha256.h>
57 #endif
58
59 #if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
60 #include <wolfssl/wolfcrypt/sha512.h>
61 #endif
62
63 #ifndef NO_MD5
64 #include <wolfssl/wolfcrypt/md5.h>
65 #endif
66
67 /******************************************************************************
68 Common Code Between SHA Functions
69 ****************************************************************************/
70
_InitSha(wc_Sha * sha,void * heap,int devId,word32 digestSz,word32 type)71 static int _InitSha(wc_Sha* sha, void* heap, int devId, word32 digestSz,
72 word32 type)
73 {
74 Buffer buf[1];
75 word32 arg[4];
76 int ret;
77
78 (void)heap;
79 (void)devId;
80
81 if (sha == NULL) {
82 return BAD_FUNC_ARG;
83 }
84
85 XMEMSET(sha, 0, sizeof(Sha));
86
87 /* Set buffer for context */
88 buf[0].BufferType = DataBuffer | LastBuffer;
89 buf[0].TheAddress = (Address)sha->ctx;
90 buf[0].Length = digestSz + WC_CAAM_CTXLEN;
91 buf[0].Transferred = 0;
92
93 arg[0] = CAAM_ALG_INIT;
94 arg[1] = digestSz + WC_CAAM_CTXLEN;
95
96 if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
97 WOLFSSL_MSG("Error with CAAM SHA init");
98 return ret;
99 }
100
101 return 0;
102 }
103
104
_ShaUpdate(wc_Sha * sha,const byte * data,word32 len,word32 digestSz,word32 type)105 static int _ShaUpdate(wc_Sha* sha, const byte* data, word32 len, word32 digestSz,
106 word32 type)
107 {
108 Buffer buf[2];
109 word32 arg[4];
110 int ret;
111 byte* local;
112
113 if (sha == NULL ||(data == NULL && len > 0)) {
114 return BAD_FUNC_ARG;
115 }
116
117 if (len == 0) return 0; /* nothing to do */
118
119 local = (byte*)sha->buffer;
120 /* check for filling out existing buffer */
121 if (sha->buffLen > 0) {
122 word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen);
123 XMEMCPY(&local[sha->buffLen], data, add);
124
125 sha->buffLen += add;
126 data += add;
127 len -= add;
128
129 if (sha->buffLen == WC_CAAM_HASH_BLOCK) {
130 /* Set buffer for context */
131 buf[0].BufferType = DataBuffer;
132 buf[0].TheAddress = (Address)sha->ctx;
133 buf[0].Length = digestSz + WC_CAAM_CTXLEN;
134 buf[0].Transferred = 0;
135
136 /* data to update with */
137 buf[1].BufferType = DataBuffer | LastBuffer;
138 buf[1].TheAddress = (Address)sha->buffer;
139 buf[1].Length = sha->buffLen;
140 buf[1].Transferred = 0;
141
142 arg[0] = CAAM_ALG_UPDATE;
143 arg[1] = digestSz + WC_CAAM_CTXLEN;
144
145 if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
146 WOLFSSL_MSG("Error with CAAM SHA update");
147 return ret;
148 }
149 sha->buffLen = 0; /* cleared out buffer */
150 }
151 }
152
153 /* check if multiple full blocks can be done */
154 if (len >= WC_CAAM_HASH_BLOCK) {
155 word32 sz = len / WC_CAAM_HASH_BLOCK;
156 sz = sz * WC_CAAM_HASH_BLOCK;
157
158 /* Set buffer for context */
159 buf[0].BufferType = DataBuffer;
160 buf[0].TheAddress = (Address)sha->ctx;
161 buf[0].Length = digestSz + WC_CAAM_CTXLEN;
162 buf[0].Transferred = 0;
163
164 /* data to update with */
165 buf[1].BufferType = DataBuffer | LastBuffer;
166 buf[1].TheAddress = (Address)data;
167 buf[1].Length = sz;
168 buf[1].Transferred = 0;
169
170 arg[0] = CAAM_ALG_UPDATE;
171 arg[1] = digestSz + WC_CAAM_CTXLEN;
172
173 if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
174 WOLFSSL_MSG("Error with CAAM SHA update");
175 return ret;
176 }
177
178 len -= sz;
179 data += sz;
180 }
181
182 /* check for left overs */
183 if (len > 0) {
184 word32 add = min(len, WC_CAAM_HASH_BLOCK - sha->buffLen);
185 XMEMCPY(&local[sha->buffLen], data, add);
186 sha->buffLen += add;
187 }
188
189 return 0;
190 }
191
192
_ShaFinal(wc_Sha * sha,byte * out,word32 digestSz,word32 type)193 static int _ShaFinal(wc_Sha* sha, byte* out, word32 digestSz,
194 word32 type)
195 {
196 Buffer buf[2];
197 word32 arg[4];
198 int ret;
199
200 if (sha == NULL || out == NULL) {
201 return BAD_FUNC_ARG;
202 }
203
204 /* Set buffer for context */
205 buf[0].BufferType = DataBuffer;
206 buf[0].TheAddress = (Address)sha->ctx;
207 buf[0].Length = digestSz + WC_CAAM_CTXLEN;
208 buf[0].Transferred = 0;
209
210 /* add any potential left overs */
211 buf[1].BufferType = DataBuffer | LastBuffer;
212 buf[1].TheAddress = (Address)sha->buffer;
213 buf[1].Length = sha->buffLen;
214 buf[1].Transferred = 0;
215
216 arg[0] = CAAM_ALG_FINAL;
217 arg[1] = digestSz + WC_CAAM_CTXLEN;
218
219 if ((ret = wc_caamAddAndWait(buf, arg, type)) != 0) {
220 WOLFSSL_MSG("Error with CAAM SHA init");
221 return ret;
222 }
223
224 return 0;
225 }
226
227 /******************************************************************************
228 MD5
229 ****************************************************************************/
230 #if !defined(NO_MD5)
wc_InitMd5_ex(wc_Md5 * sha,void * heap,int devId)231 int wc_InitMd5_ex(wc_Md5* sha, void* heap, int devId)
232 {
233 return _InitSha(sha, heap, devId, MD5_DIGEST_SIZE, CAAM_MD5);
234 }
235
236
wc_Md5Update(wc_Md5 * sha,const byte * data,word32 len)237 int wc_Md5Update(wc_Md5* sha, const byte* data, word32 len)
238 {
239 return _ShaUpdate(sha, data, len, MD5_DIGEST_SIZE, CAAM_MD5);
240 }
241
242
wc_Md5Final(wc_Md5 * sha,byte * hash)243 int wc_Md5Final(wc_Md5* sha, byte* hash)
244 {
245 int ret;
246 if ((ret = _ShaFinal(sha, hash, MD5_DIGEST_SIZE, CAAM_MD5)) != 0) {
247 return ret;
248 }
249
250 XMEMCPY(hash, (byte*)sha->ctx, MD5_DIGEST_SIZE);
251 return _InitSha(sha, NULL, 0, MD5_DIGEST_SIZE, CAAM_MD5);
252 }
253 #endif /* !NO_MD5 */
254
255
256 /******************************************************************************
257 SHA 1
258 ****************************************************************************/
259 #if !defined(NO_SHA)
wc_InitSha_ex(wc_Sha * sha,void * heap,int devId)260 int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
261 {
262 return _InitSha(sha, heap, devId, SHA_DIGEST_SIZE, CAAM_SHA);
263 }
264
265
wc_ShaUpdate(wc_Sha * sha,const byte * data,word32 len)266 int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
267 {
268 return _ShaUpdate(sha, data, len, SHA_DIGEST_SIZE, CAAM_SHA);
269 }
270
271
wc_ShaFinal(wc_Sha * sha,byte * out)272 int wc_ShaFinal(wc_Sha* sha, byte* out)
273 {
274 int ret;
275 if ((ret = _ShaFinal(sha, out, SHA_DIGEST_SIZE, CAAM_SHA)) != 0) {
276 return ret;
277 }
278
279 XMEMCPY(out, (byte*)sha->ctx, SHA_DIGEST_SIZE);
280 return _InitSha(sha, NULL, 0, SHA_DIGEST_SIZE, CAAM_SHA);
281 }
282 #endif /* !NO_SHA */
283
284
285 /******************************************************************************
286 SHA 224
287 ****************************************************************************/
288 #ifdef WOLFSSL_SHA224
wc_InitSha224_ex(wc_Sha224 * sha,void * heap,int devId)289 int wc_InitSha224_ex(wc_Sha224* sha, void* heap, int devId)
290 {
291 return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA224);
292 }
293
294
wc_Sha224Update(wc_Sha224 * sha,const byte * data,word32 len)295 int wc_Sha224Update(wc_Sha224* sha, const byte* data, word32 len)
296 {
297 return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA224);
298 }
299
300
wc_Sha224Final(wc_Sha224 * sha,byte * out)301 int wc_Sha224Final(wc_Sha224* sha, byte* out)
302 {
303 int ret;
304 if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA224)) != 0) {
305 return ret;
306 }
307
308 XMEMCPY(out, (byte*)sha->ctx, SHA224_DIGEST_SIZE);
309 return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA224);
310 }
311 #endif /* WOLFSSL_SHA224 */
312
313
314 /******************************************************************************
315 SHA 256
316 ****************************************************************************/
317 #if !defined(NO_SHA256)
wc_InitSha256_ex(wc_Sha256 * sha,void * heap,int devId)318 int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId)
319 {
320 return _InitSha(sha, heap, devId, SHA256_DIGEST_SIZE, CAAM_SHA256);
321 }
322
323
wc_Sha256Update(wc_Sha256 * sha,const byte * data,word32 len)324 int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len)
325 {
326 return _ShaUpdate(sha, data, len, SHA256_DIGEST_SIZE, CAAM_SHA256);
327 }
328
329
wc_Sha256Final(wc_Sha256 * sha,byte * out)330 int wc_Sha256Final(wc_Sha256* sha, byte* out)
331 {
332 int ret;
333 if ((ret = _ShaFinal(sha, out, SHA256_DIGEST_SIZE, CAAM_SHA256)) != 0) {
334 return ret;
335 }
336
337 XMEMCPY(out, (byte*)sha->ctx, SHA256_DIGEST_SIZE);
338 return _InitSha(sha, NULL, 0, SHA256_DIGEST_SIZE, CAAM_SHA256);
339 }
340 #endif /* !NO_SHA256 */
341
342
343 /******************************************************************************
344 SHA 384
345 ****************************************************************************/
346 #ifdef WOLFSSL_SHA384
wc_InitSha384_ex(wc_Sha384 * sha,void * heap,int devId)347 int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId)
348 {
349 return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA384);
350 }
351
352
wc_Sha384Update(wc_Sha384 * sha,const byte * data,word32 len)353 int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len)
354 {
355 return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA384);
356 }
357
358
wc_Sha384Final(wc_Sha384 * sha,byte * out)359 int wc_Sha384Final(wc_Sha384* sha, byte* out)
360 {
361 int ret;
362 if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA384)) != 0) {
363 return ret;
364 }
365
366 XMEMCPY(out, (byte*)sha->ctx, SHA384_DIGEST_SIZE);
367 return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA384);
368 }
369 #endif /* WOLFSSL_SHA384 */
370
371
372
373 /******************************************************************************
374 SHA 512
375 ****************************************************************************/
376 #ifdef WOLFSSL_SHA512
wc_InitSha512_ex(wc_Sha512 * sha,void * heap,int devId)377 int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId)
378 {
379 return _InitSha(sha, heap, devId, SHA512_DIGEST_SIZE, CAAM_SHA512);
380 }
381
382
wc_Sha512Update(wc_Sha512 * sha,const byte * data,word32 len)383 int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len)
384 {
385 return _ShaUpdate(sha, data, len, SHA512_DIGEST_SIZE, CAAM_SHA512);
386 }
387
388
wc_Sha512Final(wc_Sha512 * sha,byte * out)389 int wc_Sha512Final(wc_Sha512* sha, byte* out)
390 {
391 int ret;
392 if ((ret = _ShaFinal(sha, out, SHA512_DIGEST_SIZE, CAAM_SHA512)) != 0) {
393 return ret;
394 }
395
396 XMEMCPY(out, (byte*)sha->ctx, SHA512_DIGEST_SIZE);
397 return _InitSha(sha, NULL, 0, SHA512_DIGEST_SIZE, CAAM_SHA512);
398 }
399 #endif /* WOLFSSL_SHA512 */
400
401 #endif /* WOLFSSL_IMX6_CAAM && !NO_IMX6_CAAM_HASH */
402