Skip to content

Commit

Permalink
Working ISO authentication on the PM3 : cf. emsec#313
Browse files Browse the repository at this point in the history
  • Loading branch information
maxieds committed Mar 30, 2022
1 parent 45a6c3f commit f4faaa7
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 65 deletions.
24 changes: 19 additions & 5 deletions Firmware/Chameleon-Mini/Application/CryptoAES128.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static aes_callback_t __CryptoAESCallbackFunc = NULL;
static CryptoAESBlock_t __CryptoAES_IVData = { 0 };

/* Set the last operation mode (ECB or CBC) init for the context */
static uint8_t __CryptoAESOpMode = CRYPTO_AES_CBC_MODE;
static uint8_t __CryptoAESOpMode = CRYPTO_AES_ECB_MODE;

void aes_start(void) {
AES.CTRL |= AES_START_bm;
Expand Down Expand Up @@ -238,16 +238,18 @@ static void CryptoAESDecryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const

uint8_t CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
const uint8_t *IV, const uint8_t *Key) {
bool copyIVBuffer = true;
if ((Count % CRYPTO_AES_BLOCK_SIZE) != 0) {
return 0xBE;
} else if (IV == NULL) {
memset(__CryptoAES_IVData, 0x00, CRYPTO_AES_BLOCK_SIZE);
IV = &__CryptoAES_IVData[0];
copyIVBuffer = false;
}
CryptoAESBlock_t inputBlock;
size_t bufBlocks = (Count + CRYPTO_AES_BLOCK_SIZE - 1) / CRYPTO_AES_BLOCK_SIZE;
for (int blk = 0; blk < bufBlocks; blk++) {
if (__CryptoAESOpMode == CRYPTO_AES_CBC_MODE) {
CryptoAESBlock_t inputBlock;
if (blk == 0) {
memcpy(inputBlock, &Plaintext[0], CRYPTO_AES_BLOCK_SIZE);
CryptoMemoryXOR(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
Expand All @@ -256,26 +258,33 @@ uint8_t CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciph
CryptoMemoryXOR(&Plaintext[blk * CRYPTO_AES_BLOCK_SIZE], inputBlock, CRYPTO_AES_BLOCK_SIZE);
}
CryptoAESEncryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key, true);
if (blk + 1 == bufBlocks && copyIVBuffer) {
memcpy(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
}
} else {
CryptoAESEncryptBlock(Plaintext + blk * CRYPTO_AES_BLOCK_SIZE,
Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key, true);
memcpy(inputBlock, Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
CryptoMemoryXOR(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
CryptoAESEncryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key, true);
memcpy(IV, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
}
}
return 0;
}

uint8_t CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
const uint8_t *IV, const uint8_t *Key) {
bool copyIVBuffer = true;
if ((Count % CRYPTO_AES_BLOCK_SIZE) != 0) {
return 0xBE;
} else if (IV == NULL) {
memset(__CryptoAES_IVData, 0x00, CRYPTO_AES_BLOCK_SIZE);
IV = &__CryptoAES_IVData[0];
copyIVBuffer = false;
}
CryptoAESBlock_t inputBlock;
size_t bufBlocks = (Count + CRYPTO_AES_BLOCK_SIZE - 1) / CRYPTO_AES_BLOCK_SIZE;
for (int blk = 0; blk < bufBlocks; blk++) {
if (__CryptoAESOpMode == CRYPTO_AES_CBC_MODE) {
CryptoAESBlock_t inputBlock;
CryptoAESDecryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key);
if (blk == 0) {
memcpy(Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, inputBlock, CRYPTO_AES_BLOCK_SIZE);
Expand All @@ -285,9 +294,14 @@ uint8_t CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciph
CryptoMemoryXOR(&Ciphertext[(blk - 1) * CRYPTO_AES_BLOCK_SIZE],
Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
}
if (blk + 1 == bufBlocks && copyIVBuffer) {
memcpy(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
}
} else {
CryptoAESDecryptBlock(Plaintext + blk * CRYPTO_AES_BLOCK_SIZE,
Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key);
CryptoMemoryXOR(IV, Plaintext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
memcpy(IV, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
}
}
return 0;
Expand Down
77 changes: 49 additions & 28 deletions Firmware/Chameleon-Mini/Application/CryptoTDEA.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
#include "CryptoTDEA.h"
#include "CryptoAES128.h"

/* Set the last operation mode (ECB or CBC) init for the context */
static 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) {
uint16_t numBlocks = (Count + CryptoSpec->blockSize - 1) / CryptoSpec->blockSize;
bool dataNeedsPadding = (Count % CryptoSpec->blockSize) != 0;
uint16_t blockIndex = 0;
uint8_t *ctBuf = (uint8_t *) Ciphertext;
uint8_t inputBlock[CryptoSpec->blockSize];
uint8_t IV[CryptoSpec->blockSize];
if (IVIn == NULL) {
Expand All @@ -22,22 +24,31 @@ static void CryptoEncryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Coun
memcpy(IV, IVIn, CryptoSpec->blockSize);
}
while (blockIndex < numBlocks) {
if (blockIndex == 0) {
memset(inputBlock, 0x00, CryptoSpec->blockSize);
memcpy(inputBlock, &Plaintext[0], CryptoSpec->blockSize);
if (__CryptoDESOpMode == CRYPTO_DES_CBC_MODE) {
if (blockIndex == 0) {
memset(inputBlock, 0x00, CryptoSpec->blockSize);
memcpy(inputBlock, &Plaintext[0], CryptoSpec->blockSize);
CryptoMemoryXOR(IV, inputBlock, CryptoSpec->blockSize);
} else if (dataNeedsPadding && 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);
} else {
memcpy(inputBlock, &Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize], CryptoSpec->blockSize);
CryptoMemoryXOR(&Plaintext[blockIndex * CryptoSpec->blockSize], inputBlock, CryptoSpec->blockSize);
}
CryptoSpec->cryptFunc(inputBlock, &Ciphertext[blockIndex * CryptoSpec->blockSize], Keys);
} else { /* ECB mode */
memcpy(inputBlock, &Plaintext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
CryptoMemoryXOR(IV, inputBlock, CryptoSpec->blockSize);
} else if (dataNeedsPadding && 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);
} else {
memcpy(inputBlock, &Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize], CryptoSpec->blockSize);
CryptoMemoryXOR(&Plaintext[blockIndex * CryptoSpec->blockSize], inputBlock, CryptoSpec->blockSize);
CryptoSpec->cryptFunc(inputBlock, &Ciphertext[blockIndex * CryptoSpec->blockSize], Keys);
memcpy(IV, &Ciphertext[blockIndex * CryptoSpec->blockSize], CryptoSpec->blockSize);
}
CryptoSpec->cryptFunc(inputBlock, ctBuf, Keys);
ctBuf += CryptoSpec->blockSize;
blockIndex++;
}
if (IVIn != NULL) {
memcpy(IVIn, IV, CryptoSpec->blockSize);
}
}

static void CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys);
Expand All @@ -53,24 +64,34 @@ static void CryptoDecryptCBCBuffer(CryptoTDEA_CBCSpec *CryptoSpec, uint16_t Coun
memcpy(IV, IVIn, CryptoSpec->blockSize);
}
while (blockIndex < numBlocks) {
CryptoSpec->cryptFunc(inputBlock, Ciphertext + blockIndex * CryptoSpec->blockSize, Keys);
if (blockIndex == 0 && !dataNeedsPadding) {
memcpy(Plaintext, inputBlock, CryptoSpec->blockSize);
CryptoMemoryXOR(IV, Plaintext, CryptoSpec->blockSize);
} else if (blockIndex == 0 && dataNeedsPadding && numBlocks == 0x01) {
memcpy(Plaintext, inputBlock, Count % CryptoSpec->blockSize);
CryptoMemoryXOR(IV, Plaintext, Count % CryptoSpec->blockSize);
} else 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);
} else {
memcpy(Plaintext + blockIndex * CryptoSpec->blockSize, inputBlock, CryptoSpec->blockSize);
CryptoMemoryXOR(&Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize],
Plaintext + blockIndex * CryptoSpec->blockSize, CryptoSpec->blockSize);
if (__CryptoDESOpMode == CRYPTO_DES_CBC_MODE) {
CryptoSpec->cryptFunc(inputBlock, Ciphertext + blockIndex * CryptoSpec->blockSize, Keys);
if (blockIndex == 0 && !dataNeedsPadding) {
memcpy(Plaintext, inputBlock, CryptoSpec->blockSize);
CryptoMemoryXOR(IV, Plaintext, CryptoSpec->blockSize);
} else if (blockIndex == 0 && dataNeedsPadding && numBlocks == 0x01) {
memcpy(Plaintext, inputBlock, Count % CryptoSpec->blockSize);
CryptoMemoryXOR(IV, Plaintext, Count % CryptoSpec->blockSize);
} else 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);
} else {
memcpy(Plaintext + blockIndex * CryptoSpec->blockSize, inputBlock, CryptoSpec->blockSize);
CryptoMemoryXOR(&Ciphertext[(blockIndex - 1) * CryptoSpec->blockSize],
Plaintext + blockIndex * CryptoSpec->blockSize, CryptoSpec->blockSize);
}
} else { /* ECB mode */
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);
}
blockIndex++;
}
if (IVIn != NULL) {
memcpy(IVIn, IV, CryptoSpec->blockSize);
}
}

void EncryptDESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
Expand Down
4 changes: 4 additions & 0 deletions Firmware/Chameleon-Mini/Application/CryptoTDEA.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ PCD's side.
*/

/* DES Operation cipher mode */
#define CRYPTO_DES_ECB_MODE 0 // Electronic Code Book mode
#define CRYPTO_DES_CBC_MODE 1 // Cipher Block Chaining mode

/* Key sizes, in bytes */
#define CRYPTO_DES_KEY_SIZE 8 /* Bytes */
#define CRYPTO_2KTDEA_KEY_SIZE (CRYPTO_DES_KEY_SIZE * 2)
Expand Down
2 changes: 2 additions & 0 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ void InvalidateAuthState(BYTE keepPICCAuthData) {
CryptoAuthMethod = CRYPTO_TYPE_ANY;
ActiveCommMode = DESFIRE_DEFAULT_COMMS_STANDARD;
DesfireCommMode = ActiveCommMode;
memset(&SessionKey[0], 0x00, CRYPTO_MAX_BLOCK_SIZE);
memset(&SessionIV[0], 0x00, CRYPTO_MAX_BLOCK_SIZE);
}

bool IsAuthenticated(void) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,8 @@ uint16_t ISO144433APiccProcess(uint8_t *Buffer, uint16_t BitCount) {
const char *logMsg = PSTR("ISO14443-3/4: EXPECTING RATS");
LogDebuggingMsg(logMsg);
} else if (Cmd == ISO14443A_CMD_SELECT_CL3) {
return ISO14443A_APP_NO_RESPONSE;
Buffer[0] = 0x00;
return 1 * BITS_PER_BYTE;
}
/* Forward to ISO/IEC 14443-4 processing code */
uint16_t ByteCount = (BitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
Expand Down
Loading

0 comments on commit f4faaa7

Please sign in to comment.