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