Skip to content

Commit a24fbe8

Browse files
committed
Preliminary (partial) support for more CommModes -- This is going to need substantial testing -- III
1 parent 74f216f commit a24fbe8

File tree

8 files changed

+222
-173
lines changed

8 files changed

+222
-173
lines changed

Firmware/Chameleon-Mini/Application/CryptoAES128.c

+15-15
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,8 @@ uint8_t CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciph
296296
// This routine performs the CBC "send" mode chaining: C = E(P ^ IV); IV = C
297297
static void CryptoAES_CBCSend(uint16_t Count, void *Plaintext, void *Ciphertext, uint8_t *IV, uint8_t *Key, CryptoAES_CBCSpec_t CryptoSpec);
298298
static void CryptoAES_CBCSend(uint16_t Count, void *Plaintext, void *Ciphertext,
299-
uint8_t *IV, uint8_t *Key,
300-
CryptoAES_CBCSpec_t CryptoSpec) {
299+
uint8_t *IV, uint8_t *Key,
300+
CryptoAES_CBCSpec_t CryptoSpec) {
301301
uint16_t numBlocks = CRYPTO_BYTES_TO_BLOCKS(Count, CryptoSpec.blockSize);
302302
uint16_t blockIndex = 0;
303303
uint8_t *ptBuf = (uint8_t *) Plaintext, *ctBuf = (uint8_t *) Ciphertext;
@@ -323,8 +323,8 @@ static void CryptoAES_CBCSend(uint16_t Count, void *Plaintext, void *Ciphertext,
323323
// This routine performs the CBC "receive" mode chaining: C = E(P) ^ IV; IV = P
324324
static void CryptoAES_CBCRecv(uint16_t Count, void *Plaintext, void *Ciphertext, uint8_t *IV, uint8_t *Key, CryptoAES_CBCSpec_t CryptoSpec);
325325
static void CryptoAES_CBCRecv(uint16_t Count, void *Plaintext, void *Ciphertext,
326-
uint8_t *IV, uint8_t *Key,
327-
CryptoAES_CBCSpec_t CryptoSpec) {
326+
uint8_t *IV, uint8_t *Key,
327+
CryptoAES_CBCSpec_t CryptoSpec) {
328328
uint16_t numBlocks = CRYPTO_BYTES_TO_BLOCKS(Count, CryptoSpec.blockSize);
329329
uint16_t blockIndex = 0;
330330
uint8_t *ptBuf = (uint8_t *) Plaintext, *ctBuf = (uint8_t *) Ciphertext;
@@ -389,18 +389,18 @@ uint16_t appendBufferCRC32C(uint8_t *bufferData, uint16_t bufferSize) {
389389
uint32_t workingCRC = INIT_CRC32C_VALUE;
390390
for (int i = 0; i < bufferSize; i++) {
391391
workingCRC = workingCRC ^ *(bufferData++);
392-
for (int j = 0; j < 8; j++) {
392+
for (int j = 0; j < 8; j++) {
393393
if (workingCRC & 1) {
394-
workingCRC = (workingCRC >> 1) ^ LE_CRC32C_POLYNOMIAL;
395-
} else {
396-
workingCRC = workingCRC >> 1;
397-
}
398-
}
394+
workingCRC = (workingCRC >> 1) ^ LE_CRC32C_POLYNOMIAL;
395+
} else {
396+
workingCRC = workingCRC >> 1;
397+
}
398+
}
399399
}
400-
// Append the CRC32C bytes in little endian byte order to the end of the buffer:
401-
bufferData[bufferSize] = (uint8_t) (workingCRC & 0x000000FF);
402-
bufferData[bufferSize + 1] = (uint8_t) ((workingCRC & 0x0000FF00) >> 8);
403-
bufferData[bufferSize + 2] = (uint8_t) ((workingCRC & 0x00FF0000) >> 16);
404-
bufferData[bufferSize + 4] = (uint8_t) ((workingCRC & 0xFF000000) >> 24);
400+
// Append the CRC32C bytes in little endian byte order to the end of the buffer:
401+
bufferData[bufferSize] = (uint8_t)(workingCRC & 0x000000FF);
402+
bufferData[bufferSize + 1] = (uint8_t)((workingCRC & 0x0000FF00) >> 8);
403+
bufferData[bufferSize + 2] = (uint8_t)((workingCRC & 0x00FF0000) >> 16);
404+
bufferData[bufferSize + 4] = (uint8_t)((workingCRC & 0xFF000000) >> 24);
405405
return bufferSize + 4;
406406
}

Firmware/Chameleon-Mini/Application/CryptoCMAC.c

+82-32
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ static void getCMACSubK1(const uint8_t *bufferL, uint8_t blockSize, uint8_t poly
4545
RotateArrayLeft(bufferL, bufferOut, blockSize);
4646
if ((bufferL[0] & 0x80) != 0) {
4747
for (int kidx = 0; kidx < blockSize; kidx++) {
48-
bufferOut[kidx] = (uint8_t) (bufferOut[kidx] ^ _cmac_RB[kidx]);
49-
}
48+
bufferOut[kidx] = (uint8_t)(bufferOut[kidx] ^ _cmac_RB[kidx]);
49+
}
5050
}
5151
}
5252

@@ -56,8 +56,8 @@ static void getCMACSubK2(const uint8_t *bufferK1, uint8_t blockSize, uint8_t pol
5656
RotateArrayLeft(bufferK1, bufferOut, blockSize);
5757
if ((bufferK1[0] & 0x80) != 0) {
5858
for (int kidx = 0; kidx < blockSize; kidx++) {
59-
bufferOut[kidx] = (uint8_t) (bufferOut[kidx] ^ _cmac_RB[kidx]);
60-
}
59+
bufferOut[kidx] = (uint8_t)(bufferOut[kidx] ^ _cmac_RB[kidx]);
60+
}
6161
}
6262
}
6363

@@ -66,32 +66,32 @@ static bool appendBufferCMACSubroutine(uint8_t cryptoType, const uint8_t *keyDat
6666
uint16_t newBlockSize = bufferSize;
6767
if (bufferSize == 0) {
6868
memset(bufferOut, 0x00, blockSize);
69-
bufferOut[0] = (uint8_t) 0x80;
70-
newBlockSize = blockSize;
69+
bufferOut[0] = (uint8_t) 0x80;
70+
newBlockSize = blockSize;
7171
} else if ((bufferSize % blockSize) != 0) {
72-
newBlockSize = bufferSize - (bufferSize % blockSize) + blockSize;
72+
newBlockSize = bufferSize - (bufferSize % blockSize) + blockSize;
7373
bufferOut[bufferSize] = (uint8_t) 0x80;
7474
}
7575
if (bufferSize != 0 && (bufferSize % blockSize) == 0) {
7676
// Complete block (use K1):
77-
for (int i = bufferSize - blockSize; i < bufferSize; i++) {
77+
for (int i = bufferSize - blockSize; i < bufferSize; i++) {
7878
bufferOut[i] ^= bufferK1[i - bufferSize + blockSize];
79-
}
79+
}
8080
} else {
8181
// Incomplete block (use K2):
82-
for (int i = bufferSize - blockSize; i < bufferSize; i++) {
82+
for (int i = bufferSize - blockSize; i < bufferSize; i++) {
8383
bufferOut[i] ^= bufferK2[i - bufferSize + blockSize];
84-
}
84+
}
8585
}
8686
switch (cryptoType) {
8787
case CRYPTO_TYPE_3K3DES:
88-
Encrypt3DESBuffer(newBlockSize, bufferOut, bufferOut + bufferSize, keyData, bufferIV);
89-
break;
90-
case CRYPTO_TYPE_AES128:
91-
CryptoAESEncryptBuffer(newBlockSize, bufferOut, bufferOut + bufferSize, keyData, bufferIV);
92-
break;
88+
Encrypt3DESBuffer(newBlockSize, bufferOut, &bufferOut[bufferSize], keyData, bufferIV);
89+
break;
90+
case CRYPTO_TYPE_AES128:
91+
CryptoAESEncryptBuffer(newBlockSize, bufferOut, &bufferOut[bufferSize], keyData, bufferIV);
92+
break;
9393
default:
94-
return false;
94+
return false;
9595
}
9696
memmove(&bufferOut[0], &bufferOut[newBlockSize], newBlockSize);
9797
memcpy(_cmac_final, &bufferOut[newBlockSize - blockSize], blockSize);
@@ -103,40 +103,90 @@ bool appendBufferCMAC(uint8_t cryptoType, const uint8_t *keyData, uint8_t *buffe
103103
uint8_t blockSize, rb;
104104
uint8_t *nistL = _cmac_K2;
105105
switch (cryptoType) {
106-
case CRYPTO_TYPE_3K3DES:
106+
case CRYPTO_TYPE_3K3DES:
107107
blockSize = CRYPTO_3KTDEA_BLOCK_SIZE;
108-
rb = CRYPTO_CMAC_RB64;
109-
memset(_cmac_zeros, 0x00, blockSize);
110-
Encrypt3DESBuffer(blockSize, _cmac_zeros, nistL, _cmac_zeros, keyData);
111-
break;
112-
case CRYPTO_TYPE_AES128:
108+
rb = CRYPTO_CMAC_RB64;
109+
memset(_cmac_zeros, 0x00, blockSize);
110+
Encrypt3DESBuffer(blockSize, _cmac_zeros, nistL, _cmac_zeros, keyData);
111+
break;
112+
case CRYPTO_TYPE_AES128:
113113
blockSize = CRYPTO_AES_BLOCK_SIZE;
114-
rb = CRYPTO_CMAC_RB128;
115-
memset(_cmac_zeros, 0x00, blockSize);
116-
CryptoAESEncryptBuffer(blockSize, _cmac_zeros, nistL, _cmac_zeros, keyData);
117-
break;
114+
rb = CRYPTO_CMAC_RB128;
115+
memset(_cmac_zeros, 0x00, blockSize);
116+
CryptoAESEncryptBuffer(blockSize, _cmac_zeros, nistL, _cmac_zeros, keyData);
117+
break;
118118
default:
119-
return false;
119+
return false;
120120
}
121121
getCMACSubK1(nistL, blockSize, rb, _cmac_K1);
122122
getCMACSubK2(_cmac_K1, blockSize, rb, _cmac_K2);
123123
if (IV == NULL) {
124124
IV = _cmac_zeros;
125-
memset(IV, 0x00, blockSize);
126-
return appendBufferCMACSubroutine(cryptoType, keyData, _cmac_K1, _cmac_K2, IV, blockSize, bufferData, bufferSize);
125+
memset(IV, 0x00, blockSize);
126+
return appendBufferCMACSubroutine(cryptoType, keyData, _cmac_K1, _cmac_K2, IV, blockSize, bufferData, bufferSize);
127127
} else {
128128
return appendBufferCMACSubroutine(cryptoType, keyData, _cmac_K1, _cmac_K2, IV, blockSize, bufferData, bufferSize);
129129
}
130130
}
131131

132+
bool checkBufferCMAC(uint8_t *bufferData, uint16_t bufferSize, uint16_t checksumSize) {
133+
if (checksumSize > bufferSize) {
134+
return false;
135+
}
136+
if (checksumSize == CRYPTO_3KTDEA_BLOCK_SIZE) {
137+
appendBufferCMAC(CRYPTO_TYPE_3K3DES, SessionKey, &bufferData[bufferSize], bufferSize - checksumSize, SessionIV);
138+
memcpy(_cmac_zeros, &bufferData[bufferSize], checksumSize);
139+
if (memcmp(_cmac_zeros, &bufferData[bufferSize - checksumSize], checksumSize)) {
140+
return false;
141+
}
142+
return true;
143+
} else if (checksumSize == CRYPTO_AES_BLOCK_SIZE) {
144+
appendBufferCMAC(CRYPTO_TYPE_AES128, SessionKey, &bufferData[bufferSize], bufferSize - checksumSize, SessionIV);
145+
memcpy(_cmac_zeros, &bufferData[bufferSize], checksumSize);
146+
if (memcmp(_cmac_zeros, &bufferData[bufferSize - checksumSize], checksumSize)) {
147+
return false;
148+
}
149+
return true;
150+
}
151+
return false;
152+
}
153+
132154
uint16_t appendBufferMAC(const uint8_t *keyData, uint8_t *bufferData, uint16_t bufferSize) {
133155
memcpy(&_mac_key24[2 * CRYPTO_DES_BLOCK_SIZE], keyData, CRYPTO_DES_BLOCK_SIZE);
134156
memcpy(&_mac_key24[CRYPTO_DES_BLOCK_SIZE], keyData, CRYPTO_DES_BLOCK_SIZE);
135157
memcpy(&_mac_key24[0], keyData, CRYPTO_DES_BLOCK_SIZE);
136158
memset(&_cmac_zeros[0], 0x00, CRYPTO_DES_BLOCK_SIZE);
137-
Encrypt3DESBuffer(bufferSize, bufferData, &bufferData[3 * CRYPTO_DES_BLOCK_SIZE], _cmac_zeros, keyData);
159+
uint16_t paddedBufferSize = bufferSize;
160+
if ((bufferSize % CRYPTO_DES_BLOCK_SIZE) != 0) {
161+
paddedBufferSize = bufferSize + CRYPTO_DES_BLOCK_SIZE - (bufferSize % CRYPTO_DES_BLOCK_SIZE);
162+
memset(&bufferData[bufferSize], 0x00, paddedBufferSize - bufferSize);
163+
}
164+
Encrypt3DESBuffer(paddedBufferSize, bufferData, &bufferData[paddedBufferSize], _cmac_zeros, keyData);
138165
// Copy the 4-byte MAC from the ciphertext (end of the bufferData array):
139-
memcpy(&_cmac_zeros[0], &bufferData[3 * CRYPTO_DES_BLOCK_SIZE + bufferSize - CRYPTO_DES_BLOCK_SIZE], 4);
166+
memcpy(&_cmac_zeros[0], &bufferData[paddedBufferSize - CRYPTO_DES_BLOCK_SIZE], 4);
140167
memcpy(&bufferData[bufferSize], &_cmac_zeros[0], 4);
141168
return bufferSize + 4;
142169
}
170+
171+
bool checkBufferMAC(uint8_t *bufferData, uint16_t bufferSize, uint16_t checksumSize) {
172+
if (checksumSize > bufferSize) {
173+
return false;
174+
}
175+
const uint8_t *keyData = SessionKey;
176+
memcpy(&_mac_key24[2 * CRYPTO_DES_BLOCK_SIZE], keyData, CRYPTO_DES_BLOCK_SIZE);
177+
memcpy(&_mac_key24[CRYPTO_DES_BLOCK_SIZE], keyData, CRYPTO_DES_BLOCK_SIZE);
178+
memcpy(&_mac_key24[0], keyData, CRYPTO_DES_BLOCK_SIZE);
179+
memset(&_cmac_zeros[0], 0x00, CRYPTO_DES_BLOCK_SIZE);
180+
uint16_t paddedBufferSize = bufferSize;
181+
if ((bufferSize % CRYPTO_DES_BLOCK_SIZE) != 0) {
182+
paddedBufferSize = bufferSize + CRYPTO_DES_BLOCK_SIZE - (bufferSize % CRYPTO_DES_BLOCK_SIZE);
183+
memset(&bufferData[bufferSize], 0x00, paddedBufferSize - bufferSize);
184+
}
185+
Encrypt3DESBuffer(paddedBufferSize, bufferData, &bufferData[paddedBufferSize], _cmac_zeros, keyData);
186+
// Copy the 4-byte MAC from the ciphertext (end of the bufferData array):
187+
memcpy(&_cmac_zeros[0], &bufferData[paddedBufferSize - CRYPTO_DES_BLOCK_SIZE], 4);
188+
if (memcmp(&bufferData[bufferSize - checksumSize], &_cmac_zeros[0], 4)) {
189+
return false;
190+
}
191+
return true;
192+
}

Firmware/Chameleon-Mini/Application/DESFire/DESFireChameleonTerminal.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -226,19 +226,19 @@ CommandStatusIdType CommandDESFireSetCommMode(char *OutParam, const char *InPara
226226
if (!strcasecmp_P(valueStr, PSTR("Plaintext"))) {
227227
DesfireCommMode = DESFIRE_COMMS_PLAINTEXT;
228228
DesfireCommandState.ActiveCommMode = DesfireCommMode;
229-
return COMMAND_INFO_OK;
229+
return COMMAND_INFO_OK;
230230
} else if (!strcasecmp_P(valueStr, PSTR("Plaintext:MAC"))) {
231231
DesfireCommMode = DESFIRE_COMMS_PLAINTEXT_MAC;
232232
DesfireCommandState.ActiveCommMode = DesfireCommMode;
233233
return COMMAND_INFO_OK;
234234
} else if (!strcasecmp_P(valueStr, PSTR("Enciphered:3K3DES"))) {
235235
DesfireCommMode = DESFIRE_COMMS_CIPHERTEXT_DES;
236236
DesfireCommandState.ActiveCommMode = DesfireCommMode;
237-
return COMMAND_INFO_OK;
237+
return COMMAND_INFO_OK;
238238
} else if (!strcasecmp_P(valueStr, PSTR("Enciphered:AES128"))) {
239239
DesfireCommMode = DESFIRE_COMMS_CIPHERTEXT_AES128;
240240
DesfireCommandState.ActiveCommMode = DesfireCommMode;
241-
return COMMAND_INFO_OK;
241+
return COMMAND_INFO_OK;
242242
}
243243
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("Options are: Plaintext|Plaintext:MAC|Enciphered:3K3DES|Enciphered:AES128"));
244244
return COMMAND_ERR_INVALID_USAGE_ID;

Firmware/Chameleon-Mini/Application/DESFire/DESFirePICCControl.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ uint8_t ReadDataFilterSetup(uint8_t CommSettings) {
151151
TransferState.WriteData.Encryption.Func = &CryptoAESEncrypt_CBCSend;
152152
memset(SessionIV, 0, sizeof(SessionIVByteSize));
153153
SessionIVByteSize = CRYPTO_AES_KEY_SIZE;
154-
default:
154+
default:
155155
return STATUS_PARAMETER_ERROR;
156156
}
157157
return STATUS_OPERATION_OK;
@@ -160,12 +160,12 @@ uint8_t ReadDataFilterSetup(uint8_t CommSettings) {
160160
uint8_t WriteDataFilterSetup(uint8_t CommSettings) {
161161
switch (CommSettings) {
162162
case DESFIRE_COMMS_PLAINTEXT:
163-
TransferState.Checksums.UpdateFunc = NULL;
164-
TransferState.Checksums.FinalFunc = NULL;
165-
TransferState.Checksums.MACData.CryptoChecksumFunc.TDEAFunc = NULL;
163+
TransferState.Checksums.UpdateFunc = NULL;
164+
TransferState.Checksums.FinalFunc = NULL;
165+
TransferState.Checksums.MACData.CryptoChecksumFunc.TDEAFunc = NULL;
166166
memset(SessionIV, 0, sizeof(SessionIVByteSize));
167-
SessionIVByteSize = 0;
168-
break;
167+
SessionIVByteSize = 0;
168+
break;
169169
case DESFIRE_COMMS_PLAINTEXT_MAC:
170170
TransferState.Checksums.UpdateFunc = &TransferChecksumUpdateMACTDEA;
171171
TransferState.Checksums.FinalFunc = &TransferChecksumFinalMACTDEA;
@@ -181,8 +181,8 @@ uint8_t WriteDataFilterSetup(uint8_t CommSettings) {
181181
memset(SessionIV, 0, sizeof(SessionIVByteSize));
182182
SessionIVByteSize = CRYPTO_AES_KEY_SIZE;
183183
break;
184-
case DESFIRE_COMMS_CIPHERTEXT_AES128:
185-
// A.k.a., CommMode=FULL from NXP application note AN12343:
184+
case DESFIRE_COMMS_CIPHERTEXT_AES128:
185+
// A.k.a., CommMode=FULL from NXP application note AN12343:
186186
TransferState.Checksums.UpdateFunc = &TransferChecksumUpdateCMAC;
187187
TransferState.Checksums.FinalFunc = &TransferChecksumFinalCMAC;
188188
TransferState.Checksums.MACData.CRCA = ISO14443A_CRCA_INIT; // TODO ???

0 commit comments

Comments
 (0)