Merge pull request #2679 from nvx/d40_crypto_fix

fis MF3ICD40 (D40) secure channel crypto
This commit is contained in:
Iceman 2024-12-05 06:21:49 +01:00 committed by GitHub
commit c849a06a0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 10 additions and 3 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Fixed DESFire D40 secure channel crypto (@nvx)
- Fixed `hf mfp info` fix signature check on 4b UID cards (@doegox) - Fixed `hf mfp info` fix signature check on 4b UID cards (@doegox)
- Automatically set maximum read/write block when using predefined types in `hf_mf_ultimatecard` script (@piotrva) - Automatically set maximum read/write block when using predefined types in `hf_mf_ultimatecard` script (@piotrva)
- Changed SPI flash detection to calculate the size instead of table lookup, updated spi_flash_decode.py script with more ICs (@ANTodorov) - Changed SPI flash detection to calculate the size instead of table lookup, updated spi_flash_decode.py script with more ICs (@ANTodorov)

View file

@ -1222,14 +1222,17 @@ static int DesfireAuthenticateEV1(DesfireContext_t *dctx, DesfireSecureChannel s
// - Encrypt our response // - Encrypt our response
if (secureChannel == DACd40) { if (secureChannel == DACd40) {
// Original DESFire (MF3ICD40) silicon can only do encryption operations, so all PCD
// side operations must be decrypt, even when encrypting when doing D40 compatible
// secure channel operations
memset(IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); memset(IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE);
DesfireCryptoEncDecEx(dctx, DCOMainKey, RndA, rndlen, encRndA, true, true, IV); DesfireCryptoEncDecEx(dctx, DCOMainKey, RndA, rndlen, encRndA, true, false, IV);
memcpy(both, encRndA, rndlen); memcpy(both, encRndA, rndlen);
bin_xor(rotRndB, encRndA, rndlen); bin_xor(rotRndB, encRndA, rndlen);
memset(IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); memset(IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE);
DesfireCryptoEncDecEx(dctx, DCOMainKey, rotRndB, rndlen, encRndB, true, true, IV); DesfireCryptoEncDecEx(dctx, DCOMainKey, rotRndB, rndlen, encRndB, true, false, IV);
memcpy(both + rndlen, encRndB, rndlen); memcpy(both + rndlen, encRndB, rndlen);
} else if (secureChannel == DACEV1) { } else if (secureChannel == DACEV1) {

View file

@ -313,6 +313,10 @@ static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, ui
size_t srcmaclen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType)); size_t srcmaclen = padded_data_length(srcdatalen - hdrlen, desfire_get_key_block_length(ctx->keyType));
uint8_t mac[32] = {0}; uint8_t mac[32] = {0};
PrintAndLogEx(DEBUG, "MACing");
// Even though original DESFire (MF3ICD40) silicon can only encrypt which means normally
// every PCD operation must be decrypt, verifying a MAC involves the same operation on both
// sides so this is still encrypt here
DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, data, srcmaclen, NULL, true, true, mac); DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, data, srcmaclen, NULL, true, true, mac);
if (DesfireEV1D40TransmitMAC(ctx, cmd)) { if (DesfireEV1D40TransmitMAC(ctx, cmd)) {
@ -889,4 +893,3 @@ bool PrintChannelModeWarning(uint8_t cmd, DesfireSecureChannel secureChannel, De
return found; return found;
} }