1 /***************************************************************************//**
2  * @file
3  * @brief Cryptography accelerator peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 #include "em_device.h"
31 
32 #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
33 
34 #include "em_crypto.h"
35 #include "sl_assert.h"
36 #include <stddef.h>
37 #include <string.h>
38 
39 /***************************************************************************//**
40  * @addtogroup crypto
41  * @{
42  ******************************************************************************/
43 
44 /*******************************************************************************
45  *******************************   DEFINES   ***********************************
46  ******************************************************************************/
47 
48 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
49 
50 #define CRYPTO_INSTRUCTIONS_PER_REG              (4UL)
51 #define CRYPTO_INSTRUCTIONS_MAX                  (12UL)
52 #define CRYPTO_INSTRUCTION_REGS                  (CRYPTO_INSTRUCTIONS_MAX / CRYPTO_INSTRUCTIONS_PER_REG)
53 
54 #define CRYPTO_SHA1_BLOCK_SIZE_IN_BITS           (512UL)
55 #define CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES          (CRYPTO_SHA1_BLOCK_SIZE_IN_BITS / 8UL)
56 #define CRYPTO_SHA1_BLOCK_SIZE_IN_32BIT_WORDS    (CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES / sizeof(uint32_t))
57 #define CRYPTO_SHA1_DIGEST_SIZE_IN_32BIT_WORDS   (CRYPTO_SHA1_DIGEST_SIZE_IN_BYTES / sizeof(uint32_t))
58 
59 #define CRYPTO_SHA256_BLOCK_SIZE_IN_BITS         (512UL)
60 #define CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES        (CRYPTO_SHA256_BLOCK_SIZE_IN_BITS / 8UL)
61 #define CRYPTO_SHA256_BLOCK_SIZE_IN_32BIT_WORDS  (CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES / sizeof(uint32_t))
62 
63 #define CRYPTO_SHA256_DIGEST_SIZE_IN_32BIT_WORDS (CRYPTO_SHA256_DIGEST_SIZE_IN_BYTES / sizeof(uint32_t))
64 
65 #define PARTIAL_OPERAND_WIDTH_LOG2               (7UL)  /* 2^7 = 128 */
66 #define PARTIAL_OPERAND_WIDTH                    (1UL << PARTIAL_OPERAND_WIDTH_LOG2)
67 #define PARTIAL_OPERAND_WIDTH_MASK               (PARTIAL_OPERAND_WIDTH - 1UL)
68 #define PARTIAL_OPERAND_WIDTH_IN_BYTES           (PARTIAL_OPERAND_WIDTH / 8UL)
69 #define PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS     (PARTIAL_OPERAND_WIDTH_IN_BYTES / sizeof(uint32_t))
70 
71 #define SWAP32(x)                                (__REV(x))
72 
73 #define CRYPTO_AES_BLOCKSIZE                     (16UL)
74 
75 /*******************************************************************************
76  ***********************   STATIC FUNCTIONS   **********************************
77  ******************************************************************************/
78 
79 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
80 __STATIC_INLINE void CRYPTO_DataWriteVariableSize(CRYPTO_DataReg_TypeDef dataReg,
81                                                   const CRYPTO_Data_TypeDef val,
82                                                   int valSize);
83 #endif // USE_VARIABLE_SIZED_DATA_LOADS
84 
85 __STATIC_INLINE void cryptoBurstToCryptoAndZeroize(volatile uint32_t * reg,
86                                                    const uint32_t * val);
87 
88 __STATIC_INLINE void cryptoBurstFromCryptoAndZeroize(volatile uint32_t * reg,
89                                                      uint32_t * val);
90 
91 __STATIC_INLINE void cryptoBigintZeroize(uint32_t * words32bits,
92                                          unsigned   num32bitWords);
93 
94 __STATIC_INLINE void cryptoBigintIncrement(uint32_t * words32bits,
95                                            unsigned   num32bitWords);
96 
97 __STATIC_INLINE void CRYPTO_AES_ProcessLoop(CRYPTO_TypeDef *crypto,
98                                             unsigned int len,
99                                             CRYPTO_DataReg_TypeDef inReg,
100                                             const uint8_t * in,
101                                             CRYPTO_DataReg_TypeDef outReg,
102                                             uint8_t * out);
103 
104 static void CRYPTO_AES_CBCx(CRYPTO_TypeDef *crypto,
105                             uint8_t * out,
106                             const uint8_t * in,
107                             unsigned int len,
108                             const uint8_t * key,
109                             const uint8_t * iv,
110                             bool encrypt,
111                             CRYPTO_KeyWidth_TypeDef keyWidth);
112 
113 static void CRYPTO_AES_PCBCx(CRYPTO_TypeDef *crypto,
114                              uint8_t * out,
115                              const uint8_t * in,
116                              unsigned int len,
117                              const uint8_t * key,
118                              const uint8_t * iv,
119                              bool encrypt,
120                              CRYPTO_KeyWidth_TypeDef keyWidth);
121 
122 static void CRYPTO_AES_CFBx(CRYPTO_TypeDef *crypto,
123                             uint8_t * out,
124                             const uint8_t * in,
125                             unsigned int len,
126                             const uint8_t * key,
127                             const uint8_t * iv,
128                             bool encrypt,
129                             CRYPTO_KeyWidth_TypeDef keyWidth);
130 
131 static void CRYPTO_AES_CTRx(CRYPTO_TypeDef *crypto,
132                             uint8_t * out,
133                             const uint8_t * in,
134                             unsigned int len,
135                             const uint8_t * key,
136                             uint8_t * ctr,
137                             CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,
138                             CRYPTO_KeyWidth_TypeDef keyWidth);
139 
140 static void CRYPTO_AES_ECBx(CRYPTO_TypeDef *crypto,
141                             uint8_t * out,
142                             const uint8_t * in,
143                             unsigned int len,
144                             const uint8_t * key,
145                             bool encrypt,
146                             CRYPTO_KeyWidth_TypeDef keyWidth);
147 
148 static void CRYPTO_AES_OFBx(CRYPTO_TypeDef *crypto,
149                             uint8_t * out,
150                             const uint8_t * in,
151                             unsigned int len,
152                             const uint8_t * key,
153                             const uint8_t * iv,
154                             CRYPTO_KeyWidth_TypeDef keyWidth);
155 
156 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
157 /***************************************************************************//**
158  * @brief
159  *   Write variable sized 32 bit data array (max 128 bits) to a DATAX register.
160  *
161  * @details
162  *   Write variable sized 32 bit array (max 128 bits / 4 words) to a DATAX
163  *   register in the CRYPTO module.
164  *
165  * @param[in]  dataReg    The 128 bits DATA register.
166  * @param[in]  val        Value of the data to write to the DATA register.
167  * @param[in]  valSize    Size of @ref val in number of 32 bit words.
168  ******************************************************************************/
169 __STATIC_INLINE
CRYPTO_DataWriteVariableSize(CRYPTO_DataReg_TypeDef dataReg,const CRYPTO_Data_TypeDef val,int valSize)170 void CRYPTO_DataWriteVariableSize(CRYPTO_DataReg_TypeDef    dataReg,
171                                   const CRYPTO_Data_TypeDef val,
172                                   int                       valSize)
173 {
174   int i;
175   volatile uint32_t * reg = (volatile uint32_t *) dataReg;
176 
177   if (valSize < 4) {
178     /* Non optimal write of data. */
179     for (i = 0; i < valSize; i++) {
180       *reg = *val++;
181     }
182     for (; i < 4; i++) {
183       *reg = 0;
184     }
185   } else {
186     CRYPTO_BurstToCrypto(reg, &val[0]);
187   }
188 }
189 #endif
190 
191 /** @endcond */
192 
193 /*******************************************************************************
194  **************************   GLOBAL FUNCTIONS   *******************************
195  ******************************************************************************/
CRYPTO_BurstToCrypto(volatile uint32_t * reg,const uint32_t * val)196 void CRYPTO_BurstToCrypto(volatile uint32_t * reg,
197                           const uint32_t * val)
198 {
199   /* Load data from memory into local registers. */
200   register uint32_t v0 = val[0];
201   register uint32_t v1 = val[1];
202   register uint32_t v2 = val[2];
203   register uint32_t v3 = val[3];
204   /* Store data to CRYPTO */
205   *reg = v0;
206   *reg = v1;
207   *reg = v2;
208   *reg = v3;
209 }
210 
CRYPTO_BurstFromCrypto(volatile uint32_t * reg,uint32_t * val)211 void CRYPTO_BurstFromCrypto(volatile uint32_t * reg, uint32_t * val)
212 {
213   /* Load data from CRYPTO into local registers. */
214   register uint32_t v0 = *reg;
215   register uint32_t v1 = *reg;
216   register uint32_t v2 = *reg;
217   register uint32_t v3 = *reg;
218   /* Store data to memory */
219   val[0] = v0;
220   val[1] = v1;
221   val[2] = v2;
222   val[3] = v3;
223 }
224 
CRYPTO_DataWrite(CRYPTO_DataReg_TypeDef dataReg,const CRYPTO_Data_TypeDef val)225 void CRYPTO_DataWrite(CRYPTO_DataReg_TypeDef dataReg,
226                       const CRYPTO_Data_TypeDef val)
227 {
228   CRYPTO_BurstToCrypto(dataReg, val);
229 }
230 
CRYPTO_DataWriteUnaligned(volatile uint32_t * reg,const uint8_t * val)231 void CRYPTO_DataWriteUnaligned(volatile uint32_t * reg,
232                                const uint8_t * val)
233 {
234   /* Check data is 32-bit aligned, if not move to temporary buffer before
235      writing.*/
236   if ((uintptr_t)val & 0x3) {
237     uint32_t temp[4];
238     memcpy(temp, val, sizeof(temp));
239     CRYPTO_DataWrite(reg, temp);
240   } else {
241     // Avoid casting val directly to uint32_t pointer as this can lead to the
242     // compiler making incorrect assumptions in the case where val is un-
243     // aligned.
244     const uint8_t * volatile tmp_val_ptr = val;
245     CRYPTO_DataWrite(reg, (const uint32_t*)tmp_val_ptr);
246   }
247 }
248 
CRYPTO_DataRead(CRYPTO_DataReg_TypeDef dataReg,CRYPTO_Data_TypeDef val)249 void CRYPTO_DataRead(CRYPTO_DataReg_TypeDef  dataReg,
250                      CRYPTO_Data_TypeDef     val)
251 {
252   CRYPTO_BurstFromCrypto(dataReg, val);
253 }
254 
CRYPTO_DataReadUnaligned(volatile uint32_t * reg,uint8_t * val)255 void CRYPTO_DataReadUnaligned(volatile uint32_t * reg,
256                               uint8_t * val)
257 {
258   /* Check data is 32bit aligned, if not, read into temporary buffer and
259      then move to user buffer. */
260   if ((uintptr_t)val & 0x3) {
261     uint32_t temp[4];
262     CRYPTO_DataRead(reg, temp);
263     memcpy(val, temp, sizeof(temp));
264   } else {
265     // Avoid casting val directly to uint32_t pointer as this can lead to the
266     // compiler making incorrect assumptions in the case where val is un-
267     // aligned.
268     uint8_t * volatile tmp_val_ptr = val;
269     CRYPTO_DataRead(reg, (uint32_t*)tmp_val_ptr);
270   }
271 }
272 
CRYPTO_DDataWrite(CRYPTO_DDataReg_TypeDef ddataReg,const CRYPTO_DData_TypeDef val)273 void CRYPTO_DDataWrite(CRYPTO_DDataReg_TypeDef ddataReg,
274                        const CRYPTO_DData_TypeDef val)
275 {
276   CRYPTO_BurstToCrypto(ddataReg, &val[0]);
277   CRYPTO_BurstToCrypto(ddataReg, &val[4]);
278 }
279 
CRYPTO_DDataRead(CRYPTO_DDataReg_TypeDef ddataReg,CRYPTO_DData_TypeDef val)280 void CRYPTO_DDataRead(CRYPTO_DDataReg_TypeDef  ddataReg,
281                       CRYPTO_DData_TypeDef     val)
282 {
283   CRYPTO_BurstFromCrypto(ddataReg, &val[0]);
284   CRYPTO_BurstFromCrypto(ddataReg, &val[4]);
285 }
286 
CRYPTO_DDataReadUnaligned(CRYPTO_DDataReg_TypeDef ddataReg,uint8_t * val)287 void CRYPTO_DDataReadUnaligned(CRYPTO_DDataReg_TypeDef ddataReg,
288                                uint8_t * val)
289 {
290   /* Check if the buffer pointer is 32-bit aligned, if not read the data into a
291      temporary 32-bit aligned buffer then copy the data to the output buffer.*/
292   if ((uintptr_t)val & 0x3) {
293     CRYPTO_DData_TypeDef temp;
294     CRYPTO_DDataRead(ddataReg, temp);
295     memcpy(val, temp, sizeof(temp));
296   } else {
297     // Avoid casting val directly to uint32_t pointer as this can lead to the
298     // compiler making incorrect assumptions in the case where val is un-
299     // aligned.
300     uint8_t * volatile tmp_val_ptr = val;
301     CRYPTO_DDataRead(ddataReg, (uint32_t*) tmp_val_ptr);
302   }
303 }
304 
CRYPTO_QDataRead(CRYPTO_QDataReg_TypeDef qdataReg,CRYPTO_QData_TypeDef val)305 void CRYPTO_QDataRead(CRYPTO_QDataReg_TypeDef qdataReg,
306                       CRYPTO_QData_TypeDef    val)
307 {
308   CRYPTO_BurstFromCrypto(qdataReg, &val[0]);
309   CRYPTO_BurstFromCrypto(qdataReg, &val[4]);
310   CRYPTO_BurstFromCrypto(qdataReg, &val[8]);
311   CRYPTO_BurstFromCrypto(qdataReg, &val[12]);
312 }
313 
CRYPTO_QDataWrite(CRYPTO_QDataReg_TypeDef qdataReg,const CRYPTO_QData_TypeDef val)314 void CRYPTO_QDataWrite(CRYPTO_QDataReg_TypeDef qdataReg,
315                        const CRYPTO_QData_TypeDef val)
316 {
317   CRYPTO_BurstToCrypto(qdataReg, &val[0]);
318   CRYPTO_BurstToCrypto(qdataReg, &val[4]);
319   CRYPTO_BurstToCrypto(qdataReg, &val[8]);
320   CRYPTO_BurstToCrypto(qdataReg, &val[12]);
321 }
322 
CRYPTO_QDataWriteUnaligned(CRYPTO_QDataReg_TypeDef qdataReg,const uint8_t * val)323 void CRYPTO_QDataWriteUnaligned(CRYPTO_QDataReg_TypeDef qdataReg,
324                                 const uint8_t * val)
325 {
326   /* Check data is 32-bit aligned,
327      if not move to temporary 32-bit aligned buffer before writing. */
328   if ((uintptr_t)val & 0x3) {
329     CRYPTO_QData_TypeDef temp;
330     memcpy(temp, val, sizeof(temp));
331     CRYPTO_QDataWrite(qdataReg, temp);
332   } else {
333     // Avoid casting val directly to uint32_t pointer as this can lead to the
334     // compiler making incorrect assumptions in the case where val is un-
335     // aligned.
336     const uint8_t * volatile tmp_val_ptr = val;
337     CRYPTO_QDataWrite(qdataReg, (const uint32_t*) tmp_val_ptr);
338   }
339 }
340 
341 // Write sensitive value (typically key) to CRYPTO and zeroize local registers.
342 // Sensitive values in local registers may leak to stack or read directly by
343 // malicious software.
cryptoBurstToCryptoAndZeroize(volatile uint32_t * reg,const uint32_t * val)344 __STATIC_INLINE void cryptoBurstToCryptoAndZeroize(volatile uint32_t * reg,
345                                                    const uint32_t * val)
346 {
347   /* Load data from memory into local registers. */
348   register volatile uint32_t v0 = val[0];
349   register volatile uint32_t v1 = val[1];
350   register volatile uint32_t v2 = val[2];
351   register volatile uint32_t v3 = val[3];
352   /* Store data to CRYPTO */
353   *reg = v0;
354   *reg = v1;
355   *reg = v2;
356   *reg = v3;
357   v0 = 0;
358   v1 = 0;
359   v2 = 0;
360   v3 = 0;
361 }
362 
363 // Read sensitive value (typically key) from CRYPTO and zeroize local registers.
364 // Sensitive values in local registers may leak to stack or read directly by
365 // malicious software.
cryptoBurstFromCryptoAndZeroize(volatile uint32_t * reg,uint32_t * val)366 __STATIC_INLINE void cryptoBurstFromCryptoAndZeroize(volatile uint32_t * reg, uint32_t * val)
367 {
368   /* Load data from CRYPTO into local registers. */
369   register volatile uint32_t v0 = *reg;
370   register volatile uint32_t v1 = *reg;
371   register volatile uint32_t v2 = *reg;
372   register volatile uint32_t v3 = *reg;
373   /* Store data to memory */
374   val[0] = v0;
375   val[1] = v1;
376   val[2] = v2;
377   val[3] = v3;
378   v0 = 0;
379   v1 = 0;
380   v2 = 0;
381   v3 = 0;
382 }
383 
CRYPTO_KeyBufWrite(CRYPTO_TypeDef * crypto,CRYPTO_KeyBuf_TypeDef val,CRYPTO_KeyWidth_TypeDef keyWidth)384 void CRYPTO_KeyBufWrite(CRYPTO_TypeDef          *crypto,
385                         CRYPTO_KeyBuf_TypeDef    val,
386                         CRYPTO_KeyWidth_TypeDef  keyWidth)
387 {
388   if (keyWidth == cryptoKey256Bits) {
389     /* Set AES-256 mode */
390     BUS_RegBitWrite(&crypto->CTRL, _CRYPTO_CTRL_AES_SHIFT, _CRYPTO_CTRL_AES_AES256);
391     /* Load key in KEYBUF register (= DDATA4) */
392     cryptoBurstToCryptoAndZeroize(&crypto->DDATA4, &val[0]);
393     cryptoBurstToCryptoAndZeroize(&crypto->DDATA4, &val[4]);
394   } else {
395     /* Set AES-128 mode */
396     BUS_RegBitWrite(&crypto->CTRL, _CRYPTO_CTRL_AES_SHIFT, _CRYPTO_CTRL_AES_AES128);
397     cryptoBurstToCryptoAndZeroize(&crypto->KEYBUF, &val[0]);
398   }
399 }
400 
CRYPTO_KeyBufWriteUnaligned(CRYPTO_TypeDef * crypto,const uint8_t * val,CRYPTO_KeyWidth_TypeDef keyWidth)401 void CRYPTO_KeyBufWriteUnaligned(CRYPTO_TypeDef          *crypto,
402                                  const uint8_t *          val,
403                                  CRYPTO_KeyWidth_TypeDef  keyWidth)
404 {
405   /* Check if key val buffer is 32bit aligned, if not move to temporary
406      aligned buffer before writing.*/
407   if ((uintptr_t)val & 0x3) {
408     CRYPTO_KeyBuf_TypeDef temp;
409     if (keyWidth == cryptoKey128Bits) {
410       memcpy(temp, val, 16);
411     } else {
412       memcpy(temp, val, 32);
413     }
414     CRYPTO_KeyBufWrite(crypto, temp, keyWidth);
415     // Wipe out the plaintext key from the temp buffer on stack.
416     cryptoBigintZeroize(temp,
417                         keyWidth == cryptoKey128Bits
418                         ? CRYPTO_DATA_SIZE_IN_32BIT_WORDS
419                         : CRYPTO_DDATA_SIZE_IN_32BIT_WORDS);
420   } else {
421     // Avoid casting val directly to uint32_t pointer as this can lead to the
422     // compiler making incorrect assumptions in the case where val is un-
423     // aligned.
424     const uint8_t * volatile tmp_val_ptr = val;
425     CRYPTO_KeyBufWrite(crypto, (uint32_t*)tmp_val_ptr, keyWidth);
426   }
427 }
428 
CRYPTO_KeyBuf128Write(CRYPTO_TypeDef * crypto,const uint32_t * val)429 void CRYPTO_KeyBuf128Write(CRYPTO_TypeDef *crypto,
430                            const uint32_t * val)
431 {
432   CRYPTO_BurstToCrypto(&crypto->KEYBUF, val);
433 }
434 
CRYPTO_ModulusSet(CRYPTO_TypeDef * crypto,CRYPTO_ModulusId_TypeDef modulusId)435 void CRYPTO_ModulusSet(CRYPTO_TypeDef *          crypto,
436                        CRYPTO_ModulusId_TypeDef  modulusId)
437 {
438   uint32_t temp = crypto->WAC & (~(_CRYPTO_WAC_MODULUS_MASK | _CRYPTO_WAC_MODOP_MASK));
439 
440   switch (modulusId) {
441     case cryptoModulusBin256:
442     case cryptoModulusBin128:
443     case cryptoModulusGcmBin128:
444     case cryptoModulusEccB233:
445     case cryptoModulusEccB163:
446 #ifdef _CRYPTO_WAC_MODULUS_ECCBIN233N
447     case cryptoModulusEccB233Order:
448     case cryptoModulusEccB233KOrder:
449     case cryptoModulusEccB163Order:
450     case cryptoModulusEccB163KOrder:
451 #endif
452       crypto->WAC = temp | (uint32_t)modulusId | CRYPTO_WAC_MODOP_BINARY;
453       break;
454 
455     case cryptoModulusEccP256:
456     case cryptoModulusEccP224:
457     case cryptoModulusEccP192:
458 #ifdef _CRYPTO_WAC_MODULUS_ECCPRIME256P
459     case cryptoModulusEccP256Order:
460     case cryptoModulusEccP224Order:
461     case cryptoModulusEccP192Order:
462 #endif
463       crypto->WAC = temp | (uint32_t)modulusId | CRYPTO_WAC_MODOP_REGULAR;
464       break;
465 
466     default:
467       /* Unknown modulus identifier. */
468       EFM_ASSERT(false);
469       break;
470   }
471 }
472 
473 /***************************************************************************//**
474  * @brief
475  *   Read the key value currently used by the CRYPTO module.
476  *
477  * @details
478  *   Read 128 bits or 256 bits from the KEY register in the CRYPTO module.
479  *
480  * @param[in]  crypto
481  *   A pointer to the CRYPTO peripheral register block.
482  *
483  * @param[in]  val
484  *   A value of the data to write to the KEYBUF register.
485  *
486  * @param[in]  keyWidth
487  *   Key width - 128 or 256 bits
488  ******************************************************************************/
CRYPTO_KeyRead(CRYPTO_TypeDef * crypto,CRYPTO_KeyBuf_TypeDef val,CRYPTO_KeyWidth_TypeDef keyWidth)489 void CRYPTO_KeyRead(CRYPTO_TypeDef *         crypto,
490                     CRYPTO_KeyBuf_TypeDef    val,
491                     CRYPTO_KeyWidth_TypeDef  keyWidth)
492 {
493   EFM_ASSERT(&val[0] != NULL);
494 
495   cryptoBurstFromCryptoAndZeroize(&crypto->KEY, &val[0]);
496   if (keyWidth == cryptoKey256Bits) {
497     cryptoBurstFromCryptoAndZeroize(&crypto->KEY, &val[4]);
498   }
499 }
500 
501 /***************************************************************************//**
502  * @brief
503  *   Read the key value currently used by the CRYPTO module.
504  *
505  * @details
506  *   Read 128 bits or 256 bits from the KEY register in the CRYPTO module.
507  *   The destination pointer does not have to be word-aligned, but an unaligned
508  *   pointer might incur a performance penalty.
509  *
510  * @param[in]  crypto
511  *   A pointer to the CRYPTO peripheral register block.
512  *
513  * @param[in]  val
514  *   A pointer to a buffer which the key will be written to.
515  *   Can be unaligned.
516  *
517  * @param[in]  keyWidth
518  *   Key width - 128 or 256 bits
519  ******************************************************************************/
CRYPTO_KeyReadUnaligned(CRYPTO_TypeDef * crypto,uint8_t * val,CRYPTO_KeyWidth_TypeDef keyWidth)520 void CRYPTO_KeyReadUnaligned(CRYPTO_TypeDef *         crypto,
521                              uint8_t *                val,
522                              CRYPTO_KeyWidth_TypeDef  keyWidth)
523 {
524   if ((uint32_t)val & 0x3) {
525     CRYPTO_KeyBuf_TypeDef temp;
526     CRYPTO_KeyRead(crypto, temp, keyWidth);
527     if (keyWidth == cryptoKey128Bits) {
528       memcpy(val, temp, 16);
529     } else {
530       memcpy(val, temp, 32);
531     }
532     // Wipe out the plaintext key from the temp buffer on stack.
533     cryptoBigintZeroize(temp,
534                         keyWidth == cryptoKey128Bits
535                         ? CRYPTO_DATA_SIZE_IN_32BIT_WORDS
536                         : CRYPTO_DDATA_SIZE_IN_32BIT_WORDS);
537   } else {
538     // Avoid casting val directly to uint32_t pointer as this can lead to the
539     // compiler making incorrect assumptions in the case where val is un-
540     // aligned.
541     uint8_t * volatile tmp_val_ptr = val;
542     CRYPTO_KeyRead(crypto, (uint32_t*)tmp_val_ptr, keyWidth);
543   }
544 }
545 
546 /***************************************************************************//**
547  * @brief
548  *   Perform a SHA-1 hash operation on a message.
549  *
550  * @details
551  *   This function performs a SHA-1 hash operation on the message specified by
552  *   msg with length msgLen and returns the message digest in msgDigest.
553  *
554  * @param[in]  crypto
555  *   A pointer to the CRYPTO peripheral register block.
556  *
557  * @param[in]  msg
558  *   Message to hash.
559  *
560  * @param[in]  msgLen
561  *   Length of message in bytes.
562  *
563  * @param[out] msgDigest
564  *   A message digest.
565  ******************************************************************************/
CRYPTO_SHA_1(CRYPTO_TypeDef * crypto,const uint8_t * msg,uint64_t msgLen,CRYPTO_SHA1_Digest_TypeDef msgDigest)566 void CRYPTO_SHA_1(CRYPTO_TypeDef *             crypto,
567                   const uint8_t *              msg,
568                   uint64_t                     msgLen,
569                   CRYPTO_SHA1_Digest_TypeDef   msgDigest)
570 {
571   uint32_t  temp;
572   uint32_t  len;
573   int       blockLen;
574   uint32_t  shaBlock[CRYPTO_SHA1_BLOCK_SIZE_IN_32BIT_WORDS];
575   uint8_t * p8ShaBlock = (uint8_t *) shaBlock;
576 
577   /* Initialize the CRYPTO module to do SHA-1. */
578   crypto->CTRL     = CRYPTO_CTRL_SHA_SHA1;
579   crypto->SEQCTRL  = 0;
580   crypto->SEQCTRLB = 0;
581 
582   /* Set the result width of the MADD32 operation. */
583   CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
584 
585   /* Write the initialization value to DDATA1.  */
586   crypto->DDATA1 = 0x67452301UL;
587   crypto->DDATA1 = 0xefcdab89UL;
588   crypto->DDATA1 = 0x98badcfeUL;
589   crypto->DDATA1 = 0x10325476UL;
590   crypto->DDATA1 = 0xc3d2e1f0UL;
591   crypto->DDATA1 = 0x00000000UL;
592   crypto->DDATA1 = 0x00000000UL;
593   crypto->DDATA1 = 0x00000000UL;
594 
595   /* Copy data to DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
596   CRYPTO_EXECUTE_2(crypto,
597                    CRYPTO_CMD_INSTR_DDATA1TODDATA0,
598                    CRYPTO_CMD_INSTR_SELDDATA0DDATA1);
599 
600   len = (uint32_t)msgLen;
601 
602   while (len >= CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES) {
603     /* Write block to QDATA1.  */
604     CRYPTO_InstructionSequenceWait(crypto);
605     CRYPTO_QDataWriteUnaligned(&crypto->QDATA1BIG, msg);
606 
607     /* Execute SHA. */
608     CRYPTO_EXECUTE_3(crypto,
609                      CRYPTO_CMD_INSTR_SHA,
610                      CRYPTO_CMD_INSTR_MADD32,
611                      CRYPTO_CMD_INSTR_DDATA0TODDATA1);
612 
613     len -= CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES;
614     msg += CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES;
615   }
616 
617   blockLen = 0;
618 
619   /* Build the last (or second to last) block. */
620   for (; len > 0U; len--) {
621     p8ShaBlock[blockLen++] = *msg++;
622   }
623 
624   /* Append the '1' bit. */
625   p8ShaBlock[blockLen++] = 0x80;
626 
627   /* If the length is currently above 56 bytes, zeros are appended
628    * then compressed.  Then, zeros are padded and length
629    * encoded like normal.
630    */
631   if (blockLen > 56) {
632     while (blockLen < 64) {
633       p8ShaBlock[blockLen++] = 0;
634     }
635 
636     /* Write block to QDATA1BIG. */
637     CRYPTO_InstructionSequenceWait(crypto);
638     CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
639 
640     /* Execute SH. */
641     CRYPTO_EXECUTE_3(crypto,
642                      CRYPTO_CMD_INSTR_SHA,
643                      CRYPTO_CMD_INSTR_MADD32,
644                      CRYPTO_CMD_INSTR_DDATA0TODDATA1);
645     blockLen = 0;
646   }
647 
648   /* Pad up to 56 bytes of zeros. */
649   while (blockLen < 56) {
650     p8ShaBlock[blockLen++] = 0;
651   }
652 
653   /* Finally, encode the message length. */
654   {
655     uint64_t msgLenInBits = msgLen << 3U;
656     temp = (uint32_t)(msgLenInBits >> 32U);
657     *(uint32_t*)&p8ShaBlock[56] = SWAP32(temp);
658     temp = (uint32_t)msgLenInBits & 0xFFFFFFFFUL;
659     *(uint32_t*)&p8ShaBlock[60] = SWAP32(temp);
660   }
661 
662   /* Write block to QDATA1BIG. */
663   CRYPTO_InstructionSequenceWait(crypto);
664   CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
665 
666   /* Execute SHA. */
667   CRYPTO_EXECUTE_3(crypto,
668                    CRYPTO_CMD_INSTR_SHA,
669                    CRYPTO_CMD_INSTR_MADD32,
670                    CRYPTO_CMD_INSTR_DDATA0TODDATA1);
671 
672   /* Read the resulting message digest from DDATA0BIG.  */
673   CRYPTO_InstructionSequenceWait(crypto);
674 
675   /* Check if the buffer pointer is 32-bit aligned, if not read the data into a
676      temporary 32-bit aligned buffer then copy the data to the output buffer.*/
677   if ((uintptr_t)msgDigest & 0x3) {
678     CRYPTO_DData_TypeDef tempDData;
679     CRYPTO_DDataRead(&crypto->DDATA0BIG, tempDData);
680     memcpy(msgDigest, tempDData, sizeof(CRYPTO_SHA1_Digest_TypeDef));
681   } else {
682     ((uint32_t*)msgDigest)[0] = crypto->DDATA0BIG;
683     ((uint32_t*)msgDigest)[1] = crypto->DDATA0BIG;
684     ((uint32_t*)msgDigest)[2] = crypto->DDATA0BIG;
685     ((uint32_t*)msgDigest)[3] = crypto->DDATA0BIG;
686     ((uint32_t*)msgDigest)[4] = crypto->DDATA0BIG;
687     crypto->DDATA0BIG;
688     crypto->DDATA0BIG;
689     crypto->DDATA0BIG;
690   }
691 }
692 
693 /***************************************************************************//**
694  * @brief
695  *   Perform a SHA-256 hash operation on a message.
696  *
697  * @details
698  *   This function performs a SHA-256 hash operation on the message specified
699  *   by msg with length msgLen and returns the message digest in msgDigest.
700  *
701  * @param[in]  crypto
702  *   A pointer to the CRYPTO peripheral register block.
703  *
704  * @param[in]  msg
705  *   A message to hash.
706  *
707  * @param[in]  msgLen
708  *   The length of message in bytes.
709  *
710  * @param[out] msgDigest
711  *   A message digest.
712  ******************************************************************************/
CRYPTO_SHA_256(CRYPTO_TypeDef * crypto,const uint8_t * msg,uint64_t msgLen,CRYPTO_SHA256_Digest_TypeDef msgDigest)713 void CRYPTO_SHA_256(CRYPTO_TypeDef *             crypto,
714                     const uint8_t *              msg,
715                     uint64_t                     msgLen,
716                     CRYPTO_SHA256_Digest_TypeDef msgDigest)
717 {
718   uint32_t  temp;
719   uint32_t  len;
720   int       blockLen;
721   uint32_t  shaBlock[CRYPTO_SHA256_BLOCK_SIZE_IN_32BIT_WORDS];
722   uint8_t * p8ShaBlock = (uint8_t *) shaBlock;
723 
724   /* Initial values */
725   shaBlock[0] = 0x6a09e667UL;
726   shaBlock[1] = 0xbb67ae85UL;
727   shaBlock[2] = 0x3c6ef372UL;
728   shaBlock[3] = 0xa54ff53aUL;
729   shaBlock[4] = 0x510e527fUL;
730   shaBlock[5] = 0x9b05688cUL;
731   shaBlock[6] = 0x1f83d9abUL;
732   shaBlock[7] = 0x5be0cd19UL;
733 
734   /* Initialize the CRYPTO module to do SHA-256 (SHA-2). */
735   crypto->CTRL     = CRYPTO_CTRL_SHA_SHA2;
736   crypto->SEQCTRL  = 0;
737   crypto->SEQCTRLB = 0;
738 
739   /* Set the result width of the MADD32 operation. */
740   CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
741 
742   /* Write the initialization value to DDATA1.  */
743   CRYPTO_DDataWrite(&crypto->DDATA1, shaBlock);
744 
745   /* Copy data ot DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
746   CRYPTO_EXECUTE_2(crypto,
747                    CRYPTO_CMD_INSTR_DDATA1TODDATA0,
748                    CRYPTO_CMD_INSTR_SELDDATA0DDATA1);
749   len = (uint32_t)msgLen;
750 
751   while (len >= CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES) {
752     /* Write block to QDATA1BIG.  */
753     CRYPTO_InstructionSequenceWait(crypto);
754     CRYPTO_QDataWriteUnaligned(&crypto->QDATA1BIG, msg);
755 
756     /* Execute SHA. */
757     CRYPTO_EXECUTE_3(crypto,
758                      CRYPTO_CMD_INSTR_SHA,
759                      CRYPTO_CMD_INSTR_MADD32,
760                      CRYPTO_CMD_INSTR_DDATA0TODDATA1);
761 
762     len -= CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES;
763     msg += CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES;
764   }
765 
766   blockLen = 0;
767 
768   /* Build the last (or second to last) block. */
769   for (; len > 0U; len--) {
770     p8ShaBlock[blockLen++] = *msg++;
771   }
772 
773   /* Append the '1' bit. */
774   p8ShaBlock[blockLen++] = 0x80;
775 
776   /* If the length is currently above 56 bytes, zeros are appended
777    * then compressed.  Then, zeros are padded and length
778    * encoded like normal.
779    */
780   if (blockLen > 56) {
781     while (blockLen < 64) {
782       p8ShaBlock[blockLen++] = 0;
783     }
784 
785     /* Write block to QDATA1BIG. */
786     CRYPTO_InstructionSequenceWait(crypto);
787     CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
788 
789     /* Execute SHA. */
790     CRYPTO_EXECUTE_3(crypto,
791                      CRYPTO_CMD_INSTR_SHA,
792                      CRYPTO_CMD_INSTR_MADD32,
793                      CRYPTO_CMD_INSTR_DDATA0TODDATA1);
794     blockLen = 0;
795   }
796 
797   /* Pad up to 56 bytes of zeros. */
798   while (blockLen < 56) {
799     p8ShaBlock[blockLen++] = 0;
800   }
801 
802   /* Finally, encode the message length. */
803   {
804     uint64_t msgLenInBits = msgLen << 3;
805     temp = (uint32_t)(msgLenInBits >> 32);
806     *(uint32_t *)&p8ShaBlock[56] = SWAP32(temp);
807     temp = (uint32_t)msgLenInBits & 0xFFFFFFFFUL;
808     *(uint32_t *)&p8ShaBlock[60] = SWAP32(temp);
809   }
810 
811   /* Write the final block to QDATA1BIG. */
812   CRYPTO_InstructionSequenceWait(crypto);
813   CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
814 
815   /* Execute SHA. */
816   CRYPTO_EXECUTE_3(crypto,
817                    CRYPTO_CMD_INSTR_SHA,
818                    CRYPTO_CMD_INSTR_MADD32,
819                    CRYPTO_CMD_INSTR_DDATA0TODDATA1);
820 
821   /* Read the resulting message digest from DDATA0BIG.  */
822   CRYPTO_InstructionSequenceWait(crypto);
823   CRYPTO_DDataReadUnaligned(&crypto->DDATA0BIG, msgDigest);
824 }
825 
826 /***************************************************************************//**
827  * @brief
828  *   Set the 32 bit word array to zero.
829  *
830  * @param[in]  words32bits    A pointer to the 32 bit word array.
831  * @param[in]  num32bitWords  A number of 32 bit words in array.
832  ******************************************************************************/
cryptoBigintZeroize(uint32_t * words32bits,unsigned num32bitWords)833 __STATIC_INLINE void cryptoBigintZeroize(uint32_t * words32bits,
834                                          unsigned   num32bitWords)
835 {
836   volatile uint32_t *p = words32bits;
837   while (num32bitWords--) {
838     *p++ = 0;
839   }
840 }
841 
842 /***************************************************************************//**
843  * @brief
844  *   Increment value of 32bit word array by one.
845  *
846  * @param[in] words32bits    Pointer to 32bit word array
847  * @param[in] num32bitWords  Number of 32bit words in array
848  ******************************************************************************/
cryptoBigintIncrement(uint32_t * words32bits,unsigned num32bitWords)849 __STATIC_INLINE void cryptoBigintIncrement(uint32_t * words32bits,
850                                            unsigned   num32bitWords)
851 {
852   unsigned i;
853   for (i = 0; i < num32bitWords; i++) {
854     if (++words32bits[i] != 0UL) {
855       break;
856     }
857   }
858   return;
859 }
860 
861 /***************************************************************************//**
862  * @brief
863  *   Multiply two big integers.
864  *
865  * @details
866  *   This function uses the CRYPTO unit to multiply two big integer operands.
867  *   If USE_VARIABLE_SIZED_DATA_LOADS is defined, the sizes of the operands
868  *   may be any multiple of 32 bits. If USE_VARIABLE_SIZED_DATA_LOADS is _not_
869  *   defined, the sizes of the operands must be a multiple of 128 bits.
870  *
871  * @param[in]  crypto   CRYPTO module
872  * @param[in]  A        An operand A
873  * @param[in]  aSize    The size of the operand A in bits
874  * @param[in]  B        An operand B
875  * @param[in]  bSize    The size of the operand B in bits
876  * @param[out] R        The result of multiplication
877  * @param[in]  rSize    The size of the result buffer R in bits
878  ******************************************************************************/
CRYPTO_Mul(CRYPTO_TypeDef * crypto,uint32_t * A,int aSize,uint32_t * B,int bSize,uint32_t * R,int rSize)879 void CRYPTO_Mul(CRYPTO_TypeDef * crypto,
880                 uint32_t * A, int aSize,
881                 uint32_t * B, int bSize,
882                 uint32_t * R, int rSize)
883 {
884   unsigned i, j;
885 
886   /****************   Initializations   ******************/
887 
888 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
889   unsigned numWordsLastOperandA = ((unsigned)aSize & PARTIAL_OPERAND_WIDTH_MASK) >> 5;
890   unsigned numPartialOperandsA = numWordsLastOperandA
891                                  ? ((unsigned)aSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1
892                                  : (unsigned)aSize >> PARTIAL_OPERAND_WIDTH_LOG2;
893   unsigned numWordsLastOperandB = ((unsigned)bSize & PARTIAL_OPERAND_WIDTH_MASK) >> 5;
894   unsigned numPartialOperandsB = numWordsLastOperandB
895                                  ? ((unsigned)bSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1
896                                  : (unsigned)bSize >> PARTIAL_OPERAND_WIDTH_LOG2;
897   unsigned numWordsLastOperandR = ((unsigned)rSize & PARTIAL_OPERAND_WIDTH_MASK) >> 5;
898   unsigned numPartialOperandsR = numWordsLastOperandR
899                                  ? ((unsigned)rSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1
900                                  : (unsigned)rSize >> PARTIAL_OPERAND_WIDTH_LOG2;
901   EFM_ASSERT(numPartialOperandsA + numPartialOperandsB <= numPartialOperandsR);
902 #else
903   unsigned numPartialOperandsA = (unsigned)aSize >> PARTIAL_OPERAND_WIDTH_LOG2;
904   unsigned numPartialOperandsB = (unsigned)bSize >> PARTIAL_OPERAND_WIDTH_LOG2;
905   EFM_ASSERT(((unsigned)aSize & PARTIAL_OPERAND_WIDTH_MASK) == 0UL);
906   EFM_ASSERT(((unsigned)bSize & PARTIAL_OPERAND_WIDTH_MASK) == 0UL);
907 #endif
908   EFM_ASSERT(aSize + bSize <= rSize);
909 
910   /* Set R to zero. */
911   cryptoBigintZeroize(R, (unsigned)rSize >> 5);
912 
913   /* Set the multiplication width. */
914   crypto->WAC = CRYPTO_WAC_MULWIDTH_MUL128 | CRYPTO_WAC_RESULTWIDTH_256BIT;
915 
916   /* Set up DMA request signaling for MCU to run in parallel with
917      the CRYPTO instruction sequence execution and prepare data loading which
918      can take place immediately when CRYPTO is ready inside the instruction
919      sequence. */
920   crypto->CTRL =
921     CRYPTO_CTRL_DMA0RSEL_DATA0 | CRYPTO_CTRL_DMA0MODE_FULL
922     | CRYPTO_CTRL_DMA1RSEL_DATA1 | CRYPTO_CTRL_DMA1MODE_FULL;
923 
924   CRYPTO_EXECUTE_4(crypto,
925                    CRYPTO_CMD_INSTR_CCLR,    /* Carry = 0 */
926                    CRYPTO_CMD_INSTR_CLR,     /* DDATA0 = 0 */
927                    /* clear result accumulation register */
928                    CRYPTO_CMD_INSTR_DDATA0TODDATA2,
929                    CRYPTO_CMD_INSTR_SELDDATA1DDATA3);
930   /*
931      register map:
932      DDATA0: working register
933      DDATA1: B(j)
934      DDATA2: R(i+j+1) and R(i+j), combined with DMA entry for B(j)
935      DDATA3: A(i)
936    */
937 
938   CRYPTO_SEQ_LOAD_10(crypto,
939                      /* Temporarily load the partial operand B(j) to DATA0. */
940                      /* R(i+j+1) is still in DATA1 */
941                      CRYPTO_CMD_INSTR_DMA0TODATA,
942                      /* Move B(j) to DDATA1. */
943                      CRYPTO_CMD_INSTR_DDATA2TODDATA1,
944 
945                      /* Restore the previous partial result (now R(i+j)). */
946                      CRYPTO_CMD_INSTR_DATA1TODATA0,
947 
948                      /* Load the next partial result R(i+j+1). */
949                      CRYPTO_CMD_INSTR_DMA1TODATA,
950 
951                      /* Execute the partial multiplication A(i)inDDATA1 * B(j)inDDATA3.*/
952                      CRYPTO_CMD_INSTR_MULO,
953 
954                      /* Add the result to the previous partial result. */
955                      /* AND take the previous carry value into account */
956                      /* at the right place (bit 128, ADDIC instruction. */
957                      CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
958                      CRYPTO_CMD_INSTR_ADDIC,
959 
960                      /* Save the new partial result (lower half). */
961                      CRYPTO_CMD_INSTR_DDATA0TODDATA2,
962                      CRYPTO_CMD_INSTR_DATATODMA0,
963                      /* Reset the operand selector for next.*/
964                      CRYPTO_CMD_INSTR_SELDDATA2DDATA3
965                      );
966 
967   /****************   End Initializations   ******************/
968 
969   for (i = 0; i < numPartialOperandsA; i++) {
970     /* Load the partial operand #1 A>>(i*PARTIAL_OPERAND_WIDTH) to DDATA1. */
971 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
972     if ( (numWordsLastOperandA != 0) && (i == numPartialOperandsA - 1) ) {
973       CRYPTO_DataWriteVariableSize(&crypto->DATA2,
974                                    &A[i * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
975                                    numWordsLastOperandA);
976     } else {
977       CRYPTO_DataWrite(&crypto->DATA2, &A[i * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
978     }
979 #else
980     CRYPTO_DataWrite(&crypto->DATA2, &A[i * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
981 #endif
982 
983     /* Load the partial result in R>>(i*PARTIAL_OPERAND_WIDTH) to DATA1. */
984 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
985     if ( (numWordsLastOperandR != 0) && (i == numPartialOperandsR - 1) ) {
986       CRYPTO_DataWriteVariableSize(&crypto->DATA1,
987                                    &R[i * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
988                                    numWordsLastOperandR);
989     } else {
990       CRYPTO_DataWrite(&crypto->DATA1, &R[i * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
991     }
992 #else
993     CRYPTO_DataWrite(&crypto->DATA1, &R[i * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
994 #endif
995 
996     /* Clear carry. */
997     crypto->CMD = CRYPTO_CMD_INSTR_CCLR;
998 
999     /* Set up the number of sequence iterations and block size. */
1000     crypto->SEQCTRL = CRYPTO_SEQCTRL_BLOCKSIZE_16BYTES
1001                       | (PARTIAL_OPERAND_WIDTH_IN_BYTES * numPartialOperandsB);
1002 
1003     /* Execute the MULtiply instruction sequence. */
1004     CRYPTO_InstructionSequenceExecute(crypto);
1005 
1006     for (j = 0; j < numPartialOperandsB; j++) {
1007       /* Load the partial operand 2 B>>(j*`PARTIAL_OPERAND_WIDTH) to DDATA2
1008          (via DATA0). */
1009       while ((crypto->STATUS & CRYPTO_STATUS_DMAACTIVE) == 0) {
1010       }
1011 
1012 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
1013       if ( (numWordsLastOperandB != 0) && (j == numPartialOperandsB - 1) ) {
1014         CRYPTO_DataWriteVariableSize(&crypto->DATA0,
1015                                      &B[j * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
1016                                      numWordsLastOperandB);
1017       } else {
1018         CRYPTO_DataWrite(&crypto->DATA0,
1019                          &B[j * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
1020       }
1021 #else
1022       CRYPTO_DataWrite(&crypto->DATA0,
1023                        &B[j * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
1024 #endif
1025 
1026       /* Load the most significant partial result
1027          R>>((i+j+1)*`PARTIAL_OPERAND_WIDTH) into DATA1. */
1028 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
1029       if ( (numWordsLastOperandR != 0) && ( (i + j + 1U) == numPartialOperandsR - 1U) ) {
1030         CRYPTO_DataWriteVariableSize(&crypto->DATA1,
1031                                      &R[(i + j + 1U) * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
1032                                      numWordsLastOperandR);
1033       } else {
1034         CRYPTO_DataWrite(&crypto->DATA1,
1035                          &R[(i + j + 1U) * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
1036       }
1037 #else
1038       CRYPTO_DataWrite(&crypto->DATA1,
1039                        &R[(i + j + 1U) * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
1040 #endif
1041       while ((crypto->STATUS & CRYPTO_STATUS_DMAACTIVE) == 0) {
1042       }
1043       /* Store the least significant partial result. */
1044       CRYPTO_DataRead(&crypto->DATA0,
1045                       &R[(i + j) * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
1046     } /* for (j=0; j<numPartialOperandsB; j++) */
1047 
1048     /* Handle carry at the end of the inner loop. */
1049     if (CRYPTO_CarryIsSet(crypto)) {
1050       cryptoBigintIncrement(&R[(i + numPartialOperandsB + 1U)
1051                                * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
1052                             (numPartialOperandsA - i - 1U)
1053                             * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS);
1054     }
1055 
1056     CRYPTO_DataRead(&crypto->DATA1,
1057                     &R[(i + numPartialOperandsB)
1058                        * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
1059   } /* for (i=0; i<numPartialOperandsA; i++) */
1060 }
1061 
1062 /***************************************************************************//**
1063  * @brief
1064  *   AES Cipher-block chaining (CBC) cipher mode encryption/decryption, 128 bit key.
1065  *
1066  * @details
1067  *   Encryption:
1068  * @verbatim
1069  *           Plaintext                  Plaintext
1070  *               |                          |
1071  *               V                          V
1072  * InitVector ->XOR        +-------------->XOR
1073  *               |         |                |
1074  *               V         |                V
1075  *       +--------------+  |        +--------------+
1076  * Key ->| Block cipher |  |  Key ->| Block cipher |
1077  *       |  encryption  |  |        |  encryption  |
1078  *       +--------------+  |        +--------------+
1079  *               |---------+                |
1080  *               V                          V
1081  *           Ciphertext                 Ciphertext
1082  * @endverbatim
1083  *   Decryption:
1084  * @verbatim
1085  *         Ciphertext                 Ciphertext
1086  *              |----------+                |
1087  *              V          |                V
1088  *       +--------------+  |        +--------------+
1089  * Key ->| Block cipher |  |  Key ->| Block cipher |
1090  *       |  decryption  |  |        |  decryption  |
1091  *       +--------------+  |        +--------------+
1092  *               |         |                |
1093  *               V         |                V
1094  * InitVector ->XOR        +-------------->XOR
1095  *               |                          |
1096  *               V                          V
1097  *           Plaintext                  Plaintext
1098  * @endverbatim
1099  *   See general comments on layout and byte ordering of parameters.
1100  *
1101  * @param[in]  crypto
1102  *   A pointer to the CRYPTO peripheral register block.
1103  *
1104  * @param[out] out
1105  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1106  *   may be set equal to @p in, in which case the input buffer is overwritten.
1107  *
1108  * @param[in] in
1109  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1110  *
1111  * @param[in] len
1112  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1113  *
1114  * @param[in] key
1115  *   When encrypting, this is the 128 bit encryption key. When
1116  *   decrypting, this is the 128 bit decryption key. The decryption key may
1117  *   be generated from the encryption key with CRYPTO_AES_DecryptKey128().
1118  *   If this argument is null, the key will not be loaded, as it is assumed
1119  *   the key has been loaded into KEYHA previously.
1120  *
1121  * @param[in] iv
1122  *   128 bit initialization vector to use.
1123  *
1124  * @param[in] encrypt
1125  *   Set to true to encrypt, false to decrypt.
1126  ******************************************************************************/
CRYPTO_AES_CBC128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt)1127 void CRYPTO_AES_CBC128(CRYPTO_TypeDef *  crypto,
1128                        uint8_t *         out,
1129                        const uint8_t *   in,
1130                        unsigned int      len,
1131                        const uint8_t *   key,
1132                        const uint8_t *   iv,
1133                        bool              encrypt)
1134 {
1135   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1136   CRYPTO_AES_CBCx(crypto, out, in, len, key, iv, encrypt, cryptoKey128Bits);
1137 }
1138 
1139 /***************************************************************************//**
1140  * @brief
1141  *   AES Cipher-block chaining (CBC) cipher mode encryption/decryption, 256 bit
1142  *   key.
1143  *
1144  * @details
1145  *   See CRYPTO_AES_CBC128() for the CBC figure.
1146  *
1147  *   See general comments on layout and byte ordering of parameters.
1148  *
1149  * @param[in]  crypto
1150  *   A pointer to the CRYPTO peripheral register block.
1151  *
1152  * @param[out] out
1153  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1154  *   may be set equal to @p in, in which case the input buffer is overwritten.
1155  *
1156  * @param[in] in
1157  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1158  *
1159  * @param[in] len
1160  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1161  *
1162  * @param[in] key
1163  *   When encrypting, this is the 256 bit encryption key. When
1164  *   decrypting, this is the 256 bit decryption key. The decryption key may
1165  *   be generated from the encryption key with CRYPTO_AES_DecryptKey256().
1166  *
1167  * @param[in] iv
1168  *   128 bit initialization vector to use.
1169  *
1170  * @param[in] encrypt
1171  *   Set to true to encrypt, false to decrypt.
1172  ******************************************************************************/
CRYPTO_AES_CBC256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt)1173 void CRYPTO_AES_CBC256(CRYPTO_TypeDef *  crypto,
1174                        uint8_t *         out,
1175                        const uint8_t *   in,
1176                        unsigned int      len,
1177                        const uint8_t *   key,
1178                        const uint8_t *   iv,
1179                        bool              encrypt)
1180 {
1181   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1182   CRYPTO_AES_CBCx(crypto, out, in, len, key, iv, encrypt, cryptoKey256Bits);
1183 }
1184 
1185 /***************************************************************************//**
1186  * @brief
1187  *   AES Propagating Cipher-block chaining (PCBC) cipher mode encryption/decryption, 128 bit key.
1188  *
1189  * @details
1190  *   Encryption:
1191  * @verbatim
1192  *           Plaintext                  Plaintext
1193  *               |--------------+           |
1194  *               V              V           V
1195  * InitVector ->XOR        +-->XOR-------->XOR
1196  *               |         |                |
1197  *               V         |                V
1198  *       +--------------+  |        +--------------+
1199  * Key ->| Block cipher |  |  Key ->| Block cipher |
1200  *       |  encryption  |  |        |  encryption  |
1201  *       +--------------+  |        +--------------+
1202  *               |---------+                |
1203  *               V                          V
1204  *           Ciphertext                 Ciphertext
1205  * @endverbatim
1206  *   Decryption:
1207  * @verbatim
1208  *         Ciphertext                 Ciphertext
1209  *              |----------+                |
1210  *              V          |                V
1211  *       +--------------+  |        +--------------+
1212  * Key ->| Block cipher |  |  Key ->| Block cipher |
1213  *       |  decryption  |  |        |  decryption  |
1214  *       +--------------+  |        +--------------+
1215  *               |         |               |
1216  *               V         V               V
1217  * InitVector ->XOR  +--->XOR------------>XOR
1218  *               |---+                     |
1219  *               V                         V
1220  *           Plaintext                  Plaintext
1221  * @endverbatim
1222  *   See general comments on layout and byte ordering of parameters.
1223  *
1224  * @param[in]  crypto
1225  *   A pointer to the CRYPTO peripheral register block.
1226  *
1227  * @param[out] out
1228  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1229  *   may be set equal to @p in, in which case the input buffer is overwritten.
1230  *
1231  * @param[in] in
1232  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1233  *
1234  * @param[in] len
1235  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1236  *
1237  * @param[in] key
1238  *   When encrypting, this is the 128 bit encryption key. When
1239  *   decrypting, this is the 128 bit decryption key. The decryption key may
1240  *   be generated from the encryption key with CRYPTO_AES_DecryptKey128().
1241  *   If this argument is null, the key will not be loaded, as it is assumed
1242  *   the key has been loaded into KEYHA previously.
1243  *
1244  * @param[in] iv
1245  *   128 bit initialization vector to use.
1246  *
1247  * @param[in] encrypt
1248  *   Set to true to encrypt, false to decrypt.
1249  ******************************************************************************/
CRYPTO_AES_PCBC128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt)1250 void CRYPTO_AES_PCBC128(CRYPTO_TypeDef * crypto,
1251                         uint8_t *         out,
1252                         const uint8_t *   in,
1253                         unsigned int      len,
1254                         const uint8_t *   key,
1255                         const uint8_t *   iv,
1256                         bool              encrypt)
1257 {
1258   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1259   CRYPTO_AES_PCBCx(crypto, out, in, len, key, iv, encrypt, cryptoKey128Bits);
1260 }
1261 
1262 /***************************************************************************//**
1263  * @brief
1264  *   AES Propagating Cipher-block chaining (PCBC) cipher mode encryption/decryption, 256 bit
1265  *   key.
1266  *
1267  * @details
1268  *   See CRYPTO_AES_PCBC128() for the PCBC figure.
1269  *
1270  *   See general comments on layout and byte ordering of parameters.
1271  *
1272  * @param[in]  crypto
1273  *   A pointer to the CRYPTO peripheral register block.
1274  *
1275  * @param[out] out
1276  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1277  *   may be set equal to @p in, in which case the input buffer is overwritten.
1278  *
1279  * @param[in] in
1280  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1281  *
1282  * @param[in] len
1283  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1284  *
1285  * @param[in] key
1286  *   When encrypting, this is the 256 bit encryption key. When
1287  *   decrypting, this is the 256 bit decryption key. The decryption key may
1288  *   be generated from the encryption key with CRYPTO_AES_DecryptKey256().
1289  *
1290  * @param[in] iv
1291  *   128 bit initialization vector to use.
1292  *
1293  * @param[in] encrypt
1294  *   Set to true to encrypt, false to decrypt.
1295  ******************************************************************************/
CRYPTO_AES_PCBC256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt)1296 void CRYPTO_AES_PCBC256(CRYPTO_TypeDef * crypto,
1297                         uint8_t *         out,
1298                         const uint8_t *   in,
1299                         unsigned int      len,
1300                         const uint8_t *   key,
1301                         const uint8_t *   iv,
1302                         bool              encrypt)
1303 {
1304   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1305   CRYPTO_AES_PCBCx(crypto, out, in, len, key, iv, encrypt, cryptoKey256Bits);
1306 }
1307 
1308 /***************************************************************************//**
1309  * @brief
1310  *   AES Cipher feedback (CFB) cipher mode encryption/decryption, 128 bit key.
1311  *
1312  * @details
1313  *   Encryption:
1314  * @verbatim
1315  *           InitVector    +----------------+
1316  *               |         |                |
1317  *               V         |                V
1318  *       +--------------+  |        +--------------+
1319  * Key ->| Block cipher |  |  Key ->| Block cipher |
1320  *       |  encryption  |  |        |  encryption  |
1321  *       +--------------+  |        +--------------+
1322  *               |         |                |
1323  *               V         |                V
1324  *  Plaintext ->XOR        |   Plaintext ->XOR
1325  *               |---------+                |
1326  *               V                          V
1327  *           Ciphertext                 Ciphertext
1328  * @endverbatim
1329  *   Decryption:
1330  * @verbatim
1331  *          InitVector     +----------------+
1332  *               |         |                |
1333  *               V         |                V
1334  *       +--------------+  |        +--------------+
1335  * Key ->| Block cipher |  |  Key ->| Block cipher |
1336  *       |  encryption  |  |        |  encryption  |
1337  *       +--------------+  |        +--------------+
1338  *               |         |                |
1339  *               V         |                V
1340  *              XOR<- Ciphertext           XOR<- Ciphertext
1341  *               |                          |
1342  *               V                          V
1343  *           Plaintext                  Plaintext
1344  * @endverbatim
1345  *   See general comments on layout and byte ordering of parameters.
1346  *
1347  * @param[in]  crypto
1348  *   A pointer to the CRYPTO peripheral register block.
1349  *
1350  * @param[out] out
1351  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1352  *   may be set equal to @p in, in which case the input buffer is overwritten.
1353  *
1354  * @param[in] in
1355  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1356  *
1357  * @param[in] len
1358  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1359  *
1360  * @param[in] key
1361  *   128 bit encryption key is used for both encryption and decryption modes.
1362  *
1363  * @param[in] iv
1364  *   128 bit initialization vector to use.
1365  *
1366  * @param[in] encrypt
1367  *   Set to true to encrypt, false to decrypt.
1368  ******************************************************************************/
CRYPTO_AES_CFB128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt)1369 void CRYPTO_AES_CFB128(CRYPTO_TypeDef *  crypto,
1370                        uint8_t *         out,
1371                        const uint8_t *   in,
1372                        unsigned int      len,
1373                        const uint8_t *   key,
1374                        const uint8_t *   iv,
1375                        bool              encrypt)
1376 {
1377   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1378   CRYPTO_AES_CFBx(crypto, out, in, len, key, iv, encrypt, cryptoKey128Bits);
1379 }
1380 
1381 /***************************************************************************//**
1382  * @brief
1383  *   AES Cipher feedback (CFB) cipher mode encryption/decryption, 256 bit key.
1384  *
1385  * @details
1386  *   See CRYPTO_AES_CFB128() for the CFB figure.
1387  *
1388  *   See general comments on layout and byte ordering of parameters.
1389  *
1390  * @param[in]  crypto
1391  *   A pointer to the CRYPTO peripheral register block.
1392  *
1393  * @param[out] out
1394  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1395  *   may be set equal to @p in, in which case the input buffer is overwritten.
1396  *
1397  * @param[in] in
1398  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1399  *
1400  * @param[in] len
1401  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1402  *
1403  * @param[in] key
1404  *   256 bit encryption key is used for both encryption and decryption modes.
1405  *
1406  * @param[in] iv
1407  *   128 bit initialization vector to use.
1408  *
1409  * @param[in] encrypt
1410  *   Set to true to encrypt, false to decrypt.
1411  ******************************************************************************/
CRYPTO_AES_CFB256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt)1412 void CRYPTO_AES_CFB256(CRYPTO_TypeDef *  crypto,
1413                        uint8_t *         out,
1414                        const uint8_t *   in,
1415                        unsigned int      len,
1416                        const uint8_t *   key,
1417                        const uint8_t *   iv,
1418                        bool              encrypt)
1419 {
1420   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1421   CRYPTO_AES_CFBx(crypto, out, in, len, key, iv, encrypt, cryptoKey256Bits);
1422 }
1423 
1424 /***************************************************************************//**
1425  * @brief
1426  *   AES Counter (CTR) cipher mode encryption/decryption, 128 bit key.
1427  *
1428  * @details
1429  *   Encryption:
1430  * @verbatim
1431  *           Counter                    Counter
1432  *              |                          |
1433  *              V                          V
1434  *       +--------------+           +--------------+
1435  * Key ->| Block cipher |     Key ->| Block cipher |
1436  *       |  encryption  |           |  encryption  |
1437  *       +--------------+           +--------------+
1438  *              |                          |
1439  * Plaintext ->XOR            Plaintext ->XOR
1440  *              |                          |
1441  *              V                          V
1442  *         Ciphertext                 Ciphertext
1443  * @endverbatim
1444  *   Decryption:
1445  * @verbatim
1446  *           Counter                    Counter
1447  *              |                          |
1448  *              V                          V
1449  *       +--------------+           +--------------+
1450  * Key ->| Block cipher |     Key ->| Block cipher |
1451  *       |  encryption  |           |  encryption  |
1452  *       +--------------+           +--------------+
1453  *               |                          |
1454  * Ciphertext ->XOR           Ciphertext ->XOR
1455  *               |                          |
1456  *               V                          V
1457  *           Plaintext                  Plaintext
1458  * @endverbatim
1459  *   See general comments on layout and byte ordering of parameters.
1460  *
1461  * @param[in]  crypto
1462  *   A pointer to CRYPTO peripheral register block.
1463  *
1464  * @param[out] out
1465  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1466  *   may be set equal to @p in, in which case the input buffer is overwritten.
1467  *
1468  * @param[in] in
1469  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1470  *
1471  * @param[in] len
1472  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1473  *
1474  * @param[in] key
1475  *   128 bit encryption key.
1476  *   If this argument is null, the key will not be loaded, as it is assumed
1477  *   the key has been loaded into KEYHA previously.
1478  *
1479  * @param[in,out] ctr
1480  *   128 bit initial counter value. The counter is updated after each AES
1481  *   block encoding through use of @p ctrFunc.
1482  *
1483  * @param[in] ctrFunc
1484  *   A function used to update the counter value. Not supported by CRYPTO.
1485  *   This parameter is included for backwards compatibility with
1486  *   the EFM32 em_aes.h API.
1487  ******************************************************************************/
CRYPTO_AES_CTR128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,uint8_t * ctr,CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)1488 void CRYPTO_AES_CTR128(CRYPTO_TypeDef *  crypto,
1489                        uint8_t *         out,
1490                        const uint8_t *   in,
1491                        unsigned int      len,
1492                        const uint8_t *   key,
1493                        uint8_t *         ctr,
1494                        CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
1495 {
1496   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1497   CRYPTO_AES_CTRx(crypto, out, in, len, key, ctr, ctrFunc, cryptoKey128Bits);
1498 }
1499 
1500 /***************************************************************************//**
1501  * @brief
1502  *   AES Counter (CTR) cipher mode encryption/decryption, 256 bit key.
1503  *
1504  * @details
1505  *   See CRYPTO_AES_CTR128() for CTR figure.
1506  *
1507  *   See general comments on layout and byte ordering of parameters.
1508  *
1509  * @param[in]  crypto
1510  *   A pointer to the CRYPTO peripheral register block.
1511  *
1512  * @param[out] out
1513  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1514  *   may be set equal to @p in, in which case the input buffer is overwritten.
1515  *
1516  * @param[in] in
1517  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1518  *
1519  * @param[in] len
1520  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1521  *
1522  * @param[in] key
1523  *   256 bit encryption key.
1524  *
1525  * @param[in,out] ctr
1526  *   128 bit initial counter value. The counter is updated after each AES
1527  *   block encoding through use of @p ctrFunc.
1528  *
1529  * @param[in] ctrFunc
1530  *   A function used to update counter value. Not supported by CRYPTO.
1531  *   This parameter is included in order for backwards compatibility with
1532  *   the EFM32 em_aes.h API.
1533  ******************************************************************************/
CRYPTO_AES_CTR256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,uint8_t * ctr,CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)1534 void CRYPTO_AES_CTR256(CRYPTO_TypeDef *  crypto,
1535                        uint8_t *         out,
1536                        const uint8_t *   in,
1537                        unsigned int      len,
1538                        const uint8_t *   key,
1539                        uint8_t *         ctr,
1540                        CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
1541 {
1542   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1543   CRYPTO_AES_CTRx(crypto, out, in, len, key, ctr, ctrFunc, cryptoKey256Bits);
1544 }
1545 
1546 /***************************************************************************//**
1547  * @brief
1548  *   Update the last 32 bits of 128 bit counter by incrementing with 1.
1549  *
1550  * @details
1551  *   Notice that no special consideration is given to the possible wrap around. If
1552  *   32 least significant bits are 0xFFFFFFFF, they will be updated to 0x00000000,
1553  *   ignoring overflow.
1554  *
1555  *   See general comments on layout and byte ordering of parameters.
1556  *
1557  * @param[in,out] ctr
1558  *   A buffer holding 128 bit counter to be updated.
1559  ******************************************************************************/
CRYPTO_AES_CTRUpdate32Bit(uint8_t * ctr)1560 void CRYPTO_AES_CTRUpdate32Bit(uint8_t * ctr)
1561 {
1562   uint32_t * _ctr = (uint32_t *) ctr;
1563 
1564   _ctr[3] = __REV(__REV(_ctr[3]) + 1U);
1565 }
1566 
1567 /***************************************************************************//**
1568  * @brief
1569  *   Generate 128 bit AES decryption key from 128 bit encryption key. The
1570  *   decryption key is used for some cipher modes when decrypting.
1571  *
1572  * @details
1573  *   See general comments on layout and byte ordering of parameters.
1574  *
1575  * @param[in]  crypto
1576  *   A pointer to the CRYPTO peripheral register block.
1577  *
1578  * @param[out] out
1579  *   A buffer to place 128 bit decryption key. Must be at least 16 bytes long. It
1580  *   may be set equal to @p in, in which case the input buffer is overwritten.
1581  *
1582  * @param[in] in
1583  *   A buffer holding 128 bit encryption key. Must be at least 16 bytes long.
1584  ******************************************************************************/
CRYPTO_AES_DecryptKey128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in)1585 void CRYPTO_AES_DecryptKey128(CRYPTO_TypeDef *  crypto,
1586                               uint8_t *         out,
1587                               const uint8_t *   in)
1588 {
1589   /* Setup CRYPTO in AES-128 mode. */
1590   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1591 
1592   /* Load key */
1593   CRYPTO_DataWriteUnaligned(&crypto->KEYBUF, in);
1594 
1595   /* Do dummy encryption to generate decrypt key */
1596   crypto->CMD = CRYPTO_CMD_INSTR_AESENC;
1597 
1598   /* Wait for the instruction to finish. */
1599   CRYPTO_InstructionSequenceWait(crypto);
1600 
1601   /* Save decryption key */
1602   CRYPTO_DataReadUnaligned(&crypto->KEY, out);
1603 }
1604 
1605 /***************************************************************************//**
1606  * @brief
1607  *   Generate 256 bit AES decryption key from 256 bit encryption key. The
1608  *   decryption key is used for some cipher modes when decrypting.
1609  *
1610  * @details
1611  *   See general comments on layout and byte ordering of parameters.
1612  *
1613  * @param[in]  crypto
1614  *   A pointer to the CRYPTO peripheral register block.
1615  *
1616  * @param[out] out
1617  *   A buffer to place 256 bit decryption key. Must be at least 32 bytes long. It
1618  *   may be set equal to @p in, in which case the input buffer is overwritten.
1619  *
1620  * @param[in] in
1621  *   A buffer holding 256 bit encryption key. Must be at least 32 bytes long.
1622  ******************************************************************************/
CRYPTO_AES_DecryptKey256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in)1623 void CRYPTO_AES_DecryptKey256(CRYPTO_TypeDef *  crypto,
1624                               uint8_t *         out,
1625                               const uint8_t *   in)
1626 {
1627   /* Set up CRYPTO in AES-256 mode. */
1628   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1629 
1630   /* Load the key. */
1631   CRYPTO_DataWriteUnaligned(&crypto->KEYBUF, in);
1632   CRYPTO_DataWriteUnaligned(&crypto->KEYBUF, &in[16]);
1633 
1634   /* Do dummy encryption to generate a decrypt key. */
1635   crypto->CMD = CRYPTO_CMD_INSTR_AESENC;
1636 
1637   /* Wait for the instruction to finish. */
1638   CRYPTO_InstructionSequenceWait(crypto);
1639 
1640   /* Save the decryption key. */
1641   CRYPTO_DataReadUnaligned(&crypto->KEY, out);
1642   CRYPTO_DataReadUnaligned(&crypto->KEY, &out[16]);
1643 }
1644 
1645 /***************************************************************************//**
1646  * @brief
1647  *   AES Electronic Codebook (ECB) cipher mode encryption/decryption,
1648  *   128 bit key.
1649  *
1650  * @details
1651  *   Encryption:
1652  * @verbatim
1653  *          Plaintext                  Plaintext
1654  *              |                          |
1655  *              V                          V
1656  *       +--------------+           +--------------+
1657  * Key ->| Block cipher |     Key ->| Block cipher |
1658  *       |  encryption  |           |  encryption  |
1659  *       +--------------+           +--------------+
1660  *              |                          |
1661  *              V                          V
1662  *         Ciphertext                 Ciphertext
1663  * @endverbatim
1664  *   Decryption:
1665  * @verbatim
1666  *         Ciphertext                 Ciphertext
1667  *              |                          |
1668  *              V                          V
1669  *       +--------------+           +--------------+
1670  * Key ->| Block cipher |     Key ->| Block cipher |
1671  *       |  decryption  |           |  decryption  |
1672  *       +--------------+           +--------------+
1673  *              |                          |
1674  *              V                          V
1675  *          Plaintext                  Plaintext
1676  * @endverbatim
1677  *   See general comments on layout and byte ordering of parameters.
1678  *
1679  * @param[in]  crypto
1680  *   A pointer to the CRYPTO peripheral register block.
1681  *
1682  * @param[out] out
1683  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1684  *   may be set equal to @p in, in which case the input buffer is overwritten.
1685  *
1686  * @param[in] in
1687  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1688  *
1689  * @param[in] len
1690  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1691  *
1692  * @param[in] key
1693  *   When encrypting, this is the 128 bit encryption key. When
1694  *   decrypting, this is the 128 bit decryption key. The decryption key may
1695  *   be generated from the encryption key with CRYPTO_AES_DecryptKey128().
1696  *
1697  * @param[in] encrypt
1698  *   Set to true to encrypt, false to decrypt.
1699  ******************************************************************************/
CRYPTO_AES_ECB128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,bool encrypt)1700 void CRYPTO_AES_ECB128(CRYPTO_TypeDef *  crypto,
1701                        uint8_t *         out,
1702                        const uint8_t *   in,
1703                        unsigned int      len,
1704                        const uint8_t *   key,
1705                        bool              encrypt)
1706 {
1707   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1708   CRYPTO_AES_ECBx(crypto, out, in, len, key, encrypt, cryptoKey128Bits);
1709 }
1710 
1711 /***************************************************************************//**
1712  * @brief
1713  *   AES Electronic Codebook (ECB) cipher mode encryption/decryption,
1714  *   256 bit key.
1715  *
1716  * @details
1717  *   See CRYPTO_AES_ECB128() for ECB figure.
1718  *
1719  *   See general comments on layout and byte ordering of parameters.
1720  *
1721  * @param[in]  crypto
1722  *   A pointer to the CRYPTO peripheral register block.
1723  *
1724  * @param[out] out
1725  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1726  *   may be set equal to @p in, in which case the input buffer is overwritten.
1727  *
1728  * @param[in] in
1729  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1730  *
1731  * @param[in] len
1732  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1733  *
1734  * @param[in] key
1735  *   When encrypting, this is the 256 bit encryption key. When
1736  *   decrypting, this is the 256 bit decryption key. The decryption key may
1737  *   be generated from the encryption key with CRYPTO_AES_DecryptKey256().
1738  *
1739  * @param[in] encrypt
1740  *   Set to true to encrypt, false to decrypt.
1741  ******************************************************************************/
CRYPTO_AES_ECB256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,bool encrypt)1742 void CRYPTO_AES_ECB256(CRYPTO_TypeDef *  crypto,
1743                        uint8_t *         out,
1744                        const uint8_t *   in,
1745                        unsigned int      len,
1746                        const uint8_t *   key,
1747                        bool              encrypt)
1748 {
1749   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1750   CRYPTO_AES_ECBx(crypto, out, in, len, key, encrypt, cryptoKey256Bits);
1751 }
1752 
1753 /***************************************************************************//**
1754  * @brief
1755  *   AES Output feedback (OFB) cipher mode encryption/decryption, 128 bit key.
1756  *
1757  * @details
1758  *   Encryption:
1759  * @verbatim
1760  *          InitVector    +----------------+
1761  *              |         |                |
1762  *              V         |                V
1763  *       +--------------+ |        +--------------+
1764  * Key ->| Block cipher | |  Key ->| Block cipher |
1765  *       |  encryption  | |        |  encryption  |
1766  *       +--------------+ |        +--------------+
1767  *              |         |                |
1768  *              |---------+                |
1769  *              V                          V
1770  * Plaintext ->XOR            Plaintext ->XOR
1771  *              |                          |
1772  *              V                          V
1773  *         Ciphertext                 Ciphertext
1774  * @endverbatim
1775  *   Decryption:
1776  * @verbatim
1777  *          InitVector    +----------------+
1778  *              |         |                |
1779  *              V         |                V
1780  *       +--------------+ |        +--------------+
1781  * Key ->| Block cipher | |  Key ->| Block cipher |
1782  *       |  encryption  | |        |  encryption  |
1783  *       +--------------+ |        +--------------+
1784  *              |         |                |
1785  *              |---------+                |
1786  *              V                          V
1787  * Ciphertext ->XOR           Ciphertext ->XOR
1788  *              |                          |
1789  *              V                          V
1790  *          Plaintext                  Plaintext
1791  * @endverbatim
1792  *   See general comments on layout and byte ordering of parameters.
1793  *
1794  * @param[in]  crypto
1795  *   A pointer to the CRYPTO peripheral register block.
1796  *
1797  * @param[out] out
1798  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1799  *   may be set equal to @p in, in which case the input buffer is overwritten.
1800  *
1801  * @param[in] in
1802  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1803  *
1804  * @param[in] len
1805  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1806  *
1807  * @param[in] key
1808  *   128 bit encryption key.
1809  *
1810  * @param[in] iv
1811  *   128 bit initialization vector to use.
1812  ******************************************************************************/
CRYPTO_AES_OFB128(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv)1813 void CRYPTO_AES_OFB128(CRYPTO_TypeDef *  crypto,
1814                        uint8_t *         out,
1815                        const uint8_t *   in,
1816                        unsigned int      len,
1817                        const uint8_t *   key,
1818                        const uint8_t *   iv)
1819 {
1820   crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1821   CRYPTO_AES_OFBx(crypto, out, in, len, key, iv, cryptoKey128Bits);
1822 }
1823 
1824 /***************************************************************************//**
1825  * @brief
1826  *   AES Output feedback (OFB) cipher mode encryption/decryption, 256 bit key.
1827  *
1828  * @details
1829  *   See CRYPTO_AES_OFB128() for OFB figure.
1830  *
1831  *   See general comments on layout and byte ordering of parameters.
1832  *
1833  * @param[in]  crypto
1834  *   A pointer to CRYPTO peripheral register block.
1835  *
1836  * @param[out] out
1837  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1838  *   may be set equal to @p in, in which case the input buffer is overwritten.
1839  *
1840  * @param[in] in
1841  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1842  *
1843  * @param[in] len
1844  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1845  *
1846  * @param[in] key
1847  *   256 bit encryption key.
1848  *
1849  * @param[in] iv
1850  *   128 bit initialization vector to use.
1851  ******************************************************************************/
CRYPTO_AES_OFB256(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv)1852 void CRYPTO_AES_OFB256(CRYPTO_TypeDef *  crypto,
1853                        uint8_t *         out,
1854                        const uint8_t *   in,
1855                        unsigned int      len,
1856                        const uint8_t *   key,
1857                        const uint8_t *   iv)
1858 {
1859   crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1860   CRYPTO_AES_OFBx(crypto, out, in, len, key, iv, cryptoKey256Bits);
1861 }
1862 
1863 /*******************************************************************************
1864  **************************   LOCAL FUNCTIONS   *******************************
1865  ******************************************************************************/
1866 
1867 /***************************************************************************//**
1868  * @brief
1869  *   Cipher-block chaining (CBC) cipher mode encryption/decryption, 128/256 bit key.
1870  *
1871  * @details
1872  *   See CRYPTO_AES_CBC128() for CBC figure.
1873  *
1874  *   See general comments on layout and byte ordering of parameters.
1875  *
1876  * @param[in]  crypto
1877  *   A pointer to the CRYPTO peripheral register block.
1878  *
1879  * @param[out] out
1880  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1881  *   may be set equal to @p in, in which case the input buffer is overwritten.
1882  *
1883  * @param[in] in
1884  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1885  *
1886  * @param[in] len
1887  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1888  *
1889  * @param[in] key
1890  *   When encrypting, this is the 256 bit encryption key. When
1891  *   decrypting, this is the 256 bit decryption key. The decryption key may
1892  *   be generated from the encryption key with CRYPTO_AES_DecryptKey256().
1893  *
1894  * @param[in] iv
1895  *   128 bit initialization vector to use.
1896  *
1897  * @param[in] encrypt
1898  *   Set to true to encrypt, false to decrypt.
1899  *
1900  * @param[in] keyWidth
1901  *   Set to cryptoKey128Bits or cryptoKey256Bits.
1902  ******************************************************************************/
CRYPTO_AES_CBCx(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt,CRYPTO_KeyWidth_TypeDef keyWidth)1903 static void CRYPTO_AES_CBCx(CRYPTO_TypeDef *  crypto,
1904                             uint8_t *         out,
1905                             const uint8_t *   in,
1906                             unsigned int      len,
1907                             const uint8_t *   key,
1908                             const uint8_t *   iv,
1909                             bool              encrypt,
1910                             CRYPTO_KeyWidth_TypeDef keyWidth)
1911 {
1912   EFM_ASSERT((len % CRYPTO_AES_BLOCKSIZE) == 0U);
1913 
1914   /* Initialize control registers. */
1915   crypto->WAC = 0;
1916 
1917   CRYPTO_KeyBufWriteUnaligned(crypto, key, keyWidth);
1918 
1919   if (encrypt) {
1920     CRYPTO_DataWriteUnaligned(&crypto->DATA0, iv);
1921 
1922     CRYPTO_SEQ_LOAD_2(crypto,
1923                       CRYPTO_CMD_INSTR_DATA1TODATA0XOR,
1924                       CRYPTO_CMD_INSTR_AESENC);
1925   } else {
1926     CRYPTO_DataWriteUnaligned(&crypto->DATA2, iv);
1927 
1928     CRYPTO_SEQ_LOAD_4(crypto,
1929                       CRYPTO_CMD_INSTR_DATA1TODATA0,
1930                       CRYPTO_CMD_INSTR_AESDEC,
1931                       CRYPTO_CMD_INSTR_DATA2TODATA0XOR,
1932                       CRYPTO_CMD_INSTR_DATA1TODATA2);
1933   }
1934 
1935   CRYPTO_AES_ProcessLoop(crypto, len,
1936                          &crypto->DATA1, in,
1937                          &crypto->DATA0, out);
1938 }
1939 
1940 /***************************************************************************//**
1941  * @brief
1942  *   Propagating cipher-block chaining (PCBC) cipher mode encryption/decryption, 128/256 bit key.
1943  *
1944  * @details
1945  *   See CRYPTO_AES_PCBC128() for PCBC figure.
1946  *
1947  *   See general comments on layout and byte ordering of parameters.
1948  *
1949  * @param[in]  crypto
1950  *   A pointer to the CRYPTO peripheral register block.
1951  *
1952  * @param[out] out
1953  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
1954  *   may be set equal to @p in, in which case the input buffer is overwritten.
1955  *
1956  * @param[in] in
1957  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
1958  *
1959  * @param[in] len
1960  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
1961  *
1962  * @param[in] key
1963  *   When encrypting, this is the 256 bit encryption key. When
1964  *   decrypting, this is the 256 bit decryption key. The decryption key may
1965  *   be generated from the encryption key with CRYPTO_AES_DecryptKey256().
1966  *
1967  * @param[in] iv
1968  *   128 bit initialization vector to use.
1969  *
1970  * @param[in] encrypt
1971  *   Set to true to encrypt, false to decrypt.
1972  *
1973  * @param[in] keyWidth
1974  *   Set to cryptoKey128Bits or cryptoKey256Bits.
1975  ******************************************************************************/
CRYPTO_AES_PCBCx(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt,CRYPTO_KeyWidth_TypeDef keyWidth)1976 static void CRYPTO_AES_PCBCx(CRYPTO_TypeDef * crypto,
1977                              uint8_t *         out,
1978                              const uint8_t *   in,
1979                              unsigned int      len,
1980                              const uint8_t *   key,
1981                              const uint8_t *   iv,
1982                              bool              encrypt,
1983                              CRYPTO_KeyWidth_TypeDef keyWidth)
1984 {
1985   EFM_ASSERT((len % CRYPTO_AES_BLOCKSIZE) == 0U);
1986 
1987   /* Initialize control registers. */
1988   crypto->WAC = 0;
1989 
1990   CRYPTO_KeyBufWriteUnaligned(crypto, key, keyWidth);
1991   CRYPTO_DataWriteUnaligned(&crypto->DATA0, iv);
1992 
1993   if (encrypt) {
1994     CRYPTO_SEQ_LOAD_4(crypto,
1995                       CRYPTO_CMD_INSTR_DATA1TODATA0XOR,
1996                       CRYPTO_CMD_INSTR_AESENC,
1997                       CRYPTO_CMD_INSTR_DATA0TODATA2,
1998                       CRYPTO_CMD_INSTR_DATA1TODATA0XOR);
1999   } else {
2000     CRYPTO_SEQ_LOAD_6(crypto,
2001                       CRYPTO_CMD_INSTR_DATA0TODATA3,
2002                       CRYPTO_CMD_INSTR_DATA1TODATA0,
2003                       CRYPTO_CMD_INSTR_AESDEC,
2004                       CRYPTO_CMD_INSTR_DATA3TODATA0XOR,
2005                       CRYPTO_CMD_INSTR_DATA0TODATA2,
2006                       CRYPTO_CMD_INSTR_DATA1TODATA0XOR);
2007   }
2008 
2009   CRYPTO_AES_ProcessLoop(crypto, len,
2010                          &crypto->DATA1, in,
2011                          &crypto->DATA2, out);
2012 }
2013 
2014 /***************************************************************************//**
2015  * @brief
2016  *   Cipher feedback (CFB) cipher mode encryption/decryption, 128/256 bit key.
2017  *
2018  * @details
2019  *   See CRYPTO_AES_CFB128() for CFB figure.
2020  *
2021  *   See general comments on layout and byte ordering of parameters.
2022  *
2023  * @param[in]  crypto
2024  *   A pointer to the CRYPTO peripheral register block.
2025  *
2026  * @param[out] out
2027  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
2028  *   may be set equal to @p in, in which case the input buffer is overwritten.
2029  *
2030  * @param[in] in
2031  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
2032  *
2033  * @param[in] len
2034  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
2035  *
2036  * @param[in] key
2037  *   256 bit encryption key is used for both encryption and decryption modes.
2038  *
2039  * @param[in] iv
2040  *   128 bit initialization vector to use.
2041  *
2042  * @param[in] encrypt
2043  *   Set to true to encrypt, false to decrypt.
2044  *
2045  * @param[in] keyWidth
2046  *   Set to cryptoKey128Bits or cryptoKey256Bits.
2047  ******************************************************************************/
CRYPTO_AES_CFBx(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,bool encrypt,CRYPTO_KeyWidth_TypeDef keyWidth)2048 static void CRYPTO_AES_CFBx(CRYPTO_TypeDef *  crypto,
2049                             uint8_t *         out,
2050                             const uint8_t *   in,
2051                             unsigned int      len,
2052                             const uint8_t *   key,
2053                             const uint8_t *   iv,
2054                             bool              encrypt,
2055                             CRYPTO_KeyWidth_TypeDef keyWidth)
2056 {
2057   EFM_ASSERT((len % CRYPTO_AES_BLOCKSIZE) == 0U);
2058 
2059   /* Initialize control registers. */
2060   crypto->WAC = 0;
2061 
2062   /* Load the key. */
2063   CRYPTO_KeyBufWriteUnaligned(crypto, key, keyWidth);
2064 
2065   /* Load instructions to the CRYPTO sequencer. */
2066   if (encrypt) {
2067     /* Load IV */
2068     CRYPTO_DataWriteUnaligned(&crypto->DATA0, iv);
2069 
2070     CRYPTO_SEQ_LOAD_2(crypto,
2071                       CRYPTO_CMD_INSTR_AESENC,
2072                       CRYPTO_CMD_INSTR_DATA1TODATA0XOR);
2073   } else {
2074     /* Load IV */
2075     CRYPTO_DataWriteUnaligned(&crypto->DATA2, iv);
2076 
2077     CRYPTO_SEQ_LOAD_4(crypto,
2078                       CRYPTO_CMD_INSTR_DATA2TODATA0,
2079                       CRYPTO_CMD_INSTR_AESENC,
2080                       CRYPTO_CMD_INSTR_DATA1TODATA0XOR,
2081                       CRYPTO_CMD_INSTR_DATA1TODATA2);
2082   }
2083 
2084   CRYPTO_AES_ProcessLoop(crypto, len,
2085                          &crypto->DATA1, in,
2086                          &crypto->DATA0, out);
2087 }
2088 
2089 /***************************************************************************//**
2090  * @brief
2091  *   Counter (CTR) cipher mode encryption/decryption, 128/256 bit key.
2092  *
2093  * @details
2094  *   See CRYPTO_AES_CTR128() for CTR figure.
2095  *
2096  *   See general comments on layout and byte ordering of parameters.
2097  *
2098  * @param[in]  crypto
2099  *   A pointer to the CRYPTO peripheral register block.
2100  *
2101  * @param[out] out
2102  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
2103  *   may be set equal to @p in, in which case the input buffer is overwritten.
2104  *
2105  * @param[in] in
2106  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
2107  *
2108  * @param[in] len
2109  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
2110  *
2111  * @param[in] key
2112  *   256 bit encryption key.
2113  *
2114  * @param[in,out] ctr
2115  *   128 bit initial counter value. The counter is updated after each AES
2116  *   block encoding through use of @p ctrFunc.
2117  *
2118  * @param[in] ctrFunc
2119  *   A function used to update counter value. Not supported by CRYPTO.
2120  *   This parameter is included for backwards compatibility with
2121  *   the EFM32 em_aes.h API.
2122  *
2123  * @param[in] keyWidth
2124  *   Set to cryptoKey128Bits or cryptoKey256Bits.
2125  ******************************************************************************/
CRYPTO_AES_CTRx(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,uint8_t * ctr,CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,CRYPTO_KeyWidth_TypeDef keyWidth)2126 static void CRYPTO_AES_CTRx(CRYPTO_TypeDef *  crypto,
2127                             uint8_t *         out,
2128                             const uint8_t *   in,
2129                             unsigned int      len,
2130                             const uint8_t *   key,
2131                             uint8_t *         ctr,
2132                             CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,
2133                             CRYPTO_KeyWidth_TypeDef keyWidth)
2134 {
2135   (void) ctrFunc;
2136 
2137   EFM_ASSERT((len % CRYPTO_AES_BLOCKSIZE) == 0U);
2138 
2139   /* Initialize control registers. */
2140   crypto->CTRL |= CRYPTO_CTRL_INCWIDTH_INCWIDTH4;
2141   crypto->WAC   = 0;
2142 
2143   CRYPTO_KeyBufWriteUnaligned(crypto, key, keyWidth);
2144 
2145   CRYPTO_DataWriteUnaligned(&crypto->DATA1, ctr);
2146 
2147   CRYPTO_SEQ_LOAD_4(crypto,
2148                     CRYPTO_CMD_INSTR_DATA1TODATA0,
2149                     CRYPTO_CMD_INSTR_AESENC,
2150                     CRYPTO_CMD_INSTR_DATA1INC,
2151                     CRYPTO_CMD_INSTR_DATA2TODATA0XOR);
2152 
2153   CRYPTO_AES_ProcessLoop(crypto, len,
2154                          &crypto->DATA2, in,
2155                          &crypto->DATA0, out);
2156 
2157   CRYPTO_DataReadUnaligned(&crypto->DATA1, ctr);
2158 }
2159 
2160 /***************************************************************************//**
2161  * @brief
2162  *   Electronic Codebook (ECB) cipher mode encryption/decryption, 128/256 bit key.
2163  *
2164  * @details
2165  *   See CRYPTO_AES_ECB128() for ECB figure.
2166  *
2167  *   See general comments on layout and byte ordering of parameters.
2168  *
2169  * @param[in]  crypto
2170  *   A pointer to the CRYPTO peripheral register block.
2171  *
2172  * @param[out] out
2173  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
2174  *   may be set equal to @p in, in which case the input buffer is overwritten.
2175  *
2176  * @param[in] in
2177  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
2178  *
2179  * @param[in] len
2180  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
2181  *
2182  * @param[in] key
2183  *   When encrypting, this is the 256 bit encryption key. When
2184  *   decrypting, this is the 256 bit decryption key. The decryption key may
2185  *   be generated from the encryption key with CRYPTO_AES_DecryptKey256().
2186  *
2187  * @param[in] encrypt
2188  *   Set to true to encrypt, false to decrypt.
2189  *
2190  * @param[in] keyWidth
2191  *   Set to cryptoKey128Bits or cryptoKey256Bits.
2192  ******************************************************************************/
CRYPTO_AES_ECBx(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,bool encrypt,CRYPTO_KeyWidth_TypeDef keyWidth)2193 static void CRYPTO_AES_ECBx(CRYPTO_TypeDef *  crypto,
2194                             uint8_t *         out,
2195                             const uint8_t *   in,
2196                             unsigned int      len,
2197                             const uint8_t *   key,
2198                             bool              encrypt,
2199                             CRYPTO_KeyWidth_TypeDef keyWidth)
2200 {
2201   EFM_ASSERT((len % CRYPTO_AES_BLOCKSIZE) == 0U);
2202 
2203   crypto->WAC = 0;
2204 
2205   CRYPTO_KeyBufWriteUnaligned(crypto, key, keyWidth);
2206 
2207   if (encrypt) {
2208     CRYPTO_SEQ_LOAD_2(crypto,
2209                       CRYPTO_CMD_INSTR_AESENC,
2210                       CRYPTO_CMD_INSTR_DATA0TODATA1);
2211   } else {
2212     CRYPTO_SEQ_LOAD_2(crypto,
2213                       CRYPTO_CMD_INSTR_AESDEC,
2214                       CRYPTO_CMD_INSTR_DATA0TODATA1);
2215   }
2216 
2217   CRYPTO_AES_ProcessLoop(crypto, len,
2218                          &crypto->DATA0, in,
2219                          &crypto->DATA1, out);
2220 }
2221 
2222 /***************************************************************************//**
2223  * @brief
2224  *   Output feedback (OFB) cipher mode encryption/decryption, 128/256 bit key.
2225  *
2226  * @details
2227  *   See CRYPTO_AES_OFB128() for OFB figure.
2228  *
2229  *   See general comments on layout and byte ordering of parameters.
2230  *
2231  * @param[in]  crypto
2232  *   A pointer to CRYPTO peripheral register block.
2233  *
2234  * @param[out] out
2235  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
2236  *   may be set equal to @p in, in which case the input buffer is overwritten.
2237  *
2238  * @param[in] in
2239  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
2240  *
2241  * @param[in] len
2242  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
2243  *
2244  * @param[in] key
2245  *   256 bit encryption key.
2246  *
2247  * @param[in] iv
2248  *   128 bit initialization vector to use.
2249  *
2250  * @param[in] keyWidth
2251  *   Set to cryptoKey128Bits or cryptoKey256Bits.
2252  ******************************************************************************/
CRYPTO_AES_OFBx(CRYPTO_TypeDef * crypto,uint8_t * out,const uint8_t * in,unsigned int len,const uint8_t * key,const uint8_t * iv,CRYPTO_KeyWidth_TypeDef keyWidth)2253 static void CRYPTO_AES_OFBx(CRYPTO_TypeDef *  crypto,
2254                             uint8_t *         out,
2255                             const uint8_t *   in,
2256                             unsigned int      len,
2257                             const uint8_t *   key,
2258                             const uint8_t *   iv,
2259                             CRYPTO_KeyWidth_TypeDef keyWidth)
2260 {
2261   EFM_ASSERT((len % CRYPTO_AES_BLOCKSIZE) == 0U);
2262 
2263   crypto->WAC = 0;
2264 
2265   CRYPTO_KeyBufWriteUnaligned(crypto, key, keyWidth);
2266 
2267   CRYPTO_DataWriteUnaligned(&crypto->DATA2, iv);
2268 
2269   CRYPTO_SEQ_LOAD_6(crypto,
2270                     CRYPTO_CMD_INSTR_DATA0TODATA1,
2271                     CRYPTO_CMD_INSTR_DATA2TODATA0,
2272                     CRYPTO_CMD_INSTR_AESENC,
2273                     CRYPTO_CMD_INSTR_DATA0TODATA2,
2274                     CRYPTO_CMD_INSTR_DATA1TODATA0XOR,
2275                     CRYPTO_CMD_INSTR_DATA0TODATA1);
2276 
2277   CRYPTO_AES_ProcessLoop(crypto, len,
2278                          &crypto->DATA0, in,
2279                          &crypto->DATA1, out);
2280 }
2281 
2282 /***************************************************************************//**
2283  * @brief
2284  *   Perform generic AES loop.
2285  *
2286  * @details
2287  *   Function loads given register with provided input data. Triggers CRYPTO to
2288  *   perform sequence of instructions and read specified output register to
2289  *   output buffer.
2290  *
2291  * @param[in]  crypto
2292  *   A pointer to the CRYPTO peripheral register block.
2293  *
2294  * @param[in] len
2295  *   A number of bytes to encrypt/decrypt. Must be a multiple of 16.
2296  *
2297  * @param[in] inReg
2298  *   An input register - one of DATA0,DATA1,DATA2,DATA3
2299  *
2300  * @param[in] in
2301  *   A buffer holding data to encrypt/decrypt. Must be at least @p len long.
2302  *
2303  * @param[in] outReg
2304  *   An output register - one of DATA0,DATA1,DATA2,DATA3
2305  *
2306  * @param[out] out
2307  *   A buffer to place encrypted/decrypted data. Must be at least @p len long. It
2308  *   may be set equal to @p in, in which case the input buffer is overwritten.
2309  ******************************************************************************/
CRYPTO_AES_ProcessLoop(CRYPTO_TypeDef * crypto,unsigned int len,CRYPTO_DataReg_TypeDef inReg,const uint8_t * in,CRYPTO_DataReg_TypeDef outReg,uint8_t * out)2310 __STATIC_INLINE void CRYPTO_AES_ProcessLoop(CRYPTO_TypeDef *        crypto,
2311                                             unsigned int            len,
2312                                             CRYPTO_DataReg_TypeDef  inReg,
2313                                             const uint8_t  *        in,
2314                                             CRYPTO_DataReg_TypeDef  outReg,
2315                                             uint8_t *               out)
2316 {
2317   len /= CRYPTO_AES_BLOCKSIZE;
2318   crypto->SEQCTRL = 16UL << _CRYPTO_SEQCTRL_LENGTHA_SHIFT;
2319 
2320   if (((uintptr_t)in & 0x3) || ((uintptr_t)out & 0x3)) {
2321     while (len > 0UL) {
2322       len--;
2323       /* Load data and trigger encryption. */
2324       CRYPTO_DataWriteUnaligned(inReg, in);
2325       CRYPTO_InstructionSequenceExecute(crypto);
2326 
2327       /* Wait for the sequence to finish. */
2328       CRYPTO_InstructionSequenceWait(crypto);
2329       /* Save encrypted/decrypted data. */
2330       CRYPTO_DataReadUnaligned(outReg, out);
2331 
2332       out += 16;
2333       in  += 16;
2334     }
2335   } else {
2336     /* Optimized version, 15% faster for -O3. */
2337     if (len > 0UL) {
2338       /* Load first data and trigger encryption. */
2339       CRYPTO_DataWrite(inReg, (uint32_t *)in);
2340       CRYPTO_InstructionSequenceExecute(crypto);
2341 
2342       /* Do loop administration while CRYPTO engine is working. */
2343       in += 16;
2344       len--;
2345 
2346       while (len > 0UL) {
2347         /* Wait for the sequence to finish. */
2348         CRYPTO_InstructionSequenceWait(crypto);
2349         /* Save encrypted/decrypted data. */
2350         CRYPTO_DataRead(outReg, (uint32_t *)out);
2351 
2352         /* Load next data and retrigger encryption asap. */
2353         CRYPTO_DataWrite(inReg, (uint32_t *)in);
2354         CRYPTO_InstructionSequenceExecute(crypto);
2355 
2356         /* Do loop administration while CRYPTO engine is working. */
2357         out += 16;
2358         in += 16;
2359         len--;
2360       }
2361 
2362       /* Wait for the sequence to finish. */
2363       CRYPTO_InstructionSequenceWait(crypto);
2364       /* Save last encrypted/decrypted data. */
2365       CRYPTO_DataRead(outReg, (uint32_t *)out);
2366     }
2367   }
2368 }
2369 
2370 /** @} (end addtogroup crypto) */
2371 
2372 #endif /* defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
2373