EFM32 Gecko Software Documentation  efm32g-doc-5.1.2
em_crypto.c
Go to the documentation of this file.
1 /***************************************************************************/
32 #include "em_device.h"
33 
34 #if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
35 
36 #include "em_crypto.h"
37 #include "em_assert.h"
38 
39 /***************************************************************************/
44 /***************************************************************************/
49 /*******************************************************************************
50  ******************************* DEFINES ***********************************
51  ******************************************************************************/
52 
55 #define CRYPTO_INSTRUCTIONS_PER_REG (4)
56 #define CRYPTO_INSTRUCTIONS_MAX (12)
57 #define CRYPTO_INSTRUCTION_REGS (CRYPTO_INSTRUCTIONS_MAX/CRYPTO_INSTRUCTIONS_PER_REG)
58 
59 #define CRYPTO_SHA1_BLOCK_SIZE_IN_BITS (512)
60 #define CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES (CRYPTO_SHA1_BLOCK_SIZE_IN_BITS/8)
61 #define CRYPTO_SHA1_BLOCK_SIZE_IN_32BIT_WORDS (CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES/sizeof(uint32_t))
62 #define CRYPTO_SHA1_DIGEST_SIZE_IN_32BIT_WORDS (CRYPTO_SHA1_DIGEST_SIZE_IN_BYTES/sizeof(uint32_t))
63 
64 #define CRYPTO_SHA256_BLOCK_SIZE_IN_BITS (512)
65 #define CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES (CRYPTO_SHA256_BLOCK_SIZE_IN_BITS/8)
66 #define CRYPTO_SHA256_BLOCK_SIZE_IN_32BIT_WORDS (CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES/sizeof(uint32_t))
67 
68 #define CRYPTO_SHA256_DIGEST_SIZE_IN_32BIT_WORDS (CRYPTO_SHA256_DIGEST_SIZE_IN_BYTES/sizeof(uint32_t))
69 
70 #define PARTIAL_OPERAND_WIDTH_LOG2 (7) /* 2^7 = 128 */
71 #define PARTIAL_OPERAND_WIDTH (1<<PARTIAL_OPERAND_WIDTH_LOG2)
72 #define PARTIAL_OPERAND_WIDTH_MASK (PARTIAL_OPERAND_WIDTH-1)
73 #define PARTIAL_OPERAND_WIDTH_IN_BYTES (PARTIAL_OPERAND_WIDTH/8)
74 #define PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS (PARTIAL_OPERAND_WIDTH_IN_BYTES/sizeof(uint32_t))
75 
76 #define SWAP32(x) (__REV(x))
77 
78 #define CRYPTO_AES_BLOCKSIZE (16)
79 
80 /*******************************************************************************
81  *********************** STATIC FUNCTIONS **********************************
82  ******************************************************************************/
83 
84 static inline void CRYPTO_AES_ProcessLoop(CRYPTO_TypeDef *crypto,
85  uint32_t len,
86  CRYPTO_DataReg_TypeDef inReg,
87  uint32_t * in,
88  CRYPTO_DataReg_TypeDef outReg,
89  uint32_t * out);
90 
91 static void CRYPTO_AES_CBCx(CRYPTO_TypeDef *crypto,
92  uint8_t * out,
93  const uint8_t * in,
94  unsigned int len,
95  const uint8_t * key,
96  const uint8_t * iv,
97  bool encrypt,
98  CRYPTO_KeyWidth_TypeDef keyWidth);
99 
100 static void CRYPTO_AES_CFBx(CRYPTO_TypeDef *crypto,
101  uint8_t * out,
102  const uint8_t * in,
103  unsigned int len,
104  const uint8_t * key,
105  const uint8_t * iv,
106  bool encrypt,
107  CRYPTO_KeyWidth_TypeDef keyWidth);
108 
109 static void CRYPTO_AES_CTRx(CRYPTO_TypeDef *crypto,
110  uint8_t * out,
111  const uint8_t * in,
112  unsigned int len,
113  const uint8_t * key,
114  uint8_t * ctr,
115  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,
116  CRYPTO_KeyWidth_TypeDef keyWidth);
117 
118 static void CRYPTO_AES_ECBx(CRYPTO_TypeDef *crypto,
119  uint8_t * out,
120  const uint8_t * in,
121  unsigned int len,
122  const uint8_t * key,
123  bool encrypt,
124  CRYPTO_KeyWidth_TypeDef keyWidth);
125 
126 static void CRYPTO_AES_OFBx(CRYPTO_TypeDef *crypto,
127  uint8_t * out,
128  const uint8_t * in,
129  unsigned int len,
130  const uint8_t * key,
131  const uint8_t * iv,
132  CRYPTO_KeyWidth_TypeDef keyWidth);
133 
134 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
135 /***************************************************************************/
147 __STATIC_INLINE
148 void CRYPTO_DataWriteVariableSize(CRYPTO_DataReg_TypeDef dataReg,
149  const CRYPTO_Data_TypeDef val,
150  int valSize)
151 {
152  int i;
153  volatile uint32_t * reg = (volatile uint32_t *) dataReg;
154 
155  if (valSize < 4)
156  {
157  /* Non optimal write of data. */
158  for (i = 0; i < valSize; i++)
159  *reg = *val++;
160  for (; i < 4; i++)
161  *reg = 0;
162  }
163  else
164  {
165  CRYPTO_BurstToCrypto(reg, &val[0]);
166  }
167 }
168 #endif
169 
172 /*******************************************************************************
173  ************************** GLOBAL FUNCTIONS *******************************
174  ******************************************************************************/
175 
176 /***************************************************************************/
190 void CRYPTO_ModulusSet(CRYPTO_TypeDef * crypto,
191  CRYPTO_ModulusId_TypeDef modulusId)
192 {
193  uint32_t temp = crypto->WAC & (~(_CRYPTO_WAC_MODULUS_MASK | _CRYPTO_WAC_MODOP_MASK));
194 
195  switch (modulusId)
196  {
197  case cryptoModulusBin256:
198  case cryptoModulusBin128:
199  case cryptoModulusGcmBin128:
200  case cryptoModulusEccB233:
201  case cryptoModulusEccB163:
202 #ifdef _CRYPTO_WAC_MODULUS_ECCBIN233N
203  case cryptoModulusEccB233Order:
204  case cryptoModulusEccB233KOrder:
205  case cryptoModulusEccB163Order:
206  case cryptoModulusEccB163KOrder:
207 #endif
208  crypto->WAC = temp | modulusId | CRYPTO_WAC_MODOP_BINARY;
209  break;
210 
211  case cryptoModulusEccP256:
212  case cryptoModulusEccP224:
213  case cryptoModulusEccP192:
214 #ifdef _CRYPTO_WAC_MODULUS_ECCPRIME256P
215  case cryptoModulusEccP256Order:
216  case cryptoModulusEccP224Order:
217  case cryptoModulusEccP192Order:
218 #endif
219  crypto->WAC = temp | modulusId | CRYPTO_WAC_MODOP_REGULAR;
220  break;
221 
222  default:
223  /* Unknown modulus identifier. */
224  EFM_ASSERT(0);
225  }
226 }
227 
228 /***************************************************************************/
244 void CRYPTO_KeyRead(CRYPTO_TypeDef * crypto,
245  CRYPTO_KeyBuf_TypeDef val,
246  CRYPTO_KeyWidth_TypeDef keyWidth)
247 {
248  EFM_ASSERT(val);
249 
250  CRYPTO_BurstFromCrypto(&crypto->KEY, &val[0]);
251  if (keyWidth == cryptoKey256Bits)
252  {
253  CRYPTO_BurstFromCrypto(&crypto->KEY, &val[4]);
254  }
255 }
256 
257 /***************************************************************************/
277 void CRYPTO_SHA_1(CRYPTO_TypeDef * crypto,
278  const uint8_t * msg,
279  uint64_t msgLen,
280  CRYPTO_SHA1_Digest_TypeDef msgDigest)
281 {
282  uint32_t temp;
283  uint32_t len;
284  int blockLen;
285  uint32_t shaBlock[CRYPTO_SHA1_BLOCK_SIZE_IN_32BIT_WORDS]=
286  {
287  /* Initial value */
288  0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
289  };
290  uint8_t * p8ShaBlock = (uint8_t *) shaBlock;
291 
292  /* Initialize crypto module to do SHA-1. */
293  crypto->CTRL = CRYPTO_CTRL_SHA_SHA1;
294  crypto->SEQCTRL = 0;
295  crypto->SEQCTRLB = 0;
296 
297  /* Set result width of MADD32 operation. */
298  CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
299 
300  /* Write init value to DDATA1. */
301  CRYPTO_DDataWrite(&crypto->DDATA1, shaBlock);
302 
303  /* Copy data to DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
304  CRYPTO_EXECUTE_2(crypto,
305  CRYPTO_CMD_INSTR_DDATA1TODDATA0,
306  CRYPTO_CMD_INSTR_SELDDATA0DDATA1);
307 
308  len = msgLen;
309 
310  while (len >= CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES)
311  {
312  /* Write block to QDATA1. */
313  CRYPTO_QDataWrite(&crypto->QDATA1BIG, (uint32_t *) msg);
314 
315  /* Execute SHA */
316  CRYPTO_EXECUTE_3(crypto,
317  CRYPTO_CMD_INSTR_SHA,
318  CRYPTO_CMD_INSTR_MADD32,
319  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
320 
321  len -= CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES;
322  msg += CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES;
323  }
324 
325  blockLen = 0;
326 
327  /* Build the last (or second to last) block */
328  for (; len; len--)
329  p8ShaBlock[blockLen++] = *msg++;
330 
331  /* append the '1' bit */
332  p8ShaBlock[blockLen++] = 0x80;
333 
334  /* if the length is currently above 56 bytes we append zeros
335  * then compress. Then we can fall back to padding zeros and length
336  * encoding like normal.
337  */
338  if (blockLen > 56)
339  {
340  while (blockLen < 64)
341  p8ShaBlock[blockLen++] = 0;
342 
343  /* Write block to QDATA1BIG. */
344  CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
345 
346  /* Execute SHA */
347  CRYPTO_EXECUTE_3(crypto,
348  CRYPTO_CMD_INSTR_SHA,
349  CRYPTO_CMD_INSTR_MADD32,
350  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
351  blockLen = 0;
352  }
353 
354  /* pad upto 56 bytes of zeroes */
355  while (blockLen < 56)
356  p8ShaBlock[blockLen++] = 0;
357 
358  /* And finally, encode the message length. */
359  {
360  uint64_t msgLenInBits = msgLen << 3;
361  temp = msgLenInBits >> 32;
362  *(uint32_t*)&p8ShaBlock[56] = SWAP32(temp);
363  temp = msgLenInBits & 0xFFFFFFFF;
364  *(uint32_t*)&p8ShaBlock[60] = SWAP32(temp);
365  }
366 
367  /* Write block to QDATA1BIG. */
368  CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
369 
370  /* Execute SHA */
371  CRYPTO_EXECUTE_3(crypto,
372  CRYPTO_CMD_INSTR_SHA,
373  CRYPTO_CMD_INSTR_MADD32,
374  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
375 
376  /* Read resulting message digest from DDATA0BIG. */
377  ((uint32_t*)msgDigest)[0] = crypto->DDATA0BIG;
378  ((uint32_t*)msgDigest)[1] = crypto->DDATA0BIG;
379  ((uint32_t*)msgDigest)[2] = crypto->DDATA0BIG;
380  ((uint32_t*)msgDigest)[3] = crypto->DDATA0BIG;
381  ((uint32_t*)msgDigest)[4] = crypto->DDATA0BIG;
382  temp = crypto->DDATA0BIG;
383  temp = crypto->DDATA0BIG;
384  temp = crypto->DDATA0BIG;
385 }
386 
387 /***************************************************************************/
407 void CRYPTO_SHA_256(CRYPTO_TypeDef * crypto,
408  const uint8_t * msg,
409  uint64_t msgLen,
410  CRYPTO_SHA256_Digest_TypeDef msgDigest)
411 {
412  uint32_t temp;
413  uint32_t len;
414  int blockLen;
415  uint32_t shaBlock[CRYPTO_SHA256_BLOCK_SIZE_IN_32BIT_WORDS]=
416  {
417  /* Initial value */
418  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
419  0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
420  };
421  uint8_t * p8ShaBlock = (uint8_t *) shaBlock;
422 
423  /* Initialize crypyo module to do SHA-256 (SHA-2). */
424  crypto->CTRL = CRYPTO_CTRL_SHA_SHA2;
425  crypto->SEQCTRL = 0;
426  crypto->SEQCTRLB = 0;
427 
428  /* Set result width of MADD32 operation. */
429  CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
430 
431  /* Write init value to DDATA1. */
432  CRYPTO_DDataWrite(&crypto->DDATA1, shaBlock);
433 
434  /* Copy data ot DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
435  CRYPTO_EXECUTE_2(crypto,
436  CRYPTO_CMD_INSTR_DDATA1TODDATA0,
437  CRYPTO_CMD_INSTR_SELDDATA0DDATA1);
438  len = msgLen;
439 
440  while (len >= CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES)
441  {
442  /* Write block to QDATA1BIG. */
443  CRYPTO_QDataWrite(&crypto->QDATA1BIG, (uint32_t *) msg);
444 
445  /* Execute SHA */
446  CRYPTO_EXECUTE_3(crypto,
447  CRYPTO_CMD_INSTR_SHA,
448  CRYPTO_CMD_INSTR_MADD32,
449  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
450 
451  len -= CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES;
452  msg += CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES;
453  }
454 
455  blockLen = 0;
456 
457  /* Build the last (or second to last) block */
458  for (; len; len--)
459  p8ShaBlock[blockLen++] = *msg++;
460 
461  /* append the '1' bit */
462  p8ShaBlock[blockLen++] = 0x80;
463 
464  /* if the length is currently above 56 bytes we append zeros
465  * then compress. Then we can fall back to padding zeros and length
466  * encoding like normal.
467  */
468  if (blockLen > 56)
469  {
470  while (blockLen < 64)
471  p8ShaBlock[blockLen++] = 0;
472 
473  /* Write block to QDATA1BIG. */
474  CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
475 
476  /* Execute SHA */
477  CRYPTO_EXECUTE_3(crypto,
478  CRYPTO_CMD_INSTR_SHA,
479  CRYPTO_CMD_INSTR_MADD32,
480  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
481  blockLen = 0;
482  }
483 
484  /* Pad upto 56 bytes of zeroes */
485  while (blockLen < 56)
486  p8ShaBlock[blockLen++] = 0;
487 
488  /* And finally, encode the message length. */
489  {
490  uint64_t msgLenInBits = msgLen << 3;
491  temp = msgLenInBits >> 32;
492  *(uint32_t *)&p8ShaBlock[56] = SWAP32(temp);
493  temp = msgLenInBits & 0xFFFFFFFF;
494  *(uint32_t *)&p8ShaBlock[60] = SWAP32(temp);
495  }
496 
497  /* Write the final block to QDATA1BIG. */
498  CRYPTO_QDataWrite(&crypto->QDATA1BIG, shaBlock);
499 
500  /* Execute SHA */
501  CRYPTO_EXECUTE_3(crypto,
502  CRYPTO_CMD_INSTR_SHA,
503  CRYPTO_CMD_INSTR_MADD32,
504  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
505 
506  /* Read resulting message digest from DDATA0BIG. */
507  CRYPTO_DDataRead(&crypto->DDATA0BIG, (uint32_t *)msgDigest);
508 }
509 
510 /***************************************************************************/
517 __STATIC_INLINE void cryptoBigintZeroize(uint32_t * words32bits,
518  int num32bitWords)
519 {
520  while (num32bitWords--)
521  *words32bits++ = 0;
522 }
523 
524 /***************************************************************************/
531 __STATIC_INLINE void cryptoBigintIncrement(uint32_t * words32bits,
532  int num32bitWords)
533 {
534  int i;
535  for (i=0; i<num32bitWords; i++)
536  if (++words32bits[i] != 0)
537  break;
538  return;
539 }
540 
541 /***************************************************************************/
558 void CRYPTO_Mul(CRYPTO_TypeDef * crypto,
559  uint32_t * A, int aSize,
560  uint32_t * B, int bSize,
561  uint32_t * R, int rSize)
562 {
563  int i, j;
564 
565  /**************** Initializations ******************/
566 
567 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
568  int numWordsLastOperandA = (aSize&PARTIAL_OPERAND_WIDTH_MASK)>>5;
569  int numPartialOperandsA = numWordsLastOperandA ?
570  (aSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1 :
571  aSize >> PARTIAL_OPERAND_WIDTH_LOG2;
572  int numWordsLastOperandB = (bSize&PARTIAL_OPERAND_WIDTH_MASK)>>5;
573  int numPartialOperandsB = numWordsLastOperandB ?
574  (bSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1 :
575  bSize >> PARTIAL_OPERAND_WIDTH_LOG2;
576  int numWordsLastOperandR = (rSize&PARTIAL_OPERAND_WIDTH_MASK)>>5;
577  int numPartialOperandsR = numWordsLastOperandR ?
578  (rSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1 :
579  rSize >> PARTIAL_OPERAND_WIDTH_LOG2;
580  EFM_ASSERT(numPartialOperandsA + numPartialOperandsB <= numPartialOperandsR);
581 #else
582  int numPartialOperandsA = aSize >> PARTIAL_OPERAND_WIDTH_LOG2;
583  int numPartialOperandsB = bSize >> PARTIAL_OPERAND_WIDTH_LOG2;
584  EFM_ASSERT((aSize & PARTIAL_OPERAND_WIDTH_MASK) == 0);
585  EFM_ASSERT((bSize & PARTIAL_OPERAND_WIDTH_MASK) == 0);
586 #endif
587  EFM_ASSERT(aSize + bSize <= rSize);
588 
589  /* Set R to zero. */
590  cryptoBigintZeroize(R, rSize >> 5);
591 
592  /* Set multiplication width. */
593  crypto->WAC = CRYPTO_WAC_MULWIDTH_MUL128 | CRYPTO_WAC_RESULTWIDTH_256BIT;
594 
595  /* Setup DMA request signalling in order for MCU to run in parallel with
596  CRYPTO instruction sequence execution, and prepare data loading which
597  can take place immediately when CRYPTO is ready inside the instruction
598  sequence. */
599  crypto->CTRL =
600  CRYPTO_CTRL_DMA0RSEL_DATA0 | CRYPTO_CTRL_DMA0MODE_FULL |
601  CRYPTO_CTRL_DMA1RSEL_DATA1 | CRYPTO_CTRL_DMA1MODE_FULL;
602 
603  CRYPTO_EXECUTE_4(crypto,
604  CRYPTO_CMD_INSTR_CCLR, /* Carry = 0 */
605  CRYPTO_CMD_INSTR_CLR, /* DDATA0 = 0 */
606  /* clear result accumulation register */
607  CRYPTO_CMD_INSTR_DDATA0TODDATA2,
608  CRYPTO_CMD_INSTR_SELDDATA1DDATA3);
609  /*
610  register map:
611  DDATA0: working register
612  DDATA1: B(j)
613  DDATA2: R(i+j+1) and R(i+j), combined with DMA entry for B(j)
614  DDATA3: A(i)
615  */
616 
617  CRYPTO_SEQ_LOAD_10(crypto,
618  /* Temporarily load partial operand B(j) to DATA0. */
619  /* R(i+j+1) is still in DATA1 */
620  CRYPTO_CMD_INSTR_DMA0TODATA,
621  /* Move B(j) to DDATA1 */
622  CRYPTO_CMD_INSTR_DDATA2TODDATA1,
623 
624  /* Restore previous partial result (now R(i+j)) */
625  CRYPTO_CMD_INSTR_DATA1TODATA0,
626 
627  /* Load next partial result R(i+j+1) */
628  CRYPTO_CMD_INSTR_DMA1TODATA,
629 
630  /* Execute partial multiplication A(i)inDDATA1 * B(j)inDDATA3*/
631  CRYPTO_CMD_INSTR_MULO,
632 
633  /* Add the result to the previous partial result */
634  /* AND take the previous carry value into account */
635  /* at the right place (bit 128, ADDIC instruction */
636  CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
637  CRYPTO_CMD_INSTR_ADDIC,
638 
639  /* Save the new partial result (lower half) */
640  CRYPTO_CMD_INSTR_DDATA0TODDATA2,
641  CRYPTO_CMD_INSTR_DATATODMA0,
642  /* Reset the operand selector for next*/
643  CRYPTO_CMD_INSTR_SELDDATA2DDATA3
644  );
645 
646  /**************** End Initializations ******************/
647 
648  for(i=0; i<numPartialOperandsA; i++)
649  {
650  /* Load partial operand #1 A>>(i*PARTIAL_OPERAND_WIDTH) to DDATA1. */
651 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
652  if ( (numWordsLastOperandA != 0) && ( i == numPartialOperandsA-1 ) )
653  CRYPTO_DataWriteVariableSize(&crypto->DATA2,
654  &A[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
655  numWordsLastOperandA);
656  else
657  CRYPTO_DataWrite(&crypto->DATA2, &A[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
658 #else
659  CRYPTO_DataWrite(&crypto->DATA2, &A[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
660 #endif
661 
662  /* Load partial result in R>>(i*PARTIAL_OPERAND_WIDTH) to DATA1. */
663 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
664  if ( (numWordsLastOperandR != 0) && ( i == numPartialOperandsR-1 ) )
665  CRYPTO_DataWriteVariableSize(&crypto->DATA1,
666  &R[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
667  numWordsLastOperandR);
668  else
669  CRYPTO_DataWrite(&crypto->DATA1, &R[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
670 #else
671  CRYPTO_DataWrite(&crypto->DATA1, &R[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
672 #endif
673 
674  /* Clear carry */
675  crypto->CMD = CRYPTO_CMD_INSTR_CCLR;
676 
677  /* Setup number of sequence iterations and block size. */
678  crypto->SEQCTRL = CRYPTO_SEQCTRL_BLOCKSIZE_16BYTES
679  | (PARTIAL_OPERAND_WIDTH_IN_BYTES * numPartialOperandsB);
680 
681  /* Execute the MULtiply instruction sequence. */
682  CRYPTO_InstructionSequenceExecute(crypto);
683 
684  for (j=0; j<numPartialOperandsB; j++)
685  {
686  /* Load partial operand 2 B>>(j*`PARTIAL_OPERAND_WIDTH) to DDATA2
687  (via DATA0). */
688 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
689  if ( (numWordsLastOperandB != 0) && ( j == numPartialOperandsB-1 ) )
690  CRYPTO_DataWriteVariableSize(&crypto->DATA0,
691  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
692  numWordsLastOperandB);
693  else
694  CRYPTO_DataWrite(&crypto->DATA0,
695  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
696 #else
697  CRYPTO_DataWrite(&crypto->DATA0,
698  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
699 #endif
700 
701  /* Load most significant partial result
702  R>>((i+j+1)*`PARTIAL_OPERAND_WIDTH) into DATA1. */
703 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
704  if ( (numWordsLastOperandR != 0) && ( (i+j+1) == numPartialOperandsR-1 ) )
705  CRYPTO_DataWriteVariableSize(&crypto->DATA1,
706  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
707  numWordsLastOperandR);
708  else
709  CRYPTO_DataWrite(&crypto->DATA1,
710  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
711 #else
712  CRYPTO_DataWrite(&crypto->DATA1,
713  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
714 #endif
715  /* Store least significant partial result */
716  CRYPTO_DataRead(&crypto->DATA0,
717  &R[(i+j)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
718 
719  } /* for (j=0; j<numPartialOperandsB; j++) */
720 
721  /* Handle carry at the end of the inner loop. */
722  if (CRYPTO_CarryIsSet(crypto))
723  cryptoBigintIncrement(&R[(i+numPartialOperandsB+1)
724  *PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
725  (numPartialOperandsA-i-1)
726  *PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS);
727 
728  CRYPTO_DataRead(&crypto->DATA1,
729  &R[(i+numPartialOperandsB)
730  * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
731 
732  } /* for (i=0; i<numPartialOperandsA; i++) */
733 }
734 
735 /***************************************************************************/
800 void CRYPTO_AES_CBC128(CRYPTO_TypeDef * crypto,
801  uint8_t * out,
802  const uint8_t * in,
803  unsigned int len,
804  const uint8_t * key,
805  const uint8_t * iv,
806  bool encrypt)
807 {
808  crypto->CTRL = CRYPTO_CTRL_AES_AES128;
809  CRYPTO_AES_CBCx(crypto, out, in, len, key, iv, encrypt, cryptoKey128Bits);
810 }
811 
812 /***************************************************************************/
846 void CRYPTO_AES_CBC256(CRYPTO_TypeDef * crypto,
847  uint8_t * out,
848  const uint8_t * in,
849  unsigned int len,
850  const uint8_t * key,
851  const uint8_t * iv,
852  bool encrypt)
853 {
854  crypto->CTRL = CRYPTO_CTRL_AES_AES256;
855  CRYPTO_AES_CBCx(crypto, out, in, len, key, iv, encrypt, cryptoKey256Bits);
856 }
857 
858 /***************************************************************************/
919 void CRYPTO_AES_CFB128(CRYPTO_TypeDef * crypto,
920  uint8_t * out,
921  const uint8_t * in,
922  unsigned int len,
923  const uint8_t * key,
924  const uint8_t * iv,
925  bool encrypt)
926 {
927  crypto->CTRL = CRYPTO_CTRL_AES_AES128;
928  CRYPTO_AES_CFBx(crypto, out, in, len, key, iv, encrypt, cryptoKey128Bits);
929 }
930 
931 /***************************************************************************/
962 void CRYPTO_AES_CFB256(CRYPTO_TypeDef * crypto,
963  uint8_t * out,
964  const uint8_t * in,
965  unsigned int len,
966  const uint8_t * key,
967  const uint8_t * iv,
968  bool encrypt)
969 {
970  crypto->CTRL = CRYPTO_CTRL_AES_AES256;
971  CRYPTO_AES_CFBx(crypto, out, in, len, key, iv, encrypt, cryptoKey256Bits);
972 }
973 
974 /***************************************************************************/
1038 void CRYPTO_AES_CTR128(CRYPTO_TypeDef * crypto,
1039  uint8_t * out,
1040  const uint8_t * in,
1041  unsigned int len,
1042  const uint8_t * key,
1043  uint8_t * ctr,
1044  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
1045 {
1046  crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1047  CRYPTO_AES_CTRx(crypto, out, in, len, key, ctr, ctrFunc, cryptoKey128Bits);
1048 }
1049 
1050 /***************************************************************************/
1084 void CRYPTO_AES_CTR256(CRYPTO_TypeDef * crypto,
1085  uint8_t * out,
1086  const uint8_t * in,
1087  unsigned int len,
1088  const uint8_t * key,
1089  uint8_t * ctr,
1090  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
1091 {
1092  crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1093  CRYPTO_AES_CTRx(crypto, out, in, len, key, ctr, ctrFunc, cryptoKey256Bits);
1094 }
1095 
1096 /***************************************************************************/
1110 void CRYPTO_AES_CTRUpdate32Bit(uint8_t * ctr)
1111 {
1112  uint32_t * _ctr = (uint32_t *) ctr;
1113 
1114  _ctr[3] = __REV(__REV(_ctr[3]) + 1);
1115 }
1116 
1117 /***************************************************************************/
1135 void CRYPTO_AES_DecryptKey128(CRYPTO_TypeDef * crypto,
1136  uint8_t * out,
1137  const uint8_t * in)
1138 {
1139  uint32_t * _out = (uint32_t *) out;
1140  const uint32_t * _in = (const uint32_t *) in;
1141 
1142  /* Setup CRYPTO in AES-128 mode. */
1143  crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1144 
1145  /* Load key */
1146  CRYPTO_BurstToCrypto(&crypto->KEYBUF, &_in[0]);
1147 
1148  /* Do dummy encryption to generate decrypt key */
1149  crypto->CMD = CRYPTO_CMD_INSTR_AESENC;
1150 
1151  /* Save decryption key */
1152  CRYPTO_BurstFromCrypto(&crypto->KEY, &_out[0]);
1153 }
1154 
1155 /***************************************************************************/
1173 void CRYPTO_AES_DecryptKey256(CRYPTO_TypeDef * crypto,
1174  uint8_t * out,
1175  const uint8_t * in)
1176 {
1177  uint32_t * _out = (uint32_t *) out;
1178  const uint32_t * _in = (const uint32_t *) in;
1179 
1180  /* Setup CRYPTO in AES-256 mode. */
1181  crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1182 
1183  /* Load key */
1184  CRYPTO_BurstToCrypto(&crypto->KEYBUF, &_in[0]);
1185  CRYPTO_BurstToCrypto(&crypto->KEYBUF, &_in[4]);
1186 
1187  /* Do dummy encryption to generate decrypt key */
1188  crypto->CMD = CRYPTO_CMD_INSTR_AESENC;
1189 
1190  /* Save decryption key */
1191  CRYPTO_BurstFromCrypto(&crypto->KEY, &_out[0]);
1192  CRYPTO_BurstFromCrypto(&crypto->KEY, &_out[4]);
1193 }
1194 
1195 /***************************************************************************/
1250 void CRYPTO_AES_ECB128(CRYPTO_TypeDef * crypto,
1251  uint8_t * out,
1252  const uint8_t * in,
1253  unsigned int len,
1254  const uint8_t * key,
1255  bool encrypt)
1256 {
1257  crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1258  CRYPTO_AES_ECBx(crypto, out, in, len, key, encrypt, cryptoKey128Bits);
1259 }
1260 
1261 /***************************************************************************/
1292 void CRYPTO_AES_ECB256(CRYPTO_TypeDef * crypto,
1293  uint8_t * out,
1294  const uint8_t * in,
1295  unsigned int len,
1296  const uint8_t * key,
1297  bool encrypt)
1298 {
1299  crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1300  CRYPTO_AES_ECBx(crypto, out, in, len, key, encrypt, cryptoKey256Bits);
1301 }
1302 
1303 /***************************************************************************/
1363 void CRYPTO_AES_OFB128(CRYPTO_TypeDef * crypto,
1364  uint8_t * out,
1365  const uint8_t * in,
1366  unsigned int len,
1367  const uint8_t * key,
1368  const uint8_t * iv)
1369 {
1370  crypto->CTRL = CRYPTO_CTRL_AES_AES128;
1371  CRYPTO_AES_OFBx(crypto, out, in, len, key, iv, cryptoKey128Bits);
1372 }
1373 
1374 /***************************************************************************/
1402 void CRYPTO_AES_OFB256(CRYPTO_TypeDef * crypto,
1403  uint8_t * out,
1404  const uint8_t * in,
1405  unsigned int len,
1406  const uint8_t * key,
1407  const uint8_t * iv)
1408 {
1409  crypto->CTRL = CRYPTO_CTRL_AES_AES256;
1410  CRYPTO_AES_OFBx(crypto, out, in, len, key, iv, cryptoKey256Bits);
1411 }
1412 
1413 /*******************************************************************************
1414  ************************** LOCAL FUNCTIONS *******************************
1415  ******************************************************************************/
1416 
1417 /***************************************************************************/
1453 static void CRYPTO_AES_CBCx(CRYPTO_TypeDef * crypto,
1454  uint8_t * out,
1455  const uint8_t * in,
1456  unsigned int len,
1457  const uint8_t * key,
1458  const uint8_t * iv,
1459  bool encrypt,
1460  CRYPTO_KeyWidth_TypeDef keyWidth)
1461 {
1462  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1463 
1464  /* Initialize control registers. */
1465  crypto->WAC = 0;
1466 
1467  CRYPTO_KeyBufWrite(crypto, (uint32_t *)key, keyWidth);
1468 
1469  if (encrypt)
1470  {
1471  CRYPTO_DataWrite(&crypto->DATA0, (uint32_t *)iv);
1472 
1473  crypto->SEQ0 =
1474  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR0_SHIFT |
1475  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT;
1476 
1477  CRYPTO_AES_ProcessLoop(crypto, len,
1478  &crypto->DATA1, (uint32_t *) in,
1479  &crypto->DATA0, (uint32_t *) out);
1480  }
1481  else
1482  {
1483  CRYPTO_DataWrite(&crypto->DATA2, (uint32_t *) iv);
1484 
1485  crypto->SEQ0 =
1486  CRYPTO_CMD_INSTR_DATA1TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1487  CRYPTO_CMD_INSTR_AESDEC << _CRYPTO_SEQ0_INSTR1_SHIFT |
1488  CRYPTO_CMD_INSTR_DATA2TODATA0XOR << _CRYPTO_SEQ0_INSTR2_SHIFT |
1489  CRYPTO_CMD_INSTR_DATA1TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
1490 
1491  crypto->SEQ1 = 0;
1492 
1493  /* The following call is equivalent to the last call in the
1494  'if( encrypt )' branch. However moving this
1495  call outside the conditional scope results in slightly poorer
1496  performance for some compiler optimizations. */
1497  CRYPTO_AES_ProcessLoop(crypto, len,
1498  &crypto->DATA1, (uint32_t *) in,
1499  &crypto->DATA0, (uint32_t *) out);
1500  }
1501 }
1502 
1503 /***************************************************************************/
1537 static void CRYPTO_AES_CFBx(CRYPTO_TypeDef * crypto,
1538  uint8_t * out,
1539  const uint8_t * in,
1540  unsigned int len,
1541  const uint8_t * key,
1542  const uint8_t * iv,
1543  bool encrypt,
1544  CRYPTO_KeyWidth_TypeDef keyWidth)
1545 {
1546  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1547 
1548  /* Initialize control registers. */
1549  crypto->WAC = 0;
1550 
1551  /* Load Key */
1552  CRYPTO_KeyBufWrite(crypto, (uint32_t *)key, keyWidth);
1553 
1554  /* Load instructions to CRYPTO sequencer. */
1555  if (encrypt)
1556  {
1557  /* Load IV */
1558  CRYPTO_DataWrite(&crypto->DATA0, (uint32_t *)iv);
1559 
1560  crypto->SEQ0 =
1561  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR0_SHIFT |
1562  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR1_SHIFT;
1563 
1564  CRYPTO_AES_ProcessLoop(crypto, len,
1565  &crypto->DATA1, (uint32_t *)in,
1566  &crypto->DATA0, (uint32_t *)out
1567  );
1568  }
1569  else
1570  {
1571  /* Load IV */
1572  CRYPTO_DataWrite(&crypto->DATA2, (uint32_t *)iv);
1573 
1574  crypto->SEQ0 =
1575  CRYPTO_CMD_INSTR_DATA2TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1576  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT |
1577  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR2_SHIFT |
1578  CRYPTO_CMD_INSTR_DATA1TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
1579  crypto->SEQ1 = 0;
1580 
1581  CRYPTO_AES_ProcessLoop(crypto, len,
1582  &crypto->DATA1, (uint32_t *)in,
1583  &crypto->DATA0, (uint32_t *)out
1584  );
1585  }
1586 }
1587 
1588 /***************************************************************************/
1625 static void CRYPTO_AES_CTRx(CRYPTO_TypeDef * crypto,
1626  uint8_t * out,
1627  const uint8_t * in,
1628  unsigned int len,
1629  const uint8_t * key,
1630  uint8_t * ctr,
1631  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,
1632  CRYPTO_KeyWidth_TypeDef keyWidth)
1633 {
1634  (void) ctrFunc;
1635 
1636  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1637 
1638  /* Initialize control registers. */
1639  crypto->CTRL |= CRYPTO_CTRL_INCWIDTH_INCWIDTH4;
1640  crypto->WAC = 0;
1641 
1642  CRYPTO_KeyBufWrite(crypto, (uint32_t *)key, keyWidth);
1643 
1644  CRYPTO_DataWrite(&crypto->DATA1, (uint32_t *) ctr);
1645 
1646  crypto->SEQ0 = CRYPTO_CMD_INSTR_DATA1TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1647  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT |
1648  CRYPTO_CMD_INSTR_DATA0TODATA3 << _CRYPTO_SEQ0_INSTR2_SHIFT |
1649  CRYPTO_CMD_INSTR_DATA1INC << _CRYPTO_SEQ0_INSTR3_SHIFT;
1650 
1651  crypto->SEQ1 = CRYPTO_CMD_INSTR_DATA2TODATA0XOR << _CRYPTO_SEQ1_INSTR4_SHIFT;
1652 
1653  CRYPTO_AES_ProcessLoop(crypto, len,
1654  &crypto->DATA2, (uint32_t *) in,
1655  &crypto->DATA0, (uint32_t *) out);
1656 
1657  CRYPTO_DataRead(&crypto->DATA1, (uint32_t *) ctr);
1658 }
1659 
1660 /***************************************************************************/
1693 static void CRYPTO_AES_ECBx(CRYPTO_TypeDef * crypto,
1694  uint8_t * out,
1695  const uint8_t * in,
1696  unsigned int len,
1697  const uint8_t * key,
1698  bool encrypt,
1699  CRYPTO_KeyWidth_TypeDef keyWidth)
1700 {
1701  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1702 
1703  crypto->WAC = 0;
1704 
1705  CRYPTO_KeyBufWrite(crypto, (uint32_t *)key, keyWidth);
1706 
1707  if (encrypt)
1708  {
1709  crypto->SEQ0 =
1710  (CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR0_SHIFT |
1711  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ0_INSTR1_SHIFT);
1712  }
1713  else
1714  {
1715  crypto->SEQ0 =
1716  (CRYPTO_CMD_INSTR_AESDEC << _CRYPTO_SEQ0_INSTR0_SHIFT |
1717  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ0_INSTR1_SHIFT);
1718  }
1719 
1720  CRYPTO_AES_ProcessLoop(crypto, len,
1721  &crypto->DATA0, (uint32_t *) in,
1722  &crypto->DATA1, (uint32_t *) out);
1723 }
1724 
1725 /***************************************************************************/
1756 static void CRYPTO_AES_OFBx(CRYPTO_TypeDef * crypto,
1757  uint8_t * out,
1758  const uint8_t * in,
1759  unsigned int len,
1760  const uint8_t * key,
1761  const uint8_t * iv,
1762  CRYPTO_KeyWidth_TypeDef keyWidth)
1763 {
1764  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1765 
1766  crypto->WAC = 0;
1767 
1768  CRYPTO_KeyBufWrite(crypto, (uint32_t *)key, keyWidth);
1769 
1770  CRYPTO_DataWrite(&crypto->DATA2, (uint32_t *)iv);
1771 
1772  crypto->SEQ0 =
1773  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1774  CRYPTO_CMD_INSTR_DATA2TODATA0 << _CRYPTO_SEQ0_INSTR1_SHIFT |
1775  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR2_SHIFT |
1776  CRYPTO_CMD_INSTR_DATA0TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
1777  crypto->SEQ1 =
1778  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ1_INSTR4_SHIFT |
1779  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ1_INSTR5_SHIFT;
1780 
1781  CRYPTO_AES_ProcessLoop(crypto, len,
1782  &crypto->DATA0, (uint32_t *) in,
1783  &crypto->DATA1, (uint32_t *) out);
1784 }
1785 
1786 /***************************************************************************/
1814 static inline void CRYPTO_AES_ProcessLoop(CRYPTO_TypeDef * crypto,
1815  uint32_t len,
1816  CRYPTO_DataReg_TypeDef inReg,
1817  uint32_t * in,
1818  CRYPTO_DataReg_TypeDef outReg,
1819  uint32_t * out)
1820 {
1821  len /= CRYPTO_AES_BLOCKSIZE;
1822  crypto->SEQCTRL = 16 << _CRYPTO_SEQCTRL_LENGTHA_SHIFT;
1823 
1824  while (len--)
1825  {
1826  /* Load data and trigger encryption */
1827  CRYPTO_DataWrite(inReg, (uint32_t *)in);
1828 
1829  crypto->CMD = CRYPTO_CMD_SEQSTART;
1830 
1831  /* Save encrypted/decrypted data */
1832  CRYPTO_DataRead(outReg, (uint32_t *)out);
1833 
1834  out += 4;
1835  in += 4;
1836  }
1837 }
1838 
1842 #endif /* defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
Emlib peripheral API "assert" implementation.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
Cryptography accelerator peripheral API.