| OLD | NEW |
| (Empty) |
| 1 Index: net/third_party/nss/ssl/ssl3con.c | |
| 2 =================================================================== | |
| 3 --- net/third_party/nss/ssl/ssl3con.c (revision 220594) | |
| 4 +++ net/third_party/nss/ssl/ssl3con.c (working copy) | |
| 5 @@ -3933,6 +3933,20 @@ | |
| 6 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); | |
| 7 return SECFailure; | |
| 8 } | |
| 9 + | |
| 10 + /* A backup SHA-1 hash for a potential client auth signature. */ | |
| 11 + if (!ss->sec.isServer) { | |
| 12 + ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_SHA1); | |
| 13 + if (ss->ssl3.hs.md5 == NULL) { | |
| 14 + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 15 + return SECFailure; | |
| 16 + } | |
| 17 + | |
| 18 + if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) { | |
| 19 + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 20 + return SECFailure; | |
| 21 + } | |
| 22 + } | |
| 23 } else { | |
| 24 /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or | |
| 25 * created successfully. */ | |
| 26 @@ -4043,6 +4057,13 @@ | |
| 27 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); | |
| 28 return rv; | |
| 29 } | |
| 30 + if (ss->ssl3.hs.md5) { | |
| 31 + rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); | |
| 32 + if (rv != SECSuccess) { | |
| 33 + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 34 + return rv; | |
| 35 + } | |
| 36 + } | |
| 37 } else { | |
| 38 rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); | |
| 39 if (rv != SECSuccess) { | |
| 40 @@ -4791,6 +4812,30 @@ | |
| 41 return rv; | |
| 42 } | |
| 43 | |
| 44 +static SECStatus | |
| 45 +ssl3_ComputeBackupHandshakeHashes(sslSocket * ss, | |
| 46 + SSL3Hashes * hashes) /* output goes here. */ | |
| 47 +{ | |
| 48 + SECStatus rv = SECSuccess; | |
| 49 + | |
| 50 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 51 + PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single ); | |
| 52 + | |
| 53 + rv = PK11_DigestFinal(ss->ssl3.hs.md5, hashes->u.raw, &hashes->len, | |
| 54 + sizeof(hashes->u.raw)); | |
| 55 + if (rv != SECSuccess) { | |
| 56 + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 57 + rv = SECFailure; | |
| 58 + goto loser; | |
| 59 + } | |
| 60 + hashes->hashAlg = SEC_OID_SHA1; | |
| 61 + | |
| 62 +loser: | |
| 63 + PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); | |
| 64 + ss->ssl3.hs.md5 = NULL; | |
| 65 + return rv; | |
| 66 +} | |
| 67 + | |
| 68 /* | |
| 69 * SSL 2 based implementations pass in the initial outbound buffer | |
| 70 * so that the handshake hash can contain the included information. | |
| 71 @@ -6044,7 +6089,17 @@ | |
| 72 SSL_GETPID(), ss->fd)); | |
| 73 | |
| 74 ssl_GetSpecReadLock(ss); | |
| 75 - rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); | |
| 76 + /* In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the handshake hash | |
| 77 + * function (SHA-256). If the server or the client does not support SHA-256 | |
| 78 + * as a signature hash, we can either maintain a backup SHA-1 handshake | |
| 79 + * hash or buffer all handshake messages. | |
| 80 + */ | |
| 81 + if (ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) { | |
| 82 + rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes); | |
| 83 + PORT_Assert(ss->ssl3.hs.md5 == NULL); | |
| 84 + } else { | |
| 85 + rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); | |
| 86 + } | |
| 87 ssl_ReleaseSpecReadLock(ss); | |
| 88 if (rv != SECSuccess) { | |
| 89 goto done; /* err code was set by ssl3_ComputeHandshakeHashes */ | |
| 90 @@ -6098,11 +6153,6 @@ | |
| 91 if (rv != SECSuccess) { | |
| 92 goto done; | |
| 93 } | |
| 94 - /* We always sign using the handshake hash function. It's possible that | |
| 95 - * a server could support SHA-256 as the handshake hash but not as a | |
| 96 - * signature hash. In that case we wouldn't be able to do client | |
| 97 - * certificates with it. The alternative is to buffer all handshake | |
| 98 - * messages. */ | |
| 99 sigAndHash.hashAlg = hashes.hashAlg; | |
| 100 | |
| 101 rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash); | |
| 102 @@ -6802,6 +6852,70 @@ | |
| 103 } | |
| 104 | |
| 105 | |
| 106 +/* | |
| 107 + * Returns true if the client authentication key is an RSA or DSA key that | |
| 108 + * may be able to sign only SHA-1 hashes. | |
| 109 + */ | |
| 110 +static PRBool | |
| 111 +ssl3_ClientKeyPrefersSHA1(sslSocket *ss) | |
| 112 +{ | |
| 113 + SECKEYPublicKey *pubk; | |
| 114 + PRBool prefer_sha1 = PR_FALSE; | |
| 115 + | |
| 116 +#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32) | |
| 117 + /* If the key is in CAPI, assume conservatively that the CAPI service | |
| 118 + * provider may be unable to sign SHA-256 hashes. | |
| 119 + */ | |
| 120 + if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) { | |
| 121 + /* CAPI only supports RSA and DSA signatures, so we don't need to | |
| 122 + * check the key type. */ | |
| 123 + return PR_TRUE; | |
| 124 + } | |
| 125 +#endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */ | |
| 126 + | |
| 127 + /* If the key is a 1024-bit RSA or DSA key, assume conservatively that | |
| 128 + * it may be unable to sign SHA-256 hashes. This is the case for older | |
| 129 + * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and | |
| 130 + * older, DSA key size is at most 1024 bits and the hash function must | |
| 131 + * be SHA-1. | |
| 132 + */ | |
| 133 + pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate); | |
| 134 + if (pubk == NULL) { | |
| 135 + return PR_FALSE; | |
| 136 + } | |
| 137 + if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) { | |
| 138 + prefer_sha1 = SECKEY_PublicKeyStrength(pubk) <= 128; | |
| 139 + } | |
| 140 + SECKEY_DestroyPublicKey(pubk); | |
| 141 + return prefer_sha1; | |
| 142 +} | |
| 143 + | |
| 144 +/* Destroys the backup handshake hash context if we don't need it. */ | |
| 145 +static void | |
| 146 +ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss, | |
| 147 + const SECItem *algorithms) | |
| 148 +{ | |
| 149 + PRBool need_backup_hash = PR_FALSE; | |
| 150 + unsigned int i; | |
| 151 + | |
| 152 + PORT_Assert(ss->ssl3.hs.md5); | |
| 153 + if (ssl3_ClientKeyPrefersSHA1(ss)) { | |
| 154 + /* Use SHA-1 if the server supports it. */ | |
| 155 + for (i = 0; i < algorithms->len; i += 2) { | |
| 156 + if (algorithms->data[i] == tls_hash_sha1 && | |
| 157 + (algorithms->data[i+1] == tls_sig_rsa || | |
| 158 + algorithms->data[i+1] == tls_sig_dsa)) { | |
| 159 + need_backup_hash = PR_TRUE; | |
| 160 + break; | |
| 161 + } | |
| 162 + } | |
| 163 + } | |
| 164 + if (!need_backup_hash) { | |
| 165 + PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); | |
| 166 + ss->ssl3.hs.md5 = NULL; | |
| 167 + } | |
| 168 +} | |
| 169 + | |
| 170 typedef struct dnameNode { | |
| 171 struct dnameNode *next; | |
| 172 SECItem name; | |
| 173 @@ -6994,6 +7108,9 @@ | |
| 174 } | |
| 175 goto send_no_certificate; | |
| 176 } | |
| 177 + if (isTLS12) { | |
| 178 + ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms); | |
| 179 + } | |
| 180 break; /* not an error */ | |
| 181 } | |
| 182 #endif /* NSS_PLATFORM_CLIENT_AUTH */ | |
| 183 @@ -7029,6 +7146,9 @@ | |
| 184 } | |
| 185 goto send_no_certificate; | |
| 186 } | |
| 187 + if (isTLS12) { | |
| 188 + ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms); | |
| 189 + } | |
| 190 break; /* not an error */ | |
| 191 | |
| 192 case SECFailure: | |
| 193 @@ -7227,6 +7347,13 @@ | |
| 194 (ss->ssl3.platformClientKey || | |
| 195 ss->ssl3.clientPrivateKey != NULL); | |
| 196 | |
| 197 + if (!sendClientCert && | |
| 198 + ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) { | |
| 199 + /* Don't need the backup handshake hash. */ | |
| 200 + PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); | |
| 201 + ss->ssl3.hs.md5 = NULL; | |
| 202 + } | |
| 203 + | |
| 204 /* We must wait for the server's certificate to be authenticated before | |
| 205 * sending the client certificate in order to disclosing the client | |
| 206 * certificate to an attacker that does not have a valid cert for the | |
| 207 Index: net/third_party/nss/ssl/sslimpl.h | |
| 208 =================================================================== | |
| 209 --- net/third_party/nss/ssl/sslimpl.h (revision 220594) | |
| 210 +++ net/third_party/nss/ssl/sslimpl.h (working copy) | |
| 211 @@ -838,6 +838,9 @@ | |
| 212 * SSL 3.0 - TLS 1.1 use both |md5| and |sha|. |md5| is used for MD5 and | |
| 213 * |sha| for SHA-1. | |
| 214 * TLS 1.2 and later use only |sha|, for SHA-256. */ | |
| 215 + /* NOTE: On the client side, TLS 1.2 and later use |md5| as a backup | |
| 216 + * handshake hash for generating client auth signatures. Confusingly, the | |
| 217 + * backup hash function is SHA-1. */ | |
| 218 PK11Context * md5; | |
| 219 PK11Context * sha; | |
| 220 | |
| OLD | NEW |