Research, development and trades concerning the powerful Proxmark3 device.
Remember; sharing is caring. Bring something back to the community.
"Learn the tools of the trade the hard way." +Fravia
You are not logged in.
Time changes and with it the technology
Proxmark3 @ discord
Users of this forum, please be aware that information stored on this site is not private.
Pages: 1
Hi,
I am currently trying to understand the multi sector authentication process. Therefore I tried to verify these traces given by roel. Everything works fine for the first authentication round and after the second authencation command and resetting the Crypto1 state, I am able to correctly decrypt the new Nt. But afterwards my encrypted reader answer [Nr + Nt'] differs from the trace.
Testing multi sector authentication!
UID: 9C599B32
Key: FFFFFFFFFFFF
First authentication:
Nt: 82A4166C
[Nr + Nt']: A1E458CE6EEA41E0
At: 9A427B20
command: 6000F57B
switching key
decrypted Nt: A55D950B
Nt': 1491FBDB
[Nr + Nt']: 00F539F4473612FD <- this result seems to be wrong
My current understanding is, that the nested authentication only differs in the first authentication step where Nt is send encrypted. I would highly appreciate any comments or hints!
#include "crapto1.h"
#include <stdio.h>
int main(void)
{
uint16_t i;
uint64_t key = 0xffffffffffffLLU;
uint8_t uid[] = {0x9c,0x59,0x9b,0x32};
uint8_t nt[] = {0x82,0xA4,0x16,0x6C};
uint8_t nr[] = {0xEF,0xEA,0x1C,0xDA};
uint8_t ar[8];
uint8_t at[] = {0x5c,0xad,0xf4,0x39};
printf("\nTesting multi sector authentication!\n\n");
printf("UID:\t\t");
for(i=0;i<4;i++)
printf("%02X",uid[i]);
printf("\n");
printf("Key:\t\t%llX\n\n",key);
printf("First authentication: \n\n");
uint32_t nt32 = 0;
for(i=0;i<4;i++)
nt32 = (nt32 << 8) | nt[i];
printf("Nt:\t\t%08X\n",nt32);
struct Crypto1State * state;
state = crypto1_create(key);
// feed in uid^nt and drop keystream in the first round
for(i=0;i<4;i++)
{
crypto1_byte(state,uid[i]^nt[i],0);
}
// encrypt reader nonce
for(i=0;i<4;i++)
{
ar[i] = crypto1_byte(state,nr[i],0) ^ nr[i];
}
// generate answer to tag nonce and encrypt it
nt32 = prng_successor(nt32,32);
for(i=4;i<8;i++)
{
nt32 = prng_successor(nt32,8);
ar[i] = crypto1_byte(state,0x00,0) ^ (nt32&0xff);
}
// output
printf("[Nr + Nt']:\t");
for(i=0;i<8;i++)
printf("%02X",ar[i]);
printf("\n");
// decrypt tag answer at
printf("At:\t\t");
for(i=0;i<4;i++)
printf("%02X",crypto1_byte(state,0x00,0)^at[i]);
printf("\n");
// encrypted 2nd authentication command
uint8_t command[] = {0x8e,0x0e,0x5d,0xb9};
// decrypt command
printf("command:\t");
for(i=0;i<4;i++)
printf("%02X",crypto1_byte(state,0x00,0)^command[i]);
printf("\n");
// interesting part begins here:
printf("switching key\n");
crypto1_destroy(state);
state = crypto1_create(key);
uint8_t nt_enc[] = {0x5a,0x92,0x0d,0x85};
// feed in uid^nt_enc and decrypt tagnonce
printf("decrypted Nt:\t");
// this time do not drop the first 32 keystream bits
// use them to decrypt [Nt]
for(i=0;i<4;i++)
{
printf("%02X",crypto1_byte(state,uid[i]^nt_enc[i],1)^nt_enc[i]);
}
printf("\n");
uint8_t nt_new[] = {0xA5,0x5D,0x95,0x0B};
uint8_t nr_new[] = {0xEF,0x60,0xE2,0x6F};
uint32_t nt32_new = 0;
for(i=0;i<4;i++)
nt32_new = (nt32_new << 8) | nt_new[i];
// From here on it seems to go wrong :(
// encrypt reader nonce
for(i=0;i<4;i++)
{
ar[i] = crypto1_byte(state,nr_new[i],0) ^ nr_new[i];
}
// generate answer to tag nonce and encrypt it
nt32_new = prng_successor(nt32_new,32);
printf("Nt':\t\t");
for(i=4;i<8;i++)
{
nt32_new = prng_successor(nt32_new,8);
printf("%02X",nt32_new&0xff);
ar[i] = crypto1_byte(state,0x00,0) ^ (nt32_new&0xff);
}
printf("\n");
// Output
printf("[Nr + Nt']:\t");
for(i=0;i<8;i++)
printf("%02X",ar[i]);
printf("\n");
return 0;
}
Offline
so after a little while i figured it out
roel's flaw in the trace: what he calls Nr is actually just the keystream that Nr is xorred against
and uhm your flaw is writing horrible code
here's a clean version of what goes on:
#include "crapto1.h"
#include <stdio.h>
int main()
{
struct Crypto1State * state;
//shared informationn
uint64_t key = 0xffffffffffffULL;
uint32_t uid = 0x9c599b32;
//information available to the tag
uint32_t nonce = 0xA55D950B;
uint32_t rn_enc = 0x98d76b77;
uint32_t rr_enc = 0xd6c6e870;
//information available to the reader
uint32_t nonce_enc = 0x5a920d85;
uint32_t rn = 0x77B78918;
uint32_t tr_enc = 0xca7e0b63;
//TAG
printf("from the TAG's point of view:\n");
state = crypto1_create(key);
printf("\tsending [tag nonce] : %08X\n", nonce ^ crypto1_word(state, uid ^ nonce, 0));
printf("\treceived reader nonce : %08X\n", rn_enc ^ crypto1_word(state, rn_enc , 1));
printf("\treceived reader reply : %08X\n", rr_enc ^ crypto1_word(state, 0, 0));
printf("\tsending [tag reply] : %08X\n", prng_successor(nonce, 96) ^ crypto1_word(state, 0, 0));
//READER
printf("\nfrom the READER's point of view:\n");
state = crypto1_create(key);
printf("\treceived tag nonce : %08X\n", nonce = (nonce_enc ^ crypto1_word(state, uid ^ nonce_enc, 1)));
printf("\tsending [reader nonce] : %08X\n", rn ^ crypto1_word(state, rn, 0));
printf("\tsending [reader reply] : %08X\n", prng_successor(nonce, 64) ^ crypto1_word(state, 0, 0));
printf("\treceived tag reply : %08X\n", tr_enc ^ crypto1_word(state, 0, 0));
return 0;
}
to get roel's output substitute in
printf("\treceived reader nonce : %08X\n", crypto1_word(state, rn_enc , 1));
cheers.
Offline
Thank you very much!
Offline
Pages: 1