Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combining GCM and CTR mode #48

Open
poojitha-sai opened this issue Feb 19, 2020 · 4 comments
Open

Combining GCM and CTR mode #48

poojitha-sai opened this issue Feb 19, 2020 · 4 comments

Comments

@poojitha-sai
Copy link

Hello,

Is is possible to combine multiple modes of AES encryption?
I tried to combine GCM and CTR mode with HMAC in the same program and the program crashed.
Please suggest how to implement it.

@rweather
Copy link
Owner

What kind of Arduino device are you using? If it is a Uno or some other device with a small amount of RAM, then that may account for the crashing.

The more algorithms you include, the greater the data space in RAM required. If it gets too large, the data space will overlap with the stack space at the top of memory and memory corruption will start happening. If you have lots of "..." strings or byte arrays in your codel, then that will increase data space usage too.

I saw this quite a bit when developing the the test programs on Uno, which is why some of them use program memory for the test vectors - I had to get the values out of data space or memory corruption would occur.

Try using an Arduino device with more RAM and see if that helps. If you have lots of RAM already, then there may be some other bug going on in your code that is causing memory corruption.

@poojitha-sai
Copy link
Author

I'm using an Arduino UNO. My program does use a lot of strings and byte arrays too. Could you please tell me if there's a way to optimize this and make it work?

@rweather
Copy link
Owner

Without seeing your code, it is difficult to advise.

I do wonder why you need both GCM and CTR/HMAC mode? GCM is essentially CTR mode combined with GHASH authentication, a form of authenticated encryption. CTR/HMAC is another different form of authenticated encryption.

At a guess you currently have the following classes compiled into your sketch: AES, GHASH, SHA256, GCM, CTR, and HMAC. If you are also using my random number generator, then you also have RNG and ChaCha added to the memory burden.

If your application truly does call for all those algorithms, then you may have to consider upgrading to an Arduino with more memory.

I suggest that you pick just one authenticated encryption mode, either GCM or possibly ChaChaPoly so you can share the ChaCha code with the RNG.

@poojitha-sai
Copy link
Author

poojitha-sai commented Feb 22, 2020

I'm trying to test security for CAN communication using different modes of AES encryption. Individual modes work fine. But I wanted to see if different modes of encryption can be used for selected messages. Hence, I faced this problem.
Below is the code for my CAN receiver:

`#include "CTR.h"
#include <Crypto.h>
#include <AES.h>
#include <SHA256.h>
#include <GCM.h>
#include <string.h>
#if defined(ESP8266) || defined(ESP32)
#include <pgmspace.h>
#else
#include <avr/pgmspace.h>
#endif

#include <mcp_can.h>
#include <SPI.h>

GCM gcm;
CTR ctr;
SHA256 hash;

const uint8_t Num_IDs = 6;
const uint8_t Num_Clusters = 2;
uint8_t Num_Mirr = Num_IDs / Num_Clusters;

uint8_t key[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
uint8_t iv[Num_IDs][16] = {{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, {1, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, {2, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, {3, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}, {4, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}};
uint8_t adata[16];

const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN); // Set CS pin

void setup()
{
Serial.begin(9600);

while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
gcm.setKey(key, sizeof(key));
gcm.addAuthData(adata, sizeof(adata));
}

void loop()
{

uint8_t plaintext[Num_IDs][8];
uint8_t tag[Num_IDs][8];
uint8_t ciphertext[Num_IDs][16];
bool auth_result[Num_IDs];
uint8_t msgData[Num_IDs][8];
uint8_t msgTag[Num_IDs][8];
unsigned char len = 8;
unsigned char buf[8];
static uint8_t recv[Num_IDs];
unsigned int canId;
uint8_t RecvDelay[Num_IDs];
bool enable[Num_IDs];

if (CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf

canId = CAN.getCanId();

/*
    Serial.println("-----------------------------");
    Serial.print("Get data from ID: ");
    Serial.println(canId, HEX);

    for (int i = 0; i < len; i++) // print the data
    {
      Serial.print(buf[i], HEX);
      Serial.print("\t");
    }
    Serial.println();
*/

/*Logic for filtering messages*/

for (int i = 1; i <= Num_Clusters; i++)
{
  for (int y = 1; y <= Num_Mirr; y++)
  {
    int z = 2 * Num_Mirr * (i - 1) + y - 1;
    int x = y + ((i - 1) * Num_Mirr) - 1;
    if (canId == z)
    {

      /*Copy message tag*/
      copy(buf, msgTag[x], 8);
      recv[x] |= 1;

    }
    else if (canId == (z + Num_Mirr))
    {

      /*Copy message data*/
      copy(buf, msgData[x], 8);
      recv[x] |= 2;

    }


    if (recv[x] == 3) //to check if both tag and data are received.
    {
      for (uint8_t j = 0; j < 8; j++)
      {

        ciphertext[x][j] = msgData[x][j];
        tag[x][j] = msgTag[x][j];

      }

      /*GCM decryption for selected messages*/
      if ((x + 1) % 3 == 0) {
        gcm.setKey(key, sizeof(key));
        gcm.setIV(iv[x], sizeof(iv[x]));
        gcm.decrypt(plaintext[x], ciphertext[x], 8);
        Serial.print((String)"plaintext[" + x + "]\n");
        for (int j = 0; j < 8; j++) {
          Serial.print(plaintext[x][j], DEC); //To plot data in MATLAB Simulink
          Serial.println("");
        }

        auth_result[x] = gcm.checkTag(tag[x], 8);

        if (auth_result[x] == 1)
        {
          Serial.println((String)"Message " + x + " authenticated");

        }

      }

      /*CTR decryption*/
      else {

        ctr.setKey(key, 16);
        ctr.setIV(iv[x], 16);

        ctr.decrypt(plaintext[x], ciphertext[x], 8);
        Serial.print((String)"Plaintext[" + x + "]\n");
        for (int j = 0; j < 8; j++) {
          Serial.print(plaintext[x][j]);
          Serial.println("");
        }

        hash.resetHMAC(key, sizeof(key));
        hash.update(ciphertext[x], 8);
        hash.finalizeHMAC(key, sizeof(key), tag[x], 8);
        for (int j = 0; j < 8; j++) {
          if (tag[x][j] == msgTag[x][j])
          {
            auth_result[x] |= 1;
          }
          else
          {
            auth_result[x] &= 0;
          }

        }

        if (auth_result[x] == 1)
        {
          Serial.println((String)"Message " + x + " authenticated");

        }
        recv[x] = 0;
      }
    }

  }
}

}

/Dyn switching ends/

}

void copy(uint8_t* src, uint8_t* dst, uint8_t len) {
memcpy(dst, src, sizeof(src[0])*len);
}`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants