1 /* pic32mz-crypt.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 
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26 
27 #include <wolfssl/wolfcrypt/settings.h>
28 
29 #ifdef WOLFSSL_MICROCHIP_PIC32MZ
30 
31 #ifdef NO_INLINE
32     #include <wolfssl/wolfcrypt/misc.h>
33 #else
34     #define WOLFSSL_MISC_INCLUDED
35     #include <wolfcrypt/src/misc.c>
36 #endif
37 
38 #include <wolfssl/wolfcrypt/logging.h>
39 #include <wolfssl/wolfcrypt/error-crypt.h>
40 
41 #include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
42 
43 #ifdef WOLFSSL_PIC32MZ_CRYPT
44 #include <wolfssl/wolfcrypt/aes.h>
45 #include <wolfssl/wolfcrypt/des3.h>
46 #endif
47 
48 #ifdef WOLFSSL_PIC32MZ_HASH
49 #include <wolfssl/wolfcrypt/md5.h>
50 #include <wolfssl/wolfcrypt/sha.h>
51 #include <wolfssl/wolfcrypt/sha256.h>
52 #endif
53 
54 
55 #if defined(WOLFSSL_PIC32MZ_CRYPT) || defined(WOLFSSL_PIC32MZ_HASH)
56 
Pic32GetBlockSize(int algo)57 static int Pic32GetBlockSize(int algo)
58 {
59     switch (algo) {
60         case PIC32_ALGO_HMAC1:
61             return PIC32_BLOCKSIZE_HMAC;
62         case PIC32_ALGO_SHA256:
63             return PIC32_BLOCKSIZE_SHA256;
64         case PIC32_ALGO_SHA1:
65             return PIC32_BLOCKSIZE_SHA1;
66         case PIC32_ALGO_MD5:
67             return PIC32_BLOCKSIZE_MD5;
68         case PIC32_ALGO_AES:
69             return PIC32_BLOCKSIZE_AES;
70         case PIC32_ALGO_TDES:
71             return PIC32_BLOCKSIZE_TDES;
72         case PIC32_ALGO_DES:
73             return PIC32_BLOCKSIZE_DES;
74     }
75     return 0;
76 }
77 
Pic32Crypto(const byte * pIn,int inLen,word32 * pOut,int outLen,int dir,int algo,int cryptoalgo,word32 * key,int keyLen,word32 * iv,int ivLen)78 static int Pic32Crypto(const byte* pIn, int inLen, word32* pOut, int outLen,
79     int dir, int algo, int cryptoalgo,
80 
81     /* For DES/AES only */
82     word32* key, int keyLen, word32* iv, int ivLen)
83 {
84     int ret = 0;
85     int blockSize = Pic32GetBlockSize(algo);
86     volatile bufferDescriptor bd __attribute__((aligned (8)));
87     securityAssociation sa __attribute__((aligned (8)));
88     securityAssociation *sa_p;
89     bufferDescriptor *bd_p;
90     byte *in_p;
91     byte *out_p;
92     word32* dst;
93     word32 padRemain;
94     int timeout = 0xFFFFFF;
95     word32* in = (word32*)pIn;
96     word32* out = pOut;
97     int isDynamic = 0;
98 
99     /* check args */
100     if (in == NULL || inLen <= 0 || out == NULL || blockSize == 0) {
101         return BAD_FUNC_ARG;
102     }
103 
104     /* check pointer alignment - must be word aligned */
105     if (((size_t)in % sizeof(word32)) || ((size_t)out % sizeof(word32))) {
106         /* dynamically allocate aligned pointers */
107         isDynamic = 1;
108         in = (word32*)XMALLOC(inLen, NULL, DYNAMIC_TYPE_AES_BUFFER);
109         if (in == NULL)
110             return MEMORY_E;
111         if ((word32*)pIn == pOut) /* inline */
112             out = (word32*)in;
113         else {
114             out = (word32*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_AES_BUFFER);
115             if (out == NULL) {
116                 XFREE(in, NULL, DYNAMIC_TYPE_AES_BUFFER);
117                 return MEMORY_E;
118             }
119         }
120         XMEMCPY(in, pIn, inLen);
121     }
122 
123     /* get uncached address */
124     sa_p = KVA0_TO_KVA1(&sa);
125     bd_p = KVA0_TO_KVA1(&bd);
126     out_p= KVA0_TO_KVA1(out);
127     in_p = KVA0_TO_KVA1(in);
128 
129     /* Sync cache if in physical memory (not flash) */
130     if (PIC32MZ_IF_RAM(in_p)) {
131         XMEMCPY(in_p, in, inLen);
132     }
133 
134     /* Set up the Security Association */
135     XMEMSET(sa_p, 0, sizeof(sa));
136     sa_p->SA_CTRL.ALGO = algo;
137     sa_p->SA_CTRL.ENCTYPE = dir;
138     sa_p->SA_CTRL.FB = 1; /* first block */
139     sa_p->SA_CTRL.LNC = 1; /* Load new set of keys */
140     if (key) {
141         /* cipher */
142         sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo;
143 
144         switch (keyLen) {
145             case 32:
146                 sa_p->SA_CTRL.KEYSIZE = PIC32_KEYSIZE_256;
147                 break;
148             case 24:
149             case 8: /* DES */
150                 sa_p->SA_CTRL.KEYSIZE = PIC32_KEYSIZE_192;
151                 break;
152             case 16:
153                 sa_p->SA_CTRL.KEYSIZE = PIC32_KEYSIZE_128;
154                 break;
155         }
156 
157         dst = (word32*)KVA0_TO_KVA1(sa.SA_ENCKEY +
158             (sizeof(sa.SA_ENCKEY)/sizeof(word32)) - (keyLen/sizeof(word32)));
159         ByteReverseWords(dst, key, keyLen);
160 
161         if (iv && ivLen > 0) {
162             sa_p->SA_CTRL.LOADIV = 1;
163             dst = (word32*)KVA0_TO_KVA1(sa.SA_ENCIV +
164                 (sizeof(sa.SA_ENCIV)/sizeof(word32)) - (ivLen/sizeof(word32)));
165             ByteReverseWords(dst, iv, ivLen);
166         }
167     }
168     else {
169         /* hashing */
170         sa_p->SA_CTRL.LOADIV = 1;
171         sa_p->SA_CTRL.IRFLAG = 0; /* immediate result for hashing */
172 
173         dst = (word32*)KVA0_TO_KVA1(sa.SA_AUTHIV +
174             (sizeof(sa.SA_AUTHIV)/sizeof(word32)) - (outLen/sizeof(word32)));
175         ByteReverseWords(dst, out, outLen);
176     }
177 
178     /* Set up the Buffer Descriptor */
179     XMEMSET(bd_p, 0, sizeof(bd));
180     bd_p->BD_CTRL.BUFLEN = inLen;
181     padRemain = (inLen % 4); /* make sure buffer is 4-byte multiple */
182     if (padRemain != 0) {
183         bd_p->BD_CTRL.BUFLEN += (4 - padRemain);
184     }
185     bd_p->BD_CTRL.SA_FETCH_EN = 1; /* Fetch the security association */
186     bd_p->BD_CTRL.PKT_INT_EN = 1;  /* enable interrupt */
187     bd_p->BD_CTRL.LAST_BD = 1;     /* last buffer desc in chain */
188     bd_p->BD_CTRL.LIFM = 1;        /* last in frame */
189     bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa);
190     bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in);
191     if (key) {
192         /* cipher */
193         if (in != out)
194             XMEMSET(out_p, 0, outLen); /* clear output buffer */
195         bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out);
196     }
197     else {
198         /* hashing */
199         /* digest result returned in UPDPTR */
200         bd_p->UPDPTR = (unsigned int)KVA_TO_PA(out);
201     }
202     bd_p->NXTPTR = (unsigned int)KVA_TO_PA(&bd);
203     bd_p->MSGLEN = inLen;          /* actual message size */
204     bd_p->BD_CTRL.DESC_EN = 1;     /* enable this descriptor */
205 
206     /* begin access to hardware */
207     ret = wolfSSL_CryptHwMutexLock();
208     if (ret == 0) {
209         /* Software Reset the Crypto Engine */
210         CECON = 1 << 6;
211         while (CECON);
212 
213         /* Clear the interrupt flags */
214         CEINTSRC = 0xF;
215 
216         /* Run the engine */
217         CEBDPADDR = (unsigned int)KVA_TO_PA(&bd);
218         CEINTEN = 0x07; /* enable DMA Packet Completion Interrupt */
219 
220         /* input swap, enable BD fetch and start DMA */
221     #if PIC32_NO_OUT_SWAP
222         CECON = 0x25;
223     #else
224         CECON = 0xa5; /* bit 7 = enable out swap */
225     #endif
226 
227         /* wait for operation to complete */
228         while (CEINTSRCbits.PKTIF == 0 && --timeout > 0) {};
229 
230         /* Clear the interrupt flags */
231         CEINTSRC = 0xF;
232 
233         /* check for errors */
234         if (CESTATbits.ERROP || timeout <= 0) {
235         #if 0
236             printf("PIC32 Crypto: ERROP %x, ERRPHASE %x, TIMEOUT %s\n",
237                 CESTATbits.ERROP, CESTATbits.ERRPHASE, timeout <= 0 ? "yes" : "no");
238         #endif
239             ret = ASYNC_OP_E;
240         }
241 
242         wolfSSL_CryptHwMutexUnLock();
243 
244         /* copy result to output */
245     #if PIC32_NO_OUT_SWAP
246         /* swap bytes */
247         ByteReverseWords(out, (word32*)out_p, outLen);
248     #elif defined(_SYS_DEVCON_LOCAL_H)
249         /* sync cache */
250         SYS_DEVCON_DataCacheInvalidate((word32)out, outLen);
251     #else
252         XMEMCPY(out, out_p, outLen);
253     #endif
254     }
255 
256     /* handle unaligned */
257     if (isDynamic) {
258         /* return result */
259         XMEMCPY(pOut, out, outLen);
260 
261         /* free dynamic buffers */
262         XFREE(in, NULL, DYNAMIC_TYPE_AES_BUFFER);
263         if ((word32*)pIn != pOut)
264             XFREE(out, NULL, DYNAMIC_TYPE_AES_BUFFER);
265     }
266 
267     return ret;
268 }
269 #endif /* WOLFSSL_PIC32MZ_CRYPT || WOLFSSL_PIC32MZ_HASH */
270 
271 
272 #ifdef WOLFSSL_PIC32MZ_HASH
273 
274 #ifdef WOLFSSL_PIC32MZ_LARGE_HASH
275 
276 /* tunable large hash block size */
277 #ifndef PIC32_BLOCK_SIZE
278     #define PIC32_BLOCK_SIZE 256
279 #endif
280 
281 #define PIC32MZ_MIN_BLOCK    64
282 #define PIC32MZ_MAX_BLOCK    (32*1024)
283 
284 #ifndef PIC32MZ_MAX_BD
285     #define PIC32MZ_MAX_BD   2
286 #endif
287 
288 #if PIC32_BLOCK_SIZE < PIC32MZ_MIN_BLOCK
289     #error Encryption block size must be at least 64 bytes.
290 #endif
291 
292 /* Crypt Engine descriptor */
293 typedef struct {
294     int currBd;
295     int err;
296     unsigned int msgSize;
297     uint32_t processed;
298     uint32_t dbPtr;
299     int engine_ready;
300     volatile bufferDescriptor   bd[PIC32MZ_MAX_BD] __attribute__((aligned (8)));
301     securityAssociation         sa                 __attribute__((aligned (8)));
302 } pic32mz_desc;
303 
304 static pic32mz_desc gLHDesc __attribute__((coherent));
305 static uint8_t gLHDataBuf[PIC32MZ_MAX_BD][PIC32_BLOCK_SIZE] __attribute__((aligned (4), coherent));
306 
reset_engine(int algo)307 static void reset_engine(int algo)
308 {
309     int i;
310 
311     wolfSSL_CryptHwMutexLock();
312 
313     /* Software reset */
314     CECON = 1 << 6;
315     while (CECON);
316 
317     /* Clear the interrupt flags */
318     CEINTSRC = 0xF;
319 
320     /* Make sure everything is clear first before we setup */
321     XMEMSET(&gLHDesc, 0, sizeof(pic32mz_desc));
322 
323     /* Set up the Security Association */
324     gLHDesc.sa.SA_CTRL.ALGO = algo;
325     gLHDesc.sa.SA_CTRL.LNC = 1;
326     gLHDesc.sa.SA_CTRL.FB = 1;
327     gLHDesc.sa.SA_CTRL.ENCTYPE = 1;
328     gLHDesc.sa.SA_CTRL.LOADIV = 1;
329 
330     /* Set up the Buffer Descriptor */
331     gLHDesc.err = 0;
332     for (i = 0; i < PIC32MZ_MAX_BD; i++) {
333         XMEMSET((void *)&gLHDesc.bd[i], 0, sizeof(gLHDesc.bd[i]));
334         gLHDesc.bd[i].BD_CTRL.LAST_BD = 1;
335         gLHDesc.bd[i].BD_CTRL.LIFM = 1;
336         gLHDesc.bd[i].BD_CTRL.PKT_INT_EN = 1;
337         gLHDesc.bd[i].SA_ADDR = KVA_TO_PA(&gLHDesc.sa);
338         gLHDesc.bd[i].SRCADDR = KVA_TO_PA(&gLHDataBuf[i]);
339         if (PIC32MZ_MAX_BD > i+1)
340             gLHDesc.bd[i].NXTPTR = KVA_TO_PA(&gLHDesc.bd[i+1]);
341         else
342             gLHDesc.bd[i].NXTPTR = KVA_TO_PA(&gLHDesc.bd[0]);
343         XMEMSET((void *)&gLHDataBuf[i], 0, PIC32_BLOCK_SIZE);
344     }
345     gLHDesc.bd[0].BD_CTRL.SA_FETCH_EN = 1; /* Fetch the security association on the first BD */
346     gLHDesc.dbPtr = 0;
347     gLHDesc.currBd = 0;
348     gLHDesc.msgSize = 0;
349     gLHDesc.processed = 0;
350     CEBDPADDR = KVA_TO_PA(&(gLHDesc.bd[0]));
351 
352     CEPOLLCON = 10;
353 
354 #if PIC32_NO_OUT_SWAP
355     CECON = 0x27;
356 #else
357     CECON = 0xa7;
358 #endif
359 }
360 
update_engine(const byte * input,word32 len,word32 * hash)361 static void update_engine(const byte *input, word32 len, word32 *hash)
362 {
363     int total;
364 
365     gLHDesc.bd[gLHDesc.currBd].UPDPTR = KVA_TO_PA(hash);
366 
367     /* Add the data to the current buffer. If the buffer fills, start processing it
368        and fill the next one. */
369     while (len) {
370         /* If we've been given the message size, we can process along the
371            way.
372            Enable the current buffer descriptor if it is full. */
373         if (gLHDesc.dbPtr >= PIC32_BLOCK_SIZE) {
374             /* Wrap up the buffer descriptor and enable it so the engine can process */
375             gLHDesc.bd[gLHDesc.currBd].MSGLEN = gLHDesc.msgSize;
376             gLHDesc.bd[gLHDesc.currBd].BD_CTRL.BUFLEN = gLHDesc.dbPtr;
377             gLHDesc.bd[gLHDesc.currBd].BD_CTRL.LAST_BD = 0;
378             gLHDesc.bd[gLHDesc.currBd].BD_CTRL.LIFM = 0;
379             gLHDesc.bd[gLHDesc.currBd].BD_CTRL.DESC_EN = 1;
380             /* Move to the next buffer descriptor, or wrap around. */
381             gLHDesc.currBd++;
382             if (gLHDesc.currBd >= PIC32MZ_MAX_BD)
383                 gLHDesc.currBd = 0;
384             /* Wait until the engine has processed the new BD. */
385             while (gLHDesc.bd[gLHDesc.currBd].BD_CTRL.DESC_EN);
386             gLHDesc.bd[gLHDesc.currBd].UPDPTR = KVA_TO_PA(hash);
387             gLHDesc.dbPtr = 0;
388         }
389         if (!PIC32MZ_IF_RAM(input)) {
390             /* If we're inputting from flash, let the BD have
391                the address and max the buffer size */
392             gLHDesc.bd[gLHDesc.currBd].SRCADDR = KVA_TO_PA(input);
393             total = (len > PIC32MZ_MAX_BLOCK ? PIC32MZ_MAX_BLOCK : len);
394             gLHDesc.dbPtr = total;
395             len -= total;
396             input += total;
397         }
398         else {
399             if (len > PIC32_BLOCK_SIZE - gLHDesc.dbPtr) {
400                 /* We have more data than can be put in the buffer. Fill what we can.*/
401                 total = PIC32_BLOCK_SIZE - gLHDesc.dbPtr;
402                 XMEMCPY(&gLHDataBuf[gLHDesc.currBd][gLHDesc.dbPtr], input, total);
403                 len -= total;
404                 gLHDesc.dbPtr = PIC32_BLOCK_SIZE;
405                 input += total;
406             }
407             else {
408                 /* Fill up what we have, but don't turn on the engine.*/
409                 XMEMCPY(&gLHDataBuf[gLHDesc.currBd][gLHDesc.dbPtr], input, len);
410                 gLHDesc.dbPtr += len;
411                 len = 0;
412             }
413         }
414     }
415 }
416 
start_engine(void)417 static void start_engine(void)
418 {
419     /* Wrap up the last buffer descriptor and enable it */
420     int bufferLen;
421 
422     bufferLen = gLHDesc.dbPtr;
423     if (bufferLen % 4)
424         bufferLen = (bufferLen + 4) - (bufferLen % 4);
425     /* initialize the MSGLEN on engine startup to avoid infinite loop when
426      * length is less than 257 (size of PIC32_BLOCK_SIZE) */
427     gLHDesc.bd[gLHDesc.currBd].MSGLEN = gLHDesc.msgSize;
428     gLHDesc.bd[gLHDesc.currBd].BD_CTRL.BUFLEN = bufferLen;
429     gLHDesc.bd[gLHDesc.currBd].BD_CTRL.LAST_BD = 1;
430     gLHDesc.bd[gLHDesc.currBd].BD_CTRL.LIFM = 1;
431     gLHDesc.bd[gLHDesc.currBd].BD_CTRL.DESC_EN = 1;
432 }
433 
wait_engine(char * hash,int hash_sz)434 void wait_engine(char *hash, int hash_sz)
435 {
436     int i;
437     unsigned int engineRunning;
438 
439     do {
440         engineRunning = 0;
441         for (i = 0; i < PIC32MZ_MAX_BD; i++) {
442             engineRunning = engineRunning || gLHDesc.bd[i].BD_CTRL.DESC_EN;
443         }
444     } while (engineRunning);
445 
446 #if PIC32_NO_OUT_SWAP
447     /* swap bytes */
448     ByteReverseWords(hash, KVA0_TO_KVA1(hash), hash_sz);
449 #else
450     /* copy output - hardware already swapped */
451     XMEMCPY(hash, KVA0_TO_KVA1(hash), hash_sz);
452 #endif
453 
454     wolfSSL_CryptHwMutexUnLock();
455 }
456 
457 #endif /* WOLFSSL_PIC32MZ_LARGE_HASH */
458 
wc_Pic32Hash(const byte * in,int inLen,word32 * out,int outLen,int algo)459 int wc_Pic32Hash(const byte* in, int inLen, word32* out, int outLen, int algo)
460 {
461     return Pic32Crypto(in, inLen, out, outLen, PIC32_ENCRYPTION, algo, 0,
462         NULL, 0, NULL, 0);
463 }
464 
wc_Pic32HashCopy(hashUpdCache * src,hashUpdCache * dst)465 int wc_Pic32HashCopy(hashUpdCache* src, hashUpdCache* dst)
466 {
467     /* mark destination as copy, so cache->buf is not free'd */
468     if (dst) {
469         dst->isCopy = 1;
470     }
471     return 0;
472 }
473 
wc_Pic32HashUpdate(hashUpdCache * cache,byte * stdBuf,int stdBufLen,word32 * digest,int digestSz,const byte * data,int len,int algo,void * heap)474 static int wc_Pic32HashUpdate(hashUpdCache* cache, byte* stdBuf, int stdBufLen,
475     word32* digest, int digestSz, const byte* data, int len, int algo, void* heap)
476 {
477     int ret = 0;
478     word32 newLenUpd, newLenPad, padRemain;
479     byte* newBuf;
480     int isNewBuf = 0;
481 
482 #ifdef WOLFSSL_PIC32MZ_LARGE_HASH
483     /* if final length is set then pass straight to hardware */
484     if (cache->finalLen) {
485         if (cache->bufLen == 0) {
486             reset_engine(algo);
487             gLHDesc.msgSize = cache->finalLen;
488         }
489         update_engine(data, len, digest);
490         cache->bufLen += len; /* track progress for blockType */
491         return 0;
492     }
493 #endif
494 
495     /* cache updates */
496     /* calculate new len */
497     newLenUpd = cache->updLen + len;
498 
499     /* calculate padded len - pad buffer at 64-bytes for hardware */
500     newLenPad = newLenUpd;
501     padRemain = (newLenUpd % PIC32_BLOCKSIZE_HASH);
502     if (padRemain != 0) {
503         newLenPad += (PIC32_BLOCKSIZE_HASH - padRemain);
504     }
505 
506     /* determine buffer source */
507     if (newLenPad <= stdBufLen) {
508         /* use standard buffer */
509         newBuf = stdBuf;
510     }
511     else if (newLenPad > cache->bufLen) {
512         /* alloc buffer */
513         newBuf = (byte*)XMALLOC(newLenPad, heap, DYNAMIC_TYPE_HASH_TMP);
514         if (newBuf == NULL) {
515             if (cache->buf != stdBuf && !cache->isCopy) {
516                 XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP);
517                 cache->buf = NULL;
518                 cache->updLen = cache->bufLen = 0;
519             }
520             return MEMORY_E;
521         }
522         isNewBuf = 1;
523         cache->isCopy = 0; /* no longer using copy buffer */
524     }
525     else {
526         /* use existing buffer */
527         newBuf = cache->buf;
528     }
529     if (cache->buf && cache->updLen > 0) {
530         XMEMCPY(newBuf, cache->buf, cache->updLen);
531         if (isNewBuf && cache->buf != stdBuf) {
532             XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP);
533             cache->buf = NULL;
534         }
535     }
536     XMEMCPY(newBuf + cache->updLen, data, len);
537 
538     cache->buf = newBuf;
539     cache->updLen = newLenUpd;
540     cache->bufLen = newLenPad;
541 
542     return ret;
543 }
544 
wc_Pic32HashFinal(hashUpdCache * cache,byte * stdBuf,word32 * digest,byte * hash,int digestSz,int algo,void * heap)545 static int wc_Pic32HashFinal(hashUpdCache* cache, byte* stdBuf,
546     word32* digest, byte* hash, int digestSz, int algo, void* heap)
547 {
548     int ret = 0;
549 
550     /* if room add the pad */
551     if (cache->buf && cache->updLen < cache->bufLen) {
552         cache->buf[cache->updLen] = 0x80;
553     }
554 
555 #ifdef WOLFSSL_PIC32MZ_LARGE_HASH
556     if (cache->finalLen) {
557         /* Only submit to hardware if update data provided matches expected */
558         if (cache->bufLen == cache->finalLen) {
559             start_engine();
560             wait_engine((char*)digest, digestSz);
561             XMEMCPY(hash, digest, digestSz);
562         }
563         else {
564             wolfSSL_CryptHwMutexUnLock();
565             ret = BUFFER_E;
566         }
567         cache->finalLen = 0;
568     }
569     else
570 #endif
571     {
572         if (cache->updLen == 0) {
573             /* handle empty input */
574             switch (algo) {
575                 case PIC32_ALGO_SHA256: {
576                     const char* sha256EmptyHash =
577                         "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9"
578                         "\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52"
579                         "\xb8\x55";
580                     XMEMCPY(hash, sha256EmptyHash, digestSz);
581                     break;
582                 }
583                 case PIC32_ALGO_SHA1: {
584                     const char* shaEmptyHash =
585                         "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18"
586                         "\x90\xaf\xd8\x07\x09";
587                     XMEMCPY(hash, shaEmptyHash, digestSz);
588                     break;
589                 }
590                 case PIC32_ALGO_MD5: {
591                     const char* md5EmptyHash =
592                         "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42"
593                         "\x7e";
594                     XMEMCPY(hash, md5EmptyHash, digestSz);
595                     break;
596                 }
597             } /* switch */
598         }
599         else {
600             ret = wc_Pic32Hash(cache->buf, cache->updLen, digest, digestSz, algo);
601             if (ret == 0) {
602                 XMEMCPY(hash, digest, digestSz);
603             }
604         }
605 
606         if (cache->buf && cache->buf != stdBuf && !cache->isCopy) {
607             XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP);
608             cache->buf = NULL;
609         }
610     }
611 
612     cache->buf = NULL;
613     cache->bufLen = cache->updLen = 0;
614 
615     return ret;
616 }
617 
wc_Pic32HashFree(hashUpdCache * cache,void * heap)618 static void wc_Pic32HashFree(hashUpdCache* cache, void* heap)
619 {
620     if (cache && cache->buf && !cache->isCopy) {
621         XFREE(cache->buf, heap, DYNAMIC_TYPE_HASH_TMP);
622         cache->buf = NULL;
623     }
624 }
625 
626 /* API's for compatibility with Harmony wrappers - not used */
627 #ifndef NO_MD5
wc_InitMd5_ex(wc_Md5 * md5,void * heap,int devId)628     int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId)
629     {
630         if (md5 == NULL)
631             return BAD_FUNC_ARG;
632 
633         XMEMSET(md5, 0, sizeof(wc_Md5));
634         md5->heap = heap;
635         (void)devId;
636         return 0;
637     }
wc_Md5Update(wc_Md5 * md5,const byte * data,word32 len)638     int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
639     {
640         if (md5 == NULL || (data == NULL && len > 0))
641             return BAD_FUNC_ARG;
642         return wc_Pic32HashUpdate(&md5->cache, (byte*)md5->buffer,
643             sizeof(md5->buffer), md5->digest, MD5_DIGEST_SIZE,
644             data, len, PIC32_ALGO_MD5, md5->heap);
645     }
wc_Md5Final(wc_Md5 * md5,byte * hash)646     int wc_Md5Final(wc_Md5* md5, byte* hash)
647     {
648         int ret;
649 
650         if (md5 == NULL || hash == NULL)
651             return BAD_FUNC_ARG;
652 
653         ret = wc_Pic32HashFinal(&md5->cache, (byte*)md5->buffer,
654             md5->digest, hash, MD5_DIGEST_SIZE,
655             PIC32_ALGO_MD5, md5->heap);
656 
657         wc_InitMd5_ex(md5, md5->heap, INVALID_DEVID);  /* reset state */
658 
659         return ret;
660     }
wc_Md5SizeSet(wc_Md5 * md5,word32 len)661     void wc_Md5SizeSet(wc_Md5* md5, word32 len)
662     {
663         if (md5) {
664         #ifdef WOLFSSL_PIC32MZ_LARGE_HASH
665             md5->cache.finalLen = len;
666         #else
667             (void)len;
668         #endif
669         }
670     }
wc_Md5Pic32Free(wc_Md5 * md5)671     void wc_Md5Pic32Free(wc_Md5* md5)
672     {
673         if (md5) {
674             wc_Pic32HashFree(&md5->cache, md5->heap);
675         }
676     }
677 #endif /* !NO_MD5 */
678 #ifndef NO_SHA
wc_InitSha_ex(wc_Sha * sha,void * heap,int devId)679     int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
680     {
681         if (sha == NULL)
682             return BAD_FUNC_ARG;
683 
684         XMEMSET(sha, 0, sizeof(wc_Sha));
685         sha->heap = heap;
686         (void)devId;
687         return 0;
688     }
wc_ShaUpdate(wc_Sha * sha,const byte * data,word32 len)689     int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
690     {
691         if (sha == NULL || (data == NULL && len > 0))
692             return BAD_FUNC_ARG;
693         return wc_Pic32HashUpdate(&sha->cache, (byte*)sha->buffer,
694             sizeof(sha->buffer), sha->digest, SHA_DIGEST_SIZE,
695             data, len, PIC32_ALGO_SHA1, sha->heap);
696     }
wc_ShaFinal(wc_Sha * sha,byte * hash)697     int wc_ShaFinal(wc_Sha* sha, byte* hash)
698     {
699         int ret;
700 
701         if (sha == NULL || hash == NULL)
702             return BAD_FUNC_ARG;
703 
704         ret = wc_Pic32HashFinal(&sha->cache, (byte*)sha->buffer,
705             sha->digest, hash, SHA_DIGEST_SIZE,
706             PIC32_ALGO_SHA1, sha->heap);
707 
708         wc_InitSha_ex(sha, sha->heap, INVALID_DEVID);  /* reset state */
709 
710         return ret;
711     }
wc_ShaSizeSet(wc_Sha * sha,word32 len)712     void wc_ShaSizeSet(wc_Sha* sha, word32 len)
713     {
714         if (sha) {
715         #ifdef WOLFSSL_PIC32MZ_LARGE_HASH
716             sha->cache.finalLen = len;
717         #else
718             (void)len;
719         #endif
720         }
721     }
wc_ShaPic32Free(wc_Sha * sha)722     void wc_ShaPic32Free(wc_Sha* sha)
723     {
724         if (sha) {
725             wc_Pic32HashFree(&sha->cache, sha->heap);
726         }
727     }
728 #endif /* !NO_SHA */
729 #ifndef NO_SHA256
wc_InitSha256_ex(wc_Sha256 * sha256,void * heap,int devId)730     int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
731     {
732         if (sha256 == NULL)
733             return BAD_FUNC_ARG;
734 
735         XMEMSET(sha256, 0, sizeof(wc_Sha256));
736         sha256->heap = heap;
737         (void)devId;
738         return 0;
739     }
wc_Sha256Update(wc_Sha256 * sha256,const byte * data,word32 len)740     int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
741     {
742         if (sha256 == NULL || (data == NULL && len > 0))
743             return BAD_FUNC_ARG;
744         return wc_Pic32HashUpdate(&sha256->cache, (byte*)sha256->buffer,
745             sizeof(sha256->buffer), sha256->digest, SHA256_DIGEST_SIZE,
746             data, len, PIC32_ALGO_SHA256, sha256->heap);
747     }
wc_Sha256Final(wc_Sha256 * sha256,byte * hash)748     int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
749     {
750         int ret;
751 
752         if (sha256 == NULL || hash == NULL)
753             return BAD_FUNC_ARG;
754 
755         ret = wc_Pic32HashFinal(&sha256->cache, (byte*)sha256->buffer,
756             sha256->digest, hash, SHA256_DIGEST_SIZE,
757             PIC32_ALGO_SHA256, sha256->heap);
758 
759         wc_InitSha256_ex(sha256, sha256->heap, INVALID_DEVID);  /* reset state */
760 
761         return ret;
762     }
wc_Sha256SizeSet(wc_Sha256 * sha256,word32 len)763     void wc_Sha256SizeSet(wc_Sha256* sha256, word32 len)
764     {
765         if (sha256) {
766         #ifdef WOLFSSL_PIC32MZ_LARGE_HASH
767             sha256->cache.finalLen = len;
768         #else
769             (void)len;
770         #endif
771         }
772     }
wc_Sha256Pic32Free(wc_Sha256 * sha256)773     void wc_Sha256Pic32Free(wc_Sha256* sha256)
774     {
775         if (sha256) {
776             wc_Pic32HashFree(&sha256->cache, sha256->heap);
777         }
778     }
779 #endif /* !NO_SHA256 */
780 #endif /* WOLFSSL_PIC32MZ_HASH */
781 
782 
783 #ifdef WOLFSSL_PIC32MZ_CRYPT
784 #if !defined(NO_AES)
wc_Pic32AesCrypt(word32 * key,int keyLen,word32 * iv,int ivLen,byte * out,const byte * in,word32 sz,int dir,int algo,int cryptoalgo)785     int wc_Pic32AesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen,
786         byte* out, const byte* in, word32 sz,
787         int dir, int algo, int cryptoalgo)
788     {
789         return Pic32Crypto(in, sz, (word32*)out, sz, dir, algo, cryptoalgo,
790             key, keyLen, iv, ivLen);
791     }
792 #endif /* !NO_AES */
793 
794 #ifndef NO_DES3
wc_Pic32DesCrypt(word32 * key,int keyLen,word32 * iv,int ivLen,byte * out,const byte * in,word32 sz,int dir,int algo,int cryptoalgo)795     int wc_Pic32DesCrypt(word32 *key, int keyLen, word32 *iv, int ivLen,
796         byte* out, const byte* in, word32 sz,
797         int dir, int algo, int cryptoalgo)
798     {
799         return Pic32Crypto(in, sz, (word32*)out, sz, dir, algo, cryptoalgo,
800             key, keyLen, iv, ivLen);
801     }
802 #endif /* !NO_DES3 */
803 #endif /* WOLFSSL_PIC32MZ_CRYPT */
804 
805 #endif /* WOLFSSL_MICROCHIP_PIC32MZ */
806