Skip to content

Commit

Permalink
Stashing more working code to test PM3 compatibility (ISO/EV1 auth)
Browse files Browse the repository at this point in the history
  • Loading branch information
maxieds committed Mar 30, 2022
1 parent 7ecf3cb commit 45a6c3f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 39 deletions.
6 changes: 4 additions & 2 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFireCrypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ bool IsAuthenticated(void) {

BYTE GetDefaultCryptoMethodKeySize(uint8_t cryptoType) {
switch (cryptoType) {
case CRYPTO_TYPE_ANY:
return CRYPTO_3KTDEA_KEY_SIZE;
case CRYPTO_TYPE_2KTDEA:
return CRYPTO_2KTDEA_KEY_SIZE;
case CRYPTO_TYPE_3K3DES:
return CRYPTO_3KTDEA_KEY_SIZE;
case CRYPTO_TYPE_AES128:
return 16;
return CRYPTO_AES_BLOCK_SIZE;
default:
return 8;
return CRYPTO_DES_BLOCK_SIZE;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This notice must be retained at the top of all source files where indicated.
#include "DESFirePICCHeaderLayout.h"
#include "DESFireISO7816Support.h"
#include "DESFireInstructions.h"
#include "DESFireStatusCodes.h"
#include "../ISO14443-3A.h"

Iso7816WrappedParams_t Iso7816P1Data = ISO7816_NO_DATA;
Expand All @@ -37,6 +38,8 @@ uint8_t Iso7816EfIdNumber = ISO7816_EF_NOT_SPECIFIED;
Iso7816WrappedCommandType_t IsWrappedISO7816CommandType(uint8_t *Buffer, uint16_t ByteCount) {
if (ByteCount >= 6 && Buffer[3] == ByteCount - 6) {
return ISO7816_WRAPPED_CMD_TYPE_PM3RAW;
} else if (ByteCount >= 3 && Buffer[2] == STATUS_ADDITIONAL_FRAME) {
return ISO7816_WRAPPED_CMD_TYPE_PM3_ADDITIONAL_FRAME;
} else if (ByteCount <= ISO7816_PROLOGUE_SIZE + ISO14443A_CRCA_SIZE + 2) {
return ISO7816_WRAPPED_CMD_TYPE_NONE;
} else if (!Iso7816CLA(Buffer[2])) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,11 @@ extern uint8_t Iso7816FileOffset;
extern uint8_t Iso7816EfIdNumber;

typedef enum {
ISO7816_WRAPPED_CMD_TYPE_NONE = 0,
ISO7816_WRAPPED_CMD_TYPE_STANDARD = 1,
ISO7816_WRAPPED_CMD_TYPE_PM3RAW = 2,
/* Others ??? */
ISO7816_WRAPPED_CMD_TYPE_NONE = 0,
ISO7816_WRAPPED_CMD_TYPE_STANDARD = 1,
ISO7816_WRAPPED_CMD_TYPE_PM3RAW = 2,
ISO7816_WRAPPED_CMD_TYPE_PM3_ADDITIONAL_FRAME = 3,
/* ??? Others ??? */
} Iso7816WrappedCommandType_t;

Iso7816WrappedCommandType_t IsWrappedISO7816CommandType(uint8_t *Buffer, uint16_t ByteCount);
Expand Down
39 changes: 19 additions & 20 deletions Firmware/Chameleon-Mini/Application/DESFire/DESFireInstructions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1732,9 +1732,6 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) {
if (!AuthenticatedWithPICCMasterKey && KeyId != DESFIRE_MASTER_KEY_ID) {
Buffer[0] = STATUS_PERMISSION_DENIED;
return DESFIRE_STATUS_RESPONSE_SIZE;
} else if ((Authenticated || AuthenticatedWithPICCMasterKey) && AuthenticatedWithKey != KeyId) {
Buffer[0] = STATUS_NO_SUCH_KEY;
return DESFIRE_STATUS_RESPONSE_SIZE;
} else {
InvalidateAuthState(SelectedApp.Slot == DESFIRE_PICC_APP_SLOT);
}
Expand All @@ -1744,25 +1741,19 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) {
Buffer[0] = STATUS_PARAMETER_ERROR;
return DESFIRE_STATUS_RESPONSE_SIZE;
}
/* Make sure that this key is 3DES, and figure out its byte size */
BYTE cryptoKeyType = ReadKeyCryptoType(SelectedApp.Slot, KeyId);
if (!CryptoType3KTDEA(cryptoKeyType)) {
Buffer[0] = STATUS_NO_SUCH_KEY;
return DESFIRE_STATUS_RESPONSE_SIZE;
}

/* Update state */
Key = SessionKey;
DesfireCommandState.KeyId = KeyId;
BYTE selectedKeyCryptoType = ReadKeyCryptoType(SelectedApp.Slot, KeyId);
if (selectedKeyCryptoType == CRYPTO_TYPE_ANY || selectedKeyCryptoType == CRYPTO_TYPE_3K3DES) {
BYTE cryptoKeyType = ReadKeyCryptoType(SelectedApp.Slot, KeyId);
if (cryptoKeyType == CRYPTO_TYPE_ANY || cryptoKeyType == CRYPTO_TYPE_3K3DES) {
keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_3K3DES);
DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_3K3DES;
DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_3K3DES);
CryptoChallengeResponseBytesSize = CRYPTO_CHALLENGE_RESPONSE_BYTES;
} else if (selectedKeyCryptoType == CRYPTO_TYPE_AES128) {
} else if (cryptoKeyType == CRYPTO_TYPE_AES128) {
return DesfireCmdAuthenticateAES1(Buffer, ByteCount);
} else if (selectedKeyCryptoType == CRYPTO_TYPE_DES) {
} else if (cryptoKeyType == CRYPTO_TYPE_DES) {
keySize = GetDefaultCryptoMethodKeySize(CRYPTO_TYPE_DES);
DesfireCommandState.CryptoMethodType = CRYPTO_TYPE_DES;
DesfireCommandState.ActiveCommMode = GetCryptoMethodCommSettings(CRYPTO_TYPE_DES);
Expand All @@ -1776,7 +1767,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) {

/* Fetch the key */
ReadAppKey(SelectedApp.Slot, KeyId, Key, keySize);
if (selectedKeyCryptoType == CRYPTO_TYPE_DES) {
if (cryptoKeyType == CRYPTO_TYPE_DES) {
memcpy(&Key[CRYPTO_DES_BLOCK_SIZE], &Key[0], CRYPTO_DES_BLOCK_SIZE);
memcpy(&Key[2 * CRYPTO_DES_BLOCK_SIZE], &Key[0], CRYPTO_DES_BLOCK_SIZE);
}
Expand Down Expand Up @@ -1807,7 +1798,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA1(uint8_t *Buffer, uint16_t ByteCount) {
LogEntry(LOG_APP_NONCE_B, DesfireCommandState.RndB, CryptoChallengeResponseBytesSize);

/* Encrypt RndB with the selected key and transfer it back to the PCD */
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES) {
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES || cryptoKeyType == CRYPTO_TYPE_ANY) {
Encrypt3DESBuffer(CryptoChallengeResponseBytesSize, DesfireCommandState.RndB,
&Buffer[1], NULL, Key);
} else {
Expand All @@ -1833,14 +1824,22 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) {

cryptoKeyType = DesfireCommandState.CryptoMethodType;
keySize = GetDefaultCryptoMethodKeySize(cryptoKeyType);
CryptoChallengeResponseBytesSize = CRYPTO_CHALLENGE_RESPONSE_BYTES;
if (cryptoKeyType == CRYPTO_TYPE_ANY || cryptoKeyType == CRYPTO_TYPE_3K3DES) {
CryptoChallengeResponseBytesSize = CRYPTO_CHALLENGE_RESPONSE_BYTES;
} else if (cryptoKeyType == CRYPTO_TYPE_DES) {
CryptoChallengeResponseBytesSize = CRYPTO_DES_BLOCK_SIZE;
} else {
CryptoChallengeResponseBytesSize = CRYPTO_DES_BLOCK_SIZE;
}

/* Set status for the next incoming command on error */
DesfireState = DESFIRE_IDLE;
/* Validate command length */
if (ByteCount != 2 * CryptoChallengeResponseBytesSize + 1) {
Buffer[0] = STATUS_LENGTH_ERROR;
return DESFIRE_STATUS_RESPONSE_SIZE;
Buffer[1] = ByteCount;
Buffer[2] = CryptoChallengeResponseBytesSize;
return 3 * DESFIRE_STATUS_RESPONSE_SIZE;
}

/* Reset parameters for authentication from the first exchange */
Expand All @@ -1856,7 +1855,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) {
BYTE challengeRndAB[2 * CryptoChallengeResponseBytesSize];
BYTE challengeRndA[CryptoChallengeResponseBytesSize];
BYTE challengeRndB[CryptoChallengeResponseBytesSize];
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES) {
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES || cryptoKeyType == CRYPTO_TYPE_ANY) {
Decrypt3DESBuffer(2 * CryptoChallengeResponseBytesSize, challengeRndAB,
&Buffer[1], NULL, Key);
} else {
Expand All @@ -1876,7 +1875,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) {

/* Encrypt and send back the once rotated RndA buffer to the PCD */
RotateArrayLeft(challengeRndA, challengeRndAB, CryptoChallengeResponseBytesSize);
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES) {
if (cryptoKeyType == CRYPTO_TYPE_DES || cryptoKeyType == CRYPTO_TYPE_3K3DES || cryptoKeyType == CRYPTO_TYPE_ANY) {
Encrypt3DESBuffer(CryptoChallengeResponseBytesSize, challengeRndAB,
&Buffer[1], NULL, Key);
} else {
Expand All @@ -1897,7 +1896,7 @@ uint16_t DesfireCmdAuthenticate3KTDEA2(uint8_t *Buffer, uint16_t ByteCount) {

/* Return the status on success */
Buffer[0] = STATUS_OPERATION_OK;
return DESFIRE_STATUS_RESPONSE_SIZE;
return DESFIRE_STATUS_RESPONSE_SIZE + CryptoChallengeResponseBytesSize;

}

Expand Down
24 changes: 20 additions & 4 deletions Firmware/Chameleon-Mini/Application/MifareDESFire.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) {
if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_STANDARD) {
memmove(&Buffer[0], &Buffer[2], ByteCount - 2);
ByteCount = ByteCount - 2;
} else if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_PM3_ADDITIONAL_FRAME) {
Buffer[0] = DesfireCmdCLA;
Buffer[1] = STATUS_ADDITIONAL_FRAME;
if (ByteCount > 3) {
memmove(&Buffer[3], &Buffer[5], ByteCount - 3);
}
Buffer[2] = 0x00;
Buffer[3] = 0x00;
Buffer[4] = ByteCount - 3;
ByteCount += 1;
} else if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_PM3RAW) {
/* Something like the following (for PM3 raw ISO auth):
* 0a 00 1a 00 CRC1 CRC2 -- first two are prologue -- last two are checksum
Expand All @@ -250,12 +260,15 @@ uint16_t MifareDesfireAppProcess(uint8_t *Buffer, uint16_t BitCount) {
Buffer[3] = 0x00;
Buffer[4] = ByteCount - 5;
}
uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, ByteCount);
uint16_t UnwrappedBitCount = IncomingByteCount * BITS_PER_BYTE;
uint16_t UnwrappedBitCount = ByteCount * BITS_PER_BYTE;
if (Iso7816CmdType != ISO7816_WRAPPED_CMD_TYPE_PM3_ADDITIONAL_FRAME) {
uint16_t IncomingByteCount = DesfirePreprocessAPDU(ActiveCommMode, Buffer, ByteCount);
UnwrappedBitCount = IncomingByteCount * BITS_PER_BYTE;
}
uint16_t ProcessedBitCount = MifareDesfireProcess(Buffer, UnwrappedBitCount);
uint16_t ProcessedByteCount = (ProcessedBitCount + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
/* Undo the leading 0x91 and shift for the PM3 raw wrapped commands: (TODO) */
if (Iso7816CmdType == ISO7816_WRAPPED_CMD_TYPE_PM3RAW && ProcessedByteCount > 0) {
/* Undo the leading 0x91 and shift for the PM3 raw wrapped commands: */
if (Iso7816CmdType != ISO7816_WRAPPED_CMD_TYPE_STANDARD && ProcessedByteCount > 0) {
memmove(&Buffer[1], &Buffer[0], ProcessedByteCount);
Buffer[0] = Buffer[ProcessedByteCount];
--ProcessedByteCount;
Expand Down Expand Up @@ -312,6 +325,9 @@ void ResetLocalStructureData(void) {
SessionIVByteSize = 0x00;
SelectedApp.Slot = 0;
SelectedFile.Num = -1;
ISO144433AReset();
ISO144434Reset();
MifareDesfireReset();
}

void MifareDesfireGetUid(ConfigurationUidType Uid) {
Expand Down
18 changes: 9 additions & 9 deletions Firmware/Chameleon-Mini/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ SETTINGS += -DENABLE_EEPROM_SETTINGS

#Set a default logging mode for debugging with the DESFire
#emulation code:
#SETTINGS += -DDESFIRE_DEFAULT_LOGGING_MODE=DEBUGGING
SETTINGS += -DDESFIRE_DEFAULT_LOGGING_MODE=OFF
#CONFIG_SETTINGS += -DDESFIRE_DEFAULT_LOGGING_MODE=DEBUGGING
CONFIG_SETTINGS += -DDESFIRE_DEFAULT_LOGGING_MODE=OFF

#Set a default testing mode setting (0 = OFF, non-NULL = ON):
SETTINGS += -DDESFIRE_DEFAULT_TESTING_MODE=0
#SETTINGS += -DDESFIRE_DEFAULT_TESTING_MODE=1
CONFIG_SETTINGS += -DDESFIRE_DEFAULT_TESTING_MODE=0
#CONFIG_SETTINGS += -DDESFIRE_DEFAULT_TESTING_MODE=1

#Feature: Use randomized UIDs that mask the actual secret UID until
#the tag has been issued a successful authentication sequence:
Expand All @@ -124,10 +124,10 @@ SETTINGS += -DDESFIRE_DEFAULT_TESTING_MODE=0

#Set a minimum incoming/outgoing log size so we do not spam the
#Chameleon Mini logs to much by logging everything:
SETTINGS += -DDESFIRE_MIN_INCOMING_LOGSIZE=1
#SETTINGS += -DDESFIRE_MIN_INCOMING_LOGSIZE=0
#SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=1
#SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=0
CONFIG_SETTINGS += -DDESFIRE_MIN_INCOMING_LOGSIZE=1
#CONFIG_SETTINGS += -DDESFIRE_MIN_INCOMING_LOGSIZE=0
#CONFIG_SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=1
#CONFIG_SETTINGS += -DDESFIRE_MIN_OUTGOING_LOGSIZE=0

#Enable printing of crypto tests when a new DESFire emulation instance is started:
#SETTINGS += -DDESFIRE_RUN_CRYPTO_TESTING_PROCEDURE
Expand Down Expand Up @@ -320,7 +320,7 @@ desfire-build: local-clean $(TARGET).elf $(TARGET).hex $(TARGET).eep $(TARGET).b
@avr-size -B -x $(TARGET).elf
@echo ""
@avr-size -C -x $(TARGET).elf
desfire: CONFIG_SETTINGS:=$(DESFIRE_CONFIG_SETTINGS_BASE) -DDEFAULT_CONFIGURATION=CONFIG_NONE -fno-inline-small-functions
desfire: CONFIG_SETTINGS:=$(DESFIRE_CONFIG_SETTINGS_BASE) -fno-inline-small-functions
desfire: desfire-build

desfire-dev: CONFIG_SETTINGS:=$(DESFIRE_CONFIG_SETTINGS_BASE) -fno-inline-small-functions \
Expand Down

0 comments on commit 45a6c3f

Please sign in to comment.