cancel
Showing results for 
Search instead for 
Did you mean: 

Cypher using AES 128 CTR

Dosan
Associate III

Hi,

Im trying to encryp using AES 128 CTR but i dont get the same result that online calculators.

Im using this online calculator: https://cryptii.com/pipes/aes-encryption

My code is the next:

uint8_t IVKey[] = {0xDD, 0xF9, 0x11, 0xA6, 0xDD, 0xF9, 0x11, 0xA6, 0xDD, 0xF9, 0x11, 0xA6, 0xDD, 0xF9, 0x11, 0xA6};

	AesDeInit();

	// CTR AES
  hcryp.Instance = AES;
  hcryp.Init.DataType = CRYP_DATATYPE_1B;
  hcryp.Init.KeySize = CRYP_KEYSIZE_128B;
  hcryp.Init.pKey = (uint32_t *)AESKey;
  hcryp.Init.Algorithm = CRYP_AES_CTR;
  hcryp.Init.pInitVect = (uint32_t *)IVKey;

  if (HAL_CRYP_Init(&hcryp) != HAL_OK)
  {
    Error_Handler();
  }

and the AESKey is the next:

const uint8_t AESKey[] =
{0x44, 0x26, 0x44, 0x20, 0x45, 0x6C, 0x65, 0x74, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x63, 0x61, 0x20
};

My AES function is the next:

int16_t AesEncrypt(char *In,int16_t Len)
{
	uint8_t Buf[16];

	if (Len & 0x0F)					
		Len+=16-(Len & 0x0F);

	if (HAL_CRYP_DeInit(&hcryp)!=HAL_OK)
		Len=0;
	else if (HAL_CRYP_Init(&hcryp)!=HAL_OK)
		Len=0;
	else
	{
		for (int16_t i=Len;i>0;i-=16)				// Encripta paquete
		{
			if (HAL_CRYP_Encrypt(&hcryp,(uint32_t *)In,16,(uint32_t *)Buf,255)!=HAL_OK)
			{
				Len=0;
				break;
			}
			memcpy(In,Buf,16);
			In+=16;
		}
	}

	return Len;
}

and the string insert into the function is

char Message2[] = {0x50, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x01, 0x03, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00};

The result with the online calculator is: 6c 9d 95 e6 9a 75 ed 03 7c a2 81 80 f9 a6 c3 18

The result that im getting is: c4, b0, c3, 8d, 2d, b2, 5b, 20, 89,75, 57 76, 83, 06, be, 1e

My result is wrong t i dont know what am i doing wrong.

Any suggestion?

Thanks,

Best Regards,

1 ACCEPTED SOLUTION

Accepted Solutions
Dosan
Associate III

Hi all,

Its working now.

My problem was that the AESKey and IVKey were declared as uint8_t and works with uint32_t

and both keys must be declared as a global variables, not a local variable.

Thanks,

Best REgards,

View solution in original post

11 REPLIES 11
AA1
Senior III

Instead of use CRYP_DATATYPE_1B, use CRYP_DATATYPE_8B.
Also verify if all needed struct fields are initialized.

Confirming on-line result with C library here, Decrypting in this case, but symmetrical..

KEY
0000 : 44 26 44 20 45 6C 65 74-74 72 6F 6E 69 63 61 20 D&D Elettronica

IV
0000 : DD F9 11 A6 DD F9 11 A6-DD F9 11 A6 DD F9 11 A6 ................

CRYPT-TEXT
0000 : 50 00 30 30 30 30 30 31-01 03 08 20 00 00 00 00 P.000001... ....

PLAIN-TEXT
0000 : 6C 9D 95 E6 9A 75 ED 03-7C A2 81 80 F9 A6 C3 18 l....u..|.......

  

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

How do you get to this result?

I tested the premise using my AES library, on a PC, because I don't have much trust in on-line calculators, and I don't have a crypto G0 to hand currently. And I haven't enough coffee yet..

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Dosan
Associate III

Hi all,

Its working now.

My problem was that the AESKey and IVKey were declared as uint8_t and works with uint32_t

and both keys must be declared as a global variables, not a local variable.

Thanks,

Best REgards,

I'm going to revisit this as doing CTR a year later, had some patterns working well on SAMD51, which also lacked good examples for the HW engine.  https://github.com/cturvey/RandomNinjaChef/blob/main/SAMD51_AES_128_CTR.ino

Anyway on the U545

uint8_t key[] = { //"828fee1792c05eaafe93a438683d1703" from JSON
  0x82,0x8F,0xEE,0x17,0x92,0xC0,0x5E,0xAA,0xFE,0x93,0xA4,0x38,0x68,0x3D,0x17,0x03 };
uint32_t shufkey[] = { // 32-bit words, with endian byte swap
  0x828FEE17, 0x92C05EAA, 0xFE93A438, 0x683D1703 };

uint8_t iv[] = {
  0x00,0x6B,0x10,0xC0,0xC3,0x98,0x10,0x6C,0x2D,0xC0,0x00,0x00,0x00,0x00,0x00,0x01 };
uint32_t shufiv[] = {
  0x006B10C0,0xC398106C,0x2DC00000,0x00000001 };

void TestAES128CTR(void)
{
  /* Peripheral clock enable */
   __HAL_RCC_AES_CLK_ENABLE();

  hcryp.Instance              = AES;

  hcryp.Init.DataType         = CRYP_DATATYPE_8B; // PASS:shufkey/shufiv
  hcryp.Init.KeySize          = CRYP_KEYSIZE_128B;
  hcryp.Init.pKey             = (uint32_t *)shufkey;
  hcryp.Init.pInitVect        = (uint32_t *)shufiv;
  hcryp.Init.Algorithm        = CRYP_AES_CTR;
  hcryp.Init.DataWidthUnit    = CRYP_DATAWIDTHUNIT_BYTE; // WORD; impacts sizeof()
  hcryp.Init.HeaderWidthUnit  = CRYP_HEADERWIDTHUNIT_WORD;
  hcryp.Init.KeyIVConfigSkip  = CRYP_KEYIVCONFIG_ALWAYS;
  hcryp.Init.KeyMode          = CRYP_KEYMODE_NORMAL;

  if (HAL_CRYP_Init(&hcryp) != HAL_OK)
  {
    Error_Handler(__FILE__,__LINE__);
  }

#define TIMEOUT_VALUE 1000

  memset(junk, 0, sizeof(junk)); // Clear destination to affirm scope
	
  if (HAL_CRYP_Encrypt(&hcryp, (void *)in, sizeof(in), (void *)junk, TIMEOUT_VALUE) == HAL_OK)
  {
    /* Display encrypted Data */
    DumpData(sizeof(junk), junk);
    if (memcmp(out,junk,sizeof(out)) == 0) puts("PASS"); else puts("FAIL");
  }
  else
  {
    /* Processing Error */
    Error_Handler(__FILE__,__LINE__);
  }
}

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

@Jocelyn RICARD does the library provide any "Swap Management" on the KEY and IV? Or is getting the KEY/IV WORD's into BIG ENDIAN all on the user?

https://github.com/cturvey/RandomNinjaChef/blob/main/STM32U5_AES_128_CTR.c

I might have to try harder with the padding, because it works when I don't bother with it, but the XOR pattern is coming from the AES crypt of the IV, in a stateful 16-byte line, incrementing the count, not the source data in the plain text (encrypt / decrypt being identical / symmetrical in nature in CTR)

u5_aes_ctr_001.jpgu5_aes_ctr_003.jpg

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hello @Tesla DeLorean ,

For first point, I guess you already know the answer. This key in put as a stream of bytes is not provided in the HAL.

I can see 2 solutions for that.

1) Just add a code to reverse the key and iv at input:

   uint32_t buildKey[4] ;
   uint32_t buildIv[4] ;
   for(uint32_t i=0; i<4; i++)
   {
	   buildKey[i]= __REV(*(uint32_t*)&key[i*4]);
	   buildIv[i]=__REV(*(uint32_t *)&iv[i*4]);
   }

2) Do this directly in CRYP_SetKey and in CRYP_SetIV but changing HAL may not be a good idea...

 

Regarding your second point, I don' catch exactly what you want. Could you please detail ?

Thank you

Best regards

Jocelyn

 

>>Regarding your second point, I don' catch exactly what you want. Could you please detail ?

Just that I find the libraries some what quixotic and inconsistent. It makes cross-platform use and demonstration more frustrating than necessary. I'm not a huge fan of "online calculators" as there's a lot of variables and moving parts, but people do use them to test/validate what they're doing, and I have to work with real-world usage of the technologies, and the rigidity of HW implementations with different sets of expectations. This and PKA are fraught with issues of interpretations and expectations, and zero tolerance for any mismatch.

In terms of when things get swapped/shuffled, that a KEY/IV that's literally in the correct byte order for the large endian mode/representation, in a form data crosses the wire, writes to a file, that that's not the acceptable form, and the library code doesn't have a flag to move it to a form the engine demands. Thank goodness the data portion has a swap-management.

The documentation/library could do with some illustration of exactly what "swap management" does at a bit/byte/word level, it's applicability to data and key/iv patterns, and inconsistency there.  RM0456, not sure if the is better illustrations elsewhere.

u5_aes_ctr_002.jpg

My second observation regards zero pad, I'd really like to use the input data in-situ, not move it to a secondary buffer, the benefit of CTR is that it needs only XOR the content, it's not doing bitswitching/crypting over the entire 128-bit / 16-byte line.

The unit doesn't look to need padding, the unit outputs 32-bit words, so there's slight overspill on the data return buffer, but the bytes that need encrypting/decrypting are done so correctly. The last line on my pattern has 6-bytes, I get 8-bytes touched by the library, the 6 I want, and it adds 2 junk bytes, I can live with that, but I think the "needs padding" observation in the docs overstates the actual need/requirement. Perhaps it impacts other uses?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..