Failing certificate on Client Authentication

Hello, we are developing an application that uses TLS client authentication with self-signed certificate. The app has multiple targets, including iOS and macOS clients. However, we are encountering issues with the client certificate on both platforms. Specifically, the client certificate is being rejected when making a URLRequest, and an AuthChallenge is triggered. The strange part is that the TLS handshake fails for every target except one iOS target, making it unclear whether the issue lies with the server or the system.

Flow

  • The connection uses TLS with Client Authentication. User is authenticated by client certificate, that is issued when user signs in. The certificate is self-signed. It is decoded from PKCS#12 blob into Swift.Data and then successfully imported with SecPKCS12Import. The Keychain uses access groups (separate for each target), kSecAttrSynchronizable is set to false and the items are accessible .afterFirstUnlock.
  • The certificate is used for two types of connections - 1) Basic query request 2) Periodic status report
    • First type of request never fails - it is successful, the problem arises with second type of requests.
  • If the certificate is expired on didReceive challenge: URLAuthenticationChallenge, it is refreshed and then provided for verification with URLCredential

Issue

  • With default target everything works as expected. The issue arose when another targets with the same functionality (Different UI, Access Group, Bundle identifier) were added (different xcodeproj or same). Importing certificate is successful as are basic query requests. The issue are with the second type of requests - Periodic status report. Whenever this request is sent via URLSession, it fails.

Here is the output in Xcode console:

- boringssl_context_handle_fatal_alert(2072) [C1.1.1.1:2][0x13c0755a0] read alert, level: fatal, description: bad certificate
- nw_read_request_report [C1] Receive failed with error "bad certificate format"
- boringssl_session_handshake_error_print(44) [C1.1.1.1:2][0x13c0755a0] Error: 5266350496:error:10000412:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_CERTIFICATE:/AppleInternal/Library/BuildRoots/a8fc4767-fd9e-11ee-8f2e-b26cde007628/Library/Caches/com.apple.xbs/Sources/boringssl/ssl/tls_record.cc:592:SSL alert number 42
- “Task <..>.<1> finished with error [-1202] Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “<redacted>” which could put your confidential information at risk.”“


The certificate is in fact not invalid, since it works as expected for the other type of request and with the one specific target Here is the output from Console.app

I also noticed an additional error when I specifically searched for errors in Console.app. I'm not sure if it's connected, though it doesn't seem likely, as this error appears far more frequently than the requests.


| Security	| com.apple.security      | trustd	| SecKeyVerifySignature failed: Error Domain=NSOSStatusErrorDomain Code=-67808 "RSA signature verification failed, no match" UserInfo={numberOfErrorsDeep=0, NSDescription=RSA signature verification failed, no match}	debug	21:56:54.822609+0200
|  Security	|  com.apple.security	|  trustd	|  SecKeyVerifySignature failed: Error Domain=NSOSStatusErrorDomain Code=-50 "rsa_pub_crypt failed, ccerr=-7" (paramErr: error in user parameter list) UserInfo={numberOfErrorsDeep=0, NSDescription=rsa_pub_crypt failed, ccerr=-7}	debug	21:56:43.954898+0200

On iOS an additional error appears.



SecKeyVerifySignature failed: Error Domain=NSOSStatusErrorDomain Code=-50 "<SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 4, 2048 bits (block size: 256), exponent: {hex: 10001, decimal: 65537}, modulus: F12EA3…97D85C5, addr: 0x7eca128c0>: sign - input buffer bad size (264 bytes)" UserInfo={numberOfErrorsDeep=0, NSDescription=<SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 4, 2048 bits (block size: 256), exponent: {hex: 10001, decimal: 65537}, modulus: F12EA31…A835FA7B

With the message that says, "The certificate for this server is invalid...," it appears that the server certificate is failing. However, as mentioned, it works for another target that uses the exact same endpoint. When making a simple GET request to this endpoint, it passes as expected, probably since client certificate is not requested. I also checked the trust result on AuthenticationChallenge and it was successful.

Could this be an issue with the client/server certificate itself? Or perhaps with how the client certificate is being handled—such as storing it inside the keychain, possible collisions? Thank you for your response.

UPDATE:

We have found out that changing the identifier of non-working app to the bundle identifier of the working app resolves the issue (and introduces changing from working to non-working bundle id).

With this information we then looked at app settings, app privacy and App Store Connect settings - especially profiles, identifiers, capabilities and certificates, but did not see any difference there or anything suspicious of the issue.

Failing certificate on Client Authentication
 
 
Q