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