Skip to content

Commit

Permalink
AuthLegacy(0x0A) works using 3DES enc/dec modes
Browse files Browse the repository at this point in the history
  • Loading branch information
maxieds committed Jan 31, 2022
1 parent 6ee1958 commit 195e600
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 86 deletions.
90 changes: 38 additions & 52 deletions Firmware/Chameleon-Mini/Application/CryptoTDEA.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,68 @@
* Author: Maxie D. Schmidt (@maxieds)
*/

#include <string.h>

#include "../Common.h"
#include "CryptoTDEA.h"
#include "CryptoAES128.h"

//__asm__(
// STRINGIFY(#include "CryptoTDEA.S")
//);

void EncryptDESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *Keys) {
void 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
};
uint16_t numBlocks = (Count + CryptoSpec.blockSize - 1) / CryptoSpec.blockSize;
uint16_t blockIndex = 0;
uint8_t *ptBuf = (uint8_t *) Plaintext, *ctBuf = (uint8_t *) Ciphertext;
uint8_t *ctBuf = (uint8_t *) Ciphertext;
uint8_t inputBlock[CRYPTO_DES_BLOCK_SIZE];
uint8_t IV[CRYPTO_DES_BLOCK_SIZE];
if (IVIn == NULL) {
memset(IV, 0x00, CRYPTO_DES_BLOCK_SIZE);
} else {
memcpy(IV, IVIn, CRYPTO_DES_BLOCK_SIZE);
}
while (blockIndex < numBlocks) {
CryptoSpec.cryptFunc(ptBuf, ctBuf, Keys);
ptBuf += CryptoSpec.blockSize;
ctBuf += CryptoSpec.blockSize;
blockIndex++;
if (blockIndex == 0) {
memcpy(inputBlock, &Plaintext[0], CRYPTO_DES_BLOCK_SIZE);
CryptoMemoryXOR(IV, inputBlock, CRYPTO_DES_BLOCK_SIZE);
} else {
memcpy(inputBlock, &Ciphertext[(blockIndex - 1) * CRYPTO_DES_BLOCK_SIZE], CRYPTO_DES_BLOCK_SIZE);
CryptoMemoryXOR(&Plaintext[blockIndex * CRYPTO_DES_BLOCK_SIZE], inputBlock, CRYPTO_DES_BLOCK_SIZE);
}
CryptoSpec.cryptFunc(inputBlock, ctBuf, Keys);
ctBuf += CryptoSpec.blockSize;
blockIndex++;
}
}

void DecryptDESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *Keys) {
void 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
};
uint16_t numBlocks = (Count + CryptoSpec.blockSize - 1) / CryptoSpec.blockSize;
uint16_t blockIndex = 0;
uint8_t *ptBuf = (uint8_t *) Plaintext, *ctBuf = (uint8_t *) Ciphertext;
while (blockIndex < numBlocks) {
CryptoSpec.cryptFunc(ptBuf, ctBuf, Keys);
ptBuf += CryptoSpec.blockSize;
ctBuf += CryptoSpec.blockSize;
blockIndex++;
}
}

/* OLD: 3DES ECB (Now done with CBC): */
#if 0
void Encrypt3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoEncrypt3KTDEA,
.blockSize = CRYPTO_3KTDEA_BLOCK_SIZE
};
uint16_t numBlocks = (Count + CryptoSpec.blockSize - 1) / CryptoSpec.blockSize;
uint16_t blockIndex = 0;
uint8_t *ptBuf = (uint8_t *) Plaintext, *ctBuf = (uint8_t *) Ciphertext;
while (blockIndex < numBlocks) {
CryptoSpec.cryptFunc(ptBuf, ctBuf, Keys);
ptBuf += CryptoSpec.blockSize;
ctBuf += CryptoSpec.blockSize;
blockIndex++;
uint8_t inputBlock[CRYPTO_DES_BLOCK_SIZE];
uint8_t IV[CRYPTO_DES_BLOCK_SIZE];
if (IVIn == NULL) {
memset(IV, 0x00, CRYPTO_DES_BLOCK_SIZE);
} else {
memcpy(IV, IVIn, CRYPTO_DES_BLOCK_SIZE);
}
}

void Decrypt3DESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
.cryptFunc = &CryptoDecrypt3KTDEA,
.blockSize = CRYPTO_3KTDEA_BLOCK_SIZE
};
uint16_t numBlocks = (Count + CryptoSpec.blockSize - 1) / CryptoSpec.blockSize;
uint16_t blockIndex = 0;
uint8_t *ptBuf = (uint8_t *) Plaintext, *ctBuf = (uint8_t *) Ciphertext;
while (blockIndex < numBlocks) {
CryptoSpec.cryptFunc(ptBuf, ctBuf, Keys);
ptBuf += CryptoSpec.blockSize;
ctBuf += CryptoSpec.blockSize;
CryptoSpec.cryptFunc(inputBlock, Ciphertext + blockIndex * CRYPTO_DES_BLOCK_SIZE, Keys);
if (blockIndex == 0) {
memcpy(Plaintext, inputBlock, CRYPTO_DES_BLOCK_SIZE);
CryptoMemoryXOR(IV, Plaintext, CRYPTO_DES_BLOCK_SIZE);
} else {
memcpy(Plaintext + blockIndex * CRYPTO_DES_BLOCK_SIZE, inputBlock, CRYPTO_DES_BLOCK_SIZE);
CryptoMemoryXOR(&Ciphertext[(blockIndex - 1) * CRYPTO_DES_BLOCK_SIZE],
Plaintext + blockIndex * CRYPTO_DES_BLOCK_SIZE, CRYPTO_DES_BLOCK_SIZE);
}
blockIndex++;
}
}
#endif

#include <string.h>
#include "CryptoAES128.h"

void Encrypt3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IVIn, const uint8_t *Keys) {
CryptoTDEA_CBCSpec CryptoSpec = {
Expand Down
4 changes: 2 additions & 2 deletions Firmware/Chameleon-Mini/Application/CryptoTDEA.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ typedef void (*CryptoTDEAFuncType)(const void *PlainText, void *Ciphertext, cons

void CryptoEncryptDEA(void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void CryptoDecryptDEA(void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void EncryptDESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void DecryptDESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *Keys);
void EncryptDESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IV, const uint8_t *Keys);
void DecryptDESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IV, const uint8_t *Keys);

/** Performs the Triple DEA enciphering in ECB mode (single block)
*
Expand Down
29 changes: 13 additions & 16 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,9 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) {
return DESFIRE_STATUS_RESPONSE_SIZE;
}

/* Indicate that we are in AES key authentication land */
keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_DES);
/* Indicate that we are in DES key authentication land */
Key = &SessionKey;
keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_3K3DES);
DesfireCommandState.KeyId = KeyId;
DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_3K3DES;
DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_3K3DES);
Expand Down Expand Up @@ -471,8 +472,8 @@ uint16_t EV0CmdAuthenticateLegacy1(uint8_t *Buffer, uint16_t ByteCount) {
uint8_t rndBPadded[2 * CRYPTO_CHALLENGE_RESPONSE_BYTES];
memset(rndBPadded, 0x00, 2 * CRYPTO_CHALLENGE_RESPONSE_BYTES);
memcpy(rndBPadded, DesfireCommandState.RndB, CRYPTO_CHALLENGE_RESPONSE_BYTES);
EncryptDESBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, rndBPadded,
&Buffer[1], *Key);
Encrypt3DESBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, rndBPadded,
&Buffer[1], NULL, *Key);

/* Scrub the key */
memset(*Key, 0, keySize);
Expand All @@ -490,13 +491,15 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) {

/* Set status for the next incoming command on error */
DesfireState = DESFIRE_IDLE;

/* Validate command length */
if (ByteCount != 2 * CRYPTO_DES_BLOCK_SIZE + 1) {
if (ByteCount != 2 * CRYPTO_CHALLENGE_RESPONSE_BYTES + 1) {
Buffer[0] = STATUS_LENGTH_ERROR;
return DESFIRE_STATUS_RESPONSE_SIZE;
}

/* Reset parameters for authentication from the first exchange */
Key = &SessionKey;
KeyId = DesfireCommandState.KeyId;
cryptoKeyType = DesfireCommandState.CryptoMethodType;
keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_3K3DES);
Expand All @@ -506,16 +509,16 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) {
BYTE challengeRndAB[2 * CRYPTO_CHALLENGE_RESPONSE_BYTES];
BYTE challengeRndA[CRYPTO_CHALLENGE_RESPONSE_BYTES];
BYTE challengeRndB[CRYPTO_CHALLENGE_RESPONSE_BYTES];
DecryptDESBuffer(2 * CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB,
&Buffer[1], *Key);
Decrypt3DESBuffer(2 * CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB,
&Buffer[1], NULL, *Key);
RotateArrayRight(challengeRndAB + CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndB,
CRYPTO_CHALLENGE_RESPONSE_BYTES);
memcpy(challengeRndA, challengeRndAB, CRYPTO_CHALLENGE_RESPONSE_BYTES);

/* Check that the returned RndB matches what we sent in the previous round */
if (memcmp(DesfireCommandState.RndB, challengeRndB, CRYPTO_CHALLENGE_RESPONSE_BYTES)) {
Buffer[0] = STATUS_AUTHENTICATION_ERROR;
return DESFIRE_STATUS_RESPONSE_SIZE;
return DESFIRE_STATUS_RESPONSE_SIZE;
}

/* Authenticated successfully */
Expand All @@ -526,10 +529,8 @@ uint16_t EV0CmdAuthenticateLegacy2(uint8_t *Buffer, uint16_t ByteCount) {

/* Encrypt and send back the once rotated RndA buffer to the PCD */
RotateArrayLeft(challengeRndA, challengeRndAB, CRYPTO_CHALLENGE_RESPONSE_BYTES);
//memset(challengeRndAB, 0x00, 2 * CRYPTO_CHALLENGE_RESPONSE_BYTES);
//memcpy(challengeRndAB, challengeRndA, CRYPTO_CHALLENGE_RESPONSE_BYTES);
EncryptDESBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB,
&Buffer[1], *Key);
Encrypt3DESBuffer(CRYPTO_CHALLENGE_RESPONSE_BYTES, challengeRndAB,
&Buffer[1], NULL, *Key);

/* Scrub the key */
memset(*Key, 0, keySize);
Expand Down Expand Up @@ -1692,10 +1693,6 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) {
return DESFIRE_STATUS_RESPONSE_SIZE;
}

/* The next calls just zero out the key buffers (not specific to AES): */
//InitAESCryptoKeyData(&SessionKey);
//InitAESCryptoKeyData(&SessionIV);

keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_3K3DES);
Key = &SessionKey;

Expand Down
90 changes: 76 additions & 14 deletions Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,37 @@ static inline size_t Decrypt3DES(const uint8_t *encSrcBuf, size_t bufSize,
return bufSize;
}

static inline size_t EncryptDES(const uint8_t *plainSrcBuf, size_t bufSize,
uint8_t *encDestBuf, const uint8_t *IVIn, CryptoData_t cdata) {
DES_key_schedule keySched;
uint8_t *kd = cdata.keyData;
DES_set_key(kd, &keySched);
uint8_t IV[CRYPTO_DES_BLOCK_SIZE];
if (IVIn == NULL) {
memset(IV, 0x00, CRYPTO_DES_BLOCK_SIZE);
} else {
memcpy(IV, IVIn, CRYPTO_DES_BLOCK_SIZE);
}
DES_cbc_encrypt(plainSrcBuf, encDestBuf, bufSize, &keySched, &IV, DES_ENCRYPT);
return bufSize;
}

static inline size_t DecryptDES(const uint8_t *encSrcBuf, size_t bufSize,
uint8_t *plainDestBuf, const uint8_t *IVIn, CryptoData_t cdata) {
DES_key_schedule keySched;
uint8_t *kd = cdata.keyData;
DES_set_key(kd, &keySched);
uint8_t IV[CRYPTO_DES_BLOCK_SIZE];
if (IVIn == NULL) {
memset(IV, 0x00, CRYPTO_DES_BLOCK_SIZE);
} else {
memcpy(IV, IVIn, CRYPTO_DES_BLOCK_SIZE);
}
DES_cbc_encrypt(encSrcBuf, plainDestBuf, bufSize, &keySched, &IV, DES_DECRYPT);
return bufSize;
}


static inline bool TestAESEncyptionRoutines(void) {
fprintf(stdout, ">>> TestAESEncryptionRoutines [non-DESFire command]:\n");
const uint8_t keyData[] = {
Expand Down Expand Up @@ -203,20 +234,7 @@ static inline bool TestAESEncyptionRoutines(void) {
}

static inline bool Test3DESEncyptionRoutines(void) {
fprintf(stdout, ">>> TestAESEncryptionRoutines [non-DESFire command]:\n");
//const uint8_t keyData[] = {
// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
//};
//const uint8_t ptData[] = {
// 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
// 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
//};
//const uint8_t ctData[] = {
// 0x3e, 0xf0, 0xa8, 0x91, 0xcf, 0x8e, 0xd9, 0x90,
// 0xc4, 0x77, 0xeb, 0x09, 0x02, 0xf0, 0xc5, 0x4a
//};
fprintf(stdout, ">>> Test3DESEncryptionRoutines [non-DESFire command]:\n");
const uint8_t keyData[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xf1, 0xe0, 0xd3, 0xc2, 0xb5, 0xa4, 0x97, 0x86,
Expand Down Expand Up @@ -266,6 +284,50 @@ static inline bool Test3DESEncyptionRoutines(void) {
fprintf(stdout, "\n");
return status;
}

static inline bool TestLegacyDESEncyptionRoutines(void) {
fprintf(stdout, ">>> TestLegacyDESEncryptionRoutines [non-DESFire command]:\n");
const uint8_t keyData[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
};
const uint8_t ptData[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
const uint8_t ctData[] = {
0x3e, 0xf0, 0xa8, 0x91, 0xcf, 0x8e, 0xd9, 0x90,
0xc4, 0x77, 0xeb, 0x09, 0x02, 0xf0, 0xc5, 0x4a
};
CryptoData_t cdata;
cdata.keyData = keyData;
cdata.keySize = 8;
const uint16_t testDataSize = 2 * 8;
uint8_t pt[testDataSize], ct[testDataSize];
EncryptDES(ptData, testDataSize, ct, NULL, cdata);
DecryptDES(ctData, testDataSize, pt, NULL, cdata);
fprintf(stdout, " -- : PT [FIXED] = "); print_hex(ptData, testDataSize);
fprintf(stdout, " -- : CT [FIXED] = "); print_hex(ctData, testDataSize);
fprintf(stdout, " -- : CT [ENC] = "); print_hex(ct, testDataSize);
fprintf(stdout, " -- : PT [DEC] = "); print_hex(pt, testDataSize);
bool status = true;
if(memcmp(ct, ctData, testDataSize)) {
fprintf(stdout, " -- CT does NOT match !!\n");
status = false;
}
else {
fprintf(stdout, " -- CT matches.\n");
}
if(memcmp(pt, ptData, testDataSize)) {
fprintf(stdout, " -- Decrypted PT from CT does NOT match !!\n");
status = false;
}
else {
fprintf(stdout, " -- Decrypted PT from CT matches.\n");
}
fprintf(stdout, "\n");
return status;
}

static inline int GenerateRandomBytes(uint8_t *destBuf, size_t numBytes) {
return RAND_pseudo_bytes(destBuf, numBytes);
}
Expand Down
Loading

0 comments on commit 195e600

Please sign in to comment.