Issue #3499
ISAKMP Signature hash algorithm / EAP-TLS Authentification
Description
I am trying to delegate authentification to FreeRadius.
My configuration look like this :
keyexchange=ikev2
type=tunnel
leftsourceip=%config
leftauth=eap-tls
left=%any
...
For leftauth there's no option to limit hash algorithms when using eap-tls.
Signature are base on an HSM that can only handle NIST P-256 curve with SHA256.
Exemple :
Jun 29 13:54:23 11[IKE] <si|1> authentication of '...' with ECDSA_WITH_SHA256_DER successful
Jun 29 13:54:23 11[IKE] <si|1> server requested EAP_TLS authentication (id 0x01)
Jun 29 13:54:23 11[ENC] <si|1> generating IKE_AUTH request 2 [ EAP/RES/TLS ]
Jun 29 13:54:23 11[NET] <si|1> sending packet: from 10.111.0.113[4500] to 10.111.0.46[4500] (222 bytes)
Jun 29 13:54:23 12[NET] <si|1> received packet: from 10.111.0.46[4500] to 10.111.0.113[4500] (1065 bytes)
Jun 29 13:54:23 12[ENC] <si|1> parsed IKE_AUTH response 2 [ EAP/REQ/TLS ]
Jun 29 13:54:23 12[TLS] <si|1> negotiated TLS 1.2 using suite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Jun 29 13:54:23 12[ENC] <si|1> generating IKE_AUTH request 3 [ EAP/RES/TLS ]
Jun 29 13:54:23 12[NET] <si|1> sending packet: from 10.111.0.113[4500] to 10.111.0.46[4500] (67 bytes)
Jun 29 13:54:23 13[NET] <si|1> received packet: from 10.111.0.46[4500] to 10.111.0.113[4500] (631 bytes)
Jun 29 13:54:23 13[ENC] <si|1> parsed IKE_AUTH response 3 [ EAP/REQ/TLS ]
Jun 29 13:54:23 13[TLS] <si|1> received TLS server certificate 'C=FR, O=...'
Jun 29 13:54:23 13[CFG] <si|1> using certificate "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> using trusted intermediate ca certificate "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> checking certificate status of "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> using trusted ca certificate "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> reached self-signed root ca with a path length of 0
Jun 29 13:54:24 13[CFG] <si|1> using trusted certificate "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> crl correctly signed by "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> crl is valid: until Jun 23 07:02:39 2035
Jun 29 13:54:24 13[CFG] <si|1> using cached crl
Jun 29 13:54:24 13[CFG] <si|1> certificate status is good
Jun 29 13:54:24 13[CFG] <si|1> using trusted ca certificate "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> checking certificate status of "C=FR, O=..."
Jun 29 13:54:24 13[CFG] <si|1> certificate status is not available
Jun 29 13:54:24 13[CFG] <si|1> reached self-signed root ca with a path length of 1
Jun 29 13:54:24 13[TLS] <si|1> received TLS cert request for unknown CA 'C=FR, O=...'
Jun 29 13:54:24 13[TLS] <si|1> received TLS cert request for unknown CA 'C=FR, O=...'
Jun 29 13:54:24 13[TLS] <si|1> sending TLS peer certificate 'C=FR, O=...'
Jun 29 13:54:24 13[LIB] <si|1> C_Sign() failed: DATA_LEN_RANGE
Jun 29 13:54:24 13[LIB] <si|1> C_Sign() failed: DATA_LEN_RANGE
Jun 29 13:54:24 13[ENC] <si|1> generating IKE_AUTH request 4 [ EAP/RES/TLS ]
Jun 29 13:54:24 13[NET] <si|1> sending packet: from 10.111.0.113[4500] to 10.111.0.46[4500] (1085 bytes)
Jun 29 13:54:24 14[NET] <si|1> received packet: from 10.111.0.46[4500] to 10.111.0.113[4500] (67 bytes)
Jun 29 13:54:24 14[ENC] <si|1> parsed IKE_AUTH response 4 [ EAP/REQ/TLS ]
Jun 29 13:54:24 14[ENC] <si|1> generating IKE_AUTH request 5 [ EAP/RES/TLS ]
Jun 29 13:54:24 14[NET] <si|1> sending packet: from 10.111.0.113[4500] to 10.111.0.46[4500] (339 bytes)
Jun 29 13:54:24 15[NET] <si|1> received packet: from 10.111.0.46[4500] to 10.111.0.113[4500] (162 bytes)
Jun 29 13:54:24 15[ENC] <si|1> parsed IKE_AUTH response 5 [ EAP/REQ/TLS ]
Jun 29 13:54:24 15[ENC] <si|1> generating IKE_AUTH request 6 [ EAP/RES/TLS ]
Jun 29 13:54:24 15[NET] <si|1> sending packet: from 10.111.0.113[4500] to 10.111.0.46[4500] (67 bytes)
Jun 29 13:54:24 16[NET] <si|1> received packet: from 10.111.0.46[4500] to 10.111.0.113[4500] (65 bytes)
Jun 29 13:54:24 16[ENC] <si|1> parsed IKE_AUTH response 6 [ EAP/SUCC ]
Jun 29 13:54:24 16[IKE] <si|1> EAP method EAP_TLS succeeded, MSK established
Jun 29 13:54:24 16[IKE] <si|1> authentication of 'C=FR, O=...' (myself) with EAP
Jun 29 13:54:24 16[ENC] <si|1> generating IKE_AUTH request 7 [ AUTH ]
Jun 29 13:54:24 16[NET] <si|1> sending packet: from 10.111.0.113[4500] to 10.111.0.46[4500] (97 bytes)
Jun 29 13:54:24 07[NET] <si|1> received packet: from 10.111.0.46[4500] to 10.111.0.113[4500] (249 bytes)
Jun 29 13:54:24 07[ENC] <si|1> parsed IKE_AUTH response 7 [ AUTH CPRP(ADDR DNS DNS MASK) SA TSi TSr N(AUTH_LFT) N(MOBIKE_SUP) N(NO_ADD_ADDR) ]
Jun 29 13:54:24 07[IKE] <si|1> authentication of '...' with EAP successful
Because there's no limitation for hash algorithm, the first signature failed (using SHA512) and just after another working attempt is made with SHA256.
History
#1 Updated by Tobias Brunner about 2 years ago
- Status changed from New to Feedback
Is that actually a problem?
#2 Updated by David MAFFRAND about 2 years ago
Yes, it's generating extra messages and we'd like to use our embedded HSM only when it's necessary.
#3 Updated by Tobias Brunner about 2 years ago
Yes, it's generating extra messages
You mean the two C_Sign() failed: DATA_LEN_RANGE
messages?
and we'd like to use our embedded HSM only when it's necessary.
What do you mean? Handling that error should not have that much of an impact (checking the input data is probably one of the the first things it does).
By the way, did you try the current master branch (or the current developers release)? It contains a change in the pkcs11 plugin that should filter out unsupported signature mechanisms (at least if the HSM reports only the ones it actually supports via C_GetMechanismList
- of course, that's a global command, so it does not work if the limitation depends on the key).
#4 Updated by David MAFFRAND about 2 years ago
You mean the two C_Sign() failed: DATA_LEN_RANGE messages?
No I was wrong, I thought it was generating extra IKE_AUTH request message
What do you mean? Handling that error should not have that much of an impact (checking the input data is probably one of the the first things it does).
Well it's an embedded HSM, its lifetime also depend on usage, that's why we'd like to use it only when it's necessary.
Checking the input data, is not done, it's more a kind of try / failure / succeed
I used a pkcs11 proxy to see what's happening to the HSM.
Raw signature is supported with key size limited to 256.
Calling C_GetMechanismInfo Input slotID: 1 type: 4161 (CKM_ECDSA) pInfo: 0xbe88308c Output pInfo: 0xbe88308c ulMinKeySize: 256 ulMaxKeySize: 256 flags: 10241 CKF_HW: TRUE CKF_ENCRYPT: FALSE CKF_DECRYPT: FALSE CKF_DIGEST: FALSE CKF_SIGN: TRUE CKF_SIGN_RECOVER: FALSE CKF_VERIFY: TRUE CKF_VERIFY_RECOVER: FALSE CKF_GENERATE: FALSE CKF_GENERATE_KEY_PAIR: FALSE CKF_WRAP: FALSE CKF_UNWRAP: FALSE CKF_DERIVE: FALSE CKF_EC_F_P: FALSE CKF_EC_F_2M: FALSE CKF_EC_ECPARAMETERS: FALSE CKF_EC_NAMEDCURVE: FALSE CKF_EC_UNCOMPRESS: FALSE CKF_EC_COMPRESS: FALSE CKF_EXTENSION: FALSE Returning 0 (CKR_OK)
Actually, signature mechanism try different hash algorithm till it manage to generate one
Calling C_SignInit Input hSession: 2922383072 pMechanism: 0xb6ce755c mechanism: 4161 (CKM_ECDSA) pParameter: (nil) ulParameterLen: (nil) hKey: 7153408 Returning 0 (CKR_OK)
First try (512 bits) => Failed
Calling C_Sign Input hSession: 2922383072 pData: 0xae3043e8 *pData: HEX(89C83E94AF9B3FC7302C1F6E0D9E67708BD235F0B46CE94CD6D74DB79AFFD9803951806B3FF9F3B9D0EE77F54A87E18F6BA474C8852710050A29941DEFBB84DF) ulDataLen: 64 pSignature: 0xae3047b8 pulSignatureLen: 0xb0cc6318 *pulSignatureLen: 64 Returning 33 (CKR_DATA_LEN_RANGE)
Second try (384 bits) => Failed
Calling C_Sign Input hSession: 2922383072 pData: 0xae300d30 *pData: HEX(88E59669E2894C21EF5BC70756DA0E9DE6B220F85B8D245F38819B7CCE75F92BCE9C1682501D30263BB6DF39F69C134E) ulDataLen: 48 pSignature: 0xae3043e8 pulSignatureLen: 0xb0cc6318 *pulSignatureLen: 64 Returning 33 (CKR_DATA_LEN_RANGE)
Thirs try (256 bits) => Ok
Calling C_Sign Input hSession: 2922383072 pData: 0xae304ba8 *pData: HEX(E619C44A9773797519B362B3B2E3A2C298AA55029C2A9FC233B9B2150220ECBD) ulDataLen: 32 pSignature: 0xae3047b8 pulSignatureLen: 0xb0cc6318 *pulSignatureLen: 64 Output pSignature: 0xae3047b8 pulSignatureLen: 0xb0cc6318 *pSignature: HEX(1590D51F55DDC1754B042F9B0B8AEA9A95F48C91AF764F1A51BD4E17782CFC337404A666619B0C74C4AA6B563EF00EC88F1DEECF66833460395831511217C02C) *pulSignatureLen: 64 Returning 0 (CKR_OK)
#5 Updated by David MAFFRAND about 2 years ago
I also use these parameters :
strongswan.conf
charon {
tls {
suites = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
}
...
ipsec.conf
leftauth=eap-tls:ecdsa-256-sha256
So I don't understand why SHA512 / SHA384 are tried for ECDSA signature before SHA256
#6 Updated by Tobias Brunner about 2 years ago
Checking the input data, is not done, it's more a kind of try / failure / succeed
Are you sure about that. It seems it bails out because it feels the input data length is too long (CKR_DATA_LEN_RANGE
), which is the length of the hashed data (64 for SHA-512, 48 for SHA-384 and finally 32 for SHA-256, which it accepts).
Raw signature is supported with key size limited to 256.
Hm, I see. The key length is not the problem, though. It's the data length, for which the mechanisms can't report a supported range. Actually, the PKCS#11 standard in section 2.3.6 has a table that explains that C_Sign
for CKM_ECDSA
accepts any input length with a footnote that says: "Input the entire raw digest. Internally, this will be truncated to the appropriate number of bits.", which seems what the HSM should do instead of reporting CKR_DATA_LEN_RANGE
. Section 2.3.1 on EC signatures says it similarly: "If the length of the hash value is larger than the bit length of n, only the leftmost bits of the hash up to the length of n will be used. Any truncation is done by the token.".
Actually, signature mechanism try different hash algorithm till it manage to generate one
Yes, the TLS library tries all hash/signature-combinations the server supports in the order it sent them in the SignatureAndHashAlgorithm extension.
leftauth=eap-tls:ecdsa-256-sha256So I don't understand why SHA512 / SHA384 are tried for ECDSA signature before SHA256
Such constraints currently have no effect on the TLS signatures whatsoever (they are only used during certificate chain validation, which makes not much sense in leftauth).