The limit of respone in APDU sendCommand

We send APDU command to ISO-7816 tag and receive the resposne, but some error occurred.


Exceeding 1694 bytes will failure

We send the APDU command. The phone successfully get response from PN7150 when the length of response is under 1694 bytes, but we get an error when the length of response is greater than or equal to 1694 bytes.


The exception as follows : Error Domain=NFCError Code=100 "Tag connection lost"


Android can work

We use Android to test same function, it can be executed successfully.


I think the APDU command on iOS has the response limit or other issue.

It is the result of ours test on iOS :

  • send 100 bytes, response 1529 bytes : occasionally success.
  • send 100 bytes, response 1200 bytes : success.
  • send 0 byte, response 1694 bytes : error.
  • send 0 byte, response 1693 bytes : success.


Code

The following is the part of the send and receive APDU.


func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
      
    var tag: NFCTag? = nil
    for nfcTag in tags {
        if case .iso7816(_) = nfcTag {
            session.alertMessage = "Detect an iso7816 tag."
            tag = nfcTag
        }
    }
    if tag == nil {
        session.invalidate(errorMessage: "No valid tag found.")
        return
    }
       
    session.connect(to: tag!) { (error: Error?) in

        if error != nil {
            session.invalidate(errorMessage: "Connection error. Please try again.")
            return
        }
        guard case let .iso7816(iso7816Tag) = tag else {
            return
        }
                  
        let CLA: UInt8 = 0x00
        let INS: UInt8 = 0xB0
        let p1: UInt8 = 0x00
        let p2:UInt8 = 0x04
        let data : Data = self.stringToHex(self.message) // sent data
        let Le:Int = 1500 // extends APDU
        let apduCommand = NFCISO7816APDU(instructionClass: CLA,instructionCode: INS,p1Parameter: p1,p2Parameter: p2,data: data,expectedResponseLength: Le)

        iso7816Tag.sendCommand(apdu: apduCommand) { (response: Data, sw1:UInt8, sw2:UInt8, error: Error?) in
            
            // if response > 1694 bytes , error occurred
            if error != nil {
                self.readerSession?.invalidate(errorMessage: "Send command tag error. Please try again.")
                return
            }

            print(String(data:response,encoding: .ascii)!)
            self.readerSession?.alertMessage = "Send Command Success!"
            self.readerSession?.invalidate()  
        }  
    }
}


Thank you.

Replies

I've noted similar behavior and have had better success with not using the extended APDU length and relying instead upon legacy message chaining.

Thanks for your reply.

But what do you mean the "legacy message chaining" ?



By the way, we try different value on Le :

1. Le = 0 -> error occurred (cannot received response).

2. Le = 255 or 1500 -> response received successfully by iPhone and the results of experiment are as above.

I just want to say that the value of Le doesn't seem to effect the response directly.


Thank you. 😁

I am able to connect to the card using NFCTagReaderSession and NFCISO7816Tag tag but i can't get ATR number after connection and it shows zero bytes in historicalBytes, while in android we are able to get some number in historicalBytes for same type of cards\


One more filed we have NFCISO7816Tag "identifier" but it is getting different number for same type of card.


print("iso7816Tag historical bytes \(iso7816Tag.historicalBytes)")

print("iso7816Tag identifier \(iso7816Tag.identifier)")


We want same number or value for same type of card that can be used for ATR validation in our code.


Please suggest to get an ATR number or value for same type of cards.

I'm also testing having iOS communicate using the ISO-7816 protocal to a PN7150 Device setup with Host Card Emulation.


From the PN7150 Device, I'm seeing that iOS always starts off communication to it by automatically

sending it a SELECT APDU-Command Twice.

I'm wondering if anyone else has seen this, and can explain why it is doing this?


The content of the SELECT APDU-Command being;


CLA: 0x0

INS: 0xa4

P1: 0x4

P2: 0x0

Lc: 0x07

DATA: d2 76 00 00 85 01 01

Le: 0


As noted in Section 7.1.1 SELECT command, ISO/IEC 7816-4 Spec

~ see http://www.embedx.com/pdfs/ISO_STD_7816/info_isoiec7816-4%7Bed21.0%7Den.pdf

~ The DATA value here corresponds to the ISO7816 AID I've set in my Info.plist file (D2760000850101)


Specifically iOS does the following;

1. iOS first sends the SELECT APDU-Command

2. iOS closes the connection.

3. iOS then sends the SELECT APDU-Command again, leaves the connection open

4. iOS then sends the APDU-Command I've actually programmed it to

~ via the function sendCommand(apdu: NFCISO7816APDU, completionHandler: @escaping (Data, UInt8, UInt8, Error?) -> Void)

5. iOS closes the connection.



Is iOS sending the SELECT APDU-Command in the first place as a conveniance so that we do not have to?

If so, why send the command twice?

Why not just send the command once, leave the connection open, then send the programmed APDU command(s) before closing the connection?

Also related to testing iOS communicate using the ISO-7816 protocal to a PN7150 device;


If I have iOS initiate the NFC-Scan while it is already in the RF-Field of the PN7150 device,

the communication will fail more than half of the time with an Error of

Domain=NFCError Code=104 "Tag is not connected"


And the XCode Debugger console showing the following trace-output;

2019-10-31 13:40:35.397849-0400

NFCTagReader[381:37470] [CoreNFC] 00000002 80436f00

-[NFCTagReaderSession _connectTag:error:]:573 Error Domain=NFCError Code=100 "Stack Error"

UserInfo={NSLocalizedDescription=Stack Error, NSUnderlyingError=0x2824989c0 {Error Domain=nfcd Code=29 "Tag Error" UserInfo={NSLocalizedDescription=Tag Error}}}


If I have iOS initiate the NFC-Scan outside of the RF-Field of the PN7150 device, then bring it into proximity of it,

then communication will succeed the majority of the time.



Does this behavior make sence?

Should iOS always initiate a scan away from an NFC-Device it is to communicate with, then be brought into proximity of it?
Should iOS not initiate a scan while in close proximity to the NFC-Device it is to communicate with?