[strongSwan] Improve interoperability - signature validation failed, looking for another key

Carlos Velasco carlos.velasco at nimastelecom.com
Sat Sep 24 00:55:34 CEST 2022


Hello,

I came across this problem when migrating a L2L VPN (VTI) from PSK to Digital Certificates, between Strongswan 5.9.7 and Cisco Firepower 7.0.4

Problem:
After switching to certificate (auth=pubkey, ...) this error showed up in Strongswan:
signature validation failed, looking for another key

During troubleshooting I found this issue:
https://wiki.strongswan.org/issues/3059
===
Don't know what that is, but maybe you configured something incorrectly there or the implementation does something wrong when it produces the signature value. One possible cause could be if it doesn't use SHA-1 for the signature (it's the only hash algorithm strongSwan uses for the legacy IKEv2 RSA authentication, i.e. if RFC 7427 is not supported/used by the peer)
===

And also, in Cisco:
https://bst.cisco.com/quickview/bug/CSCuw01249 (Enhancement request to support RFC 7427). Still open (not implemented).
https://bst.cisco.com/quickview/bug/CSCvb21927
===
Cisco Adaptive Security Appliance (ASA) Software
Symptom:
3rd party IKEv2 client will fail to validate authentication response from the ASA when certificates are being used.
For example, Strongswan will return:
"signature validation failed, looking for another key"
Windows native IKEv2 client will return:
"Error 13826: Failed to verify signature"
*Conditions:**
**- PRF SHA2 (SHA256 or SHA512) is in use under "crypto ikev2 policy"*
*Workaround:**
**- Use PRF SHA1**
*- Apple iOS built-in client works with SHA-256 but fails with SHA512
Further Problem Description:
With PRF SHA2 ASA uses SHA2 to sign authentication payload. The rfc7427 say *SHA-1 should be used, but it is not mandatory*.
For the sake of interoperability with 3rd party implementations unable to use SHA2 the following command was introduced:
tunnel-group TUN-GROUP ipsec-attributes
  ikev2 rsa-sig-hash sha1
===

_*In my tests I found out that Cisco uses the same algorithm for RSA Digital Signature than the one agreed PRF in proposal*_.
So, if Strongswan uses proposals = aes256gcm128-prfsha512-ecp521 and Cisco Firepower is using defaults, SHA2-512 is used in PRF and in RSA authentication.
===
charon-systemd[3442731]: received proposals: IKE:AES_GCM_16_256/AES_GCM_16_192/AES_GCM_16_128/PRF_HMAC_SHA2_512/PRF_HMAC_SHA2_384/PRF_HMAC_SHA2_256/PRF_HMAC_SHA1/ECP_521/ECP_384/ECP_256/MODP_4096/MODP_3072/MODP_2048
charon-systemd: charon-systemd[3442731]: configured proposals: IKE:AES_GCM_16_256/PRF_HMAC_SHA2_512/ECP_521
charon-systemd: charon-systemd[3442731]: selected proposal: IKE:AES_GCM_16_256/PRF_HMAC_SHA2_512/ECP_521
...
charon-systemd: charon-systemd[3442731]:   using cached ocsp response
charon-systemd: charon-systemd[3442731]: certificate status is good
charon-systemd: charon-systemd[3442731]:   certificate "C=ES, O=XXX, CN=XXXX" key: 2048 bit RSA
charon-systemd: charon-systemd[3442731]:   reached self-signed root ca with a path length of 0
charon-systemd: charon-systemd[3442731]: signature validation failed, looking for another key
===
This is because Strongswan is using SHA-1 but Cisco is sending SHA2-512.

Actually, it is the rfc7296 the one mentioning SHA-1.
https://www.rfc-editor.org/rfc/rfc7296#section-3.8
===
    RSA Digital Signature                  1
       Computed as specified in Section 2.15 using an RSA private key
       with RSASSA-PKCS1-v1_5 signature scheme specified in [PKCS1]
       (implementers should note that IKEv1 used a different method for
       RSA signatures).  To promote interoperability, implementations
       that support this type *SHOULD* support signatures that use SHA-1
       as the hash function and *SHOULD* use SHA-1 as the default hash
       function when generating signatures.  Implementations can use the
       certificates received from a given peer as a hint for selecting a
       mutually understood hash function for the AUTH payload signature.
       Note, however, that the hash algorithm used in the AUTH payload
       signature doesn't have to be the same as any hash algorithm(s)
       used in the certificate(s).
===

Without RFC 7427 we only have a recommendation (SHOULD), as per RFC 2119
===
3. SHOULD   This word, or the adjective "RECOMMENDED", mean that there
    may exist valid reasons in particular circumstances to ignore a
    particular item, but the full implications must be understood and
    carefully weighed before choosing a different course.
===

So, considering all this, I have made a patch to try SHA2-512, SHA2-384, SHA2-256 if SHA1 fails. It is more a "quick and dirty" patch, sorry, my knowledge of Strongswan internals is limited.
Another approach could be to use the pre-agreed PRF algorithm for RSA Auth, if SHA-1 fails.

With this patch the VPN between Strongswan and Cisco Firepower is successful with any proposal I tested.
===
charon-systemd: charon-systemd[3523065]:   using certificate "C=XX, O=XXXX, CN=XXXX"
charon-systemd: charon-systemd[3523065]:   certificate "C=XX, O=XXXX, CN=XXXX" key: 4096 bit RSA
charon-systemd: charon-systemd[3523065]:   using trusted ca certificate "C=XX, O=XXXX, CN=CAXXXX"
charon-systemd: charon-systemd[3523065]: checking certificate status of "C=XX, O=XXXX, CN=XXXX"
charon-systemd: charon-systemd[3523065]:   ocsp response correctly signed by "C=XX, O=XXXX, CN=OCSPXXXX"
charon-systemd: charon-systemd[3523065]:   ocsp response is valid: until Sep 23 15:54:09 2022
charon-systemd: charon-systemd[3523065]:   using cached ocsp response
charon-systemd: charon-systemd[3523065]: certificate status is good
charon-systemd: charon-systemd[3523065]:   certificate "C=XX, O=XXXX, CN=CAXXXX" key: 2048 bit RSA
charon-systemd: charon-systemd[3523065]:   reached self-signed root ca with a path length of 0
charon-systemd: charon-systemd[3523065]: *authentication of 'C=XX, O=XXXX, CN=XXXX' with RSA_EMSA_PKCS1_SHA1 failed. Retrying with RSA_EMSA_PKCS1_SHA2_512*
charon-systemd: charon-systemd[3523065]:   using certificate "C=XX, O=XXXX, CN=XXXX"
charon-systemd: charon-systemd[3523065]:   certificate "C=XX, O=XXXX, CN=XXXX" key: 4096 bit RSA
charon-systemd: charon-systemd[3523065]:   using trusted ca certificate "C=XX, O=XXXX, CN=CAXXXX"
charon-systemd: charon-systemd[3523065]: checking certificate status of "C=XX, O=XXXX, CN=XXXX"
charon-systemd: charon-systemd[3523065]:   ocsp response correctly signed by "C=XX, O=XXXX, CN=OCSPXXXX"
charon-systemd: charon-systemd[3523065]:   ocsp response is valid: until Sep 23 15:54:09 2022
charon-systemd: charon-systemd[3523065]:   using cached ocsp response
charon-systemd: charon-systemd[3523065]: certificate status is good
  charon-systemd: charon-systemd[3523065]:   certificate "C=XX, O=XXXX, CN=CAXXXX" key: 2048 bit RSA
charon-systemd: charon-systemd[3523065]:   reached self-signed root ca with a path length of 0
charon-systemd: charon-systemd[3523065]: *authentication of 'C=XX, O=XXXX, CN=XXXX with RSA_EMSA_PKCS1_SHA2_512 successful*
===

Patch is attached.

Regards,
Carlos Velasco
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.strongswan.org/pipermail/users/attachments/20220924/91c6ddde/attachment.html>
-------------- next part --------------
diff -ur a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c	2022-07-19 14:14:08.000000000 +0200
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c	2022-09-23 15:46:17.850804518 +0200
@@ -634,6 +634,62 @@
 										  COND_ONLINE_VALIDATION_SUSPENDED);
 	enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
 													key_type, id, auth, online);
+
+	if (auth_method == AUTH_RSA)
+	{
+		while (status == NOT_FOUND)
+		{
+			while (enumerator->enumerate(enumerator, &public, &current_auth))
+			{
+				if (public->verify(public, params->scheme, params->params, octets,
+								   auth_data) &&
+					is_compliant_cert(current_auth))
+				{
+					DBG1(DBG_IKE, "authentication of '%Y' with %N successful", id,
+						signature_scheme_names, params->scheme);
+					status = SUCCESS;
+					auth->merge(auth, current_auth, FALSE);
+					auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
+					auth->add(auth, AUTH_RULE_IKE_SIGNATURE_SCHEME,
+							  signature_params_clone(params));
+					if (!online)
+					{
+						auth->add(auth, AUTH_RULE_CERT_VALIDATION_SUSPENDED, TRUE);
+					}
+					break;
+				}
+				else
+				{
+					if (params->scheme == SIGN_RSA_EMSA_PKCS1_SHA1)
+					{
+						DBG1(DBG_IKE, "authentication of '%Y' with %N failed. Retrying with %N", id,
+							signature_scheme_names, params->scheme, signature_scheme_names, SIGN_RSA_EMSA_PKCS1_SHA2_512);
+						params->scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512;
+						break;
+					}
+					if (params->scheme == SIGN_RSA_EMSA_PKCS1_SHA2_512)
+					{
+						DBG1(DBG_IKE, "authentication of '%Y' with %N failed. Retrying with %N", id,
+							signature_scheme_names, params->scheme, signature_scheme_names, SIGN_RSA_EMSA_PKCS1_SHA2_384);
+						params->scheme = SIGN_RSA_EMSA_PKCS1_SHA2_384;
+						break;
+					}
+					if (params->scheme == SIGN_RSA_EMSA_PKCS1_SHA2_384)
+					{
+						DBG1(DBG_IKE, "authentication of '%Y' with %N failed. Retrying with %N", id,
+							signature_scheme_names, params->scheme, signature_scheme_names, SIGN_RSA_EMSA_PKCS1_SHA2_256);
+						params->scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256;
+						break;
+					}
+					status = FAILED;
+					DBG1(DBG_IKE, "signature validation failed, looking for another key");
+					break;
+				}
+			}
+		}
+	}
+	else
+	{
 	while (enumerator->enumerate(enumerator, &public, &current_auth))
 	{
 		if (public->verify(public, params->scheme, params->params, octets,
@@ -674,6 +730,7 @@
 			DBG1(DBG_IKE, "signature validation failed, looking for another key");
 		}
 	}
+	}
 	enumerator->destroy(enumerator);
 	chunk_free(&octets);
 	signature_params_destroy(params);


More information about the Users mailing list