EFM32 Gecko Software Documentation  efm32g-doc-4.2.1
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 #include "em_bitband.h"
39 
40 /***************************************************************************/
45 /***************************************************************************/
176 /*******************************************************************************
177  ******************************* DEFINES ***********************************
178  ******************************************************************************/
179 
182 #define CRYPTO_INSTRUCTIONS_PER_REG (4)
183 #define CRYPTO_INSTRUCTIONS_MAX (12)
184 #define CRYPTO_INSTRUCTION_REGS (CRYPTO_INSTRUCTIONS_MAX/CRYPTO_INSTRUCTIONS_PER_REG)
185 
186 #define CRYPTO_SHA1_BLOCK_SIZE_IN_BITS (512)
187 #define CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES (CRYPTO_SHA1_BLOCK_SIZE_IN_BITS/8)
188 #define CRYPTO_SHA1_BLOCK_SIZE_IN_32BIT_WORDS (CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES/sizeof(uint32_t))
189 #define CRYPTO_SHA1_DIGEST_SIZE_IN_32BIT_WORDS (CRYPTO_SHA1_DIGEST_SIZE_IN_BYTES/sizeof(uint32_t))
190 
191 #define CRYPTO_SHA256_BLOCK_SIZE_IN_BITS (512)
192 #define CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES (CRYPTO_SHA256_BLOCK_SIZE_IN_BITS/8)
193 #define CRYPTO_SHA256_BLOCK_SIZE_IN_32BIT_WORDS (CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES/sizeof(uint32_t))
194 
195 #define CRYPTO_SHA256_DIGEST_SIZE_IN_32BIT_WORDS (CRYPTO_SHA256_DIGEST_SIZE_IN_BYTES/sizeof(uint32_t))
196 
197 #define PARTIAL_OPERAND_WIDTH_LOG2 (7) /* 2^7 = 128 */
198 #define PARTIAL_OPERAND_WIDTH (1<<PARTIAL_OPERAND_WIDTH_LOG2)
199 #define PARTIAL_OPERAND_WIDTH_MASK (PARTIAL_OPERAND_WIDTH-1)
200 #define PARTIAL_OPERAND_WIDTH_IN_BYTES (PARTIAL_OPERAND_WIDTH/8)
201 #define PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS (PARTIAL_OPERAND_WIDTH_IN_BYTES/sizeof(uint32_t))
202 
203 #define SWAP32(x) (__REV(x))
204 
205 #define CRYPTO_AES_BLOCKSIZE (16)
206 
207 /*******************************************************************************
208  *********************** STATIC FUNCTIONS **********************************
209  ******************************************************************************/
210 
211 static inline void CRYPTO_AES_ProcessLoop(uint32_t len,
212  CRYPTO_DataReg_TypeDef inReg,
213  uint32_t * in,
214  CRYPTO_DataReg_TypeDef outReg,
215  uint32_t * out);
216 
217 static void CRYPTO_AES_CBCx(uint8_t * out,
218  const uint8_t * in,
219  unsigned int len,
220  const uint8_t * key,
221  const uint8_t * iv,
222  bool encrypt,
223  CRYPTO_KeyWidth_TypeDef keyWidth);
224 
225 static void CRYPTO_AES_CFBx(uint8_t * out,
226  const uint8_t * in,
227  unsigned int len,
228  const uint8_t * key,
229  const uint8_t * iv,
230  bool encrypt,
231  CRYPTO_KeyWidth_TypeDef keyWidth);
232 
233 static void CRYPTO_AES_CTRx(uint8_t * out,
234  const uint8_t * in,
235  unsigned int len,
236  const uint8_t * key,
237  uint8_t * ctr,
238  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,
239  CRYPTO_KeyWidth_TypeDef keyWidth);
240 
241 static void CRYPTO_AES_ECBx(uint8_t * out,
242  const uint8_t * in,
243  unsigned int len,
244  const uint8_t * key,
245  bool encrypt,
246  CRYPTO_KeyWidth_TypeDef keyWidth);
247 
248 static void CRYPTO_AES_OFBx(uint8_t * out,
249  const uint8_t * in,
250  unsigned int len,
251  const uint8_t * key,
252  const uint8_t * iv,
253  CRYPTO_KeyWidth_TypeDef keyWidth);
254 
255 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
256 /***************************************************************************/
268 __STATIC_INLINE
269 void CRYPTO_DataWriteVariableSize(CRYPTO_DataReg_TypeDef dataReg,
270  const CRYPTO_Data_TypeDef val,
271  int valSize)
272 {
273  int i;
274  volatile uint32_t * reg = (volatile uint32_t *) dataReg;
275 
276  if (valSize < 4)
277  {
278  /* Non optimal write of data. */
279  for (i = 0; i < valSize; i++)
280  *reg = *val++;
281  for (; i < 4; i++)
282  *reg = 0;
283  }
284  else
285  {
286  CRYPTO_BurstToCrypto(reg, &val[0]);
287  }
288 }
289 #endif
290 
293 /*******************************************************************************
294  ************************** GLOBAL FUNCTIONS *******************************
295  ******************************************************************************/
296 
297 /***************************************************************************/
307 void CRYPTO_ModulusSet(CRYPTO_ModulusType_TypeDef modType)
308 {
309  uint32_t temp = CRYPTO->WAC & (~(_CRYPTO_WAC_MODULUS_MASK | _CRYPTO_WAC_MODOP_MASK));
310 
311  switch (modType)
312  {
313  case cryptoModulusBin256:
314  case cryptoModulusBin128:
315  case cryptoModulusGcmBin128:
316  case cryptoModulusEccB233:
317  case cryptoModulusEccB163:
318 #ifdef _CRYPTO_WAC_MODULUS_ECCBIN233N
319  case cryptoModulusEccB233Order:
320  case cryptoModulusEccB233KOrder:
321  case cryptoModulusEccB163Order:
322  case cryptoModulusEccB163KOrder:
323 #endif
324  CRYPTO->WAC = temp | modType | CRYPTO_WAC_MODOP_BINARY;
325  break;
326 
327  case cryptoModulusEccP256:
328  case cryptoModulusEccP224:
329  case cryptoModulusEccP192:
330 #ifdef _CRYPTO_WAC_MODULUS_ECCPRIME256P
331  case cryptoModulusEccP256Order:
332  case cryptoModulusEccP224Order:
333  case cryptoModulusEccP192Order:
334 #endif
335  CRYPTO->WAC = temp | modType | CRYPTO_WAC_MODOP_REGULAR;
336  break;
337 
338  default:
339  /* Unknown modulus type. */
340  EFM_ASSERT(0);
341  }
342 }
343 
344 /***************************************************************************/
354 void CRYPTO_KeyRead(CRYPTO_KeyBuf_TypeDef val,
355  CRYPTO_KeyWidth_TypeDef keyWidth)
356 {
357  EFM_ASSERT(val);
358 
359  CRYPTO_BurstFromCrypto(&CRYPTO->KEY, &val[0]);
360  if (keyWidth == cryptoKey256Bits)
361  {
362  CRYPTO_BurstFromCrypto(&CRYPTO->KEY, &val[4]);
363  }
364 }
365 
366 /***************************************************************************/
378 void CRYPTO_SHA_1(const uint8_t * msg,
379  uint64_t msgLen,
380  CRYPTO_SHA1_Digest_TypeDef msgDigest)
381 {
382  uint32_t temp;
383  int len;
384  int blockLen;
385  uint32_t shaBlock[CRYPTO_SHA1_BLOCK_SIZE_IN_32BIT_WORDS]=
386  {
387  /* Initial value */
388  0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
389  };
390  uint8_t * p8ShaBlock = (uint8_t *) shaBlock;
391 
392  /* Initialize crypto module to do SHA-1. */
393  CRYPTO->CTRL = CRYPTO_CTRL_SHA_SHA1;
394  CRYPTO->SEQCTRL = 0;
395  CRYPTO->SEQCTRLB = 0;
396 
397  /* Set result width of MADD32 operation. */
398  CRYPTO_ResultWidthSet(cryptoResult256Bits);
399 
400  /* Write init value to DDATA1. */
401  CRYPTO_DDataWrite(cryptoRegDDATA1, shaBlock);
402 
403  /* Copy data to DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
404  CRYPTO_EXECUTE_2(CRYPTO_CMD_INSTR_DDATA1TODDATA0,
405  CRYPTO_CMD_INSTR_SELDDATA0DDATA1);
406 
407  len = msgLen;
408 
409  while (len >= CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES)
410  {
411  /* Write block to QDATA1. */
412  CRYPTO_QDataWrite(cryptoRegQDATA1BIG, (uint32_t *) msg);
413 
414  /* Execute SHA */
415  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
416  CRYPTO_CMD_INSTR_MADD32,
417  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
418 
419  len -= CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES;
420  msg += CRYPTO_SHA1_BLOCK_SIZE_IN_BYTES;
421  }
422 
423  blockLen = 0;
424 
425  /* Build the last (or second to last) block */
426  for (; len; len--)
427  p8ShaBlock[blockLen++] = *msg++;
428 
429  /* append the '1' bit */
430  p8ShaBlock[blockLen++] = 0x80;
431 
432  /* if the length is currently above 56 bytes we append zeros
433  * then compress. Then we can fall back to padding zeros and length
434  * encoding like normal.
435  */
436  if (blockLen > 56)
437  {
438  while (blockLen < 64)
439  p8ShaBlock[blockLen++] = 0;
440 
441  /* Write block to QDATA1BIG. */
442  CRYPTO_QDataWrite(cryptoRegQDATA1BIG, shaBlock);
443 
444  /* Execute SHA */
445  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
446  CRYPTO_CMD_INSTR_MADD32,
447  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
448  blockLen = 0;
449  }
450 
451  /* pad upto 56 bytes of zeroes */
452  while (blockLen < 56)
453  p8ShaBlock[blockLen++] = 0;
454 
455  /* And finally, encode the message length. */
456  {
457  uint64_t msgLenInBits = msgLen << 3;
458  temp = msgLenInBits >> 32;
459  *(uint32_t*)&p8ShaBlock[56] = SWAP32(temp);
460  temp = msgLenInBits & 0xFFFFFFFF;
461  *(uint32_t*)&p8ShaBlock[60] = SWAP32(temp);
462  }
463 
464  /* Write block to QDATA1BIG. */
465  CRYPTO_QDataWrite(cryptoRegQDATA1BIG, shaBlock);
466 
467  /* Execute SHA */
468  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
469  CRYPTO_CMD_INSTR_MADD32,
470  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
471 
472  /* Read resulting message digest from DDATA0BIG. */
473  ((uint32_t*)msgDigest)[0] = CRYPTO->DDATA0BIG;
474  ((uint32_t*)msgDigest)[1] = CRYPTO->DDATA0BIG;
475  ((uint32_t*)msgDigest)[2] = CRYPTO->DDATA0BIG;
476  ((uint32_t*)msgDigest)[3] = CRYPTO->DDATA0BIG;
477  ((uint32_t*)msgDigest)[4] = CRYPTO->DDATA0BIG;
478  temp = CRYPTO->DDATA0BIG;
479  temp = CRYPTO->DDATA0BIG;
480  temp = CRYPTO->DDATA0BIG;
481 }
482 
483 /***************************************************************************/
495 void CRYPTO_SHA_256(const uint8_t * msg,
496  uint64_t msgLen,
497  CRYPTO_SHA256_Digest_TypeDef msgDigest)
498 {
499  uint32_t temp;
500  int len;
501  int blockLen;
502  uint32_t shaBlock[CRYPTO_SHA256_BLOCK_SIZE_IN_32BIT_WORDS]=
503  {
504  /* Initial value */
505  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
506  0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
507  };
508  uint8_t * p8ShaBlock = (uint8_t *) shaBlock;
509 
510  /* Initialize crypyo module to do SHA-256 (SHA-2). */
511  CRYPTO->CTRL = CRYPTO_CTRL_SHA_SHA2;
512  CRYPTO->SEQCTRL = 0;
513  CRYPTO->SEQCTRLB = 0;
514 
515  /* Set result width of MADD32 operation. */
516  CRYPTO_ResultWidthSet(cryptoResult256Bits);
517 
518  /* Write init value to DDATA1. */
519  CRYPTO_DDataWrite(cryptoRegDDATA1, shaBlock);
520 
521  /* Copy data ot DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
522  CRYPTO_EXECUTE_2(CRYPTO_CMD_INSTR_DDATA1TODDATA0,
523  CRYPTO_CMD_INSTR_SELDDATA0DDATA1);
524  len = msgLen;
525 
526  while (len >= CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES)
527  {
528  /* Write block to QDATA1BIG. */
529  CRYPTO_QDataWrite(cryptoRegQDATA1BIG, (uint32_t *) msg);
530 
531  /* Execute SHA */
532  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
533  CRYPTO_CMD_INSTR_MADD32,
534  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
535 
536  len -= CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES;
537  msg += CRYPTO_SHA256_BLOCK_SIZE_IN_BYTES;
538  }
539 
540  blockLen = 0;
541 
542  /* Build the last (or second to last) block */
543  for (; len; len--)
544  p8ShaBlock[blockLen++] = *msg++;
545 
546  /* append the '1' bit */
547  p8ShaBlock[blockLen++] = 0x80;
548 
549  /* if the length is currently above 56 bytes we append zeros
550  * then compress. Then we can fall back to padding zeros and length
551  * encoding like normal.
552  */
553  if (blockLen > 56)
554  {
555  while (blockLen < 64)
556  p8ShaBlock[blockLen++] = 0;
557 
558  /* Write block to QDATA1BIG. */
559  CRYPTO_QDataWrite(cryptoRegQDATA1BIG, shaBlock);
560 
561  /* Execute SHA */
562  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
563  CRYPTO_CMD_INSTR_MADD32,
564  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
565  blockLen = 0;
566  }
567 
568  /* Pad upto 56 bytes of zeroes */
569  while (blockLen < 56)
570  p8ShaBlock[blockLen++] = 0;
571 
572  /* And finally, encode the message length. */
573  {
574  uint64_t msgLenInBits = msgLen << 3;
575  temp = msgLenInBits >> 32;
576  *(uint32_t *)&p8ShaBlock[56] = SWAP32(temp);
577  temp = msgLenInBits & 0xFFFFFFFF;
578  *(uint32_t *)&p8ShaBlock[60] = SWAP32(temp);
579  }
580 
581  /* Write the final block to QDATA1BIG. */
582  CRYPTO_QDataWrite(cryptoRegQDATA1BIG, shaBlock);
583 
584  /* Execute SHA */
585  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
586  CRYPTO_CMD_INSTR_MADD32,
587  CRYPTO_CMD_INSTR_DDATA0TODDATA1);
588 
589  /* Read resulting message digest from DDATA0BIG. */
590  CRYPTO_DDataRead(cryptoRegDDATA0BIG, (uint32_t *)msgDigest);
591 }
592 
593 /***************************************************************************/
600 __STATIC_INLINE void cryptoBigintZeroize(uint32_t * words32bits,
601  int num32bitWords)
602 {
603  while (num32bitWords--)
604  *words32bits++ = 0;
605 }
606 
607 /***************************************************************************/
614 __STATIC_INLINE void cryptoBigintIncrement(uint32_t * words32bits,
615  int num32bitWords)
616 {
617  int i;
618  for (i=0; i<num32bitWords; i++)
619  if (++words32bits[i] != 0)
620  break;
621  return;
622 }
623 
624 /***************************************************************************/
641 void CRYPTO_Mul(uint32_t * A, int aSize,
642  uint32_t * B, int bSize,
643  uint32_t * R, int rSize)
644 {
645  int i, j;
646 
647  /**************** Initializations ******************/
648 
649 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
650  int numWordsLastOperandA = (aSize&PARTIAL_OPERAND_WIDTH_MASK)>>5;
651  int numPartialOperandsA = numWordsLastOperandA ?
652  (aSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1 :
653  aSize >> PARTIAL_OPERAND_WIDTH_LOG2;
654  int numWordsLastOperandB = (bSize&PARTIAL_OPERAND_WIDTH_MASK)>>5;
655  int numPartialOperandsB = numWordsLastOperandB ?
656  (bSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1 :
657  bSize >> PARTIAL_OPERAND_WIDTH_LOG2;
658  int numWordsLastOperandR = (rSize&PARTIAL_OPERAND_WIDTH_MASK)>>5;
659  int numPartialOperandsR = numWordsLastOperandR ?
660  (rSize >> PARTIAL_OPERAND_WIDTH_LOG2) + 1 :
661  rSize >> PARTIAL_OPERAND_WIDTH_LOG2;
662  EFM_ASSERT(numPartialOperandsA + numPartialOperandsB <= numPartialOperandsR);
663 #else
664  int numPartialOperandsA = aSize >> PARTIAL_OPERAND_WIDTH_LOG2;
665  int numPartialOperandsB = bSize >> PARTIAL_OPERAND_WIDTH_LOG2;
666  EFM_ASSERT((aSize & PARTIAL_OPERAND_WIDTH_MASK) == 0);
667  EFM_ASSERT((bSize & PARTIAL_OPERAND_WIDTH_MASK) == 0);
668 #endif
669  EFM_ASSERT(aSize + bSize <= rSize);
670 
671  /* Set R to zero. */
672  cryptoBigintZeroize(R, rSize >> 5);
673 
674  /* Set multiplication width. */
675  CRYPTO->WAC = CRYPTO_WAC_MULWIDTH_MUL128 | CRYPTO_WAC_RESULTWIDTH_256BIT;
676 
677  /* Setup DMA request signalling in order for MCU to run in parallel with
678  CRYPTO instruction sequence execution, and prepare data loading which
679  can take place immediately when CRYPTO is ready inside the instruction
680  sequence. */
681  CRYPTO->CTRL =
682  CRYPTO_CTRL_DMA0RSEL_DATA0 | CRYPTO_CTRL_DMA0MODE_FULL |
683  CRYPTO_CTRL_DMA1RSEL_DATA1 | CRYPTO_CTRL_DMA1MODE_FULL;
684 
685  CRYPTO_EXECUTE_4(
686  CRYPTO_CMD_INSTR_CCLR, /* Carry = 0 */
687  CRYPTO_CMD_INSTR_CLR, /* DDATA0 = 0 */
688  /* clear result accumulation register */
689  CRYPTO_CMD_INSTR_DDATA0TODDATA2,
690  CRYPTO_CMD_INSTR_SELDDATA1DDATA3);
691  /*
692  register map:
693  DDATA0: working register
694  DDATA1: B(j)
695  DDATA2: R(i+j+1) and R(i+j), combined with DMA entry for B(j)
696  DDATA3: A(i)
697  */
698 
699  CRYPTO_SEQ_LOAD_10(
700  /* Temporarily load partial operand B(j) to DATA0. */
701  /* R(i+j+1) is still in DATA1 */
702  CRYPTO_CMD_INSTR_DMA0TODATA,
703  /* Move B(j) to DDATA1 */
704  CRYPTO_CMD_INSTR_DDATA2TODDATA1,
705 
706  /* Restore previous partial result (now R(i+j)) */
707  CRYPTO_CMD_INSTR_DATA1TODATA0,
708 
709  /* Load next partial result R(i+j+1) */
710  CRYPTO_CMD_INSTR_DMA1TODATA,
711 
712  /* Execute partial multiplication A(i)inDDATA1 * B(j)inDDATA3*/
713  CRYPTO_CMD_INSTR_MULO,
714 
715  /* Add the result to the previous partial result */
716  /* AND take the previous carry value into account */
717  /* at the right place (bit 128, ADDIC instruction */
718  CRYPTO_CMD_INSTR_SELDDATA0DDATA2,
719  CRYPTO_CMD_INSTR_ADDIC,
720 
721  /* Save the new partial result (lower half) */
722  CRYPTO_CMD_INSTR_DDATA0TODDATA2,
723  CRYPTO_CMD_INSTR_DATATODMA0,
724  /* Reset the operand selector for next*/
725  CRYPTO_CMD_INSTR_SELDDATA2DDATA3
726  );
727 
728  /**************** End Initializations ******************/
729 
730  for(i=0; i<numPartialOperandsA; i++)
731  {
732  /* Load partial operand #1 A>>(i*PARTIAL_OPERAND_WIDTH) to DDATA1. */
733 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
734  if ( (numWordsLastOperandA != 0) && ( i == numPartialOperandsA-1 ) )
735  CRYPTO_DataWriteVariableSize(cryptoRegDATA2,
736  &A[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
737  numWordsLastOperandA);
738  else
739  CRYPTO_DataWrite(cryptoRegDATA2, &A[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
740 #else
741  CRYPTO_DataWrite(cryptoRegDATA2, &A[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
742 #endif
743 
744  /* Load partial result in R>>(i*PARTIAL_OPERAND_WIDTH) to DATA1. */
745 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
746  if ( (numWordsLastOperandR != 0) && ( i == numPartialOperandsR-1 ) )
747  CRYPTO_DataWriteVariableSize(cryptoRegDATA1,
748  &R[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
749  numWordsLastOperandR);
750  else
751  CRYPTO_DataWrite(cryptoRegDATA1, &R[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
752 #else
753  CRYPTO_DataWrite(cryptoRegDATA1, &R[i*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
754 #endif
755 
756  /* Clear carry */
757  CRYPTO->CMD = CRYPTO_CMD_INSTR_CCLR;
758 
759  /* Setup number of sequence iterations and block size. */
760  CRYPTO->SEQCTRL = CRYPTO_SEQCTRL_BLOCKSIZE_16BYTES
761  | (PARTIAL_OPERAND_WIDTH_IN_BYTES * numPartialOperandsB);
762 
763  /* Execute the MULtiply instruction sequence. */
764  CRYPTO_InstructionSequenceExecute();
765 
766  for (j=0; j<numPartialOperandsB; j++)
767  {
768  /* Load partial operand 2 B>>(j*`PARTIAL_OPERAND_WIDTH) to DDATA2
769  (via DATA0). */
770 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
771  if ( (numWordsLastOperandB != 0) && ( j == numPartialOperandsB-1 ) )
772  CRYPTO_DataWriteVariableSize(cryptoRegDATA0,
773  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
774  numWordsLastOperandB);
775  else
776  CRYPTO_DataWrite(cryptoRegDATA0,
777  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
778 #else
779  CRYPTO_DataWrite(cryptoRegDATA0,
780  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
781 #endif
782 
783  /* Load most significant partial result
784  R>>((i+j+1)*`PARTIAL_OPERAND_WIDTH) into DATA1. */
785 #ifdef USE_VARIABLE_SIZED_DATA_LOADS
786  if ( (numWordsLastOperandR != 0) && ( (i+j+1) == numPartialOperandsR-1 ) )
787  CRYPTO_DataWriteVariableSize(cryptoRegDATA1,
788  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
789  numWordsLastOperandR);
790  else
791  CRYPTO_DataWrite(cryptoRegDATA1,
792  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
793 #else
794  CRYPTO_DataWrite(cryptoRegDATA1,
795  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
796 #endif
797  /* Store least significant partial result */
798  CRYPTO_DataRead(cryptoRegDATA0,
799  &R[(i+j)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
800 
801  } /* for (j=0; j<numPartialOperandsB; j++) */
802 
803  /* Handle carry at the end of the inner loop. */
804  if (CRYPTO_CarryIsSet())
805  cryptoBigintIncrement(&R[(i+numPartialOperandsB+1)
806  *PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS],
807  (numPartialOperandsA-i-1)
808  *PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS);
809 
810  CRYPTO_DataRead(cryptoRegDATA1,
811  &R[(i+numPartialOperandsB)
812  * PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
813 
814  } /* for (i=0; i<numPartialOperandsA; i++) */
815 }
816 
817 /***************************************************************************/
879 void CRYPTO_AES_CBC128(uint8_t * out,
880  const uint8_t * in,
881  unsigned int len,
882  const uint8_t * key,
883  const uint8_t * iv,
884  bool encrypt)
885 {
886  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES128;
887  CRYPTO_AES_CBCx(out, in, len, key, iv, encrypt, cryptoKey128Bits);
888 }
889 
890 /***************************************************************************/
921 void CRYPTO_AES_CBC256(uint8_t * out,
922  const uint8_t * in,
923  unsigned int len,
924  const uint8_t * key,
925  const uint8_t * iv,
926  bool encrypt)
927 {
928  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES256;
929  CRYPTO_AES_CBCx(out, in, len, key, iv, encrypt, cryptoKey256Bits);
930 }
931 
932 /***************************************************************************/
990 void CRYPTO_AES_CFB128(uint8_t * out,
991  const uint8_t * in,
992  unsigned int len,
993  const uint8_t * key,
994  const uint8_t * iv,
995  bool encrypt)
996 {
997  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES128;
998  CRYPTO_AES_CFBx(out, in, len, key, iv, encrypt, cryptoKey128Bits);
999 }
1000 
1001 /***************************************************************************/
1029 void CRYPTO_AES_CFB256(uint8_t * out,
1030  const uint8_t * in,
1031  unsigned int len,
1032  const uint8_t * key,
1033  const uint8_t * iv,
1034  bool encrypt)
1035 {
1036  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES256;
1037  CRYPTO_AES_CFBx(out, in, len, key, iv, encrypt, cryptoKey256Bits);
1038 }
1039 
1040 /***************************************************************************/
1101 void CRYPTO_AES_CTR128(uint8_t * out,
1102  const uint8_t * in,
1103  unsigned int len,
1104  const uint8_t * key,
1105  uint8_t * ctr,
1106  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
1107 {
1108  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES128;
1109  CRYPTO_AES_CTRx(out, in, len, key, ctr, ctrFunc, cryptoKey128Bits);
1110 }
1111 
1112 /***************************************************************************/
1143 void CRYPTO_AES_CTR256(uint8_t * out,
1144  const uint8_t * in,
1145  unsigned int len,
1146  const uint8_t * key,
1147  uint8_t * ctr,
1148  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
1149 {
1150  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES256;
1151  CRYPTO_AES_CTRx(out, in, len, key, ctr, ctrFunc, cryptoKey256Bits);
1152 }
1153 
1154 /***************************************************************************/
1168 void CRYPTO_AES_CTRUpdate32Bit(uint8_t * ctr)
1169 {
1170  uint32_t * _ctr = (uint32_t *) ctr;
1171 
1172  _ctr[3] = __REV(__REV(_ctr[3]) + 1);
1173 }
1174 
1175 /***************************************************************************/
1190 void CRYPTO_AES_DecryptKey128(uint8_t * out, const uint8_t * in)
1191 {
1192  uint32_t * _out = (uint32_t *) out;
1193  const uint32_t * _in = (const uint32_t *) in;
1194 
1195  /* Load key */
1196  CRYPTO_BurstToCrypto(&CRYPTO->KEYBUF, &_in[0]);
1197 
1198  /* Do dummy encryption to generate decrypt key */
1199  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES128;
1200  CRYPTO_IntClear(CRYPTO_IF_INSTRDONE);
1201  CRYPTO->CMD = CRYPTO_CMD_INSTR_AESENC;
1202 
1203  /* Save decryption key */
1204  CRYPTO_BurstFromCrypto(&CRYPTO->KEY, &_out[0]);
1205 }
1206 
1207 /***************************************************************************/
1222 void CRYPTO_AES_DecryptKey256(uint8_t * out, const uint8_t * in)
1223 {
1224  uint32_t * _out = (uint32_t *) out;
1225  const uint32_t * _in = (const uint32_t *) in;
1226 
1227  /* Load key */
1228  CRYPTO_BurstToCrypto(&CRYPTO->KEYBUF, &_in[0]);
1229  CRYPTO_BurstToCrypto(&CRYPTO->KEYBUF, &_in[4]);
1230 
1231  /* Do dummy encryption to generate decrypt key */
1232  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES256;
1233  CRYPTO->CMD = CRYPTO_CMD_INSTR_AESENC;
1234 
1235  /* Save decryption key */
1236  CRYPTO_BurstFromCrypto(&CRYPTO->KEY, &_out[0]);
1237  CRYPTO_BurstFromCrypto(&CRYPTO->KEY, &_out[4]);
1238 }
1239 
1240 /***************************************************************************/
1292 void CRYPTO_AES_ECB128(uint8_t * out,
1293  const uint8_t * in,
1294  unsigned int len,
1295  const uint8_t * key,
1296  bool encrypt)
1297 {
1298  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES128;
1299  CRYPTO_AES_ECBx(out, in, len, key, encrypt, cryptoKey128Bits);
1300 }
1301 
1302 /***************************************************************************/
1330 void CRYPTO_AES_ECB256(uint8_t * out,
1331  const uint8_t * in,
1332  unsigned int len,
1333  const uint8_t * key,
1334  bool encrypt)
1335 {
1336  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES256;
1337  CRYPTO_AES_ECBx(out, in, len, key, encrypt, cryptoKey256Bits);
1338 }
1339 
1340 /***************************************************************************/
1397 void CRYPTO_AES_OFB128(uint8_t * out,
1398  const uint8_t * in,
1399  unsigned int len,
1400  const uint8_t * key,
1401  const uint8_t * iv)
1402 {
1403  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES128;
1404  CRYPTO_AES_OFBx(out, in, len, key, iv, cryptoKey128Bits);
1405 }
1406 
1407 /***************************************************************************/
1432 void CRYPTO_AES_OFB256(uint8_t * out,
1433  const uint8_t * in,
1434  unsigned int len,
1435  const uint8_t * key,
1436  const uint8_t * iv)
1437 {
1438  CRYPTO->CTRL = CRYPTO_CTRL_AES_AES256;
1439  CRYPTO_AES_OFBx(out, in, len, key, iv, cryptoKey256Bits);
1440 }
1441 
1442 /*******************************************************************************
1443  ************************** LOCAL FUNCTIONS *******************************
1444  ******************************************************************************/
1445 
1446 /***************************************************************************/
1479 static void CRYPTO_AES_CBCx(uint8_t * out,
1480  const uint8_t * in,
1481  unsigned int len,
1482  const uint8_t * key,
1483  const uint8_t * iv,
1484  bool encrypt,
1485  CRYPTO_KeyWidth_TypeDef keyWidth)
1486 {
1487  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1488 
1489  /* Initialize control registers. */
1490  CRYPTO->WAC = 0;
1491 
1492  CRYPTO_KeyBufWrite((uint32_t *)key, keyWidth);
1493 
1494  if (encrypt)
1495  {
1496  CRYPTO_DataWrite(cryptoRegDATA0, (uint32_t *)iv);
1497 
1498  CRYPTO->SEQ0 =
1499  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR0_SHIFT |
1500  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT;
1501 
1502  CRYPTO_AES_ProcessLoop(len,
1503  cryptoRegDATA1, (uint32_t *) in,
1504  cryptoRegDATA0, (uint32_t *) out);
1505  }
1506  else
1507  {
1508  CRYPTO_DataWrite(cryptoRegDATA2, (uint32_t *) iv);
1509 
1510  CRYPTO->SEQ0 =
1511  CRYPTO_CMD_INSTR_DATA1TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1512  CRYPTO_CMD_INSTR_AESDEC << _CRYPTO_SEQ0_INSTR1_SHIFT |
1513  CRYPTO_CMD_INSTR_DATA2TODATA0XOR << _CRYPTO_SEQ0_INSTR2_SHIFT |
1514  CRYPTO_CMD_INSTR_DATA1TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
1515 
1516  CRYPTO->SEQ1 = 0;
1517 
1518  /* The following call is equivalent to the last call in the
1519  'if( encrypt )' branch. However moving this
1520  call outside the conditional scope results in slightly poorer
1521  performance for some compiler optimizations. */
1522  CRYPTO_AES_ProcessLoop(len,
1523  cryptoRegDATA1, (uint32_t *) in,
1524  cryptoRegDATA0, (uint32_t *) out);
1525  }
1526 }
1527 
1528 /***************************************************************************/
1559 static void CRYPTO_AES_CFBx(uint8_t * out,
1560  const uint8_t * in,
1561  unsigned int len,
1562  const uint8_t * key,
1563  const uint8_t * iv,
1564  bool encrypt,
1565  CRYPTO_KeyWidth_TypeDef keyWidth)
1566 {
1567  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1568 
1569  /* Initialize control registers. */
1570  CRYPTO->WAC = 0;
1571 
1572  /* Load Key */
1573  CRYPTO_KeyBufWrite((uint32_t *)key, keyWidth);
1574 
1575  /* Load instructions to CRYPTO sequencer. */
1576  if (encrypt)
1577  {
1578  /* Load IV */
1579  CRYPTO_DataWrite(cryptoRegDATA0, (uint32_t *)iv);
1580 
1581  CRYPTO->SEQ0 =
1582  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR0_SHIFT |
1583  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR1_SHIFT;
1584 
1585  CRYPTO_AES_ProcessLoop(len,
1586  cryptoRegDATA1, (uint32_t *)in,
1587  cryptoRegDATA0, (uint32_t *)out
1588  );
1589  }
1590  else
1591  {
1592  /* Load IV */
1593  CRYPTO_DataWrite(cryptoRegDATA2, (uint32_t *)iv);
1594 
1595  CRYPTO->SEQ0 =
1596  CRYPTO_CMD_INSTR_DATA2TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1597  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT |
1598  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ0_INSTR2_SHIFT |
1599  CRYPTO_CMD_INSTR_DATA1TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
1600  CRYPTO->SEQ1 = 0;
1601 
1602  CRYPTO_AES_ProcessLoop(len,
1603  cryptoRegDATA1, (uint32_t *)in,
1604  cryptoRegDATA0, (uint32_t *)out
1605  );
1606  }
1607 }
1608 
1609 /***************************************************************************/
1643 static void CRYPTO_AES_CTRx(uint8_t * out,
1644  const uint8_t * in,
1645  unsigned int len,
1646  const uint8_t * key,
1647  uint8_t * ctr,
1648  CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc,
1649  CRYPTO_KeyWidth_TypeDef keyWidth)
1650 {
1651  (void) ctrFunc;
1652 
1653  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1654 
1655  /* Initialize control registers. */
1656  CRYPTO->CTRL |= CRYPTO_CTRL_INCWIDTH_INCWIDTH4;
1657  CRYPTO->WAC = 0;
1658 
1659  CRYPTO_KeyBufWrite((uint32_t *)key, keyWidth);
1660 
1661  CRYPTO_DataWrite(cryptoRegDATA1, (uint32_t *) ctr);
1662 
1663  CRYPTO->SEQ0 = CRYPTO_CMD_INSTR_DATA1TODATA0 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1664  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR1_SHIFT |
1665  CRYPTO_CMD_INSTR_DATA0TODATA3 << _CRYPTO_SEQ0_INSTR2_SHIFT |
1666  CRYPTO_CMD_INSTR_DATA1INC << _CRYPTO_SEQ0_INSTR3_SHIFT;
1667 
1668  CRYPTO->SEQ1 = CRYPTO_CMD_INSTR_DATA2TODATA0XOR << _CRYPTO_SEQ1_INSTR4_SHIFT;
1669 
1670  CRYPTO_AES_ProcessLoop(len,
1671  cryptoRegDATA2, (uint32_t *) in,
1672  cryptoRegDATA0, (uint32_t *) out);
1673 
1674  CRYPTO_DataRead(cryptoRegDATA1, (uint32_t *) ctr);
1675 }
1676 
1677 /***************************************************************************/
1707 static void CRYPTO_AES_ECBx(uint8_t * out,
1708  const uint8_t * in,
1709  unsigned int len,
1710  const uint8_t * key,
1711  bool encrypt,
1712  CRYPTO_KeyWidth_TypeDef keyWidth)
1713 {
1714  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1715 
1716  CRYPTO->WAC = 0;
1717 
1718  CRYPTO_KeyBufWrite((uint32_t *)key, keyWidth);
1719 
1720  if (encrypt)
1721  {
1722  CRYPTO->SEQ0 =
1723  (CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR0_SHIFT |
1724  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ0_INSTR1_SHIFT);
1725  }
1726  else
1727  {
1728  CRYPTO->SEQ0 =
1729  (CRYPTO_CMD_INSTR_AESDEC << _CRYPTO_SEQ0_INSTR0_SHIFT |
1730  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ0_INSTR1_SHIFT);
1731  }
1732 
1733  CRYPTO_AES_ProcessLoop(len,
1734  cryptoRegDATA0, (uint32_t *) in,
1735  cryptoRegDATA1, (uint32_t *) out);
1736 }
1737 
1738 /***************************************************************************/
1766 static void CRYPTO_AES_OFBx(uint8_t * out,
1767  const uint8_t * in,
1768  unsigned int len,
1769  const uint8_t * key,
1770  const uint8_t * iv,
1771  CRYPTO_KeyWidth_TypeDef keyWidth)
1772 {
1773  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1774 
1775  CRYPTO->WAC = 0;
1776 
1777  CRYPTO_KeyBufWrite((uint32_t *)key, keyWidth);
1778 
1779  CRYPTO_DataWrite(cryptoRegDATA2, (uint32_t *)iv);
1780 
1781  CRYPTO->SEQ0 =
1782  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ0_INSTR0_SHIFT |
1783  CRYPTO_CMD_INSTR_DATA2TODATA0 << _CRYPTO_SEQ0_INSTR1_SHIFT |
1784  CRYPTO_CMD_INSTR_AESENC << _CRYPTO_SEQ0_INSTR2_SHIFT |
1785  CRYPTO_CMD_INSTR_DATA0TODATA2 << _CRYPTO_SEQ0_INSTR3_SHIFT;
1786  CRYPTO->SEQ1 =
1787  CRYPTO_CMD_INSTR_DATA1TODATA0XOR << _CRYPTO_SEQ1_INSTR4_SHIFT |
1788  CRYPTO_CMD_INSTR_DATA0TODATA1 << _CRYPTO_SEQ1_INSTR5_SHIFT;
1789 
1790  CRYPTO_AES_ProcessLoop(len,
1791  cryptoRegDATA0, (uint32_t *) in,
1792  cryptoRegDATA1, (uint32_t *) out);
1793 }
1794 
1795 /***************************************************************************/
1820 static inline void CRYPTO_AES_ProcessLoop(uint32_t len,
1821  CRYPTO_DataReg_TypeDef inReg,
1822  uint32_t * in,
1823  CRYPTO_DataReg_TypeDef outReg,
1824  uint32_t * out)
1825 {
1826  len /= CRYPTO_AES_BLOCKSIZE;
1827  CRYPTO->SEQCTRL = 16 << _CRYPTO_SEQCTRL_LENGTHA_SHIFT;
1828 
1829  while (len--)
1830  {
1831  /* Load data and trigger encryption */
1832  CRYPTO_DataWrite(inReg, (uint32_t *)in);
1833 
1834  CRYPTO->CMD = CRYPTO_CMD_SEQSTART;
1835 
1836  /* Save encrypted/decrypted data */
1837  CRYPTO_DataRead(outReg, (uint32_t *)out);
1838 
1839  out += 4;
1840  in += 4;
1841  }
1842 }
1843 
1847 #endif /* defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0) */
Emlib peripheral API "assert" implementation.
Bitband Peripheral API.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
Cryptography accelerator peripheral API.