]>
cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdanalyse.c 
   1  //-----------------------------------------------------------------------------    2  // Copyright (C) 2016 iceman    4  // This code is licensed to you under the terms of the GNU GPL, version 2 or,    5  // at your option, any later version. See the LICENSE.txt file for the text of    7  //-----------------------------------------------------------------------------    8  // Analyse bytes commands    9  //-----------------------------------------------------------------------------   10  #include  "cmdanalyse.h"   11  #include  "nonce2key/nonce2key.h"   13  static int  CmdHelp ( const char  * Cmd
);   15  int  usage_analyse_lcr ( void ) {   16          PrintAndLog ( "Specifying the bytes of a UID with a known LRC will find the last byte value" );   17          PrintAndLog ( "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX." );   19          PrintAndLog ( "Usage:  analyse lcr [h] <bytes>" );   20          PrintAndLog ( "Options:" );   21          PrintAndLog ( "           h          This help" );   22          PrintAndLog ( "           <bytes>    bytes to calc missing XOR in a LCR" );   24          PrintAndLog ( "Samples:" );   25          PrintAndLog ( "      analyse lcr 04008064BA" );   26          PrintAndLog ( "expected output: Target (BA) requires final LRC XOR byte value: 5A" );   29  int  usage_analyse_checksum ( void ) {   30          PrintAndLog ( "The bytes will be added with eachother and than limited with the applied mask" );   31          PrintAndLog ( "Finally compute ones' complement of the least significant bytes" );   33          PrintAndLog ( "Usage:  analyse chksum [h] [v] b <bytes> m <mask>" );   34          PrintAndLog ( "Options:" );   35          PrintAndLog ( "           h          This help" );   36          PrintAndLog ( "           v          supress header" );   37          PrintAndLog ( "           b <bytes>  bytes to calc missing XOR in a LCR" );   38          PrintAndLog ( "           m <mask>   bit mask to limit the outpuyt" );   40          PrintAndLog ( "Samples:" );   41          PrintAndLog ( "      analyse chksum b 137AF00A0A0D m FF" );   42          PrintAndLog ( "expected output: 0x61" );   45  int  usage_analyse_crc ( void ){   46          PrintAndLog ( "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output" );   48          PrintAndLog ( "Usage:  analyse crc [h] <bytes>" );   49          PrintAndLog ( "Options:" );   50          PrintAndLog ( "           h          This help" );   51          PrintAndLog ( "           <bytes>    bytes to calc crc" );   53          PrintAndLog ( "Samples:" );   54          PrintAndLog ( "      analyse crc 137AF00A0A0D" );   57  int  usage_analyse_hid ( void ){   58          PrintAndLog ( "Permute function from 'heart of darkness' paper." );   60          PrintAndLog ( "Usage:  analyse hid [h] <r|f> <bytes>" );   61          PrintAndLog ( "Options:" );   62          PrintAndLog ( "           h          This help" );   63          PrintAndLog ( "           r          reverse permuted key" );   64          PrintAndLog ( "           f          permute key" );   65          PrintAndLog ( "           <bytes>    input bytes" );   67          PrintAndLog ( "Samples:" );   68          PrintAndLog ( "      analyse hid r 0123456789abcdef" );   71  int  usage_analyse_nuid ( void ){   72          PrintAndLog ( "Generate 4byte NUID from 7byte UID" );   74          PrintAndLog ( "Usage:  analyse hid [h] <bytes>" );   75          PrintAndLog ( "Options:" );   76          PrintAndLog ( "           h          This help" );   77          PrintAndLog ( "           <bytes>  input bytes (14 hexsymbols)" );   79          PrintAndLog ( "Samples:" );   80          PrintAndLog ( "      analyse nuid 11223344556677" );   84  static uint8_t  calculateLRC (  uint8_t *  bytes
,  uint8_t  len
) {   86      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++)   91  static uint16_t  calcSumCrumbAdd (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {   93      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++) {   94          sum 
+=  CRUMB ( bytes
[ i
],  0 );   95                  sum 
+=  CRUMB ( bytes
[ i
],  2 );   96                  sum 
+=  CRUMB ( bytes
[ i
],  4 );   97                  sum 
+=  CRUMB ( bytes
[ i
],  6 );  102  static uint16_t  calcSumCrumbAddOnes (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  103          return  (~ calcSumCrumbAdd ( bytes
,  len
,  mask
) &  mask
);  105  static uint16_t  calcSumNibbleAdd (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  107      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++) {  108          sum 
+=  NIBBLE_LOW ( bytes
[ i
]);  109                  sum 
+=  NIBBLE_HIGH ( bytes
[ i
]);  114  static uint16_t  calcSumNibbleAddOnes (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
){  115          return  (~ calcSumNibbleAdd ( bytes
,  len
,  mask
) &  mask
);  117  static uint16_t  calcSumCrumbXor (   uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  119      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++) {  120          sum 
^=  CRUMB ( bytes
[ i
],  0 );  121                  sum 
^=  CRUMB ( bytes
[ i
],  2 );  122                  sum 
^=  CRUMB ( bytes
[ i
],  4 );  123                  sum 
^=  CRUMB ( bytes
[ i
],  6 );  128  static uint16_t  calcSumNibbleXor (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  130      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++) {  131          sum 
^=  NIBBLE_LOW ( bytes
[ i
]);  132                  sum 
^=  NIBBLE_HIGH ( bytes
[ i
]);  137  static uint16_t  calcSumByteXor (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  139      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++)  144  static uint16_t  calcSumByteAdd (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  146      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++)  152  static uint16_t  calcSumByteAddOnes (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  153          return  (~ calcSumByteAdd ( bytes
,  len
,  mask
) &  mask
);  156  static uint16_t  calcSumByteSub (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  158      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++)  163  static uint16_t  calcSumByteSubOnes (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
){  164          return  (~ calcSumByteSub ( bytes
,  len
,  mask
) &  mask
);  166  static uint16_t  calcSumNibbleSub (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  168      for  ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++) {  169          sum 
-=  NIBBLE_LOW ( bytes
[ i
]);  170                  sum 
-=  NIBBLE_HIGH ( bytes
[ i
]);  175  static uint16_t  calcSumNibbleSubOnes (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
) {  176          return  (~ calcSumNibbleSub ( bytes
,  len
,  mask
) &  mask
);  179  // BSD shift checksum 8bit version  180  static uint16_t  calcBSDchecksum8 (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
){  182          for ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++){  183                  sum 
= (( sum 
&  0xFF ) >>  1 ) | (( sum 
&  0x1 ) <<  7 );    // rotate accumulator  184                  sum 
+=  bytes
[ i
];   // add next byte  190  // BSD shift checksum 4bit version  191  static uint16_t  calcBSDchecksum4 (  uint8_t *  bytes
,  uint8_t  len
,  uint32_t  mask
){  193          for ( uint8_t  i 
=  0 ;  i 
<  len
;  i
++){  194                  sum 
= (( sum 
&  0xF ) >>  1 ) | (( sum 
&  0x1 ) <<  3 );    // rotate accumulator  195                  sum 
+=  NIBBLE_HIGH ( bytes
[ i
]);   // add high nibble  197                  sum 
= (( sum 
&  0xF ) >>  1 ) | (( sum 
&  0x1 ) <<  3 );    // rotate accumulator  198                  sum 
+=  NIBBLE_LOW ( bytes
[ i
]);   // add low nibble  205  // measuring LFSR maximum length  206  int  CmdAnalyseLfsr ( const char  * Cmd
){  208      uint16_t  start_state 
=  0 ;   /* Any nonzero start state will work. */  209      uint16_t  lfsr 
=  start_state
;  210      //uint32_t period = 0;  212          uint8_t  iv 
=  param_get8ex ( Cmd
,  0 ,  0 ,  16 );  213          uint8_t  find 
=  param_get8ex ( Cmd
,  1 ,  0 ,  16 );  215          printf ( "LEGIC LFSR IV 0x %0 2X:  \n " ,  iv
);  216          printf ( " bit# | lfsr | ^0x40 |  0x %0 2X ^ lfsr  \n " , find
);  218          for  ( uint8_t  i 
=  0x01 ;  i 
<  0x30 ;  i 
+=  1 ) {  221                  legic_prng_forward ( i
);  222                  lfsr 
=  legic_prng_get_bits ( 12 );  224                  printf ( "  %0 2X |  %0 3X |  %0 3X |  %0 3X  \n " , i
,  lfsr
,  0x40  ^  lfsr
,  find 
^  lfsr
);  228  int  CmdAnalyseLCR ( const char  * Cmd
) {  230          char  cmdp 
=  param_getchar ( Cmd
,  0 );  231          if  ( strlen ( Cmd
) ==  0 ||  cmdp 
==  'h'  ||  cmdp 
==  'H' )  return  usage_analyse_lcr ();  234          param_gethex_ex ( Cmd
,  0 ,  data
, & len
);  235          if  (  len%2 
)  return  usage_analyse_lcr ();  237          uint8_t  finalXor 
=  calculateLRC ( data
,  len
);  238          PrintAndLog ( "Target [ %0 2X] requires final LRC XOR byte value: 0x %0 2X" , data
[ len
- 1 ] , finalXor
);  241  int  CmdAnalyseCRC ( const char  * Cmd
) {  243          char  cmdp 
=  param_getchar ( Cmd
,  0 );  244          if  ( strlen ( Cmd
) ==  0  ||  cmdp 
==  'h'  ||  cmdp 
==  'H' )  return  usage_analyse_crc ();  246          int  len 
=  strlen ( Cmd
);  247          if  (  len 
&  1  )  return  usage_analyse_crc ();  249          // add 1 for null terminator.  250          uint8_t  * data 
=  malloc ( len
+ 1 );  251          if  (  data 
==  NULL 
)  return  1 ;  253          if  (  param_gethex ( Cmd
,  0 ,  data
,  len
)) {  255                  return  usage_analyse_crc ();  259          //PrintAndLog("\nTests with '%s' hex bytes", sprint_hex(data, len));  261          PrintAndLog ( " \n Tests of reflection. Two current methods in source code" );         262          PrintAndLog ( "   reflect(0x3e23L,3) is  %0 4X == 0x3e26" ,  reflect ( 0x3e23 L
, 3 ) );  263          PrintAndLog ( "  SwapBits(0x3e23L,3) is  %0 4X == 0x3e26" ,  SwapBits ( 0x3e23 L
, 3 ) );  264          PrintAndLog ( "  0xB400 ==  %0 4X" ,  reflect ( ( 1  <<  16  |  0xb400 ), 16 ) );  267          // Test of CRC16,  '123456789' string.  269          PrintAndLog ( " \n Tests with '123456789' string" );  270          uint8_t  dataStr
[] = {  0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x39  };  271          uint8_t  legic8 
=  CRC8Legic ( dataStr
,  sizeof ( dataStr
));  273          PrintAndLog ( "LEGIC: CRC16:  %X " ,  CRC16Legic ( dataStr
,  sizeof ( dataStr
),  legic8
));  275          //these below has been tested OK.  276          PrintAndLog ( "Confirmed CRC Implementations" );  277          PrintAndLog ( "LEGIC: CRC8 :  %X  (0xC6 expected)" ,  legic8
);  278          PrintAndLog ( "MAXIM: CRC8 :  %X  (0xA1 expected)" ,  CRC8Maxim ( dataStr
,  sizeof ( dataStr
)));  279          PrintAndLog ( "DNP  : CRC16:  %X  (0x82EA expected)" ,  CRC16_DNP ( dataStr
,  sizeof ( dataStr
)));   280          PrintAndLog ( "CCITT: CRC16:  %X  (0xE5CC expected)" ,  CRC16_CCITT ( dataStr
,  sizeof ( dataStr
)));  282          PrintAndLog ( "ICLASS org: CRC16:  %X  (0x expected)" , iclass_crc16 ( ( char *) dataStr
,  sizeof ( dataStr
)));  283          PrintAndLog ( "ICLASS ice: CRC16:  %X  (0x expected)" , CRC16_ICLASS ( dataStr
,  sizeof ( dataStr
)));  287          uint8_t  dataStr1234
[] = {  0x1 , 0x2 , 0x3 , 0x4 };  288          PrintAndLog ( "ISO15693 org:  : CRC16:  %X  (0xF0B8 expected)" ,  Iso15693Crc ( dataStr1234
,  sizeof ( dataStr1234
)));  289          PrintAndLog ( "ISO15693 ice:  : CRC16:  %X  (0xF0B8 expected)" ,  CRC16_Iso15693 ( dataStr1234
,  sizeof ( dataStr1234
)));  294  int  CmdAnalyseCHKSUM ( const char  * Cmd
){  298          uint32_t  mask 
=  0xFFFF ;  300          bool  useHeader 
=  false ;  302          memset ( data
,  0x0 ,  sizeof ( data
));  304          while ( param_getchar ( Cmd
,  cmdp
) !=  0x00 ) {  305                  switch ( param_getchar ( Cmd
,  cmdp
)) {  308                          param_gethex_ex ( Cmd
,  cmdp
+ 1 ,  data
, & len
);  309                          if  (  len%2 
)  errors 
=  true ;  315                          mask 
=  param_get32ex ( Cmd
,  cmdp
+ 1 ,  0 ,  16 );  325                          return  usage_analyse_checksum ();  327                          PrintAndLog ( "Unknown parameter ' %c '" ,  param_getchar ( Cmd
,  cmdp
));  334          if ( errors
)  return  usage_analyse_checksum ();  337                  PrintAndLog ( "     add          | sub         | add 1's compl    | sub 1's compl   | xor" );  338                  PrintAndLog ( "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble     | byte nibble cumb |  BSD       |" );  339                  PrintAndLog ( "------------------+-------------+------------------+-----------------+--------------------" );  341          PrintAndLog ( "0x %X  0x %X    0x %X   | 0x %X  0x %X    | 0x %X  0x %X    0x %X  | 0x %X  0x %X        | 0x %X  0x %X    0x %X   | 0x %X   0x %X  | \n " ,          342                                    calcSumByteAdd ( data
,  len
,  mask
)  343                                  ,  calcSumNibbleAdd ( data
,  len
,  mask
)  344                                  ,  calcSumCrumbAdd ( data
,  len
,  mask
)  345                                  ,  calcSumByteSub ( data
,  len
,  mask
)  346                                  ,  calcSumNibbleSub ( data
,  len
,  mask
)  347                                  ,  calcSumByteAddOnes ( data
,  len
,  mask
)  348                                  ,  calcSumNibbleAddOnes ( data
,  len
,  mask
)  349                                  ,  calcSumCrumbAddOnes ( data
,  len
,  mask
)  350                                  ,  calcSumByteSubOnes ( data
,  len
,  mask
)  351                                  ,  calcSumNibbleSubOnes ( data
,  len
,  mask
)  352                                  ,  calcSumByteXor ( data
,  len
,  mask
)  353                                  ,  calcSumNibbleXor ( data
,  len
,  mask
)  354                                  ,  calcSumCrumbXor ( data
,  len
,  mask
)  355                                  ,  calcBSDchecksum8 ( data
,  len
,  mask
)  356                                  ,  calcBSDchecksum4 ( data
,  len
,  mask
)  361  int  CmdAnalyseDates ( const char  * Cmd
){  362          // look for datestamps in a given array of bytes  363          PrintAndLog ( "To be implemented. Feel free to contribute!" );  366  int  CmdAnalyseTEASelfTest ( const char  * Cmd
){  368          uint8_t  v
[ 8 ],  v_le
[ 8 ];  369          memset ( v
,  0x00 ,  sizeof ( v
));  370          memset ( v_le
,  0x00 ,  sizeof ( v_le
));  371          uint8_t *  v_ptr 
=  v_le
;  373          uint8_t  cmdlen 
=  strlen ( Cmd
);  374          cmdlen 
= (  sizeof ( v
)<< 2  <  cmdlen 
) ?  sizeof ( v
)<< 2  :  cmdlen
;  376          if  (  param_gethex ( Cmd
,  0 ,  v
,  cmdlen
) >  0  ){  377                  PrintAndLog ( "can't read hex chars, uneven? ::  %u " ,  cmdlen
);  381          SwapEndian64ex ( v 
,  8 ,  4 ,  v_ptr
);  384          uint8_t  key
[ 16 ] = { 0x55 , 0xFE , 0xF6 , 0x30 , 0x62 , 0xBF , 0x0B , 0xC1 , 0xC9 , 0xB3 , 0x7C , 0x34 , 0x97 , 0x3E , 0x29 , 0xFB  };  386          uint8_t *  key_ptr 
=  keyle
;  387          SwapEndian64ex ( key 
,  sizeof ( key
),  4 ,  key_ptr
);  389          PrintAndLog ( "TEST LE enc|  %s " ,  sprint_hex ( v_ptr
,  8 ));  391          tea_decrypt ( v_ptr
,  key_ptr
);      392          PrintAndLog ( "TEST LE dec |  %s " ,  sprint_hex_ascii ( v_ptr
,  8 ));  394          tea_encrypt ( v_ptr
,  key_ptr
);      395          tea_encrypt ( v_ptr
,  key_ptr
);  396          PrintAndLog ( "TEST enc2 |  %s " ,  sprint_hex_ascii ( v_ptr
,  8 ));  401  int  CmdAnalyseA ( const char  * Cmd
){  404  // uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000)  405  // uid(2e086b1a) nt(230736f6) ks(0e0b0e0b090c0d02) nr(000000001)  406  // uid(2e086b1a) nt(230736f6) ks(0e05060e01080b08) nr(000000002)  407  uint64_t d1[] = {0x2e086b1a, 0x230736f6, 0x0000001, 0x0e0b0e0b090c0d02};  408  uint64_t d2[] = {0x2e086b1a, 0x230736f6, 0x0000002, 0x0e05060e01080b08};  410  // uid(17758822) nt(c0c69e59) ks(080105020705040e) nr(00000001)  411  // uid(17758822) nt(c0c69e59) ks(01070a05050c0705) nr(00000002)  412  uint64_t d1[] = {0x17758822, 0xc0c69e59, 0x0000001, 0x080105020705040e};  413  uint64_t d2[] = {0x17758822, 0xc0c69e59, 0x0000002, 0x01070a05050c0705};  415  // uid(6e442129) nt(8f699195) ks(090d0b0305020f02) nr(00000001)  416  // uid(6e442129) nt(8f699195) ks(03030508030b0c0e) nr(00000002)  417  // uid(6e442129) nt(8f699195) ks(02010f030c0d050d) nr(00000003)  418  // uid(6e442129) nt(8f699195) ks(00040f0f0305030e) nr(00000004)  419  uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02};  420  uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e};  422  uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001)  423  uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002)  426          uint64_t  d1
[] = { 0x3e172b29 ,  0x039b7bd2 ,  0x0000001 ,  0x0c0e0f0505080800 };  427          uint64_t  d2
[] = { 0x3e172b29 ,  0x039b7bd2 ,  0x0000002 ,  0x0e06090d03000b0f };  429          nonce2key_ex ( 0 ,  0  ,  d1
[ 0 ],  d1
[ 1 ],  d1
[ 2 ],  d1
[ 3 ], & key
);  430          nonce2key_ex ( 0 ,  0  ,  d2
[ 0 ],  d2
[ 1 ],  d2
[ 2 ],  d2
[ 3 ], & key
);  434  static void  permute ( uint8_t  * data
,  uint8_t  len
,  uint8_t  * output
){         437          if  (  len 
>  KEY_SIZE 
) {  438                  for ( uint8_t  m 
=  0 ;  m 
<  len
;  m 
+=  KEY_SIZE
){  439                          permute ( data
+ m
,  KEY_SIZE
,  output
+ m
);  443          if  (  len 
!=  KEY_SIZE 
) {  444                  printf ( "wrong key size \n " );  448          for (  i
= 0 ;  i 
<  KEY_SIZE
; ++ i
){  451                  for (  j
= 0 ;  j 
<  KEY_SIZE
; ++ j
){  459  static void  permute_rev ( uint8_t  * data
,  uint8_t  len
,  uint8_t  * output
){  460          permute ( data
,  len
,  output
);  461          permute ( output
,  len
,  data
);  462          permute ( data
,  len
,  output
);  464  static void  simple_crc ( uint8_t  * data
,  uint8_t  len
,  uint8_t  * output
){  466          for (  uint8_t  i
= 0 ;  i 
<  len
; ++ i
){  467                  // seventh byte contains the crc.  468                  if  ( ( i 
&  0x7 ) ==  0x7  ) {  469                          output
[ i
] =  crc 
^  0xFF ;  477  // DES doesn't use the MSB.  478  static void  shave ( uint8_t  * data
,  uint8_t  len
){  479          for  ( uint8_t  i
= 0 ;  i
< len
; ++ i
)  482  static void  generate_rev ( uint8_t  * data
,  uint8_t  len
) {  483          uint8_t  * key 
=  calloc ( len
, 1 );     484          printf ( "input permuted key |  %s  \n " ,  sprint_hex ( data
,  len
));  485          permute_rev ( data
,  len
,  key
);  486          printf ( "    unpermuted key |  %s  \n " ,  sprint_hex ( key
,  len
));  488          printf ( "               key |  %s  \n " ,  sprint_hex ( key
,  len
));  491  static void  generate ( uint8_t  * data
,  uint8_t  len
) {  492          uint8_t  * key 
=  calloc ( len
, 1 );  493          uint8_t  * pkey 
=  calloc ( len
, 1 );    494          printf ( "    input key |  %s  \n " ,  sprint_hex ( data
,  len
));  495          permute ( data
,  len
,  pkey
);  496          printf ( " permuted key |  %s  \n " ,  sprint_hex ( pkey
,  len
));  497          simple_crc ( pkey
,  len
,  key 
);  498          printf ( "   CRC'ed key |  %s  \n " ,  sprint_hex ( key
,  len
));  502  int  CmdAnalyseHid ( const char  * Cmd
){  504          uint8_t  key
[ 8 ] = { 0 };     505          uint8_t  key_std_format
[ 8 ] = { 0 };  506          uint8_t  key_iclass_format
[ 8 ] = { 0 };  507          uint8_t  data
[ 16 ] = { 0 };  508          bool  isReverse 
=  FALSE
;  510          char  cmdp 
=  param_getchar ( Cmd
,  0 );  511          if  ( strlen ( Cmd
) ==  0 ||  cmdp 
==  'h'  ||  cmdp 
==  'H' )  return  usage_analyse_hid ();  513          if  (  cmdp 
==  'r'  ||  cmdp 
==  'R'  )   516          param_gethex_ex ( Cmd
,  1 ,  data
, & len
);  517          if  (  len%2 
)  return  usage_analyse_hid ();  521          memcpy ( key
,  data
,  8 );  524                  generate_rev ( data
,  len
);  525                  permutekey_rev ( key
,  key_std_format
);  526                  printf ( " holiman iclass key |  %s  \n " ,  sprint_hex ( key_std_format
,  8 ));  530                  permutekey ( key
,  key_iclass_format
);               531                  printf ( " holiman std key |  %s  \n " ,  sprint_hex ( key_iclass_format
,  8 ));  536  void  generate4bNUID ( uint8_t  * uid
,  uint8_t  * nuid
){  538          uint8_t  first
,  second
;  540          ComputeCrc14443 ( CRC_14443_A
,  uid
,  3 , & first
, & second
);  541          nuid
[ 0 ] |= ( second 
&  0xE0 ) |  0xF ;  547          UpdateCrc14443 ( uid
[ 3 ], & crc
);  548          UpdateCrc14443 ( uid
[ 4 ], & crc
);  549          UpdateCrc14443 ( uid
[ 5 ], & crc
);  550          UpdateCrc14443 ( uid
[ 6 ], & crc
);  552          nuid
[ 2 ] = ( crc 
>>  8 ) &  0xFF  ;  553          nuid
[ 3 ] =  crc 
&  0xFF ;  556  int  CmdAnalyseNuid ( const char  * Cmd
){  557          uint8_t  nuid
[ 4 ] = { 0 };    558          uint8_t  uid
[ 7 ] = { 0 };  560          char  cmdp 
=  param_getchar ( Cmd
,  0 );  561          if  ( strlen ( Cmd
) ==  0 ||  cmdp 
==  'h'  ||  cmdp 
==  'H' )  return  usage_analyse_nuid ();  563          /* selftest  UID 040D681AB52281  -> NUID 8F430FEF */  564          if  ( cmdp 
==  't'  ||  cmdp 
==  'T' ) {  565                  memcpy ( uid
,  " \x04\x0d\x68\x1a\xb5\x22\x81 " ,  7 );  566                  generate4bNUID ( uid
,  nuid
);  567                  if  (  0  ==  memcmp ( nuid
,  " \x8f\x43\x0f\xef " ,  4 ))  568                          printf ( "Selftest OK \n " );  570                          printf ( "Selftest Failed \n " );  574          param_gethex_ex ( Cmd
,  0 ,  uid
, & len
);  575          if  (  len%2  
||  len 
!=  14 )  return  usage_analyse_nuid ();  577          generate4bNUID ( uid
,  nuid
);  579          printf ( "UID  |  %s  \n " ,  sprint_hex ( uid
,  7 ));  580          printf ( "NUID |  %s  \n " ,  sprint_hex ( nuid
,  4 ));  583  static  command_t CommandTable
[] = {  584          { "help" ,         CmdHelp
,             1 ,  "This help" },  585          { "lcr" ,          CmdAnalyseLCR
,           1 ,  "Generate final byte for XOR LRC" },  586          { "crc" ,          CmdAnalyseCRC
,           1 ,  "Stub method for CRC evaluations" },  587          { "chksum" ,       CmdAnalyseCHKSUM
,        1 ,  "Checksum with adding, masking and one's complement" },  588          { "dates" ,        CmdAnalyseDates
,         1 ,  "Look for datestamps in a given array of bytes" },  589          { "tea" ,          CmdAnalyseTEASelfTest
,   1 ,  "Crypto TEA test" },  590          { "lfsr" ,         CmdAnalyseLfsr
,          1 ,       "LFSR tests" },  591          { "a" ,            CmdAnalyseA
,             1 ,       "num bits test" },  592          { "hid" ,          CmdAnalyseHid
,           1 ,       "Permute function from 'heart of darkness' paper" },  593          { "nuid" ,         CmdAnalyseNuid
,          1 ,       "create NUID from 7byte UID" },  594          { NULL
,  NULL
,  0 ,  NULL
}  597  int  CmdAnalyse ( const char  * Cmd
) {  598          clearCommandBuffer ();  599          CmdsParse ( CommandTable
,  Cmd
);  603  int  CmdHelp ( const char  * Cmd
) {  604          CmdsHelp ( CommandTable
);