Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 /* | 2 /* |
| 3 * SSL3 Protocol | 3 * SSL3 Protocol |
| 4 * | 4 * |
| 5 * This Source Code Form is subject to the terms of the Mozilla Public | 5 * This Source Code Form is subject to the terms of the Mozilla Public |
| 6 * License, v. 2.0. If a copy of the MPL was not distributed with this | 6 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 8 | 8 |
| 9 /* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ | 9 /* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ |
| 10 | 10 |
| (...skipping 3915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3926 if (ss->ssl3.hs.sha == NULL) { | 3926 if (ss->ssl3.hs.sha == NULL) { |
| 3927 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | 3927 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
| 3928 return SECFailure; | 3928 return SECFailure; |
| 3929 } | 3929 } |
| 3930 ss->ssl3.hs.hashType = handshake_hash_single; | 3930 ss->ssl3.hs.hashType = handshake_hash_single; |
| 3931 | 3931 |
| 3932 if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { | 3932 if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { |
| 3933 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); | 3933 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
| 3934 return SECFailure; | 3934 return SECFailure; |
| 3935 } | 3935 } |
| 3936 | |
| 3937 #ifdef _WIN32 | |
| 3938 /* A backup SHA-1 hash for a potential client auth signature. */ | |
| 3939 if (!ss->sec.isServer) { | |
| 3940 ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_SHA1); | |
| 3941 if (ss->ssl3.hs.md5 == NULL) { | |
| 3942 PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE); | |
|
agl
2013/08/28 15:15:08
Is destroying hs.sha needed here? It's not done in
wtc
2013/08/28 22:05:45
Done.
| |
| 3943 ss->ssl3.hs.sha = NULL; | |
| 3944 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 3945 return SECFailure; | |
| 3946 } | |
| 3947 | |
| 3948 if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) { | |
| 3949 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 3950 return SECFailure; | |
| 3951 } | |
| 3952 } | |
| 3953 #endif | |
| 3936 } else { | 3954 } else { |
| 3937 /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or | 3955 /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or |
| 3938 * created successfully. */ | 3956 * created successfully. */ |
| 3939 ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5); | 3957 ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5); |
| 3940 if (ss->ssl3.hs.md5 == NULL) { | 3958 if (ss->ssl3.hs.md5 == NULL) { |
| 3941 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); | 3959 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
| 3942 return SECFailure; | 3960 return SECFailure; |
| 3943 } | 3961 } |
| 3944 ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); | 3962 ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); |
| 3945 if (ss->ssl3.hs.sha == NULL) { | 3963 if (ss->ssl3.hs.sha == NULL) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4036 } | 4054 } |
| 4037 return rv; | 4055 return rv; |
| 4038 } | 4056 } |
| 4039 #endif | 4057 #endif |
| 4040 if (ss->ssl3.hs.hashType == handshake_hash_single) { | 4058 if (ss->ssl3.hs.hashType == handshake_hash_single) { |
| 4041 rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); | 4059 rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); |
| 4042 if (rv != SECSuccess) { | 4060 if (rv != SECSuccess) { |
| 4043 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); | 4061 ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
| 4044 return rv; | 4062 return rv; |
| 4045 } | 4063 } |
| 4064 if (ss->ssl3.hs.md5) { | |
| 4065 rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); | |
| 4066 if (rv != SECSuccess) { | |
| 4067 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 4068 return rv; | |
| 4069 } | |
| 4070 } | |
| 4046 } else { | 4071 } else { |
|
Ryan Sleevi
2013/08/28 20:40:09
Does it make sense to collapse the if on line 4058
wtc
2013/08/28 22:05:45
Yes. The code can be further simplified if we only
| |
| 4047 rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); | 4072 rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); |
| 4048 if (rv != SECSuccess) { | 4073 if (rv != SECSuccess) { |
| 4049 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); | 4074 ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
| 4050 return rv; | 4075 return rv; |
| 4051 } | 4076 } |
| 4052 rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); | 4077 rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); |
| 4053 if (rv != SECSuccess) { | 4078 if (rv != SECSuccess) { |
| 4054 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | 4079 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
| 4055 return rv; | 4080 return rv; |
| 4056 } | 4081 } |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4784 rv = SECFailure; | 4809 rv = SECFailure; |
| 4785 } | 4810 } |
| 4786 if (shaStateBuf != shaStackBuf) { | 4811 if (shaStateBuf != shaStackBuf) { |
| 4787 PORT_ZFree(shaStateBuf, shaStateLen); | 4812 PORT_ZFree(shaStateBuf, shaStateLen); |
| 4788 } | 4813 } |
| 4789 } | 4814 } |
| 4790 } | 4815 } |
| 4791 return rv; | 4816 return rv; |
| 4792 } | 4817 } |
| 4793 | 4818 |
| 4819 static SECStatus | |
| 4820 ssl3_ComputeBackupHandshakeHashes(sslSocket * ss, | |
| 4821 SSL3Hashes * hashes) /* output goes here. */ | |
| 4822 { | |
| 4823 SECStatus rv = SECSuccess; | |
| 4824 | |
| 4825 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 4826 PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single ); | |
| 4827 | |
| 4828 rv = PK11_DigestFinal(ss->ssl3.hs.md5, hashes->u.raw, &hashes->len, | |
| 4829 sizeof(hashes->u.raw)); | |
| 4830 if (rv != SECSuccess) { | |
| 4831 ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); | |
| 4832 rv = SECFailure; | |
| 4833 goto loser; | |
| 4834 } | |
| 4835 hashes->hashAlg = SEC_OID_SHA1; | |
| 4836 | |
| 4837 loser: | |
| 4838 PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); | |
| 4839 ss->ssl3.hs.md5 = NULL; | |
| 4840 return rv; | |
| 4841 } | |
| 4842 | |
| 4794 /* | 4843 /* |
| 4795 * SSL 2 based implementations pass in the initial outbound buffer | 4844 * SSL 2 based implementations pass in the initial outbound buffer |
| 4796 * so that the handshake hash can contain the included information. | 4845 * so that the handshake hash can contain the included information. |
| 4797 * | 4846 * |
| 4798 * Called from ssl2_BeginClientHandshake() in sslcon.c | 4847 * Called from ssl2_BeginClientHandshake() in sslcon.c |
| 4799 */ | 4848 */ |
| 4800 SECStatus | 4849 SECStatus |
| 4801 ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length) | 4850 ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length) |
| 4802 { | 4851 { |
| 4803 SECStatus rv; | 4852 SECStatus rv; |
| (...skipping 1233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6037 unsigned int len; | 6086 unsigned int len; |
| 6038 SSL3SignatureAndHashAlgorithm sigAndHash; | 6087 SSL3SignatureAndHashAlgorithm sigAndHash; |
| 6039 | 6088 |
| 6040 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | 6089 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
| 6041 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | 6090 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
| 6042 | 6091 |
| 6043 SSL_TRC(3, ("%d: SSL3[%d]: send certificate_verify handshake", | 6092 SSL_TRC(3, ("%d: SSL3[%d]: send certificate_verify handshake", |
| 6044 SSL_GETPID(), ss->fd)); | 6093 SSL_GETPID(), ss->fd)); |
| 6045 | 6094 |
| 6046 ssl_GetSpecReadLock(ss); | 6095 ssl_GetSpecReadLock(ss); |
| 6047 rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); | 6096 if (ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) { |
| 6097 » rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes); | |
|
Ryan Sleevi
2013/08/28 20:40:09
Given that ssl3_ComputeBackupHandshakeHashes has a
wtc
2013/08/28 22:05:45
That was my original plan. I didn't do that for tw
| |
| 6098 » PORT_Assert(ss->ssl3.hs.md5 == NULL); | |
| 6099 } else { | |
| 6100 » rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); | |
| 6101 } | |
| 6048 ssl_ReleaseSpecReadLock(ss); | 6102 ssl_ReleaseSpecReadLock(ss); |
| 6049 if (rv != SECSuccess) { | 6103 if (rv != SECSuccess) { |
| 6050 goto done; /* err code was set by ssl3_ComputeHandshakeHashes */ | 6104 goto done; /* err code was set by ssl3_ComputeHandshakeHashes */ |
| 6051 } | 6105 } |
| 6052 | 6106 |
| 6053 isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); | 6107 isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
| 6054 isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); | 6108 isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
| 6055 if (ss->ssl3.platformClientKey) { | 6109 if (ss->ssl3.platformClientKey) { |
| 6056 #ifdef NSS_PLATFORM_CLIENT_AUTH | 6110 #ifdef NSS_PLATFORM_CLIENT_AUTH |
| 6057 keyType = CERT_GetCertKeyType( | 6111 keyType = CERT_GetCertKeyType( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6095 if (isTLS12) { | 6149 if (isTLS12) { |
| 6096 rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType, | 6150 rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType, |
| 6097 &sigAndHash.sigAlg); | 6151 &sigAndHash.sigAlg); |
| 6098 if (rv != SECSuccess) { | 6152 if (rv != SECSuccess) { |
| 6099 goto done; | 6153 goto done; |
| 6100 } | 6154 } |
| 6101 /* We always sign using the handshake hash function. It's possible that | 6155 /* We always sign using the handshake hash function. It's possible that |
| 6102 * a server could support SHA-256 as the handshake hash but not as a | 6156 * a server could support SHA-256 as the handshake hash but not as a |
| 6103 * signature hash. In that case we wouldn't be able to do client | 6157 * signature hash. In that case we wouldn't be able to do client |
| 6104 * certificates with it. The alternative is to buffer all handshake | 6158 * certificates with it. The alternative is to buffer all handshake |
| 6105 * messages. */ | 6159 * messages. */ |
|
Ryan Sleevi
2013/08/28 20:40:09
This comment seems inaccurate now.
wtc
2013/08/28 22:05:45
Thanks. This is also not the best place for this c
| |
| 6106 sigAndHash.hashAlg = hashes.hashAlg; | 6160 sigAndHash.hashAlg = hashes.hashAlg; |
| 6107 | 6161 |
| 6108 rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash); | 6162 rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash); |
| 6109 if (rv != SECSuccess) { | 6163 if (rv != SECSuccess) { |
| 6110 goto done; /* err set by AppendHandshake. */ | 6164 goto done; /* err set by AppendHandshake. */ |
| 6111 } | 6165 } |
| 6112 } | 6166 } |
| 6113 rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2); | 6167 rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2); |
| 6114 if (rv != SECSuccess) { | 6168 if (rv != SECSuccess) { |
| 6115 goto done; /* error code set by AppendHandshake */ | 6169 goto done; /* error code set by AppendHandshake */ |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6987 if (ss->ssl3.clientCertificate != NULL) { | 7041 if (ss->ssl3.clientCertificate != NULL) { |
| 6988 CERT_DestroyCertificate(ss->ssl3.clientCertificate); | 7042 CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
| 6989 ss->ssl3.clientCertificate = NULL; | 7043 ss->ssl3.clientCertificate = NULL; |
| 6990 } | 7044 } |
| 6991 if (ss->ssl3.platformClientKey) { | 7045 if (ss->ssl3.platformClientKey) { |
| 6992 ssl_FreePlatformKey(ss->ssl3.platformClientKey); | 7046 ssl_FreePlatformKey(ss->ssl3.platformClientKey); |
| 6993 ss->ssl3.platformClientKey = (PlatformKey)NULL; | 7047 ss->ssl3.platformClientKey = (PlatformKey)NULL; |
| 6994 } | 7048 } |
| 6995 goto send_no_certificate; | 7049 goto send_no_certificate; |
| 6996 } | 7050 } |
| 7051 | |
| 7052 if (isTLS12 && ss->ssl3.hs.md5) { | |
| 7053 PRBool need_backup_hash = PR_FALSE; | |
| 7054 #ifdef _WIN32 | |
| 7055 /* If the key is in CAPI, assume conservatively that the CAPI | |
| 7056 * service provider may be unable to sign SHA-256 hashes. | |
| 7057 * Use SHA-1 if the server supports it. */ | |
| 7058 if (ss->ssl3.platformClientKey->dwKeySpec != | |
| 7059 CERT_NCRYPT_KEY_SPEC) { | |
| 7060 /* CAPI only supports RSA and DSA signatures. Ideally we | |
| 7061 * should get the key type. Since DSA client keys are rare, | |
| 7062 * assume we have an RSA client key. */ | |
|
Ryan Sleevi
2013/08/28 20:40:09
Why not also support DSA?
if (algorithms.data[i]
wtc
2013/08/28 22:05:45
Originally I thought I'd need to call
keyT
| |
| 7063 for (i = 0; i < algorithms.len; i += 2) { | |
| 7064 if (algorithms.data[i] == tls_hash_sha1 && | |
| 7065 algorithms.data[i + 1] == tls_sig_rsa) { | |
| 7066 need_backup_hash = PR_TRUE; | |
| 7067 break; | |
| 7068 } | |
| 7069 } | |
| 7070 } | |
| 7071 #endif /* _WIN32 */ | |
| 7072 if (!need_backup_hash) { | |
| 7073 PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); | |
| 7074 ss->ssl3.hs.md5 = NULL; | |
| 7075 } | |
| 7076 } | |
| 6997 break; /* not an error */ | 7077 break; /* not an error */ |
| 6998 } | 7078 } |
| 6999 #endif /* NSS_PLATFORM_CLIENT_AUTH */ | 7079 #endif /* NSS_PLATFORM_CLIENT_AUTH */ |
| 7000 /* check what the callback function returned */ | 7080 /* check what the callback function returned */ |
| 7001 if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { | 7081 if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { |
| 7002 /* we are missing either the key or cert */ | 7082 /* we are missing either the key or cert */ |
| 7003 if (ss->ssl3.clientCertificate) { | 7083 if (ss->ssl3.clientCertificate) { |
| 7004 /* got a cert, but no key - free it */ | 7084 /* got a cert, but no key - free it */ |
| 7005 CERT_DestroyCertificate(ss->ssl3.clientCertificate); | 7085 CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
| 7006 ss->ssl3.clientCertificate = NULL; | 7086 ss->ssl3.clientCertificate = NULL; |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7220 PRBool sendClientCert; | 7300 PRBool sendClientCert; |
| 7221 | 7301 |
| 7222 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 7302 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
| 7223 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | 7303 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
| 7224 | 7304 |
| 7225 sendClientCert = !ss->ssl3.sendEmptyCert && | 7305 sendClientCert = !ss->ssl3.sendEmptyCert && |
| 7226 ss->ssl3.clientCertChain != NULL && | 7306 ss->ssl3.clientCertChain != NULL && |
| 7227 (ss->ssl3.platformClientKey || | 7307 (ss->ssl3.platformClientKey || |
| 7228 ss->ssl3.clientPrivateKey != NULL); | 7308 ss->ssl3.clientPrivateKey != NULL); |
| 7229 | 7309 |
| 7310 if (!sendClientCert && | |
| 7311 ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) { | |
| 7312 /* Don't need the backup handshake hash. */ | |
| 7313 PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); | |
| 7314 ss->ssl3.hs.md5 = NULL; | |
| 7315 } | |
|
Ryan Sleevi
2013/08/28 20:40:09
I think it's very weird to do the cleanup in this
wtc
2013/08/28 22:05:45
This is to stop the backup SHA-1 hashing as soon a
| |
| 7316 | |
| 7230 /* We must wait for the server's certificate to be authenticated before | 7317 /* We must wait for the server's certificate to be authenticated before |
| 7231 * sending the client certificate in order to disclosing the client | 7318 * sending the client certificate in order to disclosing the client |
| 7232 * certificate to an attacker that does not have a valid cert for the | 7319 * certificate to an attacker that does not have a valid cert for the |
| 7233 * domain we are connecting to. | 7320 * domain we are connecting to. |
| 7234 * | 7321 * |
| 7235 * XXX: We should do the same for the NPN extension, but for that we | 7322 * XXX: We should do the same for the NPN extension, but for that we |
| 7236 * need an option to give the application the ability to leak the NPN | 7323 * need an option to give the application the ability to leak the NPN |
| 7237 * information to get better performance. | 7324 * information to get better performance. |
| 7238 * | 7325 * |
| 7239 * During the initial handshake on a connection, we never send/receive | 7326 * During the initial handshake on a connection, we never send/receive |
| (...skipping 5024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12264 PORT_Free(ss->ssl3.hs.recvdFragments.buf); | 12351 PORT_Free(ss->ssl3.hs.recvdFragments.buf); |
| 12265 } | 12352 } |
| 12266 } | 12353 } |
| 12267 | 12354 |
| 12268 ss->ssl3.initialized = PR_FALSE; | 12355 ss->ssl3.initialized = PR_FALSE; |
| 12269 | 12356 |
| 12270 SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); | 12357 SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); |
| 12271 } | 12358 } |
| 12272 | 12359 |
| 12273 /* End of ssl3con.c */ | 12360 /* End of ssl3con.c */ |
| OLD | NEW |