pátek 5. prosince 2014

Reading of Smart Cards on Apple iOS devices - Part 2

In previous tutorial we have started reading smart card's data using Thursby's PKard reader and their SDK. We can read data from "Printed Information" and get data of facial image. Let's start to read from "CHUID". 

CHUID - Card Holder Unique Identifier 


The CHUID is defined to provide the basis for interoperable identification of individuals and to extend capabilities over magnetic stripe technology for Physical Access Control System applications. It contains a series of mandatory and optional tagged objects. Some of these include the Federal Agency Smart Credential Number (FASC-N), the Global Unique ID (GUID), and the Asymmetric Signature. 















FASC-N 


Let's dive deeper into grabbing FASC-N data. First step is to get CHUID data.

// CHUID
TSS_PKI_Data *CHUID = [TSS_PKI_Data dataObjectWithName:@"CHUID"];

Next step is to get NSData of FASC-N.

if (CHUID) {
   // FASC-N
   NSData *FASCN = [CHUID dataWithBerTlvTag:0x30];
   
   ...
}


Now it's necessary to get string format of FASC-N from NSData. It needs 3 steps to do it.
1) Convert FASC-N NSData to binary string. It should looks like this: "110101001110011....."
2) Divide this binary string into parts each 5 characters long.
3) Replace with corresponding character due to this part of code:
    
// The 40-character FASC-N credential is encoded as a 200 bit (25-byte) record    
// Packed BCD 4-Bit Decimal Format with Odd Parity.
         if ([bits isEqualToString:@"00001"]) return @"0";
    else if ([bits isEqualToString:@"10000"]) return @"1";
    else if ([bits isEqualToString:@"01000"]) return @"2";
    else if ([bits isEqualToString:@"11001"]) return @"3";
    else if ([bits isEqualToString:@"00100"]) return @"4";
    else if ([bits isEqualToString:@"10101"]) return @"5";
    else if ([bits isEqualToString:@"01101"]) return @"6";
    else if ([bits isEqualToString:@"11100"]) return @"7";
    else if ([bits isEqualToString:@"00010"]) return @"8";
    else if ([bits isEqualToString:@"10011"]) return @"9";
    else if ([bits isEqualToString:@"11010"]) return @"S"; // Start Sentinel
    else if ([bits isEqualToString:@"10110"]) return @"F"; // Field Separator

    else if ([bits isEqualToString:@"11111"]) return @"E"; // End Sentinel




















Final string format of FASC-N should looks like this: "S9999F9999F999999F1F1F1234567890199991E8"But how to interpret this string? I found all important informations in documentation in TIG SCEPACS v2.3 by the Physical Access Interagency Interoperability Working Group, December 20, 2005.  - Refer to section 6.1

You will find all informations about FASC-N in the documentation. Here we have FASC-N description:





and here we have FASC-N field description:







































Now it's easy to get anything from FASC-N string. Let's take our example string "S9999F9999F999999F1F1F1234567890199991E8", if you want to display Agency code, you have to look at the tables above. You will find, that Agency code is located after start sentinel, which has length of 1 digit. Agency code has 4 digits and it is located after sentinel. Required agency code is 9999. This way, you can continue parsing all the FASC-N string and get required parts of FASC-N. 


GIUD 


Extending our code we can start grabbing GUID data.

// CHUID
TSS_PKI_Data *CHUID = [TSS_PKI_Data dataObjectWithName:@"CHUID"];
NSUUID *UUID = nil;
VLFASCNData *FASCNData = nil;

if (CHUID) {
        
   // FASC-N
   NSData *FASCN = [CHUID dataWithBerTlvTag:0x30];
   if (FASCN) {
      FASCNData = [[VLFASCNData alloc] initWithFASCNData:FASCN];
   }
        
   // GUID
   NSData *GUID = [CHUID dataWithBerTlvTag:0x34];
   if (GUID) {
      // RFC 4122 - conformant UUID value
      UUID = [[NSUUID alloc]initWithUUIDBytes:GUID.bytes];
   }
}


X.509 / X.509 Extension 


At the end of this tutorial, here is example code how to grab subject name, email or Authority Key Identifier (AKI) / Subject Key Identifier (SKI) from X.509 extension.

NSArray *certs = [TSS_PKI_Identity currentIdentitiesWithAssertion:kAssertCertificateKeyUsageDigitalSignature];

NSString *subjectName;
NSString *emailAddress;
NSData *dataAKI;
NSData *dataSKI;
        
if ( certs.count > 0 ) {
            
   TSS_PKI_Identity *signatureCert = certs[0];
   subjectName = signatureCert.certificate.subjectName;
   emailAddress = signatureCert.certificate.subjectAltNames[X509SubjectAltNameRFC822];
            
   // Authority Key Identifier & Subject Key Identifier
   X509 *inCert = signatureCert.certificate.nativeX509;
   X509_EXTENSION *authorityKeyIdentifier = getExtensionFromCert(inCert, NID_authority_key_identifier);
   X509_EXTENSION *subjectKeyIdentifier = getExtensionFromCert(inCert, NID_subject_key_identifier);
            
   if (authorityKeyIdentifier) {
      dataAKI = [NSData dataWithBytes:authorityKeyIdentifier->value->data length:authorityKeyIdentifier->value->length];
   }
            
   if (subjectKeyIdentifier) {
       dataSKI = [NSData dataWithBytes:subjectKeyIdentifier->value->data length:subjectKeyIdentifier->value->length];
   }
}

It takes a time to get all the informations about reading specific data from smart card. I hope these tutorials will help you with development for iOS devices which needs to grab data from smart cards.

Reading of Smart Cards on Apple iOS devices - Part 1


In this tutorial, I would like to show you, how to read data from smart cards using iOS devices. First, what we need is to connect our iPhone / iPad with hardware device for reading smart cards and SDK to develop our own application. We have used PKard Reader from Thursby Software which is available in several form factors. 

Thursby Software's PKard Reader support the major standard smart card formats including PIV and PIV-I smart cards, the CAC / CAC Dual Persona (
Common Access Card) used by the U.S. military and DOD (Department of Defense).




Using Thursby's PKard Reader and PKard Toolkit for iOS, we can start reading data from smart card. I will show you how to read data from smart card's "Printed information", "CHUID" and get image data from "Facial Image".


Printed information

















// Printed Infromation
TSS_PKI_Data *printedInfo = [TSS_PKI_Data dataObjectWithName:@"Printed Information"];
        
if (printedInfo) {
            
  NSData *nameData = [printedInfo dataWithBerTlvTag:1];
  NSString *name = [[NSString alloc] initWithData:nameData encoding:NSUTF8StringEncoding];
  
  // other tags 
  NSData *employeeAffiliationData = [printedInfo dataWithBerTlvTag:2];
  NSData *expirationDateData = [printedInfo dataWithBerTlvTag:4];
  NSData *agencyCardSerialNumberData = [printedInfo dataWithBerTlvTag:5];
  NSData *issuerIdentificationData = [printedInfo dataWithBerTlvTag:6];
  NSData *organizationAffiliation1Data = [printedInfo dataWithBerTlvTag:7];
  NSData *organizationAffiliation2Data = [printedInfo dataWithBerTlvTag:8];
}


Facial image

If you need to get facial image data, you can do it like this:

// Facial image
NSData *facialImageData = nil;
TSS_PKI_Data *pkiFacialImageData = [TSS_PKI_Data dataObjectWithName:@"Facial Image"];
if (pkiFacialImageData) {
   NSData *cbeffData = [pkiFacialImageData cbeffData];
   
   if (cbeffData) {
      NistBiometricExchangeFormat *cbeff = [[NistBiometricExchangeFormat alloc] initWithCBEFFData:cbeffData];
      facialImageData = cbeff.jpeg;
   }
}

You can find sample project which is included in PKard Toolkit. In case, there are things you are not able to find in documentation, ask Thursby for the answer. Their support works great.

Next part we will read data from "CHUID" especially reading and formating FASC-N, GUID and from X509 extension Authority Key Identifier.