diff --git a/client/src/cipurse/cipursecore.c b/client/src/cipurse/cipursecore.c index 54f90bd52..3b905214f 100644 --- a/client/src/cipurse/cipursecore.c +++ b/client/src/cipurse/cipursecore.c @@ -13,6 +13,7 @@ #include "commonutil.h" // ARRAYLEN #include "comms.h" // DropField #include "util_posix.h" // msleep +#include // memcpy memset #include "cmdhf14a.h" #include "emv/emvcore.h" @@ -36,6 +37,10 @@ static int CIPURSEExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, DropField(); msleep(50); } + + // long messages is not allowed + if (apdu.Lc > 228) + return 20; // COMPUTE APDU int datalen = 0; @@ -144,6 +149,7 @@ bool CIPURSEChannelAuthenticate(uint8_t keyIndex, uint8_t *key, bool verbose) { if (verbose) PrintAndLogEx(INFO, "Authentication " _GREEN_("OK")); + CipurseCChannelSetSecurityLevels(&cpc, CPSMACed, CPSMACed); memcpy(&cipurseContext, &cpc, sizeof(CipurseContext)); return true; } else { diff --git a/client/src/cipurse/cipursecrypto.c b/client/src/cipurse/cipursecrypto.c index d18907247..71b076515 100644 --- a/client/src/cipurse/cipursecrypto.c +++ b/client/src/cipurse/cipursecrypto.c @@ -25,6 +25,16 @@ uint8_t AESData0[CIPURSE_AES_KEY_LENGTH] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t QConstant[CIPURSE_AES_KEY_LENGTH] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73}; +uint8_t CipurseCSecurityLevelEnc(CipurseChannelSecurityLevel lvl) { + switch (lvl) { + case CPSNone: return 0x00; + case CPSPlain: return 0x00; + case CPSMACed: return 0x01; + case CPSEncrypted: return 0x02; + default: return 0x00; + } +} + static void bin_xor(uint8_t *d1, uint8_t *d2, size_t len) { for(size_t i = 0; i < len; i++) d1[i] = d1[i] ^ d2[i]; @@ -152,6 +162,11 @@ void CipurseCSetKey(CipurseContext *ctx, uint8_t keyId, uint8_t *key) { memcpy(ctx->key, key, member_size(CipurseContext, key)); } +void CipurseCChannelSetSecurityLevels(CipurseContext *ctx, CipurseChannelSecurityLevel req, CipurseChannelSecurityLevel resp) { + ctx->RequestSecurity = req; + ctx->ResponseSecurity = resp; +} + void CipurseCSetRandomFromPICC(CipurseContext *ctx, uint8_t *random) { if (ctx == NULL) return; @@ -165,6 +180,13 @@ void CipurseCSetRandomHost(CipurseContext *ctx) { memset(ctx->rT, 0x20, member_size(CipurseContext, rT)); } +uint8_t CipurseCGetSMI(CipurseContext *ctx, bool LePresent) { + uint8_t res = LePresent ? 1 : 0; + res = res | (CipurseCSecurityLevelEnc(ctx->RequestSecurity) << 2); + res = res | (CipurseCSecurityLevelEnc(ctx->ResponseSecurity) << 6); + return res; +} + static void CipurseCFillAuthData(CipurseContext *ctx, uint8_t *authdata) { memcpy(authdata, ctx->cP, member_size(CipurseContext, cP)); memcpy(&authdata[member_size(CipurseContext, cP)], ctx->RT, member_size(CipurseContext, RT)); diff --git a/client/src/cipurse/cipursecrypto.h b/client/src/cipurse/cipursecrypto.h index 0ceafc5ff..d98f3e4fe 100644 --- a/client/src/cipurse/cipursecrypto.h +++ b/client/src/cipurse/cipursecrypto.h @@ -22,12 +22,12 @@ #define member_size(type, member) sizeof(((type *)0)->member) -enum CipurseChannelSecurityLevel { +typedef enum { CPSNone, CPSPlain, CPSMACed, CPSEncrypted -}; +} CipurseChannelSecurityLevel; typedef struct CipurseContextS { uint8_t keyId; @@ -44,16 +44,24 @@ typedef struct CipurseContextS { uint8_t frameKey[CIPURSE_AES_KEY_LENGTH]; uint8_t frameKeyNext[CIPURSE_AES_KEY_LENGTH]; + + CipurseChannelSecurityLevel RequestSecurity; + CipurseChannelSecurityLevel ResponseSecurity; } CipurseContext; +uint8_t CipurseCSecurityLevelEnc(CipurseChannelSecurityLevel lvl); + void CipurseCClearContext(CipurseContext *ctx); void CipurseCSetKey(CipurseContext *ctx, uint8_t keyId, uint8_t *key); void CipurseCSetRandomFromPICC(CipurseContext *ctx, uint8_t *random); void CipurseCSetRandomHost(CipurseContext *ctx); +uint8_t CipurseCGetSMI(CipurseContext *ctx, bool LePresent); void CipurseCAuthenticateHost(CipurseContext *ctx, uint8_t *authdata); bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT); +void CipurseCChannelSetSecurityLevels(CipurseContext *ctx, CipurseChannelSecurityLevel req, CipurseChannelSecurityLevel resp); + void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen); size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen);