mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
authentication works
This commit is contained in:
parent
1a937b33c4
commit
1ba9606011
3 changed files with 21 additions and 35 deletions
|
@ -53,7 +53,7 @@ static void bin_pad2(uint8_t *dst, size_t dstlen, uint8_t *src, size_t srclen) {
|
||||||
|
|
||||||
static uint64_t rotateLeft48(uint64_t src) {
|
static uint64_t rotateLeft48(uint64_t src) {
|
||||||
uint64_t dst = src << 1;
|
uint64_t dst = src << 1;
|
||||||
if (dst && 0x0001000000000000UL != 0) {
|
if (dst & 0x0001000000000000UL) {
|
||||||
dst = dst | 1;
|
dst = dst | 1;
|
||||||
dst = dst & 0x0000ffffffffffffUL;
|
dst = dst & 0x0000ffffffffffffUL;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ static uint64_t computeNLM48(uint64_t x, uint64_t y) {
|
||||||
y = rotateLeft48(y);
|
y = rotateLeft48(y);
|
||||||
if (y & 1)
|
if (y & 1)
|
||||||
res = res ^ x;
|
res = res ^ x;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,30 +92,6 @@ static void computeNLM(uint8_t *res, uint8_t *x, uint8_t *y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CipurseCGenerateK0AndCp(CipurseContext *ctx) {
|
static void CipurseCGenerateK0AndCp(CipurseContext *ctx) {
|
||||||
/* // session key derivation function
|
|
||||||
// kP := NLM(EXT(kID), rP)
|
|
||||||
// k0 := AES(key=PAD2(kP) XOR PAD(rT),kID) XOR kID
|
|
||||||
var temp1 = CryptoUtils.extFunction(kid, CIPURSE_SECURITY_PARAM_N) ?: return null
|
|
||||||
val kp = CryptoUtils.computeNLM(rP, temp1) ?: return null
|
|
||||||
temp1 = CryptoUtils.pad2(kp) ?: return null
|
|
||||||
val temp2 = CryptoUtils.pad(rT) ?: return null
|
|
||||||
temp1 = temp1 xor temp2
|
|
||||||
|
|
||||||
// session key K0
|
|
||||||
k0 = AesECB.aesEncrypt(temp1, kid) ?: return null
|
|
||||||
k0 = k0 xor kid
|
|
||||||
|
|
||||||
// first frame key k1, function to calculate k1,
|
|
||||||
// k1 := AES(key = RP; k0 XOR RT) XOR (k0 XOR RT)
|
|
||||||
temp1 = k0 xor RT
|
|
||||||
val temp3: ByteArray = AesECB.aesEncrypt(RP, temp1) ?: return null
|
|
||||||
frameKeyi = temp3 xor temp1
|
|
||||||
Log.d(TAG, "frame key=${Utils.toHex(frameKeyi)}")
|
|
||||||
|
|
||||||
// function to caluclate cP := AES(key=k0, RP).
|
|
||||||
// terminal response
|
|
||||||
return AesECB.aesEncrypt(k0, RP)*/
|
|
||||||
|
|
||||||
uint8_t temp1[CIPURSE_AES_KEY_LENGTH] = {0};
|
uint8_t temp1[CIPURSE_AES_KEY_LENGTH] = {0};
|
||||||
uint8_t temp2[CIPURSE_AES_KEY_LENGTH] = {0};
|
uint8_t temp2[CIPURSE_AES_KEY_LENGTH] = {0};
|
||||||
uint8_t kp[CIPURSE_SECURITY_PARAM_N] = {0};
|
uint8_t kp[CIPURSE_SECURITY_PARAM_N] = {0};
|
||||||
|
@ -204,3 +180,7 @@ void CipurseCAuthenticateHost(CipurseContext *ctx, uint8_t *authdata) {
|
||||||
if (authdata != NULL)
|
if (authdata != NULL)
|
||||||
CipurseCFillAuthData(ctx, authdata);
|
CipurseCFillAuthData(ctx, authdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT) {
|
||||||
|
return (memcmp(CT, ctx->CT, CIPURSE_AES_KEY_LENGTH) == 0);
|
||||||
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ void CipurseCSetRandomFromPICC(CipurseContext *ctx, uint8_t *random);
|
||||||
void CipurseCSetRandomHost(CipurseContext *ctx);
|
void CipurseCSetRandomHost(CipurseContext *ctx);
|
||||||
|
|
||||||
void CipurseCAuthenticateHost(CipurseContext *ctx, uint8_t *authdata);
|
void CipurseCAuthenticateHost(CipurseContext *ctx, uint8_t *authdata);
|
||||||
|
bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT);
|
||||||
|
|
||||||
|
|
||||||
void CipurseCGetKVV(uint8_t *key, uint8_t *kvv);
|
void CipurseCGetKVV(uint8_t *key, uint8_t *kvv);
|
||||||
|
|
|
@ -130,12 +130,12 @@ static int CmdHFCipurseAuth(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CipurseContext cpc = {0};
|
CipurseContext cpc = {0};
|
||||||
CipurseCSetKey(&cpc, 1, key);
|
CipurseCSetKey(&cpc, keyId, key);
|
||||||
|
|
||||||
uint8_t kvv[CIPURSE_KVV_LENGTH] = {0};
|
uint8_t kvv[CIPURSE_KVV_LENGTH] = {0};
|
||||||
CipurseCGetKVV(key, kvv);
|
CipurseCGetKVV(key, kvv);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
PrintAndLogEx(INFO, "Key: %s KVV: %s", sprint_hex(key, CIPURSE_AES_KEY_LENGTH), sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH));
|
PrintAndLogEx(INFO, "Key id: %d key: %s KVV: %s", keyId, sprint_hex(key, CIPURSE_AES_KEY_LENGTH), sprint_hex_inrow(kvv, CIPURSE_KVV_LENGTH));
|
||||||
|
|
||||||
// get RP, rP
|
// get RP, rP
|
||||||
res = CIPURSEChallenge(buf, sizeof(buf), &len, &sw);
|
res = CIPURSEChallenge(buf, sizeof(buf), &len, &sw);
|
||||||
|
@ -152,17 +152,22 @@ static int CmdHFCipurseAuth(const char *Cmd) {
|
||||||
|
|
||||||
// authenticate
|
// authenticate
|
||||||
res = CIPURSEMutalAuthenticate(keyId, authparams, sizeof(authparams), buf, sizeof(buf), &len, &sw);
|
res = CIPURSEMutalAuthenticate(keyId, authparams, sizeof(authparams), buf, sizeof(buf), &len, &sw);
|
||||||
if (res != 0 || sw != 0x9000 || len != 0x16) {
|
if (res != 0 || sw != 0x9000 || len != 16) {
|
||||||
if (sw == 0x6988)
|
if (sw == 0x6988)
|
||||||
PrintAndLogEx(ERR, "Cipurse authentication error. Wrong key.");
|
PrintAndLogEx(ERR, "Cipurse authentication " _RED_("error") ". Wrong key.");
|
||||||
else if ((sw == 0x6A88))
|
else if ((sw == 0x6A88))
|
||||||
PrintAndLogEx(ERR, "Cipurse authentication error. Wrong key number.");
|
PrintAndLogEx(ERR, "Cipurse authentication " _RED_("error") ". Wrong key number.");
|
||||||
else PrintAndLogEx(ERR, "Cipurse authentication error. Card returns 0x%04x.", sw);
|
else PrintAndLogEx(ERR, "Cipurse authentication " _RED_("error") ". Card returns 0x%04x.", sw);
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CipurseCCheckCT(&cpc, buf))
|
||||||
|
PrintAndLogEx(INFO, "Authentication " _GREEN_("OK"));
|
||||||
|
else
|
||||||
|
PrintAndLogEx(ERR, "Authentication " _RED_("ERROR") " card returned wrong CT");
|
||||||
|
|
||||||
DropField();
|
DropField();
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue