diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -7061,49 +7061,68 @@ ssl3_SendClientKeyExchange(sslSocket *ss loser: if (serverKey) SECKEY_DestroyPublicKey(serverKey); return rv; /* err code already set. */ } static SECStatus -ssl_PickSignatureScheme(sslSocket *ss, SECKEYPublicKey *key, +ssl_PickSignatureScheme(sslSocket *ss, + SECKEYPublicKey *pubKey, + SECKEYPrivateKey *privKey, const SignatureScheme *peerSchemes, unsigned int peerSchemeCount, PRBool requireSha1) { unsigned int i, j; const namedGroupDef *group = NULL; KeyType keyType; + PK11SlotInfo *slot; + PRBool slotDoesPss; PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3; - if (!key) { + if (!pubKey || !privKey) { PORT_Assert(0); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } - keyType = SECKEY_GetPublicKeyType(key); + slot = PK11_GetSlotFromPrivateKey(privKey); + if (!slot) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + slotDoesPss = PK11_DoesMechanism(slot, auth_alg_defs[ssl_auth_rsa_pss]); + PK11_FreeSlot(slot); + + keyType = SECKEY_GetPublicKeyType(pubKey); + if (keyType == ecKey) { - group = ssl_ECPubKey2NamedGroup(key); + group = ssl_ECPubKey2NamedGroup(pubKey); } /* Here we look for the first local preference that the client has * indicated support for in their signature_algorithms extension. */ for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) { SSLHashType hashType; SECOidTag hashOID; SignatureScheme preferred = ss->ssl3.signatureSchemes[i]; PRUint32 policy; if (!ssl_SignatureSchemeValidForKey(isTLS13, keyType, group, preferred)) { continue; } + /* Skip RSA-PSS schemes when the certificate's private key slot does + * not support this signature mechanism. */ + if (ssl_IsRsaPssSignatureScheme(preferred) && !slotDoesPss) { + continue; + } + hashType = ssl_SignatureSchemeToHashType(preferred); hashOID = ssl3_HashTypeToOID(hashType); if (requireSha1 && hashOID != SEC_OID_SHA1) { continue; } if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) && !(policy & NSS_USE_ALG_IN_SSL_KX)) { /* we ignore hashes we don't support */ @@ -7148,51 +7167,54 @@ ssl3_PickServerSignatureScheme(sslSocket PORT_Assert(0); PORT_SetError(SEC_ERROR_INVALID_KEY); return SECFailure; } return SECSuccess; } /* Sets error code, if needed. */ - return ssl_PickSignatureScheme(ss, keyPair->pubKey, + return ssl_PickSignatureScheme(ss, keyPair->pubKey, keyPair->privKey, ss->ssl3.hs.clientSigSchemes, ss->ssl3.hs.numClientSigScheme, - PR_FALSE); + PR_FALSE /* requireSha1 */); } static SECStatus ssl_PickClientSignatureScheme(sslSocket *ss, const SignatureScheme *schemes, unsigned int numSchemes) { - SECKEYPublicKey *key; + SECKEYPrivateKey *privKey = ss->ssl3.clientPrivateKey; + SECKEYPublicKey *pubKey; SECStatus rv; - key = CERT_ExtractPublicKey(ss->ssl3.clientCertificate); - PORT_Assert(key); + pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate); + PORT_Assert(pubKey); if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && - (SECKEY_GetPublicKeyType(key) == rsaKey || - SECKEY_GetPublicKeyType(key) == dsaKey) && - SECKEY_PublicKeyStrengthInBits(key) <= 1024) { + (SECKEY_GetPublicKeyType(pubKey) == rsaKey || + SECKEY_GetPublicKeyType(pubKey) == dsaKey) && + SECKEY_PublicKeyStrengthInBits(pubKey) <= 1024) { /* If the key is a 1024-bit RSA or DSA key, assume conservatively that * it may be unable to sign SHA-256 hashes. This is the case for older * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and * older, DSA key size is at most 1024 bits and the hash function must * be SHA-1. */ - rv = ssl_PickSignatureScheme(ss, key, schemes, numSchemes, PR_TRUE); + rv = ssl_PickSignatureScheme(ss, pubKey, privKey, schemes, numSchemes, + PR_TRUE /* requireSha1 */); if (rv == SECSuccess) { - SECKEY_DestroyPublicKey(key); + SECKEY_DestroyPublicKey(pubKey); return SECSuccess; } /* If this fails, that's because the peer doesn't advertise SHA-1, * so fall back to the full negotiation. */ } - rv = ssl_PickSignatureScheme(ss, key, schemes, numSchemes, PR_FALSE); - SECKEY_DestroyPublicKey(key); + rv = ssl_PickSignatureScheme(ss, pubKey, privKey, schemes, numSchemes, + PR_FALSE /* requireSha1 */); + SECKEY_DestroyPublicKey(pubKey); return rv; } /* Called from ssl3_HandleServerHelloDone(). */ static SECStatus ssl3_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey) { SECStatus rv = SECFailure; @@ -10593,16 +10615,23 @@ ssl3_EncodeSigAlgs(sslSocket *ss, PRUint return SECFailure; } for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) { PRUint32 policy = 0; SSLHashType hashType = ssl_SignatureSchemeToHashType( ss->ssl3.signatureSchemes[i]); SECOidTag hashOID = ssl3_HashTypeToOID(hashType); + + /* Skip RSA-PSS schemes if there are no tokens to verify them. */ + if (ssl_IsRsaPssSignatureScheme(ss->ssl3.signatureSchemes[i]) && + !PK11_TokenExists(auth_alg_defs[ssl_auth_rsa_pss])) { + continue; + } + if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) || (policy & NSS_USE_ALG_IN_SSL_KX)) { p = ssl_EncodeUintX((PRUint32)ss->ssl3.signatureSchemes[i], 2, p); } } if (p == buf) { PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);