1 //----------------------------------------------------------------------------- 
   2 // Frederik Möllers - August 2012 
   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 // Routines to support the German eletronic "Personalausweis" (ID card) 
   9 // Note that the functions which do not implement USB commands do NOT initialize 
  10 // the card (with iso14443a_select_card etc.). If You want to use these 
  11 // functions, You need to do the setup before calling them! 
  12 //----------------------------------------------------------------------------- 
  14 #include "iso14443a.h" 
  18 // Protocol and Parameter Selection Request 
  19 // use regular (1x) speed in both directions 
  20 // CRC is already included 
  21 static const uint8_t pps
[] = {0xD0, 0x11, 0x00, 0x52, 0xA6}; 
  23 // APDUs for communication with German Identification Card 
  25 // General Authenticate (request encrypted nonce) WITHOUT the Le at the end 
  26 static const uint8_t apdu_general_authenticate_pace_get_nonce
[] = { 
  32         0x7C, // Type: Dynamic Authentication Data 
  33         0x00, // Length: 0 bytes 
  36 // MSE: Set AT (only CLA, INS, P1 and P2) 
  37 static const uint8_t apdu_mse_set_at_start
[] = { 
  44 // SELECT BINARY with the ID for EF.CardAccess 
  45 static const uint8_t apdu_select_binary_cardaccess
[] = { 
  56 static const uint8_t apdu_read_binary
[] = { 
  65 // the leading bytes of a PACE OID 
  66 static const uint8_t oid_pace_start
[] = { 
  67     0x04, // itu-t, identified-organization 
  70     0x00, // etsi-identified-organization 
  77 //----------------------------------------------------------------------------- 
  78 // Closes the communication channel and turns off the field 
  79 //----------------------------------------------------------------------------- 
  82         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
  86 //----------------------------------------------------------------------------- 
  87 // Parses DER encoded data, e.g. from EF.CardAccess and fills out the given 
  88 // structs. If a pointer is 0, it is ignored. 
  89 // The function returns 0 on success and if an error occured, it returns the 
  90 // offset where it occured. 
  92 // TODO: This function can access memory outside of the given data if the DER 
  94 // TODO: Support skipping elements with a length > 0x7F 
  95 // TODO: Support OIDs with a length > 7F 
  96 // TODO: Support elements with long tags (tag is longer than 1 byte) 
  97 // TODO: Support proprietary PACE domain parameters 
  98 //----------------------------------------------------------------------------- 
  99 size_t EPA_Parse_CardAccess(uint8_t *data
, 
 101                             pace_version_info_t 
*pace_info
) 
 105         while (index 
<= length 
- 2) { 
 106                 // determine type of element 
 108                 if (data
[index
] == 0x31 || data
[index
] == 0x30) { 
 109                         // enter the set (skip tag + length) 
 111                         // check for extended length 
 112                         if ((data
[index 
- 1] & 0x80) != 0) { 
 113                                 index 
+= (data
[index
-1] & 0x7F); 
 117                 else if (data
[index
] == 0x06) { 
 118                         // is this a PACE OID? 
 119                         if (data
[index 
+ 1] == 0x0A // length matches 
 120                             && memcmp(data 
+ index 
+ 2, 
 122                                       sizeof(oid_pace_start
)) == 0 // content matches 
 123                             && pace_info 
!= NULL
) 
 125                                 // first, clear the pace_info struct 
 126                                 memset(pace_info
, 0, sizeof(pace_version_info_t
)); 
 127                                 memcpy(pace_info
->oid
, data 
+ index 
+ 2, sizeof(pace_info
->oid
)); 
 128                                 // a PACE OID is followed by the version 
 129                                 index 
+= data
[index 
+ 1] + 2; 
 130                                 if (data
[index
] == 02 && data
[index 
+ 1] == 01) { 
 131                                         pace_info
->version 
= data
[index 
+ 2]; 
 137                                 // after that there might(!) be the parameter ID 
 138                                 if (data
[index
] == 02 && data
[index 
+ 1] == 01) { 
 139                                         pace_info
->parameter_id 
= data
[index 
+ 2]; 
 145                                 index 
+= 2 + data
[index 
+ 1]; 
 148                 // if the length is 0, something is wrong 
 149                 // TODO: This needs to be extended to support long tags 
 150                 else if (data
[index 
+ 1] == 0) { 
 155                         // TODO: This needs to be extended to support long tags 
 156                         // TODO: This needs to be extended to support unknown elements with 
 158                         index 
+= 2 + data
[index 
+ 1]; 
 162         // TODO: We should check whether we reached the end in error, but for that 
 163         //       we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO) 
 167 //----------------------------------------------------------------------------- 
 168 // Read the file EF.CardAccess and save it into a buffer (at most max_length bytes) 
 169 // Returns -1 on failure or the length of the data on success 
 170 // TODO: for the moment this sends only 1 APDU regardless of the requested length 
 171 //----------------------------------------------------------------------------- 
 172 int EPA_Read_CardAccess(uint8_t *buffer
, size_t max_length
) 
 174         // the response APDU of the card 
 175         // since the card doesn't always care for the expected length we send it, 
 176         // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) 
 177         uint8_t response_apdu
[262]; 
 178         int rapdu_length 
= 0; 
 180         // select the file EF.CardAccess 
 181         rapdu_length 
= iso14_apdu((uint8_t *)apdu_select_binary_cardaccess
, 
 182                                   sizeof(apdu_select_binary_cardaccess
), 
 184         if (rapdu_length 
!= 6 
 185             || response_apdu
[rapdu_length 
- 4] != 0x90 
 186             || response_apdu
[rapdu_length 
- 3] != 0x00) 
 192         rapdu_length 
= iso14_apdu((uint8_t *)apdu_read_binary
, 
 193                                   sizeof(apdu_read_binary
), 
 195         if (rapdu_length 
<= 6 
 196             || response_apdu
[rapdu_length 
- 4] != 0x90 
 197             || response_apdu
[rapdu_length 
- 3] != 0x00) 
 202         // copy the content into the buffer 
 203         // length of data available: apdu_length - 4 (ISO frame) - 2 (SW) 
 204         size_t to_copy 
= rapdu_length 
- 6; 
 205         to_copy 
= to_copy 
< max_length 
? to_copy 
: max_length
; 
 206         memcpy(buffer
, response_apdu
+2, to_copy
); 
 210 //----------------------------------------------------------------------------- 
 211 // Abort helper function for EPA_PACE_Collect_Nonce 
 212 // sets relevant data in ack, sends the response 
 213 //----------------------------------------------------------------------------- 
 214 static void EPA_PACE_Collect_Nonce_Abort(uint8_t step
, int func_return
) 
 216 //      // step in which the failure occured 
 217 //      ack->arg[0] = step; 
 218 //      // last return code 
 219 //      ack->arg[1] = func_return; 
 221         // power down the field 
 224         // send the USB packet 
 225   cmd_send(CMD_ACK
,step
,func_return
,0,0,0); 
 226 //UsbSendPacket((void *)ack, sizeof(UsbCommand)); 
 229 //----------------------------------------------------------------------------- 
 230 // Acquire one encrypted PACE nonce 
 231 //----------------------------------------------------------------------------- 
 232 void EPA_PACE_Collect_Nonce(UsbCommand 
*c
) 
 238          *           step where the error occured or 0 if no error occured 
 240      *           return code of the last executed function 
 245         // return value of a function 
 248 //      // initialize ack with 0s 
 249 //      memset(ack->arg, 0, 12); 
 250 //      memset(ack->d.asBytes, 0, 48); 
 252         // set up communication 
 253         func_return 
= EPA_Setup(); 
 254         if (func_return 
!= 0) { 
 255                 EPA_PACE_Collect_Nonce_Abort(1, func_return
); 
 259         // increase the timeout (at least some cards really do need this!) 
 260         iso14a_set_timeout(0x0002FFFF); 
 262         // read the CardAccess file 
 263         // this array will hold the CardAccess file 
 264         uint8_t card_access
[256] = {0}; 
 265         int card_access_length 
= EPA_Read_CardAccess(card_access
, 256); 
 266         // the response has to be at least this big to hold the OID 
 267         if (card_access_length 
< 18) { 
 268                 EPA_PACE_Collect_Nonce_Abort(2, card_access_length
); 
 272         // this will hold the PACE info of the card 
 273         pace_version_info_t pace_version_info
; 
 274         // search for the PACE OID 
 275         func_return 
= EPA_Parse_CardAccess(card_access
, 
 278         if (func_return 
!= 0 || pace_version_info
.version 
== 0) { 
 279                 EPA_PACE_Collect_Nonce_Abort(3, func_return
); 
 283         // initiate the PACE protocol 
 284         // use the CAN for the password since that doesn't change 
 285         func_return 
= EPA_PACE_MSE_Set_AT(pace_version_info
, 2); 
 288         uint8_t nonce
[256] = {0}; 
 289         uint8_t requested_size 
= (uint8_t)c
->arg
[0]; 
 290         func_return 
= EPA_PACE_Get_Nonce(requested_size
, nonce
); 
 291         // check if the command succeeded 
 294                 EPA_PACE_Collect_Nonce_Abort(4, func_return
); 
 301         // save received information 
 302 //      ack->arg[1] = func_return; 
 303 //      memcpy(ack->d.asBytes, nonce, func_return); 
 304 //      UsbSendPacket((void *)ack, sizeof(UsbCommand)); 
 305   cmd_send(CMD_ACK
,0,func_return
,0,nonce
,func_return
); 
 308 //----------------------------------------------------------------------------- 
 309 // Performs the "Get Nonce" step of the PACE protocol and saves the returned 
 310 // nonce. The caller is responsible for allocating enough memory to store the 
 311 // nonce. Note that the returned size might be less or than or greater than the 
 313 // Returns the actual size of the nonce on success or a less-than-zero error 
 315 //----------------------------------------------------------------------------- 
 316 int EPA_PACE_Get_Nonce(uint8_t requested_length
, uint8_t *nonce
) 
 319         uint8_t apdu
[sizeof(apdu_general_authenticate_pace_get_nonce
) + 1]; 
 320         // copy the constant part 
 322                apdu_general_authenticate_pace_get_nonce
, 
 323                sizeof(apdu_general_authenticate_pace_get_nonce
)); 
 324         // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU 
 325         apdu
[sizeof(apdu_general_authenticate_pace_get_nonce
)] = requested_length 
+ 4; 
 328         uint8_t response_apdu
[262]; 
 329         int send_return 
= iso14_apdu(apdu
, 
 332         // check if the command succeeded 
 334                 || response_apdu
[send_return 
- 4] != 0x90 
 335                 || response_apdu
[send_return 
- 3] != 0x00) 
 340         // if there is no nonce in the RAPDU, return here 
 341         if (send_return 
< 10) 
 346         // get the actual length of the nonce 
 347         uint8_t nonce_length 
= response_apdu
[5]; 
 348         if (nonce_length 
> send_return 
- 10) 
 350                 nonce_length 
= send_return 
- 10; 
 353         memcpy(nonce
, response_apdu 
+ 6, nonce_length
); 
 358 //----------------------------------------------------------------------------- 
 359 // Initializes the PACE protocol by performing the "MSE: Set AT" step 
 360 // Returns 0 on success or a non-zero error code on failure 
 361 //----------------------------------------------------------------------------- 
 362 int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info
, uint8_t password
) 
 364         // create the MSE: Set AT APDU 
 366         // the minimum length (will be increased as more data is added) 
 367         size_t apdu_length 
= 20; 
 368         // copy the constant part 
 370                apdu_mse_set_at_start
, 
 371                sizeof(apdu_mse_set_at_start
)); 
 375         apdu
[6] = sizeof(pace_version_info
.oid
); 
 378                pace_version_info
.oid
, 
 379                sizeof(pace_version_info
.oid
)); 
 386         // if standardized domain parameters are used, copy the ID 
 387         if (pace_version_info
.parameter_id 
!= 0) { 
 389                 // type: domain parameter 
 393                 // copy the parameter ID 
 394                 apdu
[22] = pace_version_info
.parameter_id
; 
 396         // now set Lc to the actual length 
 397         apdu
[4] = apdu_length 
- 5; 
 399         uint8_t response_apdu
[6]; 
 400         int send_return 
= iso14_apdu(apdu
, 
 403         // check if the command succeeded 
 405                 || response_apdu
[send_return 
- 4] != 0x90 
 406                 || response_apdu
[send_return 
- 3] != 0x00) 
 413 //----------------------------------------------------------------------------- 
 414 // Set up a communication channel (Card Select, PPS) 
 415 // Returns 0 on success or a non-zero error code on failure 
 416 //----------------------------------------------------------------------------- 
 423         // card select information 
 424         iso14a_card_select_t card_select_info
; 
 425         // power up the field 
 426         iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD
); 
 429         return_code 
= iso14443a_select_card(uid
, &card_select_info
, NULL
); 
 430         if (return_code 
!= 1) { 
 434         // send the PPS request 
 435         ReaderTransmit((uint8_t *)pps
, sizeof(pps
), NULL
); 
 436         uint8_t pps_response
[3]; 
 437         uint8_t pps_response_par
[1]; 
 438         return_code 
= ReaderReceive(pps_response
, pps_response_par
); 
 439         if (return_code 
!= 3 || pps_response
[0] != 0xD0) { 
 440                 return return_code 
== 0 ? 2 : return_code
;