From 29365e7e1231b13c34d9cd55e3c3272d4c38223c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kelemen=20Jeno=CC=8B?= Date: Mon, 13 Sep 2021 15:52:40 +0200 Subject: [PATCH 1/3] Read passport via bacHash. --- Sources/NFCPassportReader/BACHandler.swift | 50 ++++++++++++--- Sources/NFCPassportReader/PACEHandler.swift | 33 +++++++++- .../NFCPassportReader/PassportReader.swift | 63 +++++++++++++++---- 3 files changed, 122 insertions(+), 24 deletions(-) diff --git a/Sources/NFCPassportReader/BACHandler.swift b/Sources/NFCPassportReader/BACHandler.swift index 45b12fdc..e65e8040 100644 --- a/Sources/NFCPassportReader/BACHandler.swift +++ b/Sources/NFCPassportReader/BACHandler.swift @@ -32,26 +32,44 @@ public class BACHandler { public init(tagReader: TagReader) { self.tagReader = tagReader } - + public func performBACAndGetSessionKeys( mrzKey : String, completed: @escaping (_ error : NFCPassportReaderError?)->() ) { guard let tagReader = self.tagReader else { - completed( NFCPassportReaderError.NoConnectedTag) + completed(.NoConnectedTag) return } - Log.debug( "BACHandler - deriving Document Basic Access Keys" ) - do { - _ = try self.deriveDocumentBasicAccessKeys(mrz: mrzKey) - } catch { - Log.error( "ERROR - \(error.localizedDescription)" ) - completed( NFCPassportReaderError.InvalidDataPassed("Unable to derive BAC Keys - \(error.localizedDescription)") ) + _ = 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 + getChallenge(completed: completed) + } + + public func performBACAndGetSessionKeys( bacHash : [UInt8], completed: @escaping (_ error : NFCPassportReaderError?)->() ) { + guard let tagReader = self.tagReader else { + completed(.NoConnectedTag) return - } + _ = try? deriveDocumentBasicAccessKeys(bacHash: bacHash) + // 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 + getChallenge(completed: completed) + } + + private func getChallenge(completed: @escaping (_ error : NFCPassportReaderError?)->() ) { + + guard let tagReader = self.tagReader else { + completed( NFCPassportReaderError.NoConnectedTag) + return + } + // get Challenge Log.debug( "BACHandler - Getting initial challenge" ) tagReader.getChallenge() { [unowned self] (response, error) in @@ -98,6 +116,20 @@ public class BACHandler { return (ksenc, ksmac) } + func deriveDocumentBasicAccessKeys(bacHash: [UInt8]) throws -> ([UInt8], [UInt8]) { + + let kseed = Array(bacHash[0..<16]) + let smskg = SecureMessagingSessionKeyGenerator() + self.ksenc = try smskg.deriveKey(keySeed: kseed, mode: .ENC_MODE) + self.ksmac = try smskg.deriveKey(keySeed: kseed, mode: .MAC_MODE) + //let (kenc, kmac) = computeKeysFromKseed(Kseed: kseed) + //self.ksenc = kenc + //self.ksmac = kmac + debugPrint("ertejkjtberjbktjbketrbjterbjbejejrejrt") + + return (ksenc, ksmac) + } + /// /// Calculate the kseed from the kmrz: /// - Calculate a SHA-1 hash of the kmrz diff --git a/Sources/NFCPassportReader/PACEHandler.swift b/Sources/NFCPassportReader/PACEHandler.swift index f8302ff2..0c5c50f2 100644 --- a/Sources/NFCPassportReader/PACEHandler.swift +++ b/Sources/NFCPassportReader/PACEHandler.swift @@ -22,7 +22,6 @@ private enum PACEHandlerError { switch self { case .DHKeyAgreementError(let errMsg): return errMsg case .ECDHKeyAgreementError(let errMsg): return errMsg - } } } @@ -61,6 +60,9 @@ public class PACEHandler { private var digestAlg : String = "" private var keyLength : Int = -1 + private var mrzKey: String? + private var bacHash: [UInt8]? + public init(cardAccess : CardAccess, tagReader: TagReader) throws { self.tagReader = tagReader @@ -72,7 +74,18 @@ public class PACEHandler { isPACESupported = true } - public func doPACE( mrzKey : String, completed: @escaping (Bool)->() ) { + public func doPace(mrzKey: String, completed: @escaping (Bool)->()) { + + self.mrzKey = mrzKey + doPACE(completed: completed) + } + + public func doPace(bacHash: [UInt8], completed: @escaping (Bool)->()) { + self.bacHash = bacHash + doPACE(completed: completed) + } + + private func doPACE(completed: @escaping (Bool)->() ) { guard isPACESupported else { completed( false ) return @@ -93,7 +106,12 @@ public class PACEHandler { keyLength = try paceInfo.getKeyLength() // Get key length the enc cipher. Either 128, 192, or 256. paceKeyType = PACEHandler.MRZ_PACE_KEY_REFERENCE - paceKey = try createPaceKey( from: mrzKey ) + + if let mrzKey = mrzKey { + paceKey = try createPaceKey( from: mrzKey ) + } else if let bacHash = bacHash { + paceKey = try createPaceKey(from: bacHash) + } // Temporary logging Log.verbose("doPace - inpit parameters" ) @@ -642,6 +660,15 @@ extension PACEHandler { return key } + func createPaceKey( from bacHash: [UInt8] ) throws -> [UInt8] { + //let buf: [UInt8] = bacHash//Array(bacHash[0..<16]) + let hash = bacHash//Array(bacHash[0..<16])//calcSHA1Hash(bacHash) + + let smskg = SecureMessagingSessionKeyGenerator() + let key = try smskg.deriveKey(keySeed: hash, cipherAlgName: cipherAlg, keyLength: keyLength, nonce: nil, mode: .PACE_MODE, paceKeyReference: paceKeyType) + return key + } + /// Performs the ECDH PACE GM key agreement protocol by multiplying a private key with a public key /// - Parameters: /// - key: an EVP_PKEY structure containng a ECDH private key diff --git a/Sources/NFCPassportReader/PassportReader.swift b/Sources/NFCPassportReader/PassportReader.swift index c8c4584a..c29c09f8 100644 --- a/Sources/NFCPassportReader/PassportReader.swift +++ b/Sources/NFCPassportReader/PassportReader.swift @@ -29,7 +29,8 @@ public class PassportReader : NSObject { private var bacHandler : BACHandler? private var caHandler : ChipAuthenticationHandler? private var paceHandler : PACEHandler? - private var mrzKey : String = "" + private var mrzKey : String? + private var bacHash : [UInt8]? private var dataAmountToReadOverride : Int? = nil private var scanCompletedHandler: ((NFCPassportModel?, NFCPassportReaderError?)->())! @@ -59,10 +60,22 @@ public class PassportReader : NSObject { public func overrideNFCDataAmountToRead( amount: Int ) { dataAmountToReadOverride = amount } + + public func readPassport( bacHash : [UInt8], tags: [DataGroupId] = [], skipSecureElements :Bool = true, customDisplayMessage: ((NFCViewDisplayMessage) -> String?)? = nil, completed: @escaping (NFCPassportModel?, NFCPassportReaderError?)->()) { + + self.bacHash = bacHash + readPassport(tags: tags, skipSecureElements: skipSecureElements, customDisplayMessage: customDisplayMessage, completed: completed) + } + + public func readPassport( mrzKey : String, tags: [DataGroupId] = [], skipSecureElements :Bool = true, customDisplayMessage: ((NFCViewDisplayMessage) -> String?)? = nil, completed: @escaping (NFCPassportModel?, NFCPassportReaderError?)->()) { - public func readPassport( mrzKey : String, tags: [DataGroupId] = [], skipSecureElements :Bool = true, skipCA : Bool = false, skipPACE: Bool = false, customDisplayMessage: ((NFCViewDisplayMessage) -> String?)? = nil, completed: @escaping (NFCPassportModel?, NFCPassportReaderError?)->()) { - self.passport = NFCPassportModel() self.mrzKey = mrzKey + readPassport(tags: tags, skipSecureElements: skipSecureElements, customDisplayMessage: customDisplayMessage, completed: completed) + } + + private func readPassport(tags: [DataGroupId] = [], skipSecureElements :Bool = true, skipCA : Bool = true, skipPACE: Bool = false, customDisplayMessage: ((NFCViewDisplayMessage) -> String?)? = nil, completed: @escaping (NFCPassportModel?, NFCPassportReaderError?)->()) { + self.passport = NFCPassportModel() + //self.mrzKey = mrzKey self.skipCA = skipCA self.skipPACE = skipPACE @@ -356,10 +369,22 @@ extension PassportReader { Log.info( "Starting Basic Access Control (BAC)" ) self.bacHandler = BACHandler( tagReader: tagReader ) - bacHandler?.performBACAndGetSessionKeys( mrzKey: mrzKey ) { error in + if let bacHash = bacHash { + bacHandler?.performBACAndGetSessionKeys( bacHash: bacHash ) { error in + self.bacHandler = nil + completed(error) + } + } + else if let mrzKey = mrzKey { + bacHandler?.performBACAndGetSessionKeys( mrzKey: mrzKey ) { error in + self.bacHandler = nil + completed(error) + } + } + /*bacHandler?.performBACAndGetSessionKeys( mrzKey: mrzKey ) { error in self.bacHandler = nil completed(error) - } + }*/ } func handlePACE( cardAccess:CardAccess, completed: @escaping (NFCPassportReaderError?)->()) { @@ -372,14 +397,28 @@ extension PassportReader { do { self.paceHandler = try PACEHandler( cardAccess: cardAccess, tagReader: tagReader ) - paceHandler?.doPACE(mrzKey: mrzKey ) { paceSucceeded in - if paceSucceeded { - completed(nil) - } else { - self.paceHandler = nil - completed(NFCPassportReaderError.InvalidDataPassed("PACE Failed")) - } + + if let mrzKey = self.mrzKey { + paceHandler?.doPace(mrzKey: mrzKey, completed: { paceSucceeded in + + if paceSucceeded { + completed(nil) + } else { + self.paceHandler = nil + completed(NFCPassportReaderError.InvalidDataPassed("PACE Failed")) + } + }) + } else if let bacHash = self.bacHash { + paceHandler?.doPace(bacHash: bacHash, completed: { paceSucceeded in + if paceSucceeded { + completed(nil) + } else { + self.paceHandler = nil + completed(NFCPassportReaderError.InvalidDataPassed("PACE Failed")) + } + }) } + } catch let error as NFCPassportReaderError { completed( error ) } catch { From e2b15f421876a0e649f9739d4eaca38f3b74deca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kelemen=20Jeno=CC=8B?= Date: Mon, 13 Sep 2021 15:57:19 +0200 Subject: [PATCH 2/3] clean --- Sources/NFCPassportReader/BACHandler.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Sources/NFCPassportReader/BACHandler.swift b/Sources/NFCPassportReader/BACHandler.swift index e65e8040..21eaf3cd 100644 --- a/Sources/NFCPassportReader/BACHandler.swift +++ b/Sources/NFCPassportReader/BACHandler.swift @@ -122,11 +122,7 @@ public class BACHandler { let smskg = SecureMessagingSessionKeyGenerator() self.ksenc = try smskg.deriveKey(keySeed: kseed, mode: .ENC_MODE) self.ksmac = try smskg.deriveKey(keySeed: kseed, mode: .MAC_MODE) - //let (kenc, kmac) = computeKeysFromKseed(Kseed: kseed) - //self.ksenc = kenc - //self.ksmac = kmac - debugPrint("ertejkjtberjbktjbketrbjterbjbejejrejrt") - + return (ksenc, ksmac) } From 1996e2a53ed2df68a4dc39e7e4812b4b8b859d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kelemen=20Jeno=CC=8B?= Date: Mon, 13 Sep 2021 16:00:35 +0200 Subject: [PATCH 3/3] clean --- Sources/NFCPassportReader/PassportReader.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Sources/NFCPassportReader/PassportReader.swift b/Sources/NFCPassportReader/PassportReader.swift index c29c09f8..0a33ff77 100644 --- a/Sources/NFCPassportReader/PassportReader.swift +++ b/Sources/NFCPassportReader/PassportReader.swift @@ -381,10 +381,6 @@ extension PassportReader { completed(error) } } - /*bacHandler?.performBACAndGetSessionKeys( mrzKey: mrzKey ) { error in - self.bacHandler = nil - completed(error) - }*/ } func handlePACE( cardAccess:CardAccess, completed: @escaping (NFCPassportReaderError?)->()) {