security level logic

This commit is contained in:
merlokk 2021-05-29 22:37:32 +03:00
commit 9857094274
3 changed files with 38 additions and 2 deletions

View file

@ -13,6 +13,7 @@
#include "commonutil.h" // ARRAYLEN
#include "comms.h" // DropField
#include "util_posix.h" // msleep
#include <string.h> // 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 {

View file

@ -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));

View file

@ -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);