Ejemplo n.º 1
0
//-----------------------------------------------------------------------------
// Acquire one encrypted PACE nonce
//-----------------------------------------------------------------------------
void EPA_PACE_Collect_Nonce(UsbCommand *c)
{
	/*
	 * ack layout:
	 * 	arg:
	 * 		1. element
	 *           step where the error occured or 0 if no error occured
     *       2. element
     *           return code of the last executed function
	 * 	d:
	 * 		Encrypted nonce
	 */

	// return value of a function
	int func_return;

//	// initialize ack with 0s
//	memset(ack->arg, 0, 12);
//	memset(ack->d.asBytes, 0, 48);
	
	// set up communication
	func_return = EPA_Setup();
	if (func_return != 0) {
		EPA_PACE_Collect_Nonce_Abort(1, func_return);
		return;
	}

	// increase the timeout (at least some cards really do need this!)
	iso14a_set_timeout(0x0002FFFF);
	
	// read the CardAccess file
	// this array will hold the CardAccess file
	uint8_t card_access[256] = {0};
	int card_access_length = EPA_Read_CardAccess(card_access, 256);
	// the response has to be at least this big to hold the OID
	if (card_access_length < 18) {
		EPA_PACE_Collect_Nonce_Abort(2, card_access_length);
		return;
	}

	// this will hold the PACE info of the card
	pace_version_info_t pace_version_info;
	// search for the PACE OID
	func_return = EPA_Parse_CardAccess(card_access,
	                                   card_access_length,
	                                   &pace_version_info);
	if (func_return != 0 || pace_version_info.version == 0) {
		EPA_PACE_Collect_Nonce_Abort(3, func_return);
		return;
	}
	
	// initiate the PACE protocol
	// use the CAN for the password since that doesn't change
	func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
	
	// now get the nonce
	uint8_t nonce[256] = {0};
	uint8_t requested_size = (uint8_t)c->arg[0];
	func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
	// check if the command succeeded
	if (func_return < 0)
	{
		EPA_PACE_Collect_Nonce_Abort(4, func_return);
		return;
	}
  
  // all done, return
	EPA_Finish();
	
	// save received information
//	ack->arg[1] = func_return;
//	memcpy(ack->d.asBytes, nonce, func_return);
//	UsbSendPacket((void *)ack, sizeof(UsbCommand));
  cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
}
Ejemplo n.º 2
0
//-----------------------------------------------------------------------------
// Perform the PACE protocol by replaying given APDUs
//-----------------------------------------------------------------------------
void EPA_PACE_Replay(UsbCommand *c)
{
	uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};

	// if an APDU has been passed, save it
	if (c->arg[0] != 0) {
		// make sure it's not too big
		if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
		{
			cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
		}
		memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
	           c->d.asBytes,
	           c->arg[2]);
		// save/update APDU length
		if (c->arg[1] == 0) {
			apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];
		} else {
			apdu_lengths_replay[c->arg[0] - 1] += c->arg[2];
		}
		cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
		return;
	}

	// return value of a function
	int func_return;

	// set up communication
	func_return = EPA_Setup();
	if (func_return != 0) {
		EPA_Finish();
		cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0);
		return;
	}

	// increase the timeout (at least some cards really do need this!)/////////////
	// iso14a_set_timeout(0x0003FFFF);

	// response APDU
	uint8_t response_apdu[300] = {0};

	// now replay the data and measure the timings
	for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
		StartCountUS();
		func_return = EPA_APDU(apdus_replay[i].data,
		                         apdu_lengths_replay[i],
		                         response_apdu);
		timings[i] = GetCountUS();
		// every step but the last one should succeed
		if (i < sizeof(apdu_lengths_replay) - 1
		    && (func_return < 6
		        || response_apdu[func_return - 4] != 0x90
		        || response_apdu[func_return - 3] != 0x00))
		{
			EPA_Finish();
			cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20);
			return;
		}
	}
	EPA_Finish();
	cmd_send(CMD_ACK,0,0,0,timings,20);
	return;
}