Skip to content

Commit

Permalink
Updating TDEA (x3) crypto code to handle uneven buffer sizes ; Change…
Browse files Browse the repository at this point in the history
…s to DESFire auth instructions reinit / (in)validate state logic
  • Loading branch information
maxieds committed Jul 19, 2022
1 parent 5c894b8 commit 3d86fe4
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 172 deletions.
40 changes: 24 additions & 16 deletions Firmware/Chameleon-Mini/Application/CryptoAES128.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ static void CryptoAESEncryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const
} while (aes_is_busy());
aes_read_outputdata(Ciphertext);
aes_clear_interrupt_flag();
aes_clear_error_flag();
}

static void CryptoAESDecryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key) {
Expand All @@ -236,11 +235,10 @@ static void CryptoAESDecryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const
} while (aes_is_busy());
aes_read_outputdata(Plaintext);
aes_clear_interrupt_flag();
aes_clear_error_flag();
}

uint8_t CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IVIn, const uint8_t *Key) {
int CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IVIn, const uint8_t *Key) {
uint8_t *IV = IVIn;
if ((Count % CRYPTO_AES_BLOCK_SIZE) != 0) {
return 0xBE;
Expand Down Expand Up @@ -289,15 +287,19 @@ uint8_t CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciph
memcpy(IV, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
}
}
return 0;
if (aes_is_error()) {
aes_clear_error_flag();
return AES.STATUS & AES_ERROR_bm;
} else if (unevenBlockSize) {
return CRYPTO_AES_EXIT_UNEVEN_BLOCKS;
} else {
return CRYPTO_AES_EXIT_SUCCESS;
}
}

uint8_t CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IVIn, const uint8_t *Key) {
int CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IVIn, const uint8_t *Key) {
uint8_t *IV = IVIn;
if ((Count % CRYPTO_AES_BLOCK_SIZE) != 0) {
return 0xBE;
}
if (IVIn == NULL) {
memset(__CryptoAES_IVData, 0x00, CRYPTO_AES_BLOCK_SIZE);
IV = &__CryptoAES_IVData[0];
Expand Down Expand Up @@ -342,16 +344,22 @@ uint8_t CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciph
memcpy(IV, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
} else {
uint8_t numInputUnevenBytes = Count % CRYPTO_AES_BLOCK_SIZE;
CryptoAESBlock_t inputBlockTemp;
memset(inputBlockTemp, 0x00, CRYPTO_AES_BLOCK_SIZE);
memcpy(inputBlockTemp, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, numInputUnevenBytes);
CryptoAESDecryptBlock(Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, inputBlockTemp, Key);
memset(inputBlock, 0x00, CRYPTO_AES_BLOCK_SIZE);
memcpy(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, numInputUnevenBytes);
CryptoAESDecryptBlock(Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, inputBlock, Key);
CryptoMemoryXOR(IV, Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
memcpy(IV, inputBlockTemp, CRYPTO_AES_BLOCK_SIZE);
memcpy(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
}
}
}
return 0;
if (aes_is_error()) {
aes_clear_error_flag();
return AES.STATUS & AES_ERROR_bm;
} else if (unevenBlockSize) {
return CRYPTO_AES_EXIT_UNEVEN_BLOCKS;
} else {
return CRYPTO_AES_EXIT_SUCCESS;
}
}

// This routine performs the CBC "send" mode chaining: C = E(P ^ IV); IV = C
Expand Down
18 changes: 10 additions & 8 deletions Firmware/Chameleon-Mini/Application/CryptoAES128.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,18 @@ extern uint8_t __CryptoAESOpMode;
#define CRYPTO_AES_URAT_MRWRITE_SUBKEY 4 // Mode Register written during the sub-keys generation
#define CRYPTO_AES_URAT_READ_WRITEONLY 5 // Write-only register read access

/* Error and status codes */
#define CRYPTO_AES_EXIT_SUCCESS 0
#define CRYPTO_AES_EXIT_UNEVEN_BLOCKS 1

/* Define types for the AES-128 specific implementation: */
#define CRYPTO_AES_KEY_SIZE 16
typedef uint8_t CryptoAESKey_t[CRYPTO_AES_KEY_SIZE];

#define CRYPTO_AES_BLOCK_SIZE 16
typedef uint8_t CryptoAESBlock_t[CRYPTO_AES_BLOCK_SIZE];

#define CryptoAESBytesToBlocks(byteCount) \
((byteCount + CRYPTO_AES_BLOCK_SIZE - 1) / CRYPTO_AES_BLOCK_SIZE)
#define CryptoAESBytesToBlocks(byteCount) ((byteCount + CRYPTO_AES_BLOCK_SIZE - 1) / CRYPTO_AES_BLOCK_SIZE)

typedef enum aes_dec {
AES_ENCRYPT,
Expand Down Expand Up @@ -141,10 +144,10 @@ void aes_set_callback(const aes_callback_t callback);
void CryptoAESGetConfigDefaults(CryptoAESConfig_t *ctx);
void CryptoAESInitContext(CryptoAESConfig_t *ctx);

uint8_t CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IV, const uint8_t *Key);
uint8_t CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IV, const uint8_t *Key);
int CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IV, const uint8_t *Key);
int CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IV, const uint8_t *Key);

typedef uint8_t (*CryptoAESFuncType)(uint8_t *, uint8_t *, uint8_t *);
typedef struct {
Expand All @@ -165,8 +168,7 @@ void CryptoAESEncrypt_CBCSend(uint16_t Count, uint8_t *PlainText, uint8_t *Ciphe
uint8_t *Key, uint8_t *IV);

/* Crypto utility functions: */
#define CRYPTO_BYTES_TO_BLOCKS(numBytes, blockSize) \
( ((numBytes) + (blockSize) - 1) / (blockSize) )
#define CRYPTO_BYTES_TO_BLOCKS(numBytes, blockSize) ( ((numBytes) + (blockSize) - 1) / (blockSize) )

#define CryptoMemoryXOR(inputBuf, destBuf, bufSize) ({ \
uint8_t *in = (uint8_t *) inputBuf; \
Expand Down
82 changes: 46 additions & 36 deletions Firmware/Chameleon-Mini/Application/CryptoTDEA.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
/* Set the last operation mode (ECB or CBC) init for the context */
uint8_t __CryptoDESOpMode = CRYPTO_DES_ECB_MODE;

static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys);
static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
static int CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys);
static int CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
uint16_t numBlocks = (Count + CryptoSpec->blockSize - 1) / CryptoSpec->blockSize;
bool dataNeedsPadding = (Count % CryptoSpec->blockSize) != 0;
bool unevenBlockSize = (Count % CryptoSpec->blockSize) != 0;
uint16_t blockIndex = 0;
uint8_t inputBlock[CryptoSpec->blockSize];
uint8_t IV[CryptoSpec->blockSize];
Expand All @@ -29,7 +29,7 @@ static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Coun
memset(inputBlock, 0x00, CryptoSpec->blockSize);
memcpy(inputBlock, &Plaintext[0], CryptoSpec->blockSize);
CryptoMemoryXOR(IV, inputBlock, CryptoSpec->blockSize);
} else if (dataNeedsPadding && blockIndex + 1 == numBlocks) {
} else if (unevenBlockSize && blockIndex + 1 == numBlocks) {
memset(inputBlock, 0x00, CryptoSpec->blockSize);
memcpy(inputBlock, &Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize], Count % CryptoSpec->blockSize);
CryptoMemoryXOR(&Plaintext[blockIndex * CryptoSpec->blockSize], inputBlock, CryptoSpec->blockSize);
Expand All @@ -39,28 +39,33 @@ static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Coun
}
CryptoSpec->cryptFunc(inputBlock, &Ciphertext[blockIndex * CryptoSpec->blockSize], Keys);
} else { /* ECB mode */
if (dataNeedsPadding && blockIndex + 1 == numBlocks) {
if (unevenBlockSize && blockIndex + 1 == numBlocks) {
memset(inputBlock, 0x00, CryptoSpec->blockSize);
memcpy(inputBlock, &Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize], Count % CryptoSpec->blockSize);
CryptoMemoryXOR(&Plaintext[blockIndex * CryptoSpec->blockSize], inputBlock, CryptoSpec->blockSize);
memcpy(inputBlock, &Plaintext[blockIndex * CryptoSpec->blockSize], Count % CryptoSpec->blockSize);
} else {
memcpy(inputBlock, &Plaintext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
CryptoMemoryXOR(IV, inputBlock, CryptoSpec->blockSize);
CryptoSpec->cryptFunc(inputBlock, &Ciphertext[blockIndex * CryptoSpec->blockSize], Keys);
memcpy(IV, &Ciphertext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
}
CryptoMemoryXOR(IV, inputBlock, CryptoSpec->blockSize);
CryptoSpec->cryptFunc(inputBlock, &Ciphertext[blockIndex * CryptoSpec->blockSize], Keys);
memcpy(IV, &Ciphertext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
}
blockIndex++;
}
if (IVIn != NULL) {
memcpy(IVIn, IV, CryptoSpec->blockSize);
}
/* TODO: Check for status errors with AVR DES.STATUS ??? */
if (unevenBlockSize) {
return CRYPTO_TDEA_EXIT_UNEVEN_BLOCKS;
} else {
return CRYPTO_TDEA_EXIT_SUCCESS;
}
}

static void CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys);
static void CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
static int CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys);
static int CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
uint16_t numBlocks = (Count + CryptoSpec->blockSize - 1) / CryptoSpec->blockSize;
bool dataNeedsPadding = (Count % CryptoSpec->blockSize) != 0;
bool unevenBlockSize = (Count % CryptoSpec->blockSize) != 0;
uint16_t blockIndex = 0;
uint8_t inputBlock[CryptoSpec->blockSize];
uint8_t IV[CryptoSpec->blockSize];
Expand All @@ -72,13 +77,13 @@ static void CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Coun
while (blockIndex < numBlocks) {
if (__CryptoDESOpMode == CRYPTO_DES_CBC_MODE) {
CryptoSpec->cryptFunc(inputBlock, Ciphertext + blockIndex * CryptoSpec->blockSize, Keys);
if (blockIndex == 0 && !dataNeedsPadding) {
if (blockIndex == 0 && !unevenBlockSize) {
memcpy(Plaintext, inputBlock, CryptoSpec->blockSize);
CryptoMemoryXOR(IV, Plaintext, CryptoSpec->blockSize);
} else if (blockIndex == 0 && dataNeedsPadding && numBlocks == 0x01) {
} else if (blockIndex == 0 && unevenBlockSize && numBlocks == 0x01) {
memcpy(Plaintext, inputBlock, Count % CryptoSpec->blockSize);
CryptoMemoryXOR(IV, Plaintext, Count % CryptoSpec->blockSize);
} else if (dataNeedsPadding && blockIndex + 1 == numBlocks) {
} else if (unevenBlockSize && blockIndex + 1 == numBlocks) {
memcpy(Plaintext + blockIndex * CryptoSpec->blockSize, inputBlock, Count % CryptoSpec->blockSize);
CryptoMemoryXOR(&Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize],
Plaintext + blockIndex * CryptoSpec->blockSize, Count % CryptoSpec->blockSize);
Expand All @@ -88,68 +93,73 @@ static void CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Coun
Plaintext + blockIndex * CryptoSpec->blockSize, CryptoSpec->blockSize);
}
} else { /* ECB mode */
if (dataNeedsPadding && blockIndex + 1 == numBlocks) {
memcpy(Plaintext + blockIndex * CryptoSpec->blockSize, inputBlock, Count % CryptoSpec->blockSize);
CryptoMemoryXOR(&Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize],
Plaintext + blockIndex * CryptoSpec->blockSize, Count % CryptoSpec->blockSize);
if (unevenBlockSize && blockIndex + 1 == numBlocks) {
memset(inputBlock, 0x00, CryptoSpec->blockSize);
memcpy(inputBlock, &Plaintext[blockIndex * CryptoSpec->blockSize], Count % CryptoSpec->blockSize);
} else {
CryptoSpec->cryptFunc(&Plaintext[blockIndex * CryptoSpec->blockSize],
&Ciphertext[blockIndex * CryptoSpec->blockSize], Keys);
CryptoMemoryXOR(IV, &Plaintext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
memcpy(IV, &Ciphertext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
memcpy(inputBlock, &Ciphertext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
}
CryptoSpec->cryptFunc(&Plaintext[blockIndex * CryptoSpec->blockSize], inputBlock, Keys);
CryptoMemoryXOR(IV, &Plaintext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
memcpy(IV, inputBlock, CryptoSpec->blockSize);
}
blockIndex++;
}
if (IVIn != NULL) {
memcpy(IVIn, IV, CryptoSpec->blockSize);
}
/* TODO: Check for status errors with AVR DES.STATUS ??? */
if (unevenBlockSize) {
return CRYPTO_TDEA_EXIT_UNEVEN_BLOCKS;
} else {
return CRYPTO_TDEA_EXIT_SUCCESS;
}
}

void EncryptDESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
int EncryptDESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoEncryptDEA,
.blockSize = CRYPTO_DES_BLOCK_SIZE
};
CryptoEncryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
return CryptoEncryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
}

void DecryptDESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
int DecryptDESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoDecryptDEA,
.blockSize = CRYPTO_DES_BLOCK_SIZE
};
CryptoDecryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
return CryptoDecryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
}

void Encrypt2K3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
int Encrypt2K3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoEncrypt2KTDEA,
.blockSize = CRYPTO_2KTDEA_BLOCK_SIZE
};
CryptoEncryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
return CryptoEncryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
}

void Decrypt2K3DESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
int Decrypt2K3DESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoDecrypt2KTDEA,
.blockSize = CRYPTO_2KTDEA_BLOCK_SIZE
};
CryptoDecryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
return CryptoDecryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
}

void Encrypt3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
int Encrypt3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoEncrypt3KTDEA,
.blockSize = CRYPTO_3KTDEA_BLOCK_SIZE
};
CryptoEncryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
return CryptoEncryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
}

void Decrypt3DESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
int Decrypt3DESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoDecrypt3KTDEA,
.blockSize = CRYPTO_3KTDEA_BLOCK_SIZE
};
CryptoDecryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
return CryptoDecryptCBCBuffer(&CryptoSpec, Count, Plaintext, Ciphertext, IVIn, Keys);
}
Loading

0 comments on commit 3d86fe4

Please sign in to comment.