Search code examples
iosobjective-cxcodenfcentitlements

"Missing required entitlement" after connecting to ID06 (ISO-DEV)


I´ve created a basic iPhone application for iOS 17.5 using XCode where I would like to scan a PIV card (ID06) and just log the result. I´ve tried to minimize the code as much as possible, but whatever I do I receive:

-[NFCTagReaderSession _connectTag:error:]:744 Error Domain=NFCError Code=2 "Missing required entitlement" UserInfo={NSLocalizedDescription=Missing required entitlement}

after I`ve connected to the card.

I`ve tripplechecked the signing certificate to include NFC option in Apple developer portal, and also deleted the certificate locally on my computer to be sure it uses the latest.

Here´s my ViewController:

ViewController.h

#import <UIKit/UIKit.h>
#import <CoreNFC/CoreNFC.h>

@interface ViewController : UIViewController <NFCTagReaderSessionDelegate>

@property (nonatomic, strong) NFCTagReaderSession *nfcSession;

@end

Viewcontroller.m

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self startScanning];
}

- (void)startScanning {
    self.nfcSession = [[NFCTagReaderSession alloc] initWithPollingOption:NFCPollingISO14443 delegate:self queue:nil];
    self.nfcSession.alertMessage = @"Hold your iPhone near the NFC tag.";
    [self.nfcSession beginSession];
}

- (void)tagReaderSession:(NFCTagReaderSession *)session didDetectTags:(NSArray<__kindof id<NFCTag>> *)tags {
    id<NFCTag> tag = [tags firstObject];
    
    [session connectToTag:tag completionHandler:^(NSError * _Nullable error) {
        if (error != nil) {
            [session invalidateSessionWithErrorMessage:@"Connection failed"];
            return;
        }
        
        id<NFCISO7816Tag> iso7816Tag = [tag asNFCISO7816Tag];
        NSLog(@"Connected: %@", iso7816Tag);
        
        // FOLLOWING APDU COMMAND CAN BE REMOVED, THE RESULT IS THE SAME
        NSData *readCertCommandData = [NSData dataWithBytes:(unsigned char[]){0x00, 0xB0, 0x00, 0x00, 0x10} length:5];
        NFCISO7816APDU *readCertCommand = [[NFCISO7816APDU alloc] initWithInstructionClass:0x00
                                                                           instructionCode:0xB0
                                                                               p1Parameter:0x00
                                                                               p2Parameter:0x00
                                                                                      data:readCertCommandData
                                                                    expectedResponseLength:256];

        [iso7816Tag sendCommandAPDU:readCertCommand completionHandler:^(NSData *responseData, uint8_t sw1, uint8_t sw2, NSError * _Nullable error) {
            if (error) {
                NSLog(@"Error sending read certificate APDU: %@", error.localizedDescription);
                [self.nfcSession invalidateSessionWithErrorMessage:@"Session invalidated"];
            } else {
                NSLog(@"Read Certificate Response Data: %@", responseData);
                NSLog(@"Status Word: %02X %02X", sw1, sw2);
                [self.nfcSession invalidateSession];
            }
        }];
    }];
}

- (void)tagReaderSessionDidBecomeActive:(NFCTagReaderSession *)session {
    NSLog(@"NFC session did become active");
}

- (void)tagReaderSession:(NFCTagReaderSession *)session didInvalidateWithError:(NSError *)error {
    NSLog(@"NFC session did invalidate with error: %@", error.localizedDescription);
}

@end

And also my .entitlements:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.nfc.readersession.formats</key>
    <array>
        <string>TAG</string>
        <string>NDEF</string>
    </array>
</dict>
</plist>

And my Info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NFCReaderUsageDescription</key>
    <string>Need NFC to scan</string>
    <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
    <array>
        <string>A000000116071</string>
    </array>
</dict>
</plist>

The log when executing this on my iPhone 15 Pro Max (iOS 17.5.1):

NFC session did become active
-[NFCTagReaderSession _connectTag:error:]:744 Error Domain=NFCError Code=2 "Missing required entitlement"
UserInfo={NSLocalizedDescription=Missing required entitlement}
Connected: <NFCISO7816Tag: 0x30159d300>
Error sending read certificate APDU: Session invalidated
NFC session did invalidate with error: Session invalidated by user

So question is, why does it connect to the card, but then invalidate the session right after?

Any help is appreciated, I`m out of ideas!


Solution

  • So I finally found the problem. By adding the correct AID to Info.plist, the connection to the PIV card is established and APDU commands can be executed.

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>NFCReaderUsageDescription</key>
        <string>Need NFC to scan</string>
        <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
        <array>
            <string>A00000030800001000</string>
        </array>
    </dict>
    </plist>