diff --git a/app/ios/NFCPassportReader-Bridging-Header.h b/app/ios/AwesomeProject-Bridging-Header.h similarity index 100% rename from app/ios/NFCPassportReader-Bridging-Header.h rename to app/ios/AwesomeProject-Bridging-Header.h diff --git a/app/ios/NFCPassportReader.xcodeproj/project.pbxproj b/app/ios/AwesomeProject.xcodeproj/project.pbxproj similarity index 100% rename from app/ios/NFCPassportReader.xcodeproj/project.pbxproj rename to app/ios/AwesomeProject.xcodeproj/project.pbxproj diff --git a/app/ios/NFCPassportReader.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme b/app/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme similarity index 100% rename from app/ios/NFCPassportReader.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme rename to app/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme diff --git a/app/ios/NFCPassportReader.xcworkspace/contents.xcworkspacedata b/app/ios/AwesomeProject.xcworkspace/contents.xcworkspacedata similarity index 100% rename from app/ios/NFCPassportReader.xcworkspace/contents.xcworkspacedata rename to app/ios/AwesomeProject.xcworkspace/contents.xcworkspacedata diff --git a/app/ios/NFCPassportReader.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/ios/AwesomeProject.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from app/ios/NFCPassportReader.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to app/ios/AwesomeProject.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/app/ios/NFCPassportReader/AES_3DES_DESEncryption.swift b/app/ios/AwesomeProject/AES_3DES_DESEncryption.swift similarity index 100% rename from app/ios/NFCPassportReader/AES_3DES_DESEncryption.swift rename to app/ios/AwesomeProject/AES_3DES_DESEncryption.swift diff --git a/app/ios/NFCPassportReader/AppDelegate.h b/app/ios/AwesomeProject/AppDelegate.h similarity index 100% rename from app/ios/NFCPassportReader/AppDelegate.h rename to app/ios/AwesomeProject/AppDelegate.h diff --git a/app/ios/NFCPassportReader/AppDelegate.mm b/app/ios/AwesomeProject/AppDelegate.mm similarity index 100% rename from app/ios/NFCPassportReader/AppDelegate.mm rename to app/ios/AwesomeProject/AppDelegate.mm diff --git a/app/ios/NFCPassportReader/AwesomeProject.entitlements b/app/ios/AwesomeProject/AwesomeProject.entitlements similarity index 100% rename from app/ios/NFCPassportReader/AwesomeProject.entitlements rename to app/ios/AwesomeProject/AwesomeProject.entitlements diff --git a/app/ios/NFCPassportReader/DataGroups/ActiveAuthenticationInfo.swift b/app/ios/AwesomeProject/DataGroups/ActiveAuthenticationInfo.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/ActiveAuthenticationInfo.swift rename to app/ios/AwesomeProject/DataGroups/ActiveAuthenticationInfo.swift diff --git a/app/ios/NFCPassportReader/DataGroups/COM.swift b/app/ios/AwesomeProject/DataGroups/COM.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/COM.swift rename to app/ios/AwesomeProject/DataGroups/COM.swift diff --git a/app/ios/NFCPassportReader/DataGroups/CardAccess.swift b/app/ios/AwesomeProject/DataGroups/CardAccess.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/CardAccess.swift rename to app/ios/AwesomeProject/DataGroups/CardAccess.swift diff --git a/app/ios/NFCPassportReader/DataGroups/ChipAuthenticationInfo.swift b/app/ios/AwesomeProject/DataGroups/ChipAuthenticationInfo.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/ChipAuthenticationInfo.swift rename to app/ios/AwesomeProject/DataGroups/ChipAuthenticationInfo.swift diff --git a/app/ios/NFCPassportReader/DataGroups/ChipAuthenticationPublicKeyInfo.swift b/app/ios/AwesomeProject/DataGroups/ChipAuthenticationPublicKeyInfo.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/ChipAuthenticationPublicKeyInfo.swift rename to app/ios/AwesomeProject/DataGroups/ChipAuthenticationPublicKeyInfo.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup.swift b/app/ios/AwesomeProject/DataGroups/DataGroup.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup1.swift b/app/ios/AwesomeProject/DataGroups/DataGroup1.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup1.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup1.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup11.swift b/app/ios/AwesomeProject/DataGroups/DataGroup11.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup11.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup11.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup12.swift b/app/ios/AwesomeProject/DataGroups/DataGroup12.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup12.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup12.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup14.swift b/app/ios/AwesomeProject/DataGroups/DataGroup14.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup14.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup14.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup15.swift b/app/ios/AwesomeProject/DataGroups/DataGroup15.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup15.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup15.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup2.swift b/app/ios/AwesomeProject/DataGroups/DataGroup2.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup2.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup2.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroup7.swift b/app/ios/AwesomeProject/DataGroups/DataGroup7.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroup7.swift rename to app/ios/AwesomeProject/DataGroups/DataGroup7.swift diff --git a/app/ios/NFCPassportReader/DataGroups/DataGroupId.swift b/app/ios/AwesomeProject/DataGroups/DataGroupId.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/DataGroupId.swift rename to app/ios/AwesomeProject/DataGroups/DataGroupId.swift diff --git a/app/ios/NFCPassportReader/DataGroups/NotImplementedDG.swift b/app/ios/AwesomeProject/DataGroups/NotImplementedDG.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/NotImplementedDG.swift rename to app/ios/AwesomeProject/DataGroups/NotImplementedDG.swift diff --git a/app/ios/NFCPassportReader/DataGroups/PACEInfo.swift b/app/ios/AwesomeProject/DataGroups/PACEInfo.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/PACEInfo.swift rename to app/ios/AwesomeProject/DataGroups/PACEInfo.swift diff --git a/app/ios/NFCPassportReader/DataGroups/SOD.swift b/app/ios/AwesomeProject/DataGroups/SOD.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/SOD.swift rename to app/ios/AwesomeProject/DataGroups/SOD.swift diff --git a/app/ios/NFCPassportReader/DataGroups/SecurityInfo.swift b/app/ios/AwesomeProject/DataGroups/SecurityInfo.swift similarity index 100% rename from app/ios/NFCPassportReader/DataGroups/SecurityInfo.swift rename to app/ios/AwesomeProject/DataGroups/SecurityInfo.swift diff --git a/app/ios/NFCPassportReader/Images.xcassets/AppIcon.appiconset/Contents.json b/app/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from app/ios/NFCPassportReader/Images.xcassets/AppIcon.appiconset/Contents.json rename to app/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json diff --git a/app/ios/NFCPassportReader/Images.xcassets/Contents.json b/app/ios/AwesomeProject/Images.xcassets/Contents.json similarity index 100% rename from app/ios/NFCPassportReader/Images.xcassets/Contents.json rename to app/ios/AwesomeProject/Images.xcassets/Contents.json diff --git a/app/ios/NFCPassportReader/Info.plist b/app/ios/AwesomeProject/Info.plist similarity index 100% rename from app/ios/NFCPassportReader/Info.plist rename to app/ios/AwesomeProject/Info.plist diff --git a/app/ios/NFCPassportReader/NFCViewDisplayMessage.swift b/app/ios/AwesomeProject/NFCViewDisplayMessage.swift similarity index 100% rename from app/ios/NFCPassportReader/NFCViewDisplayMessage.swift rename to app/ios/AwesomeProject/NFCViewDisplayMessage.swift diff --git a/app/ios/NFCPassportReader/OpenSSLUtils.swift b/app/ios/AwesomeProject/OpenSSLUtils.swift similarity index 100% rename from app/ios/NFCPassportReader/OpenSSLUtils.swift rename to app/ios/AwesomeProject/OpenSSLUtils.swift diff --git a/app/ios/NFCPassportReader/PACEHandler.swift b/app/ios/AwesomeProject/PACEHandler.swift similarity index 100% rename from app/ios/NFCPassportReader/PACEHandler.swift rename to app/ios/AwesomeProject/PACEHandler.swift diff --git a/app/ios/NFCPassportReader/PassportReader.swift b/app/ios/AwesomeProject/PassportReader.swift similarity index 100% rename from app/ios/NFCPassportReader/PassportReader.swift rename to app/ios/AwesomeProject/PassportReader.swift diff --git a/app/ios/NFCPassportReader/ResponseAPDU.swift b/app/ios/AwesomeProject/ResponseAPDU.swift similarity index 100% rename from app/ios/NFCPassportReader/ResponseAPDU.swift rename to app/ios/AwesomeProject/ResponseAPDU.swift diff --git a/app/ios/NFCPassportReader/SecureMessaging.swift b/app/ios/AwesomeProject/SecureMessaging.swift similarity index 100% rename from app/ios/NFCPassportReader/SecureMessaging.swift rename to app/ios/AwesomeProject/SecureMessaging.swift diff --git a/app/ios/NFCPassportReader/SecureMessagingSessionKeyGenerator.swift b/app/ios/AwesomeProject/SecureMessagingSessionKeyGenerator.swift similarity index 100% rename from app/ios/NFCPassportReader/SecureMessagingSessionKeyGenerator.swift rename to app/ios/AwesomeProject/SecureMessagingSessionKeyGenerator.swift diff --git a/app/ios/NFCPassportReader/SimpleASN1DumpParser.swift b/app/ios/AwesomeProject/SimpleASN1DumpParser.swift similarity index 100% rename from app/ios/NFCPassportReader/SimpleASN1DumpParser.swift rename to app/ios/AwesomeProject/SimpleASN1DumpParser.swift diff --git a/app/ios/NFCPassportReader/TagReader.swift b/app/ios/AwesomeProject/TagReader.swift similarity index 100% rename from app/ios/NFCPassportReader/TagReader.swift rename to app/ios/AwesomeProject/TagReader.swift diff --git a/app/ios/NFCPassportReader/Utils.swift b/app/ios/AwesomeProject/Utils.swift similarity index 100% rename from app/ios/NFCPassportReader/Utils.swift rename to app/ios/AwesomeProject/Utils.swift diff --git a/app/ios/NFCPassportReader/X509Wrapper.swift b/app/ios/AwesomeProject/X509Wrapper.swift similarity index 100% rename from app/ios/NFCPassportReader/X509Wrapper.swift rename to app/ios/AwesomeProject/X509Wrapper.swift diff --git a/app/ios/NFCPassportReader/main.m b/app/ios/AwesomeProject/main.m similarity index 100% rename from app/ios/NFCPassportReader/main.m rename to app/ios/AwesomeProject/main.m diff --git a/app/ios/NFCPassportReader/masterList.pem b/app/ios/AwesomeProject/masterList.pem similarity index 100% rename from app/ios/NFCPassportReader/masterList.pem rename to app/ios/AwesomeProject/masterList.pem diff --git a/app/ios/NFCPassportReaderTests/AwesomeProjectTests.m b/app/ios/AwesomeProjectTests/AwesomeProjectTests.m similarity index 100% rename from app/ios/NFCPassportReaderTests/AwesomeProjectTests.m rename to app/ios/AwesomeProjectTests/AwesomeProjectTests.m diff --git a/app/ios/NFCPassportReaderTests/Info.plist b/app/ios/AwesomeProjectTests/Info.plist similarity index 100% rename from app/ios/NFCPassportReaderTests/Info.plist rename to app/ios/AwesomeProjectTests/Info.plist diff --git a/app/ios/NFCPassportReader/BACHandler.swift b/app/ios/NFCPassportReader/BACHandler.swift deleted file mode 100644 index d5a05d63c..000000000 --- a/app/ios/NFCPassportReader/BACHandler.swift +++ /dev/null @@ -1,185 +0,0 @@ -import Foundation - -#if !os(macOS) -import CoreNFC - -@available(iOS 15, *) -public class BACHandler { - let KENC : [UInt8] = [0,0,0,1] - let KMAC : [UInt8] = [0,0,0,2] - - public var ksenc : [UInt8] = [] - public var ksmac : [UInt8] = [] - - var rnd_icc : [UInt8] = [] - var rnd_ifd : [UInt8] = [] - public var kifd : [UInt8] = [] - - var tagReader : TagReader? - - public init() { - // For testing only - } - - public init(tagReader: TagReader) { - self.tagReader = tagReader - } - - public func performBACAndGetSessionKeys( mrzKey : String ) async throws { - guard let tagReader = self.tagReader else { - throw NFCPassportReaderError.NoConnectedTag - } - - Log.debug( "BACHandler - deriving Document Basic Access Keys" ) - _ = try self.deriveDocumentBasicAccessKeys(mrz: mrzKey) - - // Make sure we clear secure messaging (could happen if we read an invalid DG or we hit a secure error - tagReader.secureMessaging = nil - - // get Challenge - Log.debug( "BACHandler - Getting initial challenge" ) - let response = try await tagReader.getChallenge() - - Log.verbose( "DATA - \(response.data)" ) - - Log.debug( "BACHandler - Doing mutual authentication" ) - let cmd_data = self.authentication(rnd_icc: [UInt8](response.data)) - let maResponse = try await tagReader.doMutualAuthentication(cmdData: Data(cmd_data)) - Log.debug( "DATA - \(maResponse.data)" ) - guard maResponse.data.count > 0 else { - throw NFCPassportReaderError.InvalidMRZKey - } - - let (KSenc, KSmac, ssc) = try self.sessionKeys(data: [UInt8](maResponse.data)) - tagReader.secureMessaging = SecureMessaging(ksenc: KSenc, ksmac: KSmac, ssc: ssc) - Log.debug( "BACHandler - complete" ) - } - - - func deriveDocumentBasicAccessKeys(mrz: String) throws -> ([UInt8], [UInt8]) { - let kseed = generateInitialKseed(kmrz:mrz) - - Log.verbose("Calculate the Basic Access Keys (Kenc and Kmac) using TR-SAC 1.01, 4.2") - let smskg = SecureMessagingSessionKeyGenerator() - self.ksenc = try smskg.deriveKey(keySeed: kseed, mode: .ENC_MODE) - self.ksmac = try smskg.deriveKey(keySeed: kseed, mode: .MAC_MODE) - - return (ksenc, ksmac) - } - - /// - /// Calculate the kseed from the kmrz: - /// - Calculate a SHA-1 hash of the kmrz - /// - Take the most significant 16 bytes to form the Kseed. - /// @param kmrz: The MRZ information - /// @type kmrz: a string - /// @return: a 16 bytes string - /// - /// - Parameter kmrz: mrz key - /// - Returns: first 16 bytes of the mrz SHA1 hash - /// - func generateInitialKseed(kmrz : String ) -> [UInt8] { - - Log.verbose("Calculate the SHA-1 hash of MRZ_information") - Log.verbose("\tMRZ KEY - \(kmrz)") - let hash = calcSHA1Hash( [UInt8](kmrz.data(using:.utf8)!) ) - - Log.verbose("\tsha1(MRZ_information): \(binToHexRep(hash))") - - let subHash = Array(hash[0..<16]) - Log.verbose("Take the most significant 16 bytes to form the Kseed") - Log.verbose("\tKseed: \(binToHexRep(subHash))" ) - - return Array(subHash) - } - - - /// Construct the command data for the mutual authentication. - /// - Request an 8 byte random number from the MRTD's chip (rnd.icc) - /// - Generate an 8 byte random (rnd.ifd) and a 16 byte random (kifd) - /// - Concatenate rnd.ifd, rnd.icc and kifd (s = rnd.ifd + rnd.icc + kifd) - /// - Encrypt it with TDES and the Kenc key (eifd = TDES(s, Kenc)) - /// - Compute the MAC over eifd with TDES and the Kmax key (mifd = mac(pad(eifd)) - /// - Construct the APDU data for the mutualAuthenticate command (cmd_data = eifd + mifd) - /// - /// @param rnd_icc: The challenge received from the ICC. - /// @type rnd_icc: A 8 bytes binary string - /// @return: The APDU binary data for the mutual authenticate command - func authentication( rnd_icc : [UInt8]) -> [UInt8] { - self.rnd_icc = rnd_icc - - Log.verbose("Request an 8 byte random number from the MRTD's chip") - Log.verbose("\tRND.ICC: " + binToHexRep(self.rnd_icc)) - - self.rnd_icc = rnd_icc - - let rnd_ifd = generateRandomUInt8Array(8) - let kifd = generateRandomUInt8Array(16) - - Log.verbose("Generate an 8 byte random and a 16 byte random") - Log.verbose("\tRND.IFD: \(binToHexRep(rnd_ifd))" ) - Log.verbose("\tRND.Kifd: \(binToHexRep(kifd))") - - let s = rnd_ifd + rnd_icc + kifd - - Log.verbose("Concatenate RND.IFD, RND.ICC and Kifd") - Log.verbose("\tS: \(binToHexRep(s))") - - let iv : [UInt8] = [0, 0, 0, 0, 0, 0, 0, 0] - let eifd = tripleDESEncrypt(key: ksenc,message: s, iv: iv) - - Log.verbose("Encrypt S with TDES key Kenc as calculated in Appendix 5.2") - Log.verbose("\tEifd: \(binToHexRep(eifd))") - - let mifd = mac(algoName: .DES, key: ksmac, msg: pad(eifd, blockSize:8)) - - Log.verbose("Compute MAC over eifd with TDES key Kmac as calculated in-Appendix 5.2") - Log.verbose("\tMifd: \(binToHexRep(mifd))") - // Construct APDU - - let cmd_data = eifd + mifd - Log.verbose("Construct command data for MUTUAL AUTHENTICATE") - Log.verbose("\tcmd_data: \(binToHexRep(cmd_data))") - - self.rnd_ifd = rnd_ifd - self.kifd = kifd - - return cmd_data - } - - /// Calculate the session keys (KSenc, KSmac) and the SSC from the data - /// received by the mutual authenticate command. - - /// @param data: the data received from the mutual authenticate command send to the chip. - /// @type data: a binary string - /// @return: A set of two 16 bytes keys (KSenc, KSmac) and the SSC - public func sessionKeys(data : [UInt8] ) throws -> ([UInt8], [UInt8], [UInt8]) { - Log.verbose("Decrypt and verify received data and compare received RND.IFD with generated RND.IFD \(binToHexRep(self.ksmac))" ) - - let response = tripleDESDecrypt(key: self.ksenc, message: [UInt8](data[0..<32]), iv: [0,0,0,0,0,0,0,0] ) - - let response_kicc = [UInt8](response[16..<32]) - let Kseed = xor(self.kifd, response_kicc) - Log.verbose("Calculate XOR of Kifd and Kicc") - Log.verbose("\tKseed: \(binToHexRep(Kseed))" ) - - let smskg = SecureMessagingSessionKeyGenerator() - let KSenc = try smskg.deriveKey(keySeed: Kseed, mode: .ENC_MODE) - let KSmac = try smskg.deriveKey(keySeed: Kseed, mode: .MAC_MODE) - -// let KSenc = self.keyDerivation(kseed: Kseed,c: KENC) -// let KSmac = self.keyDerivation(kseed: Kseed,c: KMAC) - - Log.verbose("Calculate Session Keys (KSenc and KSmac) using Appendix 5.1") - Log.verbose("\tKSenc: \(binToHexRep(KSenc))" ) - Log.verbose("\tKSmac: \(binToHexRep(KSmac))" ) - - - let ssc = [UInt8](self.rnd_icc.suffix(4) + self.rnd_ifd.suffix(4)) - Log.verbose("Calculate Send Sequence Counter") - Log.verbose("\tSSC: \(binToHexRep(ssc))" ) - return (KSenc, KSmac, ssc) - } - -} -#endif diff --git a/app/ios/NFCPassportReader/ChipAuthenticationHandler.swift b/app/ios/NFCPassportReader/ChipAuthenticationHandler.swift deleted file mode 100644 index d726faabe..000000000 --- a/app/ios/NFCPassportReader/ChipAuthenticationHandler.swift +++ /dev/null @@ -1,216 +0,0 @@ -import Foundation -import OpenSSL - -#if !os(macOS) -import CoreNFC -import CryptoKit - -@available(iOS 15, *) -class ChipAuthenticationHandler { - - private static let NO_PACE_KEY_REFERENCE : UInt8 = 0x00 - private static let ENC_MODE : UInt8 = 0x1 - private static let MAC_MODE : UInt8 = 0x2 - private static let PACE_MODE : UInt8 = 0x3 - - private static let COMMAND_CHAINING_CHUNK_SIZE = 224 - - var tagReader : TagReader? - var gaSegments = [[UInt8]]() - - var chipAuthInfos = [Int:ChipAuthenticationInfo]() - var chipAuthPublicKeyInfos = [ChipAuthenticationPublicKeyInfo]() - - var isChipAuthenticationSupported : Bool = false - - public init(dg14 : DataGroup14, tagReader: TagReader) { - self.tagReader = tagReader - - for secInfo in dg14.securityInfos { - if let cai = secInfo as? ChipAuthenticationInfo { - let keyId = cai.getKeyId() - chipAuthInfos[keyId] = cai - } else if let capki = secInfo as? ChipAuthenticationPublicKeyInfo { - chipAuthPublicKeyInfos.append(capki) - } - } - - if chipAuthPublicKeyInfos.count > 0 { - isChipAuthenticationSupported = true - } - } - - public func doChipAuthentication() async throws { - - Log.info( "Performing Chip Authentication - number of public keys found - \(chipAuthPublicKeyInfos.count)" ) - guard isChipAuthenticationSupported else { - throw NFCPassportReaderError.NotYetSupported( "ChipAuthentication not supported" ) - } - - var success = false - for pubKey in chipAuthPublicKeyInfos { - do { - success = try await self.doChipAuthentication( with: pubKey) - if success { - break - } - } catch { - // try next key - } - } - - if !success { - throw NFCPassportReaderError.ChipAuthenticationFailed - } - } - - private func doChipAuthentication( with chipAuthPublicKeyInfo : ChipAuthenticationPublicKeyInfo ) async throws -> Bool { - - // So it turns out that some passports don't have ChipAuthInfo items. - // So if we do have a ChipAuthInfo the we take the keyId (if present) and OID from there, - // BUT if we don't then we will try to infer the OID from the public key - let keyId = chipAuthPublicKeyInfo.keyId - let chipAuthInfoOID : String - if let chipAuthInfo = chipAuthInfos[keyId ?? 0] { - chipAuthInfoOID = chipAuthInfo.oid - } else { - if let oid = inferOID( fromPublicKeyOID:chipAuthPublicKeyInfo.oid) { - chipAuthInfoOID = oid - } else { - return false - } - } - - try await self.doCA( keyId: keyId, encryptionDetailsOID: chipAuthInfoOID, publicKey: chipAuthPublicKeyInfo.pubKey ) - return true - } - - /// Infer OID from public key type - Best guess seems to be to use 3DES_CBC_CBC for both ECDH and DH keys - /// Apparently works for French passports - private func inferOID(fromPublicKeyOID: String ) -> String? { - if fromPublicKeyOID == SecurityInfo.ID_PK_ECDH_OID { - Log.warning("No ChipAuthenticationInfo - guessing its id-CA-ECDH-3DES-CBC-CBC"); - return SecurityInfo.ID_CA_ECDH_3DES_CBC_CBC_OID - } else if fromPublicKeyOID == SecurityInfo.ID_PK_DH_OID { - Log.warning("No ChipAuthenticationInfo - guessing its id-CA-DH-3DES-CBC-CBC"); - return SecurityInfo.ID_CA_DH_3DES_CBC_CBC_OID - } - - Log.warning("No ChipAuthenticationInfo and unsupported ChipAuthenticationPublicKeyInfo public key OID \(fromPublicKeyOID)") - return nil; - } - - private func doCA( keyId: Int?, encryptionDetailsOID oid: String, publicKey: OpaquePointer) async throws { - - // Generate Ephemeral Keypair from parameters from DG14 Public key - // This should work for both EC and DH keys - var ephemeralKeyPair : OpaquePointer? = nil - let pctx = EVP_PKEY_CTX_new(publicKey, nil) - EVP_PKEY_keygen_init(pctx) - EVP_PKEY_keygen(pctx, &ephemeralKeyPair) - EVP_PKEY_CTX_free(pctx) - - // Send the public key to the passport - try await sendPublicKey(oid: oid, keyId: keyId, pcdPublicKey: ephemeralKeyPair!) - - Log.debug( "Public Key successfully sent to passport!" ) - - // Use our ephemeral private key and the passports public key to generate a shared secret - // (the passport with do the same thing with their private key and our public key) - let sharedSecret = OpenSSLUtils.computeSharedSecret(privateKeyPair:ephemeralKeyPair!, publicKey:publicKey) - - // Now try to restart Secure Messaging using the new shared secret and - try restartSecureMessaging( oid : oid, sharedSecret : sharedSecret, maxTranceiveLength : 1, shouldCheckMAC : true) - } - - private func sendPublicKey(oid : String, keyId : Int?, pcdPublicKey : OpaquePointer) async throws { - let cipherAlg = try ChipAuthenticationInfo.toCipherAlgorithm(oid: oid) - guard let keyData = OpenSSLUtils.getPublicKeyData(from: pcdPublicKey) else { - throw NFCPassportReaderError.InvalidDataPassed("Unable to get public key data from public key" ) - } - - if cipherAlg.hasPrefix("DESede") { - - var idData : [UInt8] = [] - if let keyId = keyId { - idData = intToBytes( val:keyId, removePadding:true) - idData = wrapDO( b:0x84, arr:idData) - } - let wrappedKeyData = wrapDO( b:0x91, arr:keyData) - _ = try await self.tagReader?.sendMSEKAT(keyData: Data(wrappedKeyData), idData: Data(idData)) - } else if cipherAlg.hasPrefix("AES") { - _ = try await self.tagReader?.sendMSESetATIntAuth(oid: oid, keyId: keyId) - let data = wrapDO(b: 0x80, arr:keyData) - gaSegments = self.chunk(data: data, segmentSize: ChipAuthenticationHandler.COMMAND_CHAINING_CHUNK_SIZE ) - try await self.handleGeneralAuthentication() - } else { - throw NFCPassportReaderError.InvalidDataPassed("Cipher Algorithm \(cipherAlg) not supported") - } - } - - private func handleGeneralAuthentication() async throws { - repeat { - // Pull next segment from list - let segment = gaSegments.removeFirst() - let isLast = gaSegments.isEmpty - - // send it - _ = try await self.tagReader?.sendGeneralAuthenticate(data: segment, isLast: isLast) - } while ( !gaSegments.isEmpty ) - } - - private func restartSecureMessaging( oid : String, sharedSecret : [UInt8], maxTranceiveLength : Int, shouldCheckMAC : Bool) throws { - let cipherAlg = try ChipAuthenticationInfo.toCipherAlgorithm(oid: oid) - let keyLength = try ChipAuthenticationInfo.toKeyLength(oid: oid) - - // Start secure messaging. - let smskg = SecureMessagingSessionKeyGenerator() - let ksEnc = try smskg.deriveKey(keySeed: sharedSecret, cipherAlgName: cipherAlg, keyLength: keyLength, mode: .ENC_MODE) - let ksMac = try smskg.deriveKey(keySeed: sharedSecret, cipherAlgName: cipherAlg, keyLength: keyLength, mode: .MAC_MODE) - - let ssc = withUnsafeBytes(of: 0.bigEndian, Array.init) - if (cipherAlg.hasPrefix("DESede")) { - Log.info( "Restarting secure messaging using DESede encryption") - let sm = SecureMessaging(encryptionAlgorithm: .DES, ksenc: ksEnc, ksmac: ksMac, ssc: ssc) - tagReader?.secureMessaging = sm - } else if (cipherAlg.hasPrefix("AES")) { - Log.info( "Restarting secure messaging using AES encryption") - let sm = SecureMessaging(encryptionAlgorithm: .AES, ksenc: ksEnc, ksmac: ksMac, ssc: ssc) - tagReader?.secureMessaging = sm - } else { - Log.error( "Not restarting secure messaging as unsupported cipher algorithm requested - \(cipherAlg)") - throw NFCPassportReaderError.InvalidDataPassed("Unsupported cipher algorithm \(cipherAlg)" ) - } - } - - - func inferDigestAlgorithmFromCipherAlgorithmForKeyDerivation( cipherAlg : String, keyLength : Int) throws -> String { - if cipherAlg == "DESede" || cipherAlg == "AES-128" { - return "SHA1" - } - if cipherAlg == "AES" && keyLength == 128 { - return "SHA1" - } - if cipherAlg == "AES-256" || cipherAlg == "AES-192" { - return "SHA256" - } - if cipherAlg == "AES" && (keyLength == 192 || keyLength == 256) { - return "SHA256" - } - - throw NFCPassportReaderError.InvalidDataPassed("Unsupported cipher algorithm or key length") - } - - /// Chunks up a byte array into a number of segments of the given size, - /// and a final segment if there is a remainder. - /// - Parameter segmentSize the number of bytes per segment - /// - Parameter data the data to be partitioned - /// - Parameter a list with the segments - func chunk( data : [UInt8], segmentSize: Int ) -> [[UInt8]] { - return stride(from: 0, to: data.count, by: segmentSize).map { - Array(data[$0 ..< Swift.min($0 + segmentSize, data.count)]) - } - } -} - -#endif