I’ve been trying to get matching results between the TI-MSP432’s encryption engine and a python equivalent on my laptop. It has been a bit frustrating but I think I’ve got it. The main cause of my frustration is that the AES registers are declared as if they represented 16 bit quantities and so the compiler was generating 2 byte writes to the registers. For example, the AESAKEY register is declared in msp432p401r_classic.h as follows:
#define AESAKEY (HWREG16(0x40003C06))
This messed up the engine’s state when I wanted to write bytes. Anyway, it works now and here is some Energia code that outputs the same answer as a python script (which is included in the comments). The code needs a little work and I hope to set up an encrypted link between the MSP432 and the PC over the UART.
#include <msp432.h> /*key and message obtained from NIST test vectors in http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf */ /* Using AES 128 ECB Encryption */ /* Tested against the following python code: # This produces the same answer as http://aes.online-domain-tools.com/ # but not the same as NIST test vector for ECB from Crypto.Cipher import AES import binascii key = binascii.unhexlify('8d2e60365f17c7df1040d7501b4a7b5a') IV = 16 * '\x00' mode = AES.MODE_ECB encryptor = AES.new(key, mode, IV=IV) text = binascii.unhexlify('59b5088e6dadc3ad5f27a460872d5929') #text=b'Plain text msg ' ciphertext = encryptor.encrypt(text) print(binascii.hexlify(ciphertext)) */ const char key[]="8d2e60365f17c7df1040d7501b4a7b5a"; const char testmsg[]="59b5088e6dadc3ad5f27a460872d5929"; uint32_t ByteStringToNumber(const char *Str) { uint32_t UpperNibble = 0; uint32_t LowerNibble = 0; if (Str[0] > '9') UpperNibble = ( Str[0] | 32 ) - 'a' + 10; // ensure lower case, remove hex 'a' and offset by 10 else UpperNibble = ( Str[0] - '0'); if (Str[1] > '9') LowerNibble = ( Str[1] | 32 ) - 'a' + 10; // ensure lower case, remove hex 'a' and offset by 10 else LowerNibble = ( Str[1] - '0'); return (UpperNibble << 4) + LowerNibble; } void setKey(const char * keystr) { // The key will take the form of a 32 character ASCII string produced // by a tool like openssl. // This routine will extract the bytes from the string and store them // in the AES accelerator int Index; uint32_t KeySection; uint8_t *Ptr = (uint8_t *)(&AESAKEY); Serial.println("Setting the following key: "); for (Index = 0; Index < 16; Index++) { KeySection = ByteStringToNumber(keystr+Index*2); Serial.print(KeySection,HEX); Serial.print(" "); *Ptr = (uint8_t) KeySection; } Serial.println(""); printAESRegisters(); } void encryptBlock(const char *plain_text, char *crypto_text, uint32_t len) { // Encrypts a 128 bit (16 byte) block of text int Index = 0; uint8_t Dummy = 0; uint32_t Section; volatile void *Ptr; // select encrypt mode AESACTL0 = 0;//0xfffc; setKey(key); Ptr = &AESADIN; Serial.println("Encrypting the following:" ); for (Index = 0; Index < 16; Index++) { Section = ByteStringToNumber(plain_text+Index*2); Serial.print(Section,HEX); Serial.print(" "); *((uint8_t *)Ptr) = (uint8_t)Section; } Serial.println(" "); delay(4); //while ( (AESACTL0 & (1 << 8) )==0); // wait for ready flag Ptr = &AESADOUT; for (Index = 0; Index < 16; Index ++) { crypto_text[Index] = *((uint8_t *)Ptr); } } void printAESRegisters() { Serial.print("AESASTAT: "); Serial.print(String(AESASTAT,16)); Serial.print(", AESACTL0: "); Serial.print(String(AESACTL0,16)); Serial.print(", AESACTL1: "); Serial.println(String(AESACTL1,16)); } // the setup routine runs once when you press reset: void setup() { Serial.begin(38400); } char CryptoText[17]; // the loop routine runs over and over again forever: void loop() { int Index; CryptoText[16]=0; AESACTL0 = 0; encryptBlock(testmsg,CryptoText,16); Serial.println("Just encrypted"); printAESRegisters(); Serial.println("Crypto Text:"); for (Index = 0 ; Index < 16; Index ++ ) { Serial.print(int(CryptoText[Index]),HEX); Serial.print(" "); } Serial.println(" "); Serial.println(CryptoText); Serial.println("--------------------------------"); delay(501); }