EFM32 Pearl Gecko Software Documentation  efm32pg1-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,
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,
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 /***************************************************************************/
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:
318 #ifdef _CRYPTO_WAC_MODULUS_ECCBIN233N
323 #endif
324  CRYPTO->WAC = temp | modType | CRYPTO_WAC_MODOP_BINARY;
325  break;
326 
330 #ifdef _CRYPTO_WAC_MODULUS_ECCPRIME256P
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 /***************************************************************************/
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. */
394  CRYPTO->SEQCTRL = 0;
395  CRYPTO->SEQCTRLB = 0;
396 
397  /* Set result width of MADD32 operation. */
399 
400  /* Write init value to DDATA1. */
402 
403  /* Copy data to DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
404  CRYPTO_EXECUTE_2(CRYPTO_CMD_INSTR_DDATA1TODDATA0,
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,
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. */
443 
444  /* Execute SHA */
445  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
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. */
466 
467  /* Execute SHA */
468  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
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,
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). */
512  CRYPTO->SEQCTRL = 0;
513  CRYPTO->SEQCTRLB = 0;
514 
515  /* Set result width of MADD32 operation. */
517 
518  /* Write init value to DDATA1. */
520 
521  /* Copy data ot DDATA0 and select DDATA0 and DDATA1 for SHA operation. */
522  CRYPTO_EXECUTE_2(CRYPTO_CMD_INSTR_DDATA1TODDATA0,
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,
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. */
560 
561  /* Execute SHA */
562  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
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. */
583 
584  /* Execute SHA */
585  CRYPTO_EXECUTE_3(CRYPTO_CMD_INSTR_SHA,
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. */
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 =
684 
685  CRYPTO_EXECUTE_4(
686  CRYPTO_CMD_INSTR_CCLR, /* Carry = 0 */
687  CRYPTO_CMD_INSTR_CLR, /* DDATA0 = 0 */
688  /* clear result accumulation register */
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 */
703  /* Move B(j) to DDATA1 */
705 
706  /* Restore previous partial result (now R(i+j)) */
708 
709  /* Load next partial result R(i+j+1) */
711 
712  /* Execute partial multiplication A(i)inDDATA1 * B(j)inDDATA3*/
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 */
720 
721  /* Save the new partial result (lower half) */
724  /* Reset the operand selector for next*/
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 */
758 
759  /* Setup number of sequence iterations and block size. */
761  | (PARTIAL_OPERAND_WIDTH_IN_BYTES * numPartialOperandsB);
762 
763  /* Execute the MULtiply instruction sequence. */
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
777  &B[j*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
778 #else
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
792  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
793 #else
795  &R[(i+j+1)*PARTIAL_OPERAND_WIDTH_IN_32BIT_WORDS]);
796 #endif
797  /* Store least significant partial result */
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 
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 {
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 {
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 {
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 {
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,
1107 {
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,
1149 {
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 */
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 */
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 {
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 {
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 {
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 {
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 =
1501 
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 =
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. */
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 =
1584 
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 =
1600  CRYPTO->SEQ1 = 0;
1601 
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,
1649  CRYPTO_KeyWidth_TypeDef keyWidth)
1650 {
1651  (void) ctrFunc;
1652 
1653  EFM_ASSERT(!(len % CRYPTO_AES_BLOCKSIZE));
1654 
1655  /* Initialize control registers. */
1657  CRYPTO->WAC = 0;
1658 
1659  CRYPTO_KeyBufWrite((uint32_t *)key, keyWidth);
1660 
1661  CRYPTO_DataWrite(cryptoRegDATA1, (uint32_t *) ctr);
1662 
1667 
1669 
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 =
1725  }
1726  else
1727  {
1728  CRYPTO->SEQ0 =
1731  }
1732 
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 =
1786  CRYPTO->SEQ1 =
1789 
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) */
#define CRYPTO_CMD_INSTR_DATA0TODATA3
#define CRYPTO_CMD_INSTR_DATA1TODATA0
#define CRYPTO_WAC_RESULTWIDTH_256BIT
#define CRYPTO_CMD_INSTR_AESENC
#define _CRYPTO_SEQ1_INSTR5_SHIFT
void CRYPTO_AES_CFB128(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, bool encrypt)
AES Cipher feedback (CFB) cipher mode encryption/decryption, 128 bit key.
Definition: em_crypto.c:990
void CRYPTO_AES_CBC128(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, bool encrypt)
AES Cipher-block chaining (CBC) cipher mode encryption/decryption, 128 bit key.
Definition: em_crypto.c:879
#define CRYPTO_CMD_INSTR_DATA0TODATA1
Emlib peripheral API "assert" implementation.
#define CRYPTO_CMD_INSTR_DATA0TODATA2
__STATIC_INLINE void CRYPTO_DataRead(CRYPTO_DataReg_TypeDef dataReg, CRYPTO_Data_TypeDef val)
Read 128 bits of data from a DATAX register in the CRYPTO module.
Definition: em_crypto.h:621
#define CRYPTO_CTRL_SHA_SHA1
void CRYPTO_AES_CTRUpdate32Bit(uint8_t *ctr)
Update last 32 bits of 128 bit counter, by incrementing with 1.
Definition: em_crypto.c:1168
#define CRYPTO_CTRL_AES_AES256
#define _CRYPTO_SEQ0_INSTR1_SHIFT
#define CRYPTO_CMD_INSTR_DATATODMA0
#define _CRYPTO_SEQ0_INSTR3_SHIFT
__STATIC_INLINE void cryptoBigintIncrement(uint32_t *words32bits, int num32bitWords)
Increment value of 32bit word array by one.
Definition: em_crypto.c:614
#define _CRYPTO_SEQCTRL_LENGTHA_SHIFT
static void CRYPTO_AES_OFBx(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, CRYPTO_KeyWidth_TypeDef keyWidth)
Output feedback (OFB) cipher mode encryption/decryption, 128/256 bit key.
Definition: em_crypto.c:1766
#define _CRYPTO_WAC_MODULUS_MASK
#define CRYPTO_CMD_INSTR_DDATA0TODDATA2
#define CRYPTO_CMD_INSTR_DDATA2TODDATA1
Bitband Peripheral API.
uint32_t CRYPTO_Data_TypeDef[CRYPTO_DATA_SIZE_IN_32BIT_WORDS]
Definition: em_crypto.h:289
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define CRYPTO_CMD_SEQSTART
#define _CRYPTO_SEQ0_INSTR2_SHIFT
void CRYPTO_ModulusSet(CRYPTO_ModulusType_TypeDef modType)
Set the modulus type used for wide arithmetic operations.
Definition: em_crypto.c:307
void CRYPTO_KeyRead(CRYPTO_KeyBuf_TypeDef val, CRYPTO_KeyWidth_TypeDef keyWidth)
Read the key value currently used by the CRYPTO module.
Definition: em_crypto.c:354
#define CRYPTO_IF_INSTRDONE
void CRYPTO_AES_OFB128(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv)
AES Output feedback (OFB) cipher mode encryption/decryption, 128 bit key.
Definition: em_crypto.c:1397
static void CRYPTO_AES_CTRx(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)
Counter (CTR) cipher mode encryption/decryption, 128/256 bit key.
Definition: em_crypto.c:1643
__STATIC_INLINE void CRYPTO_QDataWrite(CRYPTO_QDataReg_TypeDef qdataReg, CRYPTO_QData_TypeDef val)
Write 512 bits of data to a QDATAX register in the CRYPTO module.
Definition: em_crypto.h:677
static void CRYPTO_AES_CBCx(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, bool encrypt, CRYPTO_KeyWidth_TypeDef keyWidth)
Cipher-block chaining (CBC) cipher mode encryption/decryption, 128/256 bit key.
Definition: em_crypto.c:1479
static void CRYPTO_AES_ProcessLoop(uint32_t len, CRYPTO_DataReg_TypeDef inReg, uint32_t *in, CRYPTO_DataReg_TypeDef outReg, uint32_t *out)
Function performs generic AES loop.
Definition: em_crypto.c:1820
#define CRYPTO_CMD_INSTR_ADDIC
CRYPTO_ModulusType_TypeDef
Definition: em_crypto.h:367
#define CRYPTO_WAC_MODOP_BINARY
__STATIC_INLINE void CRYPTO_IntClear(uint32_t flags)
Clear one or more pending CRYPTO interrupts.
Definition: em_crypto.h:1015
void CRYPTO_AES_ECB128(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, bool encrypt)
AES Electronic Codebook (ECB) cipher mode encryption/decryption, 128 bit key.
Definition: em_crypto.c:1292
#define CRYPTO_CMD_INSTR_SELDDATA2DDATA3
#define CRYPTO_CTRL_DMA1RSEL_DATA1
__STATIC_INLINE void CRYPTO_BurstFromCrypto(volatile uint32_t *reg, uint32_t *val)
Read a 128 bit value from a crypto register.
Definition: em_crypto.h:577
__STATIC_INLINE void CRYPTO_DDataRead(CRYPTO_DDataReg_TypeDef ddataReg, CRYPTO_DData_TypeDef val)
Read 256 bits of data from a DDATAX register in the CRYPTO module.
Definition: em_crypto.h:658
#define CRYPTO_CTRL_DMA0MODE_FULL
#define CRYPTO_CMD_INSTR_DDATA0TODDATA1
void CRYPTO_SHA_256(const uint8_t *msg, uint64_t msgLen, CRYPTO_SHA256_Digest_TypeDef digest)
Perform a SHA-256 hash operation on a message.
Definition: em_crypto.c:495
void CRYPTO_AES_DecryptKey256(uint8_t *out, const uint8_t *in)
Generate 256 bit AES decryption key from 256 bit encryption key. The decryption key is used for some ...
Definition: em_crypto.c:1222
#define CRYPTO_CMD_INSTR_SHA
CRYPTO_KeyWidth_TypeDef
Definition: em_crypto.h:414
#define CRYPTO_CMD_INSTR_DATA1INC
__STATIC_INLINE void CRYPTO_DataWrite(CRYPTO_DataReg_TypeDef dataReg, const CRYPTO_Data_TypeDef val)
Write 128 bits of data to a DATAX register in the CRYPTO module.
Definition: em_crypto.h:603
uint8_t CRYPTO_SHA1_Digest_TypeDef[CRYPTO_SHA1_DIGEST_SIZE_IN_BYTES]
Definition: em_crypto.h:448
#define CRYPTO_CMD_INSTR_DATA1TODATA0XOR
#define CRYPTO_CMD_INSTR_SELDDATA1DDATA3
#define CRYPTO_CMD_INSTR_DMA0TODATA
static void CRYPTO_AES_CFBx(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, bool encrypt, CRYPTO_KeyWidth_TypeDef keyWidth)
Cipher feedback (CFB) cipher mode encryption/decryption, 128/256 bit key.
Definition: em_crypto.c:1559
CRYPTO_DataReg_TypeDef
Definition: em_crypto.h:330
#define CRYPTO_CTRL_AES_AES128
#define CRYPTO_CTRL_SHA_SHA2
#define CRYPTO_CMD_INSTR_DATA2TODATA0XOR
Cryptography accelerator peripheral API.
void CRYPTO_AES_CFB256(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, bool encrypt)
AES Cipher feedback (CFB) cipher mode encryption/decryption, 256 bit key.
Definition: em_crypto.c:1029
#define CRYPTO_CMD_INSTR_DDATA1TODDATA0
__STATIC_INLINE void CRYPTO_KeyBufWrite(CRYPTO_KeyBuf_TypeDef val, CRYPTO_KeyWidth_TypeDef keyWidth)
Set the key value to be used by the CRYPTO module.
Definition: em_crypto.h:717
void(* CRYPTO_AES_CtrFuncPtr_TypeDef)(uint8_t *ctr)
AES counter modification function pointer.
Definition: em_crypto.h:464
__STATIC_INLINE void CRYPTO_BurstToCrypto(volatile uint32_t *reg, const uint32_t *val)
Write a 128 bit value into a crypto register.
Definition: em_crypto.h:546
void CRYPTO_SHA_1(const uint8_t *msg, uint64_t msgLen, CRYPTO_SHA1_Digest_TypeDef digest)
Perform a SHA-1 hash operation on a message.
Definition: em_crypto.c:378
#define CRYPTO_WAC_MULWIDTH_MUL128
#define CRYPTO_CTRL_DMA0RSEL_DATA0
uint32_t CRYPTO_KeyBuf_TypeDef[CRYPTO_KEYBUF_SIZE_IN_32BIT_WORDS]
Definition: em_crypto.h:323
void CRYPTO_Mul(uint32_t *A, int aSize, uint32_t *B, int bSize, uint32_t *R, int rSize)
Multiply two big integers.
Definition: em_crypto.c:641
__STATIC_INLINE void CRYPTO_ResultWidthSet(CRYPTO_ResultWidth_TypeDef resultWidth)
Set the width of the results of the non-modulus instructions.
Definition: em_crypto.h:507
#define CRYPTO_CMD_INSTR_CCLR
void CRYPTO_AES_ECB256(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, bool encrypt)
AES Electronic Codebook (ECB) cipher mode encryption/decryption, 256 bit key.
Definition: em_crypto.c:1330
#define CRYPTO_CMD_INSTR_AESDEC
__STATIC_INLINE void CRYPTO_DDataWrite(CRYPTO_DDataReg_TypeDef ddataReg, const CRYPTO_DData_TypeDef val)
Write 256 bits of data to a DDATAX register in the CRYPTO module.
Definition: em_crypto.h:639
__STATIC_INLINE bool CRYPTO_CarryIsSet(void)
Quick read access of the Carry bit from arithmetic operations.
Definition: em_crypto.h:762
void CRYPTO_AES_CTR128(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, uint8_t *ctr, CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
AES Counter (CTR) cipher mode encryption/decryption, 128 bit key.
Definition: em_crypto.c:1101
#define _CRYPTO_SEQ1_INSTR4_SHIFT
#define CRYPTO_CMD_INSTR_MULO
#define CRYPTO
#define CRYPTO_SEQCTRL_BLOCKSIZE_16BYTES
#define CRYPTO_CMD_INSTR_CLR
#define _CRYPTO_WAC_MODOP_MASK
void CRYPTO_AES_CBC256(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv, bool encrypt)
AES Cipher-block chaining (CBC) cipher mode encryption/decryption, 256 bit key.
Definition: em_crypto.c:921
#define CRYPTO_CMD_INSTR_MADD32
#define CRYPTO_CMD_INSTR_SELDDATA0DDATA2
void CRYPTO_AES_OFB256(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, const uint8_t *iv)
AES Output feedback (OFB) cipher mode encryption/decryption, 256 bit key.
Definition: em_crypto.c:1432
#define CRYPTO_CTRL_DMA1MODE_FULL
static void CRYPTO_AES_ECBx(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, bool encrypt, CRYPTO_KeyWidth_TypeDef keyWidth)
Electronic Codebook (ECB) cipher mode encryption/decryption, 128/256 bit key.
Definition: em_crypto.c:1707
__STATIC_INLINE void CRYPTO_InstructionSequenceExecute(void)
Execute the current programmed instruction sequence.
Definition: em_crypto.h:872
uint8_t CRYPTO_SHA256_Digest_TypeDef[CRYPTO_SHA256_DIGEST_SIZE_IN_BYTES]
Definition: em_crypto.h:451
#define _CRYPTO_SEQ0_INSTR0_SHIFT
void CRYPTO_AES_DecryptKey128(uint8_t *out, const uint8_t *in)
Generate 128 bit AES decryption key from 128 bit encryption key. The decryption key is used for some ...
Definition: em_crypto.c:1190
__STATIC_INLINE void cryptoBigintZeroize(uint32_t *words32bits, int num32bitWords)
Set 32bit word array to zero.
Definition: em_crypto.c:600
#define CRYPTO_CMD_INSTR_DATA2TODATA0
#define CRYPTO_WAC_MODOP_REGULAR
#define CRYPTO_CMD_INSTR_DATA1TODATA2
#define CRYPTO_CMD_INSTR_DMA1TODATA
#define CRYPTO_CTRL_INCWIDTH_INCWIDTH4
#define CRYPTO_CMD_INSTR_SELDDATA0DDATA1
void CRYPTO_AES_CTR256(uint8_t *out, const uint8_t *in, unsigned int len, const uint8_t *key, uint8_t *ctr, CRYPTO_AES_CtrFuncPtr_TypeDef ctrFunc)
AES Counter (CTR) cipher mode encryption/decryption, 256 bit key.
Definition: em_crypto.c:1143