From 126189aa0396fd1d2d529f1fd3f780b748611e71 Mon Sep 17 00:00:00 2001 From: Maxie Dion Schmidt Date: Tue, 19 Jul 2022 22:00:24 -0400 Subject: [PATCH] Verified ISODES and legacy DES auth schemes work ; AES-128 auth support is verified with the PM3 --- .../LocalInclude/CryptoUtils.h | 82 +----------- .../LocalInclude/DesfireUtils.h | 124 +----------------- Software/DESFireLibNFCTesting/Makefile | 1 - .../TestAuthenticateAES128.dump | 26 ---- .../TestAuthenticateLegacy.dump | 23 ++++ .../Source/TestAuthenticateAES128.c | 39 ------ 6 files changed, 26 insertions(+), 269 deletions(-) delete mode 100644 Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateAES128.dump create mode 100644 Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateLegacy.dump delete mode 100644 Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c diff --git a/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h b/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h index e966a728..4282e1c8 100644 --- a/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h +++ b/Software/DESFireLibNFCTesting/LocalInclude/CryptoUtils.h @@ -6,11 +6,7 @@ #include #include -#include #include -#include -#include -#include #include #include "LibNFCUtils.h" @@ -78,78 +74,6 @@ typedef struct { } \ }) -/* Set the last operation mode (ECB or CBC) init for the context */ -static uint8_t __CryptoAESOpMode = CRYPTO_AES_ECB_MODE; - -static inline size_t EncryptAES128(const uint8_t *plainSrcBuf, size_t bufSize, - uint8_t *encDestBuf, CryptoData_t cdata) { - size_t bufBlocks = bufSize / AES128_BLOCK_SIZE; - bool padLastBlock = (bufSize % AES128_BLOCK_SIZE) != 0; - uint8_t IV[AES128_BLOCK_SIZE], inputBlock[AES128_BLOCK_SIZE]; - if (cdata.ivData != NULL) { - memcpy(&IV[0], &cdata.ivData[0], AES128_BLOCK_SIZE); - } else { - memset(&IV[0], 0x00, AES128_BLOCK_SIZE); - } - if ((bufSize % AES128_BLOCK_SIZE) != 0) { - return 0xBE; - } - EVP_CIPHER_CTX *aesCtx = EVP_CIPHER_CTX_new(); - int aesOpInitStatus = 1; - if (__CryptoAESOpMode == CRYPTO_AES_CBC_MODE) { - aesOpInitStatus = EVP_EncryptInit_ex(aesCtx, EVP_aes_128_cbc(), NULL, cdata.keyData, cdata.ivData); - } else { /* ECB mode */ - aesOpInitStatus = EVP_EncryptInit_ex(aesCtx, EVP_aes_128_ecb(), NULL, cdata.keyData, cdata.ivData); - } - int ctextLength = 0, ctextInitLength = 0; - if (aesOpInitStatus != 1) { - ctextLength = 0xBE00 | aesOpInitStatus; - } else if (EVP_EncryptUpdate(aesCtx, encDestBuf, &ctextInitLength, plainSrcBuf, bufSize) != 1) { - ctextLength = 0; - } else { - ctextLength = ctextInitLength; - if (EVP_EncryptFinal_ex(aesCtx, &encDestBuf[ctextInitLength], &ctextInitLength) != 1) { - ctextLength += ctextInitLength; - } - } - EVP_CIPHER_CTX_free(aesCtx); - return ctextLength; -} - -static inline size_t DecryptAES128(const uint8_t *encSrcBuf, size_t bufSize, - uint8_t *plainDestBuf, CryptoData_t cdata) { - size_t bufBlocks = bufSize / AES128_BLOCK_SIZE; - bool padLastBlock = (bufSize % AES128_BLOCK_SIZE) != 0; - uint8_t IV[AES128_BLOCK_SIZE], inputBlock[AES128_BLOCK_SIZE]; - if (cdata.ivData != NULL) { - memcpy(&IV[0], &cdata.ivData[0], AES128_BLOCK_SIZE); - } else { - memset(&IV[0], 0x00, AES128_BLOCK_SIZE); - } - if ((bufSize % AES128_BLOCK_SIZE) != 0) { - return 0xBE; - } - EVP_CIPHER_CTX *aesCtx = EVP_CIPHER_CTX_new(); - int aesOpInitStatus = 1; - if (__CryptoAESOpMode == CRYPTO_AES_CBC_MODE) { - aesOpInitStatus = EVP_DecryptInit_ex(aesCtx, EVP_aes_128_cbc(), NULL, cdata.keyData, cdata.ivData); - } else { /* ECB mode */ - aesOpInitStatus = EVP_DecryptInit_ex(aesCtx, EVP_aes_128_ecb(), NULL, cdata.keyData, cdata.ivData); - } - int ctextLength = 0, ctextInitLength = 0; - if (aesOpInitStatus != 1) { - ctextLength = 0xBE00 | aesOpInitStatus; - } else if (EVP_DecryptUpdate(aesCtx, plainDestBuf, &ctextInitLength, encSrcBuf, bufSize) != 1) { - ctextLength = 0; - } else { - ctextLength = ctextInitLength; - if (EVP_DecryptFinal_ex(aesCtx, &plainDestBuf[ctextInitLength], &ctextInitLength) != 1) { - ctextLength += ctextInitLength; - } - } - EVP_CIPHER_CTX_free(aesCtx); - return ctextLength; -} /* Set the last operation mode (ECB or CBC) init for the context */ static uint8_t __CryptoDESOpMode = CRYPTO_DES_ECB_MODE; @@ -211,7 +135,7 @@ static inline size_t Decrypt2K3DES(const uint8_t *encSrcBuf, size_t bufSize, static inline size_t Encrypt3DES(const uint8_t *plainSrcBuf, size_t bufSize, uint8_t *encDestBuf, const uint8_t *IVIn, CryptoData_t cdata) { DES_key_schedule keySched1, keySched2, keySched3; - uint8_t IV[CRYPTO_DES_BLOCK_SIZE]; + uint8_t IV[CRYPTO_DES_BLOCK_SIZE], inputBlock[CRYPTO_DES_BLOCK_SIZE]; uint8_t *kd1 = cdata.keyData, *kd2 = &(cdata.keyData[CRYPTO_DES_BLOCK_SIZE]), *kd3 = &(cdata.keyData[2 * CRYPTO_DES_BLOCK_SIZE]); DES_set_key(kd1, &keySched1); DES_set_key(kd2, &keySched2); @@ -224,7 +148,6 @@ static inline size_t Encrypt3DES(const uint8_t *plainSrcBuf, size_t bufSize, if (__CryptoDESOpMode == CRYPTO_DES_CBC_MODE) { DES_ede3_cbc_encrypt(plainSrcBuf, encDestBuf, bufSize, &keySched1, &keySched2, &keySched3, &IV, DES_ENCRYPT); } else { - uint8_t inputBlock[CRYPTO_DES_BLOCK_SIZE]; uint16_t numBlocks = bufSize / CRYPTO_DES_BLOCK_SIZE; for (int blk = 0; blk < numBlocks; blk++) { memcpy(inputBlock, &plainSrcBuf[blk * CRYPTO_DES_BLOCK_SIZE], CRYPTO_DES_BLOCK_SIZE); @@ -242,7 +165,7 @@ static inline size_t Encrypt3DES(const uint8_t *plainSrcBuf, size_t bufSize, static inline size_t Decrypt3DES(const uint8_t *encSrcBuf, size_t bufSize, uint8_t *plainDestBuf, const uint8_t *IVIn, CryptoData_t cdata) { DES_key_schedule keySched1, keySched2, keySched3; - uint8_t IV[CRYPTO_DES_BLOCK_SIZE]; + uint8_t IV[CRYPTO_DES_BLOCK_SIZE], inputBlock[CRYPTO_DES_BLOCK_SIZE]; uint8_t *kd1 = cdata.keyData, *kd2 = &(cdata.keyData[CRYPTO_DES_BLOCK_SIZE]), *kd3 = &(cdata.keyData[2 * CRYPTO_DES_BLOCK_SIZE]); DES_set_key(kd1, &keySched1); DES_set_key(kd2, &keySched2); @@ -255,7 +178,6 @@ static inline size_t Decrypt3DES(const uint8_t *encSrcBuf, size_t bufSize, if (__CryptoDESOpMode == CRYPTO_DES_CBC_MODE) { DES_ede3_cbc_encrypt(encSrcBuf, plainDestBuf, bufSize, &keySched1, &keySched2, &keySched3, &IV, DES_DECRYPT); } else { - uint8_t inputBlock[CRYPTO_DES_BLOCK_SIZE]; uint16_t numBlocks = bufSize / CRYPTO_DES_BLOCK_SIZE; for (int blk = 0; blk < numBlocks; blk++) { DES_ecb3_encrypt(&encSrcBuf[blk * CRYPTO_DES_BLOCK_SIZE], diff --git a/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h b/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h index 1c32dbc7..6f5c6031 100644 --- a/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h +++ b/Software/DESFireLibNFCTesting/LocalInclude/DesfireUtils.h @@ -25,127 +25,6 @@ static inline void InvalidateAuthenticationStatus(void) { memset(ActiveCryptoIVBuffer, 0x00, CRYPTO_CHALLENGE_RESPONSE_SIZE); } -static inline int AuthenticateAES128(nfc_device *nfcConnDev, uint8_t keyIndex, const uint8_t *keyData) { - - if (nfcConnDev == NULL || keyData == NULL) { - InvalidateAuthenticationStatus(); - return INVALID_PARAMS_ERROR; - } else if (!AUTHENTICATED) { - InvalidateAuthenticationStatus(); - } - - // Start AES authentication (default key, blank setting of all zeros): - CryptoData_t aesCryptoData; - memset(&aesCryptoData, 0x00, sizeof(CryptoData_t)); - aesCryptoData.keySize = CRYPTO_AES128_KEY_SIZE; - aesCryptoData.keyData = keyData; - aesCryptoData.ivData = ActiveCryptoIVBuffer; - aesCryptoData.ivSize = CRYPTO_CHALLENGE_RESPONSE_SIZE; - - uint8_t AUTHENTICATE_AES_CMD[] = { - 0x90, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x00 - }; - AUTHENTICATE_AES_CMD[5] = keyIndex; - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, ">>> Start AES Authenticate:\n"); - fprintf(stdout, " -> "); - print_hex(AUTHENTICATE_AES_CMD, sizeof(AUTHENTICATE_AES_CMD)); - fprintf(stdout, " -- IV = "); - print_hex(aesCryptoData.ivData, AES128_BLOCK_SIZE); - } - RxData_t *rxDataStorage = InitRxDataStruct(MAX_FRAME_LENGTH); - bool rxDataStatus = false; - rxDataStatus = libnfcTransmitBytes(nfcConnDev, AUTHENTICATE_AES_CMD, sizeof(AUTHENTICATE_AES_CMD), rxDataStorage); - if (rxDataStatus && PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " <- "); - print_hex(rxDataStorage->rxDataBuf, rxDataStorage->recvSzRx); - } else { - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " -- !! Unable to transfer bytes !!\n"); - } - FreeRxDataStruct(rxDataStorage, true); - InvalidateAuthenticationStatus(); - return EXIT_FAILURE; - } - - // Now need to decrypt the challenge response sent back as rndB, - // rotate it left, generate a random rndA, concat rndA+rotatedRndB, - // encrypt this result, and send it forth to the PICC: - uint8_t encryptedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE], plainTextRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE], rotatedRndB[CRYPTO_CHALLENGE_RESPONSE_SIZE]; - uint8_t rndA[CRYPTO_CHALLENGE_RESPONSE_SIZE], challengeResponse[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE], challengeResponseCipherText[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE]; - memcpy(encryptedRndB, rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE); - DecryptAES128(encryptedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, plainTextRndB, aesCryptoData); - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " -- IV = "); - print_hex(aesCryptoData.ivData, AES128_BLOCK_SIZE); - } - RotateArrayRight(plainTextRndB, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE); - GenerateRandomBytes(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - ConcatByteArrays(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE, rotatedRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponse); - EncryptAES128(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE, challengeResponseCipherText, aesCryptoData); - uint16_t nonDataPaddingSize = 6; - uint8_t sendBytesBuf[2 * CRYPTO_CHALLENGE_RESPONSE_SIZE + nonDataPaddingSize]; - memset(sendBytesBuf, 0x00, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE + nonDataPaddingSize); - sendBytesBuf[0] = 0x90; - sendBytesBuf[1] = 0xaf; - sendBytesBuf[4] = 0x20; - memcpy(&sendBytesBuf[5], challengeResponseCipherText, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE); - - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " -- RNDA = "); - print_hex(rndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - fprintf(stdout, " -- RNDB = "); - print_hex(plainTextRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE); - fprintf(stdout, " -- CHAL = "); - print_hex(challengeResponse, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE); - fprintf(stdout, " -- ENC-CHAL = "); - print_hex(challengeResponseCipherText, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE); - fprintf(stdout, " -> "); - print_hex(sendBytesBuf, sizeof(sendBytesBuf)); - fprintf(stdout, " -- IV = "); - print_hex(aesCryptoData.ivData, AES128_BLOCK_SIZE); - } - rxDataStatus = libnfcTransmitBytes(nfcConnDev, sendBytesBuf, 2 * CRYPTO_CHALLENGE_RESPONSE_SIZE + nonDataPaddingSize, rxDataStorage); - if (rxDataStatus && PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " <- "); - print_hex(rxDataStorage->rxDataBuf, rxDataStorage->recvSzRx); - } else { - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " -- !! Unable to transfer bytes !!\n"); - } - FreeRxDataStruct(rxDataStorage, true); - InvalidateAuthenticationStatus(); - return EXIT_FAILURE; - } - - uint8_t decryptedRndAFromPICCRotated[CRYPTO_CHALLENGE_RESPONSE_SIZE], decryptedRndA[CRYPTO_CHALLENGE_RESPONSE_SIZE]; - DecryptAES128(rxDataStorage->rxDataBuf, CRYPTO_CHALLENGE_RESPONSE_SIZE, decryptedRndAFromPICCRotated, aesCryptoData); - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " -- IV = "); - print_hex(aesCryptoData.ivData, AES128_BLOCK_SIZE); - } - RotateArrayLeft(decryptedRndAFromPICCRotated, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - if (!memcmp(rndA, decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE)) { - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " ... AUTH OK! :)\n\n"); - } - AUTHENTICATED = true; - AUTHENTICATED_PROTO = DESFIRE_CRYPTO_AUTHTYPE_AES128; - memcpy(CRYPTO_RNDB_STATE, plainTextRndB, CRYPTO_CHALLENGE_RESPONSE_SIZE); - FreeRxDataStruct(rxDataStorage, true); - return EXIT_SUCCESS; - } else { - if (PRINT_STATUS_EXCHANGE_MESSAGES) { - fprintf(stdout, " ... AUTH FAILED -- X; :(\n"); - fprintf(stdout, " ... "); - print_hex(decryptedRndA, CRYPTO_CHALLENGE_RESPONSE_SIZE); - } - FreeRxDataStruct(rxDataStorage, true); - InvalidateAuthenticationStatus(); - return EXIT_FAILURE; - } -} - static inline int AuthenticateISO(nfc_device *nfcConnDev, uint8_t keyIndex, const uint8_t *keyData) { if (nfcConnDev == NULL || keyData == NULL) { @@ -405,12 +284,11 @@ static inline int Authenticate(nfc_device *nfcConnDev, int authType, uint8_t key return INVALID_PARAMS_ERROR; } switch (authType) { - case DESFIRE_CRYPTO_AUTHTYPE_AES128: - return AuthenticateAES128(nfcConnDev, keyIndex, keyData); case DESFIRE_CRYPTO_AUTHTYPE_ISODES: return AuthenticateISO(nfcConnDev, keyIndex, keyData); case DESFIRE_CRYPTO_AUTHTYPE_LEGACY: return AuthenticateLegacy(nfcConnDev, keyIndex, keyData); + case DESFIRE_CRYPTO_AUTHTYPE_AES128: default: break; } diff --git a/Software/DESFireLibNFCTesting/Makefile b/Software/DESFireLibNFCTesting/Makefile index e46b3f94..6c602492 100644 --- a/Software/DESFireLibNFCTesting/Makefile +++ b/Software/DESFireLibNFCTesting/Makefile @@ -52,7 +52,6 @@ UTILS_SOURCE=LocalInclude/Config.h \ FILE_BASENAMES=NFCAntiCollisionMod \ TestAuthenticateLegacy \ - TestAuthenticateAES128 \ TestAuthenticateISO \ TestGeneralCommands \ TestKeyManagementCommands \ diff --git a/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateAES128.dump b/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateAES128.dump deleted file mode 100644 index 36b9151e..00000000 --- a/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateAES128.dump +++ /dev/null @@ -1,26 +0,0 @@ ->>> TestAESEncryptionRoutines [non-DESFire command]: - -- : PT = 00 11 22 33 44 55 66 77 | 88 99 aa bb cc dd ee ff - -- : CT = c8 a3 31 ff 8e dd 3d b1 | 75 e1 54 5d be fb 76 0b - -- : CT = c8 a3 31 ff 8e dd 3d b1 | 75 e1 54 5d be fb 76 0b - -- : PT = 00 11 22 33 44 55 66 77 | 88 99 aa bb cc dd ee ff - -- CT matches. - -- Decrypted PT from CT matches. - ->>> Select Application By AID: - -> 90 5a 00 00 03 00 00 00 | 00 - <- 91 00 - ->>> GetApplicationIds command: - -> 90 6a 00 00 00 00 - <- 91 00 - ->>> Start AES Authenticate: - -> 90 aa 00 00 01 00 00 - <- 90 b0 af a1 81 cd 4d e0 | 71 08 87 98 13 76 79 a6 | 91 af - -- RNDA = 44 73 6e 84 3a 67 2a 0b - -- RNDB = 0f 8b 8c e2 ab a7 e1 db - -- CHAL = 44 73 6e 84 3a 67 2a 0b | db 0f 8b 8c e2 ab a7 e1 - -> 90 af 00 00 10 a2 b3 ac | ee db 24 1c 8f a1 c8 d1 | 3d c6 53 d3 4d 00 - <- 2c 0e 98 da 53 ab c4 74 | 38 d2 14 56 b3 d8 60 a0 | 91 00 - ... AUTH OK! :) - diff --git a/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateLegacy.dump b/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateLegacy.dump new file mode 100644 index 00000000..54405f2c --- /dev/null +++ b/Software/DESFireLibNFCTesting/SampleOutputDumps/TestAuthenticateLegacy.dump @@ -0,0 +1,23 @@ +>>> Select Application By AID: + -> 90 5a 00 00 03 00 00 00 | 00 + <- 91 00 + +>>> GetApplicationIds command: + -> 90 6a 00 00 00 00 + <- 91 00 + +>>> Start Legacy DES Authenticate: + -> 90 0a 00 00 01 00 00 + -- IV = 00 00 00 00 00 00 00 00 + <- ee 91 30 1e e8 f5 84 d6 | 91 af + -- IV = ee 91 30 1e e8 f5 84 d6 + -- RNDA = fa df a6 a3 18 78 ec f5 + -- RNDB = ca fe ba be 00 11 22 33 + -- CHAL = fa df a6 a3 18 78 ec f5 | fe ba be 00 11 22 33 ca + -- ENC-CHAL = db 12 5c 5a a6 56 a4 20 | af b0 0a 05 ac c2 ed 51 + -> 90 af 00 00 10 db 12 5c | 5a a6 56 a4 20 af b0 0a | 05 ac c2 ed 51 00 + -- IV = af b0 0a 05 ac c2 ed 51 + <- c1 ce 0a 26 d3 d1 4e d3 | 91 00 b0 0a + -- IV = c1 ce 0a 26 d3 d1 4e d3 + ... AUTH OK! :) + diff --git a/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c b/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c deleted file mode 100644 index 3b88a04b..00000000 --- a/Software/DESFireLibNFCTesting/Source/TestAuthenticateAES128.c +++ /dev/null @@ -1,39 +0,0 @@ -/* TestAuthenticateAES128.c */ - -#include "LibNFCUtils.h" -#include "LibNFCWrapper.h" -#include "DesfireUtils.h" -#include "CryptoUtils.h" - -/* - * See Notes: https://stackoverflow.com/questions/52520044/desfire-ev1-communication-how-to-assign-iv - */ - -int main(int argc, char **argv) { - - nfc_context *nfcCtxt; - nfc_device *nfcPnd = GetNFCDeviceDriver(&nfcCtxt); - if (nfcPnd == NULL) { - return EXIT_FAILURE; - } - - // Select AID application 0x000000: - if (SelectApplication(nfcPnd, MASTER_APPLICATION_AID, APPLICATION_AID_LENGTH)) { - return EXIT_FAILURE; - } - - // Get list of application IDs: - if (GetApplicationIds(nfcPnd)) { - return EXIT_FAILURE; - } - - // Start AES authentication (default key, blank setting of all zeros): - if (Authenticate(nfcPnd, DESFIRE_CRYPTO_AUTHTYPE_AES128, MASTER_KEY_INDEX, ZERO_KEY)) { - return EXIT_FAILURE; - } - - FreeNFCDeviceDriver(&nfcCtxt, &nfcPnd); - return EXIT_SUCCESS; - -} -