Can't establish VPN connection, VPN profile not verify certificate .p12.

Hello.
I am trying create VPN programmatically, because I am need enable and disable it from App but I have some problem when do it.
First when I am download file ( client.mobileconfig ) and then install to iPhone vpn works good but I can't control state of VPN.

I am was examine this file, using program "Apple Configurator 2" and create profile of vpn programmatically, but when I am want connect to VPN, I am saw this error ONLY first time then I am don't see any errors:

Connection 8: received failure notification

nwflowaddwriterequest [C8.1 (Ip&Port) failed channel-flow (satisfied (Path is satisfied), viable, interface: en0, ipv4, dns)] cannot accept write requests

nwwriterequest_report [C8] Send failed with error "Socket is not connected"

Connection 5: received failure notification
Connection 5: failed to connect 1:53, reason -1
Connection 5: encountered error(1:53)
Connection 4: received failure notification
Connection 4: failed to connect 1:53, reason -1
Connection 4: encountered error(1:53)
Connection 1: received failure notification
Connection 1: failed to connect 1:53, reason -1
Connection 1: encountered error(1:53)
Connection 2: received failure notification
Connection 2: failed to connect 1:53, reason -1
Connection 2: encountered error(1:53)
Connection 3: received failure notification
Connection 3: failed to connect 1:53, reason -1
Connection 3: encountered error(1:53)
Connection 6: received failure notification
Connection 6: failed to connect 1:53, reason -1
Connection 6: encountered error(1:53)

This Is My code:

Code Block
 let vpnManager = NEVPNManager.shared()
   
  func initVPNTunnelProviderManager() {
    print("CALL LOAD TO PREFERENCES...")
    self.vpnManager.loadFromPreferences { (error) -> Void in
      if((error) != nil) {
        print("VPN Preferences error: 1 - \(error)")
      } else {
        let IKEv2Protocol = NEVPNProtocolIKEv2()
         
        IKEv2Protocol.authenticationMethod = .certificate
        IKEv2Protocol.serverAddress = self.vpnServerAddress
        IKEv2Protocol.remoteIdentifier = self.vpnRemoteIdentifier
        IKEv2Protocol.localIdentifier = self.vpnLocalIdentifier
        IKEv2Protocol.useExtendedAuthentication = false
        IKEv2Protocol.ikeSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM
        IKEv2Protocol.ikeSecurityAssociationParameters.diffieHellmanGroup = .group20
        IKEv2Protocol.ikeSecurityAssociationParameters.integrityAlgorithm = .SHA512
        IKEv2Protocol.ikeSecurityAssociationParameters.lifetimeMinutes = 1440
        IKEv2Protocol.childSecurityAssociationParameters.encryptionAlgorithm = .algorithmAES256GCM
        IKEv2Protocol.childSecurityAssociationParameters.diffieHellmanGroup = .group20
        IKEv2Protocol.childSecurityAssociationParameters.integrityAlgorithm = .SHA512
        IKEv2Protocol.childSecurityAssociationParameters.lifetimeMinutes = 1440
        IKEv2Protocol.deadPeerDetectionRate = .medium
        IKEv2Protocol.disableRedirect = true
        IKEv2Protocol.disableMOBIKE = false
        IKEv2Protocol.enableRevocationCheck = false
        IKEv2Protocol.enablePFS = true
        IKEv2Protocol.useConfigurationAttributeInternalIPSubnet = false
        IKEv2Protocol.serverCertificateIssuerCommonName = self.vpnServerCertificateIssuerCommonName
        IKEv2Protocol.disconnectOnSleep = false
        IKEv2Protocol.certificateType = .ECDSA384
        IKEv2Protocol.identityDataPassword = self.p12Password
        IKEv2Protocol.identityData = self.dataFromFile() as Data
        self.vpnManager.protocolConfiguration = IKEv2Protocol
        self.vpnManager.localizedDescription = "Safe Login Configuration"
        self.vpnManager.isEnabled = true
        self.vpnManager.isOnDemandEnabled = true
        //Set rules
        var rules = [NEOnDemandRule]()
        let rule = NEOnDemandRuleConnect()
        rule.interfaceTypeMatch = .any
        rules.append(rule)
        //SAVE TO PREFERENCES...
        self.vpnManager.saveToPreferences(...)
      }
    } //END OF .loadFromPreferences //
  }
   
  func dataFromFile() -> NSData{
    let rootCertPath = Bundle.main.path(forResource: "client", ofType: "p12")
    let certficiateData = NSData(contentsOfFile: rootCertPath!)
    return certficiateData!
  }


If I am change this line of code:
Code Block
IKEv2Protocol.identityDataPassword = self.p12Password
IKEv2Protocol.identityData = self.dataFromFile() as Data

on this verifying method:
Code Block
IKEv2Protocol.identityReference = self.identityReference()
private func identityReference() -> Data {
    let rootCertPath = Bundle.main.path(forResource: "client", ofType: "p12")
    let certficiateData = NSData(contentsOfFile: rootCertPath!)
     
    var importResult: CFArray? = nil
    let err = SecPKCS12Import(certficiateData! as NSData, [
      kSecImportExportPassphrase: p12Password
    ] as NSDictionary, &importResult)
    guard err == errSecSuccess else { fatalError() }
    let importArray = importResult! as! [[String:Any]]
    let identity = importArray[0][kSecImportItemIdentity as String]! as! SecIdentity
    var copyResult: CFTypeRef? = nil
    let err2 = SecItemCopyMatching([
      kSecValueRef: identity,
      kSecReturnPersistentRef: true
    ] as NSDictionary, &copyResult)
    guard err2 == errSecSuccess else { fatalError() } // Here I am see fatal error here
    return copyResult! as! Data
  }


I am obtain fatal error and I am don't understand where I did mistake.

What is my problem? I can't find information about this mistakes.
If need I am attach "client.mobileconfig" file.
Answered by Systems Engineer in 638341022

I am obtain fatal error and I am don't understand where I did mistake.

Code Block swift
var copyResult: CFTypeRef? = nil
let err2 = SecItemCopyMatching([
kSecValueRef: identity,
kSecReturnPersistentRef: true
] as NSDictionary, &copyResult)
guard err2 == errSecSuccess else { fatalError() } // Here I am see fatal error here


There could be a few different things going on here, but my advice would be to take a look at what's going on with kSecValueRef: identity, in SecItemCopyMatching. This is typically done when adding an identity to the keychain, not getting the identity from the keychain as SecItemCopyMatching is used for. Also, adding and getting an identity from the keychain can be a challenge. When debugging this I usually recommend:

1) Printing out the error codes after running keychain operations and if they are not what you expect then return from the function. -25300 will mean errSecItemNotFound, -25299 will mean errSecDuplicateItem.

2) Understanding the lifecycle of an identity in the keychain. The identity contains two assets, a key and n certificates, usually 1. When adding an identity to the keychain both assets will be added separately and a certificate cannot be added as a duplicate due to unique constraints. Keep this in mind if you encounter -25299.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Accepted Answer

I am obtain fatal error and I am don't understand where I did mistake.

Code Block swift
var copyResult: CFTypeRef? = nil
let err2 = SecItemCopyMatching([
kSecValueRef: identity,
kSecReturnPersistentRef: true
] as NSDictionary, &copyResult)
guard err2 == errSecSuccess else { fatalError() } // Here I am see fatal error here


There could be a few different things going on here, but my advice would be to take a look at what's going on with kSecValueRef: identity, in SecItemCopyMatching. This is typically done when adding an identity to the keychain, not getting the identity from the keychain as SecItemCopyMatching is used for. Also, adding and getting an identity from the keychain can be a challenge. When debugging this I usually recommend:

1) Printing out the error codes after running keychain operations and if they are not what you expect then return from the function. -25300 will mean errSecItemNotFound, -25299 will mean errSecDuplicateItem.

2) Understanding the lifecycle of an identity in the keychain. The identity contains two assets, a key and n certificates, usually 1. When adding an identity to the keychain both assets will be added separately and a certificate cannot be added as a duplicate due to unique constraints. Keep this in mind if you encounter -25299.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Can't establish VPN connection, VPN profile not verify certificate .p12.
 
 
Q