mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-04-09 14:00:05 +08:00
update crypto encode/decode
This commit is contained in:
parent
c22050b638
commit
5f0f6b8032
4 changed files with 161 additions and 45 deletions
client/src/mifare
|
@ -25,10 +25,9 @@
|
||||||
#include "mifare.h" // structs
|
#include "mifare.h" // structs
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
#include "crypto/libpcrypto.h"
|
#include "crypto/libpcrypto.h"
|
||||||
|
#include "mifare/desfirecrypto.h"
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CRYPTO_BLOCK_SIZE 16
|
|
||||||
#define DESFIRE_MAX_KEY_SIZE 24
|
|
||||||
/* Mifare DESFire EV1 Application crypto operations */
|
/* Mifare DESFire EV1 Application crypto operations */
|
||||||
#define APPLICATION_CRYPTO_DES 0x00
|
#define APPLICATION_CRYPTO_DES 0x00
|
||||||
#define APPLICATION_CRYPTO_3K3DES 0x40
|
#define APPLICATION_CRYPTO_3K3DES 0x40
|
||||||
|
@ -75,13 +74,6 @@ typedef enum {
|
||||||
/* Error code managed by the library */
|
/* Error code managed by the library */
|
||||||
#define CRYPTO_ERROR 0x01
|
#define CRYPTO_ERROR 0x01
|
||||||
|
|
||||||
enum DESFIRE_CRYPTOALGO {
|
|
||||||
T_DES = 0x00,
|
|
||||||
T_3DES = 0x01, //aka 2K3DES
|
|
||||||
T_3K3DES = 0x02,
|
|
||||||
T_AES = 0x03
|
|
||||||
};
|
|
||||||
|
|
||||||
int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type);
|
int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type);
|
||||||
size_t desfire_get_key_block_length(enum DESFIRE_CRYPTOALGO key_type);
|
size_t desfire_get_key_block_length(enum DESFIRE_CRYPTOALGO key_type);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
#include "aes.h"
|
||||||
|
#include "des.h"
|
||||||
#include "crc.h"
|
#include "crc.h"
|
||||||
#include "crc16.h" // crc16 ccitt
|
#include "crc16.h" // crc16 ccitt
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
|
@ -85,39 +87,152 @@ bool DesfireIsAuthenticated(DesfireContext *dctx) {
|
||||||
return dctx->secureChannel != DACNone;
|
return dctx->secureChannel != DACNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) {
|
static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) {
|
||||||
uint8_t data[1024] = {0};
|
size_t block_size = desfire_get_key_block_length(keyType);
|
||||||
|
uint8_t sdata[MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
memcpy(sdata, data, block_size);
|
||||||
|
if (dir_to_send) {
|
||||||
|
bin_xor(sdata, ivect, block_size);
|
||||||
|
}
|
||||||
|
|
||||||
switch (ctx->keyType) {
|
uint8_t edata[MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
|
switch (keyType) {
|
||||||
case T_DES:
|
case T_DES:
|
||||||
if (ctx->secureChannel == DACd40) {
|
|
||||||
if (encode)
|
if (encode)
|
||||||
des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key);
|
des_encrypt(edata, sdata, key);
|
||||||
else
|
else
|
||||||
des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key);
|
des_decrypt(edata, sdata, key);
|
||||||
}
|
|
||||||
if (ctx->secureChannel == DACEV1) {
|
|
||||||
if (encode)
|
|
||||||
des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV);
|
|
||||||
else
|
|
||||||
des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dstdata)
|
|
||||||
memcpy(dstdata, data, srcdatalen);
|
|
||||||
break;
|
break;
|
||||||
case T_3DES:
|
case T_3DES:
|
||||||
|
if (encode) {
|
||||||
|
mbedtls_des3_context ctx3;
|
||||||
|
mbedtls_des3_set2key_enc(&ctx3, key);
|
||||||
|
mbedtls_des3_crypt_ecb(&ctx3, sdata, edata);
|
||||||
|
} else {
|
||||||
|
mbedtls_des3_context ctx3;
|
||||||
|
mbedtls_des3_set2key_dec(&ctx3, key);
|
||||||
|
mbedtls_des3_crypt_ecb(&ctx3, sdata, edata);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case T_3K3DES:
|
case T_3K3DES:
|
||||||
|
if (encode) {
|
||||||
|
mbedtls_des3_context ctx3;
|
||||||
|
mbedtls_des3_set3key_enc(&ctx3, key);
|
||||||
|
mbedtls_des3_crypt_ecb(&ctx3, sdata, edata);
|
||||||
|
} else {
|
||||||
|
mbedtls_des3_context ctx3;
|
||||||
|
mbedtls_des3_set3key_dec(&ctx3, key);
|
||||||
|
mbedtls_des3_crypt_ecb(&ctx3, sdata, edata);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case T_AES:
|
case T_AES:
|
||||||
if (encode)
|
if (encode) {
|
||||||
aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen);
|
mbedtls_aes_context actx;
|
||||||
else
|
mbedtls_aes_init(&actx);
|
||||||
aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen);
|
mbedtls_aes_setkey_enc(&actx, key, 128);
|
||||||
if (dstdata)
|
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, sdata, edata);
|
||||||
memcpy(dstdata, data, srcdatalen);
|
mbedtls_aes_free(&actx);
|
||||||
|
} else {
|
||||||
|
mbedtls_aes_context actx;
|
||||||
|
mbedtls_aes_init(&actx);
|
||||||
|
mbedtls_aes_setkey_dec(&actx, key, 128);
|
||||||
|
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, sdata, edata);
|
||||||
|
mbedtls_aes_free(&actx);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(dstdata, edata, block_size);
|
||||||
|
|
||||||
|
if (dir_to_send) {
|
||||||
|
memcpy(ivect, sdata, block_size);
|
||||||
|
} else {
|
||||||
|
memcpy(ivect, data, block_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) {
|
||||||
|
uint8_t data[1024] = {0};
|
||||||
|
|
||||||
|
if (ctx->secureChannel == DACd40)
|
||||||
|
memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE);
|
||||||
|
|
||||||
|
size_t block_size = desfire_get_key_block_length(ctx->keyType);
|
||||||
|
size_t offset = 0;
|
||||||
|
while (offset < srcdatalen) {
|
||||||
|
//mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size);
|
||||||
|
if (use_session_key)
|
||||||
|
DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode);
|
||||||
|
else
|
||||||
|
DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode);
|
||||||
|
offset += block_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstdata)
|
||||||
|
memcpy(dstdata, data, srcdatalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) {
|
||||||
|
int kbs = desfire_get_key_block_length(ctx->keyType);
|
||||||
|
const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
|
||||||
|
|
||||||
|
uint8_t l[kbs];
|
||||||
|
memset(l, 0, kbs);
|
||||||
|
|
||||||
|
uint8_t ivect[kbs];
|
||||||
|
memset(ivect, 0, kbs);
|
||||||
|
|
||||||
|
//mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER);
|
||||||
|
DesfireCryptoEncDec(ctx, true, l, kbs, NULL, true);
|
||||||
|
|
||||||
|
bool txor = false;
|
||||||
|
|
||||||
|
// Used to compute CMAC on complete blocks
|
||||||
|
memcpy(sk1, l, kbs);
|
||||||
|
txor = l[0] & 0x80;
|
||||||
|
lsl(sk1, kbs);
|
||||||
|
if (txor) {
|
||||||
|
sk1[kbs - 1] ^= R;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to compute CMAC on the last block if non-complete
|
||||||
|
memcpy(sk2, sk1, kbs);
|
||||||
|
txor = sk1[0] & 0x80;
|
||||||
|
lsl(sk2, kbs);
|
||||||
|
if (txor) {
|
||||||
|
sk2[kbs - 1] ^= R;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t *cmac) {
|
||||||
|
int kbs = desfire_get_key_block_length(ctx->keyType);
|
||||||
|
if (kbs == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t buffer[kbs];
|
||||||
|
memset(buffer, 0, kbs);
|
||||||
|
|
||||||
|
uint8_t sk1[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
uint8_t sk2[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
DesfireCMACGenerateSubkeys(ctx, sk1, sk2);
|
||||||
|
|
||||||
|
memcpy(buffer, data, len);
|
||||||
|
|
||||||
|
if ((!len) || (len % kbs)) {
|
||||||
|
buffer[len++] = 0x80;
|
||||||
|
while (len % kbs) {
|
||||||
|
buffer[len++] = 0x00;
|
||||||
|
}
|
||||||
|
bin_xor(buffer + len - kbs, sk2, kbs);
|
||||||
|
} else {
|
||||||
|
bin_xor(buffer + len - kbs, sk1, kbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
//mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
|
||||||
|
DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true);
|
||||||
|
|
||||||
|
memcpy(cmac, ctx->IV, kbs);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,21 @@
|
||||||
#define __DESFIRECRYPTO_H
|
#define __DESFIRECRYPTO_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "mifare/desfire_crypto.h"
|
|
||||||
#include "mifare/mifare4.h"
|
#include "mifare/mifare4.h"
|
||||||
|
|
||||||
#define DESF_MAX_KEY_LEN 24
|
#define MAX_CRYPTO_BLOCK_SIZE 16
|
||||||
|
#define DESFIRE_MAX_CRYPTO_BLOCK_SIZE 16
|
||||||
|
#define DESFIRE_MAX_KEY_SIZE 24
|
||||||
|
|
||||||
#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x )
|
#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x )
|
||||||
|
|
||||||
|
enum DESFIRE_CRYPTOALGO {
|
||||||
|
T_DES = 0x00,
|
||||||
|
T_3DES = 0x01, //aka 2K3DES
|
||||||
|
T_3K3DES = 0x02,
|
||||||
|
T_AES = 0x03
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm;
|
typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -54,8 +62,8 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct DesfireContextS {
|
typedef struct DesfireContextS {
|
||||||
uint8_t keyNum;
|
uint8_t keyNum;
|
||||||
enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes
|
DesfireCryptoAlgorythm keyType; // des/2tdea/3tdea/aes
|
||||||
uint8_t key[DESF_MAX_KEY_LEN];
|
uint8_t key[DESFIRE_MAX_KEY_SIZE];
|
||||||
|
|
||||||
// KDF finction
|
// KDF finction
|
||||||
uint8_t kdfAlgo;
|
uint8_t kdfAlgo;
|
||||||
|
@ -66,10 +74,10 @@ typedef struct DesfireContextS {
|
||||||
DesfireCommandSet cmdSet; // native/nativeiso/iso
|
DesfireCommandSet cmdSet; // native/nativeiso/iso
|
||||||
DesfireCommunicationMode commMode; // plain/mac/enc
|
DesfireCommunicationMode commMode; // plain/mac/enc
|
||||||
|
|
||||||
uint8_t IV[DESF_MAX_KEY_LEN];
|
uint8_t IV[DESFIRE_MAX_KEY_SIZE];
|
||||||
uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN];
|
uint8_t sessionKeyMAC[DESFIRE_MAX_KEY_SIZE];
|
||||||
uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t
|
uint8_t sessionKeyEnc[DESFIRE_MAX_KEY_SIZE]; // look at mifare4.h - mf4Session_t
|
||||||
uint8_t lastIV[DESF_MAX_KEY_LEN];
|
uint8_t lastIV[DESFIRE_MAX_KEY_SIZE];
|
||||||
//mf4Session_t AESSession;
|
//mf4Session_t AESSession;
|
||||||
uint16_t cntrTx; // for AES
|
uint16_t cntrTx; // for AES
|
||||||
uint16_t cntrRx; // for AES
|
uint16_t cntrRx; // for AES
|
||||||
|
@ -85,7 +93,8 @@ void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint
|
||||||
bool DesfireIsAuthenticated(DesfireContext *dctx);
|
bool DesfireIsAuthenticated(DesfireContext *dctx);
|
||||||
|
|
||||||
|
|
||||||
void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode);
|
void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode);
|
||||||
|
void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac);
|
||||||
|
|
||||||
|
|
||||||
#endif // __DESFIRECRYPTO_H
|
#endif // __DESFIRECRYPTO_H
|
||||||
|
|
|
@ -40,7 +40,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
|
|
||||||
rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType));
|
rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType));
|
||||||
memcpy(data, srcdata, srcdatalen);
|
memcpy(data, srcdata, srcdatalen);
|
||||||
DesfireCryptoEncDec(ctx, data, rlen, NULL, true);
|
DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true);
|
||||||
memcpy(dstdata, srcdata, srcdatalen);
|
memcpy(dstdata, srcdata, srcdatalen);
|
||||||
memcpy(&dstdata[srcdatalen], ctx->IV, 4);
|
memcpy(&dstdata[srcdatalen], ctx->IV, 4);
|
||||||
*dstdatalen = rlen;
|
*dstdatalen = rlen;
|
||||||
|
@ -49,7 +49,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16
|
rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16
|
||||||
memcpy(data, srcdata, srcdatalen);
|
memcpy(data, srcdata, srcdatalen);
|
||||||
compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]);
|
compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]);
|
||||||
DesfireCryptoEncDec(ctx, data, rlen, dstdata, true);
|
DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true);
|
||||||
*dstdatalen = rlen;
|
*dstdatalen = rlen;
|
||||||
break;
|
break;
|
||||||
case DCMNone:
|
case DCMNone:
|
||||||
|
@ -70,7 +70,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint
|
||||||
data[0] = cmd;
|
data[0] = cmd;
|
||||||
rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType));
|
rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType));
|
||||||
memcpy(&data[1], srcdata, srcdatalen);
|
memcpy(&data[1], srcdata, srcdatalen);
|
||||||
DesfireCryptoEncDec(ctx, data, rlen, NULL, true);
|
DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true);
|
||||||
|
|
||||||
memcpy(dstdata, srcdata, srcdatalen);
|
memcpy(dstdata, srcdata, srcdatalen);
|
||||||
if (srcdatalen != 0 && ctx->commMode == DCMMACed) {
|
if (srcdatalen != 0 && ctx->commMode == DCMMACed) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue