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 |