Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* |
michael@0 | 3 | * SSL3 Protocol |
michael@0 | 4 | * |
michael@0 | 5 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 6 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 8 | |
michael@0 | 9 | /* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ |
michael@0 | 10 | |
michael@0 | 11 | #include "cert.h" |
michael@0 | 12 | #include "ssl.h" |
michael@0 | 13 | #include "cryptohi.h" /* for DSAU_ stuff */ |
michael@0 | 14 | #include "keyhi.h" |
michael@0 | 15 | #include "secder.h" |
michael@0 | 16 | #include "secitem.h" |
michael@0 | 17 | #include "sechash.h" |
michael@0 | 18 | |
michael@0 | 19 | #include "sslimpl.h" |
michael@0 | 20 | #include "sslproto.h" |
michael@0 | 21 | #include "sslerr.h" |
michael@0 | 22 | #include "prtime.h" |
michael@0 | 23 | #include "prinrval.h" |
michael@0 | 24 | #include "prerror.h" |
michael@0 | 25 | #include "pratom.h" |
michael@0 | 26 | #include "prthread.h" |
michael@0 | 27 | |
michael@0 | 28 | #include "pk11func.h" |
michael@0 | 29 | #include "secmod.h" |
michael@0 | 30 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 31 | #include "blapi.h" |
michael@0 | 32 | #endif |
michael@0 | 33 | |
michael@0 | 34 | #include <stdio.h> |
michael@0 | 35 | #ifdef NSS_ENABLE_ZLIB |
michael@0 | 36 | #include "zlib.h" |
michael@0 | 37 | #endif |
michael@0 | 38 | |
michael@0 | 39 | #ifndef PK11_SETATTRS |
michael@0 | 40 | #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \ |
michael@0 | 41 | (x)->pValue=(v); (x)->ulValueLen = (l); |
michael@0 | 42 | #endif |
michael@0 | 43 | |
michael@0 | 44 | static SECStatus ssl3_AuthCertificate(sslSocket *ss); |
michael@0 | 45 | static void ssl3_CleanupPeerCerts(sslSocket *ss); |
michael@0 | 46 | static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, |
michael@0 | 47 | PK11SlotInfo * serverKeySlot); |
michael@0 | 48 | static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); |
michael@0 | 49 | static SECStatus ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss); |
michael@0 | 50 | static SECStatus ssl3_HandshakeFailure( sslSocket *ss); |
michael@0 | 51 | static SECStatus ssl3_InitState( sslSocket *ss); |
michael@0 | 52 | static SECStatus ssl3_SendCertificate( sslSocket *ss); |
michael@0 | 53 | static SECStatus ssl3_SendCertificateStatus( sslSocket *ss); |
michael@0 | 54 | static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); |
michael@0 | 55 | static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); |
michael@0 | 56 | static SECStatus ssl3_SendNextProto( sslSocket *ss); |
michael@0 | 57 | static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); |
michael@0 | 58 | static SECStatus ssl3_SendServerHello( sslSocket *ss); |
michael@0 | 59 | static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); |
michael@0 | 60 | static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss); |
michael@0 | 61 | static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, |
michael@0 | 62 | const unsigned char *b, |
michael@0 | 63 | unsigned int l); |
michael@0 | 64 | static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags); |
michael@0 | 65 | static int ssl3_OIDToTLSHashAlgorithm(SECOidTag oid); |
michael@0 | 66 | |
michael@0 | 67 | static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, |
michael@0 | 68 | int maxOutputLen, const unsigned char *input, |
michael@0 | 69 | int inputLen); |
michael@0 | 70 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 71 | static SECStatus ssl3_AESGCMBypass(ssl3KeyMaterial *keys, PRBool doDecrypt, |
michael@0 | 72 | unsigned char *out, int *outlen, int maxout, |
michael@0 | 73 | const unsigned char *in, int inlen, |
michael@0 | 74 | const unsigned char *additionalData, |
michael@0 | 75 | int additionalDataLen); |
michael@0 | 76 | #endif |
michael@0 | 77 | |
michael@0 | 78 | #define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */ |
michael@0 | 79 | #define MIN_SEND_BUF_LENGTH 4000 |
michael@0 | 80 | |
michael@0 | 81 | /* This list of SSL3 cipher suites is sorted in descending order of |
michael@0 | 82 | * precedence (desirability). It only includes cipher suites we implement. |
michael@0 | 83 | * This table is modified by SSL3_SetPolicy(). The ordering of cipher suites |
michael@0 | 84 | * in this table must match the ordering in SSL_ImplementedCiphers (sslenum.c) |
michael@0 | 85 | * |
michael@0 | 86 | * Important: See bug 946147 before enabling, reordering, or adding any cipher |
michael@0 | 87 | * suites to this list. |
michael@0 | 88 | */ |
michael@0 | 89 | static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { |
michael@0 | 90 | /* cipher_suite policy enabled isPresent */ |
michael@0 | 91 | |
michael@0 | 92 | #ifndef NSS_DISABLE_ECC |
michael@0 | 93 | { TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 94 | { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 95 | /* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around |
michael@0 | 96 | * bug 946147. |
michael@0 | 97 | */ |
michael@0 | 98 | { TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 99 | { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 100 | { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 101 | { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 102 | { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 103 | { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 104 | { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 105 | { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 106 | { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 107 | { TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 108 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 109 | |
michael@0 | 110 | { TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 111 | { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 112 | { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 113 | { TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 114 | { TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 115 | { TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 116 | { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 117 | { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 118 | { TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 119 | { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 120 | { TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 121 | { TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 122 | { TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 123 | { TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 124 | |
michael@0 | 125 | #ifndef NSS_DISABLE_ECC |
michael@0 | 126 | { TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 127 | { TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 128 | { TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 129 | { TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 130 | { TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 131 | { TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 132 | { TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 133 | { TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 134 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 135 | |
michael@0 | 136 | /* RSA */ |
michael@0 | 137 | { TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 138 | { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 139 | { TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 140 | { TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 141 | { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 142 | { TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 143 | { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 144 | { TLS_RSA_WITH_SEED_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 145 | { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 146 | { TLS_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 147 | { TLS_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 148 | { TLS_RSA_WITH_RC4_128_MD5, SSL_ALLOWED, PR_TRUE, PR_FALSE}, |
michael@0 | 149 | |
michael@0 | 150 | /* 56-bit DES "domestic" cipher suites */ |
michael@0 | 151 | { TLS_DHE_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 152 | { TLS_DHE_DSS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 153 | { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 154 | { TLS_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 155 | |
michael@0 | 156 | /* export ciphersuites with 1024-bit public key exchange keys */ |
michael@0 | 157 | { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 158 | { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 159 | |
michael@0 | 160 | /* export ciphersuites with 512-bit public key exchange keys */ |
michael@0 | 161 | { TLS_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 162 | { TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 163 | |
michael@0 | 164 | /* ciphersuites with no encryption */ |
michael@0 | 165 | #ifndef NSS_DISABLE_ECC |
michael@0 | 166 | { TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 167 | { TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 168 | { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 169 | { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 170 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 171 | { TLS_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 172 | { TLS_RSA_WITH_NULL_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 173 | { TLS_RSA_WITH_NULL_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE}, |
michael@0 | 174 | }; |
michael@0 | 175 | |
michael@0 | 176 | /* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order. |
michael@0 | 177 | */ |
michael@0 | 178 | #ifdef DEBUG |
michael@0 | 179 | void ssl3_CheckCipherSuiteOrderConsistency() |
michael@0 | 180 | { |
michael@0 | 181 | unsigned int i; |
michael@0 | 182 | |
michael@0 | 183 | /* Note that SSL_ImplementedCiphers has more elements than cipherSuites |
michael@0 | 184 | * because it SSL_ImplementedCiphers includes SSL 2.0 cipher suites. |
michael@0 | 185 | */ |
michael@0 | 186 | PORT_Assert(SSL_NumImplementedCiphers >= PR_ARRAY_SIZE(cipherSuites)); |
michael@0 | 187 | |
michael@0 | 188 | for (i = 0; i < PR_ARRAY_SIZE(cipherSuites); ++i) { |
michael@0 | 189 | PORT_Assert(SSL_ImplementedCiphers[i] == cipherSuites[i].cipher_suite); |
michael@0 | 190 | } |
michael@0 | 191 | } |
michael@0 | 192 | #endif |
michael@0 | 193 | |
michael@0 | 194 | /* This list of SSL3 compression methods is sorted in descending order of |
michael@0 | 195 | * precedence (desirability). It only includes compression methods we |
michael@0 | 196 | * implement. |
michael@0 | 197 | */ |
michael@0 | 198 | static const /*SSLCompressionMethod*/ PRUint8 compressions [] = { |
michael@0 | 199 | #ifdef NSS_ENABLE_ZLIB |
michael@0 | 200 | ssl_compression_deflate, |
michael@0 | 201 | #endif |
michael@0 | 202 | ssl_compression_null |
michael@0 | 203 | }; |
michael@0 | 204 | |
michael@0 | 205 | static const int compressionMethodsCount = |
michael@0 | 206 | sizeof(compressions) / sizeof(compressions[0]); |
michael@0 | 207 | |
michael@0 | 208 | /* compressionEnabled returns true iff the compression algorithm is enabled |
michael@0 | 209 | * for the given SSL socket. */ |
michael@0 | 210 | static PRBool |
michael@0 | 211 | compressionEnabled(sslSocket *ss, SSLCompressionMethod compression) |
michael@0 | 212 | { |
michael@0 | 213 | switch (compression) { |
michael@0 | 214 | case ssl_compression_null: |
michael@0 | 215 | return PR_TRUE; /* Always enabled */ |
michael@0 | 216 | #ifdef NSS_ENABLE_ZLIB |
michael@0 | 217 | case ssl_compression_deflate: |
michael@0 | 218 | return ss->opt.enableDeflate; |
michael@0 | 219 | #endif |
michael@0 | 220 | default: |
michael@0 | 221 | return PR_FALSE; |
michael@0 | 222 | } |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | static const /*SSL3ClientCertificateType */ PRUint8 certificate_types [] = { |
michael@0 | 226 | ct_RSA_sign, |
michael@0 | 227 | #ifndef NSS_DISABLE_ECC |
michael@0 | 228 | ct_ECDSA_sign, |
michael@0 | 229 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 230 | ct_DSS_sign, |
michael@0 | 231 | }; |
michael@0 | 232 | |
michael@0 | 233 | /* This block is the contents of the supported_signature_algorithms field of |
michael@0 | 234 | * our TLS 1.2 CertificateRequest message, in wire format. See |
michael@0 | 235 | * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 |
michael@0 | 236 | * |
michael@0 | 237 | * This block contains only sha256 entries because we only support TLS 1.2 |
michael@0 | 238 | * CertificateVerify messages that use the handshake hash. */ |
michael@0 | 239 | static const PRUint8 supported_signature_algorithms[] = { |
michael@0 | 240 | tls_hash_sha256, tls_sig_rsa, |
michael@0 | 241 | #ifndef NSS_DISABLE_ECC |
michael@0 | 242 | tls_hash_sha256, tls_sig_ecdsa, |
michael@0 | 243 | #endif |
michael@0 | 244 | tls_hash_sha256, tls_sig_dsa, |
michael@0 | 245 | }; |
michael@0 | 246 | |
michael@0 | 247 | #define EXPORT_RSA_KEY_LENGTH 64 /* bytes */ |
michael@0 | 248 | |
michael@0 | 249 | |
michael@0 | 250 | /* This global item is used only in servers. It is is initialized by |
michael@0 | 251 | ** SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest(). |
michael@0 | 252 | */ |
michael@0 | 253 | CERTDistNames *ssl3_server_ca_list = NULL; |
michael@0 | 254 | static SSL3Statistics ssl3stats; |
michael@0 | 255 | |
michael@0 | 256 | /* indexed by SSL3BulkCipher */ |
michael@0 | 257 | static const ssl3BulkCipherDef bulk_cipher_defs[] = { |
michael@0 | 258 | /* |--------- Lengths --------| */ |
michael@0 | 259 | /* cipher calg k s type i b t n */ |
michael@0 | 260 | /* e e v l a o */ |
michael@0 | 261 | /* y c | o g n */ |
michael@0 | 262 | /* | r | c | c */ |
michael@0 | 263 | /* | e | k | e */ |
michael@0 | 264 | /* | t | | | | */ |
michael@0 | 265 | {cipher_null, calg_null, 0, 0, type_stream, 0, 0, 0, 0}, |
michael@0 | 266 | {cipher_rc4, calg_rc4, 16,16, type_stream, 0, 0, 0, 0}, |
michael@0 | 267 | {cipher_rc4_40, calg_rc4, 16, 5, type_stream, 0, 0, 0, 0}, |
michael@0 | 268 | {cipher_rc4_56, calg_rc4, 16, 7, type_stream, 0, 0, 0, 0}, |
michael@0 | 269 | {cipher_rc2, calg_rc2, 16,16, type_block, 8, 8, 0, 0}, |
michael@0 | 270 | {cipher_rc2_40, calg_rc2, 16, 5, type_block, 8, 8, 0, 0}, |
michael@0 | 271 | {cipher_des, calg_des, 8, 8, type_block, 8, 8, 0, 0}, |
michael@0 | 272 | {cipher_3des, calg_3des, 24,24, type_block, 8, 8, 0, 0}, |
michael@0 | 273 | {cipher_des40, calg_des, 8, 5, type_block, 8, 8, 0, 0}, |
michael@0 | 274 | {cipher_idea, calg_idea, 16,16, type_block, 8, 8, 0, 0}, |
michael@0 | 275 | {cipher_aes_128, calg_aes, 16,16, type_block, 16,16, 0, 0}, |
michael@0 | 276 | {cipher_aes_256, calg_aes, 32,32, type_block, 16,16, 0, 0}, |
michael@0 | 277 | {cipher_camellia_128, calg_camellia, 16,16, type_block, 16,16, 0, 0}, |
michael@0 | 278 | {cipher_camellia_256, calg_camellia, 32,32, type_block, 16,16, 0, 0}, |
michael@0 | 279 | {cipher_seed, calg_seed, 16,16, type_block, 16,16, 0, 0}, |
michael@0 | 280 | {cipher_aes_128_gcm, calg_aes_gcm, 16,16, type_aead, 4, 0,16, 8}, |
michael@0 | 281 | {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, 0, 0}, |
michael@0 | 282 | }; |
michael@0 | 283 | |
michael@0 | 284 | static const ssl3KEADef kea_defs[] = |
michael@0 | 285 | { /* indexed by SSL3KeyExchangeAlgorithm */ |
michael@0 | 286 | /* kea exchKeyType signKeyType is_limited limit tls_keygen */ |
michael@0 | 287 | {kea_null, kt_null, sign_null, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 288 | {kea_rsa, kt_rsa, sign_rsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 289 | {kea_rsa_export, kt_rsa, sign_rsa, PR_TRUE, 512, PR_FALSE}, |
michael@0 | 290 | {kea_rsa_export_1024,kt_rsa, sign_rsa, PR_TRUE, 1024, PR_FALSE}, |
michael@0 | 291 | {kea_dh_dss, kt_dh, sign_dsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 292 | {kea_dh_dss_export, kt_dh, sign_dsa, PR_TRUE, 512, PR_FALSE}, |
michael@0 | 293 | {kea_dh_rsa, kt_dh, sign_rsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 294 | {kea_dh_rsa_export, kt_dh, sign_rsa, PR_TRUE, 512, PR_FALSE}, |
michael@0 | 295 | {kea_dhe_dss, kt_dh, sign_dsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 296 | {kea_dhe_dss_export, kt_dh, sign_dsa, PR_TRUE, 512, PR_FALSE}, |
michael@0 | 297 | {kea_dhe_rsa, kt_dh, sign_rsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 298 | {kea_dhe_rsa_export, kt_dh, sign_rsa, PR_TRUE, 512, PR_FALSE}, |
michael@0 | 299 | {kea_dh_anon, kt_dh, sign_null, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 300 | {kea_dh_anon_export, kt_dh, sign_null, PR_TRUE, 512, PR_FALSE}, |
michael@0 | 301 | {kea_rsa_fips, kt_rsa, sign_rsa, PR_FALSE, 0, PR_TRUE }, |
michael@0 | 302 | #ifndef NSS_DISABLE_ECC |
michael@0 | 303 | {kea_ecdh_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 304 | {kea_ecdhe_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 305 | {kea_ecdh_rsa, kt_ecdh, sign_rsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 306 | {kea_ecdhe_rsa, kt_ecdh, sign_rsa, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 307 | {kea_ecdh_anon, kt_ecdh, sign_null, PR_FALSE, 0, PR_FALSE}, |
michael@0 | 308 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 309 | }; |
michael@0 | 310 | |
michael@0 | 311 | /* must use ssl_LookupCipherSuiteDef to access */ |
michael@0 | 312 | static const ssl3CipherSuiteDef cipher_suite_defs[] = |
michael@0 | 313 | { |
michael@0 | 314 | /* cipher_suite bulk_cipher_alg mac_alg key_exchange_alg */ |
michael@0 | 315 | |
michael@0 | 316 | {TLS_NULL_WITH_NULL_NULL, cipher_null, mac_null, kea_null}, |
michael@0 | 317 | {TLS_RSA_WITH_NULL_MD5, cipher_null, mac_md5, kea_rsa}, |
michael@0 | 318 | {TLS_RSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_rsa}, |
michael@0 | 319 | {TLS_RSA_WITH_NULL_SHA256, cipher_null, hmac_sha256, kea_rsa}, |
michael@0 | 320 | {TLS_RSA_EXPORT_WITH_RC4_40_MD5,cipher_rc4_40, mac_md5, kea_rsa_export}, |
michael@0 | 321 | {TLS_RSA_WITH_RC4_128_MD5, cipher_rc4, mac_md5, kea_rsa}, |
michael@0 | 322 | {TLS_RSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_rsa}, |
michael@0 | 323 | {TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, |
michael@0 | 324 | cipher_rc2_40, mac_md5, kea_rsa_export}, |
michael@0 | 325 | #if 0 /* not implemented */ |
michael@0 | 326 | {TLS_RSA_WITH_IDEA_CBC_SHA, cipher_idea, mac_sha, kea_rsa}, |
michael@0 | 327 | {TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, |
michael@0 | 328 | cipher_des40, mac_sha, kea_rsa_export}, |
michael@0 | 329 | #endif |
michael@0 | 330 | {TLS_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_rsa}, |
michael@0 | 331 | {TLS_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa}, |
michael@0 | 332 | {TLS_DHE_DSS_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_dhe_dss}, |
michael@0 | 333 | {TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, |
michael@0 | 334 | cipher_3des, mac_sha, kea_dhe_dss}, |
michael@0 | 335 | {TLS_DHE_DSS_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_dhe_dss}, |
michael@0 | 336 | #if 0 /* not implemented */ |
michael@0 | 337 | {TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, |
michael@0 | 338 | cipher_des40, mac_sha, kea_dh_dss_export}, |
michael@0 | 339 | {TLS_DH_DSS_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_dss}, |
michael@0 | 340 | {TLS_DH_DSS_3DES_CBC_SHA, cipher_3des, mac_sha, kea_dh_dss}, |
michael@0 | 341 | {TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, |
michael@0 | 342 | cipher_des40, mac_sha, kea_dh_rsa_export}, |
michael@0 | 343 | {TLS_DH_RSA_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_rsa}, |
michael@0 | 344 | {TLS_DH_RSA_3DES_CBC_SHA, cipher_3des, mac_sha, kea_dh_rsa}, |
michael@0 | 345 | {TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, |
michael@0 | 346 | cipher_des40, mac_sha, kea_dh_dss_export}, |
michael@0 | 347 | {TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, |
michael@0 | 348 | cipher_des40, mac_sha, kea_dh_rsa_export}, |
michael@0 | 349 | #endif |
michael@0 | 350 | {TLS_DHE_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_dhe_rsa}, |
michael@0 | 351 | {TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, |
michael@0 | 352 | cipher_3des, mac_sha, kea_dhe_rsa}, |
michael@0 | 353 | #if 0 |
michael@0 | 354 | {SSL_DH_ANON_EXPORT_RC4_40_MD5, cipher_rc4_40, mac_md5, kea_dh_anon_export}, |
michael@0 | 355 | {TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, |
michael@0 | 356 | cipher_des40, mac_sha, kea_dh_anon_export}, |
michael@0 | 357 | {TLS_DH_anon_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_anon}, |
michael@0 | 358 | {TLS_DH_anon_WITH_3DES_CBC_SHA, cipher_3des, mac_sha, kea_dh_anon}, |
michael@0 | 359 | #endif |
michael@0 | 360 | |
michael@0 | 361 | |
michael@0 | 362 | /* New TLS cipher suites */ |
michael@0 | 363 | {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa}, |
michael@0 | 364 | {TLS_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_rsa}, |
michael@0 | 365 | {TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_dss}, |
michael@0 | 366 | {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe_rsa}, |
michael@0 | 367 | {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_dhe_rsa}, |
michael@0 | 368 | {TLS_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_rsa}, |
michael@0 | 369 | {TLS_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_rsa}, |
michael@0 | 370 | {TLS_DHE_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dhe_dss}, |
michael@0 | 371 | {TLS_DHE_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dhe_rsa}, |
michael@0 | 372 | {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, hmac_sha256, kea_dhe_rsa}, |
michael@0 | 373 | #if 0 |
michael@0 | 374 | {TLS_DH_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_dss}, |
michael@0 | 375 | {TLS_DH_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_rsa}, |
michael@0 | 376 | {TLS_DH_anon_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dh_anon}, |
michael@0 | 377 | {TLS_DH_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_dss}, |
michael@0 | 378 | {TLS_DH_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_rsa}, |
michael@0 | 379 | {TLS_DH_anon_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_dh_anon}, |
michael@0 | 380 | #endif |
michael@0 | 381 | |
michael@0 | 382 | {TLS_RSA_WITH_SEED_CBC_SHA, cipher_seed, mac_sha, kea_rsa}, |
michael@0 | 383 | |
michael@0 | 384 | {TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, cipher_camellia_128, mac_sha, kea_rsa}, |
michael@0 | 385 | {TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, |
michael@0 | 386 | cipher_camellia_128, mac_sha, kea_dhe_dss}, |
michael@0 | 387 | {TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, |
michael@0 | 388 | cipher_camellia_128, mac_sha, kea_dhe_rsa}, |
michael@0 | 389 | {TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, cipher_camellia_256, mac_sha, kea_rsa}, |
michael@0 | 390 | {TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, |
michael@0 | 391 | cipher_camellia_256, mac_sha, kea_dhe_dss}, |
michael@0 | 392 | {TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, |
michael@0 | 393 | cipher_camellia_256, mac_sha, kea_dhe_rsa}, |
michael@0 | 394 | |
michael@0 | 395 | {TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, |
michael@0 | 396 | cipher_des, mac_sha,kea_rsa_export_1024}, |
michael@0 | 397 | {TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, |
michael@0 | 398 | cipher_rc4_56, mac_sha,kea_rsa_export_1024}, |
michael@0 | 399 | |
michael@0 | 400 | {SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_rsa_fips}, |
michael@0 | 401 | {SSL_RSA_FIPS_WITH_DES_CBC_SHA, cipher_des, mac_sha, kea_rsa_fips}, |
michael@0 | 402 | |
michael@0 | 403 | {TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_dhe_rsa}, |
michael@0 | 404 | {TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_rsa}, |
michael@0 | 405 | {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_rsa}, |
michael@0 | 406 | {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, mac_aead, kea_ecdhe_ecdsa}, |
michael@0 | 407 | |
michael@0 | 408 | #ifndef NSS_DISABLE_ECC |
michael@0 | 409 | {TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_ecdsa}, |
michael@0 | 410 | {TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_ecdsa}, |
michael@0 | 411 | {TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdh_ecdsa}, |
michael@0 | 412 | {TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdh_ecdsa}, |
michael@0 | 413 | {TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdh_ecdsa}, |
michael@0 | 414 | |
michael@0 | 415 | {TLS_ECDHE_ECDSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdhe_ecdsa}, |
michael@0 | 416 | {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdhe_ecdsa}, |
michael@0 | 417 | {TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdhe_ecdsa}, |
michael@0 | 418 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdhe_ecdsa}, |
michael@0 | 419 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_ecdhe_ecdsa}, |
michael@0 | 420 | {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdhe_ecdsa}, |
michael@0 | 421 | |
michael@0 | 422 | {TLS_ECDH_RSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_rsa}, |
michael@0 | 423 | {TLS_ECDH_RSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_rsa}, |
michael@0 | 424 | {TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdh_rsa}, |
michael@0 | 425 | {TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdh_rsa}, |
michael@0 | 426 | {TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdh_rsa}, |
michael@0 | 427 | |
michael@0 | 428 | {TLS_ECDHE_RSA_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdhe_rsa}, |
michael@0 | 429 | {TLS_ECDHE_RSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdhe_rsa}, |
michael@0 | 430 | {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdhe_rsa}, |
michael@0 | 431 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdhe_rsa}, |
michael@0 | 432 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, hmac_sha256, kea_ecdhe_rsa}, |
michael@0 | 433 | {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdhe_rsa}, |
michael@0 | 434 | |
michael@0 | 435 | #if 0 |
michael@0 | 436 | {TLS_ECDH_anon_WITH_NULL_SHA, cipher_null, mac_sha, kea_ecdh_anon}, |
michael@0 | 437 | {TLS_ECDH_anon_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_ecdh_anon}, |
michael@0 | 438 | {TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_ecdh_anon}, |
michael@0 | 439 | {TLS_ECDH_anon_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_ecdh_anon}, |
michael@0 | 440 | {TLS_ECDH_anon_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_ecdh_anon}, |
michael@0 | 441 | #endif |
michael@0 | 442 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 443 | }; |
michael@0 | 444 | |
michael@0 | 445 | static const CK_MECHANISM_TYPE kea_alg_defs[] = { |
michael@0 | 446 | 0x80000000L, |
michael@0 | 447 | CKM_RSA_PKCS, |
michael@0 | 448 | CKM_DH_PKCS_DERIVE, |
michael@0 | 449 | CKM_KEA_KEY_DERIVE, |
michael@0 | 450 | CKM_ECDH1_DERIVE |
michael@0 | 451 | }; |
michael@0 | 452 | |
michael@0 | 453 | typedef struct SSLCipher2MechStr { |
michael@0 | 454 | SSLCipherAlgorithm calg; |
michael@0 | 455 | CK_MECHANISM_TYPE cmech; |
michael@0 | 456 | } SSLCipher2Mech; |
michael@0 | 457 | |
michael@0 | 458 | /* indexed by type SSLCipherAlgorithm */ |
michael@0 | 459 | static const SSLCipher2Mech alg2Mech[] = { |
michael@0 | 460 | /* calg, cmech */ |
michael@0 | 461 | { calg_null , (CK_MECHANISM_TYPE)0x80000000L }, |
michael@0 | 462 | { calg_rc4 , CKM_RC4 }, |
michael@0 | 463 | { calg_rc2 , CKM_RC2_CBC }, |
michael@0 | 464 | { calg_des , CKM_DES_CBC }, |
michael@0 | 465 | { calg_3des , CKM_DES3_CBC }, |
michael@0 | 466 | { calg_idea , CKM_IDEA_CBC }, |
michael@0 | 467 | { calg_fortezza , CKM_SKIPJACK_CBC64 }, |
michael@0 | 468 | { calg_aes , CKM_AES_CBC }, |
michael@0 | 469 | { calg_camellia , CKM_CAMELLIA_CBC }, |
michael@0 | 470 | { calg_seed , CKM_SEED_CBC }, |
michael@0 | 471 | { calg_aes_gcm , CKM_AES_GCM }, |
michael@0 | 472 | /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */ |
michael@0 | 473 | }; |
michael@0 | 474 | |
michael@0 | 475 | #define mmech_invalid (CK_MECHANISM_TYPE)0x80000000L |
michael@0 | 476 | #define mmech_md5 CKM_SSL3_MD5_MAC |
michael@0 | 477 | #define mmech_sha CKM_SSL3_SHA1_MAC |
michael@0 | 478 | #define mmech_md5_hmac CKM_MD5_HMAC |
michael@0 | 479 | #define mmech_sha_hmac CKM_SHA_1_HMAC |
michael@0 | 480 | #define mmech_sha256_hmac CKM_SHA256_HMAC |
michael@0 | 481 | |
michael@0 | 482 | static const ssl3MACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */ |
michael@0 | 483 | /* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */ |
michael@0 | 484 | /* mac mmech pad_size mac_size */ |
michael@0 | 485 | { mac_null, mmech_invalid, 0, 0 }, |
michael@0 | 486 | { mac_md5, mmech_md5, 48, MD5_LENGTH }, |
michael@0 | 487 | { mac_sha, mmech_sha, 40, SHA1_LENGTH}, |
michael@0 | 488 | {hmac_md5, mmech_md5_hmac, 0, MD5_LENGTH }, |
michael@0 | 489 | {hmac_sha, mmech_sha_hmac, 0, SHA1_LENGTH}, |
michael@0 | 490 | {hmac_sha256, mmech_sha256_hmac, 0, SHA256_LENGTH}, |
michael@0 | 491 | { mac_aead, mmech_invalid, 0, 0 }, |
michael@0 | 492 | }; |
michael@0 | 493 | |
michael@0 | 494 | /* indexed by SSL3BulkCipher */ |
michael@0 | 495 | const char * const ssl3_cipherName[] = { |
michael@0 | 496 | "NULL", |
michael@0 | 497 | "RC4", |
michael@0 | 498 | "RC4-40", |
michael@0 | 499 | "RC4-56", |
michael@0 | 500 | "RC2-CBC", |
michael@0 | 501 | "RC2-CBC-40", |
michael@0 | 502 | "DES-CBC", |
michael@0 | 503 | "3DES-EDE-CBC", |
michael@0 | 504 | "DES-CBC-40", |
michael@0 | 505 | "IDEA-CBC", |
michael@0 | 506 | "AES-128", |
michael@0 | 507 | "AES-256", |
michael@0 | 508 | "Camellia-128", |
michael@0 | 509 | "Camellia-256", |
michael@0 | 510 | "SEED-CBC", |
michael@0 | 511 | "AES-128-GCM", |
michael@0 | 512 | "missing" |
michael@0 | 513 | }; |
michael@0 | 514 | |
michael@0 | 515 | #ifndef NSS_DISABLE_ECC |
michael@0 | 516 | /* The ECCWrappedKeyInfo structure defines how various pieces of |
michael@0 | 517 | * information are laid out within wrappedSymmetricWrappingkey |
michael@0 | 518 | * for ECDH key exchange. Since wrappedSymmetricWrappingkey is |
michael@0 | 519 | * a 512-byte buffer (see sslimpl.h), the variable length field |
michael@0 | 520 | * in ECCWrappedKeyInfo can be at most (512 - 8) = 504 bytes. |
michael@0 | 521 | * |
michael@0 | 522 | * XXX For now, NSS only supports named elliptic curves of size 571 bits |
michael@0 | 523 | * or smaller. The public value will fit within 145 bytes and EC params |
michael@0 | 524 | * will fit within 12 bytes. We'll need to revisit this when NSS |
michael@0 | 525 | * supports arbitrary curves. |
michael@0 | 526 | */ |
michael@0 | 527 | #define MAX_EC_WRAPPED_KEY_BUFLEN 504 |
michael@0 | 528 | |
michael@0 | 529 | typedef struct ECCWrappedKeyInfoStr { |
michael@0 | 530 | PRUint16 size; /* EC public key size in bits */ |
michael@0 | 531 | PRUint16 encodedParamLen; /* length (in bytes) of DER encoded EC params */ |
michael@0 | 532 | PRUint16 pubValueLen; /* length (in bytes) of EC public value */ |
michael@0 | 533 | PRUint16 wrappedKeyLen; /* length (in bytes) of the wrapped key */ |
michael@0 | 534 | PRUint8 var[MAX_EC_WRAPPED_KEY_BUFLEN]; /* this buffer contains the */ |
michael@0 | 535 | /* EC public-key params, the EC public value and the wrapped key */ |
michael@0 | 536 | } ECCWrappedKeyInfo; |
michael@0 | 537 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 538 | |
michael@0 | 539 | #if defined(TRACE) |
michael@0 | 540 | |
michael@0 | 541 | static char * |
michael@0 | 542 | ssl3_DecodeHandshakeType(int msgType) |
michael@0 | 543 | { |
michael@0 | 544 | char * rv; |
michael@0 | 545 | static char line[40]; |
michael@0 | 546 | |
michael@0 | 547 | switch(msgType) { |
michael@0 | 548 | case hello_request: rv = "hello_request (0)"; break; |
michael@0 | 549 | case client_hello: rv = "client_hello (1)"; break; |
michael@0 | 550 | case server_hello: rv = "server_hello (2)"; break; |
michael@0 | 551 | case hello_verify_request: rv = "hello_verify_request (3)"; break; |
michael@0 | 552 | case certificate: rv = "certificate (11)"; break; |
michael@0 | 553 | case server_key_exchange: rv = "server_key_exchange (12)"; break; |
michael@0 | 554 | case certificate_request: rv = "certificate_request (13)"; break; |
michael@0 | 555 | case server_hello_done: rv = "server_hello_done (14)"; break; |
michael@0 | 556 | case certificate_verify: rv = "certificate_verify (15)"; break; |
michael@0 | 557 | case client_key_exchange: rv = "client_key_exchange (16)"; break; |
michael@0 | 558 | case finished: rv = "finished (20)"; break; |
michael@0 | 559 | default: |
michael@0 | 560 | sprintf(line, "*UNKNOWN* handshake type! (%d)", msgType); |
michael@0 | 561 | rv = line; |
michael@0 | 562 | } |
michael@0 | 563 | return rv; |
michael@0 | 564 | } |
michael@0 | 565 | |
michael@0 | 566 | static char * |
michael@0 | 567 | ssl3_DecodeContentType(int msgType) |
michael@0 | 568 | { |
michael@0 | 569 | char * rv; |
michael@0 | 570 | static char line[40]; |
michael@0 | 571 | |
michael@0 | 572 | switch(msgType) { |
michael@0 | 573 | case content_change_cipher_spec: |
michael@0 | 574 | rv = "change_cipher_spec (20)"; break; |
michael@0 | 575 | case content_alert: rv = "alert (21)"; break; |
michael@0 | 576 | case content_handshake: rv = "handshake (22)"; break; |
michael@0 | 577 | case content_application_data: |
michael@0 | 578 | rv = "application_data (23)"; break; |
michael@0 | 579 | default: |
michael@0 | 580 | sprintf(line, "*UNKNOWN* record type! (%d)", msgType); |
michael@0 | 581 | rv = line; |
michael@0 | 582 | } |
michael@0 | 583 | return rv; |
michael@0 | 584 | } |
michael@0 | 585 | |
michael@0 | 586 | #endif |
michael@0 | 587 | |
michael@0 | 588 | SSL3Statistics * |
michael@0 | 589 | SSL_GetStatistics(void) |
michael@0 | 590 | { |
michael@0 | 591 | return &ssl3stats; |
michael@0 | 592 | } |
michael@0 | 593 | |
michael@0 | 594 | typedef struct tooLongStr { |
michael@0 | 595 | #if defined(IS_LITTLE_ENDIAN) |
michael@0 | 596 | PRInt32 low; |
michael@0 | 597 | PRInt32 high; |
michael@0 | 598 | #else |
michael@0 | 599 | PRInt32 high; |
michael@0 | 600 | PRInt32 low; |
michael@0 | 601 | #endif |
michael@0 | 602 | } tooLong; |
michael@0 | 603 | |
michael@0 | 604 | void SSL_AtomicIncrementLong(long * x) |
michael@0 | 605 | { |
michael@0 | 606 | if ((sizeof *x) == sizeof(PRInt32)) { |
michael@0 | 607 | PR_ATOMIC_INCREMENT((PRInt32 *)x); |
michael@0 | 608 | } else { |
michael@0 | 609 | tooLong * tl = (tooLong *)x; |
michael@0 | 610 | if (PR_ATOMIC_INCREMENT(&tl->low) == 0) |
michael@0 | 611 | PR_ATOMIC_INCREMENT(&tl->high); |
michael@0 | 612 | } |
michael@0 | 613 | } |
michael@0 | 614 | |
michael@0 | 615 | static PRBool |
michael@0 | 616 | ssl3_CipherSuiteAllowedForVersionRange( |
michael@0 | 617 | ssl3CipherSuite cipherSuite, |
michael@0 | 618 | const SSLVersionRange *vrange) |
michael@0 | 619 | { |
michael@0 | 620 | switch (cipherSuite) { |
michael@0 | 621 | /* See RFC 4346 A.5. Export cipher suites must not be used in TLS 1.1 or |
michael@0 | 622 | * later. This set of cipher suites is similar to, but different from, the |
michael@0 | 623 | * set of cipher suites considered exportable by SSL_IsExportCipherSuite. |
michael@0 | 624 | */ |
michael@0 | 625 | case TLS_RSA_EXPORT_WITH_RC4_40_MD5: |
michael@0 | 626 | case TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5: |
michael@0 | 627 | /* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented |
michael@0 | 628 | * TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented |
michael@0 | 629 | * TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented |
michael@0 | 630 | * TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented |
michael@0 | 631 | * TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented |
michael@0 | 632 | * TLS_DH_anon_EXPORT_WITH_RC4_40_MD5: never implemented |
michael@0 | 633 | * TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA: never implemented |
michael@0 | 634 | */ |
michael@0 | 635 | return vrange->min <= SSL_LIBRARY_VERSION_TLS_1_0; |
michael@0 | 636 | |
michael@0 | 637 | case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: |
michael@0 | 638 | case TLS_RSA_WITH_AES_256_CBC_SHA256: |
michael@0 | 639 | case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: |
michael@0 | 640 | case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: |
michael@0 | 641 | case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: |
michael@0 | 642 | case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: |
michael@0 | 643 | case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: |
michael@0 | 644 | case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: |
michael@0 | 645 | case TLS_RSA_WITH_AES_128_CBC_SHA256: |
michael@0 | 646 | case TLS_RSA_WITH_AES_128_GCM_SHA256: |
michael@0 | 647 | case TLS_RSA_WITH_NULL_SHA256: |
michael@0 | 648 | return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2; |
michael@0 | 649 | |
michael@0 | 650 | /* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and |
michael@0 | 651 | * point formats.*/ |
michael@0 | 652 | case TLS_ECDH_ECDSA_WITH_NULL_SHA: |
michael@0 | 653 | case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: |
michael@0 | 654 | case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: |
michael@0 | 655 | case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: |
michael@0 | 656 | case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: |
michael@0 | 657 | case TLS_ECDHE_ECDSA_WITH_NULL_SHA: |
michael@0 | 658 | case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: |
michael@0 | 659 | case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: |
michael@0 | 660 | case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: |
michael@0 | 661 | case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: |
michael@0 | 662 | case TLS_ECDH_RSA_WITH_NULL_SHA: |
michael@0 | 663 | case TLS_ECDH_RSA_WITH_RC4_128_SHA: |
michael@0 | 664 | case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: |
michael@0 | 665 | case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: |
michael@0 | 666 | case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: |
michael@0 | 667 | case TLS_ECDHE_RSA_WITH_NULL_SHA: |
michael@0 | 668 | case TLS_ECDHE_RSA_WITH_RC4_128_SHA: |
michael@0 | 669 | case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: |
michael@0 | 670 | case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: |
michael@0 | 671 | case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: |
michael@0 | 672 | return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0; |
michael@0 | 673 | |
michael@0 | 674 | default: |
michael@0 | 675 | return PR_TRUE; |
michael@0 | 676 | } |
michael@0 | 677 | } |
michael@0 | 678 | |
michael@0 | 679 | /* return pointer to ssl3CipherSuiteDef for suite, or NULL */ |
michael@0 | 680 | /* XXX This does a linear search. A binary search would be better. */ |
michael@0 | 681 | static const ssl3CipherSuiteDef * |
michael@0 | 682 | ssl_LookupCipherSuiteDef(ssl3CipherSuite suite) |
michael@0 | 683 | { |
michael@0 | 684 | int cipher_suite_def_len = |
michael@0 | 685 | sizeof(cipher_suite_defs) / sizeof(cipher_suite_defs[0]); |
michael@0 | 686 | int i; |
michael@0 | 687 | |
michael@0 | 688 | for (i = 0; i < cipher_suite_def_len; i++) { |
michael@0 | 689 | if (cipher_suite_defs[i].cipher_suite == suite) |
michael@0 | 690 | return &cipher_suite_defs[i]; |
michael@0 | 691 | } |
michael@0 | 692 | PORT_Assert(PR_FALSE); /* We should never get here. */ |
michael@0 | 693 | PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); |
michael@0 | 694 | return NULL; |
michael@0 | 695 | } |
michael@0 | 696 | |
michael@0 | 697 | /* Find the cipher configuration struct associate with suite */ |
michael@0 | 698 | /* XXX This does a linear search. A binary search would be better. */ |
michael@0 | 699 | static ssl3CipherSuiteCfg * |
michael@0 | 700 | ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites) |
michael@0 | 701 | { |
michael@0 | 702 | int i; |
michael@0 | 703 | |
michael@0 | 704 | for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
michael@0 | 705 | if (suites[i].cipher_suite == suite) |
michael@0 | 706 | return &suites[i]; |
michael@0 | 707 | } |
michael@0 | 708 | /* return NULL and let the caller handle it. */ |
michael@0 | 709 | PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE); |
michael@0 | 710 | return NULL; |
michael@0 | 711 | } |
michael@0 | 712 | |
michael@0 | 713 | |
michael@0 | 714 | /* Initialize the suite->isPresent value for config_match |
michael@0 | 715 | * Returns count of enabled ciphers supported by extant tokens, |
michael@0 | 716 | * regardless of policy or user preference. |
michael@0 | 717 | * If this returns zero, the user cannot do SSL v3. |
michael@0 | 718 | */ |
michael@0 | 719 | int |
michael@0 | 720 | ssl3_config_match_init(sslSocket *ss) |
michael@0 | 721 | { |
michael@0 | 722 | ssl3CipherSuiteCfg * suite; |
michael@0 | 723 | const ssl3CipherSuiteDef *cipher_def; |
michael@0 | 724 | SSLCipherAlgorithm cipher_alg; |
michael@0 | 725 | CK_MECHANISM_TYPE cipher_mech; |
michael@0 | 726 | SSL3KEAType exchKeyType; |
michael@0 | 727 | int i; |
michael@0 | 728 | int numPresent = 0; |
michael@0 | 729 | int numEnabled = 0; |
michael@0 | 730 | PRBool isServer; |
michael@0 | 731 | sslServerCerts *svrAuth; |
michael@0 | 732 | |
michael@0 | 733 | PORT_Assert(ss); |
michael@0 | 734 | if (!ss) { |
michael@0 | 735 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 736 | return 0; |
michael@0 | 737 | } |
michael@0 | 738 | if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
michael@0 | 739 | return 0; |
michael@0 | 740 | } |
michael@0 | 741 | isServer = (PRBool)(ss->sec.isServer != 0); |
michael@0 | 742 | |
michael@0 | 743 | for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
michael@0 | 744 | suite = &ss->cipherSuites[i]; |
michael@0 | 745 | if (suite->enabled) { |
michael@0 | 746 | ++numEnabled; |
michael@0 | 747 | /* We need the cipher defs to see if we have a token that can handle |
michael@0 | 748 | * this cipher. It isn't part of the static definition. |
michael@0 | 749 | */ |
michael@0 | 750 | cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite); |
michael@0 | 751 | if (!cipher_def) { |
michael@0 | 752 | suite->isPresent = PR_FALSE; |
michael@0 | 753 | continue; |
michael@0 | 754 | } |
michael@0 | 755 | cipher_alg = bulk_cipher_defs[cipher_def->bulk_cipher_alg].calg; |
michael@0 | 756 | PORT_Assert( alg2Mech[cipher_alg].calg == cipher_alg); |
michael@0 | 757 | cipher_mech = alg2Mech[cipher_alg].cmech; |
michael@0 | 758 | exchKeyType = |
michael@0 | 759 | kea_defs[cipher_def->key_exchange_alg].exchKeyType; |
michael@0 | 760 | #ifdef NSS_DISABLE_ECC |
michael@0 | 761 | svrAuth = ss->serverCerts + exchKeyType; |
michael@0 | 762 | #else |
michael@0 | 763 | /* XXX SSLKEAType isn't really a good choice for |
michael@0 | 764 | * indexing certificates. It doesn't work for |
michael@0 | 765 | * (EC)DHE-* ciphers. Here we use a hack to ensure |
michael@0 | 766 | * that the server uses an RSA cert for (EC)DHE-RSA. |
michael@0 | 767 | */ |
michael@0 | 768 | switch (cipher_def->key_exchange_alg) { |
michael@0 | 769 | case kea_ecdhe_rsa: |
michael@0 | 770 | #if NSS_SERVER_DHE_IMPLEMENTED |
michael@0 | 771 | /* XXX NSS does not yet implement the server side of _DHE_ |
michael@0 | 772 | * cipher suites. Correcting the computation for svrAuth, |
michael@0 | 773 | * as the case below does, causes NSS SSL servers to begin to |
michael@0 | 774 | * negotiate cipher suites they do not implement. So, until |
michael@0 | 775 | * server side _DHE_ is implemented, keep this disabled. |
michael@0 | 776 | */ |
michael@0 | 777 | case kea_dhe_rsa: |
michael@0 | 778 | #endif |
michael@0 | 779 | svrAuth = ss->serverCerts + kt_rsa; |
michael@0 | 780 | break; |
michael@0 | 781 | case kea_ecdh_ecdsa: |
michael@0 | 782 | case kea_ecdh_rsa: |
michael@0 | 783 | /* |
michael@0 | 784 | * XXX We ought to have different indices for |
michael@0 | 785 | * ECDSA- and RSA-signed EC certificates so |
michael@0 | 786 | * we could support both key exchange mechanisms |
michael@0 | 787 | * simultaneously. For now, both of them use |
michael@0 | 788 | * whatever is in the certificate slot for kt_ecdh |
michael@0 | 789 | */ |
michael@0 | 790 | default: |
michael@0 | 791 | svrAuth = ss->serverCerts + exchKeyType; |
michael@0 | 792 | break; |
michael@0 | 793 | } |
michael@0 | 794 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 795 | |
michael@0 | 796 | /* Mark the suites that are backed by real tokens, certs and keys */ |
michael@0 | 797 | suite->isPresent = (PRBool) |
michael@0 | 798 | (((exchKeyType == kt_null) || |
michael@0 | 799 | ((!isServer || (svrAuth->serverKeyPair && |
michael@0 | 800 | svrAuth->SERVERKEY && |
michael@0 | 801 | svrAuth->serverCertChain)) && |
michael@0 | 802 | PK11_TokenExists(kea_alg_defs[exchKeyType]))) && |
michael@0 | 803 | ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech))); |
michael@0 | 804 | if (suite->isPresent) |
michael@0 | 805 | ++numPresent; |
michael@0 | 806 | } |
michael@0 | 807 | } |
michael@0 | 808 | PORT_Assert(numPresent > 0 || numEnabled == 0); |
michael@0 | 809 | if (numPresent <= 0) { |
michael@0 | 810 | PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED); |
michael@0 | 811 | } |
michael@0 | 812 | return numPresent; |
michael@0 | 813 | } |
michael@0 | 814 | |
michael@0 | 815 | |
michael@0 | 816 | /* return PR_TRUE if suite matches policy, enabled state and is applicable to |
michael@0 | 817 | * the given version range. */ |
michael@0 | 818 | /* It would be a REALLY BAD THING (tm) if we ever permitted the use |
michael@0 | 819 | ** of a cipher that was NOT_ALLOWED. So, if this is ever called with |
michael@0 | 820 | ** policy == SSL_NOT_ALLOWED, report no match. |
michael@0 | 821 | */ |
michael@0 | 822 | /* adjust suite enabled to the availability of a token that can do the |
michael@0 | 823 | * cipher suite. */ |
michael@0 | 824 | static PRBool |
michael@0 | 825 | config_match(ssl3CipherSuiteCfg *suite, int policy, PRBool enabled, |
michael@0 | 826 | const SSLVersionRange *vrange) |
michael@0 | 827 | { |
michael@0 | 828 | PORT_Assert(policy != SSL_NOT_ALLOWED && enabled != PR_FALSE); |
michael@0 | 829 | if (policy == SSL_NOT_ALLOWED || !enabled) |
michael@0 | 830 | return PR_FALSE; |
michael@0 | 831 | return (PRBool)(suite->enabled && |
michael@0 | 832 | suite->isPresent && |
michael@0 | 833 | suite->policy != SSL_NOT_ALLOWED && |
michael@0 | 834 | suite->policy <= policy && |
michael@0 | 835 | ssl3_CipherSuiteAllowedForVersionRange( |
michael@0 | 836 | suite->cipher_suite, vrange)); |
michael@0 | 837 | } |
michael@0 | 838 | |
michael@0 | 839 | /* return number of cipher suites that match policy, enabled state and are |
michael@0 | 840 | * applicable for the configured protocol version range. */ |
michael@0 | 841 | /* called from ssl3_SendClientHello and ssl3_ConstructV2CipherSpecsHack */ |
michael@0 | 842 | static int |
michael@0 | 843 | count_cipher_suites(sslSocket *ss, int policy, PRBool enabled) |
michael@0 | 844 | { |
michael@0 | 845 | int i, count = 0; |
michael@0 | 846 | |
michael@0 | 847 | if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
michael@0 | 848 | return 0; |
michael@0 | 849 | } |
michael@0 | 850 | for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
michael@0 | 851 | if (config_match(&ss->cipherSuites[i], policy, enabled, &ss->vrange)) |
michael@0 | 852 | count++; |
michael@0 | 853 | } |
michael@0 | 854 | if (count <= 0) { |
michael@0 | 855 | PORT_SetError(SSL_ERROR_SSL_DISABLED); |
michael@0 | 856 | } |
michael@0 | 857 | return count; |
michael@0 | 858 | } |
michael@0 | 859 | |
michael@0 | 860 | /* |
michael@0 | 861 | * Null compression, mac and encryption functions |
michael@0 | 862 | */ |
michael@0 | 863 | |
michael@0 | 864 | static SECStatus |
michael@0 | 865 | Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, |
michael@0 | 866 | const unsigned char *input, int inputLen) |
michael@0 | 867 | { |
michael@0 | 868 | if (inputLen > maxOutputLen) { |
michael@0 | 869 | *outputLen = 0; /* Match PK11_CipherOp in setting outputLen */ |
michael@0 | 870 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
michael@0 | 871 | return SECFailure; |
michael@0 | 872 | } |
michael@0 | 873 | *outputLen = inputLen; |
michael@0 | 874 | if (input != output) |
michael@0 | 875 | PORT_Memcpy(output, input, inputLen); |
michael@0 | 876 | return SECSuccess; |
michael@0 | 877 | } |
michael@0 | 878 | |
michael@0 | 879 | /* |
michael@0 | 880 | * SSL3 Utility functions |
michael@0 | 881 | */ |
michael@0 | 882 | |
michael@0 | 883 | /* allowLargerPeerVersion controls whether the function will select the |
michael@0 | 884 | * highest enabled SSL version or fail when peerVersion is greater than the |
michael@0 | 885 | * highest enabled version. |
michael@0 | 886 | * |
michael@0 | 887 | * If allowLargerPeerVersion is true, peerVersion is the peer's highest |
michael@0 | 888 | * enabled version rather than the peer's selected version. |
michael@0 | 889 | */ |
michael@0 | 890 | SECStatus |
michael@0 | 891 | ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion, |
michael@0 | 892 | PRBool allowLargerPeerVersion) |
michael@0 | 893 | { |
michael@0 | 894 | if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
michael@0 | 895 | PORT_SetError(SSL_ERROR_SSL_DISABLED); |
michael@0 | 896 | return SECFailure; |
michael@0 | 897 | } |
michael@0 | 898 | |
michael@0 | 899 | if (peerVersion < ss->vrange.min || |
michael@0 | 900 | (peerVersion > ss->vrange.max && !allowLargerPeerVersion)) { |
michael@0 | 901 | PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); |
michael@0 | 902 | return SECFailure; |
michael@0 | 903 | } |
michael@0 | 904 | |
michael@0 | 905 | ss->version = PR_MIN(peerVersion, ss->vrange.max); |
michael@0 | 906 | PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, ss->version)); |
michael@0 | 907 | |
michael@0 | 908 | return SECSuccess; |
michael@0 | 909 | } |
michael@0 | 910 | |
michael@0 | 911 | static SECStatus |
michael@0 | 912 | ssl3_GetNewRandom(SSL3Random *random) |
michael@0 | 913 | { |
michael@0 | 914 | SECStatus rv; |
michael@0 | 915 | |
michael@0 | 916 | /* first 4 bytes are reserverd for time */ |
michael@0 | 917 | rv = PK11_GenerateRandom(random->rand, SSL3_RANDOM_LENGTH); |
michael@0 | 918 | if (rv != SECSuccess) { |
michael@0 | 919 | ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); |
michael@0 | 920 | } |
michael@0 | 921 | return rv; |
michael@0 | 922 | } |
michael@0 | 923 | |
michael@0 | 924 | /* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */ |
michael@0 | 925 | SECStatus |
michael@0 | 926 | ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf, |
michael@0 | 927 | PRBool isTLS) |
michael@0 | 928 | { |
michael@0 | 929 | SECStatus rv = SECFailure; |
michael@0 | 930 | PRBool doDerEncode = PR_FALSE; |
michael@0 | 931 | int signatureLen; |
michael@0 | 932 | SECItem hashItem; |
michael@0 | 933 | |
michael@0 | 934 | buf->data = NULL; |
michael@0 | 935 | |
michael@0 | 936 | switch (key->keyType) { |
michael@0 | 937 | case rsaKey: |
michael@0 | 938 | hashItem.data = hash->u.raw; |
michael@0 | 939 | hashItem.len = hash->len; |
michael@0 | 940 | break; |
michael@0 | 941 | case dsaKey: |
michael@0 | 942 | doDerEncode = isTLS; |
michael@0 | 943 | /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash. |
michael@0 | 944 | * In that case, we use just the SHA1 part. */ |
michael@0 | 945 | if (hash->hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 946 | hashItem.data = hash->u.s.sha; |
michael@0 | 947 | hashItem.len = sizeof(hash->u.s.sha); |
michael@0 | 948 | } else { |
michael@0 | 949 | hashItem.data = hash->u.raw; |
michael@0 | 950 | hashItem.len = hash->len; |
michael@0 | 951 | } |
michael@0 | 952 | break; |
michael@0 | 953 | #ifndef NSS_DISABLE_ECC |
michael@0 | 954 | case ecKey: |
michael@0 | 955 | doDerEncode = PR_TRUE; |
michael@0 | 956 | /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash. |
michael@0 | 957 | * In that case, we use just the SHA1 part. */ |
michael@0 | 958 | if (hash->hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 959 | hashItem.data = hash->u.s.sha; |
michael@0 | 960 | hashItem.len = sizeof(hash->u.s.sha); |
michael@0 | 961 | } else { |
michael@0 | 962 | hashItem.data = hash->u.raw; |
michael@0 | 963 | hashItem.len = hash->len; |
michael@0 | 964 | } |
michael@0 | 965 | break; |
michael@0 | 966 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 967 | default: |
michael@0 | 968 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
michael@0 | 969 | goto done; |
michael@0 | 970 | } |
michael@0 | 971 | PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len)); |
michael@0 | 972 | |
michael@0 | 973 | if (hash->hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 974 | signatureLen = PK11_SignatureLen(key); |
michael@0 | 975 | if (signatureLen <= 0) { |
michael@0 | 976 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
michael@0 | 977 | goto done; |
michael@0 | 978 | } |
michael@0 | 979 | |
michael@0 | 980 | buf->len = (unsigned)signatureLen; |
michael@0 | 981 | buf->data = (unsigned char *)PORT_Alloc(signatureLen); |
michael@0 | 982 | if (!buf->data) |
michael@0 | 983 | goto done; /* error code was set. */ |
michael@0 | 984 | |
michael@0 | 985 | rv = PK11_Sign(key, buf, &hashItem); |
michael@0 | 986 | } else { |
michael@0 | 987 | rv = SGN_Digest(key, hash->hashAlg, buf, &hashItem); |
michael@0 | 988 | } |
michael@0 | 989 | if (rv != SECSuccess) { |
michael@0 | 990 | ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE); |
michael@0 | 991 | } else if (doDerEncode) { |
michael@0 | 992 | SECItem derSig = {siBuffer, NULL, 0}; |
michael@0 | 993 | |
michael@0 | 994 | /* This also works for an ECDSA signature */ |
michael@0 | 995 | rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); |
michael@0 | 996 | if (rv == SECSuccess) { |
michael@0 | 997 | PORT_Free(buf->data); /* discard unencoded signature. */ |
michael@0 | 998 | *buf = derSig; /* give caller encoded signature. */ |
michael@0 | 999 | } else if (derSig.data) { |
michael@0 | 1000 | PORT_Free(derSig.data); |
michael@0 | 1001 | } |
michael@0 | 1002 | } |
michael@0 | 1003 | |
michael@0 | 1004 | PRINT_BUF(60, (NULL, "signed hashes", (unsigned char*)buf->data, buf->len)); |
michael@0 | 1005 | done: |
michael@0 | 1006 | if (rv != SECSuccess && buf->data) { |
michael@0 | 1007 | PORT_Free(buf->data); |
michael@0 | 1008 | buf->data = NULL; |
michael@0 | 1009 | } |
michael@0 | 1010 | return rv; |
michael@0 | 1011 | } |
michael@0 | 1012 | |
michael@0 | 1013 | /* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */ |
michael@0 | 1014 | SECStatus |
michael@0 | 1015 | ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, |
michael@0 | 1016 | SECItem *buf, PRBool isTLS, void *pwArg) |
michael@0 | 1017 | { |
michael@0 | 1018 | SECKEYPublicKey * key; |
michael@0 | 1019 | SECItem * signature = NULL; |
michael@0 | 1020 | SECStatus rv; |
michael@0 | 1021 | SECItem hashItem; |
michael@0 | 1022 | SECOidTag encAlg; |
michael@0 | 1023 | SECOidTag hashAlg; |
michael@0 | 1024 | |
michael@0 | 1025 | |
michael@0 | 1026 | PRINT_BUF(60, (NULL, "check signed hashes", |
michael@0 | 1027 | buf->data, buf->len)); |
michael@0 | 1028 | |
michael@0 | 1029 | key = CERT_ExtractPublicKey(cert); |
michael@0 | 1030 | if (key == NULL) { |
michael@0 | 1031 | ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); |
michael@0 | 1032 | return SECFailure; |
michael@0 | 1033 | } |
michael@0 | 1034 | |
michael@0 | 1035 | hashAlg = hash->hashAlg; |
michael@0 | 1036 | switch (key->keyType) { |
michael@0 | 1037 | case rsaKey: |
michael@0 | 1038 | encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION; |
michael@0 | 1039 | hashItem.data = hash->u.raw; |
michael@0 | 1040 | hashItem.len = hash->len; |
michael@0 | 1041 | break; |
michael@0 | 1042 | case dsaKey: |
michael@0 | 1043 | encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE; |
michael@0 | 1044 | /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash. |
michael@0 | 1045 | * In that case, we use just the SHA1 part. */ |
michael@0 | 1046 | if (hash->hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 1047 | hashItem.data = hash->u.s.sha; |
michael@0 | 1048 | hashItem.len = sizeof(hash->u.s.sha); |
michael@0 | 1049 | } else { |
michael@0 | 1050 | hashItem.data = hash->u.raw; |
michael@0 | 1051 | hashItem.len = hash->len; |
michael@0 | 1052 | } |
michael@0 | 1053 | /* Allow DER encoded DSA signatures in SSL 3.0 */ |
michael@0 | 1054 | if (isTLS || buf->len != SECKEY_SignatureLen(key)) { |
michael@0 | 1055 | signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key)); |
michael@0 | 1056 | if (!signature) { |
michael@0 | 1057 | PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
michael@0 | 1058 | return SECFailure; |
michael@0 | 1059 | } |
michael@0 | 1060 | buf = signature; |
michael@0 | 1061 | } |
michael@0 | 1062 | break; |
michael@0 | 1063 | |
michael@0 | 1064 | #ifndef NSS_DISABLE_ECC |
michael@0 | 1065 | case ecKey: |
michael@0 | 1066 | encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY; |
michael@0 | 1067 | /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated hash. |
michael@0 | 1068 | * In that case, we use just the SHA1 part. |
michael@0 | 1069 | * ECDSA signatures always encode the integers r and s using ASN.1 |
michael@0 | 1070 | * (unlike DSA where ASN.1 encoding is used with TLS but not with |
michael@0 | 1071 | * SSL3). So we can use VFY_VerifyDigestDirect for ECDSA. |
michael@0 | 1072 | */ |
michael@0 | 1073 | if (hash->hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 1074 | hashAlg = SEC_OID_SHA1; |
michael@0 | 1075 | hashItem.data = hash->u.s.sha; |
michael@0 | 1076 | hashItem.len = sizeof(hash->u.s.sha); |
michael@0 | 1077 | } else { |
michael@0 | 1078 | hashItem.data = hash->u.raw; |
michael@0 | 1079 | hashItem.len = hash->len; |
michael@0 | 1080 | } |
michael@0 | 1081 | break; |
michael@0 | 1082 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 1083 | |
michael@0 | 1084 | default: |
michael@0 | 1085 | SECKEY_DestroyPublicKey(key); |
michael@0 | 1086 | PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
michael@0 | 1087 | return SECFailure; |
michael@0 | 1088 | } |
michael@0 | 1089 | |
michael@0 | 1090 | PRINT_BUF(60, (NULL, "hash(es) to be verified", |
michael@0 | 1091 | hashItem.data, hashItem.len)); |
michael@0 | 1092 | |
michael@0 | 1093 | if (hashAlg == SEC_OID_UNKNOWN || key->keyType == dsaKey) { |
michael@0 | 1094 | /* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded. |
michael@0 | 1095 | * DSA signatures are DER-encoded in TLS but not in SSL3 and the code |
michael@0 | 1096 | * above always removes the DER encoding of DSA signatures when |
michael@0 | 1097 | * present. Thus DSA signatures are always verified with PK11_Verify. |
michael@0 | 1098 | */ |
michael@0 | 1099 | rv = PK11_Verify(key, buf, &hashItem, pwArg); |
michael@0 | 1100 | } else { |
michael@0 | 1101 | rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg, |
michael@0 | 1102 | pwArg); |
michael@0 | 1103 | } |
michael@0 | 1104 | SECKEY_DestroyPublicKey(key); |
michael@0 | 1105 | if (signature) { |
michael@0 | 1106 | SECITEM_FreeItem(signature, PR_TRUE); |
michael@0 | 1107 | } |
michael@0 | 1108 | if (rv != SECSuccess) { |
michael@0 | 1109 | ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
michael@0 | 1110 | } |
michael@0 | 1111 | return rv; |
michael@0 | 1112 | } |
michael@0 | 1113 | |
michael@0 | 1114 | |
michael@0 | 1115 | /* Caller must set hiLevel error code. */ |
michael@0 | 1116 | /* Called from ssl3_ComputeExportRSAKeyHash |
michael@0 | 1117 | * ssl3_ComputeDHKeyHash |
michael@0 | 1118 | * which are called from ssl3_HandleServerKeyExchange. |
michael@0 | 1119 | * |
michael@0 | 1120 | * hashAlg: either the OID for a hash algorithm or SEC_OID_UNKNOWN to specify |
michael@0 | 1121 | * the pre-1.2, MD5/SHA1 combination hash. |
michael@0 | 1122 | */ |
michael@0 | 1123 | SECStatus |
michael@0 | 1124 | ssl3_ComputeCommonKeyHash(SECOidTag hashAlg, |
michael@0 | 1125 | PRUint8 * hashBuf, unsigned int bufLen, |
michael@0 | 1126 | SSL3Hashes *hashes, PRBool bypassPKCS11) |
michael@0 | 1127 | { |
michael@0 | 1128 | SECStatus rv = SECSuccess; |
michael@0 | 1129 | |
michael@0 | 1130 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1131 | if (bypassPKCS11) { |
michael@0 | 1132 | if (hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 1133 | MD5_HashBuf (hashes->u.s.md5, hashBuf, bufLen); |
michael@0 | 1134 | SHA1_HashBuf(hashes->u.s.sha, hashBuf, bufLen); |
michael@0 | 1135 | hashes->len = MD5_LENGTH + SHA1_LENGTH; |
michael@0 | 1136 | } else if (hashAlg == SEC_OID_SHA1) { |
michael@0 | 1137 | SHA1_HashBuf(hashes->u.raw, hashBuf, bufLen); |
michael@0 | 1138 | hashes->len = SHA1_LENGTH; |
michael@0 | 1139 | } else if (hashAlg == SEC_OID_SHA256) { |
michael@0 | 1140 | SHA256_HashBuf(hashes->u.raw, hashBuf, bufLen); |
michael@0 | 1141 | hashes->len = SHA256_LENGTH; |
michael@0 | 1142 | } else if (hashAlg == SEC_OID_SHA384) { |
michael@0 | 1143 | SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen); |
michael@0 | 1144 | hashes->len = SHA384_LENGTH; |
michael@0 | 1145 | } else if (hashAlg == SEC_OID_SHA512) { |
michael@0 | 1146 | SHA512_HashBuf(hashes->u.raw, hashBuf, bufLen); |
michael@0 | 1147 | hashes->len = SHA512_LENGTH; |
michael@0 | 1148 | } else { |
michael@0 | 1149 | PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); |
michael@0 | 1150 | return SECFailure; |
michael@0 | 1151 | } |
michael@0 | 1152 | } else |
michael@0 | 1153 | #endif |
michael@0 | 1154 | { |
michael@0 | 1155 | if (hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 1156 | rv = PK11_HashBuf(SEC_OID_MD5, hashes->u.s.md5, hashBuf, bufLen); |
michael@0 | 1157 | if (rv != SECSuccess) { |
michael@0 | 1158 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 1159 | rv = SECFailure; |
michael@0 | 1160 | goto done; |
michael@0 | 1161 | } |
michael@0 | 1162 | |
michael@0 | 1163 | rv = PK11_HashBuf(SEC_OID_SHA1, hashes->u.s.sha, hashBuf, bufLen); |
michael@0 | 1164 | if (rv != SECSuccess) { |
michael@0 | 1165 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 1166 | rv = SECFailure; |
michael@0 | 1167 | } |
michael@0 | 1168 | hashes->len = MD5_LENGTH + SHA1_LENGTH; |
michael@0 | 1169 | } else { |
michael@0 | 1170 | hashes->len = HASH_ResultLenByOidTag(hashAlg); |
michael@0 | 1171 | if (hashes->len > sizeof(hashes->u.raw)) { |
michael@0 | 1172 | ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); |
michael@0 | 1173 | rv = SECFailure; |
michael@0 | 1174 | goto done; |
michael@0 | 1175 | } |
michael@0 | 1176 | rv = PK11_HashBuf(hashAlg, hashes->u.raw, hashBuf, bufLen); |
michael@0 | 1177 | if (rv != SECSuccess) { |
michael@0 | 1178 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 1179 | rv = SECFailure; |
michael@0 | 1180 | } |
michael@0 | 1181 | } |
michael@0 | 1182 | } |
michael@0 | 1183 | hashes->hashAlg = hashAlg; |
michael@0 | 1184 | |
michael@0 | 1185 | done: |
michael@0 | 1186 | return rv; |
michael@0 | 1187 | } |
michael@0 | 1188 | |
michael@0 | 1189 | /* Caller must set hiLevel error code. |
michael@0 | 1190 | ** Called from ssl3_SendServerKeyExchange and |
michael@0 | 1191 | ** ssl3_HandleServerKeyExchange. |
michael@0 | 1192 | */ |
michael@0 | 1193 | static SECStatus |
michael@0 | 1194 | ssl3_ComputeExportRSAKeyHash(SECOidTag hashAlg, |
michael@0 | 1195 | SECItem modulus, SECItem publicExponent, |
michael@0 | 1196 | SSL3Random *client_rand, SSL3Random *server_rand, |
michael@0 | 1197 | SSL3Hashes *hashes, PRBool bypassPKCS11) |
michael@0 | 1198 | { |
michael@0 | 1199 | PRUint8 * hashBuf; |
michael@0 | 1200 | PRUint8 * pBuf; |
michael@0 | 1201 | SECStatus rv = SECSuccess; |
michael@0 | 1202 | unsigned int bufLen; |
michael@0 | 1203 | PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8]; |
michael@0 | 1204 | |
michael@0 | 1205 | bufLen = 2*SSL3_RANDOM_LENGTH + 2 + modulus.len + 2 + publicExponent.len; |
michael@0 | 1206 | if (bufLen <= sizeof buf) { |
michael@0 | 1207 | hashBuf = buf; |
michael@0 | 1208 | } else { |
michael@0 | 1209 | hashBuf = PORT_Alloc(bufLen); |
michael@0 | 1210 | if (!hashBuf) { |
michael@0 | 1211 | return SECFailure; |
michael@0 | 1212 | } |
michael@0 | 1213 | } |
michael@0 | 1214 | |
michael@0 | 1215 | memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); |
michael@0 | 1216 | pBuf = hashBuf + SSL3_RANDOM_LENGTH; |
michael@0 | 1217 | memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); |
michael@0 | 1218 | pBuf += SSL3_RANDOM_LENGTH; |
michael@0 | 1219 | pBuf[0] = (PRUint8)(modulus.len >> 8); |
michael@0 | 1220 | pBuf[1] = (PRUint8)(modulus.len); |
michael@0 | 1221 | pBuf += 2; |
michael@0 | 1222 | memcpy(pBuf, modulus.data, modulus.len); |
michael@0 | 1223 | pBuf += modulus.len; |
michael@0 | 1224 | pBuf[0] = (PRUint8)(publicExponent.len >> 8); |
michael@0 | 1225 | pBuf[1] = (PRUint8)(publicExponent.len); |
michael@0 | 1226 | pBuf += 2; |
michael@0 | 1227 | memcpy(pBuf, publicExponent.data, publicExponent.len); |
michael@0 | 1228 | pBuf += publicExponent.len; |
michael@0 | 1229 | PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); |
michael@0 | 1230 | |
michael@0 | 1231 | rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes, |
michael@0 | 1232 | bypassPKCS11); |
michael@0 | 1233 | |
michael@0 | 1234 | PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen)); |
michael@0 | 1235 | if (hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 1236 | PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result", |
michael@0 | 1237 | hashes->u.s.md5, MD5_LENGTH)); |
michael@0 | 1238 | PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result", |
michael@0 | 1239 | hashes->u.s.sha, SHA1_LENGTH)); |
michael@0 | 1240 | } else { |
michael@0 | 1241 | PRINT_BUF(95, (NULL, "RSAkey hash: result", |
michael@0 | 1242 | hashes->u.raw, hashes->len)); |
michael@0 | 1243 | } |
michael@0 | 1244 | |
michael@0 | 1245 | if (hashBuf != buf && hashBuf != NULL) |
michael@0 | 1246 | PORT_Free(hashBuf); |
michael@0 | 1247 | return rv; |
michael@0 | 1248 | } |
michael@0 | 1249 | |
michael@0 | 1250 | /* Caller must set hiLevel error code. */ |
michael@0 | 1251 | /* Called from ssl3_HandleServerKeyExchange. */ |
michael@0 | 1252 | static SECStatus |
michael@0 | 1253 | ssl3_ComputeDHKeyHash(SECOidTag hashAlg, |
michael@0 | 1254 | SECItem dh_p, SECItem dh_g, SECItem dh_Ys, |
michael@0 | 1255 | SSL3Random *client_rand, SSL3Random *server_rand, |
michael@0 | 1256 | SSL3Hashes *hashes, PRBool bypassPKCS11) |
michael@0 | 1257 | { |
michael@0 | 1258 | PRUint8 * hashBuf; |
michael@0 | 1259 | PRUint8 * pBuf; |
michael@0 | 1260 | SECStatus rv = SECSuccess; |
michael@0 | 1261 | unsigned int bufLen; |
michael@0 | 1262 | PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8]; |
michael@0 | 1263 | |
michael@0 | 1264 | bufLen = 2*SSL3_RANDOM_LENGTH + 2 + dh_p.len + 2 + dh_g.len + 2 + dh_Ys.len; |
michael@0 | 1265 | if (bufLen <= sizeof buf) { |
michael@0 | 1266 | hashBuf = buf; |
michael@0 | 1267 | } else { |
michael@0 | 1268 | hashBuf = PORT_Alloc(bufLen); |
michael@0 | 1269 | if (!hashBuf) { |
michael@0 | 1270 | return SECFailure; |
michael@0 | 1271 | } |
michael@0 | 1272 | } |
michael@0 | 1273 | |
michael@0 | 1274 | memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); |
michael@0 | 1275 | pBuf = hashBuf + SSL3_RANDOM_LENGTH; |
michael@0 | 1276 | memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); |
michael@0 | 1277 | pBuf += SSL3_RANDOM_LENGTH; |
michael@0 | 1278 | pBuf[0] = (PRUint8)(dh_p.len >> 8); |
michael@0 | 1279 | pBuf[1] = (PRUint8)(dh_p.len); |
michael@0 | 1280 | pBuf += 2; |
michael@0 | 1281 | memcpy(pBuf, dh_p.data, dh_p.len); |
michael@0 | 1282 | pBuf += dh_p.len; |
michael@0 | 1283 | pBuf[0] = (PRUint8)(dh_g.len >> 8); |
michael@0 | 1284 | pBuf[1] = (PRUint8)(dh_g.len); |
michael@0 | 1285 | pBuf += 2; |
michael@0 | 1286 | memcpy(pBuf, dh_g.data, dh_g.len); |
michael@0 | 1287 | pBuf += dh_g.len; |
michael@0 | 1288 | pBuf[0] = (PRUint8)(dh_Ys.len >> 8); |
michael@0 | 1289 | pBuf[1] = (PRUint8)(dh_Ys.len); |
michael@0 | 1290 | pBuf += 2; |
michael@0 | 1291 | memcpy(pBuf, dh_Ys.data, dh_Ys.len); |
michael@0 | 1292 | pBuf += dh_Ys.len; |
michael@0 | 1293 | PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); |
michael@0 | 1294 | |
michael@0 | 1295 | rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes, |
michael@0 | 1296 | bypassPKCS11); |
michael@0 | 1297 | |
michael@0 | 1298 | PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen)); |
michael@0 | 1299 | if (hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 1300 | PRINT_BUF(95, (NULL, "DHkey hash: MD5 result", |
michael@0 | 1301 | hashes->u.s.md5, MD5_LENGTH)); |
michael@0 | 1302 | PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result", |
michael@0 | 1303 | hashes->u.s.sha, SHA1_LENGTH)); |
michael@0 | 1304 | } else { |
michael@0 | 1305 | PRINT_BUF(95, (NULL, "DHkey hash: result", |
michael@0 | 1306 | hashes->u.raw, hashes->len)); |
michael@0 | 1307 | } |
michael@0 | 1308 | |
michael@0 | 1309 | if (hashBuf != buf && hashBuf != NULL) |
michael@0 | 1310 | PORT_Free(hashBuf); |
michael@0 | 1311 | return rv; |
michael@0 | 1312 | } |
michael@0 | 1313 | |
michael@0 | 1314 | static void |
michael@0 | 1315 | ssl3_BumpSequenceNumber(SSL3SequenceNumber *num) |
michael@0 | 1316 | { |
michael@0 | 1317 | num->low++; |
michael@0 | 1318 | if (num->low == 0) |
michael@0 | 1319 | num->high++; |
michael@0 | 1320 | } |
michael@0 | 1321 | |
michael@0 | 1322 | /* Called twice, only from ssl3_DestroyCipherSpec (immediately below). */ |
michael@0 | 1323 | static void |
michael@0 | 1324 | ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) |
michael@0 | 1325 | { |
michael@0 | 1326 | if (mat->write_key != NULL) { |
michael@0 | 1327 | PK11_FreeSymKey(mat->write_key); |
michael@0 | 1328 | mat->write_key = NULL; |
michael@0 | 1329 | } |
michael@0 | 1330 | if (mat->write_mac_key != NULL) { |
michael@0 | 1331 | PK11_FreeSymKey(mat->write_mac_key); |
michael@0 | 1332 | mat->write_mac_key = NULL; |
michael@0 | 1333 | } |
michael@0 | 1334 | if (mat->write_mac_context != NULL) { |
michael@0 | 1335 | PK11_DestroyContext(mat->write_mac_context, PR_TRUE); |
michael@0 | 1336 | mat->write_mac_context = NULL; |
michael@0 | 1337 | } |
michael@0 | 1338 | } |
michael@0 | 1339 | |
michael@0 | 1340 | /* Called from ssl3_SendChangeCipherSpecs() and |
michael@0 | 1341 | ** ssl3_HandleChangeCipherSpecs() |
michael@0 | 1342 | ** ssl3_DestroySSL3Info |
michael@0 | 1343 | ** Caller must hold SpecWriteLock. |
michael@0 | 1344 | */ |
michael@0 | 1345 | void |
michael@0 | 1346 | ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) |
michael@0 | 1347 | { |
michael@0 | 1348 | PRBool freeit = (PRBool)(!spec->bypassCiphers); |
michael@0 | 1349 | /* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */ |
michael@0 | 1350 | if (spec->destroy) { |
michael@0 | 1351 | spec->destroy(spec->encodeContext, freeit); |
michael@0 | 1352 | spec->destroy(spec->decodeContext, freeit); |
michael@0 | 1353 | spec->encodeContext = NULL; /* paranoia */ |
michael@0 | 1354 | spec->decodeContext = NULL; |
michael@0 | 1355 | } |
michael@0 | 1356 | if (spec->destroyCompressContext && spec->compressContext) { |
michael@0 | 1357 | spec->destroyCompressContext(spec->compressContext, 1); |
michael@0 | 1358 | spec->compressContext = NULL; |
michael@0 | 1359 | } |
michael@0 | 1360 | if (spec->destroyDecompressContext && spec->decompressContext) { |
michael@0 | 1361 | spec->destroyDecompressContext(spec->decompressContext, 1); |
michael@0 | 1362 | spec->decompressContext = NULL; |
michael@0 | 1363 | } |
michael@0 | 1364 | if (freeSrvName && spec->srvVirtName.data) { |
michael@0 | 1365 | SECITEM_FreeItem(&spec->srvVirtName, PR_FALSE); |
michael@0 | 1366 | } |
michael@0 | 1367 | if (spec->master_secret != NULL) { |
michael@0 | 1368 | PK11_FreeSymKey(spec->master_secret); |
michael@0 | 1369 | spec->master_secret = NULL; |
michael@0 | 1370 | } |
michael@0 | 1371 | spec->msItem.data = NULL; |
michael@0 | 1372 | spec->msItem.len = 0; |
michael@0 | 1373 | ssl3_CleanupKeyMaterial(&spec->client); |
michael@0 | 1374 | ssl3_CleanupKeyMaterial(&spec->server); |
michael@0 | 1375 | spec->bypassCiphers = PR_FALSE; |
michael@0 | 1376 | spec->destroy=NULL; |
michael@0 | 1377 | spec->destroyCompressContext = NULL; |
michael@0 | 1378 | spec->destroyDecompressContext = NULL; |
michael@0 | 1379 | } |
michael@0 | 1380 | |
michael@0 | 1381 | /* Fill in the pending cipher spec with info from the selected ciphersuite. |
michael@0 | 1382 | ** This is as much initialization as we can do without having key material. |
michael@0 | 1383 | ** Called from ssl3_HandleServerHello(), ssl3_SendServerHello() |
michael@0 | 1384 | ** Caller must hold the ssl3 handshake lock. |
michael@0 | 1385 | ** Acquires & releases SpecWriteLock. |
michael@0 | 1386 | */ |
michael@0 | 1387 | static SECStatus |
michael@0 | 1388 | ssl3_SetupPendingCipherSpec(sslSocket *ss) |
michael@0 | 1389 | { |
michael@0 | 1390 | ssl3CipherSpec * pwSpec; |
michael@0 | 1391 | ssl3CipherSpec * cwSpec; |
michael@0 | 1392 | ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite; |
michael@0 | 1393 | SSL3MACAlgorithm mac; |
michael@0 | 1394 | SSL3BulkCipher cipher; |
michael@0 | 1395 | SSL3KeyExchangeAlgorithm kea; |
michael@0 | 1396 | const ssl3CipherSuiteDef *suite_def; |
michael@0 | 1397 | PRBool isTLS; |
michael@0 | 1398 | |
michael@0 | 1399 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 1400 | |
michael@0 | 1401 | ssl_GetSpecWriteLock(ss); /*******************************/ |
michael@0 | 1402 | |
michael@0 | 1403 | pwSpec = ss->ssl3.pwSpec; |
michael@0 | 1404 | PORT_Assert(pwSpec == ss->ssl3.prSpec); |
michael@0 | 1405 | |
michael@0 | 1406 | /* This hack provides maximal interoperability with SSL 3 servers. */ |
michael@0 | 1407 | cwSpec = ss->ssl3.cwSpec; |
michael@0 | 1408 | if (cwSpec->mac_def->mac == mac_null) { |
michael@0 | 1409 | /* SSL records are not being MACed. */ |
michael@0 | 1410 | cwSpec->version = ss->version; |
michael@0 | 1411 | } |
michael@0 | 1412 | |
michael@0 | 1413 | pwSpec->version = ss->version; |
michael@0 | 1414 | isTLS = (PRBool)(pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 1415 | |
michael@0 | 1416 | SSL_TRC(3, ("%d: SSL3[%d]: Set XXX Pending Cipher Suite to 0x%04x", |
michael@0 | 1417 | SSL_GETPID(), ss->fd, suite)); |
michael@0 | 1418 | |
michael@0 | 1419 | suite_def = ssl_LookupCipherSuiteDef(suite); |
michael@0 | 1420 | if (suite_def == NULL) { |
michael@0 | 1421 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 1422 | return SECFailure; /* error code set by ssl_LookupCipherSuiteDef */ |
michael@0 | 1423 | } |
michael@0 | 1424 | |
michael@0 | 1425 | if (IS_DTLS(ss)) { |
michael@0 | 1426 | /* Double-check that we did not pick an RC4 suite */ |
michael@0 | 1427 | PORT_Assert((suite_def->bulk_cipher_alg != cipher_rc4) && |
michael@0 | 1428 | (suite_def->bulk_cipher_alg != cipher_rc4_40) && |
michael@0 | 1429 | (suite_def->bulk_cipher_alg != cipher_rc4_56)); |
michael@0 | 1430 | } |
michael@0 | 1431 | |
michael@0 | 1432 | cipher = suite_def->bulk_cipher_alg; |
michael@0 | 1433 | kea = suite_def->key_exchange_alg; |
michael@0 | 1434 | mac = suite_def->mac_alg; |
michael@0 | 1435 | if (mac <= ssl_mac_sha && mac != ssl_mac_null && isTLS) |
michael@0 | 1436 | mac += 2; |
michael@0 | 1437 | |
michael@0 | 1438 | ss->ssl3.hs.suite_def = suite_def; |
michael@0 | 1439 | ss->ssl3.hs.kea_def = &kea_defs[kea]; |
michael@0 | 1440 | PORT_Assert(ss->ssl3.hs.kea_def->kea == kea); |
michael@0 | 1441 | |
michael@0 | 1442 | pwSpec->cipher_def = &bulk_cipher_defs[cipher]; |
michael@0 | 1443 | PORT_Assert(pwSpec->cipher_def->cipher == cipher); |
michael@0 | 1444 | |
michael@0 | 1445 | pwSpec->mac_def = &mac_defs[mac]; |
michael@0 | 1446 | PORT_Assert(pwSpec->mac_def->mac == mac); |
michael@0 | 1447 | |
michael@0 | 1448 | ss->sec.keyBits = pwSpec->cipher_def->key_size * BPB; |
michael@0 | 1449 | ss->sec.secretKeyBits = pwSpec->cipher_def->secret_key_size * BPB; |
michael@0 | 1450 | ss->sec.cipherType = cipher; |
michael@0 | 1451 | |
michael@0 | 1452 | pwSpec->encodeContext = NULL; |
michael@0 | 1453 | pwSpec->decodeContext = NULL; |
michael@0 | 1454 | |
michael@0 | 1455 | pwSpec->mac_size = pwSpec->mac_def->mac_size; |
michael@0 | 1456 | |
michael@0 | 1457 | pwSpec->compression_method = ss->ssl3.hs.compression; |
michael@0 | 1458 | pwSpec->compressContext = NULL; |
michael@0 | 1459 | pwSpec->decompressContext = NULL; |
michael@0 | 1460 | |
michael@0 | 1461 | ssl_ReleaseSpecWriteLock(ss); /*******************************/ |
michael@0 | 1462 | return SECSuccess; |
michael@0 | 1463 | } |
michael@0 | 1464 | |
michael@0 | 1465 | #ifdef NSS_ENABLE_ZLIB |
michael@0 | 1466 | #define SSL3_DEFLATE_CONTEXT_SIZE sizeof(z_stream) |
michael@0 | 1467 | |
michael@0 | 1468 | static SECStatus |
michael@0 | 1469 | ssl3_MapZlibError(int zlib_error) |
michael@0 | 1470 | { |
michael@0 | 1471 | switch (zlib_error) { |
michael@0 | 1472 | case Z_OK: |
michael@0 | 1473 | return SECSuccess; |
michael@0 | 1474 | default: |
michael@0 | 1475 | return SECFailure; |
michael@0 | 1476 | } |
michael@0 | 1477 | } |
michael@0 | 1478 | |
michael@0 | 1479 | static SECStatus |
michael@0 | 1480 | ssl3_DeflateInit(void *void_context) |
michael@0 | 1481 | { |
michael@0 | 1482 | z_stream *context = void_context; |
michael@0 | 1483 | context->zalloc = NULL; |
michael@0 | 1484 | context->zfree = NULL; |
michael@0 | 1485 | context->opaque = NULL; |
michael@0 | 1486 | |
michael@0 | 1487 | return ssl3_MapZlibError(deflateInit(context, Z_DEFAULT_COMPRESSION)); |
michael@0 | 1488 | } |
michael@0 | 1489 | |
michael@0 | 1490 | static SECStatus |
michael@0 | 1491 | ssl3_InflateInit(void *void_context) |
michael@0 | 1492 | { |
michael@0 | 1493 | z_stream *context = void_context; |
michael@0 | 1494 | context->zalloc = NULL; |
michael@0 | 1495 | context->zfree = NULL; |
michael@0 | 1496 | context->opaque = NULL; |
michael@0 | 1497 | context->next_in = NULL; |
michael@0 | 1498 | context->avail_in = 0; |
michael@0 | 1499 | |
michael@0 | 1500 | return ssl3_MapZlibError(inflateInit(context)); |
michael@0 | 1501 | } |
michael@0 | 1502 | |
michael@0 | 1503 | static SECStatus |
michael@0 | 1504 | ssl3_DeflateCompress(void *void_context, unsigned char *out, int *out_len, |
michael@0 | 1505 | int maxout, const unsigned char *in, int inlen) |
michael@0 | 1506 | { |
michael@0 | 1507 | z_stream *context = void_context; |
michael@0 | 1508 | |
michael@0 | 1509 | if (!inlen) { |
michael@0 | 1510 | *out_len = 0; |
michael@0 | 1511 | return SECSuccess; |
michael@0 | 1512 | } |
michael@0 | 1513 | |
michael@0 | 1514 | context->next_in = (unsigned char*) in; |
michael@0 | 1515 | context->avail_in = inlen; |
michael@0 | 1516 | context->next_out = out; |
michael@0 | 1517 | context->avail_out = maxout; |
michael@0 | 1518 | if (deflate(context, Z_SYNC_FLUSH) != Z_OK) { |
michael@0 | 1519 | return SECFailure; |
michael@0 | 1520 | } |
michael@0 | 1521 | if (context->avail_out == 0) { |
michael@0 | 1522 | /* We ran out of space! */ |
michael@0 | 1523 | SSL_TRC(3, ("%d: SSL3[%d] Ran out of buffer while compressing", |
michael@0 | 1524 | SSL_GETPID())); |
michael@0 | 1525 | return SECFailure; |
michael@0 | 1526 | } |
michael@0 | 1527 | |
michael@0 | 1528 | *out_len = maxout - context->avail_out; |
michael@0 | 1529 | return SECSuccess; |
michael@0 | 1530 | } |
michael@0 | 1531 | |
michael@0 | 1532 | static SECStatus |
michael@0 | 1533 | ssl3_DeflateDecompress(void *void_context, unsigned char *out, int *out_len, |
michael@0 | 1534 | int maxout, const unsigned char *in, int inlen) |
michael@0 | 1535 | { |
michael@0 | 1536 | z_stream *context = void_context; |
michael@0 | 1537 | |
michael@0 | 1538 | if (!inlen) { |
michael@0 | 1539 | *out_len = 0; |
michael@0 | 1540 | return SECSuccess; |
michael@0 | 1541 | } |
michael@0 | 1542 | |
michael@0 | 1543 | context->next_in = (unsigned char*) in; |
michael@0 | 1544 | context->avail_in = inlen; |
michael@0 | 1545 | context->next_out = out; |
michael@0 | 1546 | context->avail_out = maxout; |
michael@0 | 1547 | if (inflate(context, Z_SYNC_FLUSH) != Z_OK) { |
michael@0 | 1548 | PORT_SetError(SSL_ERROR_DECOMPRESSION_FAILURE); |
michael@0 | 1549 | return SECFailure; |
michael@0 | 1550 | } |
michael@0 | 1551 | |
michael@0 | 1552 | *out_len = maxout - context->avail_out; |
michael@0 | 1553 | return SECSuccess; |
michael@0 | 1554 | } |
michael@0 | 1555 | |
michael@0 | 1556 | static SECStatus |
michael@0 | 1557 | ssl3_DestroyCompressContext(void *void_context, PRBool unused) |
michael@0 | 1558 | { |
michael@0 | 1559 | deflateEnd(void_context); |
michael@0 | 1560 | PORT_Free(void_context); |
michael@0 | 1561 | return SECSuccess; |
michael@0 | 1562 | } |
michael@0 | 1563 | |
michael@0 | 1564 | static SECStatus |
michael@0 | 1565 | ssl3_DestroyDecompressContext(void *void_context, PRBool unused) |
michael@0 | 1566 | { |
michael@0 | 1567 | inflateEnd(void_context); |
michael@0 | 1568 | PORT_Free(void_context); |
michael@0 | 1569 | return SECSuccess; |
michael@0 | 1570 | } |
michael@0 | 1571 | |
michael@0 | 1572 | #endif /* NSS_ENABLE_ZLIB */ |
michael@0 | 1573 | |
michael@0 | 1574 | /* Initialize the compression functions and contexts for the given |
michael@0 | 1575 | * CipherSpec. */ |
michael@0 | 1576 | static SECStatus |
michael@0 | 1577 | ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec) |
michael@0 | 1578 | { |
michael@0 | 1579 | /* Setup the compression functions */ |
michael@0 | 1580 | switch (pwSpec->compression_method) { |
michael@0 | 1581 | case ssl_compression_null: |
michael@0 | 1582 | pwSpec->compressor = NULL; |
michael@0 | 1583 | pwSpec->decompressor = NULL; |
michael@0 | 1584 | pwSpec->compressContext = NULL; |
michael@0 | 1585 | pwSpec->decompressContext = NULL; |
michael@0 | 1586 | pwSpec->destroyCompressContext = NULL; |
michael@0 | 1587 | pwSpec->destroyDecompressContext = NULL; |
michael@0 | 1588 | break; |
michael@0 | 1589 | #ifdef NSS_ENABLE_ZLIB |
michael@0 | 1590 | case ssl_compression_deflate: |
michael@0 | 1591 | pwSpec->compressor = ssl3_DeflateCompress; |
michael@0 | 1592 | pwSpec->decompressor = ssl3_DeflateDecompress; |
michael@0 | 1593 | pwSpec->compressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE); |
michael@0 | 1594 | pwSpec->decompressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE); |
michael@0 | 1595 | pwSpec->destroyCompressContext = ssl3_DestroyCompressContext; |
michael@0 | 1596 | pwSpec->destroyDecompressContext = ssl3_DestroyDecompressContext; |
michael@0 | 1597 | ssl3_DeflateInit(pwSpec->compressContext); |
michael@0 | 1598 | ssl3_InflateInit(pwSpec->decompressContext); |
michael@0 | 1599 | break; |
michael@0 | 1600 | #endif /* NSS_ENABLE_ZLIB */ |
michael@0 | 1601 | default: |
michael@0 | 1602 | PORT_Assert(0); |
michael@0 | 1603 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 1604 | return SECFailure; |
michael@0 | 1605 | } |
michael@0 | 1606 | |
michael@0 | 1607 | return SECSuccess; |
michael@0 | 1608 | } |
michael@0 | 1609 | |
michael@0 | 1610 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1611 | /* Initialize encryption contexts for pending spec. |
michael@0 | 1612 | * MAC contexts are set up when computing the mac, not here. |
michael@0 | 1613 | * Master Secret already is derived in spec->msItem |
michael@0 | 1614 | * Caller holds Spec write lock. |
michael@0 | 1615 | */ |
michael@0 | 1616 | static SECStatus |
michael@0 | 1617 | ssl3_InitPendingContextsBypass(sslSocket *ss) |
michael@0 | 1618 | { |
michael@0 | 1619 | ssl3CipherSpec * pwSpec; |
michael@0 | 1620 | const ssl3BulkCipherDef *cipher_def; |
michael@0 | 1621 | void * serverContext = NULL; |
michael@0 | 1622 | void * clientContext = NULL; |
michael@0 | 1623 | BLapiInitContextFunc initFn = (BLapiInitContextFunc)NULL; |
michael@0 | 1624 | int mode = 0; |
michael@0 | 1625 | unsigned int optArg1 = 0; |
michael@0 | 1626 | unsigned int optArg2 = 0; |
michael@0 | 1627 | PRBool server_encrypts = ss->sec.isServer; |
michael@0 | 1628 | SSLCipherAlgorithm calg; |
michael@0 | 1629 | SECStatus rv; |
michael@0 | 1630 | |
michael@0 | 1631 | PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 1632 | PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); |
michael@0 | 1633 | PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); |
michael@0 | 1634 | |
michael@0 | 1635 | pwSpec = ss->ssl3.pwSpec; |
michael@0 | 1636 | cipher_def = pwSpec->cipher_def; |
michael@0 | 1637 | |
michael@0 | 1638 | calg = cipher_def->calg; |
michael@0 | 1639 | |
michael@0 | 1640 | if (calg == ssl_calg_aes_gcm) { |
michael@0 | 1641 | pwSpec->encode = NULL; |
michael@0 | 1642 | pwSpec->decode = NULL; |
michael@0 | 1643 | pwSpec->destroy = NULL; |
michael@0 | 1644 | pwSpec->encodeContext = NULL; |
michael@0 | 1645 | pwSpec->decodeContext = NULL; |
michael@0 | 1646 | pwSpec->aead = ssl3_AESGCMBypass; |
michael@0 | 1647 | ssl3_InitCompressionContext(pwSpec); |
michael@0 | 1648 | return SECSuccess; |
michael@0 | 1649 | } |
michael@0 | 1650 | |
michael@0 | 1651 | serverContext = pwSpec->server.cipher_context; |
michael@0 | 1652 | clientContext = pwSpec->client.cipher_context; |
michael@0 | 1653 | |
michael@0 | 1654 | switch (calg) { |
michael@0 | 1655 | case ssl_calg_null: |
michael@0 | 1656 | pwSpec->encode = Null_Cipher; |
michael@0 | 1657 | pwSpec->decode = Null_Cipher; |
michael@0 | 1658 | pwSpec->destroy = NULL; |
michael@0 | 1659 | goto success; |
michael@0 | 1660 | |
michael@0 | 1661 | case ssl_calg_rc4: |
michael@0 | 1662 | initFn = (BLapiInitContextFunc)RC4_InitContext; |
michael@0 | 1663 | pwSpec->encode = (SSLCipher) RC4_Encrypt; |
michael@0 | 1664 | pwSpec->decode = (SSLCipher) RC4_Decrypt; |
michael@0 | 1665 | pwSpec->destroy = (SSLDestroy) RC4_DestroyContext; |
michael@0 | 1666 | break; |
michael@0 | 1667 | case ssl_calg_rc2: |
michael@0 | 1668 | initFn = (BLapiInitContextFunc)RC2_InitContext; |
michael@0 | 1669 | mode = NSS_RC2_CBC; |
michael@0 | 1670 | optArg1 = cipher_def->key_size; |
michael@0 | 1671 | pwSpec->encode = (SSLCipher) RC2_Encrypt; |
michael@0 | 1672 | pwSpec->decode = (SSLCipher) RC2_Decrypt; |
michael@0 | 1673 | pwSpec->destroy = (SSLDestroy) RC2_DestroyContext; |
michael@0 | 1674 | break; |
michael@0 | 1675 | case ssl_calg_des: |
michael@0 | 1676 | initFn = (BLapiInitContextFunc)DES_InitContext; |
michael@0 | 1677 | mode = NSS_DES_CBC; |
michael@0 | 1678 | optArg1 = server_encrypts; |
michael@0 | 1679 | pwSpec->encode = (SSLCipher) DES_Encrypt; |
michael@0 | 1680 | pwSpec->decode = (SSLCipher) DES_Decrypt; |
michael@0 | 1681 | pwSpec->destroy = (SSLDestroy) DES_DestroyContext; |
michael@0 | 1682 | break; |
michael@0 | 1683 | case ssl_calg_3des: |
michael@0 | 1684 | initFn = (BLapiInitContextFunc)DES_InitContext; |
michael@0 | 1685 | mode = NSS_DES_EDE3_CBC; |
michael@0 | 1686 | optArg1 = server_encrypts; |
michael@0 | 1687 | pwSpec->encode = (SSLCipher) DES_Encrypt; |
michael@0 | 1688 | pwSpec->decode = (SSLCipher) DES_Decrypt; |
michael@0 | 1689 | pwSpec->destroy = (SSLDestroy) DES_DestroyContext; |
michael@0 | 1690 | break; |
michael@0 | 1691 | case ssl_calg_aes: |
michael@0 | 1692 | initFn = (BLapiInitContextFunc)AES_InitContext; |
michael@0 | 1693 | mode = NSS_AES_CBC; |
michael@0 | 1694 | optArg1 = server_encrypts; |
michael@0 | 1695 | optArg2 = AES_BLOCK_SIZE; |
michael@0 | 1696 | pwSpec->encode = (SSLCipher) AES_Encrypt; |
michael@0 | 1697 | pwSpec->decode = (SSLCipher) AES_Decrypt; |
michael@0 | 1698 | pwSpec->destroy = (SSLDestroy) AES_DestroyContext; |
michael@0 | 1699 | break; |
michael@0 | 1700 | |
michael@0 | 1701 | case ssl_calg_camellia: |
michael@0 | 1702 | initFn = (BLapiInitContextFunc)Camellia_InitContext; |
michael@0 | 1703 | mode = NSS_CAMELLIA_CBC; |
michael@0 | 1704 | optArg1 = server_encrypts; |
michael@0 | 1705 | optArg2 = CAMELLIA_BLOCK_SIZE; |
michael@0 | 1706 | pwSpec->encode = (SSLCipher) Camellia_Encrypt; |
michael@0 | 1707 | pwSpec->decode = (SSLCipher) Camellia_Decrypt; |
michael@0 | 1708 | pwSpec->destroy = (SSLDestroy) Camellia_DestroyContext; |
michael@0 | 1709 | break; |
michael@0 | 1710 | |
michael@0 | 1711 | case ssl_calg_seed: |
michael@0 | 1712 | initFn = (BLapiInitContextFunc)SEED_InitContext; |
michael@0 | 1713 | mode = NSS_SEED_CBC; |
michael@0 | 1714 | optArg1 = server_encrypts; |
michael@0 | 1715 | optArg2 = SEED_BLOCK_SIZE; |
michael@0 | 1716 | pwSpec->encode = (SSLCipher) SEED_Encrypt; |
michael@0 | 1717 | pwSpec->decode = (SSLCipher) SEED_Decrypt; |
michael@0 | 1718 | pwSpec->destroy = (SSLDestroy) SEED_DestroyContext; |
michael@0 | 1719 | break; |
michael@0 | 1720 | |
michael@0 | 1721 | case ssl_calg_idea: |
michael@0 | 1722 | case ssl_calg_fortezza : |
michael@0 | 1723 | default: |
michael@0 | 1724 | PORT_Assert(0); |
michael@0 | 1725 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 1726 | goto bail_out; |
michael@0 | 1727 | } |
michael@0 | 1728 | rv = (*initFn)(serverContext, |
michael@0 | 1729 | pwSpec->server.write_key_item.data, |
michael@0 | 1730 | pwSpec->server.write_key_item.len, |
michael@0 | 1731 | pwSpec->server.write_iv_item.data, |
michael@0 | 1732 | mode, optArg1, optArg2); |
michael@0 | 1733 | if (rv != SECSuccess) { |
michael@0 | 1734 | PORT_Assert(0); |
michael@0 | 1735 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 1736 | goto bail_out; |
michael@0 | 1737 | } |
michael@0 | 1738 | |
michael@0 | 1739 | switch (calg) { |
michael@0 | 1740 | case ssl_calg_des: |
michael@0 | 1741 | case ssl_calg_3des: |
michael@0 | 1742 | case ssl_calg_aes: |
michael@0 | 1743 | case ssl_calg_camellia: |
michael@0 | 1744 | case ssl_calg_seed: |
michael@0 | 1745 | /* For block ciphers, if the server is encrypting, then the client |
michael@0 | 1746 | * is decrypting, and vice versa. |
michael@0 | 1747 | */ |
michael@0 | 1748 | optArg1 = !optArg1; |
michael@0 | 1749 | break; |
michael@0 | 1750 | /* kill warnings. */ |
michael@0 | 1751 | case ssl_calg_null: |
michael@0 | 1752 | case ssl_calg_rc4: |
michael@0 | 1753 | case ssl_calg_rc2: |
michael@0 | 1754 | case ssl_calg_idea: |
michael@0 | 1755 | case ssl_calg_fortezza: |
michael@0 | 1756 | case ssl_calg_aes_gcm: |
michael@0 | 1757 | break; |
michael@0 | 1758 | } |
michael@0 | 1759 | |
michael@0 | 1760 | rv = (*initFn)(clientContext, |
michael@0 | 1761 | pwSpec->client.write_key_item.data, |
michael@0 | 1762 | pwSpec->client.write_key_item.len, |
michael@0 | 1763 | pwSpec->client.write_iv_item.data, |
michael@0 | 1764 | mode, optArg1, optArg2); |
michael@0 | 1765 | if (rv != SECSuccess) { |
michael@0 | 1766 | PORT_Assert(0); |
michael@0 | 1767 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 1768 | goto bail_out; |
michael@0 | 1769 | } |
michael@0 | 1770 | |
michael@0 | 1771 | pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext; |
michael@0 | 1772 | pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext; |
michael@0 | 1773 | |
michael@0 | 1774 | ssl3_InitCompressionContext(pwSpec); |
michael@0 | 1775 | |
michael@0 | 1776 | success: |
michael@0 | 1777 | return SECSuccess; |
michael@0 | 1778 | |
michael@0 | 1779 | bail_out: |
michael@0 | 1780 | return SECFailure; |
michael@0 | 1781 | } |
michael@0 | 1782 | #endif |
michael@0 | 1783 | |
michael@0 | 1784 | /* This function should probably be moved to pk11wrap and be named |
michael@0 | 1785 | * PK11_ParamFromIVAndEffectiveKeyBits |
michael@0 | 1786 | */ |
michael@0 | 1787 | static SECItem * |
michael@0 | 1788 | ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits) |
michael@0 | 1789 | { |
michael@0 | 1790 | SECItem * param = PK11_ParamFromIV(mtype, iv); |
michael@0 | 1791 | if (param && param->data && param->len >= sizeof(CK_RC2_PARAMS)) { |
michael@0 | 1792 | switch (mtype) { |
michael@0 | 1793 | case CKM_RC2_KEY_GEN: |
michael@0 | 1794 | case CKM_RC2_ECB: |
michael@0 | 1795 | case CKM_RC2_CBC: |
michael@0 | 1796 | case CKM_RC2_MAC: |
michael@0 | 1797 | case CKM_RC2_MAC_GENERAL: |
michael@0 | 1798 | case CKM_RC2_CBC_PAD: |
michael@0 | 1799 | *(CK_RC2_PARAMS *)param->data = ulEffectiveBits; |
michael@0 | 1800 | default: break; |
michael@0 | 1801 | } |
michael@0 | 1802 | } |
michael@0 | 1803 | return param; |
michael@0 | 1804 | } |
michael@0 | 1805 | |
michael@0 | 1806 | /* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data |
michael@0 | 1807 | * which is included in the MAC or AEAD additional data) to |out| and returns |
michael@0 | 1808 | * its length. See https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the |
michael@0 | 1809 | * definition of the AEAD additional data. |
michael@0 | 1810 | * |
michael@0 | 1811 | * TLS pseudo-header includes the record's version field, SSL's doesn't. Which |
michael@0 | 1812 | * pseudo-header defintiion to use should be decided based on the version of |
michael@0 | 1813 | * the protocol that was negotiated when the cipher spec became current, NOT |
michael@0 | 1814 | * based on the version value in the record itself, and the decision is passed |
michael@0 | 1815 | * to this function as the |includesVersion| argument. But, the |version| |
michael@0 | 1816 | * argument should be the record's version value. |
michael@0 | 1817 | */ |
michael@0 | 1818 | static unsigned int |
michael@0 | 1819 | ssl3_BuildRecordPseudoHeader(unsigned char *out, |
michael@0 | 1820 | SSL3SequenceNumber seq_num, |
michael@0 | 1821 | SSL3ContentType type, |
michael@0 | 1822 | PRBool includesVersion, |
michael@0 | 1823 | SSL3ProtocolVersion version, |
michael@0 | 1824 | PRBool isDTLS, |
michael@0 | 1825 | int length) |
michael@0 | 1826 | { |
michael@0 | 1827 | out[0] = (unsigned char)(seq_num.high >> 24); |
michael@0 | 1828 | out[1] = (unsigned char)(seq_num.high >> 16); |
michael@0 | 1829 | out[2] = (unsigned char)(seq_num.high >> 8); |
michael@0 | 1830 | out[3] = (unsigned char)(seq_num.high >> 0); |
michael@0 | 1831 | out[4] = (unsigned char)(seq_num.low >> 24); |
michael@0 | 1832 | out[5] = (unsigned char)(seq_num.low >> 16); |
michael@0 | 1833 | out[6] = (unsigned char)(seq_num.low >> 8); |
michael@0 | 1834 | out[7] = (unsigned char)(seq_num.low >> 0); |
michael@0 | 1835 | out[8] = type; |
michael@0 | 1836 | |
michael@0 | 1837 | /* SSL3 MAC doesn't include the record's version field. */ |
michael@0 | 1838 | if (!includesVersion) { |
michael@0 | 1839 | out[9] = MSB(length); |
michael@0 | 1840 | out[10] = LSB(length); |
michael@0 | 1841 | return 11; |
michael@0 | 1842 | } |
michael@0 | 1843 | |
michael@0 | 1844 | /* TLS MAC and AEAD additional data include version. */ |
michael@0 | 1845 | if (isDTLS) { |
michael@0 | 1846 | SSL3ProtocolVersion dtls_version; |
michael@0 | 1847 | |
michael@0 | 1848 | dtls_version = dtls_TLSVersionToDTLSVersion(version); |
michael@0 | 1849 | out[9] = MSB(dtls_version); |
michael@0 | 1850 | out[10] = LSB(dtls_version); |
michael@0 | 1851 | } else { |
michael@0 | 1852 | out[9] = MSB(version); |
michael@0 | 1853 | out[10] = LSB(version); |
michael@0 | 1854 | } |
michael@0 | 1855 | out[11] = MSB(length); |
michael@0 | 1856 | out[12] = LSB(length); |
michael@0 | 1857 | return 13; |
michael@0 | 1858 | } |
michael@0 | 1859 | |
michael@0 | 1860 | static SECStatus |
michael@0 | 1861 | ssl3_AESGCM(ssl3KeyMaterial *keys, |
michael@0 | 1862 | PRBool doDecrypt, |
michael@0 | 1863 | unsigned char *out, |
michael@0 | 1864 | int *outlen, |
michael@0 | 1865 | int maxout, |
michael@0 | 1866 | const unsigned char *in, |
michael@0 | 1867 | int inlen, |
michael@0 | 1868 | const unsigned char *additionalData, |
michael@0 | 1869 | int additionalDataLen) |
michael@0 | 1870 | { |
michael@0 | 1871 | SECItem param; |
michael@0 | 1872 | SECStatus rv = SECFailure; |
michael@0 | 1873 | unsigned char nonce[12]; |
michael@0 | 1874 | unsigned int uOutLen; |
michael@0 | 1875 | CK_GCM_PARAMS gcmParams; |
michael@0 | 1876 | |
michael@0 | 1877 | static const int tagSize = 16; |
michael@0 | 1878 | static const int explicitNonceLen = 8; |
michael@0 | 1879 | |
michael@0 | 1880 | /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the |
michael@0 | 1881 | * nonce is formed. */ |
michael@0 | 1882 | memcpy(nonce, keys->write_iv, 4); |
michael@0 | 1883 | if (doDecrypt) { |
michael@0 | 1884 | memcpy(nonce + 4, in, explicitNonceLen); |
michael@0 | 1885 | in += explicitNonceLen; |
michael@0 | 1886 | inlen -= explicitNonceLen; |
michael@0 | 1887 | *outlen = 0; |
michael@0 | 1888 | } else { |
michael@0 | 1889 | if (maxout < explicitNonceLen) { |
michael@0 | 1890 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
michael@0 | 1891 | return SECFailure; |
michael@0 | 1892 | } |
michael@0 | 1893 | /* Use the 64-bit sequence number as the explicit nonce. */ |
michael@0 | 1894 | memcpy(nonce + 4, additionalData, explicitNonceLen); |
michael@0 | 1895 | memcpy(out, additionalData, explicitNonceLen); |
michael@0 | 1896 | out += explicitNonceLen; |
michael@0 | 1897 | maxout -= explicitNonceLen; |
michael@0 | 1898 | *outlen = explicitNonceLen; |
michael@0 | 1899 | } |
michael@0 | 1900 | |
michael@0 | 1901 | param.type = siBuffer; |
michael@0 | 1902 | param.data = (unsigned char *) &gcmParams; |
michael@0 | 1903 | param.len = sizeof(gcmParams); |
michael@0 | 1904 | gcmParams.pIv = nonce; |
michael@0 | 1905 | gcmParams.ulIvLen = sizeof(nonce); |
michael@0 | 1906 | gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */ |
michael@0 | 1907 | gcmParams.ulAADLen = additionalDataLen; |
michael@0 | 1908 | gcmParams.ulTagBits = tagSize * 8; |
michael@0 | 1909 | |
michael@0 | 1910 | if (doDecrypt) { |
michael@0 | 1911 | rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, |
michael@0 | 1912 | maxout, in, inlen); |
michael@0 | 1913 | } else { |
michael@0 | 1914 | rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, |
michael@0 | 1915 | maxout, in, inlen); |
michael@0 | 1916 | } |
michael@0 | 1917 | *outlen += (int) uOutLen; |
michael@0 | 1918 | |
michael@0 | 1919 | return rv; |
michael@0 | 1920 | } |
michael@0 | 1921 | |
michael@0 | 1922 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1923 | static SECStatus |
michael@0 | 1924 | ssl3_AESGCMBypass(ssl3KeyMaterial *keys, |
michael@0 | 1925 | PRBool doDecrypt, |
michael@0 | 1926 | unsigned char *out, |
michael@0 | 1927 | int *outlen, |
michael@0 | 1928 | int maxout, |
michael@0 | 1929 | const unsigned char *in, |
michael@0 | 1930 | int inlen, |
michael@0 | 1931 | const unsigned char *additionalData, |
michael@0 | 1932 | int additionalDataLen) |
michael@0 | 1933 | { |
michael@0 | 1934 | SECStatus rv = SECFailure; |
michael@0 | 1935 | unsigned char nonce[12]; |
michael@0 | 1936 | unsigned int uOutLen; |
michael@0 | 1937 | AESContext *cx; |
michael@0 | 1938 | CK_GCM_PARAMS gcmParams; |
michael@0 | 1939 | |
michael@0 | 1940 | static const int tagSize = 16; |
michael@0 | 1941 | static const int explicitNonceLen = 8; |
michael@0 | 1942 | |
michael@0 | 1943 | /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the |
michael@0 | 1944 | * nonce is formed. */ |
michael@0 | 1945 | PORT_Assert(keys->write_iv_item.len == 4); |
michael@0 | 1946 | if (keys->write_iv_item.len != 4) { |
michael@0 | 1947 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 1948 | return SECFailure; |
michael@0 | 1949 | } |
michael@0 | 1950 | memcpy(nonce, keys->write_iv_item.data, 4); |
michael@0 | 1951 | if (doDecrypt) { |
michael@0 | 1952 | memcpy(nonce + 4, in, explicitNonceLen); |
michael@0 | 1953 | in += explicitNonceLen; |
michael@0 | 1954 | inlen -= explicitNonceLen; |
michael@0 | 1955 | *outlen = 0; |
michael@0 | 1956 | } else { |
michael@0 | 1957 | if (maxout < explicitNonceLen) { |
michael@0 | 1958 | PORT_SetError(SEC_ERROR_INPUT_LEN); |
michael@0 | 1959 | return SECFailure; |
michael@0 | 1960 | } |
michael@0 | 1961 | /* Use the 64-bit sequence number as the explicit nonce. */ |
michael@0 | 1962 | memcpy(nonce + 4, additionalData, explicitNonceLen); |
michael@0 | 1963 | memcpy(out, additionalData, explicitNonceLen); |
michael@0 | 1964 | out += explicitNonceLen; |
michael@0 | 1965 | maxout -= explicitNonceLen; |
michael@0 | 1966 | *outlen = explicitNonceLen; |
michael@0 | 1967 | } |
michael@0 | 1968 | |
michael@0 | 1969 | gcmParams.pIv = nonce; |
michael@0 | 1970 | gcmParams.ulIvLen = sizeof(nonce); |
michael@0 | 1971 | gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */ |
michael@0 | 1972 | gcmParams.ulAADLen = additionalDataLen; |
michael@0 | 1973 | gcmParams.ulTagBits = tagSize * 8; |
michael@0 | 1974 | |
michael@0 | 1975 | cx = (AESContext *)keys->cipher_context; |
michael@0 | 1976 | rv = AES_InitContext(cx, keys->write_key_item.data, |
michael@0 | 1977 | keys->write_key_item.len, |
michael@0 | 1978 | (unsigned char *)&gcmParams, NSS_AES_GCM, !doDecrypt, |
michael@0 | 1979 | AES_BLOCK_SIZE); |
michael@0 | 1980 | if (rv != SECSuccess) { |
michael@0 | 1981 | return rv; |
michael@0 | 1982 | } |
michael@0 | 1983 | if (doDecrypt) { |
michael@0 | 1984 | rv = AES_Decrypt(cx, out, &uOutLen, maxout, in, inlen); |
michael@0 | 1985 | } else { |
michael@0 | 1986 | rv = AES_Encrypt(cx, out, &uOutLen, maxout, in, inlen); |
michael@0 | 1987 | } |
michael@0 | 1988 | AES_DestroyContext(cx, PR_FALSE); |
michael@0 | 1989 | *outlen += (int) uOutLen; |
michael@0 | 1990 | |
michael@0 | 1991 | return rv; |
michael@0 | 1992 | } |
michael@0 | 1993 | #endif |
michael@0 | 1994 | |
michael@0 | 1995 | /* Initialize encryption and MAC contexts for pending spec. |
michael@0 | 1996 | * Master Secret already is derived. |
michael@0 | 1997 | * Caller holds Spec write lock. |
michael@0 | 1998 | */ |
michael@0 | 1999 | static SECStatus |
michael@0 | 2000 | ssl3_InitPendingContextsPKCS11(sslSocket *ss) |
michael@0 | 2001 | { |
michael@0 | 2002 | ssl3CipherSpec * pwSpec; |
michael@0 | 2003 | const ssl3BulkCipherDef *cipher_def; |
michael@0 | 2004 | PK11Context * serverContext = NULL; |
michael@0 | 2005 | PK11Context * clientContext = NULL; |
michael@0 | 2006 | SECItem * param; |
michael@0 | 2007 | CK_MECHANISM_TYPE mechanism; |
michael@0 | 2008 | CK_MECHANISM_TYPE mac_mech; |
michael@0 | 2009 | CK_ULONG macLength; |
michael@0 | 2010 | CK_ULONG effKeyBits; |
michael@0 | 2011 | SECItem iv; |
michael@0 | 2012 | SECItem mac_param; |
michael@0 | 2013 | SSLCipherAlgorithm calg; |
michael@0 | 2014 | |
michael@0 | 2015 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 2016 | PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); |
michael@0 | 2017 | PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); |
michael@0 | 2018 | |
michael@0 | 2019 | pwSpec = ss->ssl3.pwSpec; |
michael@0 | 2020 | cipher_def = pwSpec->cipher_def; |
michael@0 | 2021 | macLength = pwSpec->mac_size; |
michael@0 | 2022 | calg = cipher_def->calg; |
michael@0 | 2023 | PORT_Assert(alg2Mech[calg].calg == calg); |
michael@0 | 2024 | |
michael@0 | 2025 | pwSpec->client.write_mac_context = NULL; |
michael@0 | 2026 | pwSpec->server.write_mac_context = NULL; |
michael@0 | 2027 | |
michael@0 | 2028 | if (calg == calg_aes_gcm) { |
michael@0 | 2029 | pwSpec->encode = NULL; |
michael@0 | 2030 | pwSpec->decode = NULL; |
michael@0 | 2031 | pwSpec->destroy = NULL; |
michael@0 | 2032 | pwSpec->encodeContext = NULL; |
michael@0 | 2033 | pwSpec->decodeContext = NULL; |
michael@0 | 2034 | pwSpec->aead = ssl3_AESGCM; |
michael@0 | 2035 | return SECSuccess; |
michael@0 | 2036 | } |
michael@0 | 2037 | |
michael@0 | 2038 | /* |
michael@0 | 2039 | ** Now setup the MAC contexts, |
michael@0 | 2040 | ** crypto contexts are setup below. |
michael@0 | 2041 | */ |
michael@0 | 2042 | |
michael@0 | 2043 | mac_mech = pwSpec->mac_def->mmech; |
michael@0 | 2044 | mac_param.data = (unsigned char *)&macLength; |
michael@0 | 2045 | mac_param.len = sizeof(macLength); |
michael@0 | 2046 | mac_param.type = 0; |
michael@0 | 2047 | |
michael@0 | 2048 | pwSpec->client.write_mac_context = PK11_CreateContextBySymKey( |
michael@0 | 2049 | mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param); |
michael@0 | 2050 | if (pwSpec->client.write_mac_context == NULL) { |
michael@0 | 2051 | ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); |
michael@0 | 2052 | goto fail; |
michael@0 | 2053 | } |
michael@0 | 2054 | pwSpec->server.write_mac_context = PK11_CreateContextBySymKey( |
michael@0 | 2055 | mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param); |
michael@0 | 2056 | if (pwSpec->server.write_mac_context == NULL) { |
michael@0 | 2057 | ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); |
michael@0 | 2058 | goto fail; |
michael@0 | 2059 | } |
michael@0 | 2060 | |
michael@0 | 2061 | /* |
michael@0 | 2062 | ** Now setup the crypto contexts. |
michael@0 | 2063 | */ |
michael@0 | 2064 | |
michael@0 | 2065 | if (calg == calg_null) { |
michael@0 | 2066 | pwSpec->encode = Null_Cipher; |
michael@0 | 2067 | pwSpec->decode = Null_Cipher; |
michael@0 | 2068 | pwSpec->destroy = NULL; |
michael@0 | 2069 | return SECSuccess; |
michael@0 | 2070 | } |
michael@0 | 2071 | mechanism = alg2Mech[calg].cmech; |
michael@0 | 2072 | effKeyBits = cipher_def->key_size * BPB; |
michael@0 | 2073 | |
michael@0 | 2074 | /* |
michael@0 | 2075 | * build the server context |
michael@0 | 2076 | */ |
michael@0 | 2077 | iv.data = pwSpec->server.write_iv; |
michael@0 | 2078 | iv.len = cipher_def->iv_size; |
michael@0 | 2079 | param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits); |
michael@0 | 2080 | if (param == NULL) { |
michael@0 | 2081 | ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); |
michael@0 | 2082 | goto fail; |
michael@0 | 2083 | } |
michael@0 | 2084 | serverContext = PK11_CreateContextBySymKey(mechanism, |
michael@0 | 2085 | (ss->sec.isServer ? CKA_ENCRYPT : CKA_DECRYPT), |
michael@0 | 2086 | pwSpec->server.write_key, param); |
michael@0 | 2087 | iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len); |
michael@0 | 2088 | if (iv.data) |
michael@0 | 2089 | PORT_Memcpy(pwSpec->server.write_iv, iv.data, iv.len); |
michael@0 | 2090 | SECITEM_FreeItem(param, PR_TRUE); |
michael@0 | 2091 | if (serverContext == NULL) { |
michael@0 | 2092 | ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); |
michael@0 | 2093 | goto fail; |
michael@0 | 2094 | } |
michael@0 | 2095 | |
michael@0 | 2096 | /* |
michael@0 | 2097 | * build the client context |
michael@0 | 2098 | */ |
michael@0 | 2099 | iv.data = pwSpec->client.write_iv; |
michael@0 | 2100 | iv.len = cipher_def->iv_size; |
michael@0 | 2101 | |
michael@0 | 2102 | param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits); |
michael@0 | 2103 | if (param == NULL) { |
michael@0 | 2104 | ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); |
michael@0 | 2105 | goto fail; |
michael@0 | 2106 | } |
michael@0 | 2107 | clientContext = PK11_CreateContextBySymKey(mechanism, |
michael@0 | 2108 | (ss->sec.isServer ? CKA_DECRYPT : CKA_ENCRYPT), |
michael@0 | 2109 | pwSpec->client.write_key, param); |
michael@0 | 2110 | iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len); |
michael@0 | 2111 | if (iv.data) |
michael@0 | 2112 | PORT_Memcpy(pwSpec->client.write_iv, iv.data, iv.len); |
michael@0 | 2113 | SECITEM_FreeItem(param,PR_TRUE); |
michael@0 | 2114 | if (clientContext == NULL) { |
michael@0 | 2115 | ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); |
michael@0 | 2116 | goto fail; |
michael@0 | 2117 | } |
michael@0 | 2118 | pwSpec->encode = (SSLCipher) PK11_CipherOp; |
michael@0 | 2119 | pwSpec->decode = (SSLCipher) PK11_CipherOp; |
michael@0 | 2120 | pwSpec->destroy = (SSLDestroy) PK11_DestroyContext; |
michael@0 | 2121 | |
michael@0 | 2122 | pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext; |
michael@0 | 2123 | pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext; |
michael@0 | 2124 | |
michael@0 | 2125 | serverContext = NULL; |
michael@0 | 2126 | clientContext = NULL; |
michael@0 | 2127 | |
michael@0 | 2128 | ssl3_InitCompressionContext(pwSpec); |
michael@0 | 2129 | |
michael@0 | 2130 | return SECSuccess; |
michael@0 | 2131 | |
michael@0 | 2132 | fail: |
michael@0 | 2133 | if (serverContext != NULL) PK11_DestroyContext(serverContext, PR_TRUE); |
michael@0 | 2134 | if (clientContext != NULL) PK11_DestroyContext(clientContext, PR_TRUE); |
michael@0 | 2135 | if (pwSpec->client.write_mac_context != NULL) { |
michael@0 | 2136 | PK11_DestroyContext(pwSpec->client.write_mac_context,PR_TRUE); |
michael@0 | 2137 | pwSpec->client.write_mac_context = NULL; |
michael@0 | 2138 | } |
michael@0 | 2139 | if (pwSpec->server.write_mac_context != NULL) { |
michael@0 | 2140 | PK11_DestroyContext(pwSpec->server.write_mac_context,PR_TRUE); |
michael@0 | 2141 | pwSpec->server.write_mac_context = NULL; |
michael@0 | 2142 | } |
michael@0 | 2143 | |
michael@0 | 2144 | return SECFailure; |
michael@0 | 2145 | } |
michael@0 | 2146 | |
michael@0 | 2147 | /* Complete the initialization of all keys, ciphers, MACs and their contexts |
michael@0 | 2148 | * for the pending Cipher Spec. |
michael@0 | 2149 | * Called from: ssl3_SendClientKeyExchange (for Full handshake) |
michael@0 | 2150 | * ssl3_HandleRSAClientKeyExchange (for Full handshake) |
michael@0 | 2151 | * ssl3_HandleServerHello (for session restart) |
michael@0 | 2152 | * ssl3_HandleClientHello (for session restart) |
michael@0 | 2153 | * Sets error code, but caller probably should override to disambiguate. |
michael@0 | 2154 | * NULL pms means re-use old master_secret. |
michael@0 | 2155 | * |
michael@0 | 2156 | * This code is common to the bypass and PKCS11 execution paths. |
michael@0 | 2157 | * For the bypass case, pms is NULL. |
michael@0 | 2158 | */ |
michael@0 | 2159 | SECStatus |
michael@0 | 2160 | ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms) |
michael@0 | 2161 | { |
michael@0 | 2162 | ssl3CipherSpec * pwSpec; |
michael@0 | 2163 | ssl3CipherSpec * cwSpec; |
michael@0 | 2164 | SECStatus rv; |
michael@0 | 2165 | |
michael@0 | 2166 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 2167 | |
michael@0 | 2168 | ssl_GetSpecWriteLock(ss); /**************************************/ |
michael@0 | 2169 | |
michael@0 | 2170 | PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); |
michael@0 | 2171 | |
michael@0 | 2172 | pwSpec = ss->ssl3.pwSpec; |
michael@0 | 2173 | cwSpec = ss->ssl3.cwSpec; |
michael@0 | 2174 | |
michael@0 | 2175 | if (pms || (!pwSpec->msItem.len && !pwSpec->master_secret)) { |
michael@0 | 2176 | rv = ssl3_DeriveMasterSecret(ss, pms); |
michael@0 | 2177 | if (rv != SECSuccess) { |
michael@0 | 2178 | goto done; /* err code set by ssl3_DeriveMasterSecret */ |
michael@0 | 2179 | } |
michael@0 | 2180 | } |
michael@0 | 2181 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 2182 | if (ss->opt.bypassPKCS11 && pwSpec->msItem.len && pwSpec->msItem.data) { |
michael@0 | 2183 | /* Double Bypass succeeded in extracting the master_secret */ |
michael@0 | 2184 | const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; |
michael@0 | 2185 | PRBool isTLS = (PRBool)(kea_def->tls_keygen || |
michael@0 | 2186 | (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); |
michael@0 | 2187 | pwSpec->bypassCiphers = PR_TRUE; |
michael@0 | 2188 | rv = ssl3_KeyAndMacDeriveBypass( pwSpec, |
michael@0 | 2189 | (const unsigned char *)&ss->ssl3.hs.client_random, |
michael@0 | 2190 | (const unsigned char *)&ss->ssl3.hs.server_random, |
michael@0 | 2191 | isTLS, |
michael@0 | 2192 | (PRBool)(kea_def->is_limited)); |
michael@0 | 2193 | if (rv == SECSuccess) { |
michael@0 | 2194 | rv = ssl3_InitPendingContextsBypass(ss); |
michael@0 | 2195 | } |
michael@0 | 2196 | } else |
michael@0 | 2197 | #endif |
michael@0 | 2198 | if (pwSpec->master_secret) { |
michael@0 | 2199 | rv = ssl3_DeriveConnectionKeysPKCS11(ss); |
michael@0 | 2200 | if (rv == SECSuccess) { |
michael@0 | 2201 | rv = ssl3_InitPendingContextsPKCS11(ss); |
michael@0 | 2202 | } |
michael@0 | 2203 | } else { |
michael@0 | 2204 | PORT_Assert(pwSpec->master_secret); |
michael@0 | 2205 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 2206 | rv = SECFailure; |
michael@0 | 2207 | } |
michael@0 | 2208 | if (rv != SECSuccess) { |
michael@0 | 2209 | goto done; |
michael@0 | 2210 | } |
michael@0 | 2211 | |
michael@0 | 2212 | /* Generic behaviors -- common to all crypto methods */ |
michael@0 | 2213 | if (!IS_DTLS(ss)) { |
michael@0 | 2214 | pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = 0; |
michael@0 | 2215 | } else { |
michael@0 | 2216 | if (cwSpec->epoch == PR_UINT16_MAX) { |
michael@0 | 2217 | /* The problem here is that we have rehandshaked too many |
michael@0 | 2218 | * times (you are not allowed to wrap the epoch). The |
michael@0 | 2219 | * spec says you should be discarding the connection |
michael@0 | 2220 | * and start over, so not much we can do here. */ |
michael@0 | 2221 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 2222 | rv = SECFailure; |
michael@0 | 2223 | goto done; |
michael@0 | 2224 | } |
michael@0 | 2225 | /* The sequence number has the high 16 bits as the epoch. */ |
michael@0 | 2226 | pwSpec->epoch = cwSpec->epoch + 1; |
michael@0 | 2227 | pwSpec->read_seq_num.high = pwSpec->write_seq_num.high = |
michael@0 | 2228 | pwSpec->epoch << 16; |
michael@0 | 2229 | |
michael@0 | 2230 | dtls_InitRecvdRecords(&pwSpec->recvdRecords); |
michael@0 | 2231 | } |
michael@0 | 2232 | pwSpec->read_seq_num.low = pwSpec->write_seq_num.low = 0; |
michael@0 | 2233 | |
michael@0 | 2234 | done: |
michael@0 | 2235 | ssl_ReleaseSpecWriteLock(ss); /******************************/ |
michael@0 | 2236 | if (rv != SECSuccess) |
michael@0 | 2237 | ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
michael@0 | 2238 | return rv; |
michael@0 | 2239 | } |
michael@0 | 2240 | |
michael@0 | 2241 | /* |
michael@0 | 2242 | * 60 bytes is 3 times the maximum length MAC size that is supported. |
michael@0 | 2243 | */ |
michael@0 | 2244 | static const unsigned char mac_pad_1 [60] = { |
michael@0 | 2245 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2246 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2247 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2248 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2249 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2250 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2251 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, |
michael@0 | 2252 | 0x36, 0x36, 0x36, 0x36 |
michael@0 | 2253 | }; |
michael@0 | 2254 | static const unsigned char mac_pad_2 [60] = { |
michael@0 | 2255 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2256 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2257 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2258 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2259 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2260 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2261 | 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, |
michael@0 | 2262 | 0x5c, 0x5c, 0x5c, 0x5c |
michael@0 | 2263 | }; |
michael@0 | 2264 | |
michael@0 | 2265 | /* Called from: ssl3_SendRecord() |
michael@0 | 2266 | ** Caller must already hold the SpecReadLock. (wish we could assert that!) |
michael@0 | 2267 | */ |
michael@0 | 2268 | static SECStatus |
michael@0 | 2269 | ssl3_ComputeRecordMAC( |
michael@0 | 2270 | ssl3CipherSpec * spec, |
michael@0 | 2271 | PRBool useServerMacKey, |
michael@0 | 2272 | const unsigned char *header, |
michael@0 | 2273 | unsigned int headerLen, |
michael@0 | 2274 | const SSL3Opaque * input, |
michael@0 | 2275 | int inputLength, |
michael@0 | 2276 | unsigned char * outbuf, |
michael@0 | 2277 | unsigned int * outLength) |
michael@0 | 2278 | { |
michael@0 | 2279 | const ssl3MACDef * mac_def; |
michael@0 | 2280 | SECStatus rv; |
michael@0 | 2281 | |
michael@0 | 2282 | PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen)); |
michael@0 | 2283 | PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength)); |
michael@0 | 2284 | |
michael@0 | 2285 | mac_def = spec->mac_def; |
michael@0 | 2286 | if (mac_def->mac == mac_null) { |
michael@0 | 2287 | *outLength = 0; |
michael@0 | 2288 | return SECSuccess; |
michael@0 | 2289 | } |
michael@0 | 2290 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 2291 | if (spec->bypassCiphers) { |
michael@0 | 2292 | /* bypass version */ |
michael@0 | 2293 | const SECHashObject *hashObj = NULL; |
michael@0 | 2294 | unsigned int pad_bytes = 0; |
michael@0 | 2295 | PRUint64 write_mac_context[MAX_MAC_CONTEXT_LLONGS]; |
michael@0 | 2296 | |
michael@0 | 2297 | switch (mac_def->mac) { |
michael@0 | 2298 | case ssl_mac_null: |
michael@0 | 2299 | *outLength = 0; |
michael@0 | 2300 | return SECSuccess; |
michael@0 | 2301 | case ssl_mac_md5: |
michael@0 | 2302 | pad_bytes = 48; |
michael@0 | 2303 | hashObj = HASH_GetRawHashObject(HASH_AlgMD5); |
michael@0 | 2304 | break; |
michael@0 | 2305 | case ssl_mac_sha: |
michael@0 | 2306 | pad_bytes = 40; |
michael@0 | 2307 | hashObj = HASH_GetRawHashObject(HASH_AlgSHA1); |
michael@0 | 2308 | break; |
michael@0 | 2309 | case ssl_hmac_md5: /* used with TLS */ |
michael@0 | 2310 | hashObj = HASH_GetRawHashObject(HASH_AlgMD5); |
michael@0 | 2311 | break; |
michael@0 | 2312 | case ssl_hmac_sha: /* used with TLS */ |
michael@0 | 2313 | hashObj = HASH_GetRawHashObject(HASH_AlgSHA1); |
michael@0 | 2314 | break; |
michael@0 | 2315 | case ssl_hmac_sha256: /* used with TLS */ |
michael@0 | 2316 | hashObj = HASH_GetRawHashObject(HASH_AlgSHA256); |
michael@0 | 2317 | break; |
michael@0 | 2318 | default: |
michael@0 | 2319 | break; |
michael@0 | 2320 | } |
michael@0 | 2321 | if (!hashObj) { |
michael@0 | 2322 | PORT_Assert(0); |
michael@0 | 2323 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 2324 | return SECFailure; |
michael@0 | 2325 | } |
michael@0 | 2326 | |
michael@0 | 2327 | if (spec->version <= SSL_LIBRARY_VERSION_3_0) { |
michael@0 | 2328 | unsigned int tempLen; |
michael@0 | 2329 | unsigned char temp[MAX_MAC_LENGTH]; |
michael@0 | 2330 | |
michael@0 | 2331 | /* compute "inner" part of SSL3 MAC */ |
michael@0 | 2332 | hashObj->begin(write_mac_context); |
michael@0 | 2333 | if (useServerMacKey) |
michael@0 | 2334 | hashObj->update(write_mac_context, |
michael@0 | 2335 | spec->server.write_mac_key_item.data, |
michael@0 | 2336 | spec->server.write_mac_key_item.len); |
michael@0 | 2337 | else |
michael@0 | 2338 | hashObj->update(write_mac_context, |
michael@0 | 2339 | spec->client.write_mac_key_item.data, |
michael@0 | 2340 | spec->client.write_mac_key_item.len); |
michael@0 | 2341 | hashObj->update(write_mac_context, mac_pad_1, pad_bytes); |
michael@0 | 2342 | hashObj->update(write_mac_context, header, headerLen); |
michael@0 | 2343 | hashObj->update(write_mac_context, input, inputLength); |
michael@0 | 2344 | hashObj->end(write_mac_context, temp, &tempLen, sizeof temp); |
michael@0 | 2345 | |
michael@0 | 2346 | /* compute "outer" part of SSL3 MAC */ |
michael@0 | 2347 | hashObj->begin(write_mac_context); |
michael@0 | 2348 | if (useServerMacKey) |
michael@0 | 2349 | hashObj->update(write_mac_context, |
michael@0 | 2350 | spec->server.write_mac_key_item.data, |
michael@0 | 2351 | spec->server.write_mac_key_item.len); |
michael@0 | 2352 | else |
michael@0 | 2353 | hashObj->update(write_mac_context, |
michael@0 | 2354 | spec->client.write_mac_key_item.data, |
michael@0 | 2355 | spec->client.write_mac_key_item.len); |
michael@0 | 2356 | hashObj->update(write_mac_context, mac_pad_2, pad_bytes); |
michael@0 | 2357 | hashObj->update(write_mac_context, temp, tempLen); |
michael@0 | 2358 | hashObj->end(write_mac_context, outbuf, outLength, spec->mac_size); |
michael@0 | 2359 | rv = SECSuccess; |
michael@0 | 2360 | } else { /* is TLS */ |
michael@0 | 2361 | #define cx ((HMACContext *)write_mac_context) |
michael@0 | 2362 | if (useServerMacKey) { |
michael@0 | 2363 | rv = HMAC_Init(cx, hashObj, |
michael@0 | 2364 | spec->server.write_mac_key_item.data, |
michael@0 | 2365 | spec->server.write_mac_key_item.len, PR_FALSE); |
michael@0 | 2366 | } else { |
michael@0 | 2367 | rv = HMAC_Init(cx, hashObj, |
michael@0 | 2368 | spec->client.write_mac_key_item.data, |
michael@0 | 2369 | spec->client.write_mac_key_item.len, PR_FALSE); |
michael@0 | 2370 | } |
michael@0 | 2371 | if (rv == SECSuccess) { |
michael@0 | 2372 | HMAC_Begin(cx); |
michael@0 | 2373 | HMAC_Update(cx, header, headerLen); |
michael@0 | 2374 | HMAC_Update(cx, input, inputLength); |
michael@0 | 2375 | rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size); |
michael@0 | 2376 | HMAC_Destroy(cx, PR_FALSE); |
michael@0 | 2377 | } |
michael@0 | 2378 | #undef cx |
michael@0 | 2379 | } |
michael@0 | 2380 | } else |
michael@0 | 2381 | #endif |
michael@0 | 2382 | { |
michael@0 | 2383 | PK11Context *mac_context = |
michael@0 | 2384 | (useServerMacKey ? spec->server.write_mac_context |
michael@0 | 2385 | : spec->client.write_mac_context); |
michael@0 | 2386 | rv = PK11_DigestBegin(mac_context); |
michael@0 | 2387 | rv |= PK11_DigestOp(mac_context, header, headerLen); |
michael@0 | 2388 | rv |= PK11_DigestOp(mac_context, input, inputLength); |
michael@0 | 2389 | rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); |
michael@0 | 2390 | } |
michael@0 | 2391 | |
michael@0 | 2392 | PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size); |
michael@0 | 2393 | |
michael@0 | 2394 | PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength)); |
michael@0 | 2395 | |
michael@0 | 2396 | if (rv != SECSuccess) { |
michael@0 | 2397 | rv = SECFailure; |
michael@0 | 2398 | ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
michael@0 | 2399 | } |
michael@0 | 2400 | return rv; |
michael@0 | 2401 | } |
michael@0 | 2402 | |
michael@0 | 2403 | /* Called from: ssl3_HandleRecord() |
michael@0 | 2404 | * Caller must already hold the SpecReadLock. (wish we could assert that!) |
michael@0 | 2405 | * |
michael@0 | 2406 | * On entry: |
michael@0 | 2407 | * originalLen >= inputLen >= MAC size |
michael@0 | 2408 | */ |
michael@0 | 2409 | static SECStatus |
michael@0 | 2410 | ssl3_ComputeRecordMACConstantTime( |
michael@0 | 2411 | ssl3CipherSpec * spec, |
michael@0 | 2412 | PRBool useServerMacKey, |
michael@0 | 2413 | const unsigned char *header, |
michael@0 | 2414 | unsigned int headerLen, |
michael@0 | 2415 | const SSL3Opaque * input, |
michael@0 | 2416 | int inputLen, |
michael@0 | 2417 | int originalLen, |
michael@0 | 2418 | unsigned char * outbuf, |
michael@0 | 2419 | unsigned int * outLen) |
michael@0 | 2420 | { |
michael@0 | 2421 | CK_MECHANISM_TYPE macType; |
michael@0 | 2422 | CK_NSS_MAC_CONSTANT_TIME_PARAMS params; |
michael@0 | 2423 | SECItem param, inputItem, outputItem; |
michael@0 | 2424 | SECStatus rv; |
michael@0 | 2425 | PK11SymKey * key; |
michael@0 | 2426 | |
michael@0 | 2427 | PORT_Assert(inputLen >= spec->mac_size); |
michael@0 | 2428 | PORT_Assert(originalLen >= inputLen); |
michael@0 | 2429 | |
michael@0 | 2430 | if (spec->bypassCiphers) { |
michael@0 | 2431 | /* This function doesn't support PKCS#11 bypass. We fallback on the |
michael@0 | 2432 | * non-constant time version. */ |
michael@0 | 2433 | goto fallback; |
michael@0 | 2434 | } |
michael@0 | 2435 | |
michael@0 | 2436 | if (spec->mac_def->mac == mac_null) { |
michael@0 | 2437 | *outLen = 0; |
michael@0 | 2438 | return SECSuccess; |
michael@0 | 2439 | } |
michael@0 | 2440 | |
michael@0 | 2441 | macType = CKM_NSS_HMAC_CONSTANT_TIME; |
michael@0 | 2442 | if (spec->version <= SSL_LIBRARY_VERSION_3_0) { |
michael@0 | 2443 | macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME; |
michael@0 | 2444 | } |
michael@0 | 2445 | |
michael@0 | 2446 | params.macAlg = spec->mac_def->mmech; |
michael@0 | 2447 | params.ulBodyTotalLen = originalLen; |
michael@0 | 2448 | params.pHeader = (unsigned char *) header; /* const cast */ |
michael@0 | 2449 | params.ulHeaderLen = headerLen; |
michael@0 | 2450 | |
michael@0 | 2451 | param.data = (unsigned char*) ¶ms; |
michael@0 | 2452 | param.len = sizeof(params); |
michael@0 | 2453 | param.type = 0; |
michael@0 | 2454 | |
michael@0 | 2455 | inputItem.data = (unsigned char *) input; |
michael@0 | 2456 | inputItem.len = inputLen; |
michael@0 | 2457 | inputItem.type = 0; |
michael@0 | 2458 | |
michael@0 | 2459 | outputItem.data = outbuf; |
michael@0 | 2460 | outputItem.len = *outLen; |
michael@0 | 2461 | outputItem.type = 0; |
michael@0 | 2462 | |
michael@0 | 2463 | key = spec->server.write_mac_key; |
michael@0 | 2464 | if (!useServerMacKey) { |
michael@0 | 2465 | key = spec->client.write_mac_key; |
michael@0 | 2466 | } |
michael@0 | 2467 | |
michael@0 | 2468 | rv = PK11_SignWithSymKey(key, macType, ¶m, &outputItem, &inputItem); |
michael@0 | 2469 | if (rv != SECSuccess) { |
michael@0 | 2470 | if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) { |
michael@0 | 2471 | goto fallback; |
michael@0 | 2472 | } |
michael@0 | 2473 | |
michael@0 | 2474 | *outLen = 0; |
michael@0 | 2475 | rv = SECFailure; |
michael@0 | 2476 | ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
michael@0 | 2477 | return rv; |
michael@0 | 2478 | } |
michael@0 | 2479 | |
michael@0 | 2480 | PORT_Assert(outputItem.len == (unsigned)spec->mac_size); |
michael@0 | 2481 | *outLen = outputItem.len; |
michael@0 | 2482 | |
michael@0 | 2483 | return rv; |
michael@0 | 2484 | |
michael@0 | 2485 | fallback: |
michael@0 | 2486 | /* ssl3_ComputeRecordMAC expects the MAC to have been removed from the |
michael@0 | 2487 | * length already. */ |
michael@0 | 2488 | inputLen -= spec->mac_size; |
michael@0 | 2489 | return ssl3_ComputeRecordMAC(spec, useServerMacKey, header, headerLen, |
michael@0 | 2490 | input, inputLen, outbuf, outLen); |
michael@0 | 2491 | } |
michael@0 | 2492 | |
michael@0 | 2493 | static PRBool |
michael@0 | 2494 | ssl3_ClientAuthTokenPresent(sslSessionID *sid) { |
michael@0 | 2495 | PK11SlotInfo *slot = NULL; |
michael@0 | 2496 | PRBool isPresent = PR_TRUE; |
michael@0 | 2497 | |
michael@0 | 2498 | /* we only care if we are doing client auth */ |
michael@0 | 2499 | if (!sid || !sid->u.ssl3.clAuthValid) { |
michael@0 | 2500 | return PR_TRUE; |
michael@0 | 2501 | } |
michael@0 | 2502 | |
michael@0 | 2503 | /* get the slot */ |
michael@0 | 2504 | slot = SECMOD_LookupSlot(sid->u.ssl3.clAuthModuleID, |
michael@0 | 2505 | sid->u.ssl3.clAuthSlotID); |
michael@0 | 2506 | if (slot == NULL || |
michael@0 | 2507 | !PK11_IsPresent(slot) || |
michael@0 | 2508 | sid->u.ssl3.clAuthSeries != PK11_GetSlotSeries(slot) || |
michael@0 | 2509 | sid->u.ssl3.clAuthSlotID != PK11_GetSlotID(slot) || |
michael@0 | 2510 | sid->u.ssl3.clAuthModuleID != PK11_GetModuleID(slot) || |
michael@0 | 2511 | (PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) { |
michael@0 | 2512 | isPresent = PR_FALSE; |
michael@0 | 2513 | } |
michael@0 | 2514 | if (slot) { |
michael@0 | 2515 | PK11_FreeSlot(slot); |
michael@0 | 2516 | } |
michael@0 | 2517 | return isPresent; |
michael@0 | 2518 | } |
michael@0 | 2519 | |
michael@0 | 2520 | /* Caller must hold the spec read lock. */ |
michael@0 | 2521 | SECStatus |
michael@0 | 2522 | ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, |
michael@0 | 2523 | PRBool isServer, |
michael@0 | 2524 | PRBool isDTLS, |
michael@0 | 2525 | PRBool capRecordVersion, |
michael@0 | 2526 | SSL3ContentType type, |
michael@0 | 2527 | const SSL3Opaque * pIn, |
michael@0 | 2528 | PRUint32 contentLen, |
michael@0 | 2529 | sslBuffer * wrBuf) |
michael@0 | 2530 | { |
michael@0 | 2531 | const ssl3BulkCipherDef * cipher_def; |
michael@0 | 2532 | SECStatus rv; |
michael@0 | 2533 | PRUint32 macLen = 0; |
michael@0 | 2534 | PRUint32 fragLen; |
michael@0 | 2535 | PRUint32 p1Len, p2Len, oddLen = 0; |
michael@0 | 2536 | PRUint16 headerLen; |
michael@0 | 2537 | int ivLen = 0; |
michael@0 | 2538 | int cipherBytes = 0; |
michael@0 | 2539 | unsigned char pseudoHeader[13]; |
michael@0 | 2540 | unsigned int pseudoHeaderLen; |
michael@0 | 2541 | |
michael@0 | 2542 | cipher_def = cwSpec->cipher_def; |
michael@0 | 2543 | headerLen = isDTLS ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH; |
michael@0 | 2544 | |
michael@0 | 2545 | if (cipher_def->type == type_block && |
michael@0 | 2546 | cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
michael@0 | 2547 | /* Prepend the per-record explicit IV using technique 2b from |
michael@0 | 2548 | * RFC 4346 section 6.2.3.2: The IV is a cryptographically |
michael@0 | 2549 | * strong random number XORed with the CBC residue from the previous |
michael@0 | 2550 | * record. |
michael@0 | 2551 | */ |
michael@0 | 2552 | ivLen = cipher_def->iv_size; |
michael@0 | 2553 | if (ivLen > wrBuf->space - headerLen) { |
michael@0 | 2554 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 2555 | return SECFailure; |
michael@0 | 2556 | } |
michael@0 | 2557 | rv = PK11_GenerateRandom(wrBuf->buf + headerLen, ivLen); |
michael@0 | 2558 | if (rv != SECSuccess) { |
michael@0 | 2559 | ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); |
michael@0 | 2560 | return rv; |
michael@0 | 2561 | } |
michael@0 | 2562 | rv = cwSpec->encode( cwSpec->encodeContext, |
michael@0 | 2563 | wrBuf->buf + headerLen, |
michael@0 | 2564 | &cipherBytes, /* output and actual outLen */ |
michael@0 | 2565 | ivLen, /* max outlen */ |
michael@0 | 2566 | wrBuf->buf + headerLen, |
michael@0 | 2567 | ivLen); /* input and inputLen*/ |
michael@0 | 2568 | if (rv != SECSuccess || cipherBytes != ivLen) { |
michael@0 | 2569 | PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); |
michael@0 | 2570 | return SECFailure; |
michael@0 | 2571 | } |
michael@0 | 2572 | } |
michael@0 | 2573 | |
michael@0 | 2574 | if (cwSpec->compressor) { |
michael@0 | 2575 | int outlen; |
michael@0 | 2576 | rv = cwSpec->compressor( |
michael@0 | 2577 | cwSpec->compressContext, |
michael@0 | 2578 | wrBuf->buf + headerLen + ivLen, &outlen, |
michael@0 | 2579 | wrBuf->space - headerLen - ivLen, pIn, contentLen); |
michael@0 | 2580 | if (rv != SECSuccess) |
michael@0 | 2581 | return rv; |
michael@0 | 2582 | pIn = wrBuf->buf + headerLen + ivLen; |
michael@0 | 2583 | contentLen = outlen; |
michael@0 | 2584 | } |
michael@0 | 2585 | |
michael@0 | 2586 | pseudoHeaderLen = ssl3_BuildRecordPseudoHeader( |
michael@0 | 2587 | pseudoHeader, cwSpec->write_seq_num, type, |
michael@0 | 2588 | cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version, |
michael@0 | 2589 | isDTLS, contentLen); |
michael@0 | 2590 | PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader)); |
michael@0 | 2591 | if (cipher_def->type == type_aead) { |
michael@0 | 2592 | const int nonceLen = cipher_def->explicit_nonce_size; |
michael@0 | 2593 | const int tagLen = cipher_def->tag_size; |
michael@0 | 2594 | |
michael@0 | 2595 | if (headerLen + nonceLen + contentLen + tagLen > wrBuf->space) { |
michael@0 | 2596 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 2597 | return SECFailure; |
michael@0 | 2598 | } |
michael@0 | 2599 | |
michael@0 | 2600 | cipherBytes = contentLen; |
michael@0 | 2601 | rv = cwSpec->aead( |
michael@0 | 2602 | isServer ? &cwSpec->server : &cwSpec->client, |
michael@0 | 2603 | PR_FALSE, /* do encrypt */ |
michael@0 | 2604 | wrBuf->buf + headerLen, /* output */ |
michael@0 | 2605 | &cipherBytes, /* out len */ |
michael@0 | 2606 | wrBuf->space - headerLen, /* max out */ |
michael@0 | 2607 | pIn, contentLen, /* input */ |
michael@0 | 2608 | pseudoHeader, pseudoHeaderLen); |
michael@0 | 2609 | if (rv != SECSuccess) { |
michael@0 | 2610 | PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); |
michael@0 | 2611 | return SECFailure; |
michael@0 | 2612 | } |
michael@0 | 2613 | } else { |
michael@0 | 2614 | /* |
michael@0 | 2615 | * Add the MAC |
michael@0 | 2616 | */ |
michael@0 | 2617 | rv = ssl3_ComputeRecordMAC(cwSpec, isServer, |
michael@0 | 2618 | pseudoHeader, pseudoHeaderLen, pIn, contentLen, |
michael@0 | 2619 | wrBuf->buf + headerLen + ivLen + contentLen, &macLen); |
michael@0 | 2620 | if (rv != SECSuccess) { |
michael@0 | 2621 | ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); |
michael@0 | 2622 | return SECFailure; |
michael@0 | 2623 | } |
michael@0 | 2624 | p1Len = contentLen; |
michael@0 | 2625 | p2Len = macLen; |
michael@0 | 2626 | fragLen = contentLen + macLen; /* needs to be encrypted */ |
michael@0 | 2627 | PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024); |
michael@0 | 2628 | |
michael@0 | 2629 | /* |
michael@0 | 2630 | * Pad the text (if we're doing a block cipher) |
michael@0 | 2631 | * then Encrypt it |
michael@0 | 2632 | */ |
michael@0 | 2633 | if (cipher_def->type == type_block) { |
michael@0 | 2634 | unsigned char * pBuf; |
michael@0 | 2635 | int padding_length; |
michael@0 | 2636 | int i; |
michael@0 | 2637 | |
michael@0 | 2638 | oddLen = contentLen % cipher_def->block_size; |
michael@0 | 2639 | /* Assume blockSize is a power of two */ |
michael@0 | 2640 | padding_length = cipher_def->block_size - 1 - |
michael@0 | 2641 | ((fragLen) & (cipher_def->block_size - 1)); |
michael@0 | 2642 | fragLen += padding_length + 1; |
michael@0 | 2643 | PORT_Assert((fragLen % cipher_def->block_size) == 0); |
michael@0 | 2644 | |
michael@0 | 2645 | /* Pad according to TLS rules (also acceptable to SSL3). */ |
michael@0 | 2646 | pBuf = &wrBuf->buf[headerLen + ivLen + fragLen - 1]; |
michael@0 | 2647 | for (i = padding_length + 1; i > 0; --i) { |
michael@0 | 2648 | *pBuf-- = padding_length; |
michael@0 | 2649 | } |
michael@0 | 2650 | /* now, if contentLen is not a multiple of block size, fix it */ |
michael@0 | 2651 | p2Len = fragLen - p1Len; |
michael@0 | 2652 | } |
michael@0 | 2653 | if (p1Len < 256) { |
michael@0 | 2654 | oddLen = p1Len; |
michael@0 | 2655 | p1Len = 0; |
michael@0 | 2656 | } else { |
michael@0 | 2657 | p1Len -= oddLen; |
michael@0 | 2658 | } |
michael@0 | 2659 | if (oddLen) { |
michael@0 | 2660 | p2Len += oddLen; |
michael@0 | 2661 | PORT_Assert( (cipher_def->block_size < 2) || \ |
michael@0 | 2662 | (p2Len % cipher_def->block_size) == 0); |
michael@0 | 2663 | memmove(wrBuf->buf + headerLen + ivLen + p1Len, pIn + p1Len, |
michael@0 | 2664 | oddLen); |
michael@0 | 2665 | } |
michael@0 | 2666 | if (p1Len > 0) { |
michael@0 | 2667 | int cipherBytesPart1 = -1; |
michael@0 | 2668 | rv = cwSpec->encode( cwSpec->encodeContext, |
michael@0 | 2669 | wrBuf->buf + headerLen + ivLen, /* output */ |
michael@0 | 2670 | &cipherBytesPart1, /* actual outlen */ |
michael@0 | 2671 | p1Len, /* max outlen */ |
michael@0 | 2672 | pIn, p1Len); /* input, and inputlen */ |
michael@0 | 2673 | PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int) p1Len); |
michael@0 | 2674 | if (rv != SECSuccess || cipherBytesPart1 != (int) p1Len) { |
michael@0 | 2675 | PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); |
michael@0 | 2676 | return SECFailure; |
michael@0 | 2677 | } |
michael@0 | 2678 | cipherBytes += cipherBytesPart1; |
michael@0 | 2679 | } |
michael@0 | 2680 | if (p2Len > 0) { |
michael@0 | 2681 | int cipherBytesPart2 = -1; |
michael@0 | 2682 | rv = cwSpec->encode( cwSpec->encodeContext, |
michael@0 | 2683 | wrBuf->buf + headerLen + ivLen + p1Len, |
michael@0 | 2684 | &cipherBytesPart2, /* output and actual outLen */ |
michael@0 | 2685 | p2Len, /* max outlen */ |
michael@0 | 2686 | wrBuf->buf + headerLen + ivLen + p1Len, |
michael@0 | 2687 | p2Len); /* input and inputLen*/ |
michael@0 | 2688 | PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int) p2Len); |
michael@0 | 2689 | if (rv != SECSuccess || cipherBytesPart2 != (int) p2Len) { |
michael@0 | 2690 | PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); |
michael@0 | 2691 | return SECFailure; |
michael@0 | 2692 | } |
michael@0 | 2693 | cipherBytes += cipherBytesPart2; |
michael@0 | 2694 | } |
michael@0 | 2695 | } |
michael@0 | 2696 | |
michael@0 | 2697 | PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024); |
michael@0 | 2698 | |
michael@0 | 2699 | wrBuf->len = cipherBytes + headerLen; |
michael@0 | 2700 | wrBuf->buf[0] = type; |
michael@0 | 2701 | if (isDTLS) { |
michael@0 | 2702 | SSL3ProtocolVersion version; |
michael@0 | 2703 | |
michael@0 | 2704 | version = dtls_TLSVersionToDTLSVersion(cwSpec->version); |
michael@0 | 2705 | wrBuf->buf[1] = MSB(version); |
michael@0 | 2706 | wrBuf->buf[2] = LSB(version); |
michael@0 | 2707 | wrBuf->buf[3] = (unsigned char)(cwSpec->write_seq_num.high >> 24); |
michael@0 | 2708 | wrBuf->buf[4] = (unsigned char)(cwSpec->write_seq_num.high >> 16); |
michael@0 | 2709 | wrBuf->buf[5] = (unsigned char)(cwSpec->write_seq_num.high >> 8); |
michael@0 | 2710 | wrBuf->buf[6] = (unsigned char)(cwSpec->write_seq_num.high >> 0); |
michael@0 | 2711 | wrBuf->buf[7] = (unsigned char)(cwSpec->write_seq_num.low >> 24); |
michael@0 | 2712 | wrBuf->buf[8] = (unsigned char)(cwSpec->write_seq_num.low >> 16); |
michael@0 | 2713 | wrBuf->buf[9] = (unsigned char)(cwSpec->write_seq_num.low >> 8); |
michael@0 | 2714 | wrBuf->buf[10] = (unsigned char)(cwSpec->write_seq_num.low >> 0); |
michael@0 | 2715 | wrBuf->buf[11] = MSB(cipherBytes); |
michael@0 | 2716 | wrBuf->buf[12] = LSB(cipherBytes); |
michael@0 | 2717 | } else { |
michael@0 | 2718 | SSL3ProtocolVersion version = cwSpec->version; |
michael@0 | 2719 | |
michael@0 | 2720 | if (capRecordVersion) { |
michael@0 | 2721 | version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version); |
michael@0 | 2722 | } |
michael@0 | 2723 | wrBuf->buf[1] = MSB(version); |
michael@0 | 2724 | wrBuf->buf[2] = LSB(version); |
michael@0 | 2725 | wrBuf->buf[3] = MSB(cipherBytes); |
michael@0 | 2726 | wrBuf->buf[4] = LSB(cipherBytes); |
michael@0 | 2727 | } |
michael@0 | 2728 | |
michael@0 | 2729 | ssl3_BumpSequenceNumber(&cwSpec->write_seq_num); |
michael@0 | 2730 | |
michael@0 | 2731 | return SECSuccess; |
michael@0 | 2732 | } |
michael@0 | 2733 | |
michael@0 | 2734 | /* Process the plain text before sending it. |
michael@0 | 2735 | * Returns the number of bytes of plaintext that were successfully sent |
michael@0 | 2736 | * plus the number of bytes of plaintext that were copied into the |
michael@0 | 2737 | * output (write) buffer. |
michael@0 | 2738 | * Returns SECFailure on a hard IO error, memory error, or crypto error. |
michael@0 | 2739 | * Does NOT return SECWouldBlock. |
michael@0 | 2740 | * |
michael@0 | 2741 | * Notes on the use of the private ssl flags: |
michael@0 | 2742 | * (no private SSL flags) |
michael@0 | 2743 | * Attempt to make and send SSL records for all plaintext |
michael@0 | 2744 | * If non-blocking and a send gets WOULD_BLOCK, |
michael@0 | 2745 | * or if the pending (ciphertext) buffer is not empty, |
michael@0 | 2746 | * then buffer remaining bytes of ciphertext into pending buf, |
michael@0 | 2747 | * and continue to do that for all succssive records until all |
michael@0 | 2748 | * bytes are used. |
michael@0 | 2749 | * ssl_SEND_FLAG_FORCE_INTO_BUFFER |
michael@0 | 2750 | * As above, except this suppresses all write attempts, and forces |
michael@0 | 2751 | * all ciphertext into the pending ciphertext buffer. |
michael@0 | 2752 | * ssl_SEND_FLAG_USE_EPOCH (for DTLS) |
michael@0 | 2753 | * Forces the use of the provided epoch |
michael@0 | 2754 | * ssl_SEND_FLAG_CAP_RECORD_VERSION |
michael@0 | 2755 | * Caps the record layer version number of TLS ClientHello to { 3, 1 } |
michael@0 | 2756 | * (TLS 1.0). Some TLS 1.0 servers (which seem to use F5 BIG-IP) ignore |
michael@0 | 2757 | * ClientHello.client_version and use the record layer version number |
michael@0 | 2758 | * (TLSPlaintext.version) instead when negotiating protocol versions. In |
michael@0 | 2759 | * addition, if the record layer version number of ClientHello is { 3, 2 } |
michael@0 | 2760 | * (TLS 1.1) or higher, these servers reset the TCP connections. Lastly, |
michael@0 | 2761 | * some F5 BIG-IP servers hang if a record containing a ClientHello has a |
michael@0 | 2762 | * version greater than { 3, 1 } and a length greater than 255. Set this |
michael@0 | 2763 | * flag to work around such servers. |
michael@0 | 2764 | */ |
michael@0 | 2765 | PRInt32 |
michael@0 | 2766 | ssl3_SendRecord( sslSocket * ss, |
michael@0 | 2767 | DTLSEpoch epoch, /* DTLS only */ |
michael@0 | 2768 | SSL3ContentType type, |
michael@0 | 2769 | const SSL3Opaque * pIn, /* input buffer */ |
michael@0 | 2770 | PRInt32 nIn, /* bytes of input */ |
michael@0 | 2771 | PRInt32 flags) |
michael@0 | 2772 | { |
michael@0 | 2773 | sslBuffer * wrBuf = &ss->sec.writeBuf; |
michael@0 | 2774 | SECStatus rv; |
michael@0 | 2775 | PRInt32 totalSent = 0; |
michael@0 | 2776 | PRBool capRecordVersion; |
michael@0 | 2777 | |
michael@0 | 2778 | SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d", |
michael@0 | 2779 | SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), |
michael@0 | 2780 | nIn)); |
michael@0 | 2781 | PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn)); |
michael@0 | 2782 | |
michael@0 | 2783 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 2784 | |
michael@0 | 2785 | capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0); |
michael@0 | 2786 | |
michael@0 | 2787 | if (capRecordVersion) { |
michael@0 | 2788 | /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the |
michael@0 | 2789 | * TLS initial ClientHello. */ |
michael@0 | 2790 | PORT_Assert(!IS_DTLS(ss)); |
michael@0 | 2791 | PORT_Assert(!ss->firstHsDone); |
michael@0 | 2792 | PORT_Assert(type == content_handshake); |
michael@0 | 2793 | PORT_Assert(ss->ssl3.hs.ws == wait_server_hello); |
michael@0 | 2794 | } |
michael@0 | 2795 | |
michael@0 | 2796 | if (ss->ssl3.initialized == PR_FALSE) { |
michael@0 | 2797 | /* This can happen on a server if the very first incoming record |
michael@0 | 2798 | ** looks like a defective ssl3 record (e.g. too long), and we're |
michael@0 | 2799 | ** trying to send an alert. |
michael@0 | 2800 | */ |
michael@0 | 2801 | PR_ASSERT(type == content_alert); |
michael@0 | 2802 | rv = ssl3_InitState(ss); |
michael@0 | 2803 | if (rv != SECSuccess) { |
michael@0 | 2804 | return SECFailure; /* ssl3_InitState has set the error code. */ |
michael@0 | 2805 | } |
michael@0 | 2806 | } |
michael@0 | 2807 | |
michael@0 | 2808 | /* check for Token Presence */ |
michael@0 | 2809 | if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) { |
michael@0 | 2810 | PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); |
michael@0 | 2811 | return SECFailure; |
michael@0 | 2812 | } |
michael@0 | 2813 | |
michael@0 | 2814 | while (nIn > 0) { |
michael@0 | 2815 | PRUint32 contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); |
michael@0 | 2816 | unsigned int spaceNeeded; |
michael@0 | 2817 | unsigned int numRecords; |
michael@0 | 2818 | |
michael@0 | 2819 | ssl_GetSpecReadLock(ss); /********************************/ |
michael@0 | 2820 | |
michael@0 | 2821 | if (nIn > 1 && ss->opt.cbcRandomIV && |
michael@0 | 2822 | ss->ssl3.cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_1 && |
michael@0 | 2823 | type == content_application_data && |
michael@0 | 2824 | ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC mode */) { |
michael@0 | 2825 | /* We will split the first byte of the record into its own record, |
michael@0 | 2826 | * as explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h |
michael@0 | 2827 | */ |
michael@0 | 2828 | numRecords = 2; |
michael@0 | 2829 | } else { |
michael@0 | 2830 | numRecords = 1; |
michael@0 | 2831 | } |
michael@0 | 2832 | |
michael@0 | 2833 | spaceNeeded = contentLen + (numRecords * SSL3_BUFFER_FUDGE); |
michael@0 | 2834 | if (ss->ssl3.cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1 && |
michael@0 | 2835 | ss->ssl3.cwSpec->cipher_def->type == type_block) { |
michael@0 | 2836 | spaceNeeded += ss->ssl3.cwSpec->cipher_def->iv_size; |
michael@0 | 2837 | } |
michael@0 | 2838 | if (spaceNeeded > wrBuf->space) { |
michael@0 | 2839 | rv = sslBuffer_Grow(wrBuf, spaceNeeded); |
michael@0 | 2840 | if (rv != SECSuccess) { |
michael@0 | 2841 | SSL_DBG(("%d: SSL3[%d]: SendRecord, tried to get %d bytes", |
michael@0 | 2842 | SSL_GETPID(), ss->fd, spaceNeeded)); |
michael@0 | 2843 | goto spec_locked_loser; /* sslBuffer_Grow set error code. */ |
michael@0 | 2844 | } |
michael@0 | 2845 | } |
michael@0 | 2846 | |
michael@0 | 2847 | if (numRecords == 2) { |
michael@0 | 2848 | sslBuffer secondRecord; |
michael@0 | 2849 | |
michael@0 | 2850 | rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, |
michael@0 | 2851 | ss->sec.isServer, IS_DTLS(ss), |
michael@0 | 2852 | capRecordVersion, type, pIn, |
michael@0 | 2853 | 1, wrBuf); |
michael@0 | 2854 | if (rv != SECSuccess) |
michael@0 | 2855 | goto spec_locked_loser; |
michael@0 | 2856 | |
michael@0 | 2857 | PRINT_BUF(50, (ss, "send (encrypted) record data [1/2]:", |
michael@0 | 2858 | wrBuf->buf, wrBuf->len)); |
michael@0 | 2859 | |
michael@0 | 2860 | secondRecord.buf = wrBuf->buf + wrBuf->len; |
michael@0 | 2861 | secondRecord.len = 0; |
michael@0 | 2862 | secondRecord.space = wrBuf->space - wrBuf->len; |
michael@0 | 2863 | |
michael@0 | 2864 | rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, |
michael@0 | 2865 | ss->sec.isServer, IS_DTLS(ss), |
michael@0 | 2866 | capRecordVersion, type, |
michael@0 | 2867 | pIn + 1, contentLen - 1, |
michael@0 | 2868 | &secondRecord); |
michael@0 | 2869 | if (rv == SECSuccess) { |
michael@0 | 2870 | PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:", |
michael@0 | 2871 | secondRecord.buf, secondRecord.len)); |
michael@0 | 2872 | wrBuf->len += secondRecord.len; |
michael@0 | 2873 | } |
michael@0 | 2874 | } else { |
michael@0 | 2875 | if (!IS_DTLS(ss)) { |
michael@0 | 2876 | rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec, |
michael@0 | 2877 | ss->sec.isServer, |
michael@0 | 2878 | IS_DTLS(ss), |
michael@0 | 2879 | capRecordVersion, |
michael@0 | 2880 | type, pIn, |
michael@0 | 2881 | contentLen, wrBuf); |
michael@0 | 2882 | } else { |
michael@0 | 2883 | rv = dtls_CompressMACEncryptRecord(ss, epoch, |
michael@0 | 2884 | !!(flags & ssl_SEND_FLAG_USE_EPOCH), |
michael@0 | 2885 | type, pIn, |
michael@0 | 2886 | contentLen, wrBuf); |
michael@0 | 2887 | } |
michael@0 | 2888 | |
michael@0 | 2889 | if (rv == SECSuccess) { |
michael@0 | 2890 | PRINT_BUF(50, (ss, "send (encrypted) record data:", |
michael@0 | 2891 | wrBuf->buf, wrBuf->len)); |
michael@0 | 2892 | } |
michael@0 | 2893 | } |
michael@0 | 2894 | |
michael@0 | 2895 | spec_locked_loser: |
michael@0 | 2896 | ssl_ReleaseSpecReadLock(ss); /************************************/ |
michael@0 | 2897 | |
michael@0 | 2898 | if (rv != SECSuccess) |
michael@0 | 2899 | return SECFailure; |
michael@0 | 2900 | |
michael@0 | 2901 | pIn += contentLen; |
michael@0 | 2902 | nIn -= contentLen; |
michael@0 | 2903 | PORT_Assert( nIn >= 0 ); |
michael@0 | 2904 | |
michael@0 | 2905 | /* If there's still some previously saved ciphertext, |
michael@0 | 2906 | * or the caller doesn't want us to send the data yet, |
michael@0 | 2907 | * then add all our new ciphertext to the amount previously saved. |
michael@0 | 2908 | */ |
michael@0 | 2909 | if ((ss->pendingBuf.len > 0) || |
michael@0 | 2910 | (flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { |
michael@0 | 2911 | |
michael@0 | 2912 | rv = ssl_SaveWriteData(ss, wrBuf->buf, wrBuf->len); |
michael@0 | 2913 | if (rv != SECSuccess) { |
michael@0 | 2914 | /* presumably a memory error, SEC_ERROR_NO_MEMORY */ |
michael@0 | 2915 | return SECFailure; |
michael@0 | 2916 | } |
michael@0 | 2917 | wrBuf->len = 0; /* All cipher text is saved away. */ |
michael@0 | 2918 | |
michael@0 | 2919 | if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) { |
michael@0 | 2920 | PRInt32 sent; |
michael@0 | 2921 | ss->handshakeBegun = 1; |
michael@0 | 2922 | sent = ssl_SendSavedWriteData(ss); |
michael@0 | 2923 | if (sent < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) { |
michael@0 | 2924 | ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE); |
michael@0 | 2925 | return SECFailure; |
michael@0 | 2926 | } |
michael@0 | 2927 | if (ss->pendingBuf.len) { |
michael@0 | 2928 | flags |= ssl_SEND_FLAG_FORCE_INTO_BUFFER; |
michael@0 | 2929 | } |
michael@0 | 2930 | } |
michael@0 | 2931 | } else if (wrBuf->len > 0) { |
michael@0 | 2932 | PRInt32 sent; |
michael@0 | 2933 | ss->handshakeBegun = 1; |
michael@0 | 2934 | sent = ssl_DefSend(ss, wrBuf->buf, wrBuf->len, |
michael@0 | 2935 | flags & ~ssl_SEND_FLAG_MASK); |
michael@0 | 2936 | if (sent < 0) { |
michael@0 | 2937 | if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { |
michael@0 | 2938 | ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE); |
michael@0 | 2939 | return SECFailure; |
michael@0 | 2940 | } |
michael@0 | 2941 | /* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */ |
michael@0 | 2942 | sent = 0; |
michael@0 | 2943 | } |
michael@0 | 2944 | wrBuf->len -= sent; |
michael@0 | 2945 | if (wrBuf->len) { |
michael@0 | 2946 | if (IS_DTLS(ss)) { |
michael@0 | 2947 | /* DTLS just says no in this case. No buffering */ |
michael@0 | 2948 | PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
michael@0 | 2949 | return SECFailure; |
michael@0 | 2950 | } |
michael@0 | 2951 | /* now take all the remaining unsent new ciphertext and |
michael@0 | 2952 | * append it to the buffer of previously unsent ciphertext. |
michael@0 | 2953 | */ |
michael@0 | 2954 | rv = ssl_SaveWriteData(ss, wrBuf->buf + sent, wrBuf->len); |
michael@0 | 2955 | if (rv != SECSuccess) { |
michael@0 | 2956 | /* presumably a memory error, SEC_ERROR_NO_MEMORY */ |
michael@0 | 2957 | return SECFailure; |
michael@0 | 2958 | } |
michael@0 | 2959 | } |
michael@0 | 2960 | } |
michael@0 | 2961 | totalSent += contentLen; |
michael@0 | 2962 | } |
michael@0 | 2963 | return totalSent; |
michael@0 | 2964 | } |
michael@0 | 2965 | |
michael@0 | 2966 | #define SSL3_PENDING_HIGH_WATER 1024 |
michael@0 | 2967 | |
michael@0 | 2968 | /* Attempt to send the content of "in" in an SSL application_data record. |
michael@0 | 2969 | * Returns "len" or SECFailure, never SECWouldBlock, nor SECSuccess. |
michael@0 | 2970 | */ |
michael@0 | 2971 | int |
michael@0 | 2972 | ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, |
michael@0 | 2973 | PRInt32 len, PRInt32 flags) |
michael@0 | 2974 | { |
michael@0 | 2975 | PRInt32 totalSent = 0; |
michael@0 | 2976 | PRInt32 discarded = 0; |
michael@0 | 2977 | |
michael@0 | 2978 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 2979 | /* These flags for internal use only */ |
michael@0 | 2980 | PORT_Assert(!(flags & (ssl_SEND_FLAG_USE_EPOCH | |
michael@0 | 2981 | ssl_SEND_FLAG_NO_RETRANSMIT))); |
michael@0 | 2982 | if (len < 0 || !in) { |
michael@0 | 2983 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
michael@0 | 2984 | return SECFailure; |
michael@0 | 2985 | } |
michael@0 | 2986 | |
michael@0 | 2987 | if (ss->pendingBuf.len > SSL3_PENDING_HIGH_WATER && |
michael@0 | 2988 | !ssl_SocketIsBlocking(ss)) { |
michael@0 | 2989 | PORT_Assert(!ssl_SocketIsBlocking(ss)); |
michael@0 | 2990 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
michael@0 | 2991 | return SECFailure; |
michael@0 | 2992 | } |
michael@0 | 2993 | |
michael@0 | 2994 | if (ss->appDataBuffered && len) { |
michael@0 | 2995 | PORT_Assert (in[0] == (unsigned char)(ss->appDataBuffered)); |
michael@0 | 2996 | if (in[0] != (unsigned char)(ss->appDataBuffered)) { |
michael@0 | 2997 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
michael@0 | 2998 | return SECFailure; |
michael@0 | 2999 | } |
michael@0 | 3000 | in++; |
michael@0 | 3001 | len--; |
michael@0 | 3002 | discarded = 1; |
michael@0 | 3003 | } |
michael@0 | 3004 | while (len > totalSent) { |
michael@0 | 3005 | PRInt32 sent, toSend; |
michael@0 | 3006 | |
michael@0 | 3007 | if (totalSent > 0) { |
michael@0 | 3008 | /* |
michael@0 | 3009 | * The thread yield is intended to give the reader thread a |
michael@0 | 3010 | * chance to get some cycles while the writer thread is in |
michael@0 | 3011 | * the middle of a large application data write. (See |
michael@0 | 3012 | * Bugzilla bug 127740, comment #1.) |
michael@0 | 3013 | */ |
michael@0 | 3014 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 3015 | PR_Sleep(PR_INTERVAL_NO_WAIT); /* PR_Yield(); */ |
michael@0 | 3016 | ssl_GetXmitBufLock(ss); |
michael@0 | 3017 | } |
michael@0 | 3018 | toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH); |
michael@0 | 3019 | /* |
michael@0 | 3020 | * Note that the 0 epoch is OK because flags will never require |
michael@0 | 3021 | * its use, as guaranteed by the PORT_Assert above. |
michael@0 | 3022 | */ |
michael@0 | 3023 | sent = ssl3_SendRecord(ss, 0, content_application_data, |
michael@0 | 3024 | in + totalSent, toSend, flags); |
michael@0 | 3025 | if (sent < 0) { |
michael@0 | 3026 | if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) { |
michael@0 | 3027 | PORT_Assert(ss->lastWriteBlocked); |
michael@0 | 3028 | break; |
michael@0 | 3029 | } |
michael@0 | 3030 | return SECFailure; /* error code set by ssl3_SendRecord */ |
michael@0 | 3031 | } |
michael@0 | 3032 | totalSent += sent; |
michael@0 | 3033 | if (ss->pendingBuf.len) { |
michael@0 | 3034 | /* must be a non-blocking socket */ |
michael@0 | 3035 | PORT_Assert(!ssl_SocketIsBlocking(ss)); |
michael@0 | 3036 | PORT_Assert(ss->lastWriteBlocked); |
michael@0 | 3037 | break; |
michael@0 | 3038 | } |
michael@0 | 3039 | } |
michael@0 | 3040 | if (ss->pendingBuf.len) { |
michael@0 | 3041 | /* Must be non-blocking. */ |
michael@0 | 3042 | PORT_Assert(!ssl_SocketIsBlocking(ss)); |
michael@0 | 3043 | if (totalSent > 0) { |
michael@0 | 3044 | ss->appDataBuffered = 0x100 | in[totalSent - 1]; |
michael@0 | 3045 | } |
michael@0 | 3046 | |
michael@0 | 3047 | totalSent = totalSent + discarded - 1; |
michael@0 | 3048 | if (totalSent <= 0) { |
michael@0 | 3049 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
michael@0 | 3050 | totalSent = SECFailure; |
michael@0 | 3051 | } |
michael@0 | 3052 | return totalSent; |
michael@0 | 3053 | } |
michael@0 | 3054 | ss->appDataBuffered = 0; |
michael@0 | 3055 | return totalSent + discarded; |
michael@0 | 3056 | } |
michael@0 | 3057 | |
michael@0 | 3058 | /* Attempt to send buffered handshake messages. |
michael@0 | 3059 | * This function returns SECSuccess or SECFailure, never SECWouldBlock. |
michael@0 | 3060 | * Always set sendBuf.len to 0, even when returning SECFailure. |
michael@0 | 3061 | * |
michael@0 | 3062 | * Depending on whether we are doing DTLS or not, this either calls |
michael@0 | 3063 | * |
michael@0 | 3064 | * - ssl3_FlushHandshakeMessages if non-DTLS |
michael@0 | 3065 | * - dtls_FlushHandshakeMessages if DTLS |
michael@0 | 3066 | * |
michael@0 | 3067 | * Called from SSL3_SendAlert(), ssl3_SendChangeCipherSpecs(), |
michael@0 | 3068 | * ssl3_AppendHandshake(), ssl3_SendClientHello(), |
michael@0 | 3069 | * ssl3_SendHelloRequest(), ssl3_SendServerHelloDone(), |
michael@0 | 3070 | * ssl3_SendFinished(), |
michael@0 | 3071 | */ |
michael@0 | 3072 | static SECStatus |
michael@0 | 3073 | ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags) |
michael@0 | 3074 | { |
michael@0 | 3075 | if (IS_DTLS(ss)) { |
michael@0 | 3076 | return dtls_FlushHandshakeMessages(ss, flags); |
michael@0 | 3077 | } else { |
michael@0 | 3078 | return ssl3_FlushHandshakeMessages(ss, flags); |
michael@0 | 3079 | } |
michael@0 | 3080 | } |
michael@0 | 3081 | |
michael@0 | 3082 | /* Attempt to send the content of sendBuf buffer in an SSL handshake record. |
michael@0 | 3083 | * This function returns SECSuccess or SECFailure, never SECWouldBlock. |
michael@0 | 3084 | * Always set sendBuf.len to 0, even when returning SECFailure. |
michael@0 | 3085 | * |
michael@0 | 3086 | * Called from ssl3_FlushHandshake |
michael@0 | 3087 | */ |
michael@0 | 3088 | static SECStatus |
michael@0 | 3089 | ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags) |
michael@0 | 3090 | { |
michael@0 | 3091 | static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER | |
michael@0 | 3092 | ssl_SEND_FLAG_CAP_RECORD_VERSION; |
michael@0 | 3093 | PRInt32 rv = SECSuccess; |
michael@0 | 3094 | |
michael@0 | 3095 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 3096 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 3097 | |
michael@0 | 3098 | if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len) |
michael@0 | 3099 | return rv; |
michael@0 | 3100 | |
michael@0 | 3101 | /* only these flags are allowed */ |
michael@0 | 3102 | PORT_Assert(!(flags & ~allowedFlags)); |
michael@0 | 3103 | if ((flags & ~allowedFlags) != 0) { |
michael@0 | 3104 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
michael@0 | 3105 | rv = SECFailure; |
michael@0 | 3106 | } else { |
michael@0 | 3107 | rv = ssl3_SendRecord(ss, 0, content_handshake, ss->sec.ci.sendBuf.buf, |
michael@0 | 3108 | ss->sec.ci.sendBuf.len, flags); |
michael@0 | 3109 | } |
michael@0 | 3110 | if (rv < 0) { |
michael@0 | 3111 | int err = PORT_GetError(); |
michael@0 | 3112 | PORT_Assert(err != PR_WOULD_BLOCK_ERROR); |
michael@0 | 3113 | if (err == PR_WOULD_BLOCK_ERROR) { |
michael@0 | 3114 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 3115 | } |
michael@0 | 3116 | } else if (rv < ss->sec.ci.sendBuf.len) { |
michael@0 | 3117 | /* short write should never happen */ |
michael@0 | 3118 | PORT_Assert(rv >= ss->sec.ci.sendBuf.len); |
michael@0 | 3119 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 3120 | rv = SECFailure; |
michael@0 | 3121 | } else { |
michael@0 | 3122 | rv = SECSuccess; |
michael@0 | 3123 | } |
michael@0 | 3124 | |
michael@0 | 3125 | /* Whether we succeeded or failed, toss the old handshake data. */ |
michael@0 | 3126 | ss->sec.ci.sendBuf.len = 0; |
michael@0 | 3127 | return rv; |
michael@0 | 3128 | } |
michael@0 | 3129 | |
michael@0 | 3130 | /* |
michael@0 | 3131 | * Called from ssl3_HandleAlert and from ssl3_HandleCertificate when |
michael@0 | 3132 | * the remote client sends a negative response to our certificate request. |
michael@0 | 3133 | * Returns SECFailure if the application has required client auth. |
michael@0 | 3134 | * SECSuccess otherwise. |
michael@0 | 3135 | */ |
michael@0 | 3136 | static SECStatus |
michael@0 | 3137 | ssl3_HandleNoCertificate(sslSocket *ss) |
michael@0 | 3138 | { |
michael@0 | 3139 | if (ss->sec.peerCert != NULL) { |
michael@0 | 3140 | if (ss->sec.peerKey != NULL) { |
michael@0 | 3141 | SECKEY_DestroyPublicKey(ss->sec.peerKey); |
michael@0 | 3142 | ss->sec.peerKey = NULL; |
michael@0 | 3143 | } |
michael@0 | 3144 | CERT_DestroyCertificate(ss->sec.peerCert); |
michael@0 | 3145 | ss->sec.peerCert = NULL; |
michael@0 | 3146 | } |
michael@0 | 3147 | ssl3_CleanupPeerCerts(ss); |
michael@0 | 3148 | |
michael@0 | 3149 | /* If the server has required client-auth blindly but doesn't |
michael@0 | 3150 | * actually look at the certificate it won't know that no |
michael@0 | 3151 | * certificate was presented so we shutdown the socket to ensure |
michael@0 | 3152 | * an error. We only do this if we haven't already completed the |
michael@0 | 3153 | * first handshake because if we're redoing the handshake we |
michael@0 | 3154 | * know the server is paying attention to the certificate. |
michael@0 | 3155 | */ |
michael@0 | 3156 | if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) || |
michael@0 | 3157 | (!ss->firstHsDone && |
michael@0 | 3158 | (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) { |
michael@0 | 3159 | PRFileDesc * lower; |
michael@0 | 3160 | |
michael@0 | 3161 | if (ss->sec.uncache) |
michael@0 | 3162 | ss->sec.uncache(ss->sec.ci.sid); |
michael@0 | 3163 | SSL3_SendAlert(ss, alert_fatal, bad_certificate); |
michael@0 | 3164 | |
michael@0 | 3165 | lower = ss->fd->lower; |
michael@0 | 3166 | #ifdef _WIN32 |
michael@0 | 3167 | lower->methods->shutdown(lower, PR_SHUTDOWN_SEND); |
michael@0 | 3168 | #else |
michael@0 | 3169 | lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH); |
michael@0 | 3170 | #endif |
michael@0 | 3171 | PORT_SetError(SSL_ERROR_NO_CERTIFICATE); |
michael@0 | 3172 | return SECFailure; |
michael@0 | 3173 | } |
michael@0 | 3174 | return SECSuccess; |
michael@0 | 3175 | } |
michael@0 | 3176 | |
michael@0 | 3177 | /************************************************************************ |
michael@0 | 3178 | * Alerts |
michael@0 | 3179 | */ |
michael@0 | 3180 | |
michael@0 | 3181 | /* |
michael@0 | 3182 | ** Acquires both handshake and XmitBuf locks. |
michael@0 | 3183 | ** Called from: ssl3_IllegalParameter <- |
michael@0 | 3184 | ** ssl3_HandshakeFailure <- |
michael@0 | 3185 | ** ssl3_HandleAlert <- ssl3_HandleRecord. |
michael@0 | 3186 | ** ssl3_HandleChangeCipherSpecs <- ssl3_HandleRecord |
michael@0 | 3187 | ** ssl3_ConsumeHandshakeVariable <- |
michael@0 | 3188 | ** ssl3_HandleHelloRequest <- |
michael@0 | 3189 | ** ssl3_HandleServerHello <- |
michael@0 | 3190 | ** ssl3_HandleServerKeyExchange <- |
michael@0 | 3191 | ** ssl3_HandleCertificateRequest <- |
michael@0 | 3192 | ** ssl3_HandleServerHelloDone <- |
michael@0 | 3193 | ** ssl3_HandleClientHello <- |
michael@0 | 3194 | ** ssl3_HandleV2ClientHello <- |
michael@0 | 3195 | ** ssl3_HandleCertificateVerify <- |
michael@0 | 3196 | ** ssl3_HandleClientKeyExchange <- |
michael@0 | 3197 | ** ssl3_HandleCertificate <- |
michael@0 | 3198 | ** ssl3_HandleFinished <- |
michael@0 | 3199 | ** ssl3_HandleHandshakeMessage <- |
michael@0 | 3200 | ** ssl3_HandleRecord <- |
michael@0 | 3201 | ** |
michael@0 | 3202 | */ |
michael@0 | 3203 | SECStatus |
michael@0 | 3204 | SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) |
michael@0 | 3205 | { |
michael@0 | 3206 | PRUint8 bytes[2]; |
michael@0 | 3207 | SECStatus rv; |
michael@0 | 3208 | |
michael@0 | 3209 | SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d", |
michael@0 | 3210 | SSL_GETPID(), ss->fd, level, desc)); |
michael@0 | 3211 | |
michael@0 | 3212 | bytes[0] = level; |
michael@0 | 3213 | bytes[1] = desc; |
michael@0 | 3214 | |
michael@0 | 3215 | ssl_GetSSL3HandshakeLock(ss); |
michael@0 | 3216 | if (level == alert_fatal) { |
michael@0 | 3217 | if (!ss->opt.noCache && ss->sec.ci.sid && ss->sec.uncache) { |
michael@0 | 3218 | ss->sec.uncache(ss->sec.ci.sid); |
michael@0 | 3219 | } |
michael@0 | 3220 | } |
michael@0 | 3221 | ssl_GetXmitBufLock(ss); |
michael@0 | 3222 | rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); |
michael@0 | 3223 | if (rv == SECSuccess) { |
michael@0 | 3224 | PRInt32 sent; |
michael@0 | 3225 | sent = ssl3_SendRecord(ss, 0, content_alert, bytes, 2, |
michael@0 | 3226 | desc == no_certificate |
michael@0 | 3227 | ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0); |
michael@0 | 3228 | rv = (sent >= 0) ? SECSuccess : (SECStatus)sent; |
michael@0 | 3229 | } |
michael@0 | 3230 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 3231 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 3232 | return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */ |
michael@0 | 3233 | } |
michael@0 | 3234 | |
michael@0 | 3235 | /* |
michael@0 | 3236 | * Send illegal_parameter alert. Set generic error number. |
michael@0 | 3237 | */ |
michael@0 | 3238 | static SECStatus |
michael@0 | 3239 | ssl3_IllegalParameter(sslSocket *ss) |
michael@0 | 3240 | { |
michael@0 | 3241 | (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
michael@0 | 3242 | PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT |
michael@0 | 3243 | : SSL_ERROR_BAD_SERVER ); |
michael@0 | 3244 | return SECFailure; |
michael@0 | 3245 | } |
michael@0 | 3246 | |
michael@0 | 3247 | /* |
michael@0 | 3248 | * Send handshake_Failure alert. Set generic error number. |
michael@0 | 3249 | */ |
michael@0 | 3250 | static SECStatus |
michael@0 | 3251 | ssl3_HandshakeFailure(sslSocket *ss) |
michael@0 | 3252 | { |
michael@0 | 3253 | (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); |
michael@0 | 3254 | PORT_SetError( ss->sec.isServer ? SSL_ERROR_BAD_CLIENT |
michael@0 | 3255 | : SSL_ERROR_BAD_SERVER ); |
michael@0 | 3256 | return SECFailure; |
michael@0 | 3257 | } |
michael@0 | 3258 | |
michael@0 | 3259 | static void |
michael@0 | 3260 | ssl3_SendAlertForCertError(sslSocket * ss, PRErrorCode errCode) |
michael@0 | 3261 | { |
michael@0 | 3262 | SSL3AlertDescription desc = bad_certificate; |
michael@0 | 3263 | PRBool isTLS = ss->version >= SSL_LIBRARY_VERSION_3_1_TLS; |
michael@0 | 3264 | |
michael@0 | 3265 | switch (errCode) { |
michael@0 | 3266 | case SEC_ERROR_LIBRARY_FAILURE: desc = unsupported_certificate; break; |
michael@0 | 3267 | case SEC_ERROR_EXPIRED_CERTIFICATE: desc = certificate_expired; break; |
michael@0 | 3268 | case SEC_ERROR_REVOKED_CERTIFICATE: desc = certificate_revoked; break; |
michael@0 | 3269 | case SEC_ERROR_INADEQUATE_KEY_USAGE: |
michael@0 | 3270 | case SEC_ERROR_INADEQUATE_CERT_TYPE: |
michael@0 | 3271 | desc = certificate_unknown; break; |
michael@0 | 3272 | case SEC_ERROR_UNTRUSTED_CERT: |
michael@0 | 3273 | desc = isTLS ? access_denied : certificate_unknown; break; |
michael@0 | 3274 | case SEC_ERROR_UNKNOWN_ISSUER: |
michael@0 | 3275 | case SEC_ERROR_UNTRUSTED_ISSUER: |
michael@0 | 3276 | desc = isTLS ? unknown_ca : certificate_unknown; break; |
michael@0 | 3277 | case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: |
michael@0 | 3278 | desc = isTLS ? unknown_ca : certificate_expired; break; |
michael@0 | 3279 | |
michael@0 | 3280 | case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: |
michael@0 | 3281 | case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: |
michael@0 | 3282 | case SEC_ERROR_CA_CERT_INVALID: |
michael@0 | 3283 | case SEC_ERROR_BAD_SIGNATURE: |
michael@0 | 3284 | default: desc = bad_certificate; break; |
michael@0 | 3285 | } |
michael@0 | 3286 | SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d", |
michael@0 | 3287 | SSL_GETPID(), ss->fd, errCode)); |
michael@0 | 3288 | |
michael@0 | 3289 | (void) SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 3290 | } |
michael@0 | 3291 | |
michael@0 | 3292 | |
michael@0 | 3293 | /* |
michael@0 | 3294 | * Send decode_error alert. Set generic error number. |
michael@0 | 3295 | */ |
michael@0 | 3296 | SECStatus |
michael@0 | 3297 | ssl3_DecodeError(sslSocket *ss) |
michael@0 | 3298 | { |
michael@0 | 3299 | (void)SSL3_SendAlert(ss, alert_fatal, |
michael@0 | 3300 | ss->version > SSL_LIBRARY_VERSION_3_0 ? decode_error |
michael@0 | 3301 | : illegal_parameter); |
michael@0 | 3302 | PORT_SetError( ss->sec.isServer ? SSL_ERROR_BAD_CLIENT |
michael@0 | 3303 | : SSL_ERROR_BAD_SERVER ); |
michael@0 | 3304 | return SECFailure; |
michael@0 | 3305 | } |
michael@0 | 3306 | |
michael@0 | 3307 | /* Called from ssl3_HandleRecord. |
michael@0 | 3308 | ** Caller must hold both RecvBuf and Handshake locks. |
michael@0 | 3309 | */ |
michael@0 | 3310 | static SECStatus |
michael@0 | 3311 | ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) |
michael@0 | 3312 | { |
michael@0 | 3313 | SSL3AlertLevel level; |
michael@0 | 3314 | SSL3AlertDescription desc; |
michael@0 | 3315 | int error; |
michael@0 | 3316 | |
michael@0 | 3317 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 3318 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 3319 | |
michael@0 | 3320 | SSL_TRC(3, ("%d: SSL3[%d]: handle alert record", SSL_GETPID(), ss->fd)); |
michael@0 | 3321 | |
michael@0 | 3322 | if (buf->len != 2) { |
michael@0 | 3323 | (void)ssl3_DecodeError(ss); |
michael@0 | 3324 | PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT); |
michael@0 | 3325 | return SECFailure; |
michael@0 | 3326 | } |
michael@0 | 3327 | level = (SSL3AlertLevel)buf->buf[0]; |
michael@0 | 3328 | desc = (SSL3AlertDescription)buf->buf[1]; |
michael@0 | 3329 | buf->len = 0; |
michael@0 | 3330 | SSL_TRC(5, ("%d: SSL3[%d] received alert, level = %d, description = %d", |
michael@0 | 3331 | SSL_GETPID(), ss->fd, level, desc)); |
michael@0 | 3332 | |
michael@0 | 3333 | switch (desc) { |
michael@0 | 3334 | case close_notify: ss->recvdCloseNotify = 1; |
michael@0 | 3335 | error = SSL_ERROR_CLOSE_NOTIFY_ALERT; break; |
michael@0 | 3336 | case unexpected_message: error = SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT; |
michael@0 | 3337 | break; |
michael@0 | 3338 | case bad_record_mac: error = SSL_ERROR_BAD_MAC_ALERT; break; |
michael@0 | 3339 | case decryption_failed_RESERVED: |
michael@0 | 3340 | error = SSL_ERROR_DECRYPTION_FAILED_ALERT; |
michael@0 | 3341 | break; |
michael@0 | 3342 | case record_overflow: error = SSL_ERROR_RECORD_OVERFLOW_ALERT; break; |
michael@0 | 3343 | case decompression_failure: error = SSL_ERROR_DECOMPRESSION_FAILURE_ALERT; |
michael@0 | 3344 | break; |
michael@0 | 3345 | case handshake_failure: error = SSL_ERROR_HANDSHAKE_FAILURE_ALERT; |
michael@0 | 3346 | break; |
michael@0 | 3347 | case no_certificate: error = SSL_ERROR_NO_CERTIFICATE; break; |
michael@0 | 3348 | case bad_certificate: error = SSL_ERROR_BAD_CERT_ALERT; break; |
michael@0 | 3349 | case unsupported_certificate:error = SSL_ERROR_UNSUPPORTED_CERT_ALERT;break; |
michael@0 | 3350 | case certificate_revoked: error = SSL_ERROR_REVOKED_CERT_ALERT; break; |
michael@0 | 3351 | case certificate_expired: error = SSL_ERROR_EXPIRED_CERT_ALERT; break; |
michael@0 | 3352 | case certificate_unknown: error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT; |
michael@0 | 3353 | break; |
michael@0 | 3354 | case illegal_parameter: error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;break; |
michael@0 | 3355 | case inappropriate_fallback: |
michael@0 | 3356 | error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT; |
michael@0 | 3357 | break; |
michael@0 | 3358 | |
michael@0 | 3359 | /* All alerts below are TLS only. */ |
michael@0 | 3360 | case unknown_ca: error = SSL_ERROR_UNKNOWN_CA_ALERT; break; |
michael@0 | 3361 | case access_denied: error = SSL_ERROR_ACCESS_DENIED_ALERT; break; |
michael@0 | 3362 | case decode_error: error = SSL_ERROR_DECODE_ERROR_ALERT; break; |
michael@0 | 3363 | case decrypt_error: error = SSL_ERROR_DECRYPT_ERROR_ALERT; break; |
michael@0 | 3364 | case export_restriction: error = SSL_ERROR_EXPORT_RESTRICTION_ALERT; |
michael@0 | 3365 | break; |
michael@0 | 3366 | case protocol_version: error = SSL_ERROR_PROTOCOL_VERSION_ALERT; break; |
michael@0 | 3367 | case insufficient_security: error = SSL_ERROR_INSUFFICIENT_SECURITY_ALERT; |
michael@0 | 3368 | break; |
michael@0 | 3369 | case internal_error: error = SSL_ERROR_INTERNAL_ERROR_ALERT; break; |
michael@0 | 3370 | case user_canceled: error = SSL_ERROR_USER_CANCELED_ALERT; break; |
michael@0 | 3371 | case no_renegotiation: error = SSL_ERROR_NO_RENEGOTIATION_ALERT; break; |
michael@0 | 3372 | |
michael@0 | 3373 | /* Alerts for TLS client hello extensions */ |
michael@0 | 3374 | case unsupported_extension: |
michael@0 | 3375 | error = SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT; break; |
michael@0 | 3376 | case certificate_unobtainable: |
michael@0 | 3377 | error = SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT; break; |
michael@0 | 3378 | case unrecognized_name: |
michael@0 | 3379 | error = SSL_ERROR_UNRECOGNIZED_NAME_ALERT; break; |
michael@0 | 3380 | case bad_certificate_status_response: |
michael@0 | 3381 | error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT; break; |
michael@0 | 3382 | case bad_certificate_hash_value: |
michael@0 | 3383 | error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT; break; |
michael@0 | 3384 | default: error = SSL_ERROR_RX_UNKNOWN_ALERT; break; |
michael@0 | 3385 | } |
michael@0 | 3386 | if (level == alert_fatal) { |
michael@0 | 3387 | if (!ss->opt.noCache) { |
michael@0 | 3388 | if (ss->sec.uncache) |
michael@0 | 3389 | ss->sec.uncache(ss->sec.ci.sid); |
michael@0 | 3390 | } |
michael@0 | 3391 | if ((ss->ssl3.hs.ws == wait_server_hello) && |
michael@0 | 3392 | (desc == handshake_failure)) { |
michael@0 | 3393 | /* XXX This is a hack. We're assuming that any handshake failure |
michael@0 | 3394 | * XXX on the client hello is a failure to match ciphers. |
michael@0 | 3395 | */ |
michael@0 | 3396 | error = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 3397 | } |
michael@0 | 3398 | PORT_SetError(error); |
michael@0 | 3399 | return SECFailure; |
michael@0 | 3400 | } |
michael@0 | 3401 | if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) { |
michael@0 | 3402 | /* I'm a server. I've requested a client cert. He hasn't got one. */ |
michael@0 | 3403 | SECStatus rv; |
michael@0 | 3404 | |
michael@0 | 3405 | PORT_Assert(ss->sec.isServer); |
michael@0 | 3406 | ss->ssl3.hs.ws = wait_client_key; |
michael@0 | 3407 | rv = ssl3_HandleNoCertificate(ss); |
michael@0 | 3408 | return rv; |
michael@0 | 3409 | } |
michael@0 | 3410 | return SECSuccess; |
michael@0 | 3411 | } |
michael@0 | 3412 | |
michael@0 | 3413 | /* |
michael@0 | 3414 | * Change Cipher Specs |
michael@0 | 3415 | * Called from ssl3_HandleServerHelloDone, |
michael@0 | 3416 | * ssl3_HandleClientHello, |
michael@0 | 3417 | * and ssl3_HandleFinished |
michael@0 | 3418 | * |
michael@0 | 3419 | * Acquires and releases spec write lock, to protect switching the current |
michael@0 | 3420 | * and pending write spec pointers. |
michael@0 | 3421 | */ |
michael@0 | 3422 | |
michael@0 | 3423 | static SECStatus |
michael@0 | 3424 | ssl3_SendChangeCipherSpecs(sslSocket *ss) |
michael@0 | 3425 | { |
michael@0 | 3426 | PRUint8 change = change_cipher_spec_choice; |
michael@0 | 3427 | ssl3CipherSpec * pwSpec; |
michael@0 | 3428 | SECStatus rv; |
michael@0 | 3429 | PRInt32 sent; |
michael@0 | 3430 | |
michael@0 | 3431 | SSL_TRC(3, ("%d: SSL3[%d]: send change_cipher_spec record", |
michael@0 | 3432 | SSL_GETPID(), ss->fd)); |
michael@0 | 3433 | |
michael@0 | 3434 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 3435 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 3436 | |
michael@0 | 3437 | rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); |
michael@0 | 3438 | if (rv != SECSuccess) { |
michael@0 | 3439 | return rv; /* error code set by ssl3_FlushHandshake */ |
michael@0 | 3440 | } |
michael@0 | 3441 | if (!IS_DTLS(ss)) { |
michael@0 | 3442 | sent = ssl3_SendRecord(ss, 0, content_change_cipher_spec, &change, 1, |
michael@0 | 3443 | ssl_SEND_FLAG_FORCE_INTO_BUFFER); |
michael@0 | 3444 | if (sent < 0) { |
michael@0 | 3445 | return (SECStatus)sent; /* error code set by ssl3_SendRecord */ |
michael@0 | 3446 | } |
michael@0 | 3447 | } else { |
michael@0 | 3448 | rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1); |
michael@0 | 3449 | if (rv != SECSuccess) { |
michael@0 | 3450 | return rv; |
michael@0 | 3451 | } |
michael@0 | 3452 | } |
michael@0 | 3453 | |
michael@0 | 3454 | /* swap the pending and current write specs. */ |
michael@0 | 3455 | ssl_GetSpecWriteLock(ss); /**************************************/ |
michael@0 | 3456 | pwSpec = ss->ssl3.pwSpec; |
michael@0 | 3457 | |
michael@0 | 3458 | ss->ssl3.pwSpec = ss->ssl3.cwSpec; |
michael@0 | 3459 | ss->ssl3.cwSpec = pwSpec; |
michael@0 | 3460 | |
michael@0 | 3461 | SSL_TRC(3, ("%d: SSL3[%d] Set Current Write Cipher Suite to Pending", |
michael@0 | 3462 | SSL_GETPID(), ss->fd )); |
michael@0 | 3463 | |
michael@0 | 3464 | /* We need to free up the contexts, keys and certs ! */ |
michael@0 | 3465 | /* If we are really through with the old cipher spec |
michael@0 | 3466 | * (Both the read and write sides have changed) destroy it. |
michael@0 | 3467 | */ |
michael@0 | 3468 | if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { |
michael@0 | 3469 | if (!IS_DTLS(ss)) { |
michael@0 | 3470 | ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE/*freeSrvName*/); |
michael@0 | 3471 | } else { |
michael@0 | 3472 | /* With DTLS, we need to set a holddown timer in case the final |
michael@0 | 3473 | * message got lost */ |
michael@0 | 3474 | ss->ssl3.hs.rtTimeoutMs = DTLS_FINISHED_TIMER_MS; |
michael@0 | 3475 | dtls_StartTimer(ss, dtls_FinishedTimerCb); |
michael@0 | 3476 | } |
michael@0 | 3477 | } |
michael@0 | 3478 | ssl_ReleaseSpecWriteLock(ss); /**************************************/ |
michael@0 | 3479 | |
michael@0 | 3480 | return SECSuccess; |
michael@0 | 3481 | } |
michael@0 | 3482 | |
michael@0 | 3483 | /* Called from ssl3_HandleRecord. |
michael@0 | 3484 | ** Caller must hold both RecvBuf and Handshake locks. |
michael@0 | 3485 | * |
michael@0 | 3486 | * Acquires and releases spec write lock, to protect switching the current |
michael@0 | 3487 | * and pending write spec pointers. |
michael@0 | 3488 | */ |
michael@0 | 3489 | static SECStatus |
michael@0 | 3490 | ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) |
michael@0 | 3491 | { |
michael@0 | 3492 | ssl3CipherSpec * prSpec; |
michael@0 | 3493 | SSL3WaitState ws = ss->ssl3.hs.ws; |
michael@0 | 3494 | SSL3ChangeCipherSpecChoice change; |
michael@0 | 3495 | |
michael@0 | 3496 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 3497 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 3498 | |
michael@0 | 3499 | SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record", |
michael@0 | 3500 | SSL_GETPID(), ss->fd)); |
michael@0 | 3501 | |
michael@0 | 3502 | if (ws != wait_change_cipher) { |
michael@0 | 3503 | if (IS_DTLS(ss)) { |
michael@0 | 3504 | /* Ignore this because it's out of order. */ |
michael@0 | 3505 | SSL_TRC(3, ("%d: SSL3[%d]: discard out of order " |
michael@0 | 3506 | "DTLS change_cipher_spec", |
michael@0 | 3507 | SSL_GETPID(), ss->fd)); |
michael@0 | 3508 | buf->len = 0; |
michael@0 | 3509 | return SECSuccess; |
michael@0 | 3510 | } |
michael@0 | 3511 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 3512 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER); |
michael@0 | 3513 | return SECFailure; |
michael@0 | 3514 | } |
michael@0 | 3515 | |
michael@0 | 3516 | if(buf->len != 1) { |
michael@0 | 3517 | (void)ssl3_DecodeError(ss); |
michael@0 | 3518 | PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
michael@0 | 3519 | return SECFailure; |
michael@0 | 3520 | } |
michael@0 | 3521 | change = (SSL3ChangeCipherSpecChoice)buf->buf[0]; |
michael@0 | 3522 | if (change != change_cipher_spec_choice) { |
michael@0 | 3523 | /* illegal_parameter is correct here for both SSL3 and TLS. */ |
michael@0 | 3524 | (void)ssl3_IllegalParameter(ss); |
michael@0 | 3525 | PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
michael@0 | 3526 | return SECFailure; |
michael@0 | 3527 | } |
michael@0 | 3528 | buf->len = 0; |
michael@0 | 3529 | |
michael@0 | 3530 | /* Swap the pending and current read specs. */ |
michael@0 | 3531 | ssl_GetSpecWriteLock(ss); /*************************************/ |
michael@0 | 3532 | prSpec = ss->ssl3.prSpec; |
michael@0 | 3533 | |
michael@0 | 3534 | ss->ssl3.prSpec = ss->ssl3.crSpec; |
michael@0 | 3535 | ss->ssl3.crSpec = prSpec; |
michael@0 | 3536 | ss->ssl3.hs.ws = wait_finished; |
michael@0 | 3537 | |
michael@0 | 3538 | SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending", |
michael@0 | 3539 | SSL_GETPID(), ss->fd )); |
michael@0 | 3540 | |
michael@0 | 3541 | /* If we are really through with the old cipher prSpec |
michael@0 | 3542 | * (Both the read and write sides have changed) destroy it. |
michael@0 | 3543 | */ |
michael@0 | 3544 | if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { |
michael@0 | 3545 | ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE/*freeSrvName*/); |
michael@0 | 3546 | } |
michael@0 | 3547 | ssl_ReleaseSpecWriteLock(ss); /*************************************/ |
michael@0 | 3548 | return SECSuccess; |
michael@0 | 3549 | } |
michael@0 | 3550 | |
michael@0 | 3551 | /* This method uses PKCS11 to derive the MS from the PMS, where PMS |
michael@0 | 3552 | ** is a PKCS11 symkey. This is used in all cases except the |
michael@0 | 3553 | ** "triple bypass" with RSA key exchange. |
michael@0 | 3554 | ** Called from ssl3_InitPendingCipherSpec. prSpec is pwSpec. |
michael@0 | 3555 | */ |
michael@0 | 3556 | static SECStatus |
michael@0 | 3557 | ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) |
michael@0 | 3558 | { |
michael@0 | 3559 | ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; |
michael@0 | 3560 | const ssl3KEADef *kea_def= ss->ssl3.hs.kea_def; |
michael@0 | 3561 | unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; |
michael@0 | 3562 | unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; |
michael@0 | 3563 | PRBool isTLS = (PRBool)(kea_def->tls_keygen || |
michael@0 | 3564 | (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); |
michael@0 | 3565 | PRBool isTLS12= |
michael@0 | 3566 | (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 3567 | /* |
michael@0 | 3568 | * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH |
michael@0 | 3569 | * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size |
michael@0 | 3570 | * data into a 48-byte value. |
michael@0 | 3571 | */ |
michael@0 | 3572 | PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || |
michael@0 | 3573 | (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); |
michael@0 | 3574 | SECStatus rv = SECFailure; |
michael@0 | 3575 | CK_MECHANISM_TYPE master_derive; |
michael@0 | 3576 | CK_MECHANISM_TYPE key_derive; |
michael@0 | 3577 | SECItem params; |
michael@0 | 3578 | CK_FLAGS keyFlags; |
michael@0 | 3579 | CK_VERSION pms_version; |
michael@0 | 3580 | CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params; |
michael@0 | 3581 | |
michael@0 | 3582 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 3583 | PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); |
michael@0 | 3584 | PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); |
michael@0 | 3585 | if (isTLS12) { |
michael@0 | 3586 | if(isDH) master_derive = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256; |
michael@0 | 3587 | else master_derive = CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256; |
michael@0 | 3588 | key_derive = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256; |
michael@0 | 3589 | keyFlags = CKF_SIGN | CKF_VERIFY; |
michael@0 | 3590 | } else if (isTLS) { |
michael@0 | 3591 | if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH; |
michael@0 | 3592 | else master_derive = CKM_TLS_MASTER_KEY_DERIVE; |
michael@0 | 3593 | key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; |
michael@0 | 3594 | keyFlags = CKF_SIGN | CKF_VERIFY; |
michael@0 | 3595 | } else { |
michael@0 | 3596 | if (isDH) master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH; |
michael@0 | 3597 | else master_derive = CKM_SSL3_MASTER_KEY_DERIVE; |
michael@0 | 3598 | key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; |
michael@0 | 3599 | keyFlags = 0; |
michael@0 | 3600 | } |
michael@0 | 3601 | |
michael@0 | 3602 | if (pms || !pwSpec->master_secret) { |
michael@0 | 3603 | if (isDH) { |
michael@0 | 3604 | master_params.pVersion = NULL; |
michael@0 | 3605 | } else { |
michael@0 | 3606 | master_params.pVersion = &pms_version; |
michael@0 | 3607 | } |
michael@0 | 3608 | master_params.RandomInfo.pClientRandom = cr; |
michael@0 | 3609 | master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; |
michael@0 | 3610 | master_params.RandomInfo.pServerRandom = sr; |
michael@0 | 3611 | master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; |
michael@0 | 3612 | |
michael@0 | 3613 | params.data = (unsigned char *) &master_params; |
michael@0 | 3614 | params.len = sizeof master_params; |
michael@0 | 3615 | } |
michael@0 | 3616 | |
michael@0 | 3617 | if (pms != NULL) { |
michael@0 | 3618 | #if defined(TRACE) |
michael@0 | 3619 | if (ssl_trace >= 100) { |
michael@0 | 3620 | SECStatus extractRV = PK11_ExtractKeyValue(pms); |
michael@0 | 3621 | if (extractRV == SECSuccess) { |
michael@0 | 3622 | SECItem * keyData = PK11_GetKeyData(pms); |
michael@0 | 3623 | if (keyData && keyData->data && keyData->len) { |
michael@0 | 3624 | ssl_PrintBuf(ss, "Pre-Master Secret", |
michael@0 | 3625 | keyData->data, keyData->len); |
michael@0 | 3626 | } |
michael@0 | 3627 | } |
michael@0 | 3628 | } |
michael@0 | 3629 | #endif |
michael@0 | 3630 | pwSpec->master_secret = PK11_DeriveWithFlags(pms, master_derive, |
michael@0 | 3631 | ¶ms, key_derive, CKA_DERIVE, 0, keyFlags); |
michael@0 | 3632 | if (!isDH && pwSpec->master_secret && ss->opt.detectRollBack) { |
michael@0 | 3633 | SSL3ProtocolVersion client_version; |
michael@0 | 3634 | client_version = pms_version.major << 8 | pms_version.minor; |
michael@0 | 3635 | |
michael@0 | 3636 | if (IS_DTLS(ss)) { |
michael@0 | 3637 | client_version = dtls_DTLSVersionToTLSVersion(client_version); |
michael@0 | 3638 | } |
michael@0 | 3639 | |
michael@0 | 3640 | if (client_version != ss->clientHelloVersion) { |
michael@0 | 3641 | /* Destroy it. Version roll-back detected. */ |
michael@0 | 3642 | PK11_FreeSymKey(pwSpec->master_secret); |
michael@0 | 3643 | pwSpec->master_secret = NULL; |
michael@0 | 3644 | } |
michael@0 | 3645 | } |
michael@0 | 3646 | if (pwSpec->master_secret == NULL) { |
michael@0 | 3647 | /* Generate a faux master secret in the same slot as the old one. */ |
michael@0 | 3648 | PK11SlotInfo * slot = PK11_GetSlotFromKey((PK11SymKey *)pms); |
michael@0 | 3649 | PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot); |
michael@0 | 3650 | |
michael@0 | 3651 | PK11_FreeSlot(slot); |
michael@0 | 3652 | if (fpms != NULL) { |
michael@0 | 3653 | pwSpec->master_secret = PK11_DeriveWithFlags(fpms, |
michael@0 | 3654 | master_derive, ¶ms, key_derive, |
michael@0 | 3655 | CKA_DERIVE, 0, keyFlags); |
michael@0 | 3656 | PK11_FreeSymKey(fpms); |
michael@0 | 3657 | } |
michael@0 | 3658 | } |
michael@0 | 3659 | } |
michael@0 | 3660 | if (pwSpec->master_secret == NULL) { |
michael@0 | 3661 | /* Generate a faux master secret from the internal slot. */ |
michael@0 | 3662 | PK11SlotInfo * slot = PK11_GetInternalSlot(); |
michael@0 | 3663 | PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot); |
michael@0 | 3664 | |
michael@0 | 3665 | PK11_FreeSlot(slot); |
michael@0 | 3666 | if (fpms != NULL) { |
michael@0 | 3667 | pwSpec->master_secret = PK11_DeriveWithFlags(fpms, |
michael@0 | 3668 | master_derive, ¶ms, key_derive, |
michael@0 | 3669 | CKA_DERIVE, 0, keyFlags); |
michael@0 | 3670 | if (pwSpec->master_secret == NULL) { |
michael@0 | 3671 | pwSpec->master_secret = fpms; /* use the fpms as the master. */ |
michael@0 | 3672 | fpms = NULL; |
michael@0 | 3673 | } |
michael@0 | 3674 | } |
michael@0 | 3675 | if (fpms) { |
michael@0 | 3676 | PK11_FreeSymKey(fpms); |
michael@0 | 3677 | } |
michael@0 | 3678 | } |
michael@0 | 3679 | if (pwSpec->master_secret == NULL) { |
michael@0 | 3680 | ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
michael@0 | 3681 | return rv; |
michael@0 | 3682 | } |
michael@0 | 3683 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 3684 | if (ss->opt.bypassPKCS11) { |
michael@0 | 3685 | SECItem * keydata; |
michael@0 | 3686 | /* In hope of doing a "double bypass", |
michael@0 | 3687 | * need to extract the master secret's value from the key object |
michael@0 | 3688 | * and store it raw in the sslSocket struct. |
michael@0 | 3689 | */ |
michael@0 | 3690 | rv = PK11_ExtractKeyValue(pwSpec->master_secret); |
michael@0 | 3691 | if (rv != SECSuccess) { |
michael@0 | 3692 | return rv; |
michael@0 | 3693 | } |
michael@0 | 3694 | /* This returns the address of the secItem inside the key struct, |
michael@0 | 3695 | * not a copy or a reference. So, there's no need to free it. |
michael@0 | 3696 | */ |
michael@0 | 3697 | keydata = PK11_GetKeyData(pwSpec->master_secret); |
michael@0 | 3698 | if (keydata && keydata->len <= sizeof pwSpec->raw_master_secret) { |
michael@0 | 3699 | memcpy(pwSpec->raw_master_secret, keydata->data, keydata->len); |
michael@0 | 3700 | pwSpec->msItem.data = pwSpec->raw_master_secret; |
michael@0 | 3701 | pwSpec->msItem.len = keydata->len; |
michael@0 | 3702 | } else { |
michael@0 | 3703 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 3704 | return SECFailure; |
michael@0 | 3705 | } |
michael@0 | 3706 | } |
michael@0 | 3707 | #endif |
michael@0 | 3708 | return SECSuccess; |
michael@0 | 3709 | } |
michael@0 | 3710 | |
michael@0 | 3711 | |
michael@0 | 3712 | /* |
michael@0 | 3713 | * Derive encryption and MAC Keys (and IVs) from master secret |
michael@0 | 3714 | * Sets a useful error code when returning SECFailure. |
michael@0 | 3715 | * |
michael@0 | 3716 | * Called only from ssl3_InitPendingCipherSpec(), |
michael@0 | 3717 | * which in turn is called from |
michael@0 | 3718 | * sendRSAClientKeyExchange (for Full handshake) |
michael@0 | 3719 | * sendDHClientKeyExchange (for Full handshake) |
michael@0 | 3720 | * ssl3_HandleClientKeyExchange (for Full handshake) |
michael@0 | 3721 | * ssl3_HandleServerHello (for session restart) |
michael@0 | 3722 | * ssl3_HandleClientHello (for session restart) |
michael@0 | 3723 | * Caller MUST hold the specWriteLock, and SSL3HandshakeLock. |
michael@0 | 3724 | * ssl3_InitPendingCipherSpec does that. |
michael@0 | 3725 | * |
michael@0 | 3726 | */ |
michael@0 | 3727 | static SECStatus |
michael@0 | 3728 | ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss) |
michael@0 | 3729 | { |
michael@0 | 3730 | ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; |
michael@0 | 3731 | const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; |
michael@0 | 3732 | unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; |
michael@0 | 3733 | unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; |
michael@0 | 3734 | PRBool isTLS = (PRBool)(kea_def->tls_keygen || |
michael@0 | 3735 | (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); |
michael@0 | 3736 | PRBool isTLS12= |
michael@0 | 3737 | (PRBool)(isTLS && pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 3738 | /* following variables used in PKCS11 path */ |
michael@0 | 3739 | const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; |
michael@0 | 3740 | PK11SlotInfo * slot = NULL; |
michael@0 | 3741 | PK11SymKey * symKey = NULL; |
michael@0 | 3742 | void * pwArg = ss->pkcs11PinArg; |
michael@0 | 3743 | int keySize; |
michael@0 | 3744 | CK_SSL3_KEY_MAT_PARAMS key_material_params; |
michael@0 | 3745 | CK_SSL3_KEY_MAT_OUT returnedKeys; |
michael@0 | 3746 | CK_MECHANISM_TYPE key_derive; |
michael@0 | 3747 | CK_MECHANISM_TYPE bulk_mechanism; |
michael@0 | 3748 | SSLCipherAlgorithm calg; |
michael@0 | 3749 | SECItem params; |
michael@0 | 3750 | PRBool skipKeysAndIVs = (PRBool)(cipher_def->calg == calg_null); |
michael@0 | 3751 | |
michael@0 | 3752 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 3753 | PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); |
michael@0 | 3754 | PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); |
michael@0 | 3755 | |
michael@0 | 3756 | if (!pwSpec->master_secret) { |
michael@0 | 3757 | PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
michael@0 | 3758 | return SECFailure; |
michael@0 | 3759 | } |
michael@0 | 3760 | /* |
michael@0 | 3761 | * generate the key material |
michael@0 | 3762 | */ |
michael@0 | 3763 | key_material_params.ulMacSizeInBits = pwSpec->mac_size * BPB; |
michael@0 | 3764 | key_material_params.ulKeySizeInBits = cipher_def->secret_key_size* BPB; |
michael@0 | 3765 | key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB; |
michael@0 | 3766 | if (cipher_def->type == type_block && |
michael@0 | 3767 | pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
michael@0 | 3768 | /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ |
michael@0 | 3769 | key_material_params.ulIVSizeInBits = 0; |
michael@0 | 3770 | memset(pwSpec->client.write_iv, 0, cipher_def->iv_size); |
michael@0 | 3771 | memset(pwSpec->server.write_iv, 0, cipher_def->iv_size); |
michael@0 | 3772 | } |
michael@0 | 3773 | |
michael@0 | 3774 | key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited); |
michael@0 | 3775 | |
michael@0 | 3776 | key_material_params.RandomInfo.pClientRandom = cr; |
michael@0 | 3777 | key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH; |
michael@0 | 3778 | key_material_params.RandomInfo.pServerRandom = sr; |
michael@0 | 3779 | key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; |
michael@0 | 3780 | key_material_params.pReturnedKeyMaterial = &returnedKeys; |
michael@0 | 3781 | |
michael@0 | 3782 | returnedKeys.pIVClient = pwSpec->client.write_iv; |
michael@0 | 3783 | returnedKeys.pIVServer = pwSpec->server.write_iv; |
michael@0 | 3784 | keySize = cipher_def->key_size; |
michael@0 | 3785 | |
michael@0 | 3786 | if (skipKeysAndIVs) { |
michael@0 | 3787 | keySize = 0; |
michael@0 | 3788 | key_material_params.ulKeySizeInBits = 0; |
michael@0 | 3789 | key_material_params.ulIVSizeInBits = 0; |
michael@0 | 3790 | returnedKeys.pIVClient = NULL; |
michael@0 | 3791 | returnedKeys.pIVServer = NULL; |
michael@0 | 3792 | } |
michael@0 | 3793 | |
michael@0 | 3794 | calg = cipher_def->calg; |
michael@0 | 3795 | PORT_Assert( alg2Mech[calg].calg == calg); |
michael@0 | 3796 | bulk_mechanism = alg2Mech[calg].cmech; |
michael@0 | 3797 | |
michael@0 | 3798 | params.data = (unsigned char *)&key_material_params; |
michael@0 | 3799 | params.len = sizeof(key_material_params); |
michael@0 | 3800 | |
michael@0 | 3801 | if (isTLS12) { |
michael@0 | 3802 | key_derive = CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256; |
michael@0 | 3803 | } else if (isTLS) { |
michael@0 | 3804 | key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; |
michael@0 | 3805 | } else { |
michael@0 | 3806 | key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; |
michael@0 | 3807 | } |
michael@0 | 3808 | |
michael@0 | 3809 | /* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and |
michael@0 | 3810 | * DERIVE by DEFAULT */ |
michael@0 | 3811 | symKey = PK11_Derive(pwSpec->master_secret, key_derive, ¶ms, |
michael@0 | 3812 | bulk_mechanism, CKA_ENCRYPT, keySize); |
michael@0 | 3813 | if (!symKey) { |
michael@0 | 3814 | ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
michael@0 | 3815 | return SECFailure; |
michael@0 | 3816 | } |
michael@0 | 3817 | /* we really should use the actual mac'ing mechanism here, but we |
michael@0 | 3818 | * don't because these types are used to map keytype anyway and both |
michael@0 | 3819 | * mac's map to the same keytype. |
michael@0 | 3820 | */ |
michael@0 | 3821 | slot = PK11_GetSlotFromKey(symKey); |
michael@0 | 3822 | |
michael@0 | 3823 | PK11_FreeSlot(slot); /* slot is held until the key is freed */ |
michael@0 | 3824 | pwSpec->client.write_mac_key = |
michael@0 | 3825 | PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, |
michael@0 | 3826 | CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg); |
michael@0 | 3827 | if (pwSpec->client.write_mac_key == NULL ) { |
michael@0 | 3828 | goto loser; /* loser sets err */ |
michael@0 | 3829 | } |
michael@0 | 3830 | pwSpec->server.write_mac_key = |
michael@0 | 3831 | PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, |
michael@0 | 3832 | CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg); |
michael@0 | 3833 | if (pwSpec->server.write_mac_key == NULL ) { |
michael@0 | 3834 | goto loser; /* loser sets err */ |
michael@0 | 3835 | } |
michael@0 | 3836 | if (!skipKeysAndIVs) { |
michael@0 | 3837 | pwSpec->client.write_key = |
michael@0 | 3838 | PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, |
michael@0 | 3839 | bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg); |
michael@0 | 3840 | if (pwSpec->client.write_key == NULL ) { |
michael@0 | 3841 | goto loser; /* loser sets err */ |
michael@0 | 3842 | } |
michael@0 | 3843 | pwSpec->server.write_key = |
michael@0 | 3844 | PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, |
michael@0 | 3845 | bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg); |
michael@0 | 3846 | if (pwSpec->server.write_key == NULL ) { |
michael@0 | 3847 | goto loser; /* loser sets err */ |
michael@0 | 3848 | } |
michael@0 | 3849 | } |
michael@0 | 3850 | PK11_FreeSymKey(symKey); |
michael@0 | 3851 | return SECSuccess; |
michael@0 | 3852 | |
michael@0 | 3853 | |
michael@0 | 3854 | loser: |
michael@0 | 3855 | if (symKey) PK11_FreeSymKey(symKey); |
michael@0 | 3856 | ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
michael@0 | 3857 | return SECFailure; |
michael@0 | 3858 | } |
michael@0 | 3859 | |
michael@0 | 3860 | /* ssl3_InitHandshakeHashes creates handshake hash contexts and hashes in |
michael@0 | 3861 | * buffered messages in ss->ssl3.hs.messages. */ |
michael@0 | 3862 | static SECStatus |
michael@0 | 3863 | ssl3_InitHandshakeHashes(sslSocket *ss) |
michael@0 | 3864 | { |
michael@0 | 3865 | SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); |
michael@0 | 3866 | |
michael@0 | 3867 | PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown); |
michael@0 | 3868 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 3869 | if (ss->opt.bypassPKCS11) { |
michael@0 | 3870 | PORT_Assert(!ss->ssl3.hs.sha_obj && !ss->ssl3.hs.sha_clone); |
michael@0 | 3871 | if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 3872 | /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
michael@0 | 3873 | * then this will need to be updated. */ |
michael@0 | 3874 | ss->ssl3.hs.sha_obj = HASH_GetRawHashObject(HASH_AlgSHA256); |
michael@0 | 3875 | if (!ss->ssl3.hs.sha_obj) { |
michael@0 | 3876 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 3877 | return SECFailure; |
michael@0 | 3878 | } |
michael@0 | 3879 | ss->ssl3.hs.sha_clone = (void (*)(void *, void *))SHA256_Clone; |
michael@0 | 3880 | ss->ssl3.hs.hashType = handshake_hash_single; |
michael@0 | 3881 | ss->ssl3.hs.sha_obj->begin(ss->ssl3.hs.sha_cx); |
michael@0 | 3882 | } else { |
michael@0 | 3883 | ss->ssl3.hs.hashType = handshake_hash_combo; |
michael@0 | 3884 | MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); |
michael@0 | 3885 | SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); |
michael@0 | 3886 | } |
michael@0 | 3887 | } else |
michael@0 | 3888 | #endif |
michael@0 | 3889 | { |
michael@0 | 3890 | PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha); |
michael@0 | 3891 | /* |
michael@0 | 3892 | * note: We should probably lookup an SSL3 slot for these |
michael@0 | 3893 | * handshake hashes in hopes that we wind up with the same slots |
michael@0 | 3894 | * that the master secret will wind up in ... |
michael@0 | 3895 | */ |
michael@0 | 3896 | if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 3897 | /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
michael@0 | 3898 | * then this will need to be updated. */ |
michael@0 | 3899 | ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA256); |
michael@0 | 3900 | if (ss->ssl3.hs.sha == NULL) { |
michael@0 | 3901 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 3902 | return SECFailure; |
michael@0 | 3903 | } |
michael@0 | 3904 | ss->ssl3.hs.hashType = handshake_hash_single; |
michael@0 | 3905 | |
michael@0 | 3906 | if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { |
michael@0 | 3907 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 3908 | return SECFailure; |
michael@0 | 3909 | } |
michael@0 | 3910 | |
michael@0 | 3911 | /* Create a backup SHA-1 hash for a potential client auth |
michael@0 | 3912 | * signature. |
michael@0 | 3913 | * |
michael@0 | 3914 | * In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the |
michael@0 | 3915 | * handshake hash function (SHA-256). If the server or the client |
michael@0 | 3916 | * does not support SHA-256 as a signature hash, we can either |
michael@0 | 3917 | * maintain a backup SHA-1 handshake hash or buffer all handshake |
michael@0 | 3918 | * messages. |
michael@0 | 3919 | */ |
michael@0 | 3920 | if (!ss->sec.isServer) { |
michael@0 | 3921 | ss->ssl3.hs.backupHash = PK11_CreateDigestContext(SEC_OID_SHA1); |
michael@0 | 3922 | if (ss->ssl3.hs.backupHash == NULL) { |
michael@0 | 3923 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 3924 | return SECFailure; |
michael@0 | 3925 | } |
michael@0 | 3926 | |
michael@0 | 3927 | if (PK11_DigestBegin(ss->ssl3.hs.backupHash) != SECSuccess) { |
michael@0 | 3928 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 3929 | return SECFailure; |
michael@0 | 3930 | } |
michael@0 | 3931 | } |
michael@0 | 3932 | } else { |
michael@0 | 3933 | /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or |
michael@0 | 3934 | * created successfully. */ |
michael@0 | 3935 | ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5); |
michael@0 | 3936 | if (ss->ssl3.hs.md5 == NULL) { |
michael@0 | 3937 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 3938 | return SECFailure; |
michael@0 | 3939 | } |
michael@0 | 3940 | ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); |
michael@0 | 3941 | if (ss->ssl3.hs.sha == NULL) { |
michael@0 | 3942 | PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); |
michael@0 | 3943 | ss->ssl3.hs.md5 = NULL; |
michael@0 | 3944 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 3945 | return SECFailure; |
michael@0 | 3946 | } |
michael@0 | 3947 | ss->ssl3.hs.hashType = handshake_hash_combo; |
michael@0 | 3948 | |
michael@0 | 3949 | if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) { |
michael@0 | 3950 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 3951 | return SECFailure; |
michael@0 | 3952 | } |
michael@0 | 3953 | if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { |
michael@0 | 3954 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 3955 | return SECFailure; |
michael@0 | 3956 | } |
michael@0 | 3957 | } |
michael@0 | 3958 | } |
michael@0 | 3959 | |
michael@0 | 3960 | if (ss->ssl3.hs.messages.len > 0) { |
michael@0 | 3961 | if (ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf, |
michael@0 | 3962 | ss->ssl3.hs.messages.len) != |
michael@0 | 3963 | SECSuccess) { |
michael@0 | 3964 | return SECFailure; |
michael@0 | 3965 | } |
michael@0 | 3966 | PORT_Free(ss->ssl3.hs.messages.buf); |
michael@0 | 3967 | ss->ssl3.hs.messages.buf = NULL; |
michael@0 | 3968 | ss->ssl3.hs.messages.len = 0; |
michael@0 | 3969 | ss->ssl3.hs.messages.space = 0; |
michael@0 | 3970 | } |
michael@0 | 3971 | |
michael@0 | 3972 | return SECSuccess; |
michael@0 | 3973 | } |
michael@0 | 3974 | |
michael@0 | 3975 | static SECStatus |
michael@0 | 3976 | ssl3_RestartHandshakeHashes(sslSocket *ss) |
michael@0 | 3977 | { |
michael@0 | 3978 | SECStatus rv = SECSuccess; |
michael@0 | 3979 | |
michael@0 | 3980 | SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", |
michael@0 | 3981 | SSL_GETPID(), ss->fd )); |
michael@0 | 3982 | ss->ssl3.hs.hashType = handshake_hash_unknown; |
michael@0 | 3983 | ss->ssl3.hs.messages.len = 0; |
michael@0 | 3984 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 3985 | ss->ssl3.hs.sha_obj = NULL; |
michael@0 | 3986 | ss->ssl3.hs.sha_clone = NULL; |
michael@0 | 3987 | #endif |
michael@0 | 3988 | if (ss->ssl3.hs.md5) { |
michael@0 | 3989 | PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE); |
michael@0 | 3990 | ss->ssl3.hs.md5 = NULL; |
michael@0 | 3991 | } |
michael@0 | 3992 | if (ss->ssl3.hs.sha) { |
michael@0 | 3993 | PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); |
michael@0 | 3994 | ss->ssl3.hs.sha = NULL; |
michael@0 | 3995 | } |
michael@0 | 3996 | return rv; |
michael@0 | 3997 | } |
michael@0 | 3998 | |
michael@0 | 3999 | /* |
michael@0 | 4000 | * Handshake messages |
michael@0 | 4001 | */ |
michael@0 | 4002 | /* Called from ssl3_InitHandshakeHashes() |
michael@0 | 4003 | ** ssl3_AppendHandshake() |
michael@0 | 4004 | ** ssl3_StartHandshakeHash() |
michael@0 | 4005 | ** ssl3_HandleV2ClientHello() |
michael@0 | 4006 | ** ssl3_HandleHandshakeMessage() |
michael@0 | 4007 | ** Caller must hold the ssl3Handshake lock. |
michael@0 | 4008 | */ |
michael@0 | 4009 | static SECStatus |
michael@0 | 4010 | ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, |
michael@0 | 4011 | unsigned int l) |
michael@0 | 4012 | { |
michael@0 | 4013 | SECStatus rv = SECSuccess; |
michael@0 | 4014 | |
michael@0 | 4015 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 4016 | |
michael@0 | 4017 | /* We need to buffer the handshake messages until we have established |
michael@0 | 4018 | * which handshake hash function to use. */ |
michael@0 | 4019 | if (ss->ssl3.hs.hashType == handshake_hash_unknown) { |
michael@0 | 4020 | return sslBuffer_Append(&ss->ssl3.hs.messages, b, l); |
michael@0 | 4021 | } |
michael@0 | 4022 | |
michael@0 | 4023 | PRINT_BUF(90, (NULL, "handshake hash input:", b, l)); |
michael@0 | 4024 | |
michael@0 | 4025 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 4026 | if (ss->opt.bypassPKCS11) { |
michael@0 | 4027 | if (ss->ssl3.hs.hashType == handshake_hash_single) { |
michael@0 | 4028 | ss->ssl3.hs.sha_obj->update(ss->ssl3.hs.sha_cx, b, l); |
michael@0 | 4029 | } else { |
michael@0 | 4030 | MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); |
michael@0 | 4031 | SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); |
michael@0 | 4032 | } |
michael@0 | 4033 | return rv; |
michael@0 | 4034 | } |
michael@0 | 4035 | #endif |
michael@0 | 4036 | if (ss->ssl3.hs.hashType == handshake_hash_single) { |
michael@0 | 4037 | rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); |
michael@0 | 4038 | if (rv != SECSuccess) { |
michael@0 | 4039 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 4040 | return rv; |
michael@0 | 4041 | } |
michael@0 | 4042 | if (ss->ssl3.hs.backupHash) { |
michael@0 | 4043 | rv = PK11_DigestOp(ss->ssl3.hs.backupHash, b, l); |
michael@0 | 4044 | if (rv != SECSuccess) { |
michael@0 | 4045 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4046 | return rv; |
michael@0 | 4047 | } |
michael@0 | 4048 | } |
michael@0 | 4049 | } else { |
michael@0 | 4050 | rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); |
michael@0 | 4051 | if (rv != SECSuccess) { |
michael@0 | 4052 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 4053 | return rv; |
michael@0 | 4054 | } |
michael@0 | 4055 | rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); |
michael@0 | 4056 | if (rv != SECSuccess) { |
michael@0 | 4057 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4058 | return rv; |
michael@0 | 4059 | } |
michael@0 | 4060 | } |
michael@0 | 4061 | return rv; |
michael@0 | 4062 | } |
michael@0 | 4063 | |
michael@0 | 4064 | /************************************************************************** |
michael@0 | 4065 | * Append Handshake functions. |
michael@0 | 4066 | * All these functions set appropriate error codes. |
michael@0 | 4067 | * Most rely on ssl3_AppendHandshake to set the error code. |
michael@0 | 4068 | **************************************************************************/ |
michael@0 | 4069 | SECStatus |
michael@0 | 4070 | ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes) |
michael@0 | 4071 | { |
michael@0 | 4072 | unsigned char * src = (unsigned char *)void_src; |
michael@0 | 4073 | int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len; |
michael@0 | 4074 | SECStatus rv; |
michael@0 | 4075 | |
michael@0 | 4076 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); /* protects sendBuf. */ |
michael@0 | 4077 | |
michael@0 | 4078 | if (!bytes) |
michael@0 | 4079 | return SECSuccess; |
michael@0 | 4080 | if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) { |
michael@0 | 4081 | rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH, |
michael@0 | 4082 | PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes))); |
michael@0 | 4083 | if (rv != SECSuccess) |
michael@0 | 4084 | return rv; /* sslBuffer_Grow has set a memory error code. */ |
michael@0 | 4085 | room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len; |
michael@0 | 4086 | } |
michael@0 | 4087 | |
michael@0 | 4088 | PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char*)void_src, bytes)); |
michael@0 | 4089 | rv = ssl3_UpdateHandshakeHashes(ss, src, bytes); |
michael@0 | 4090 | if (rv != SECSuccess) |
michael@0 | 4091 | return rv; /* error code set by ssl3_UpdateHandshakeHashes */ |
michael@0 | 4092 | |
michael@0 | 4093 | while (bytes > room) { |
michael@0 | 4094 | if (room > 0) |
michael@0 | 4095 | PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, |
michael@0 | 4096 | room); |
michael@0 | 4097 | ss->sec.ci.sendBuf.len += room; |
michael@0 | 4098 | rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); |
michael@0 | 4099 | if (rv != SECSuccess) { |
michael@0 | 4100 | return rv; /* error code set by ssl3_FlushHandshake */ |
michael@0 | 4101 | } |
michael@0 | 4102 | bytes -= room; |
michael@0 | 4103 | src += room; |
michael@0 | 4104 | room = ss->sec.ci.sendBuf.space; |
michael@0 | 4105 | PORT_Assert(ss->sec.ci.sendBuf.len == 0); |
michael@0 | 4106 | } |
michael@0 | 4107 | PORT_Memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, src, bytes); |
michael@0 | 4108 | ss->sec.ci.sendBuf.len += bytes; |
michael@0 | 4109 | return SECSuccess; |
michael@0 | 4110 | } |
michael@0 | 4111 | |
michael@0 | 4112 | SECStatus |
michael@0 | 4113 | ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize) |
michael@0 | 4114 | { |
michael@0 | 4115 | SECStatus rv; |
michael@0 | 4116 | PRUint8 b[4]; |
michael@0 | 4117 | PRUint8 * p = b; |
michael@0 | 4118 | |
michael@0 | 4119 | switch (lenSize) { |
michael@0 | 4120 | case 4: |
michael@0 | 4121 | *p++ = (num >> 24) & 0xff; |
michael@0 | 4122 | case 3: |
michael@0 | 4123 | *p++ = (num >> 16) & 0xff; |
michael@0 | 4124 | case 2: |
michael@0 | 4125 | *p++ = (num >> 8) & 0xff; |
michael@0 | 4126 | case 1: |
michael@0 | 4127 | *p = num & 0xff; |
michael@0 | 4128 | } |
michael@0 | 4129 | SSL_TRC(60, ("%d: number:", SSL_GETPID())); |
michael@0 | 4130 | rv = ssl3_AppendHandshake(ss, &b[0], lenSize); |
michael@0 | 4131 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4132 | } |
michael@0 | 4133 | |
michael@0 | 4134 | SECStatus |
michael@0 | 4135 | ssl3_AppendHandshakeVariable( |
michael@0 | 4136 | sslSocket *ss, const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize) |
michael@0 | 4137 | { |
michael@0 | 4138 | SECStatus rv; |
michael@0 | 4139 | |
michael@0 | 4140 | PORT_Assert((bytes < (1<<8) && lenSize == 1) || |
michael@0 | 4141 | (bytes < (1L<<16) && lenSize == 2) || |
michael@0 | 4142 | (bytes < (1L<<24) && lenSize == 3)); |
michael@0 | 4143 | |
michael@0 | 4144 | SSL_TRC(60,("%d: append variable:", SSL_GETPID())); |
michael@0 | 4145 | rv = ssl3_AppendHandshakeNumber(ss, bytes, lenSize); |
michael@0 | 4146 | if (rv != SECSuccess) { |
michael@0 | 4147 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4148 | } |
michael@0 | 4149 | SSL_TRC(60, ("data:")); |
michael@0 | 4150 | rv = ssl3_AppendHandshake(ss, src, bytes); |
michael@0 | 4151 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4152 | } |
michael@0 | 4153 | |
michael@0 | 4154 | SECStatus |
michael@0 | 4155 | ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) |
michael@0 | 4156 | { |
michael@0 | 4157 | SECStatus rv; |
michael@0 | 4158 | |
michael@0 | 4159 | /* If we already have a message in place, we need to enqueue it. |
michael@0 | 4160 | * This empties the buffer. This is a convenient place to call |
michael@0 | 4161 | * dtls_StageHandshakeMessage to mark the message boundary. |
michael@0 | 4162 | */ |
michael@0 | 4163 | if (IS_DTLS(ss)) { |
michael@0 | 4164 | rv = dtls_StageHandshakeMessage(ss); |
michael@0 | 4165 | if (rv != SECSuccess) { |
michael@0 | 4166 | return rv; |
michael@0 | 4167 | } |
michael@0 | 4168 | } |
michael@0 | 4169 | |
michael@0 | 4170 | SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s", |
michael@0 | 4171 | SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t))); |
michael@0 | 4172 | |
michael@0 | 4173 | rv = ssl3_AppendHandshakeNumber(ss, t, 1); |
michael@0 | 4174 | if (rv != SECSuccess) { |
michael@0 | 4175 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4176 | } |
michael@0 | 4177 | rv = ssl3_AppendHandshakeNumber(ss, length, 3); |
michael@0 | 4178 | if (rv != SECSuccess) { |
michael@0 | 4179 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4180 | } |
michael@0 | 4181 | |
michael@0 | 4182 | if (IS_DTLS(ss)) { |
michael@0 | 4183 | /* Note that we make an unfragmented message here. We fragment in the |
michael@0 | 4184 | * transmission code, if necessary */ |
michael@0 | 4185 | rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.sendMessageSeq, 2); |
michael@0 | 4186 | if (rv != SECSuccess) { |
michael@0 | 4187 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4188 | } |
michael@0 | 4189 | ss->ssl3.hs.sendMessageSeq++; |
michael@0 | 4190 | |
michael@0 | 4191 | /* 0 is the fragment offset, because it's not fragmented yet */ |
michael@0 | 4192 | rv = ssl3_AppendHandshakeNumber(ss, 0, 3); |
michael@0 | 4193 | if (rv != SECSuccess) { |
michael@0 | 4194 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4195 | } |
michael@0 | 4196 | |
michael@0 | 4197 | /* Fragment length -- set to the packet length because not fragmented */ |
michael@0 | 4198 | rv = ssl3_AppendHandshakeNumber(ss, length, 3); |
michael@0 | 4199 | if (rv != SECSuccess) { |
michael@0 | 4200 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4201 | } |
michael@0 | 4202 | } |
michael@0 | 4203 | |
michael@0 | 4204 | return rv; /* error code set by AppendHandshake, if applicable. */ |
michael@0 | 4205 | } |
michael@0 | 4206 | |
michael@0 | 4207 | /* ssl3_AppendSignatureAndHashAlgorithm appends the serialisation of |
michael@0 | 4208 | * |sigAndHash| to the current handshake message. */ |
michael@0 | 4209 | SECStatus |
michael@0 | 4210 | ssl3_AppendSignatureAndHashAlgorithm( |
michael@0 | 4211 | sslSocket *ss, const SSL3SignatureAndHashAlgorithm* sigAndHash) |
michael@0 | 4212 | { |
michael@0 | 4213 | unsigned char serialized[2]; |
michael@0 | 4214 | |
michael@0 | 4215 | serialized[0] = ssl3_OIDToTLSHashAlgorithm(sigAndHash->hashAlg); |
michael@0 | 4216 | if (serialized[0] == 0) { |
michael@0 | 4217 | PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); |
michael@0 | 4218 | return SECFailure; |
michael@0 | 4219 | } |
michael@0 | 4220 | |
michael@0 | 4221 | serialized[1] = sigAndHash->sigAlg; |
michael@0 | 4222 | |
michael@0 | 4223 | return ssl3_AppendHandshake(ss, serialized, sizeof(serialized)); |
michael@0 | 4224 | } |
michael@0 | 4225 | |
michael@0 | 4226 | /************************************************************************** |
michael@0 | 4227 | * Consume Handshake functions. |
michael@0 | 4228 | * |
michael@0 | 4229 | * All data used in these functions is protected by two locks, |
michael@0 | 4230 | * the RecvBufLock and the SSL3HandshakeLock |
michael@0 | 4231 | **************************************************************************/ |
michael@0 | 4232 | |
michael@0 | 4233 | /* Read up the next "bytes" number of bytes from the (decrypted) input |
michael@0 | 4234 | * stream "b" (which is *length bytes long). Copy them into buffer "v". |
michael@0 | 4235 | * Reduces *length by bytes. Advances *b by bytes. |
michael@0 | 4236 | * |
michael@0 | 4237 | * If this function returns SECFailure, it has already sent an alert, |
michael@0 | 4238 | * and has set a generic error code. The caller should probably |
michael@0 | 4239 | * override the generic error code by setting another. |
michael@0 | 4240 | */ |
michael@0 | 4241 | SECStatus |
michael@0 | 4242 | ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b, |
michael@0 | 4243 | PRUint32 *length) |
michael@0 | 4244 | { |
michael@0 | 4245 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 4246 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 4247 | |
michael@0 | 4248 | if ((PRUint32)bytes > *length) { |
michael@0 | 4249 | return ssl3_DecodeError(ss); |
michael@0 | 4250 | } |
michael@0 | 4251 | PORT_Memcpy(v, *b, bytes); |
michael@0 | 4252 | PRINT_BUF(60, (ss, "consume bytes:", *b, bytes)); |
michael@0 | 4253 | *b += bytes; |
michael@0 | 4254 | *length -= bytes; |
michael@0 | 4255 | return SECSuccess; |
michael@0 | 4256 | } |
michael@0 | 4257 | |
michael@0 | 4258 | /* Read up the next "bytes" number of bytes from the (decrypted) input |
michael@0 | 4259 | * stream "b" (which is *length bytes long), and interpret them as an |
michael@0 | 4260 | * integer in network byte order. Returns the received value. |
michael@0 | 4261 | * Reduces *length by bytes. Advances *b by bytes. |
michael@0 | 4262 | * |
michael@0 | 4263 | * Returns SECFailure (-1) on failure. |
michael@0 | 4264 | * This value is indistinguishable from the equivalent received value. |
michael@0 | 4265 | * Only positive numbers are to be received this way. |
michael@0 | 4266 | * Thus, the largest value that may be sent this way is 0x7fffffff. |
michael@0 | 4267 | * On error, an alert has been sent, and a generic error code has been set. |
michael@0 | 4268 | */ |
michael@0 | 4269 | PRInt32 |
michael@0 | 4270 | ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b, |
michael@0 | 4271 | PRUint32 *length) |
michael@0 | 4272 | { |
michael@0 | 4273 | PRUint8 *buf = *b; |
michael@0 | 4274 | int i; |
michael@0 | 4275 | PRInt32 num = 0; |
michael@0 | 4276 | |
michael@0 | 4277 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 4278 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 4279 | PORT_Assert( bytes <= sizeof num); |
michael@0 | 4280 | |
michael@0 | 4281 | if ((PRUint32)bytes > *length) { |
michael@0 | 4282 | return ssl3_DecodeError(ss); |
michael@0 | 4283 | } |
michael@0 | 4284 | PRINT_BUF(60, (ss, "consume bytes:", *b, bytes)); |
michael@0 | 4285 | |
michael@0 | 4286 | for (i = 0; i < bytes; i++) |
michael@0 | 4287 | num = (num << 8) + buf[i]; |
michael@0 | 4288 | *b += bytes; |
michael@0 | 4289 | *length -= bytes; |
michael@0 | 4290 | return num; |
michael@0 | 4291 | } |
michael@0 | 4292 | |
michael@0 | 4293 | /* Read in two values from the incoming decrypted byte stream "b", which is |
michael@0 | 4294 | * *length bytes long. The first value is a number whose size is "bytes" |
michael@0 | 4295 | * bytes long. The second value is a byte-string whose size is the value |
michael@0 | 4296 | * of the first number received. The latter byte-string, and its length, |
michael@0 | 4297 | * is returned in the SECItem i. |
michael@0 | 4298 | * |
michael@0 | 4299 | * Returns SECFailure (-1) on failure. |
michael@0 | 4300 | * On error, an alert has been sent, and a generic error code has been set. |
michael@0 | 4301 | * |
michael@0 | 4302 | * RADICAL CHANGE for NSS 3.11. All callers of this function make copies |
michael@0 | 4303 | * of the data returned in the SECItem *i, so making a copy of it here |
michael@0 | 4304 | * is simply wasteful. So, This function now just sets SECItem *i to |
michael@0 | 4305 | * point to the values in the buffer **b. |
michael@0 | 4306 | */ |
michael@0 | 4307 | SECStatus |
michael@0 | 4308 | ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, |
michael@0 | 4309 | SSL3Opaque **b, PRUint32 *length) |
michael@0 | 4310 | { |
michael@0 | 4311 | PRInt32 count; |
michael@0 | 4312 | |
michael@0 | 4313 | PORT_Assert(bytes <= 3); |
michael@0 | 4314 | i->len = 0; |
michael@0 | 4315 | i->data = NULL; |
michael@0 | 4316 | count = ssl3_ConsumeHandshakeNumber(ss, bytes, b, length); |
michael@0 | 4317 | if (count < 0) { /* Can't test for SECSuccess here. */ |
michael@0 | 4318 | return SECFailure; |
michael@0 | 4319 | } |
michael@0 | 4320 | if (count > 0) { |
michael@0 | 4321 | if ((PRUint32)count > *length) { |
michael@0 | 4322 | return ssl3_DecodeError(ss); |
michael@0 | 4323 | } |
michael@0 | 4324 | i->data = *b; |
michael@0 | 4325 | i->len = count; |
michael@0 | 4326 | *b += count; |
michael@0 | 4327 | *length -= count; |
michael@0 | 4328 | } |
michael@0 | 4329 | return SECSuccess; |
michael@0 | 4330 | } |
michael@0 | 4331 | |
michael@0 | 4332 | /* tlsHashOIDMap contains the mapping between TLS hash identifiers and the |
michael@0 | 4333 | * SECOidTag used internally by NSS. */ |
michael@0 | 4334 | static const struct { |
michael@0 | 4335 | int tlsHash; |
michael@0 | 4336 | SECOidTag oid; |
michael@0 | 4337 | } tlsHashOIDMap[] = { |
michael@0 | 4338 | { tls_hash_md5, SEC_OID_MD5 }, |
michael@0 | 4339 | { tls_hash_sha1, SEC_OID_SHA1 }, |
michael@0 | 4340 | { tls_hash_sha224, SEC_OID_SHA224 }, |
michael@0 | 4341 | { tls_hash_sha256, SEC_OID_SHA256 }, |
michael@0 | 4342 | { tls_hash_sha384, SEC_OID_SHA384 }, |
michael@0 | 4343 | { tls_hash_sha512, SEC_OID_SHA512 } |
michael@0 | 4344 | }; |
michael@0 | 4345 | |
michael@0 | 4346 | /* ssl3_TLSHashAlgorithmToOID converts a TLS hash identifier into an OID value. |
michael@0 | 4347 | * If the hash is not recognised, SEC_OID_UNKNOWN is returned. |
michael@0 | 4348 | * |
michael@0 | 4349 | * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
michael@0 | 4350 | SECOidTag |
michael@0 | 4351 | ssl3_TLSHashAlgorithmToOID(int hashFunc) |
michael@0 | 4352 | { |
michael@0 | 4353 | unsigned int i; |
michael@0 | 4354 | |
michael@0 | 4355 | for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) { |
michael@0 | 4356 | if (hashFunc == tlsHashOIDMap[i].tlsHash) { |
michael@0 | 4357 | return tlsHashOIDMap[i].oid; |
michael@0 | 4358 | } |
michael@0 | 4359 | } |
michael@0 | 4360 | return SEC_OID_UNKNOWN; |
michael@0 | 4361 | } |
michael@0 | 4362 | |
michael@0 | 4363 | /* ssl3_OIDToTLSHashAlgorithm converts an OID to a TLS hash algorithm |
michael@0 | 4364 | * identifier. If the hash is not recognised, zero is returned. |
michael@0 | 4365 | * |
michael@0 | 4366 | * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
michael@0 | 4367 | static int |
michael@0 | 4368 | ssl3_OIDToTLSHashAlgorithm(SECOidTag oid) |
michael@0 | 4369 | { |
michael@0 | 4370 | unsigned int i; |
michael@0 | 4371 | |
michael@0 | 4372 | for (i = 0; i < PR_ARRAY_SIZE(tlsHashOIDMap); i++) { |
michael@0 | 4373 | if (oid == tlsHashOIDMap[i].oid) { |
michael@0 | 4374 | return tlsHashOIDMap[i].tlsHash; |
michael@0 | 4375 | } |
michael@0 | 4376 | } |
michael@0 | 4377 | return 0; |
michael@0 | 4378 | } |
michael@0 | 4379 | |
michael@0 | 4380 | /* ssl3_TLSSignatureAlgorithmForKeyType returns the TLS 1.2 signature algorithm |
michael@0 | 4381 | * identifier for a given KeyType. */ |
michael@0 | 4382 | static SECStatus |
michael@0 | 4383 | ssl3_TLSSignatureAlgorithmForKeyType(KeyType keyType, |
michael@0 | 4384 | TLSSignatureAlgorithm *out) |
michael@0 | 4385 | { |
michael@0 | 4386 | switch (keyType) { |
michael@0 | 4387 | case rsaKey: |
michael@0 | 4388 | *out = tls_sig_rsa; |
michael@0 | 4389 | return SECSuccess; |
michael@0 | 4390 | case dsaKey: |
michael@0 | 4391 | *out = tls_sig_dsa; |
michael@0 | 4392 | return SECSuccess; |
michael@0 | 4393 | case ecKey: |
michael@0 | 4394 | *out = tls_sig_ecdsa; |
michael@0 | 4395 | return SECSuccess; |
michael@0 | 4396 | default: |
michael@0 | 4397 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
michael@0 | 4398 | return SECFailure; |
michael@0 | 4399 | } |
michael@0 | 4400 | } |
michael@0 | 4401 | |
michael@0 | 4402 | /* ssl3_TLSSignatureAlgorithmForCertificate returns the TLS 1.2 signature |
michael@0 | 4403 | * algorithm identifier for the given certificate. */ |
michael@0 | 4404 | static SECStatus |
michael@0 | 4405 | ssl3_TLSSignatureAlgorithmForCertificate(CERTCertificate *cert, |
michael@0 | 4406 | TLSSignatureAlgorithm *out) |
michael@0 | 4407 | { |
michael@0 | 4408 | SECKEYPublicKey *key; |
michael@0 | 4409 | KeyType keyType; |
michael@0 | 4410 | |
michael@0 | 4411 | key = CERT_ExtractPublicKey(cert); |
michael@0 | 4412 | if (key == NULL) { |
michael@0 | 4413 | ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); |
michael@0 | 4414 | return SECFailure; |
michael@0 | 4415 | } |
michael@0 | 4416 | |
michael@0 | 4417 | keyType = key->keyType; |
michael@0 | 4418 | SECKEY_DestroyPublicKey(key); |
michael@0 | 4419 | return ssl3_TLSSignatureAlgorithmForKeyType(keyType, out); |
michael@0 | 4420 | } |
michael@0 | 4421 | |
michael@0 | 4422 | /* ssl3_CheckSignatureAndHashAlgorithmConsistency checks that the signature |
michael@0 | 4423 | * algorithm identifier in |sigAndHash| is consistent with the public key in |
michael@0 | 4424 | * |cert|. If so, SECSuccess is returned. Otherwise, PORT_SetError is called |
michael@0 | 4425 | * and SECFailure is returned. */ |
michael@0 | 4426 | SECStatus |
michael@0 | 4427 | ssl3_CheckSignatureAndHashAlgorithmConsistency( |
michael@0 | 4428 | const SSL3SignatureAndHashAlgorithm *sigAndHash, CERTCertificate* cert) |
michael@0 | 4429 | { |
michael@0 | 4430 | SECStatus rv; |
michael@0 | 4431 | TLSSignatureAlgorithm sigAlg; |
michael@0 | 4432 | |
michael@0 | 4433 | rv = ssl3_TLSSignatureAlgorithmForCertificate(cert, &sigAlg); |
michael@0 | 4434 | if (rv != SECSuccess) { |
michael@0 | 4435 | return rv; |
michael@0 | 4436 | } |
michael@0 | 4437 | if (sigAlg != sigAndHash->sigAlg) { |
michael@0 | 4438 | PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM); |
michael@0 | 4439 | return SECFailure; |
michael@0 | 4440 | } |
michael@0 | 4441 | return SECSuccess; |
michael@0 | 4442 | } |
michael@0 | 4443 | |
michael@0 | 4444 | /* ssl3_ConsumeSignatureAndHashAlgorithm reads a SignatureAndHashAlgorithm |
michael@0 | 4445 | * structure from |b| and puts the resulting value into |out|. |b| and |length| |
michael@0 | 4446 | * are updated accordingly. |
michael@0 | 4447 | * |
michael@0 | 4448 | * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
michael@0 | 4449 | SECStatus |
michael@0 | 4450 | ssl3_ConsumeSignatureAndHashAlgorithm(sslSocket *ss, |
michael@0 | 4451 | SSL3Opaque **b, |
michael@0 | 4452 | PRUint32 *length, |
michael@0 | 4453 | SSL3SignatureAndHashAlgorithm *out) |
michael@0 | 4454 | { |
michael@0 | 4455 | unsigned char bytes[2]; |
michael@0 | 4456 | SECStatus rv; |
michael@0 | 4457 | |
michael@0 | 4458 | rv = ssl3_ConsumeHandshake(ss, bytes, sizeof(bytes), b, length); |
michael@0 | 4459 | if (rv != SECSuccess) { |
michael@0 | 4460 | return rv; |
michael@0 | 4461 | } |
michael@0 | 4462 | |
michael@0 | 4463 | out->hashAlg = ssl3_TLSHashAlgorithmToOID(bytes[0]); |
michael@0 | 4464 | if (out->hashAlg == SEC_OID_UNKNOWN) { |
michael@0 | 4465 | PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); |
michael@0 | 4466 | return SECFailure; |
michael@0 | 4467 | } |
michael@0 | 4468 | |
michael@0 | 4469 | out->sigAlg = bytes[1]; |
michael@0 | 4470 | return SECSuccess; |
michael@0 | 4471 | } |
michael@0 | 4472 | |
michael@0 | 4473 | /************************************************************************** |
michael@0 | 4474 | * end of Consume Handshake functions. |
michael@0 | 4475 | **************************************************************************/ |
michael@0 | 4476 | |
michael@0 | 4477 | /* Extract the hashes of handshake messages to this point. |
michael@0 | 4478 | * Called from ssl3_SendCertificateVerify |
michael@0 | 4479 | * ssl3_SendFinished |
michael@0 | 4480 | * ssl3_HandleHandshakeMessage |
michael@0 | 4481 | * |
michael@0 | 4482 | * Caller must hold the SSL3HandshakeLock. |
michael@0 | 4483 | * Caller must hold a read or write lock on the Spec R/W lock. |
michael@0 | 4484 | * (There is presently no way to assert on a Read lock.) |
michael@0 | 4485 | */ |
michael@0 | 4486 | static SECStatus |
michael@0 | 4487 | ssl3_ComputeHandshakeHashes(sslSocket * ss, |
michael@0 | 4488 | ssl3CipherSpec *spec, /* uses ->master_secret */ |
michael@0 | 4489 | SSL3Hashes * hashes, /* output goes here. */ |
michael@0 | 4490 | PRUint32 sender) |
michael@0 | 4491 | { |
michael@0 | 4492 | SECStatus rv = SECSuccess; |
michael@0 | 4493 | PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 4494 | unsigned int outLength; |
michael@0 | 4495 | SSL3Opaque md5_inner[MAX_MAC_LENGTH]; |
michael@0 | 4496 | SSL3Opaque sha_inner[MAX_MAC_LENGTH]; |
michael@0 | 4497 | |
michael@0 | 4498 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 4499 | hashes->hashAlg = SEC_OID_UNKNOWN; |
michael@0 | 4500 | |
michael@0 | 4501 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 4502 | if (ss->opt.bypassPKCS11 && |
michael@0 | 4503 | ss->ssl3.hs.hashType == handshake_hash_single) { |
michael@0 | 4504 | /* compute them without PKCS11 */ |
michael@0 | 4505 | PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; |
michael@0 | 4506 | |
michael@0 | 4507 | if (!spec->msItem.data) { |
michael@0 | 4508 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); |
michael@0 | 4509 | return SECFailure; |
michael@0 | 4510 | } |
michael@0 | 4511 | |
michael@0 | 4512 | ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx); |
michael@0 | 4513 | ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len, |
michael@0 | 4514 | sizeof(hashes->u.raw)); |
michael@0 | 4515 | |
michael@0 | 4516 | PRINT_BUF(60, (NULL, "SHA-256: result", hashes->u.raw, hashes->len)); |
michael@0 | 4517 | |
michael@0 | 4518 | /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
michael@0 | 4519 | * then this will need to be updated. */ |
michael@0 | 4520 | hashes->hashAlg = SEC_OID_SHA256; |
michael@0 | 4521 | rv = SECSuccess; |
michael@0 | 4522 | } else if (ss->opt.bypassPKCS11) { |
michael@0 | 4523 | /* compute them without PKCS11 */ |
michael@0 | 4524 | PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; |
michael@0 | 4525 | PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; |
michael@0 | 4526 | |
michael@0 | 4527 | #define md5cx ((MD5Context *)md5_cx) |
michael@0 | 4528 | #define shacx ((SHA1Context *)sha_cx) |
michael@0 | 4529 | |
michael@0 | 4530 | if (!spec->msItem.data) { |
michael@0 | 4531 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); |
michael@0 | 4532 | return SECFailure; |
michael@0 | 4533 | } |
michael@0 | 4534 | |
michael@0 | 4535 | MD5_Clone (md5cx, (MD5Context *)ss->ssl3.hs.md5_cx); |
michael@0 | 4536 | SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx); |
michael@0 | 4537 | |
michael@0 | 4538 | if (!isTLS) { |
michael@0 | 4539 | /* compute hashes for SSL3. */ |
michael@0 | 4540 | unsigned char s[4]; |
michael@0 | 4541 | |
michael@0 | 4542 | s[0] = (unsigned char)(sender >> 24); |
michael@0 | 4543 | s[1] = (unsigned char)(sender >> 16); |
michael@0 | 4544 | s[2] = (unsigned char)(sender >> 8); |
michael@0 | 4545 | s[3] = (unsigned char)sender; |
michael@0 | 4546 | |
michael@0 | 4547 | if (sender != 0) { |
michael@0 | 4548 | MD5_Update(md5cx, s, 4); |
michael@0 | 4549 | PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4)); |
michael@0 | 4550 | } |
michael@0 | 4551 | |
michael@0 | 4552 | PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, |
michael@0 | 4553 | mac_defs[mac_md5].pad_size)); |
michael@0 | 4554 | |
michael@0 | 4555 | MD5_Update(md5cx, spec->msItem.data, spec->msItem.len); |
michael@0 | 4556 | MD5_Update(md5cx, mac_pad_1, mac_defs[mac_md5].pad_size); |
michael@0 | 4557 | MD5_End(md5cx, md5_inner, &outLength, MD5_LENGTH); |
michael@0 | 4558 | |
michael@0 | 4559 | PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength)); |
michael@0 | 4560 | |
michael@0 | 4561 | if (sender != 0) { |
michael@0 | 4562 | SHA1_Update(shacx, s, 4); |
michael@0 | 4563 | PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4)); |
michael@0 | 4564 | } |
michael@0 | 4565 | |
michael@0 | 4566 | PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, |
michael@0 | 4567 | mac_defs[mac_sha].pad_size)); |
michael@0 | 4568 | |
michael@0 | 4569 | SHA1_Update(shacx, spec->msItem.data, spec->msItem.len); |
michael@0 | 4570 | SHA1_Update(shacx, mac_pad_1, mac_defs[mac_sha].pad_size); |
michael@0 | 4571 | SHA1_End(shacx, sha_inner, &outLength, SHA1_LENGTH); |
michael@0 | 4572 | |
michael@0 | 4573 | PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength)); |
michael@0 | 4574 | PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, |
michael@0 | 4575 | mac_defs[mac_md5].pad_size)); |
michael@0 | 4576 | PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH)); |
michael@0 | 4577 | |
michael@0 | 4578 | MD5_Begin(md5cx); |
michael@0 | 4579 | MD5_Update(md5cx, spec->msItem.data, spec->msItem.len); |
michael@0 | 4580 | MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size); |
michael@0 | 4581 | MD5_Update(md5cx, md5_inner, MD5_LENGTH); |
michael@0 | 4582 | } |
michael@0 | 4583 | MD5_End(md5cx, hashes->u.s.md5, &outLength, MD5_LENGTH); |
michael@0 | 4584 | |
michael@0 | 4585 | PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH)); |
michael@0 | 4586 | |
michael@0 | 4587 | if (!isTLS) { |
michael@0 | 4588 | PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, |
michael@0 | 4589 | mac_defs[mac_sha].pad_size)); |
michael@0 | 4590 | PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH)); |
michael@0 | 4591 | |
michael@0 | 4592 | SHA1_Begin(shacx); |
michael@0 | 4593 | SHA1_Update(shacx, spec->msItem.data, spec->msItem.len); |
michael@0 | 4594 | SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size); |
michael@0 | 4595 | SHA1_Update(shacx, sha_inner, SHA1_LENGTH); |
michael@0 | 4596 | } |
michael@0 | 4597 | SHA1_End(shacx, hashes->u.s.sha, &outLength, SHA1_LENGTH); |
michael@0 | 4598 | |
michael@0 | 4599 | PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH)); |
michael@0 | 4600 | |
michael@0 | 4601 | hashes->len = MD5_LENGTH + SHA1_LENGTH; |
michael@0 | 4602 | rv = SECSuccess; |
michael@0 | 4603 | #undef md5cx |
michael@0 | 4604 | #undef shacx |
michael@0 | 4605 | } else |
michael@0 | 4606 | #endif |
michael@0 | 4607 | if (ss->ssl3.hs.hashType == handshake_hash_single) { |
michael@0 | 4608 | /* compute hashes with PKCS11 */ |
michael@0 | 4609 | PK11Context *h; |
michael@0 | 4610 | unsigned int stateLen; |
michael@0 | 4611 | unsigned char stackBuf[1024]; |
michael@0 | 4612 | unsigned char *stateBuf = NULL; |
michael@0 | 4613 | |
michael@0 | 4614 | if (!spec->master_secret) { |
michael@0 | 4615 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); |
michael@0 | 4616 | return SECFailure; |
michael@0 | 4617 | } |
michael@0 | 4618 | |
michael@0 | 4619 | h = ss->ssl3.hs.sha; |
michael@0 | 4620 | stateBuf = PK11_SaveContextAlloc(h, stackBuf, |
michael@0 | 4621 | sizeof(stackBuf), &stateLen); |
michael@0 | 4622 | if (stateBuf == NULL) { |
michael@0 | 4623 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 4624 | goto tls12_loser; |
michael@0 | 4625 | } |
michael@0 | 4626 | rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len, |
michael@0 | 4627 | sizeof(hashes->u.raw)); |
michael@0 | 4628 | if (rv != SECSuccess) { |
michael@0 | 4629 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 4630 | rv = SECFailure; |
michael@0 | 4631 | goto tls12_loser; |
michael@0 | 4632 | } |
michael@0 | 4633 | /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
michael@0 | 4634 | * then this will need to be updated. */ |
michael@0 | 4635 | hashes->hashAlg = SEC_OID_SHA256; |
michael@0 | 4636 | rv = SECSuccess; |
michael@0 | 4637 | |
michael@0 | 4638 | tls12_loser: |
michael@0 | 4639 | if (stateBuf) { |
michael@0 | 4640 | if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) { |
michael@0 | 4641 | ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
michael@0 | 4642 | rv = SECFailure; |
michael@0 | 4643 | } |
michael@0 | 4644 | if (stateBuf != stackBuf) { |
michael@0 | 4645 | PORT_ZFree(stateBuf, stateLen); |
michael@0 | 4646 | } |
michael@0 | 4647 | } |
michael@0 | 4648 | } else { |
michael@0 | 4649 | /* compute hashes with PKCS11 */ |
michael@0 | 4650 | PK11Context * md5; |
michael@0 | 4651 | PK11Context * sha = NULL; |
michael@0 | 4652 | unsigned char *md5StateBuf = NULL; |
michael@0 | 4653 | unsigned char *shaStateBuf = NULL; |
michael@0 | 4654 | unsigned int md5StateLen, shaStateLen; |
michael@0 | 4655 | unsigned char md5StackBuf[256]; |
michael@0 | 4656 | unsigned char shaStackBuf[512]; |
michael@0 | 4657 | |
michael@0 | 4658 | if (!spec->master_secret) { |
michael@0 | 4659 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); |
michael@0 | 4660 | return SECFailure; |
michael@0 | 4661 | } |
michael@0 | 4662 | |
michael@0 | 4663 | md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf, |
michael@0 | 4664 | sizeof md5StackBuf, &md5StateLen); |
michael@0 | 4665 | if (md5StateBuf == NULL) { |
michael@0 | 4666 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 4667 | goto loser; |
michael@0 | 4668 | } |
michael@0 | 4669 | md5 = ss->ssl3.hs.md5; |
michael@0 | 4670 | |
michael@0 | 4671 | shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf, |
michael@0 | 4672 | sizeof shaStackBuf, &shaStateLen); |
michael@0 | 4673 | if (shaStateBuf == NULL) { |
michael@0 | 4674 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4675 | goto loser; |
michael@0 | 4676 | } |
michael@0 | 4677 | sha = ss->ssl3.hs.sha; |
michael@0 | 4678 | |
michael@0 | 4679 | if (!isTLS) { |
michael@0 | 4680 | /* compute hashes for SSL3. */ |
michael@0 | 4681 | unsigned char s[4]; |
michael@0 | 4682 | |
michael@0 | 4683 | s[0] = (unsigned char)(sender >> 24); |
michael@0 | 4684 | s[1] = (unsigned char)(sender >> 16); |
michael@0 | 4685 | s[2] = (unsigned char)(sender >> 8); |
michael@0 | 4686 | s[3] = (unsigned char)sender; |
michael@0 | 4687 | |
michael@0 | 4688 | if (sender != 0) { |
michael@0 | 4689 | rv |= PK11_DigestOp(md5, s, 4); |
michael@0 | 4690 | PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4)); |
michael@0 | 4691 | } |
michael@0 | 4692 | |
michael@0 | 4693 | PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, |
michael@0 | 4694 | mac_defs[mac_md5].pad_size)); |
michael@0 | 4695 | |
michael@0 | 4696 | rv |= PK11_DigestKey(md5,spec->master_secret); |
michael@0 | 4697 | rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size); |
michael@0 | 4698 | rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH); |
michael@0 | 4699 | PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); |
michael@0 | 4700 | if (rv != SECSuccess) { |
michael@0 | 4701 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 4702 | rv = SECFailure; |
michael@0 | 4703 | goto loser; |
michael@0 | 4704 | } |
michael@0 | 4705 | |
michael@0 | 4706 | PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength)); |
michael@0 | 4707 | |
michael@0 | 4708 | if (sender != 0) { |
michael@0 | 4709 | rv |= PK11_DigestOp(sha, s, 4); |
michael@0 | 4710 | PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4)); |
michael@0 | 4711 | } |
michael@0 | 4712 | |
michael@0 | 4713 | PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, |
michael@0 | 4714 | mac_defs[mac_sha].pad_size)); |
michael@0 | 4715 | |
michael@0 | 4716 | rv |= PK11_DigestKey(sha, spec->master_secret); |
michael@0 | 4717 | rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size); |
michael@0 | 4718 | rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH); |
michael@0 | 4719 | PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); |
michael@0 | 4720 | if (rv != SECSuccess) { |
michael@0 | 4721 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4722 | rv = SECFailure; |
michael@0 | 4723 | goto loser; |
michael@0 | 4724 | } |
michael@0 | 4725 | |
michael@0 | 4726 | PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength)); |
michael@0 | 4727 | |
michael@0 | 4728 | PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, |
michael@0 | 4729 | mac_defs[mac_md5].pad_size)); |
michael@0 | 4730 | PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH)); |
michael@0 | 4731 | |
michael@0 | 4732 | rv |= PK11_DigestBegin(md5); |
michael@0 | 4733 | rv |= PK11_DigestKey(md5, spec->master_secret); |
michael@0 | 4734 | rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size); |
michael@0 | 4735 | rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH); |
michael@0 | 4736 | } |
michael@0 | 4737 | rv |= PK11_DigestFinal(md5, hashes->u.s.md5, &outLength, MD5_LENGTH); |
michael@0 | 4738 | PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); |
michael@0 | 4739 | if (rv != SECSuccess) { |
michael@0 | 4740 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 4741 | rv = SECFailure; |
michael@0 | 4742 | goto loser; |
michael@0 | 4743 | } |
michael@0 | 4744 | |
michael@0 | 4745 | PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH)); |
michael@0 | 4746 | |
michael@0 | 4747 | if (!isTLS) { |
michael@0 | 4748 | PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, |
michael@0 | 4749 | mac_defs[mac_sha].pad_size)); |
michael@0 | 4750 | PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH)); |
michael@0 | 4751 | |
michael@0 | 4752 | rv |= PK11_DigestBegin(sha); |
michael@0 | 4753 | rv |= PK11_DigestKey(sha,spec->master_secret); |
michael@0 | 4754 | rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size); |
michael@0 | 4755 | rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH); |
michael@0 | 4756 | } |
michael@0 | 4757 | rv |= PK11_DigestFinal(sha, hashes->u.s.sha, &outLength, SHA1_LENGTH); |
michael@0 | 4758 | PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); |
michael@0 | 4759 | if (rv != SECSuccess) { |
michael@0 | 4760 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4761 | rv = SECFailure; |
michael@0 | 4762 | goto loser; |
michael@0 | 4763 | } |
michael@0 | 4764 | |
michael@0 | 4765 | PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH)); |
michael@0 | 4766 | |
michael@0 | 4767 | hashes->len = MD5_LENGTH + SHA1_LENGTH; |
michael@0 | 4768 | rv = SECSuccess; |
michael@0 | 4769 | |
michael@0 | 4770 | loser: |
michael@0 | 4771 | if (md5StateBuf) { |
michael@0 | 4772 | if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen) |
michael@0 | 4773 | != SECSuccess) |
michael@0 | 4774 | { |
michael@0 | 4775 | ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
michael@0 | 4776 | rv = SECFailure; |
michael@0 | 4777 | } |
michael@0 | 4778 | if (md5StateBuf != md5StackBuf) { |
michael@0 | 4779 | PORT_ZFree(md5StateBuf, md5StateLen); |
michael@0 | 4780 | } |
michael@0 | 4781 | } |
michael@0 | 4782 | if (shaStateBuf) { |
michael@0 | 4783 | if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen) |
michael@0 | 4784 | != SECSuccess) |
michael@0 | 4785 | { |
michael@0 | 4786 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4787 | rv = SECFailure; |
michael@0 | 4788 | } |
michael@0 | 4789 | if (shaStateBuf != shaStackBuf) { |
michael@0 | 4790 | PORT_ZFree(shaStateBuf, shaStateLen); |
michael@0 | 4791 | } |
michael@0 | 4792 | } |
michael@0 | 4793 | } |
michael@0 | 4794 | return rv; |
michael@0 | 4795 | } |
michael@0 | 4796 | |
michael@0 | 4797 | static SECStatus |
michael@0 | 4798 | ssl3_ComputeBackupHandshakeHashes(sslSocket * ss, |
michael@0 | 4799 | SSL3Hashes * hashes) /* output goes here. */ |
michael@0 | 4800 | { |
michael@0 | 4801 | SECStatus rv = SECSuccess; |
michael@0 | 4802 | |
michael@0 | 4803 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 4804 | PORT_Assert( !ss->sec.isServer ); |
michael@0 | 4805 | PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single ); |
michael@0 | 4806 | |
michael@0 | 4807 | rv = PK11_DigestFinal(ss->ssl3.hs.backupHash, hashes->u.raw, &hashes->len, |
michael@0 | 4808 | sizeof(hashes->u.raw)); |
michael@0 | 4809 | if (rv != SECSuccess) { |
michael@0 | 4810 | ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
michael@0 | 4811 | rv = SECFailure; |
michael@0 | 4812 | goto loser; |
michael@0 | 4813 | } |
michael@0 | 4814 | hashes->hashAlg = SEC_OID_SHA1; |
michael@0 | 4815 | |
michael@0 | 4816 | loser: |
michael@0 | 4817 | PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE); |
michael@0 | 4818 | ss->ssl3.hs.backupHash = NULL; |
michael@0 | 4819 | return rv; |
michael@0 | 4820 | } |
michael@0 | 4821 | |
michael@0 | 4822 | /* |
michael@0 | 4823 | * SSL 2 based implementations pass in the initial outbound buffer |
michael@0 | 4824 | * so that the handshake hash can contain the included information. |
michael@0 | 4825 | * |
michael@0 | 4826 | * Called from ssl2_BeginClientHandshake() in sslcon.c |
michael@0 | 4827 | */ |
michael@0 | 4828 | SECStatus |
michael@0 | 4829 | ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length) |
michael@0 | 4830 | { |
michael@0 | 4831 | SECStatus rv; |
michael@0 | 4832 | |
michael@0 | 4833 | ssl_GetSSL3HandshakeLock(ss); /**************************************/ |
michael@0 | 4834 | |
michael@0 | 4835 | rv = ssl3_InitState(ss); |
michael@0 | 4836 | if (rv != SECSuccess) { |
michael@0 | 4837 | goto done; /* ssl3_InitState has set the error code. */ |
michael@0 | 4838 | } |
michael@0 | 4839 | rv = ssl3_RestartHandshakeHashes(ss); |
michael@0 | 4840 | if (rv != SECSuccess) { |
michael@0 | 4841 | goto done; |
michael@0 | 4842 | } |
michael@0 | 4843 | |
michael@0 | 4844 | PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH); |
michael@0 | 4845 | PORT_Memcpy( |
michael@0 | 4846 | &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - SSL_CHALLENGE_BYTES], |
michael@0 | 4847 | &ss->sec.ci.clientChallenge, |
michael@0 | 4848 | SSL_CHALLENGE_BYTES); |
michael@0 | 4849 | |
michael@0 | 4850 | rv = ssl3_UpdateHandshakeHashes(ss, buf, length); |
michael@0 | 4851 | /* if it failed, ssl3_UpdateHandshakeHashes has set the error code. */ |
michael@0 | 4852 | |
michael@0 | 4853 | done: |
michael@0 | 4854 | ssl_ReleaseSSL3HandshakeLock(ss); /**************************************/ |
michael@0 | 4855 | return rv; |
michael@0 | 4856 | } |
michael@0 | 4857 | |
michael@0 | 4858 | /************************************************************************** |
michael@0 | 4859 | * end of Handshake Hash functions. |
michael@0 | 4860 | * Begin Send and Handle functions for handshakes. |
michael@0 | 4861 | **************************************************************************/ |
michael@0 | 4862 | |
michael@0 | 4863 | /* Called from ssl3_HandleHelloRequest(), |
michael@0 | 4864 | * ssl3_RedoHandshake() |
michael@0 | 4865 | * ssl2_BeginClientHandshake (when resuming ssl3 session) |
michael@0 | 4866 | * dtls_HandleHelloVerifyRequest(with resending=PR_TRUE) |
michael@0 | 4867 | */ |
michael@0 | 4868 | SECStatus |
michael@0 | 4869 | ssl3_SendClientHello(sslSocket *ss, PRBool resending) |
michael@0 | 4870 | { |
michael@0 | 4871 | sslSessionID * sid; |
michael@0 | 4872 | ssl3CipherSpec * cwSpec; |
michael@0 | 4873 | SECStatus rv; |
michael@0 | 4874 | int i; |
michael@0 | 4875 | int length; |
michael@0 | 4876 | int num_suites; |
michael@0 | 4877 | int actual_count = 0; |
michael@0 | 4878 | PRBool isTLS = PR_FALSE; |
michael@0 | 4879 | PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE; |
michael@0 | 4880 | PRInt32 total_exten_len = 0; |
michael@0 | 4881 | unsigned paddingExtensionLen; |
michael@0 | 4882 | unsigned numCompressionMethods; |
michael@0 | 4883 | PRInt32 flags; |
michael@0 | 4884 | |
michael@0 | 4885 | SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(), |
michael@0 | 4886 | ss->fd)); |
michael@0 | 4887 | |
michael@0 | 4888 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 4889 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 4890 | |
michael@0 | 4891 | rv = ssl3_InitState(ss); |
michael@0 | 4892 | if (rv != SECSuccess) { |
michael@0 | 4893 | return rv; /* ssl3_InitState has set the error code. */ |
michael@0 | 4894 | } |
michael@0 | 4895 | ss->ssl3.hs.sendingSCSV = PR_FALSE; /* Must be reset every handshake */ |
michael@0 | 4896 | PORT_Assert(IS_DTLS(ss) || !resending); |
michael@0 | 4897 | |
michael@0 | 4898 | SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); |
michael@0 | 4899 | ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; |
michael@0 | 4900 | |
michael@0 | 4901 | /* We might be starting a session renegotiation in which case we should |
michael@0 | 4902 | * clear previous state. |
michael@0 | 4903 | */ |
michael@0 | 4904 | PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); |
michael@0 | 4905 | |
michael@0 | 4906 | rv = ssl3_RestartHandshakeHashes(ss); |
michael@0 | 4907 | if (rv != SECSuccess) { |
michael@0 | 4908 | return rv; |
michael@0 | 4909 | } |
michael@0 | 4910 | |
michael@0 | 4911 | /* |
michael@0 | 4912 | * During a renegotiation, ss->clientHelloVersion will be used again to |
michael@0 | 4913 | * work around a Windows SChannel bug. Ensure that it is still enabled. |
michael@0 | 4914 | */ |
michael@0 | 4915 | if (ss->firstHsDone) { |
michael@0 | 4916 | if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
michael@0 | 4917 | PORT_SetError(SSL_ERROR_SSL_DISABLED); |
michael@0 | 4918 | return SECFailure; |
michael@0 | 4919 | } |
michael@0 | 4920 | |
michael@0 | 4921 | if (ss->clientHelloVersion < ss->vrange.min || |
michael@0 | 4922 | ss->clientHelloVersion > ss->vrange.max) { |
michael@0 | 4923 | PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); |
michael@0 | 4924 | return SECFailure; |
michael@0 | 4925 | } |
michael@0 | 4926 | } |
michael@0 | 4927 | |
michael@0 | 4928 | /* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup |
michael@0 | 4929 | * handles expired entries and other details. |
michael@0 | 4930 | * XXX If we've been called from ssl2_BeginClientHandshake, then |
michael@0 | 4931 | * this lookup is duplicative and wasteful. |
michael@0 | 4932 | */ |
michael@0 | 4933 | sid = (ss->opt.noCache) ? NULL |
michael@0 | 4934 | : ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url); |
michael@0 | 4935 | |
michael@0 | 4936 | /* We can't resume based on a different token. If the sid exists, |
michael@0 | 4937 | * make sure the token that holds the master secret still exists ... |
michael@0 | 4938 | * If we previously did client-auth, make sure that the token that holds |
michael@0 | 4939 | * the private key still exists, is logged in, hasn't been removed, etc. |
michael@0 | 4940 | */ |
michael@0 | 4941 | if (sid) { |
michael@0 | 4942 | PRBool sidOK = PR_TRUE; |
michael@0 | 4943 | if (sid->u.ssl3.keys.msIsWrapped) { |
michael@0 | 4944 | /* Session key was wrapped, which means it was using PKCS11, */ |
michael@0 | 4945 | PK11SlotInfo *slot = NULL; |
michael@0 | 4946 | if (sid->u.ssl3.masterValid && !ss->opt.bypassPKCS11) { |
michael@0 | 4947 | slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, |
michael@0 | 4948 | sid->u.ssl3.masterSlotID); |
michael@0 | 4949 | } |
michael@0 | 4950 | if (slot == NULL) { |
michael@0 | 4951 | sidOK = PR_FALSE; |
michael@0 | 4952 | } else { |
michael@0 | 4953 | PK11SymKey *wrapKey = NULL; |
michael@0 | 4954 | if (!PK11_IsPresent(slot) || |
michael@0 | 4955 | ((wrapKey = PK11_GetWrapKey(slot, |
michael@0 | 4956 | sid->u.ssl3.masterWrapIndex, |
michael@0 | 4957 | sid->u.ssl3.masterWrapMech, |
michael@0 | 4958 | sid->u.ssl3.masterWrapSeries, |
michael@0 | 4959 | ss->pkcs11PinArg)) == NULL) ) { |
michael@0 | 4960 | sidOK = PR_FALSE; |
michael@0 | 4961 | } |
michael@0 | 4962 | if (wrapKey) PK11_FreeSymKey(wrapKey); |
michael@0 | 4963 | PK11_FreeSlot(slot); |
michael@0 | 4964 | slot = NULL; |
michael@0 | 4965 | } |
michael@0 | 4966 | } |
michael@0 | 4967 | /* If we previously did client-auth, make sure that the token that |
michael@0 | 4968 | ** holds the private key still exists, is logged in, hasn't been |
michael@0 | 4969 | ** removed, etc. |
michael@0 | 4970 | */ |
michael@0 | 4971 | if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) { |
michael@0 | 4972 | sidOK = PR_FALSE; |
michael@0 | 4973 | } |
michael@0 | 4974 | |
michael@0 | 4975 | /* TLS 1.0 (RFC 2246) Appendix E says: |
michael@0 | 4976 | * Whenever a client already knows the highest protocol known to |
michael@0 | 4977 | * a server (for example, when resuming a session), it should |
michael@0 | 4978 | * initiate the connection in that native protocol. |
michael@0 | 4979 | * So we pass sid->version to ssl3_NegotiateVersion() here, except |
michael@0 | 4980 | * when renegotiating. |
michael@0 | 4981 | * |
michael@0 | 4982 | * Windows SChannel compares the client_version inside the RSA |
michael@0 | 4983 | * EncryptedPreMasterSecret of a renegotiation with the |
michael@0 | 4984 | * client_version of the initial ClientHello rather than the |
michael@0 | 4985 | * ClientHello in the renegotiation. To work around this bug, we |
michael@0 | 4986 | * continue to use the client_version used in the initial |
michael@0 | 4987 | * ClientHello when renegotiating. |
michael@0 | 4988 | */ |
michael@0 | 4989 | if (sidOK) { |
michael@0 | 4990 | if (ss->firstHsDone) { |
michael@0 | 4991 | /* |
michael@0 | 4992 | * The client_version of the initial ClientHello is still |
michael@0 | 4993 | * available in ss->clientHelloVersion. Ensure that |
michael@0 | 4994 | * sid->version is bounded within |
michael@0 | 4995 | * [ss->vrange.min, ss->clientHelloVersion], otherwise we |
michael@0 | 4996 | * can't use sid. |
michael@0 | 4997 | */ |
michael@0 | 4998 | if (sid->version >= ss->vrange.min && |
michael@0 | 4999 | sid->version <= ss->clientHelloVersion) { |
michael@0 | 5000 | ss->version = ss->clientHelloVersion; |
michael@0 | 5001 | } else { |
michael@0 | 5002 | sidOK = PR_FALSE; |
michael@0 | 5003 | } |
michael@0 | 5004 | } else { |
michael@0 | 5005 | if (ssl3_NegotiateVersion(ss, sid->version, |
michael@0 | 5006 | PR_FALSE) != SECSuccess) { |
michael@0 | 5007 | sidOK = PR_FALSE; |
michael@0 | 5008 | } |
michael@0 | 5009 | } |
michael@0 | 5010 | } |
michael@0 | 5011 | |
michael@0 | 5012 | if (!sidOK) { |
michael@0 | 5013 | SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_not_ok ); |
michael@0 | 5014 | if (ss->sec.uncache) |
michael@0 | 5015 | (*ss->sec.uncache)(sid); |
michael@0 | 5016 | ssl_FreeSID(sid); |
michael@0 | 5017 | sid = NULL; |
michael@0 | 5018 | } |
michael@0 | 5019 | } |
michael@0 | 5020 | |
michael@0 | 5021 | if (sid) { |
michael@0 | 5022 | requestingResume = PR_TRUE; |
michael@0 | 5023 | SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits ); |
michael@0 | 5024 | |
michael@0 | 5025 | PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID, |
michael@0 | 5026 | sid->u.ssl3.sessionIDLength)); |
michael@0 | 5027 | |
michael@0 | 5028 | ss->ssl3.policy = sid->u.ssl3.policy; |
michael@0 | 5029 | } else { |
michael@0 | 5030 | SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_misses ); |
michael@0 | 5031 | |
michael@0 | 5032 | /* |
michael@0 | 5033 | * Windows SChannel compares the client_version inside the RSA |
michael@0 | 5034 | * EncryptedPreMasterSecret of a renegotiation with the |
michael@0 | 5035 | * client_version of the initial ClientHello rather than the |
michael@0 | 5036 | * ClientHello in the renegotiation. To work around this bug, we |
michael@0 | 5037 | * continue to use the client_version used in the initial |
michael@0 | 5038 | * ClientHello when renegotiating. |
michael@0 | 5039 | */ |
michael@0 | 5040 | if (ss->firstHsDone) { |
michael@0 | 5041 | ss->version = ss->clientHelloVersion; |
michael@0 | 5042 | } else { |
michael@0 | 5043 | rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED, |
michael@0 | 5044 | PR_TRUE); |
michael@0 | 5045 | if (rv != SECSuccess) |
michael@0 | 5046 | return rv; /* error code was set */ |
michael@0 | 5047 | } |
michael@0 | 5048 | |
michael@0 | 5049 | sid = ssl3_NewSessionID(ss, PR_FALSE); |
michael@0 | 5050 | if (!sid) { |
michael@0 | 5051 | return SECFailure; /* memory error is set */ |
michael@0 | 5052 | } |
michael@0 | 5053 | } |
michael@0 | 5054 | |
michael@0 | 5055 | isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 5056 | ssl_GetSpecWriteLock(ss); |
michael@0 | 5057 | cwSpec = ss->ssl3.cwSpec; |
michael@0 | 5058 | if (cwSpec->mac_def->mac == mac_null) { |
michael@0 | 5059 | /* SSL records are not being MACed. */ |
michael@0 | 5060 | cwSpec->version = ss->version; |
michael@0 | 5061 | } |
michael@0 | 5062 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 5063 | |
michael@0 | 5064 | if (ss->sec.ci.sid != NULL) { |
michael@0 | 5065 | ssl_FreeSID(ss->sec.ci.sid); /* decrement ref count, free if zero */ |
michael@0 | 5066 | } |
michael@0 | 5067 | ss->sec.ci.sid = sid; |
michael@0 | 5068 | |
michael@0 | 5069 | ss->sec.send = ssl3_SendApplicationData; |
michael@0 | 5070 | |
michael@0 | 5071 | /* shouldn't get here if SSL3 is disabled, but ... */ |
michael@0 | 5072 | if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
michael@0 | 5073 | PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled"); |
michael@0 | 5074 | PORT_SetError(SSL_ERROR_SSL_DISABLED); |
michael@0 | 5075 | return SECFailure; |
michael@0 | 5076 | } |
michael@0 | 5077 | |
michael@0 | 5078 | /* how many suites does our PKCS11 support (regardless of policy)? */ |
michael@0 | 5079 | num_suites = ssl3_config_match_init(ss); |
michael@0 | 5080 | if (!num_suites) |
michael@0 | 5081 | return SECFailure; /* ssl3_config_match_init has set error code. */ |
michael@0 | 5082 | |
michael@0 | 5083 | /* HACK for SCSV in SSL 3.0. On initial handshake, prepend SCSV, |
michael@0 | 5084 | * only if TLS is disabled. |
michael@0 | 5085 | */ |
michael@0 | 5086 | if (!ss->firstHsDone && !isTLS) { |
michael@0 | 5087 | /* Must set this before calling Hello Extension Senders, |
michael@0 | 5088 | * to suppress sending of empty RI extension. |
michael@0 | 5089 | */ |
michael@0 | 5090 | ss->ssl3.hs.sendingSCSV = PR_TRUE; |
michael@0 | 5091 | } |
michael@0 | 5092 | |
michael@0 | 5093 | /* When we attempt session resumption (only), we must lock the sid to |
michael@0 | 5094 | * prevent races with other resumption connections that receive a |
michael@0 | 5095 | * NewSessionTicket that will cause the ticket in the sid to be replaced. |
michael@0 | 5096 | * Once we've copied the session ticket into our ClientHello message, it |
michael@0 | 5097 | * is OK for the ticket to change, so we just need to make sure we hold |
michael@0 | 5098 | * the lock across the calls to ssl3_CallHelloExtensionSenders. |
michael@0 | 5099 | */ |
michael@0 | 5100 | if (sid->u.ssl3.lock) { |
michael@0 | 5101 | PR_RWLock_Rlock(sid->u.ssl3.lock); |
michael@0 | 5102 | } |
michael@0 | 5103 | |
michael@0 | 5104 | if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) { |
michael@0 | 5105 | PRUint32 maxBytes = 65535; /* 2^16 - 1 */ |
michael@0 | 5106 | PRInt32 extLen; |
michael@0 | 5107 | |
michael@0 | 5108 | extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL); |
michael@0 | 5109 | if (extLen < 0) { |
michael@0 | 5110 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5111 | return SECFailure; |
michael@0 | 5112 | } |
michael@0 | 5113 | maxBytes -= extLen; |
michael@0 | 5114 | total_exten_len += extLen; |
michael@0 | 5115 | |
michael@0 | 5116 | if (total_exten_len > 0) |
michael@0 | 5117 | total_exten_len += 2; |
michael@0 | 5118 | } |
michael@0 | 5119 | |
michael@0 | 5120 | #ifndef NSS_DISABLE_ECC |
michael@0 | 5121 | if (!total_exten_len || !isTLS) { |
michael@0 | 5122 | /* not sending the elliptic_curves and ec_point_formats extensions */ |
michael@0 | 5123 | ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */ |
michael@0 | 5124 | } |
michael@0 | 5125 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 5126 | |
michael@0 | 5127 | if (IS_DTLS(ss)) { |
michael@0 | 5128 | ssl3_DisableNonDTLSSuites(ss); |
michael@0 | 5129 | } |
michael@0 | 5130 | |
michael@0 | 5131 | /* how many suites are permitted by policy and user preference? */ |
michael@0 | 5132 | num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE); |
michael@0 | 5133 | if (!num_suites) { |
michael@0 | 5134 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5135 | return SECFailure; /* count_cipher_suites has set error code. */ |
michael@0 | 5136 | } |
michael@0 | 5137 | |
michael@0 | 5138 | fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume || |
michael@0 | 5139 | ss->version < sid->version); |
michael@0 | 5140 | /* make room for SCSV */ |
michael@0 | 5141 | if (ss->ssl3.hs.sendingSCSV) { |
michael@0 | 5142 | ++num_suites; |
michael@0 | 5143 | } |
michael@0 | 5144 | if (fallbackSCSV) { |
michael@0 | 5145 | ++num_suites; |
michael@0 | 5146 | } |
michael@0 | 5147 | |
michael@0 | 5148 | /* count compression methods */ |
michael@0 | 5149 | numCompressionMethods = 0; |
michael@0 | 5150 | for (i = 0; i < compressionMethodsCount; i++) { |
michael@0 | 5151 | if (compressionEnabled(ss, compressions[i])) |
michael@0 | 5152 | numCompressionMethods++; |
michael@0 | 5153 | } |
michael@0 | 5154 | |
michael@0 | 5155 | length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH + |
michael@0 | 5156 | 1 + ((sid == NULL) ? 0 : sid->u.ssl3.sessionIDLength) + |
michael@0 | 5157 | 2 + num_suites*sizeof(ssl3CipherSuite) + |
michael@0 | 5158 | 1 + numCompressionMethods + total_exten_len; |
michael@0 | 5159 | if (IS_DTLS(ss)) { |
michael@0 | 5160 | length += 1 + ss->ssl3.hs.cookieLen; |
michael@0 | 5161 | } |
michael@0 | 5162 | |
michael@0 | 5163 | /* A padding extension may be included to ensure that the record containing |
michael@0 | 5164 | * the ClientHello doesn't have a length between 256 and 511 bytes |
michael@0 | 5165 | * (inclusive). Initial, ClientHello records with such lengths trigger bugs |
michael@0 | 5166 | * in F5 devices. |
michael@0 | 5167 | * |
michael@0 | 5168 | * This is not done for DTLS nor for renegotiation. */ |
michael@0 | 5169 | if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) { |
michael@0 | 5170 | paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length); |
michael@0 | 5171 | total_exten_len += paddingExtensionLen; |
michael@0 | 5172 | length += paddingExtensionLen; |
michael@0 | 5173 | } else { |
michael@0 | 5174 | paddingExtensionLen = 0; |
michael@0 | 5175 | } |
michael@0 | 5176 | |
michael@0 | 5177 | rv = ssl3_AppendHandshakeHeader(ss, client_hello, length); |
michael@0 | 5178 | if (rv != SECSuccess) { |
michael@0 | 5179 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5180 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5181 | } |
michael@0 | 5182 | |
michael@0 | 5183 | if (ss->firstHsDone) { |
michael@0 | 5184 | /* The client hello version must stay unchanged to work around |
michael@0 | 5185 | * the Windows SChannel bug described above. */ |
michael@0 | 5186 | PORT_Assert(ss->version == ss->clientHelloVersion); |
michael@0 | 5187 | } |
michael@0 | 5188 | ss->clientHelloVersion = ss->version; |
michael@0 | 5189 | if (IS_DTLS(ss)) { |
michael@0 | 5190 | PRUint16 version; |
michael@0 | 5191 | |
michael@0 | 5192 | version = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion); |
michael@0 | 5193 | rv = ssl3_AppendHandshakeNumber(ss, version, 2); |
michael@0 | 5194 | } else { |
michael@0 | 5195 | rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2); |
michael@0 | 5196 | } |
michael@0 | 5197 | if (rv != SECSuccess) { |
michael@0 | 5198 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5199 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5200 | } |
michael@0 | 5201 | |
michael@0 | 5202 | if (!resending) { /* Don't re-generate if we are in DTLS re-sending mode */ |
michael@0 | 5203 | rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random); |
michael@0 | 5204 | if (rv != SECSuccess) { |
michael@0 | 5205 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5206 | return rv; /* err set by GetNewRandom. */ |
michael@0 | 5207 | } |
michael@0 | 5208 | } |
michael@0 | 5209 | rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random, |
michael@0 | 5210 | SSL3_RANDOM_LENGTH); |
michael@0 | 5211 | if (rv != SECSuccess) { |
michael@0 | 5212 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5213 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5214 | } |
michael@0 | 5215 | |
michael@0 | 5216 | if (sid) |
michael@0 | 5217 | rv = ssl3_AppendHandshakeVariable( |
michael@0 | 5218 | ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1); |
michael@0 | 5219 | else |
michael@0 | 5220 | rv = ssl3_AppendHandshakeNumber(ss, 0, 1); |
michael@0 | 5221 | if (rv != SECSuccess) { |
michael@0 | 5222 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5223 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5224 | } |
michael@0 | 5225 | |
michael@0 | 5226 | if (IS_DTLS(ss)) { |
michael@0 | 5227 | rv = ssl3_AppendHandshakeVariable( |
michael@0 | 5228 | ss, ss->ssl3.hs.cookie, ss->ssl3.hs.cookieLen, 1); |
michael@0 | 5229 | if (rv != SECSuccess) { |
michael@0 | 5230 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5231 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5232 | } |
michael@0 | 5233 | } |
michael@0 | 5234 | |
michael@0 | 5235 | rv = ssl3_AppendHandshakeNumber(ss, num_suites*sizeof(ssl3CipherSuite), 2); |
michael@0 | 5236 | if (rv != SECSuccess) { |
michael@0 | 5237 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5238 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5239 | } |
michael@0 | 5240 | |
michael@0 | 5241 | if (ss->ssl3.hs.sendingSCSV) { |
michael@0 | 5242 | /* Add the actual SCSV */ |
michael@0 | 5243 | rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, |
michael@0 | 5244 | sizeof(ssl3CipherSuite)); |
michael@0 | 5245 | if (rv != SECSuccess) { |
michael@0 | 5246 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5247 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5248 | } |
michael@0 | 5249 | actual_count++; |
michael@0 | 5250 | } |
michael@0 | 5251 | if (fallbackSCSV) { |
michael@0 | 5252 | rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV, |
michael@0 | 5253 | sizeof(ssl3CipherSuite)); |
michael@0 | 5254 | if (rv != SECSuccess) { |
michael@0 | 5255 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5256 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5257 | } |
michael@0 | 5258 | actual_count++; |
michael@0 | 5259 | } |
michael@0 | 5260 | for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
michael@0 | 5261 | ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; |
michael@0 | 5262 | if (config_match(suite, ss->ssl3.policy, PR_TRUE, &ss->vrange)) { |
michael@0 | 5263 | actual_count++; |
michael@0 | 5264 | if (actual_count > num_suites) { |
michael@0 | 5265 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5266 | /* set error card removal/insertion error */ |
michael@0 | 5267 | PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); |
michael@0 | 5268 | return SECFailure; |
michael@0 | 5269 | } |
michael@0 | 5270 | rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite, |
michael@0 | 5271 | sizeof(ssl3CipherSuite)); |
michael@0 | 5272 | if (rv != SECSuccess) { |
michael@0 | 5273 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5274 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5275 | } |
michael@0 | 5276 | } |
michael@0 | 5277 | } |
michael@0 | 5278 | |
michael@0 | 5279 | /* if cards were removed or inserted between count_cipher_suites and |
michael@0 | 5280 | * generating our list, detect the error here rather than send it off to |
michael@0 | 5281 | * the server.. */ |
michael@0 | 5282 | if (actual_count != num_suites) { |
michael@0 | 5283 | /* Card removal/insertion error */ |
michael@0 | 5284 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5285 | PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); |
michael@0 | 5286 | return SECFailure; |
michael@0 | 5287 | } |
michael@0 | 5288 | |
michael@0 | 5289 | rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1); |
michael@0 | 5290 | if (rv != SECSuccess) { |
michael@0 | 5291 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5292 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5293 | } |
michael@0 | 5294 | for (i = 0; i < compressionMethodsCount; i++) { |
michael@0 | 5295 | if (!compressionEnabled(ss, compressions[i])) |
michael@0 | 5296 | continue; |
michael@0 | 5297 | rv = ssl3_AppendHandshakeNumber(ss, compressions[i], 1); |
michael@0 | 5298 | if (rv != SECSuccess) { |
michael@0 | 5299 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5300 | return rv; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5301 | } |
michael@0 | 5302 | } |
michael@0 | 5303 | |
michael@0 | 5304 | if (total_exten_len) { |
michael@0 | 5305 | PRUint32 maxBytes = total_exten_len - 2; |
michael@0 | 5306 | PRInt32 extLen; |
michael@0 | 5307 | |
michael@0 | 5308 | rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2); |
michael@0 | 5309 | if (rv != SECSuccess) { |
michael@0 | 5310 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5311 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 5312 | } |
michael@0 | 5313 | |
michael@0 | 5314 | extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL); |
michael@0 | 5315 | if (extLen < 0) { |
michael@0 | 5316 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5317 | return SECFailure; |
michael@0 | 5318 | } |
michael@0 | 5319 | maxBytes -= extLen; |
michael@0 | 5320 | |
michael@0 | 5321 | extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes); |
michael@0 | 5322 | if (extLen < 0) { |
michael@0 | 5323 | if (sid->u.ssl3.lock) { PR_RWLock_Unlock(sid->u.ssl3.lock); } |
michael@0 | 5324 | return SECFailure; |
michael@0 | 5325 | } |
michael@0 | 5326 | maxBytes -= extLen; |
michael@0 | 5327 | |
michael@0 | 5328 | PORT_Assert(!maxBytes); |
michael@0 | 5329 | } |
michael@0 | 5330 | |
michael@0 | 5331 | if (sid->u.ssl3.lock) { |
michael@0 | 5332 | PR_RWLock_Unlock(sid->u.ssl3.lock); |
michael@0 | 5333 | } |
michael@0 | 5334 | |
michael@0 | 5335 | if (ss->xtnData.sentSessionTicketInClientHello) { |
michael@0 | 5336 | SSL_AtomicIncrementLong(&ssl3stats.sch_sid_stateless_resumes); |
michael@0 | 5337 | } |
michael@0 | 5338 | |
michael@0 | 5339 | if (ss->ssl3.hs.sendingSCSV) { |
michael@0 | 5340 | /* Since we sent the SCSV, pretend we sent empty RI extension. */ |
michael@0 | 5341 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 5342 | xtnData->advertised[xtnData->numAdvertised++] = |
michael@0 | 5343 | ssl_renegotiation_info_xtn; |
michael@0 | 5344 | } |
michael@0 | 5345 | |
michael@0 | 5346 | flags = 0; |
michael@0 | 5347 | if (!ss->firstHsDone && !IS_DTLS(ss)) { |
michael@0 | 5348 | flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION; |
michael@0 | 5349 | } |
michael@0 | 5350 | rv = ssl3_FlushHandshake(ss, flags); |
michael@0 | 5351 | if (rv != SECSuccess) { |
michael@0 | 5352 | return rv; /* error code set by ssl3_FlushHandshake */ |
michael@0 | 5353 | } |
michael@0 | 5354 | |
michael@0 | 5355 | ss->ssl3.hs.ws = wait_server_hello; |
michael@0 | 5356 | return rv; |
michael@0 | 5357 | } |
michael@0 | 5358 | |
michael@0 | 5359 | |
michael@0 | 5360 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 5361 | * ssl3 Hello Request. |
michael@0 | 5362 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 5363 | */ |
michael@0 | 5364 | static SECStatus |
michael@0 | 5365 | ssl3_HandleHelloRequest(sslSocket *ss) |
michael@0 | 5366 | { |
michael@0 | 5367 | sslSessionID *sid = ss->sec.ci.sid; |
michael@0 | 5368 | SECStatus rv; |
michael@0 | 5369 | |
michael@0 | 5370 | SSL_TRC(3, ("%d: SSL3[%d]: handle hello_request handshake", |
michael@0 | 5371 | SSL_GETPID(), ss->fd)); |
michael@0 | 5372 | |
michael@0 | 5373 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 5374 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 5375 | |
michael@0 | 5376 | if (ss->ssl3.hs.ws == wait_server_hello) |
michael@0 | 5377 | return SECSuccess; |
michael@0 | 5378 | if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) { |
michael@0 | 5379 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 5380 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST); |
michael@0 | 5381 | return SECFailure; |
michael@0 | 5382 | } |
michael@0 | 5383 | if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) { |
michael@0 | 5384 | ssl_GetXmitBufLock(ss); |
michael@0 | 5385 | rv = SSL3_SendAlert(ss, alert_warning, no_renegotiation); |
michael@0 | 5386 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 5387 | PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); |
michael@0 | 5388 | return SECFailure; |
michael@0 | 5389 | } |
michael@0 | 5390 | |
michael@0 | 5391 | if (sid) { |
michael@0 | 5392 | if (ss->sec.uncache) |
michael@0 | 5393 | ss->sec.uncache(sid); |
michael@0 | 5394 | ssl_FreeSID(sid); |
michael@0 | 5395 | ss->sec.ci.sid = NULL; |
michael@0 | 5396 | } |
michael@0 | 5397 | |
michael@0 | 5398 | if (IS_DTLS(ss)) { |
michael@0 | 5399 | dtls_RehandshakeCleanup(ss); |
michael@0 | 5400 | } |
michael@0 | 5401 | |
michael@0 | 5402 | ssl_GetXmitBufLock(ss); |
michael@0 | 5403 | rv = ssl3_SendClientHello(ss, PR_FALSE); |
michael@0 | 5404 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 5405 | |
michael@0 | 5406 | return rv; |
michael@0 | 5407 | } |
michael@0 | 5408 | |
michael@0 | 5409 | #define UNKNOWN_WRAP_MECHANISM 0x7fffffff |
michael@0 | 5410 | |
michael@0 | 5411 | static const CK_MECHANISM_TYPE wrapMechanismList[SSL_NUM_WRAP_MECHS] = { |
michael@0 | 5412 | CKM_DES3_ECB, |
michael@0 | 5413 | CKM_CAST5_ECB, |
michael@0 | 5414 | CKM_DES_ECB, |
michael@0 | 5415 | CKM_KEY_WRAP_LYNKS, |
michael@0 | 5416 | CKM_IDEA_ECB, |
michael@0 | 5417 | CKM_CAST3_ECB, |
michael@0 | 5418 | CKM_CAST_ECB, |
michael@0 | 5419 | CKM_RC5_ECB, |
michael@0 | 5420 | CKM_RC2_ECB, |
michael@0 | 5421 | CKM_CDMF_ECB, |
michael@0 | 5422 | CKM_SKIPJACK_WRAP, |
michael@0 | 5423 | CKM_SKIPJACK_CBC64, |
michael@0 | 5424 | CKM_AES_ECB, |
michael@0 | 5425 | CKM_CAMELLIA_ECB, |
michael@0 | 5426 | CKM_SEED_ECB, |
michael@0 | 5427 | UNKNOWN_WRAP_MECHANISM |
michael@0 | 5428 | }; |
michael@0 | 5429 | |
michael@0 | 5430 | static int |
michael@0 | 5431 | ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech) |
michael@0 | 5432 | { |
michael@0 | 5433 | const CK_MECHANISM_TYPE *pMech = wrapMechanismList; |
michael@0 | 5434 | |
michael@0 | 5435 | while (mech != *pMech && *pMech != UNKNOWN_WRAP_MECHANISM) { |
michael@0 | 5436 | ++pMech; |
michael@0 | 5437 | } |
michael@0 | 5438 | return (*pMech == UNKNOWN_WRAP_MECHANISM) ? -1 |
michael@0 | 5439 | : (pMech - wrapMechanismList); |
michael@0 | 5440 | } |
michael@0 | 5441 | |
michael@0 | 5442 | static PK11SymKey * |
michael@0 | 5443 | ssl_UnwrapSymWrappingKey( |
michael@0 | 5444 | SSLWrappedSymWrappingKey *pWswk, |
michael@0 | 5445 | SECKEYPrivateKey * svrPrivKey, |
michael@0 | 5446 | SSL3KEAType exchKeyType, |
michael@0 | 5447 | CK_MECHANISM_TYPE masterWrapMech, |
michael@0 | 5448 | void * pwArg) |
michael@0 | 5449 | { |
michael@0 | 5450 | PK11SymKey * unwrappedWrappingKey = NULL; |
michael@0 | 5451 | SECItem wrappedKey; |
michael@0 | 5452 | #ifndef NSS_DISABLE_ECC |
michael@0 | 5453 | PK11SymKey * Ks; |
michael@0 | 5454 | SECKEYPublicKey pubWrapKey; |
michael@0 | 5455 | ECCWrappedKeyInfo *ecWrapped; |
michael@0 | 5456 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 5457 | |
michael@0 | 5458 | /* found the wrapping key on disk. */ |
michael@0 | 5459 | PORT_Assert(pWswk->symWrapMechanism == masterWrapMech); |
michael@0 | 5460 | PORT_Assert(pWswk->exchKeyType == exchKeyType); |
michael@0 | 5461 | if (pWswk->symWrapMechanism != masterWrapMech || |
michael@0 | 5462 | pWswk->exchKeyType != exchKeyType) { |
michael@0 | 5463 | goto loser; |
michael@0 | 5464 | } |
michael@0 | 5465 | wrappedKey.type = siBuffer; |
michael@0 | 5466 | wrappedKey.data = pWswk->wrappedSymmetricWrappingkey; |
michael@0 | 5467 | wrappedKey.len = pWswk->wrappedSymKeyLen; |
michael@0 | 5468 | PORT_Assert(wrappedKey.len <= sizeof pWswk->wrappedSymmetricWrappingkey); |
michael@0 | 5469 | |
michael@0 | 5470 | switch (exchKeyType) { |
michael@0 | 5471 | |
michael@0 | 5472 | case kt_rsa: |
michael@0 | 5473 | unwrappedWrappingKey = |
michael@0 | 5474 | PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey, |
michael@0 | 5475 | masterWrapMech, CKA_UNWRAP, 0); |
michael@0 | 5476 | break; |
michael@0 | 5477 | |
michael@0 | 5478 | #ifndef NSS_DISABLE_ECC |
michael@0 | 5479 | case kt_ecdh: |
michael@0 | 5480 | /* |
michael@0 | 5481 | * For kt_ecdh, we first create an EC public key based on |
michael@0 | 5482 | * data stored with the wrappedSymmetricWrappingkey. Next, |
michael@0 | 5483 | * we do an ECDH computation involving this public key and |
michael@0 | 5484 | * the SSL server's (long-term) EC private key. The resulting |
michael@0 | 5485 | * shared secret is treated the same way as Fortezza's Ks, i.e., |
michael@0 | 5486 | * it is used to recover the symmetric wrapping key. |
michael@0 | 5487 | * |
michael@0 | 5488 | * The data in wrappedSymmetricWrappingkey is laid out as defined |
michael@0 | 5489 | * in the ECCWrappedKeyInfo structure. |
michael@0 | 5490 | */ |
michael@0 | 5491 | ecWrapped = (ECCWrappedKeyInfo *) pWswk->wrappedSymmetricWrappingkey; |
michael@0 | 5492 | |
michael@0 | 5493 | PORT_Assert(ecWrapped->encodedParamLen + ecWrapped->pubValueLen + |
michael@0 | 5494 | ecWrapped->wrappedKeyLen <= MAX_EC_WRAPPED_KEY_BUFLEN); |
michael@0 | 5495 | |
michael@0 | 5496 | if (ecWrapped->encodedParamLen + ecWrapped->pubValueLen + |
michael@0 | 5497 | ecWrapped->wrappedKeyLen > MAX_EC_WRAPPED_KEY_BUFLEN) { |
michael@0 | 5498 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 5499 | goto loser; |
michael@0 | 5500 | } |
michael@0 | 5501 | |
michael@0 | 5502 | pubWrapKey.keyType = ecKey; |
michael@0 | 5503 | pubWrapKey.u.ec.size = ecWrapped->size; |
michael@0 | 5504 | pubWrapKey.u.ec.DEREncodedParams.len = ecWrapped->encodedParamLen; |
michael@0 | 5505 | pubWrapKey.u.ec.DEREncodedParams.data = ecWrapped->var; |
michael@0 | 5506 | pubWrapKey.u.ec.publicValue.len = ecWrapped->pubValueLen; |
michael@0 | 5507 | pubWrapKey.u.ec.publicValue.data = ecWrapped->var + |
michael@0 | 5508 | ecWrapped->encodedParamLen; |
michael@0 | 5509 | |
michael@0 | 5510 | wrappedKey.len = ecWrapped->wrappedKeyLen; |
michael@0 | 5511 | wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen + |
michael@0 | 5512 | ecWrapped->pubValueLen; |
michael@0 | 5513 | |
michael@0 | 5514 | /* Derive Ks using ECDH */ |
michael@0 | 5515 | Ks = PK11_PubDeriveWithKDF(svrPrivKey, &pubWrapKey, PR_FALSE, NULL, |
michael@0 | 5516 | NULL, CKM_ECDH1_DERIVE, masterWrapMech, |
michael@0 | 5517 | CKA_DERIVE, 0, CKD_NULL, NULL, NULL); |
michael@0 | 5518 | if (Ks == NULL) { |
michael@0 | 5519 | goto loser; |
michael@0 | 5520 | } |
michael@0 | 5521 | |
michael@0 | 5522 | /* Use Ks to unwrap the wrapping key */ |
michael@0 | 5523 | unwrappedWrappingKey = PK11_UnwrapSymKey(Ks, masterWrapMech, NULL, |
michael@0 | 5524 | &wrappedKey, masterWrapMech, |
michael@0 | 5525 | CKA_UNWRAP, 0); |
michael@0 | 5526 | PK11_FreeSymKey(Ks); |
michael@0 | 5527 | |
michael@0 | 5528 | break; |
michael@0 | 5529 | #endif |
michael@0 | 5530 | |
michael@0 | 5531 | default: |
michael@0 | 5532 | /* Assert? */ |
michael@0 | 5533 | SET_ERROR_CODE |
michael@0 | 5534 | goto loser; |
michael@0 | 5535 | } |
michael@0 | 5536 | loser: |
michael@0 | 5537 | return unwrappedWrappingKey; |
michael@0 | 5538 | } |
michael@0 | 5539 | |
michael@0 | 5540 | /* Each process sharing the server session ID cache has its own array of |
michael@0 | 5541 | * SymKey pointers for the symmetric wrapping keys that are used to wrap |
michael@0 | 5542 | * the master secrets. There is one key for each KEA type. These Symkeys |
michael@0 | 5543 | * correspond to the wrapped SymKeys kept in the server session cache. |
michael@0 | 5544 | */ |
michael@0 | 5545 | |
michael@0 | 5546 | typedef struct { |
michael@0 | 5547 | PK11SymKey * symWrapKey[kt_kea_size]; |
michael@0 | 5548 | } ssl3SymWrapKey; |
michael@0 | 5549 | |
michael@0 | 5550 | static PZLock * symWrapKeysLock = NULL; |
michael@0 | 5551 | static ssl3SymWrapKey symWrapKeys[SSL_NUM_WRAP_MECHS]; |
michael@0 | 5552 | |
michael@0 | 5553 | SECStatus ssl_FreeSymWrapKeysLock(void) |
michael@0 | 5554 | { |
michael@0 | 5555 | if (symWrapKeysLock) { |
michael@0 | 5556 | PZ_DestroyLock(symWrapKeysLock); |
michael@0 | 5557 | symWrapKeysLock = NULL; |
michael@0 | 5558 | return SECSuccess; |
michael@0 | 5559 | } |
michael@0 | 5560 | PORT_SetError(SEC_ERROR_NOT_INITIALIZED); |
michael@0 | 5561 | return SECFailure; |
michael@0 | 5562 | } |
michael@0 | 5563 | |
michael@0 | 5564 | SECStatus |
michael@0 | 5565 | SSL3_ShutdownServerCache(void) |
michael@0 | 5566 | { |
michael@0 | 5567 | int i, j; |
michael@0 | 5568 | |
michael@0 | 5569 | if (!symWrapKeysLock) |
michael@0 | 5570 | return SECSuccess; /* lock was never initialized */ |
michael@0 | 5571 | PZ_Lock(symWrapKeysLock); |
michael@0 | 5572 | /* get rid of all symWrapKeys */ |
michael@0 | 5573 | for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) { |
michael@0 | 5574 | for (j = 0; j < kt_kea_size; ++j) { |
michael@0 | 5575 | PK11SymKey ** pSymWrapKey; |
michael@0 | 5576 | pSymWrapKey = &symWrapKeys[i].symWrapKey[j]; |
michael@0 | 5577 | if (*pSymWrapKey) { |
michael@0 | 5578 | PK11_FreeSymKey(*pSymWrapKey); |
michael@0 | 5579 | *pSymWrapKey = NULL; |
michael@0 | 5580 | } |
michael@0 | 5581 | } |
michael@0 | 5582 | } |
michael@0 | 5583 | |
michael@0 | 5584 | PZ_Unlock(symWrapKeysLock); |
michael@0 | 5585 | ssl_FreeSessionCacheLocks(); |
michael@0 | 5586 | return SECSuccess; |
michael@0 | 5587 | } |
michael@0 | 5588 | |
michael@0 | 5589 | SECStatus ssl_InitSymWrapKeysLock(void) |
michael@0 | 5590 | { |
michael@0 | 5591 | symWrapKeysLock = PZ_NewLock(nssILockOther); |
michael@0 | 5592 | return symWrapKeysLock ? SECSuccess : SECFailure; |
michael@0 | 5593 | } |
michael@0 | 5594 | |
michael@0 | 5595 | /* Try to get wrapping key for mechanism from in-memory array. |
michael@0 | 5596 | * If that fails, look for one on disk. |
michael@0 | 5597 | * If that fails, generate a new one, put the new one on disk, |
michael@0 | 5598 | * Put the new key in the in-memory array. |
michael@0 | 5599 | */ |
michael@0 | 5600 | static PK11SymKey * |
michael@0 | 5601 | getWrappingKey( sslSocket * ss, |
michael@0 | 5602 | PK11SlotInfo * masterSecretSlot, |
michael@0 | 5603 | SSL3KEAType exchKeyType, |
michael@0 | 5604 | CK_MECHANISM_TYPE masterWrapMech, |
michael@0 | 5605 | void * pwArg) |
michael@0 | 5606 | { |
michael@0 | 5607 | SECKEYPrivateKey * svrPrivKey; |
michael@0 | 5608 | SECKEYPublicKey * svrPubKey = NULL; |
michael@0 | 5609 | PK11SymKey * unwrappedWrappingKey = NULL; |
michael@0 | 5610 | PK11SymKey ** pSymWrapKey; |
michael@0 | 5611 | CK_MECHANISM_TYPE asymWrapMechanism = CKM_INVALID_MECHANISM; |
michael@0 | 5612 | int length; |
michael@0 | 5613 | int symWrapMechIndex; |
michael@0 | 5614 | SECStatus rv; |
michael@0 | 5615 | SECItem wrappedKey; |
michael@0 | 5616 | SSLWrappedSymWrappingKey wswk; |
michael@0 | 5617 | #ifndef NSS_DISABLE_ECC |
michael@0 | 5618 | PK11SymKey * Ks = NULL; |
michael@0 | 5619 | SECKEYPublicKey *pubWrapKey = NULL; |
michael@0 | 5620 | SECKEYPrivateKey *privWrapKey = NULL; |
michael@0 | 5621 | ECCWrappedKeyInfo *ecWrapped; |
michael@0 | 5622 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 5623 | |
michael@0 | 5624 | svrPrivKey = ss->serverCerts[exchKeyType].SERVERKEY; |
michael@0 | 5625 | PORT_Assert(svrPrivKey != NULL); |
michael@0 | 5626 | if (!svrPrivKey) { |
michael@0 | 5627 | return NULL; /* why are we here?!? */ |
michael@0 | 5628 | } |
michael@0 | 5629 | |
michael@0 | 5630 | symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech); |
michael@0 | 5631 | PORT_Assert(symWrapMechIndex >= 0); |
michael@0 | 5632 | if (symWrapMechIndex < 0) |
michael@0 | 5633 | return NULL; /* invalid masterWrapMech. */ |
michael@0 | 5634 | |
michael@0 | 5635 | pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType]; |
michael@0 | 5636 | |
michael@0 | 5637 | ssl_InitSessionCacheLocks(PR_TRUE); |
michael@0 | 5638 | |
michael@0 | 5639 | PZ_Lock(symWrapKeysLock); |
michael@0 | 5640 | |
michael@0 | 5641 | unwrappedWrappingKey = *pSymWrapKey; |
michael@0 | 5642 | if (unwrappedWrappingKey != NULL) { |
michael@0 | 5643 | if (PK11_VerifyKeyOK(unwrappedWrappingKey)) { |
michael@0 | 5644 | unwrappedWrappingKey = PK11_ReferenceSymKey(unwrappedWrappingKey); |
michael@0 | 5645 | goto done; |
michael@0 | 5646 | } |
michael@0 | 5647 | /* slot series has changed, so this key is no good any more. */ |
michael@0 | 5648 | PK11_FreeSymKey(unwrappedWrappingKey); |
michael@0 | 5649 | *pSymWrapKey = unwrappedWrappingKey = NULL; |
michael@0 | 5650 | } |
michael@0 | 5651 | |
michael@0 | 5652 | /* Try to get wrapped SymWrapping key out of the (disk) cache. */ |
michael@0 | 5653 | /* Following call fills in wswk on success. */ |
michael@0 | 5654 | if (ssl_GetWrappingKey(symWrapMechIndex, exchKeyType, &wswk)) { |
michael@0 | 5655 | /* found the wrapped sym wrapping key on disk. */ |
michael@0 | 5656 | unwrappedWrappingKey = |
michael@0 | 5657 | ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType, |
michael@0 | 5658 | masterWrapMech, pwArg); |
michael@0 | 5659 | if (unwrappedWrappingKey) { |
michael@0 | 5660 | goto install; |
michael@0 | 5661 | } |
michael@0 | 5662 | } |
michael@0 | 5663 | |
michael@0 | 5664 | if (!masterSecretSlot) /* caller doesn't want to create a new one. */ |
michael@0 | 5665 | goto loser; |
michael@0 | 5666 | |
michael@0 | 5667 | length = PK11_GetBestKeyLength(masterSecretSlot, masterWrapMech); |
michael@0 | 5668 | /* Zero length means fixed key length algorithm, or error. |
michael@0 | 5669 | * It's ambiguous. |
michael@0 | 5670 | */ |
michael@0 | 5671 | unwrappedWrappingKey = PK11_KeyGen(masterSecretSlot, masterWrapMech, NULL, |
michael@0 | 5672 | length, pwArg); |
michael@0 | 5673 | if (!unwrappedWrappingKey) { |
michael@0 | 5674 | goto loser; |
michael@0 | 5675 | } |
michael@0 | 5676 | |
michael@0 | 5677 | /* Prepare the buffer to receive the wrappedWrappingKey, |
michael@0 | 5678 | * the symmetric wrapping key wrapped using the server's pub key. |
michael@0 | 5679 | */ |
michael@0 | 5680 | PORT_Memset(&wswk, 0, sizeof wswk); /* eliminate UMRs. */ |
michael@0 | 5681 | |
michael@0 | 5682 | if (ss->serverCerts[exchKeyType].serverKeyPair) { |
michael@0 | 5683 | svrPubKey = ss->serverCerts[exchKeyType].serverKeyPair->pubKey; |
michael@0 | 5684 | } |
michael@0 | 5685 | if (svrPubKey == NULL) { |
michael@0 | 5686 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 5687 | goto loser; |
michael@0 | 5688 | } |
michael@0 | 5689 | wrappedKey.type = siBuffer; |
michael@0 | 5690 | wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey); |
michael@0 | 5691 | wrappedKey.data = wswk.wrappedSymmetricWrappingkey; |
michael@0 | 5692 | |
michael@0 | 5693 | PORT_Assert(wrappedKey.len <= sizeof wswk.wrappedSymmetricWrappingkey); |
michael@0 | 5694 | if (wrappedKey.len > sizeof wswk.wrappedSymmetricWrappingkey) |
michael@0 | 5695 | goto loser; |
michael@0 | 5696 | |
michael@0 | 5697 | /* wrap symmetric wrapping key in server's public key. */ |
michael@0 | 5698 | switch (exchKeyType) { |
michael@0 | 5699 | case kt_rsa: |
michael@0 | 5700 | asymWrapMechanism = CKM_RSA_PKCS; |
michael@0 | 5701 | rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey, |
michael@0 | 5702 | unwrappedWrappingKey, &wrappedKey); |
michael@0 | 5703 | break; |
michael@0 | 5704 | |
michael@0 | 5705 | #ifndef NSS_DISABLE_ECC |
michael@0 | 5706 | case kt_ecdh: |
michael@0 | 5707 | /* |
michael@0 | 5708 | * We generate an ephemeral EC key pair. Perform an ECDH |
michael@0 | 5709 | * computation involving this ephemeral EC public key and |
michael@0 | 5710 | * the SSL server's (long-term) EC private key. The resulting |
michael@0 | 5711 | * shared secret is treated in the same way as Fortezza's Ks, |
michael@0 | 5712 | * i.e., it is used to wrap the wrapping key. To facilitate |
michael@0 | 5713 | * unwrapping in ssl_UnwrapWrappingKey, we also store all |
michael@0 | 5714 | * relevant info about the ephemeral EC public key in |
michael@0 | 5715 | * wswk.wrappedSymmetricWrappingkey and lay it out as |
michael@0 | 5716 | * described in the ECCWrappedKeyInfo structure. |
michael@0 | 5717 | */ |
michael@0 | 5718 | PORT_Assert(svrPubKey->keyType == ecKey); |
michael@0 | 5719 | if (svrPubKey->keyType != ecKey) { |
michael@0 | 5720 | /* something is wrong in sslsecur.c if this isn't an ecKey */ |
michael@0 | 5721 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 5722 | rv = SECFailure; |
michael@0 | 5723 | goto ec_cleanup; |
michael@0 | 5724 | } |
michael@0 | 5725 | |
michael@0 | 5726 | privWrapKey = SECKEY_CreateECPrivateKey( |
michael@0 | 5727 | &svrPubKey->u.ec.DEREncodedParams, &pubWrapKey, NULL); |
michael@0 | 5728 | if ((privWrapKey == NULL) || (pubWrapKey == NULL)) { |
michael@0 | 5729 | rv = SECFailure; |
michael@0 | 5730 | goto ec_cleanup; |
michael@0 | 5731 | } |
michael@0 | 5732 | |
michael@0 | 5733 | /* Set the key size in bits */ |
michael@0 | 5734 | if (pubWrapKey->u.ec.size == 0) { |
michael@0 | 5735 | pubWrapKey->u.ec.size = SECKEY_PublicKeyStrengthInBits(svrPubKey); |
michael@0 | 5736 | } |
michael@0 | 5737 | |
michael@0 | 5738 | PORT_Assert(pubWrapKey->u.ec.DEREncodedParams.len + |
michael@0 | 5739 | pubWrapKey->u.ec.publicValue.len < MAX_EC_WRAPPED_KEY_BUFLEN); |
michael@0 | 5740 | if (pubWrapKey->u.ec.DEREncodedParams.len + |
michael@0 | 5741 | pubWrapKey->u.ec.publicValue.len >= MAX_EC_WRAPPED_KEY_BUFLEN) { |
michael@0 | 5742 | PORT_SetError(SEC_ERROR_INVALID_KEY); |
michael@0 | 5743 | rv = SECFailure; |
michael@0 | 5744 | goto ec_cleanup; |
michael@0 | 5745 | } |
michael@0 | 5746 | |
michael@0 | 5747 | /* Derive Ks using ECDH */ |
michael@0 | 5748 | Ks = PK11_PubDeriveWithKDF(svrPrivKey, pubWrapKey, PR_FALSE, NULL, |
michael@0 | 5749 | NULL, CKM_ECDH1_DERIVE, masterWrapMech, |
michael@0 | 5750 | CKA_DERIVE, 0, CKD_NULL, NULL, NULL); |
michael@0 | 5751 | if (Ks == NULL) { |
michael@0 | 5752 | rv = SECFailure; |
michael@0 | 5753 | goto ec_cleanup; |
michael@0 | 5754 | } |
michael@0 | 5755 | |
michael@0 | 5756 | ecWrapped = (ECCWrappedKeyInfo *) (wswk.wrappedSymmetricWrappingkey); |
michael@0 | 5757 | ecWrapped->size = pubWrapKey->u.ec.size; |
michael@0 | 5758 | ecWrapped->encodedParamLen = pubWrapKey->u.ec.DEREncodedParams.len; |
michael@0 | 5759 | PORT_Memcpy(ecWrapped->var, pubWrapKey->u.ec.DEREncodedParams.data, |
michael@0 | 5760 | pubWrapKey->u.ec.DEREncodedParams.len); |
michael@0 | 5761 | |
michael@0 | 5762 | ecWrapped->pubValueLen = pubWrapKey->u.ec.publicValue.len; |
michael@0 | 5763 | PORT_Memcpy(ecWrapped->var + ecWrapped->encodedParamLen, |
michael@0 | 5764 | pubWrapKey->u.ec.publicValue.data, |
michael@0 | 5765 | pubWrapKey->u.ec.publicValue.len); |
michael@0 | 5766 | |
michael@0 | 5767 | wrappedKey.len = MAX_EC_WRAPPED_KEY_BUFLEN - |
michael@0 | 5768 | (ecWrapped->encodedParamLen + ecWrapped->pubValueLen); |
michael@0 | 5769 | wrappedKey.data = ecWrapped->var + ecWrapped->encodedParamLen + |
michael@0 | 5770 | ecWrapped->pubValueLen; |
michael@0 | 5771 | |
michael@0 | 5772 | /* wrap symmetricWrapping key with the local Ks */ |
michael@0 | 5773 | rv = PK11_WrapSymKey(masterWrapMech, NULL, Ks, |
michael@0 | 5774 | unwrappedWrappingKey, &wrappedKey); |
michael@0 | 5775 | |
michael@0 | 5776 | if (rv != SECSuccess) { |
michael@0 | 5777 | goto ec_cleanup; |
michael@0 | 5778 | } |
michael@0 | 5779 | |
michael@0 | 5780 | /* Write down the length of wrapped key in the buffer |
michael@0 | 5781 | * wswk.wrappedSymmetricWrappingkey at the appropriate offset |
michael@0 | 5782 | */ |
michael@0 | 5783 | ecWrapped->wrappedKeyLen = wrappedKey.len; |
michael@0 | 5784 | |
michael@0 | 5785 | ec_cleanup: |
michael@0 | 5786 | if (privWrapKey) SECKEY_DestroyPrivateKey(privWrapKey); |
michael@0 | 5787 | if (pubWrapKey) SECKEY_DestroyPublicKey(pubWrapKey); |
michael@0 | 5788 | if (Ks) PK11_FreeSymKey(Ks); |
michael@0 | 5789 | asymWrapMechanism = masterWrapMech; |
michael@0 | 5790 | break; |
michael@0 | 5791 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 5792 | |
michael@0 | 5793 | default: |
michael@0 | 5794 | rv = SECFailure; |
michael@0 | 5795 | break; |
michael@0 | 5796 | } |
michael@0 | 5797 | |
michael@0 | 5798 | if (rv != SECSuccess) { |
michael@0 | 5799 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 5800 | goto loser; |
michael@0 | 5801 | } |
michael@0 | 5802 | |
michael@0 | 5803 | PORT_Assert(asymWrapMechanism != CKM_INVALID_MECHANISM); |
michael@0 | 5804 | |
michael@0 | 5805 | wswk.symWrapMechanism = masterWrapMech; |
michael@0 | 5806 | wswk.symWrapMechIndex = symWrapMechIndex; |
michael@0 | 5807 | wswk.asymWrapMechanism = asymWrapMechanism; |
michael@0 | 5808 | wswk.exchKeyType = exchKeyType; |
michael@0 | 5809 | wswk.wrappedSymKeyLen = wrappedKey.len; |
michael@0 | 5810 | |
michael@0 | 5811 | /* put it on disk. */ |
michael@0 | 5812 | /* If the wrapping key for this KEA type has already been set, |
michael@0 | 5813 | * then abandon the value we just computed and |
michael@0 | 5814 | * use the one we got from the disk. |
michael@0 | 5815 | */ |
michael@0 | 5816 | if (ssl_SetWrappingKey(&wswk)) { |
michael@0 | 5817 | /* somebody beat us to it. The original contents of our wswk |
michael@0 | 5818 | * has been replaced with the content on disk. Now, discard |
michael@0 | 5819 | * the key we just created and unwrap this new one. |
michael@0 | 5820 | */ |
michael@0 | 5821 | PK11_FreeSymKey(unwrappedWrappingKey); |
michael@0 | 5822 | |
michael@0 | 5823 | unwrappedWrappingKey = |
michael@0 | 5824 | ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType, |
michael@0 | 5825 | masterWrapMech, pwArg); |
michael@0 | 5826 | } |
michael@0 | 5827 | |
michael@0 | 5828 | install: |
michael@0 | 5829 | if (unwrappedWrappingKey) { |
michael@0 | 5830 | *pSymWrapKey = PK11_ReferenceSymKey(unwrappedWrappingKey); |
michael@0 | 5831 | } |
michael@0 | 5832 | |
michael@0 | 5833 | loser: |
michael@0 | 5834 | done: |
michael@0 | 5835 | PZ_Unlock(symWrapKeysLock); |
michael@0 | 5836 | return unwrappedWrappingKey; |
michael@0 | 5837 | } |
michael@0 | 5838 | |
michael@0 | 5839 | /* hexEncode hex encodes |length| bytes from |in| and writes it as |length*2| |
michael@0 | 5840 | * bytes to |out|. */ |
michael@0 | 5841 | static void |
michael@0 | 5842 | hexEncode(char *out, const unsigned char *in, unsigned int length) |
michael@0 | 5843 | { |
michael@0 | 5844 | static const char hextable[] = "0123456789abcdef"; |
michael@0 | 5845 | unsigned int i; |
michael@0 | 5846 | |
michael@0 | 5847 | for (i = 0; i < length; i++) { |
michael@0 | 5848 | *(out++) = hextable[in[i] >> 4]; |
michael@0 | 5849 | *(out++) = hextable[in[i] & 15]; |
michael@0 | 5850 | } |
michael@0 | 5851 | } |
michael@0 | 5852 | |
michael@0 | 5853 | /* Called from ssl3_SendClientKeyExchange(). */ |
michael@0 | 5854 | /* Presently, this always uses PKCS11. There is no bypass for this. */ |
michael@0 | 5855 | static SECStatus |
michael@0 | 5856 | sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) |
michael@0 | 5857 | { |
michael@0 | 5858 | PK11SymKey * pms = NULL; |
michael@0 | 5859 | SECStatus rv = SECFailure; |
michael@0 | 5860 | SECItem enc_pms = {siBuffer, NULL, 0}; |
michael@0 | 5861 | PRBool isTLS; |
michael@0 | 5862 | |
michael@0 | 5863 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 5864 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 5865 | |
michael@0 | 5866 | /* Generate the pre-master secret ... */ |
michael@0 | 5867 | ssl_GetSpecWriteLock(ss); |
michael@0 | 5868 | isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 5869 | |
michael@0 | 5870 | pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.pwSpec, NULL); |
michael@0 | 5871 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 5872 | if (pms == NULL) { |
michael@0 | 5873 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 5874 | goto loser; |
michael@0 | 5875 | } |
michael@0 | 5876 | |
michael@0 | 5877 | /* Get the wrapped (encrypted) pre-master secret, enc_pms */ |
michael@0 | 5878 | enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey); |
michael@0 | 5879 | enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len); |
michael@0 | 5880 | if (enc_pms.data == NULL) { |
michael@0 | 5881 | goto loser; /* err set by PORT_Alloc */ |
michael@0 | 5882 | } |
michael@0 | 5883 | |
michael@0 | 5884 | /* wrap pre-master secret in server's public key. */ |
michael@0 | 5885 | rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, pms, &enc_pms); |
michael@0 | 5886 | if (rv != SECSuccess) { |
michael@0 | 5887 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 5888 | goto loser; |
michael@0 | 5889 | } |
michael@0 | 5890 | |
michael@0 | 5891 | if (ssl_keylog_iob) { |
michael@0 | 5892 | SECStatus extractRV = PK11_ExtractKeyValue(pms); |
michael@0 | 5893 | if (extractRV == SECSuccess) { |
michael@0 | 5894 | SECItem * keyData = PK11_GetKeyData(pms); |
michael@0 | 5895 | if (keyData && keyData->data && keyData->len) { |
michael@0 | 5896 | #ifdef TRACE |
michael@0 | 5897 | if (ssl_trace >= 100) { |
michael@0 | 5898 | ssl_PrintBuf(ss, "Pre-Master Secret", |
michael@0 | 5899 | keyData->data, keyData->len); |
michael@0 | 5900 | } |
michael@0 | 5901 | #endif |
michael@0 | 5902 | if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) { |
michael@0 | 5903 | /* https://developer.mozilla.org/en/NSS_Key_Log_Format */ |
michael@0 | 5904 | |
michael@0 | 5905 | /* There could be multiple, concurrent writers to the |
michael@0 | 5906 | * keylog, so we have to do everything in a single call to |
michael@0 | 5907 | * fwrite. */ |
michael@0 | 5908 | char buf[4 + 8*2 + 1 + 48*2 + 1]; |
michael@0 | 5909 | |
michael@0 | 5910 | strcpy(buf, "RSA "); |
michael@0 | 5911 | hexEncode(buf + 4, enc_pms.data, 8); |
michael@0 | 5912 | buf[20] = ' '; |
michael@0 | 5913 | hexEncode(buf + 21, keyData->data, 48); |
michael@0 | 5914 | buf[sizeof(buf) - 1] = '\n'; |
michael@0 | 5915 | |
michael@0 | 5916 | fwrite(buf, sizeof(buf), 1, ssl_keylog_iob); |
michael@0 | 5917 | fflush(ssl_keylog_iob); |
michael@0 | 5918 | } |
michael@0 | 5919 | } |
michael@0 | 5920 | } |
michael@0 | 5921 | } |
michael@0 | 5922 | |
michael@0 | 5923 | rv = ssl3_InitPendingCipherSpec(ss, pms); |
michael@0 | 5924 | PK11_FreeSymKey(pms); pms = NULL; |
michael@0 | 5925 | |
michael@0 | 5926 | if (rv != SECSuccess) { |
michael@0 | 5927 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 5928 | goto loser; |
michael@0 | 5929 | } |
michael@0 | 5930 | |
michael@0 | 5931 | rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, |
michael@0 | 5932 | isTLS ? enc_pms.len + 2 : enc_pms.len); |
michael@0 | 5933 | if (rv != SECSuccess) { |
michael@0 | 5934 | goto loser; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5935 | } |
michael@0 | 5936 | if (isTLS) { |
michael@0 | 5937 | rv = ssl3_AppendHandshakeVariable(ss, enc_pms.data, enc_pms.len, 2); |
michael@0 | 5938 | } else { |
michael@0 | 5939 | rv = ssl3_AppendHandshake(ss, enc_pms.data, enc_pms.len); |
michael@0 | 5940 | } |
michael@0 | 5941 | if (rv != SECSuccess) { |
michael@0 | 5942 | goto loser; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 5943 | } |
michael@0 | 5944 | |
michael@0 | 5945 | rv = SECSuccess; |
michael@0 | 5946 | |
michael@0 | 5947 | loser: |
michael@0 | 5948 | if (enc_pms.data != NULL) { |
michael@0 | 5949 | PORT_Free(enc_pms.data); |
michael@0 | 5950 | } |
michael@0 | 5951 | if (pms != NULL) { |
michael@0 | 5952 | PK11_FreeSymKey(pms); |
michael@0 | 5953 | } |
michael@0 | 5954 | return rv; |
michael@0 | 5955 | } |
michael@0 | 5956 | |
michael@0 | 5957 | /* Called from ssl3_SendClientKeyExchange(). */ |
michael@0 | 5958 | /* Presently, this always uses PKCS11. There is no bypass for this. */ |
michael@0 | 5959 | static SECStatus |
michael@0 | 5960 | sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) |
michael@0 | 5961 | { |
michael@0 | 5962 | PK11SymKey * pms = NULL; |
michael@0 | 5963 | SECStatus rv = SECFailure; |
michael@0 | 5964 | PRBool isTLS; |
michael@0 | 5965 | CK_MECHANISM_TYPE target; |
michael@0 | 5966 | |
michael@0 | 5967 | SECKEYDHParams dhParam; /* DH parameters */ |
michael@0 | 5968 | SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */ |
michael@0 | 5969 | SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */ |
michael@0 | 5970 | |
michael@0 | 5971 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 5972 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 5973 | |
michael@0 | 5974 | isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 5975 | |
michael@0 | 5976 | /* Copy DH parameters from server key */ |
michael@0 | 5977 | |
michael@0 | 5978 | if (svrPubKey->keyType != dhKey) { |
michael@0 | 5979 | PORT_SetError(SEC_ERROR_BAD_KEY); |
michael@0 | 5980 | goto loser; |
michael@0 | 5981 | } |
michael@0 | 5982 | dhParam.prime.data = svrPubKey->u.dh.prime.data; |
michael@0 | 5983 | dhParam.prime.len = svrPubKey->u.dh.prime.len; |
michael@0 | 5984 | dhParam.base.data = svrPubKey->u.dh.base.data; |
michael@0 | 5985 | dhParam.base.len = svrPubKey->u.dh.base.len; |
michael@0 | 5986 | |
michael@0 | 5987 | /* Generate ephemeral DH keypair */ |
michael@0 | 5988 | privKey = SECKEY_CreateDHPrivateKey(&dhParam, &pubKey, NULL); |
michael@0 | 5989 | if (!privKey || !pubKey) { |
michael@0 | 5990 | ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); |
michael@0 | 5991 | rv = SECFailure; |
michael@0 | 5992 | goto loser; |
michael@0 | 5993 | } |
michael@0 | 5994 | PRINT_BUF(50, (ss, "DH public value:", |
michael@0 | 5995 | pubKey->u.dh.publicValue.data, |
michael@0 | 5996 | pubKey->u.dh.publicValue.len)); |
michael@0 | 5997 | |
michael@0 | 5998 | if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; |
michael@0 | 5999 | else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; |
michael@0 | 6000 | |
michael@0 | 6001 | /* Determine the PMS */ |
michael@0 | 6002 | |
michael@0 | 6003 | pms = PK11_PubDerive(privKey, svrPubKey, PR_FALSE, NULL, NULL, |
michael@0 | 6004 | CKM_DH_PKCS_DERIVE, target, CKA_DERIVE, 0, NULL); |
michael@0 | 6005 | |
michael@0 | 6006 | if (pms == NULL) { |
michael@0 | 6007 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 6008 | goto loser; |
michael@0 | 6009 | } |
michael@0 | 6010 | |
michael@0 | 6011 | SECKEY_DestroyPrivateKey(privKey); |
michael@0 | 6012 | privKey = NULL; |
michael@0 | 6013 | |
michael@0 | 6014 | rv = ssl3_InitPendingCipherSpec(ss, pms); |
michael@0 | 6015 | PK11_FreeSymKey(pms); pms = NULL; |
michael@0 | 6016 | |
michael@0 | 6017 | if (rv != SECSuccess) { |
michael@0 | 6018 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 6019 | goto loser; |
michael@0 | 6020 | } |
michael@0 | 6021 | |
michael@0 | 6022 | rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, |
michael@0 | 6023 | pubKey->u.dh.publicValue.len + 2); |
michael@0 | 6024 | if (rv != SECSuccess) { |
michael@0 | 6025 | goto loser; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 6026 | } |
michael@0 | 6027 | rv = ssl3_AppendHandshakeVariable(ss, |
michael@0 | 6028 | pubKey->u.dh.publicValue.data, |
michael@0 | 6029 | pubKey->u.dh.publicValue.len, 2); |
michael@0 | 6030 | SECKEY_DestroyPublicKey(pubKey); |
michael@0 | 6031 | pubKey = NULL; |
michael@0 | 6032 | |
michael@0 | 6033 | if (rv != SECSuccess) { |
michael@0 | 6034 | goto loser; /* err set by ssl3_AppendHandshake* */ |
michael@0 | 6035 | } |
michael@0 | 6036 | |
michael@0 | 6037 | rv = SECSuccess; |
michael@0 | 6038 | |
michael@0 | 6039 | |
michael@0 | 6040 | loser: |
michael@0 | 6041 | |
michael@0 | 6042 | if(pms) PK11_FreeSymKey(pms); |
michael@0 | 6043 | if(privKey) SECKEY_DestroyPrivateKey(privKey); |
michael@0 | 6044 | if(pubKey) SECKEY_DestroyPublicKey(pubKey); |
michael@0 | 6045 | return rv; |
michael@0 | 6046 | } |
michael@0 | 6047 | |
michael@0 | 6048 | |
michael@0 | 6049 | |
michael@0 | 6050 | |
michael@0 | 6051 | |
michael@0 | 6052 | /* Called from ssl3_HandleServerHelloDone(). */ |
michael@0 | 6053 | static SECStatus |
michael@0 | 6054 | ssl3_SendClientKeyExchange(sslSocket *ss) |
michael@0 | 6055 | { |
michael@0 | 6056 | SECKEYPublicKey * serverKey = NULL; |
michael@0 | 6057 | SECStatus rv = SECFailure; |
michael@0 | 6058 | PRBool isTLS; |
michael@0 | 6059 | |
michael@0 | 6060 | SSL_TRC(3, ("%d: SSL3[%d]: send client_key_exchange handshake", |
michael@0 | 6061 | SSL_GETPID(), ss->fd)); |
michael@0 | 6062 | |
michael@0 | 6063 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 6064 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 6065 | |
michael@0 | 6066 | if (ss->sec.peerKey == NULL) { |
michael@0 | 6067 | serverKey = CERT_ExtractPublicKey(ss->sec.peerCert); |
michael@0 | 6068 | if (serverKey == NULL) { |
michael@0 | 6069 | ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); |
michael@0 | 6070 | return SECFailure; |
michael@0 | 6071 | } |
michael@0 | 6072 | } else { |
michael@0 | 6073 | serverKey = ss->sec.peerKey; |
michael@0 | 6074 | ss->sec.peerKey = NULL; /* we're done with it now */ |
michael@0 | 6075 | } |
michael@0 | 6076 | |
michael@0 | 6077 | isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 6078 | /* enforce limits on kea key sizes. */ |
michael@0 | 6079 | if (ss->ssl3.hs.kea_def->is_limited) { |
michael@0 | 6080 | int keyLen = SECKEY_PublicKeyStrength(serverKey); /* bytes */ |
michael@0 | 6081 | |
michael@0 | 6082 | if (keyLen * BPB > ss->ssl3.hs.kea_def->key_size_limit) { |
michael@0 | 6083 | if (isTLS) |
michael@0 | 6084 | (void)SSL3_SendAlert(ss, alert_fatal, export_restriction); |
michael@0 | 6085 | else |
michael@0 | 6086 | (void)ssl3_HandshakeFailure(ss); |
michael@0 | 6087 | PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED); |
michael@0 | 6088 | goto loser; |
michael@0 | 6089 | } |
michael@0 | 6090 | } |
michael@0 | 6091 | |
michael@0 | 6092 | ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType; |
michael@0 | 6093 | ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey); |
michael@0 | 6094 | |
michael@0 | 6095 | switch (ss->ssl3.hs.kea_def->exchKeyType) { |
michael@0 | 6096 | case kt_rsa: |
michael@0 | 6097 | rv = sendRSAClientKeyExchange(ss, serverKey); |
michael@0 | 6098 | break; |
michael@0 | 6099 | |
michael@0 | 6100 | case kt_dh: |
michael@0 | 6101 | rv = sendDHClientKeyExchange(ss, serverKey); |
michael@0 | 6102 | break; |
michael@0 | 6103 | |
michael@0 | 6104 | #ifndef NSS_DISABLE_ECC |
michael@0 | 6105 | case kt_ecdh: |
michael@0 | 6106 | rv = ssl3_SendECDHClientKeyExchange(ss, serverKey); |
michael@0 | 6107 | break; |
michael@0 | 6108 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 6109 | |
michael@0 | 6110 | default: |
michael@0 | 6111 | /* got an unknown or unsupported Key Exchange Algorithm. */ |
michael@0 | 6112 | SEND_ALERT |
michael@0 | 6113 | PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
michael@0 | 6114 | break; |
michael@0 | 6115 | } |
michael@0 | 6116 | |
michael@0 | 6117 | SSL_TRC(3, ("%d: SSL3[%d]: DONE sending client_key_exchange", |
michael@0 | 6118 | SSL_GETPID(), ss->fd)); |
michael@0 | 6119 | |
michael@0 | 6120 | loser: |
michael@0 | 6121 | if (serverKey) |
michael@0 | 6122 | SECKEY_DestroyPublicKey(serverKey); |
michael@0 | 6123 | return rv; /* err code already set. */ |
michael@0 | 6124 | } |
michael@0 | 6125 | |
michael@0 | 6126 | /* Called from ssl3_HandleServerHelloDone(). */ |
michael@0 | 6127 | static SECStatus |
michael@0 | 6128 | ssl3_SendCertificateVerify(sslSocket *ss) |
michael@0 | 6129 | { |
michael@0 | 6130 | SECStatus rv = SECFailure; |
michael@0 | 6131 | PRBool isTLS; |
michael@0 | 6132 | PRBool isTLS12; |
michael@0 | 6133 | SECItem buf = {siBuffer, NULL, 0}; |
michael@0 | 6134 | SSL3Hashes hashes; |
michael@0 | 6135 | KeyType keyType; |
michael@0 | 6136 | unsigned int len; |
michael@0 | 6137 | SSL3SignatureAndHashAlgorithm sigAndHash; |
michael@0 | 6138 | |
michael@0 | 6139 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 6140 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 6141 | |
michael@0 | 6142 | SSL_TRC(3, ("%d: SSL3[%d]: send certificate_verify handshake", |
michael@0 | 6143 | SSL_GETPID(), ss->fd)); |
michael@0 | 6144 | |
michael@0 | 6145 | ssl_GetSpecReadLock(ss); |
michael@0 | 6146 | if (ss->ssl3.hs.hashType == handshake_hash_single && |
michael@0 | 6147 | ss->ssl3.hs.backupHash) { |
michael@0 | 6148 | rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes); |
michael@0 | 6149 | PORT_Assert(!ss->ssl3.hs.backupHash); |
michael@0 | 6150 | } else { |
michael@0 | 6151 | rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); |
michael@0 | 6152 | } |
michael@0 | 6153 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 6154 | if (rv != SECSuccess) { |
michael@0 | 6155 | goto done; /* err code was set by ssl3_ComputeHandshakeHashes */ |
michael@0 | 6156 | } |
michael@0 | 6157 | |
michael@0 | 6158 | isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 6159 | isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 6160 | keyType = ss->ssl3.clientPrivateKey->keyType; |
michael@0 | 6161 | rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS); |
michael@0 | 6162 | if (rv == SECSuccess) { |
michael@0 | 6163 | PK11SlotInfo * slot; |
michael@0 | 6164 | sslSessionID * sid = ss->sec.ci.sid; |
michael@0 | 6165 | |
michael@0 | 6166 | /* Remember the info about the slot that did the signing. |
michael@0 | 6167 | ** Later, when doing an SSL restart handshake, verify this. |
michael@0 | 6168 | ** These calls are mere accessors, and can't fail. |
michael@0 | 6169 | */ |
michael@0 | 6170 | slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey); |
michael@0 | 6171 | sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot); |
michael@0 | 6172 | sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot); |
michael@0 | 6173 | sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot); |
michael@0 | 6174 | sid->u.ssl3.clAuthValid = PR_TRUE; |
michael@0 | 6175 | PK11_FreeSlot(slot); |
michael@0 | 6176 | } |
michael@0 | 6177 | SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
michael@0 | 6178 | ss->ssl3.clientPrivateKey = NULL; |
michael@0 | 6179 | if (rv != SECSuccess) { |
michael@0 | 6180 | goto done; /* err code was set by ssl3_SignHashes */ |
michael@0 | 6181 | } |
michael@0 | 6182 | |
michael@0 | 6183 | len = buf.len + 2 + (isTLS12 ? 2 : 0); |
michael@0 | 6184 | |
michael@0 | 6185 | rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len); |
michael@0 | 6186 | if (rv != SECSuccess) { |
michael@0 | 6187 | goto done; /* error code set by AppendHandshake */ |
michael@0 | 6188 | } |
michael@0 | 6189 | if (isTLS12) { |
michael@0 | 6190 | rv = ssl3_TLSSignatureAlgorithmForKeyType(keyType, |
michael@0 | 6191 | &sigAndHash.sigAlg); |
michael@0 | 6192 | if (rv != SECSuccess) { |
michael@0 | 6193 | goto done; |
michael@0 | 6194 | } |
michael@0 | 6195 | sigAndHash.hashAlg = hashes.hashAlg; |
michael@0 | 6196 | |
michael@0 | 6197 | rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash); |
michael@0 | 6198 | if (rv != SECSuccess) { |
michael@0 | 6199 | goto done; /* err set by AppendHandshake. */ |
michael@0 | 6200 | } |
michael@0 | 6201 | } |
michael@0 | 6202 | rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2); |
michael@0 | 6203 | if (rv != SECSuccess) { |
michael@0 | 6204 | goto done; /* error code set by AppendHandshake */ |
michael@0 | 6205 | } |
michael@0 | 6206 | |
michael@0 | 6207 | done: |
michael@0 | 6208 | if (buf.data) |
michael@0 | 6209 | PORT_Free(buf.data); |
michael@0 | 6210 | return rv; |
michael@0 | 6211 | } |
michael@0 | 6212 | |
michael@0 | 6213 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 6214 | * ssl3 ServerHello message. |
michael@0 | 6215 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 6216 | */ |
michael@0 | 6217 | static SECStatus |
michael@0 | 6218 | ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 6219 | { |
michael@0 | 6220 | sslSessionID *sid = ss->sec.ci.sid; |
michael@0 | 6221 | PRInt32 temp; /* allow for consume number failure */ |
michael@0 | 6222 | PRBool suite_found = PR_FALSE; |
michael@0 | 6223 | int i; |
michael@0 | 6224 | int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; |
michael@0 | 6225 | SECStatus rv; |
michael@0 | 6226 | SECItem sidBytes = {siBuffer, NULL, 0}; |
michael@0 | 6227 | PRBool sid_match; |
michael@0 | 6228 | PRBool isTLS = PR_FALSE; |
michael@0 | 6229 | SSL3AlertDescription desc = illegal_parameter; |
michael@0 | 6230 | SSL3ProtocolVersion version; |
michael@0 | 6231 | |
michael@0 | 6232 | SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake", |
michael@0 | 6233 | SSL_GETPID(), ss->fd)); |
michael@0 | 6234 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 6235 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 6236 | PORT_Assert( ss->ssl3.initialized ); |
michael@0 | 6237 | |
michael@0 | 6238 | if (ss->ssl3.hs.ws != wait_server_hello) { |
michael@0 | 6239 | errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO; |
michael@0 | 6240 | desc = unexpected_message; |
michael@0 | 6241 | goto alert_loser; |
michael@0 | 6242 | } |
michael@0 | 6243 | |
michael@0 | 6244 | /* clean up anything left from previous handshake. */ |
michael@0 | 6245 | if (ss->ssl3.clientCertChain != NULL) { |
michael@0 | 6246 | CERT_DestroyCertificateList(ss->ssl3.clientCertChain); |
michael@0 | 6247 | ss->ssl3.clientCertChain = NULL; |
michael@0 | 6248 | } |
michael@0 | 6249 | if (ss->ssl3.clientCertificate != NULL) { |
michael@0 | 6250 | CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
michael@0 | 6251 | ss->ssl3.clientCertificate = NULL; |
michael@0 | 6252 | } |
michael@0 | 6253 | if (ss->ssl3.clientPrivateKey != NULL) { |
michael@0 | 6254 | SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
michael@0 | 6255 | ss->ssl3.clientPrivateKey = NULL; |
michael@0 | 6256 | } |
michael@0 | 6257 | |
michael@0 | 6258 | temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); |
michael@0 | 6259 | if (temp < 0) { |
michael@0 | 6260 | goto loser; /* alert has been sent */ |
michael@0 | 6261 | } |
michael@0 | 6262 | version = (SSL3ProtocolVersion)temp; |
michael@0 | 6263 | |
michael@0 | 6264 | if (IS_DTLS(ss)) { |
michael@0 | 6265 | /* RFC 4347 required that you verify that the server versions |
michael@0 | 6266 | * match (Section 4.2.1) in the HelloVerifyRequest and the |
michael@0 | 6267 | * ServerHello. |
michael@0 | 6268 | * |
michael@0 | 6269 | * RFC 6347 suggests (SHOULD) that servers always use 1.0 |
michael@0 | 6270 | * in HelloVerifyRequest and allows the versions not to match, |
michael@0 | 6271 | * especially when 1.2 is being negotiated. |
michael@0 | 6272 | * |
michael@0 | 6273 | * Therefore we do not check for matching here. |
michael@0 | 6274 | */ |
michael@0 | 6275 | version = dtls_DTLSVersionToTLSVersion(version); |
michael@0 | 6276 | if (version == 0) { /* Insane version number */ |
michael@0 | 6277 | goto alert_loser; |
michael@0 | 6278 | } |
michael@0 | 6279 | } |
michael@0 | 6280 | |
michael@0 | 6281 | rv = ssl3_NegotiateVersion(ss, version, PR_FALSE); |
michael@0 | 6282 | if (rv != SECSuccess) { |
michael@0 | 6283 | desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version |
michael@0 | 6284 | : handshake_failure; |
michael@0 | 6285 | errCode = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 6286 | goto alert_loser; |
michael@0 | 6287 | } |
michael@0 | 6288 | isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 6289 | |
michael@0 | 6290 | rv = ssl3_InitHandshakeHashes(ss); |
michael@0 | 6291 | if (rv != SECSuccess) { |
michael@0 | 6292 | desc = internal_error; |
michael@0 | 6293 | errCode = PORT_GetError(); |
michael@0 | 6294 | goto alert_loser; |
michael@0 | 6295 | } |
michael@0 | 6296 | |
michael@0 | 6297 | rv = ssl3_ConsumeHandshake( |
michael@0 | 6298 | ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length); |
michael@0 | 6299 | if (rv != SECSuccess) { |
michael@0 | 6300 | goto loser; /* alert has been sent */ |
michael@0 | 6301 | } |
michael@0 | 6302 | |
michael@0 | 6303 | rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length); |
michael@0 | 6304 | if (rv != SECSuccess) { |
michael@0 | 6305 | goto loser; /* alert has been sent */ |
michael@0 | 6306 | } |
michael@0 | 6307 | if (sidBytes.len > SSL3_SESSIONID_BYTES) { |
michael@0 | 6308 | if (isTLS) |
michael@0 | 6309 | desc = decode_error; |
michael@0 | 6310 | goto alert_loser; /* malformed. */ |
michael@0 | 6311 | } |
michael@0 | 6312 | |
michael@0 | 6313 | /* find selected cipher suite in our list. */ |
michael@0 | 6314 | temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); |
michael@0 | 6315 | if (temp < 0) { |
michael@0 | 6316 | goto loser; /* alert has been sent */ |
michael@0 | 6317 | } |
michael@0 | 6318 | ssl3_config_match_init(ss); |
michael@0 | 6319 | for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
michael@0 | 6320 | ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; |
michael@0 | 6321 | if (temp == suite->cipher_suite) { |
michael@0 | 6322 | SSLVersionRange vrange = {ss->version, ss->version}; |
michael@0 | 6323 | if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) { |
michael@0 | 6324 | /* config_match already checks whether the cipher suite is |
michael@0 | 6325 | * acceptable for the version, but the check is repeated here |
michael@0 | 6326 | * in order to give a more precise error code. */ |
michael@0 | 6327 | if (!ssl3_CipherSuiteAllowedForVersionRange(temp, &vrange)) { |
michael@0 | 6328 | desc = handshake_failure; |
michael@0 | 6329 | errCode = SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION; |
michael@0 | 6330 | goto alert_loser; |
michael@0 | 6331 | } |
michael@0 | 6332 | |
michael@0 | 6333 | break; /* failure */ |
michael@0 | 6334 | } |
michael@0 | 6335 | |
michael@0 | 6336 | suite_found = PR_TRUE; |
michael@0 | 6337 | break; /* success */ |
michael@0 | 6338 | } |
michael@0 | 6339 | } |
michael@0 | 6340 | if (!suite_found) { |
michael@0 | 6341 | desc = handshake_failure; |
michael@0 | 6342 | errCode = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 6343 | goto alert_loser; |
michael@0 | 6344 | } |
michael@0 | 6345 | ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)temp; |
michael@0 | 6346 | ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp); |
michael@0 | 6347 | PORT_Assert(ss->ssl3.hs.suite_def); |
michael@0 | 6348 | if (!ss->ssl3.hs.suite_def) { |
michael@0 | 6349 | PORT_SetError(errCode = SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 6350 | goto loser; /* we don't send alerts for our screw-ups. */ |
michael@0 | 6351 | } |
michael@0 | 6352 | |
michael@0 | 6353 | /* find selected compression method in our list. */ |
michael@0 | 6354 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length); |
michael@0 | 6355 | if (temp < 0) { |
michael@0 | 6356 | goto loser; /* alert has been sent */ |
michael@0 | 6357 | } |
michael@0 | 6358 | suite_found = PR_FALSE; |
michael@0 | 6359 | for (i = 0; i < compressionMethodsCount; i++) { |
michael@0 | 6360 | if (temp == compressions[i]) { |
michael@0 | 6361 | if (!compressionEnabled(ss, compressions[i])) { |
michael@0 | 6362 | break; /* failure */ |
michael@0 | 6363 | } |
michael@0 | 6364 | suite_found = PR_TRUE; |
michael@0 | 6365 | break; /* success */ |
michael@0 | 6366 | } |
michael@0 | 6367 | } |
michael@0 | 6368 | if (!suite_found) { |
michael@0 | 6369 | desc = handshake_failure; |
michael@0 | 6370 | errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP; |
michael@0 | 6371 | goto alert_loser; |
michael@0 | 6372 | } |
michael@0 | 6373 | ss->ssl3.hs.compression = (SSLCompressionMethod)temp; |
michael@0 | 6374 | |
michael@0 | 6375 | /* Note that if !isTLS and the extra stuff is not extensions, we |
michael@0 | 6376 | * do NOT goto alert_loser. |
michael@0 | 6377 | * There are some old SSL 3.0 implementations that do send stuff |
michael@0 | 6378 | * after the end of the server hello, and we deliberately ignore |
michael@0 | 6379 | * such stuff in the interest of maximal interoperability (being |
michael@0 | 6380 | * "generous in what you accept"). |
michael@0 | 6381 | * Update: Starting in NSS 3.12.6, we handle the renegotiation_info |
michael@0 | 6382 | * extension in SSL 3.0. |
michael@0 | 6383 | */ |
michael@0 | 6384 | if (length != 0) { |
michael@0 | 6385 | SECItem extensions; |
michael@0 | 6386 | rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length); |
michael@0 | 6387 | if (rv != SECSuccess || length != 0) { |
michael@0 | 6388 | if (isTLS) |
michael@0 | 6389 | goto alert_loser; |
michael@0 | 6390 | } else { |
michael@0 | 6391 | rv = ssl3_HandleHelloExtensions(ss, &extensions.data, |
michael@0 | 6392 | &extensions.len); |
michael@0 | 6393 | if (rv != SECSuccess) |
michael@0 | 6394 | goto alert_loser; |
michael@0 | 6395 | } |
michael@0 | 6396 | } |
michael@0 | 6397 | if ((ss->opt.requireSafeNegotiation || |
michael@0 | 6398 | (ss->firstHsDone && (ss->peerRequestedProtection || |
michael@0 | 6399 | ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN))) && |
michael@0 | 6400 | !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) { |
michael@0 | 6401 | desc = handshake_failure; |
michael@0 | 6402 | errCode = ss->firstHsDone ? SSL_ERROR_RENEGOTIATION_NOT_ALLOWED |
michael@0 | 6403 | : SSL_ERROR_UNSAFE_NEGOTIATION; |
michael@0 | 6404 | goto alert_loser; |
michael@0 | 6405 | } |
michael@0 | 6406 | |
michael@0 | 6407 | /* Any errors after this point are not "malformed" errors. */ |
michael@0 | 6408 | desc = handshake_failure; |
michael@0 | 6409 | |
michael@0 | 6410 | /* we need to call ssl3_SetupPendingCipherSpec here so we can check the |
michael@0 | 6411 | * key exchange algorithm. */ |
michael@0 | 6412 | rv = ssl3_SetupPendingCipherSpec(ss); |
michael@0 | 6413 | if (rv != SECSuccess) { |
michael@0 | 6414 | goto alert_loser; /* error code is set. */ |
michael@0 | 6415 | } |
michael@0 | 6416 | |
michael@0 | 6417 | /* We may or may not have sent a session id, we may get one back or |
michael@0 | 6418 | * not and if so it may match the one we sent. |
michael@0 | 6419 | * Attempt to restore the master secret to see if this is so... |
michael@0 | 6420 | * Don't consider failure to find a matching SID an error. |
michael@0 | 6421 | */ |
michael@0 | 6422 | sid_match = (PRBool)(sidBytes.len > 0 && |
michael@0 | 6423 | sidBytes.len == sid->u.ssl3.sessionIDLength && |
michael@0 | 6424 | !PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len)); |
michael@0 | 6425 | |
michael@0 | 6426 | if (sid_match && |
michael@0 | 6427 | sid->version == ss->version && |
michael@0 | 6428 | sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do { |
michael@0 | 6429 | ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; |
michael@0 | 6430 | |
michael@0 | 6431 | SECItem wrappedMS; /* wrapped master secret. */ |
michael@0 | 6432 | |
michael@0 | 6433 | ss->sec.authAlgorithm = sid->authAlgorithm; |
michael@0 | 6434 | ss->sec.authKeyBits = sid->authKeyBits; |
michael@0 | 6435 | ss->sec.keaType = sid->keaType; |
michael@0 | 6436 | ss->sec.keaKeyBits = sid->keaKeyBits; |
michael@0 | 6437 | |
michael@0 | 6438 | /* 3 cases here: |
michael@0 | 6439 | * a) key is wrapped (implies using PKCS11) |
michael@0 | 6440 | * b) key is unwrapped, but we're still using PKCS11 |
michael@0 | 6441 | * c) key is unwrapped, and we're bypassing PKCS11. |
michael@0 | 6442 | */ |
michael@0 | 6443 | if (sid->u.ssl3.keys.msIsWrapped) { |
michael@0 | 6444 | PK11SlotInfo *slot; |
michael@0 | 6445 | PK11SymKey * wrapKey; /* wrapping key */ |
michael@0 | 6446 | CK_FLAGS keyFlags = 0; |
michael@0 | 6447 | |
michael@0 | 6448 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 6449 | if (ss->opt.bypassPKCS11) { |
michael@0 | 6450 | /* we cannot restart a non-bypass session in a |
michael@0 | 6451 | ** bypass socket. |
michael@0 | 6452 | */ |
michael@0 | 6453 | break; |
michael@0 | 6454 | } |
michael@0 | 6455 | #endif |
michael@0 | 6456 | /* unwrap master secret with PKCS11 */ |
michael@0 | 6457 | slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, |
michael@0 | 6458 | sid->u.ssl3.masterSlotID); |
michael@0 | 6459 | if (slot == NULL) { |
michael@0 | 6460 | break; /* not considered an error. */ |
michael@0 | 6461 | } |
michael@0 | 6462 | if (!PK11_IsPresent(slot)) { |
michael@0 | 6463 | PK11_FreeSlot(slot); |
michael@0 | 6464 | break; /* not considered an error. */ |
michael@0 | 6465 | } |
michael@0 | 6466 | wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, |
michael@0 | 6467 | sid->u.ssl3.masterWrapMech, |
michael@0 | 6468 | sid->u.ssl3.masterWrapSeries, |
michael@0 | 6469 | ss->pkcs11PinArg); |
michael@0 | 6470 | PK11_FreeSlot(slot); |
michael@0 | 6471 | if (wrapKey == NULL) { |
michael@0 | 6472 | break; /* not considered an error. */ |
michael@0 | 6473 | } |
michael@0 | 6474 | |
michael@0 | 6475 | if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ |
michael@0 | 6476 | keyFlags = CKF_SIGN | CKF_VERIFY; |
michael@0 | 6477 | } |
michael@0 | 6478 | |
michael@0 | 6479 | wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 6480 | wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 6481 | pwSpec->master_secret = |
michael@0 | 6482 | PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, |
michael@0 | 6483 | NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, |
michael@0 | 6484 | CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); |
michael@0 | 6485 | errCode = PORT_GetError(); |
michael@0 | 6486 | PK11_FreeSymKey(wrapKey); |
michael@0 | 6487 | if (pwSpec->master_secret == NULL) { |
michael@0 | 6488 | break; /* errorCode set just after call to UnwrapSymKey. */ |
michael@0 | 6489 | } |
michael@0 | 6490 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 6491 | } else if (ss->opt.bypassPKCS11) { |
michael@0 | 6492 | /* MS is not wrapped */ |
michael@0 | 6493 | wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 6494 | wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 6495 | memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); |
michael@0 | 6496 | pwSpec->msItem.data = pwSpec->raw_master_secret; |
michael@0 | 6497 | pwSpec->msItem.len = wrappedMS.len; |
michael@0 | 6498 | #endif |
michael@0 | 6499 | } else { |
michael@0 | 6500 | /* We CAN restart a bypass session in a non-bypass socket. */ |
michael@0 | 6501 | /* need to import the raw master secret to session object */ |
michael@0 | 6502 | PK11SlotInfo *slot = PK11_GetInternalSlot(); |
michael@0 | 6503 | wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 6504 | wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 6505 | pwSpec->master_secret = |
michael@0 | 6506 | PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, |
michael@0 | 6507 | PK11_OriginUnwrap, CKA_ENCRYPT, |
michael@0 | 6508 | &wrappedMS, NULL); |
michael@0 | 6509 | PK11_FreeSlot(slot); |
michael@0 | 6510 | if (pwSpec->master_secret == NULL) { |
michael@0 | 6511 | break; |
michael@0 | 6512 | } |
michael@0 | 6513 | } |
michael@0 | 6514 | |
michael@0 | 6515 | /* Got a Match */ |
michael@0 | 6516 | SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); |
michael@0 | 6517 | |
michael@0 | 6518 | /* If we sent a session ticket, then this is a stateless resume. */ |
michael@0 | 6519 | if (ss->xtnData.sentSessionTicketInClientHello) |
michael@0 | 6520 | SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); |
michael@0 | 6521 | |
michael@0 | 6522 | if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) |
michael@0 | 6523 | ss->ssl3.hs.ws = wait_new_session_ticket; |
michael@0 | 6524 | else |
michael@0 | 6525 | ss->ssl3.hs.ws = wait_change_cipher; |
michael@0 | 6526 | |
michael@0 | 6527 | ss->ssl3.hs.isResuming = PR_TRUE; |
michael@0 | 6528 | |
michael@0 | 6529 | /* copy the peer cert from the SID */ |
michael@0 | 6530 | if (sid->peerCert != NULL) { |
michael@0 | 6531 | ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); |
michael@0 | 6532 | } |
michael@0 | 6533 | |
michael@0 | 6534 | /* NULL value for PMS signifies re-use of the old MS */ |
michael@0 | 6535 | rv = ssl3_InitPendingCipherSpec(ss, NULL); |
michael@0 | 6536 | if (rv != SECSuccess) { |
michael@0 | 6537 | goto alert_loser; /* err code was set */ |
michael@0 | 6538 | } |
michael@0 | 6539 | return SECSuccess; |
michael@0 | 6540 | } while (0); |
michael@0 | 6541 | |
michael@0 | 6542 | if (sid_match) |
michael@0 | 6543 | SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok ); |
michael@0 | 6544 | else |
michael@0 | 6545 | SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_misses ); |
michael@0 | 6546 | |
michael@0 | 6547 | /* throw the old one away */ |
michael@0 | 6548 | sid->u.ssl3.keys.resumable = PR_FALSE; |
michael@0 | 6549 | if (ss->sec.uncache) |
michael@0 | 6550 | (*ss->sec.uncache)(sid); |
michael@0 | 6551 | ssl_FreeSID(sid); |
michael@0 | 6552 | |
michael@0 | 6553 | /* get a new sid */ |
michael@0 | 6554 | ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE); |
michael@0 | 6555 | if (sid == NULL) { |
michael@0 | 6556 | goto alert_loser; /* memory error is set. */ |
michael@0 | 6557 | } |
michael@0 | 6558 | |
michael@0 | 6559 | sid->version = ss->version; |
michael@0 | 6560 | sid->u.ssl3.sessionIDLength = sidBytes.len; |
michael@0 | 6561 | PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len); |
michael@0 | 6562 | |
michael@0 | 6563 | ss->ssl3.hs.isResuming = PR_FALSE; |
michael@0 | 6564 | ss->ssl3.hs.ws = wait_server_cert; |
michael@0 | 6565 | return SECSuccess; |
michael@0 | 6566 | |
michael@0 | 6567 | alert_loser: |
michael@0 | 6568 | (void)SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 6569 | |
michael@0 | 6570 | loser: |
michael@0 | 6571 | errCode = ssl_MapLowLevelError(errCode); |
michael@0 | 6572 | return SECFailure; |
michael@0 | 6573 | } |
michael@0 | 6574 | |
michael@0 | 6575 | /* ssl3_BigIntGreaterThanOne returns true iff |mpint|, taken as an unsigned, |
michael@0 | 6576 | * big-endian integer is > 1 */ |
michael@0 | 6577 | static PRBool |
michael@0 | 6578 | ssl3_BigIntGreaterThanOne(const SECItem* mpint) { |
michael@0 | 6579 | unsigned char firstNonZeroByte = 0; |
michael@0 | 6580 | unsigned int i; |
michael@0 | 6581 | |
michael@0 | 6582 | for (i = 0; i < mpint->len; i++) { |
michael@0 | 6583 | if (mpint->data[i]) { |
michael@0 | 6584 | firstNonZeroByte = mpint->data[i]; |
michael@0 | 6585 | break; |
michael@0 | 6586 | } |
michael@0 | 6587 | } |
michael@0 | 6588 | |
michael@0 | 6589 | if (firstNonZeroByte == 0) |
michael@0 | 6590 | return PR_FALSE; |
michael@0 | 6591 | if (firstNonZeroByte > 1) |
michael@0 | 6592 | return PR_TRUE; |
michael@0 | 6593 | |
michael@0 | 6594 | /* firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte |
michael@0 | 6595 | * is followed by another byte. */ |
michael@0 | 6596 | return (i < mpint->len - 1); |
michael@0 | 6597 | } |
michael@0 | 6598 | |
michael@0 | 6599 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 6600 | * ssl3 ServerKeyExchange message. |
michael@0 | 6601 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 6602 | */ |
michael@0 | 6603 | static SECStatus |
michael@0 | 6604 | ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 6605 | { |
michael@0 | 6606 | PLArenaPool * arena = NULL; |
michael@0 | 6607 | SECKEYPublicKey *peerKey = NULL; |
michael@0 | 6608 | PRBool isTLS, isTLS12; |
michael@0 | 6609 | SECStatus rv; |
michael@0 | 6610 | int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH; |
michael@0 | 6611 | SSL3AlertDescription desc = illegal_parameter; |
michael@0 | 6612 | SSL3Hashes hashes; |
michael@0 | 6613 | SECItem signature = {siBuffer, NULL, 0}; |
michael@0 | 6614 | SSL3SignatureAndHashAlgorithm sigAndHash; |
michael@0 | 6615 | |
michael@0 | 6616 | sigAndHash.hashAlg = SEC_OID_UNKNOWN; |
michael@0 | 6617 | |
michael@0 | 6618 | SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake", |
michael@0 | 6619 | SSL_GETPID(), ss->fd)); |
michael@0 | 6620 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 6621 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 6622 | |
michael@0 | 6623 | if (ss->ssl3.hs.ws != wait_server_key && |
michael@0 | 6624 | ss->ssl3.hs.ws != wait_server_cert) { |
michael@0 | 6625 | errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH; |
michael@0 | 6626 | desc = unexpected_message; |
michael@0 | 6627 | goto alert_loser; |
michael@0 | 6628 | } |
michael@0 | 6629 | if (ss->sec.peerCert == NULL) { |
michael@0 | 6630 | errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH; |
michael@0 | 6631 | desc = unexpected_message; |
michael@0 | 6632 | goto alert_loser; |
michael@0 | 6633 | } |
michael@0 | 6634 | |
michael@0 | 6635 | isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 6636 | isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 6637 | |
michael@0 | 6638 | switch (ss->ssl3.hs.kea_def->exchKeyType) { |
michael@0 | 6639 | |
michael@0 | 6640 | case kt_rsa: { |
michael@0 | 6641 | SECItem modulus = {siBuffer, NULL, 0}; |
michael@0 | 6642 | SECItem exponent = {siBuffer, NULL, 0}; |
michael@0 | 6643 | |
michael@0 | 6644 | rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length); |
michael@0 | 6645 | if (rv != SECSuccess) { |
michael@0 | 6646 | goto loser; /* malformed. */ |
michael@0 | 6647 | } |
michael@0 | 6648 | rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length); |
michael@0 | 6649 | if (rv != SECSuccess) { |
michael@0 | 6650 | goto loser; /* malformed. */ |
michael@0 | 6651 | } |
michael@0 | 6652 | if (isTLS12) { |
michael@0 | 6653 | rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length, |
michael@0 | 6654 | &sigAndHash); |
michael@0 | 6655 | if (rv != SECSuccess) { |
michael@0 | 6656 | goto loser; /* malformed or unsupported. */ |
michael@0 | 6657 | } |
michael@0 | 6658 | rv = ssl3_CheckSignatureAndHashAlgorithmConsistency( |
michael@0 | 6659 | &sigAndHash, ss->sec.peerCert); |
michael@0 | 6660 | if (rv != SECSuccess) { |
michael@0 | 6661 | goto loser; |
michael@0 | 6662 | } |
michael@0 | 6663 | } |
michael@0 | 6664 | rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); |
michael@0 | 6665 | if (rv != SECSuccess) { |
michael@0 | 6666 | goto loser; /* malformed. */ |
michael@0 | 6667 | } |
michael@0 | 6668 | if (length != 0) { |
michael@0 | 6669 | if (isTLS) |
michael@0 | 6670 | desc = decode_error; |
michael@0 | 6671 | goto alert_loser; /* malformed. */ |
michael@0 | 6672 | } |
michael@0 | 6673 | |
michael@0 | 6674 | /* failures after this point are not malformed handshakes. */ |
michael@0 | 6675 | /* TLS: send decrypt_error if signature failed. */ |
michael@0 | 6676 | desc = isTLS ? decrypt_error : handshake_failure; |
michael@0 | 6677 | |
michael@0 | 6678 | /* |
michael@0 | 6679 | * check to make sure the hash is signed by right guy |
michael@0 | 6680 | */ |
michael@0 | 6681 | rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, modulus, exponent, |
michael@0 | 6682 | &ss->ssl3.hs.client_random, |
michael@0 | 6683 | &ss->ssl3.hs.server_random, |
michael@0 | 6684 | &hashes, ss->opt.bypassPKCS11); |
michael@0 | 6685 | if (rv != SECSuccess) { |
michael@0 | 6686 | errCode = |
michael@0 | 6687 | ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 6688 | goto alert_loser; |
michael@0 | 6689 | } |
michael@0 | 6690 | rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, |
michael@0 | 6691 | isTLS, ss->pkcs11PinArg); |
michael@0 | 6692 | if (rv != SECSuccess) { |
michael@0 | 6693 | errCode = |
michael@0 | 6694 | ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 6695 | goto alert_loser; |
michael@0 | 6696 | } |
michael@0 | 6697 | |
michael@0 | 6698 | /* |
michael@0 | 6699 | * we really need to build a new key here because we can no longer |
michael@0 | 6700 | * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate |
michael@0 | 6701 | * pkcs11 slots and ID's. |
michael@0 | 6702 | */ |
michael@0 | 6703 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 6704 | if (arena == NULL) { |
michael@0 | 6705 | goto no_memory; |
michael@0 | 6706 | } |
michael@0 | 6707 | |
michael@0 | 6708 | peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); |
michael@0 | 6709 | if (peerKey == NULL) { |
michael@0 | 6710 | PORT_FreeArena(arena, PR_FALSE); |
michael@0 | 6711 | goto no_memory; |
michael@0 | 6712 | } |
michael@0 | 6713 | |
michael@0 | 6714 | peerKey->arena = arena; |
michael@0 | 6715 | peerKey->keyType = rsaKey; |
michael@0 | 6716 | peerKey->pkcs11Slot = NULL; |
michael@0 | 6717 | peerKey->pkcs11ID = CK_INVALID_HANDLE; |
michael@0 | 6718 | if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) || |
michael@0 | 6719 | SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent)) |
michael@0 | 6720 | { |
michael@0 | 6721 | PORT_FreeArena(arena, PR_FALSE); |
michael@0 | 6722 | goto no_memory; |
michael@0 | 6723 | } |
michael@0 | 6724 | ss->sec.peerKey = peerKey; |
michael@0 | 6725 | ss->ssl3.hs.ws = wait_cert_request; |
michael@0 | 6726 | return SECSuccess; |
michael@0 | 6727 | } |
michael@0 | 6728 | |
michael@0 | 6729 | case kt_dh: { |
michael@0 | 6730 | SECItem dh_p = {siBuffer, NULL, 0}; |
michael@0 | 6731 | SECItem dh_g = {siBuffer, NULL, 0}; |
michael@0 | 6732 | SECItem dh_Ys = {siBuffer, NULL, 0}; |
michael@0 | 6733 | |
michael@0 | 6734 | rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length); |
michael@0 | 6735 | if (rv != SECSuccess) { |
michael@0 | 6736 | goto loser; /* malformed. */ |
michael@0 | 6737 | } |
michael@0 | 6738 | if (dh_p.len < 512/8) { |
michael@0 | 6739 | errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY; |
michael@0 | 6740 | goto alert_loser; |
michael@0 | 6741 | } |
michael@0 | 6742 | rv = ssl3_ConsumeHandshakeVariable(ss, &dh_g, 2, &b, &length); |
michael@0 | 6743 | if (rv != SECSuccess) { |
michael@0 | 6744 | goto loser; /* malformed. */ |
michael@0 | 6745 | } |
michael@0 | 6746 | if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_g)) |
michael@0 | 6747 | goto alert_loser; |
michael@0 | 6748 | rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length); |
michael@0 | 6749 | if (rv != SECSuccess) { |
michael@0 | 6750 | goto loser; /* malformed. */ |
michael@0 | 6751 | } |
michael@0 | 6752 | if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys)) |
michael@0 | 6753 | goto alert_loser; |
michael@0 | 6754 | if (isTLS12) { |
michael@0 | 6755 | rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length, |
michael@0 | 6756 | &sigAndHash); |
michael@0 | 6757 | if (rv != SECSuccess) { |
michael@0 | 6758 | goto loser; /* malformed or unsupported. */ |
michael@0 | 6759 | } |
michael@0 | 6760 | rv = ssl3_CheckSignatureAndHashAlgorithmConsistency( |
michael@0 | 6761 | &sigAndHash, ss->sec.peerCert); |
michael@0 | 6762 | if (rv != SECSuccess) { |
michael@0 | 6763 | goto loser; |
michael@0 | 6764 | } |
michael@0 | 6765 | } |
michael@0 | 6766 | rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); |
michael@0 | 6767 | if (rv != SECSuccess) { |
michael@0 | 6768 | goto loser; /* malformed. */ |
michael@0 | 6769 | } |
michael@0 | 6770 | if (length != 0) { |
michael@0 | 6771 | if (isTLS) |
michael@0 | 6772 | desc = decode_error; |
michael@0 | 6773 | goto alert_loser; /* malformed. */ |
michael@0 | 6774 | } |
michael@0 | 6775 | |
michael@0 | 6776 | PRINT_BUF(60, (NULL, "Server DH p", dh_p.data, dh_p.len)); |
michael@0 | 6777 | PRINT_BUF(60, (NULL, "Server DH g", dh_g.data, dh_g.len)); |
michael@0 | 6778 | PRINT_BUF(60, (NULL, "Server DH Ys", dh_Ys.data, dh_Ys.len)); |
michael@0 | 6779 | |
michael@0 | 6780 | /* failures after this point are not malformed handshakes. */ |
michael@0 | 6781 | /* TLS: send decrypt_error if signature failed. */ |
michael@0 | 6782 | desc = isTLS ? decrypt_error : handshake_failure; |
michael@0 | 6783 | |
michael@0 | 6784 | /* |
michael@0 | 6785 | * check to make sure the hash is signed by right guy |
michael@0 | 6786 | */ |
michael@0 | 6787 | rv = ssl3_ComputeDHKeyHash(sigAndHash.hashAlg, dh_p, dh_g, dh_Ys, |
michael@0 | 6788 | &ss->ssl3.hs.client_random, |
michael@0 | 6789 | &ss->ssl3.hs.server_random, |
michael@0 | 6790 | &hashes, ss->opt.bypassPKCS11); |
michael@0 | 6791 | if (rv != SECSuccess) { |
michael@0 | 6792 | errCode = |
michael@0 | 6793 | ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 6794 | goto alert_loser; |
michael@0 | 6795 | } |
michael@0 | 6796 | rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, |
michael@0 | 6797 | isTLS, ss->pkcs11PinArg); |
michael@0 | 6798 | if (rv != SECSuccess) { |
michael@0 | 6799 | errCode = |
michael@0 | 6800 | ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 6801 | goto alert_loser; |
michael@0 | 6802 | } |
michael@0 | 6803 | |
michael@0 | 6804 | /* |
michael@0 | 6805 | * we really need to build a new key here because we can no longer |
michael@0 | 6806 | * ignore calling SECKEY_DestroyPublicKey. Using the key may allocate |
michael@0 | 6807 | * pkcs11 slots and ID's. |
michael@0 | 6808 | */ |
michael@0 | 6809 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 6810 | if (arena == NULL) { |
michael@0 | 6811 | goto no_memory; |
michael@0 | 6812 | } |
michael@0 | 6813 | |
michael@0 | 6814 | ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); |
michael@0 | 6815 | if (peerKey == NULL) { |
michael@0 | 6816 | goto no_memory; |
michael@0 | 6817 | } |
michael@0 | 6818 | |
michael@0 | 6819 | peerKey->arena = arena; |
michael@0 | 6820 | peerKey->keyType = dhKey; |
michael@0 | 6821 | peerKey->pkcs11Slot = NULL; |
michael@0 | 6822 | peerKey->pkcs11ID = CK_INVALID_HANDLE; |
michael@0 | 6823 | |
michael@0 | 6824 | if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) || |
michael@0 | 6825 | SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) || |
michael@0 | 6826 | SECITEM_CopyItem(arena, &peerKey->u.dh.publicValue, &dh_Ys)) |
michael@0 | 6827 | { |
michael@0 | 6828 | PORT_FreeArena(arena, PR_FALSE); |
michael@0 | 6829 | goto no_memory; |
michael@0 | 6830 | } |
michael@0 | 6831 | ss->sec.peerKey = peerKey; |
michael@0 | 6832 | ss->ssl3.hs.ws = wait_cert_request; |
michael@0 | 6833 | return SECSuccess; |
michael@0 | 6834 | } |
michael@0 | 6835 | |
michael@0 | 6836 | #ifndef NSS_DISABLE_ECC |
michael@0 | 6837 | case kt_ecdh: |
michael@0 | 6838 | rv = ssl3_HandleECDHServerKeyExchange(ss, b, length); |
michael@0 | 6839 | return rv; |
michael@0 | 6840 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 6841 | |
michael@0 | 6842 | default: |
michael@0 | 6843 | desc = handshake_failure; |
michael@0 | 6844 | errCode = SEC_ERROR_UNSUPPORTED_KEYALG; |
michael@0 | 6845 | break; /* goto alert_loser; */ |
michael@0 | 6846 | } |
michael@0 | 6847 | |
michael@0 | 6848 | alert_loser: |
michael@0 | 6849 | (void)SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 6850 | loser: |
michael@0 | 6851 | PORT_SetError( errCode ); |
michael@0 | 6852 | return SECFailure; |
michael@0 | 6853 | |
michael@0 | 6854 | no_memory: /* no-memory error has already been set. */ |
michael@0 | 6855 | ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 6856 | return SECFailure; |
michael@0 | 6857 | } |
michael@0 | 6858 | |
michael@0 | 6859 | |
michael@0 | 6860 | /* |
michael@0 | 6861 | * Returns the TLS signature algorithm for the client authentication key and |
michael@0 | 6862 | * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes. |
michael@0 | 6863 | */ |
michael@0 | 6864 | static SECStatus |
michael@0 | 6865 | ssl3_ExtractClientKeyInfo(sslSocket *ss, |
michael@0 | 6866 | TLSSignatureAlgorithm *sigAlg, |
michael@0 | 6867 | PRBool *preferSha1) |
michael@0 | 6868 | { |
michael@0 | 6869 | SECStatus rv = SECSuccess; |
michael@0 | 6870 | SECKEYPublicKey *pubk; |
michael@0 | 6871 | |
michael@0 | 6872 | pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate); |
michael@0 | 6873 | if (pubk == NULL) { |
michael@0 | 6874 | rv = SECFailure; |
michael@0 | 6875 | goto done; |
michael@0 | 6876 | } |
michael@0 | 6877 | |
michael@0 | 6878 | rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg); |
michael@0 | 6879 | if (rv != SECSuccess) { |
michael@0 | 6880 | goto done; |
michael@0 | 6881 | } |
michael@0 | 6882 | |
michael@0 | 6883 | /* If the key is a 1024-bit RSA or DSA key, assume conservatively that |
michael@0 | 6884 | * it may be unable to sign SHA-256 hashes. This is the case for older |
michael@0 | 6885 | * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and |
michael@0 | 6886 | * older, DSA key size is at most 1024 bits and the hash function must |
michael@0 | 6887 | * be SHA-1. |
michael@0 | 6888 | */ |
michael@0 | 6889 | if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) { |
michael@0 | 6890 | *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128; |
michael@0 | 6891 | } else { |
michael@0 | 6892 | *preferSha1 = PR_FALSE; |
michael@0 | 6893 | } |
michael@0 | 6894 | |
michael@0 | 6895 | done: |
michael@0 | 6896 | if (pubk) |
michael@0 | 6897 | SECKEY_DestroyPublicKey(pubk); |
michael@0 | 6898 | return rv; |
michael@0 | 6899 | } |
michael@0 | 6900 | |
michael@0 | 6901 | /* Destroys the backup handshake hash context if we don't need it. Note that |
michael@0 | 6902 | * this function selects the hash algorithm for client authentication |
michael@0 | 6903 | * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash |
michael@0 | 6904 | * to determine whether to use SHA-1 or SHA-256. */ |
michael@0 | 6905 | static void |
michael@0 | 6906 | ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss, |
michael@0 | 6907 | const SECItem *algorithms) |
michael@0 | 6908 | { |
michael@0 | 6909 | SECStatus rv; |
michael@0 | 6910 | TLSSignatureAlgorithm sigAlg; |
michael@0 | 6911 | PRBool preferSha1; |
michael@0 | 6912 | PRBool supportsSha1 = PR_FALSE; |
michael@0 | 6913 | PRBool supportsSha256 = PR_FALSE; |
michael@0 | 6914 | PRBool needBackupHash = PR_FALSE; |
michael@0 | 6915 | unsigned int i; |
michael@0 | 6916 | |
michael@0 | 6917 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 6918 | /* Backup handshake hash is not supported in PKCS #11 bypass mode. */ |
michael@0 | 6919 | if (ss->opt.bypassPKCS11) { |
michael@0 | 6920 | PORT_Assert(!ss->ssl3.hs.backupHash); |
michael@0 | 6921 | return; |
michael@0 | 6922 | } |
michael@0 | 6923 | #endif |
michael@0 | 6924 | PORT_Assert(ss->ssl3.hs.backupHash); |
michael@0 | 6925 | |
michael@0 | 6926 | /* Determine the key's signature algorithm and whether it prefers SHA-1. */ |
michael@0 | 6927 | rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1); |
michael@0 | 6928 | if (rv != SECSuccess) { |
michael@0 | 6929 | goto done; |
michael@0 | 6930 | } |
michael@0 | 6931 | |
michael@0 | 6932 | /* Determine the server's hash support for that signature algorithm. */ |
michael@0 | 6933 | for (i = 0; i < algorithms->len; i += 2) { |
michael@0 | 6934 | if (algorithms->data[i+1] == sigAlg) { |
michael@0 | 6935 | if (algorithms->data[i] == tls_hash_sha1) { |
michael@0 | 6936 | supportsSha1 = PR_TRUE; |
michael@0 | 6937 | } else if (algorithms->data[i] == tls_hash_sha256) { |
michael@0 | 6938 | supportsSha256 = PR_TRUE; |
michael@0 | 6939 | } |
michael@0 | 6940 | } |
michael@0 | 6941 | } |
michael@0 | 6942 | |
michael@0 | 6943 | /* If either the server does not support SHA-256 or the client key prefers |
michael@0 | 6944 | * SHA-1, leave the backup hash. */ |
michael@0 | 6945 | if (supportsSha1 && (preferSha1 || !supportsSha256)) { |
michael@0 | 6946 | needBackupHash = PR_TRUE; |
michael@0 | 6947 | } |
michael@0 | 6948 | |
michael@0 | 6949 | done: |
michael@0 | 6950 | if (!needBackupHash) { |
michael@0 | 6951 | PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE); |
michael@0 | 6952 | ss->ssl3.hs.backupHash = NULL; |
michael@0 | 6953 | } |
michael@0 | 6954 | } |
michael@0 | 6955 | |
michael@0 | 6956 | typedef struct dnameNode { |
michael@0 | 6957 | struct dnameNode *next; |
michael@0 | 6958 | SECItem name; |
michael@0 | 6959 | } dnameNode; |
michael@0 | 6960 | |
michael@0 | 6961 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 6962 | * ssl3 Certificate Request message. |
michael@0 | 6963 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 6964 | */ |
michael@0 | 6965 | static SECStatus |
michael@0 | 6966 | ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 6967 | { |
michael@0 | 6968 | PLArenaPool * arena = NULL; |
michael@0 | 6969 | dnameNode * node; |
michael@0 | 6970 | PRInt32 remaining; |
michael@0 | 6971 | PRBool isTLS = PR_FALSE; |
michael@0 | 6972 | PRBool isTLS12 = PR_FALSE; |
michael@0 | 6973 | int i; |
michael@0 | 6974 | int errCode = SSL_ERROR_RX_MALFORMED_CERT_REQUEST; |
michael@0 | 6975 | int nnames = 0; |
michael@0 | 6976 | SECStatus rv; |
michael@0 | 6977 | SSL3AlertDescription desc = illegal_parameter; |
michael@0 | 6978 | SECItem cert_types = {siBuffer, NULL, 0}; |
michael@0 | 6979 | SECItem algorithms = {siBuffer, NULL, 0}; |
michael@0 | 6980 | CERTDistNames ca_list; |
michael@0 | 6981 | |
michael@0 | 6982 | SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake", |
michael@0 | 6983 | SSL_GETPID(), ss->fd)); |
michael@0 | 6984 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 6985 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 6986 | |
michael@0 | 6987 | if (ss->ssl3.hs.ws != wait_cert_request && |
michael@0 | 6988 | ss->ssl3.hs.ws != wait_server_key) { |
michael@0 | 6989 | desc = unexpected_message; |
michael@0 | 6990 | errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST; |
michael@0 | 6991 | goto alert_loser; |
michael@0 | 6992 | } |
michael@0 | 6993 | |
michael@0 | 6994 | PORT_Assert(ss->ssl3.clientCertChain == NULL); |
michael@0 | 6995 | PORT_Assert(ss->ssl3.clientCertificate == NULL); |
michael@0 | 6996 | PORT_Assert(ss->ssl3.clientPrivateKey == NULL); |
michael@0 | 6997 | |
michael@0 | 6998 | isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 6999 | isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 7000 | rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length); |
michael@0 | 7001 | if (rv != SECSuccess) |
michael@0 | 7002 | goto loser; /* malformed, alert has been sent */ |
michael@0 | 7003 | |
michael@0 | 7004 | if (isTLS12) { |
michael@0 | 7005 | rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &b, &length); |
michael@0 | 7006 | if (rv != SECSuccess) |
michael@0 | 7007 | goto loser; /* malformed, alert has been sent */ |
michael@0 | 7008 | /* An empty or odd-length value is invalid. |
michael@0 | 7009 | * SignatureAndHashAlgorithm |
michael@0 | 7010 | * supported_signature_algorithms<2..2^16-2>; |
michael@0 | 7011 | */ |
michael@0 | 7012 | if (algorithms.len == 0 || (algorithms.len & 1) != 0) |
michael@0 | 7013 | goto alert_loser; |
michael@0 | 7014 | } |
michael@0 | 7015 | |
michael@0 | 7016 | arena = ca_list.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 7017 | if (arena == NULL) |
michael@0 | 7018 | goto no_mem; |
michael@0 | 7019 | |
michael@0 | 7020 | remaining = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); |
michael@0 | 7021 | if (remaining < 0) |
michael@0 | 7022 | goto loser; /* malformed, alert has been sent */ |
michael@0 | 7023 | |
michael@0 | 7024 | if ((PRUint32)remaining > length) |
michael@0 | 7025 | goto alert_loser; |
michael@0 | 7026 | |
michael@0 | 7027 | ca_list.head = node = PORT_ArenaZNew(arena, dnameNode); |
michael@0 | 7028 | if (node == NULL) |
michael@0 | 7029 | goto no_mem; |
michael@0 | 7030 | |
michael@0 | 7031 | while (remaining > 0) { |
michael@0 | 7032 | PRInt32 len; |
michael@0 | 7033 | |
michael@0 | 7034 | if (remaining < 2) |
michael@0 | 7035 | goto alert_loser; /* malformed */ |
michael@0 | 7036 | |
michael@0 | 7037 | node->name.len = len = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); |
michael@0 | 7038 | if (len <= 0) |
michael@0 | 7039 | goto loser; /* malformed, alert has been sent */ |
michael@0 | 7040 | |
michael@0 | 7041 | remaining -= 2; |
michael@0 | 7042 | if (remaining < len) |
michael@0 | 7043 | goto alert_loser; /* malformed */ |
michael@0 | 7044 | |
michael@0 | 7045 | node->name.data = b; |
michael@0 | 7046 | b += len; |
michael@0 | 7047 | length -= len; |
michael@0 | 7048 | remaining -= len; |
michael@0 | 7049 | nnames++; |
michael@0 | 7050 | if (remaining <= 0) |
michael@0 | 7051 | break; /* success */ |
michael@0 | 7052 | |
michael@0 | 7053 | node->next = PORT_ArenaZNew(arena, dnameNode); |
michael@0 | 7054 | node = node->next; |
michael@0 | 7055 | if (node == NULL) |
michael@0 | 7056 | goto no_mem; |
michael@0 | 7057 | } |
michael@0 | 7058 | |
michael@0 | 7059 | ca_list.nnames = nnames; |
michael@0 | 7060 | ca_list.names = PORT_ArenaNewArray(arena, SECItem, nnames); |
michael@0 | 7061 | if (nnames > 0 && ca_list.names == NULL) |
michael@0 | 7062 | goto no_mem; |
michael@0 | 7063 | |
michael@0 | 7064 | for(i = 0, node = (dnameNode*)ca_list.head; |
michael@0 | 7065 | i < nnames; |
michael@0 | 7066 | i++, node = node->next) { |
michael@0 | 7067 | ca_list.names[i] = node->name; |
michael@0 | 7068 | } |
michael@0 | 7069 | |
michael@0 | 7070 | if (length != 0) |
michael@0 | 7071 | goto alert_loser; /* malformed */ |
michael@0 | 7072 | |
michael@0 | 7073 | desc = no_certificate; |
michael@0 | 7074 | ss->ssl3.hs.ws = wait_hello_done; |
michael@0 | 7075 | |
michael@0 | 7076 | if (ss->getClientAuthData != NULL) { |
michael@0 | 7077 | /* XXX Should pass cert_types and algorithms in this call!! */ |
michael@0 | 7078 | rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg, |
michael@0 | 7079 | ss->fd, &ca_list, |
michael@0 | 7080 | &ss->ssl3.clientCertificate, |
michael@0 | 7081 | &ss->ssl3.clientPrivateKey); |
michael@0 | 7082 | } else { |
michael@0 | 7083 | rv = SECFailure; /* force it to send a no_certificate alert */ |
michael@0 | 7084 | } |
michael@0 | 7085 | switch (rv) { |
michael@0 | 7086 | case SECWouldBlock: /* getClientAuthData has put up a dialog box. */ |
michael@0 | 7087 | ssl3_SetAlwaysBlock(ss); |
michael@0 | 7088 | break; /* not an error */ |
michael@0 | 7089 | |
michael@0 | 7090 | case SECSuccess: |
michael@0 | 7091 | /* check what the callback function returned */ |
michael@0 | 7092 | if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { |
michael@0 | 7093 | /* we are missing either the key or cert */ |
michael@0 | 7094 | if (ss->ssl3.clientCertificate) { |
michael@0 | 7095 | /* got a cert, but no key - free it */ |
michael@0 | 7096 | CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
michael@0 | 7097 | ss->ssl3.clientCertificate = NULL; |
michael@0 | 7098 | } |
michael@0 | 7099 | if (ss->ssl3.clientPrivateKey) { |
michael@0 | 7100 | /* got a key, but no cert - free it */ |
michael@0 | 7101 | SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
michael@0 | 7102 | ss->ssl3.clientPrivateKey = NULL; |
michael@0 | 7103 | } |
michael@0 | 7104 | goto send_no_certificate; |
michael@0 | 7105 | } |
michael@0 | 7106 | /* Setting ssl3.clientCertChain non-NULL will cause |
michael@0 | 7107 | * ssl3_HandleServerHelloDone to call SendCertificate. |
michael@0 | 7108 | */ |
michael@0 | 7109 | ss->ssl3.clientCertChain = CERT_CertChainFromCert( |
michael@0 | 7110 | ss->ssl3.clientCertificate, |
michael@0 | 7111 | certUsageSSLClient, PR_FALSE); |
michael@0 | 7112 | if (ss->ssl3.clientCertChain == NULL) { |
michael@0 | 7113 | CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
michael@0 | 7114 | ss->ssl3.clientCertificate = NULL; |
michael@0 | 7115 | SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
michael@0 | 7116 | ss->ssl3.clientPrivateKey = NULL; |
michael@0 | 7117 | goto send_no_certificate; |
michael@0 | 7118 | } |
michael@0 | 7119 | if (ss->ssl3.hs.hashType == handshake_hash_single) { |
michael@0 | 7120 | ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms); |
michael@0 | 7121 | } |
michael@0 | 7122 | break; /* not an error */ |
michael@0 | 7123 | |
michael@0 | 7124 | case SECFailure: |
michael@0 | 7125 | default: |
michael@0 | 7126 | send_no_certificate: |
michael@0 | 7127 | if (isTLS) { |
michael@0 | 7128 | ss->ssl3.sendEmptyCert = PR_TRUE; |
michael@0 | 7129 | } else { |
michael@0 | 7130 | (void)SSL3_SendAlert(ss, alert_warning, no_certificate); |
michael@0 | 7131 | } |
michael@0 | 7132 | rv = SECSuccess; |
michael@0 | 7133 | break; |
michael@0 | 7134 | } |
michael@0 | 7135 | goto done; |
michael@0 | 7136 | |
michael@0 | 7137 | no_mem: |
michael@0 | 7138 | rv = SECFailure; |
michael@0 | 7139 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
michael@0 | 7140 | goto done; |
michael@0 | 7141 | |
michael@0 | 7142 | alert_loser: |
michael@0 | 7143 | if (isTLS && desc == illegal_parameter) |
michael@0 | 7144 | desc = decode_error; |
michael@0 | 7145 | (void)SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 7146 | loser: |
michael@0 | 7147 | PORT_SetError(errCode); |
michael@0 | 7148 | rv = SECFailure; |
michael@0 | 7149 | done: |
michael@0 | 7150 | if (arena != NULL) |
michael@0 | 7151 | PORT_FreeArena(arena, PR_FALSE); |
michael@0 | 7152 | return rv; |
michael@0 | 7153 | } |
michael@0 | 7154 | |
michael@0 | 7155 | static SECStatus |
michael@0 | 7156 | ssl3_CheckFalseStart(sslSocket *ss) |
michael@0 | 7157 | { |
michael@0 | 7158 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 7159 | PORT_Assert( !ss->ssl3.hs.authCertificatePending ); |
michael@0 | 7160 | PORT_Assert( !ss->ssl3.hs.canFalseStart ); |
michael@0 | 7161 | |
michael@0 | 7162 | if (!ss->canFalseStartCallback) { |
michael@0 | 7163 | SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start", |
michael@0 | 7164 | SSL_GETPID(), ss->fd)); |
michael@0 | 7165 | } else { |
michael@0 | 7166 | PRBool maybeFalseStart; |
michael@0 | 7167 | SECStatus rv; |
michael@0 | 7168 | |
michael@0 | 7169 | /* An attacker can control the selected ciphersuite so we only wish to |
michael@0 | 7170 | * do False Start in the case that the selected ciphersuite is |
michael@0 | 7171 | * sufficiently strong that the attack can gain no advantage. |
michael@0 | 7172 | * Therefore we always require an 80-bit cipher. */ |
michael@0 | 7173 | ssl_GetSpecReadLock(ss); |
michael@0 | 7174 | maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10; |
michael@0 | 7175 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 7176 | |
michael@0 | 7177 | if (!maybeFalseStart) { |
michael@0 | 7178 | SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher", |
michael@0 | 7179 | SSL_GETPID(), ss->fd)); |
michael@0 | 7180 | } else { |
michael@0 | 7181 | rv = (ss->canFalseStartCallback)(ss->fd, |
michael@0 | 7182 | ss->canFalseStartCallbackData, |
michael@0 | 7183 | &ss->ssl3.hs.canFalseStart); |
michael@0 | 7184 | if (rv == SECSuccess) { |
michael@0 | 7185 | SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s", |
michael@0 | 7186 | SSL_GETPID(), ss->fd, |
michael@0 | 7187 | ss->ssl3.hs.canFalseStart ? "TRUE" : "FALSE")); |
michael@0 | 7188 | } else { |
michael@0 | 7189 | SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)", |
michael@0 | 7190 | SSL_GETPID(), ss->fd, |
michael@0 | 7191 | PR_ErrorToName(PR_GetError()))); |
michael@0 | 7192 | } |
michael@0 | 7193 | return rv; |
michael@0 | 7194 | } |
michael@0 | 7195 | } |
michael@0 | 7196 | |
michael@0 | 7197 | ss->ssl3.hs.canFalseStart = PR_FALSE; |
michael@0 | 7198 | return SECSuccess; |
michael@0 | 7199 | } |
michael@0 | 7200 | |
michael@0 | 7201 | PRBool |
michael@0 | 7202 | ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss) |
michael@0 | 7203 | { |
michael@0 | 7204 | PRBool result; |
michael@0 | 7205 | |
michael@0 | 7206 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 7207 | |
michael@0 | 7208 | switch (ss->ssl3.hs.ws) { |
michael@0 | 7209 | case wait_new_session_ticket: |
michael@0 | 7210 | result = PR_TRUE; |
michael@0 | 7211 | break; |
michael@0 | 7212 | case wait_change_cipher: |
michael@0 | 7213 | result = !ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn); |
michael@0 | 7214 | break; |
michael@0 | 7215 | default: |
michael@0 | 7216 | result = PR_FALSE; |
michael@0 | 7217 | break; |
michael@0 | 7218 | } |
michael@0 | 7219 | |
michael@0 | 7220 | return result; |
michael@0 | 7221 | } |
michael@0 | 7222 | |
michael@0 | 7223 | static SECStatus ssl3_SendClientSecondRound(sslSocket *ss); |
michael@0 | 7224 | |
michael@0 | 7225 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 7226 | * ssl3 Server Hello Done message. |
michael@0 | 7227 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 7228 | */ |
michael@0 | 7229 | static SECStatus |
michael@0 | 7230 | ssl3_HandleServerHelloDone(sslSocket *ss) |
michael@0 | 7231 | { |
michael@0 | 7232 | SECStatus rv; |
michael@0 | 7233 | SSL3WaitState ws = ss->ssl3.hs.ws; |
michael@0 | 7234 | |
michael@0 | 7235 | SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake", |
michael@0 | 7236 | SSL_GETPID(), ss->fd)); |
michael@0 | 7237 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 7238 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 7239 | |
michael@0 | 7240 | if (ws != wait_hello_done && |
michael@0 | 7241 | ws != wait_server_cert && |
michael@0 | 7242 | ws != wait_server_key && |
michael@0 | 7243 | ws != wait_cert_request) { |
michael@0 | 7244 | SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 7245 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); |
michael@0 | 7246 | return SECFailure; |
michael@0 | 7247 | } |
michael@0 | 7248 | |
michael@0 | 7249 | rv = ssl3_SendClientSecondRound(ss); |
michael@0 | 7250 | |
michael@0 | 7251 | return rv; |
michael@0 | 7252 | } |
michael@0 | 7253 | |
michael@0 | 7254 | /* Called from ssl3_HandleServerHelloDone and ssl3_AuthCertificateComplete. |
michael@0 | 7255 | * |
michael@0 | 7256 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 7257 | */ |
michael@0 | 7258 | static SECStatus |
michael@0 | 7259 | ssl3_SendClientSecondRound(sslSocket *ss) |
michael@0 | 7260 | { |
michael@0 | 7261 | SECStatus rv; |
michael@0 | 7262 | PRBool sendClientCert; |
michael@0 | 7263 | |
michael@0 | 7264 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 7265 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 7266 | |
michael@0 | 7267 | sendClientCert = !ss->ssl3.sendEmptyCert && |
michael@0 | 7268 | ss->ssl3.clientCertChain != NULL && |
michael@0 | 7269 | ss->ssl3.clientPrivateKey != NULL; |
michael@0 | 7270 | |
michael@0 | 7271 | if (!sendClientCert && |
michael@0 | 7272 | ss->ssl3.hs.hashType == handshake_hash_single && |
michael@0 | 7273 | ss->ssl3.hs.backupHash) { |
michael@0 | 7274 | /* Don't need the backup handshake hash. */ |
michael@0 | 7275 | PK11_DestroyContext(ss->ssl3.hs.backupHash, PR_TRUE); |
michael@0 | 7276 | ss->ssl3.hs.backupHash = NULL; |
michael@0 | 7277 | } |
michael@0 | 7278 | |
michael@0 | 7279 | /* We must wait for the server's certificate to be authenticated before |
michael@0 | 7280 | * sending the client certificate in order to disclosing the client |
michael@0 | 7281 | * certificate to an attacker that does not have a valid cert for the |
michael@0 | 7282 | * domain we are connecting to. |
michael@0 | 7283 | * |
michael@0 | 7284 | * XXX: We should do the same for the NPN extension, but for that we |
michael@0 | 7285 | * need an option to give the application the ability to leak the NPN |
michael@0 | 7286 | * information to get better performance. |
michael@0 | 7287 | * |
michael@0 | 7288 | * During the initial handshake on a connection, we never send/receive |
michael@0 | 7289 | * application data until we have authenticated the server's certificate; |
michael@0 | 7290 | * i.e. we have fully authenticated the handshake before using the cipher |
michael@0 | 7291 | * specs agreed upon for that handshake. During a renegotiation, we may |
michael@0 | 7292 | * continue sending and receiving application data during the handshake |
michael@0 | 7293 | * interleaved with the handshake records. If we were to send the client's |
michael@0 | 7294 | * second round for a renegotiation before the server's certificate was |
michael@0 | 7295 | * authenticated, then the application data sent/received after this point |
michael@0 | 7296 | * would be using cipher spec that hadn't been authenticated. By waiting |
michael@0 | 7297 | * until the server's certificate has been authenticated during |
michael@0 | 7298 | * renegotiations, we ensure that renegotiations have the same property |
michael@0 | 7299 | * as initial handshakes; i.e. we have fully authenticated the handshake |
michael@0 | 7300 | * before using the cipher specs agreed upon for that handshake for |
michael@0 | 7301 | * application data. |
michael@0 | 7302 | */ |
michael@0 | 7303 | if (ss->ssl3.hs.restartTarget) { |
michael@0 | 7304 | PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget"); |
michael@0 | 7305 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 7306 | return SECFailure; |
michael@0 | 7307 | } |
michael@0 | 7308 | if (ss->ssl3.hs.authCertificatePending && |
michael@0 | 7309 | (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) { |
michael@0 | 7310 | SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because" |
michael@0 | 7311 | " certificate authentication is still pending.", |
michael@0 | 7312 | SSL_GETPID(), ss->fd)); |
michael@0 | 7313 | ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound; |
michael@0 | 7314 | return SECWouldBlock; |
michael@0 | 7315 | } |
michael@0 | 7316 | |
michael@0 | 7317 | ssl_GetXmitBufLock(ss); /*******************************/ |
michael@0 | 7318 | |
michael@0 | 7319 | if (ss->ssl3.sendEmptyCert) { |
michael@0 | 7320 | ss->ssl3.sendEmptyCert = PR_FALSE; |
michael@0 | 7321 | rv = ssl3_SendEmptyCertificate(ss); |
michael@0 | 7322 | /* Don't send verify */ |
michael@0 | 7323 | if (rv != SECSuccess) { |
michael@0 | 7324 | goto loser; /* error code is set. */ |
michael@0 | 7325 | } |
michael@0 | 7326 | } else if (sendClientCert) { |
michael@0 | 7327 | rv = ssl3_SendCertificate(ss); |
michael@0 | 7328 | if (rv != SECSuccess) { |
michael@0 | 7329 | goto loser; /* error code is set. */ |
michael@0 | 7330 | } |
michael@0 | 7331 | } |
michael@0 | 7332 | |
michael@0 | 7333 | rv = ssl3_SendClientKeyExchange(ss); |
michael@0 | 7334 | if (rv != SECSuccess) { |
michael@0 | 7335 | goto loser; /* err is set. */ |
michael@0 | 7336 | } |
michael@0 | 7337 | |
michael@0 | 7338 | if (sendClientCert) { |
michael@0 | 7339 | rv = ssl3_SendCertificateVerify(ss); |
michael@0 | 7340 | if (rv != SECSuccess) { |
michael@0 | 7341 | goto loser; /* err is set. */ |
michael@0 | 7342 | } |
michael@0 | 7343 | } |
michael@0 | 7344 | |
michael@0 | 7345 | rv = ssl3_SendChangeCipherSpecs(ss); |
michael@0 | 7346 | if (rv != SECSuccess) { |
michael@0 | 7347 | goto loser; /* err code was set. */ |
michael@0 | 7348 | } |
michael@0 | 7349 | |
michael@0 | 7350 | /* This must be done after we've set ss->ssl3.cwSpec in |
michael@0 | 7351 | * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information |
michael@0 | 7352 | * from cwSpec. This must be done before we call ssl3_CheckFalseStart |
michael@0 | 7353 | * because the false start callback (if any) may need the information from |
michael@0 | 7354 | * the functions that depend on this being set. |
michael@0 | 7355 | */ |
michael@0 | 7356 | ss->enoughFirstHsDone = PR_TRUE; |
michael@0 | 7357 | |
michael@0 | 7358 | if (!ss->firstHsDone) { |
michael@0 | 7359 | /* XXX: If the server's certificate hasn't been authenticated by this |
michael@0 | 7360 | * point, then we may be leaking this NPN message to an attacker. |
michael@0 | 7361 | */ |
michael@0 | 7362 | rv = ssl3_SendNextProto(ss); |
michael@0 | 7363 | if (rv != SECSuccess) { |
michael@0 | 7364 | goto loser; /* err code was set. */ |
michael@0 | 7365 | } |
michael@0 | 7366 | |
michael@0 | 7367 | if (ss->opt.enableFalseStart) { |
michael@0 | 7368 | if (!ss->ssl3.hs.authCertificatePending) { |
michael@0 | 7369 | /* When we fix bug 589047, we will need to know whether we are |
michael@0 | 7370 | * false starting before we try to flush the client second |
michael@0 | 7371 | * round to the network. With that in mind, we purposefully |
michael@0 | 7372 | * call ssl3_CheckFalseStart before calling ssl3_SendFinished, |
michael@0 | 7373 | * which includes a call to ssl3_FlushHandshake, so that |
michael@0 | 7374 | * no application develops a reliance on such flushing being |
michael@0 | 7375 | * done before its false start callback is called. |
michael@0 | 7376 | */ |
michael@0 | 7377 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 7378 | rv = ssl3_CheckFalseStart(ss); |
michael@0 | 7379 | ssl_GetXmitBufLock(ss); |
michael@0 | 7380 | if (rv != SECSuccess) { |
michael@0 | 7381 | goto loser; |
michael@0 | 7382 | } |
michael@0 | 7383 | } else { |
michael@0 | 7384 | /* The certificate authentication and the server's Finished |
michael@0 | 7385 | * message are racing each other. If the certificate |
michael@0 | 7386 | * authentication wins, then we will try to false start in |
michael@0 | 7387 | * ssl3_AuthCertificateComplete. |
michael@0 | 7388 | */ |
michael@0 | 7389 | SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because" |
michael@0 | 7390 | " certificate authentication is still pending.", |
michael@0 | 7391 | SSL_GETPID(), ss->fd)); |
michael@0 | 7392 | } |
michael@0 | 7393 | } |
michael@0 | 7394 | } |
michael@0 | 7395 | |
michael@0 | 7396 | rv = ssl3_SendFinished(ss, 0); |
michael@0 | 7397 | if (rv != SECSuccess) { |
michael@0 | 7398 | goto loser; /* err code was set. */ |
michael@0 | 7399 | } |
michael@0 | 7400 | |
michael@0 | 7401 | ssl_ReleaseXmitBufLock(ss); /*******************************/ |
michael@0 | 7402 | |
michael@0 | 7403 | if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) |
michael@0 | 7404 | ss->ssl3.hs.ws = wait_new_session_ticket; |
michael@0 | 7405 | else |
michael@0 | 7406 | ss->ssl3.hs.ws = wait_change_cipher; |
michael@0 | 7407 | |
michael@0 | 7408 | PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss)); |
michael@0 | 7409 | |
michael@0 | 7410 | return SECSuccess; |
michael@0 | 7411 | |
michael@0 | 7412 | loser: |
michael@0 | 7413 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 7414 | return rv; |
michael@0 | 7415 | } |
michael@0 | 7416 | |
michael@0 | 7417 | /* |
michael@0 | 7418 | * Routines used by servers |
michael@0 | 7419 | */ |
michael@0 | 7420 | static SECStatus |
michael@0 | 7421 | ssl3_SendHelloRequest(sslSocket *ss) |
michael@0 | 7422 | { |
michael@0 | 7423 | SECStatus rv; |
michael@0 | 7424 | |
michael@0 | 7425 | SSL_TRC(3, ("%d: SSL3[%d]: send hello_request handshake", SSL_GETPID(), |
michael@0 | 7426 | ss->fd)); |
michael@0 | 7427 | |
michael@0 | 7428 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 7429 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 7430 | |
michael@0 | 7431 | rv = ssl3_AppendHandshakeHeader(ss, hello_request, 0); |
michael@0 | 7432 | if (rv != SECSuccess) { |
michael@0 | 7433 | return rv; /* err set by AppendHandshake */ |
michael@0 | 7434 | } |
michael@0 | 7435 | rv = ssl3_FlushHandshake(ss, 0); |
michael@0 | 7436 | if (rv != SECSuccess) { |
michael@0 | 7437 | return rv; /* error code set by ssl3_FlushHandshake */ |
michael@0 | 7438 | } |
michael@0 | 7439 | ss->ssl3.hs.ws = wait_client_hello; |
michael@0 | 7440 | return SECSuccess; |
michael@0 | 7441 | } |
michael@0 | 7442 | |
michael@0 | 7443 | /* |
michael@0 | 7444 | * Called from: |
michael@0 | 7445 | * ssl3_HandleClientHello() |
michael@0 | 7446 | */ |
michael@0 | 7447 | static SECComparison |
michael@0 | 7448 | ssl3_ServerNameCompare(const SECItem *name1, const SECItem *name2) |
michael@0 | 7449 | { |
michael@0 | 7450 | if (!name1 != !name2) { |
michael@0 | 7451 | return SECLessThan; |
michael@0 | 7452 | } |
michael@0 | 7453 | if (!name1) { |
michael@0 | 7454 | return SECEqual; |
michael@0 | 7455 | } |
michael@0 | 7456 | if (name1->type != name2->type) { |
michael@0 | 7457 | return SECLessThan; |
michael@0 | 7458 | } |
michael@0 | 7459 | return SECITEM_CompareItem(name1, name2); |
michael@0 | 7460 | } |
michael@0 | 7461 | |
michael@0 | 7462 | /* Sets memory error when returning NULL. |
michael@0 | 7463 | * Called from: |
michael@0 | 7464 | * ssl3_SendClientHello() |
michael@0 | 7465 | * ssl3_HandleServerHello() |
michael@0 | 7466 | * ssl3_HandleClientHello() |
michael@0 | 7467 | * ssl3_HandleV2ClientHello() |
michael@0 | 7468 | */ |
michael@0 | 7469 | sslSessionID * |
michael@0 | 7470 | ssl3_NewSessionID(sslSocket *ss, PRBool is_server) |
michael@0 | 7471 | { |
michael@0 | 7472 | sslSessionID *sid; |
michael@0 | 7473 | |
michael@0 | 7474 | sid = PORT_ZNew(sslSessionID); |
michael@0 | 7475 | if (sid == NULL) |
michael@0 | 7476 | return sid; |
michael@0 | 7477 | |
michael@0 | 7478 | if (is_server) { |
michael@0 | 7479 | const SECItem * srvName; |
michael@0 | 7480 | SECStatus rv = SECSuccess; |
michael@0 | 7481 | |
michael@0 | 7482 | ssl_GetSpecReadLock(ss); /********************************/ |
michael@0 | 7483 | srvName = &ss->ssl3.prSpec->srvVirtName; |
michael@0 | 7484 | if (srvName->len && srvName->data) { |
michael@0 | 7485 | rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.srvName, srvName); |
michael@0 | 7486 | } |
michael@0 | 7487 | ssl_ReleaseSpecReadLock(ss); /************************************/ |
michael@0 | 7488 | if (rv != SECSuccess) { |
michael@0 | 7489 | PORT_Free(sid); |
michael@0 | 7490 | return NULL; |
michael@0 | 7491 | } |
michael@0 | 7492 | } |
michael@0 | 7493 | sid->peerID = (ss->peerID == NULL) ? NULL : PORT_Strdup(ss->peerID); |
michael@0 | 7494 | sid->urlSvrName = (ss->url == NULL) ? NULL : PORT_Strdup(ss->url); |
michael@0 | 7495 | sid->addr = ss->sec.ci.peer; |
michael@0 | 7496 | sid->port = ss->sec.ci.port; |
michael@0 | 7497 | sid->references = 1; |
michael@0 | 7498 | sid->cached = never_cached; |
michael@0 | 7499 | sid->version = ss->version; |
michael@0 | 7500 | |
michael@0 | 7501 | sid->u.ssl3.keys.resumable = PR_TRUE; |
michael@0 | 7502 | sid->u.ssl3.policy = SSL_ALLOWED; |
michael@0 | 7503 | sid->u.ssl3.clientWriteKey = NULL; |
michael@0 | 7504 | sid->u.ssl3.serverWriteKey = NULL; |
michael@0 | 7505 | |
michael@0 | 7506 | if (is_server) { |
michael@0 | 7507 | SECStatus rv; |
michael@0 | 7508 | int pid = SSL_GETPID(); |
michael@0 | 7509 | |
michael@0 | 7510 | sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES; |
michael@0 | 7511 | sid->u.ssl3.sessionID[0] = (pid >> 8) & 0xff; |
michael@0 | 7512 | sid->u.ssl3.sessionID[1] = pid & 0xff; |
michael@0 | 7513 | rv = PK11_GenerateRandom(sid->u.ssl3.sessionID + 2, |
michael@0 | 7514 | SSL3_SESSIONID_BYTES -2); |
michael@0 | 7515 | if (rv != SECSuccess) { |
michael@0 | 7516 | ssl_FreeSID(sid); |
michael@0 | 7517 | ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); |
michael@0 | 7518 | return NULL; |
michael@0 | 7519 | } |
michael@0 | 7520 | } |
michael@0 | 7521 | return sid; |
michael@0 | 7522 | } |
michael@0 | 7523 | |
michael@0 | 7524 | /* Called from: ssl3_HandleClientHello, ssl3_HandleV2ClientHello */ |
michael@0 | 7525 | static SECStatus |
michael@0 | 7526 | ssl3_SendServerHelloSequence(sslSocket *ss) |
michael@0 | 7527 | { |
michael@0 | 7528 | const ssl3KEADef *kea_def; |
michael@0 | 7529 | SECStatus rv; |
michael@0 | 7530 | |
michael@0 | 7531 | SSL_TRC(3, ("%d: SSL3[%d]: begin send server_hello sequence", |
michael@0 | 7532 | SSL_GETPID(), ss->fd)); |
michael@0 | 7533 | |
michael@0 | 7534 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 7535 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); |
michael@0 | 7536 | |
michael@0 | 7537 | rv = ssl3_SendServerHello(ss); |
michael@0 | 7538 | if (rv != SECSuccess) { |
michael@0 | 7539 | return rv; /* err code is set. */ |
michael@0 | 7540 | } |
michael@0 | 7541 | rv = ssl3_SendCertificate(ss); |
michael@0 | 7542 | if (rv != SECSuccess) { |
michael@0 | 7543 | return rv; /* error code is set. */ |
michael@0 | 7544 | } |
michael@0 | 7545 | rv = ssl3_SendCertificateStatus(ss); |
michael@0 | 7546 | if (rv != SECSuccess) { |
michael@0 | 7547 | return rv; /* error code is set. */ |
michael@0 | 7548 | } |
michael@0 | 7549 | /* We have to do this after the call to ssl3_SendServerHello, |
michael@0 | 7550 | * because kea_def is set up by ssl3_SendServerHello(). |
michael@0 | 7551 | */ |
michael@0 | 7552 | kea_def = ss->ssl3.hs.kea_def; |
michael@0 | 7553 | ss->ssl3.hs.usedStepDownKey = PR_FALSE; |
michael@0 | 7554 | |
michael@0 | 7555 | if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) { |
michael@0 | 7556 | /* see if we can legally use the key in the cert. */ |
michael@0 | 7557 | int keyLen; /* bytes */ |
michael@0 | 7558 | |
michael@0 | 7559 | keyLen = PK11_GetPrivateModulusLen( |
michael@0 | 7560 | ss->serverCerts[kea_def->exchKeyType].SERVERKEY); |
michael@0 | 7561 | |
michael@0 | 7562 | if (keyLen > 0 && |
michael@0 | 7563 | keyLen * BPB <= kea_def->key_size_limit ) { |
michael@0 | 7564 | /* XXX AND cert is not signing only!! */ |
michael@0 | 7565 | /* just fall through and use it. */ |
michael@0 | 7566 | } else if (ss->stepDownKeyPair != NULL) { |
michael@0 | 7567 | ss->ssl3.hs.usedStepDownKey = PR_TRUE; |
michael@0 | 7568 | rv = ssl3_SendServerKeyExchange(ss); |
michael@0 | 7569 | if (rv != SECSuccess) { |
michael@0 | 7570 | return rv; /* err code was set. */ |
michael@0 | 7571 | } |
michael@0 | 7572 | } else { |
michael@0 | 7573 | #ifndef HACKED_EXPORT_SERVER |
michael@0 | 7574 | PORT_SetError(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED); |
michael@0 | 7575 | return rv; |
michael@0 | 7576 | #endif |
michael@0 | 7577 | } |
michael@0 | 7578 | #ifndef NSS_DISABLE_ECC |
michael@0 | 7579 | } else if ((kea_def->kea == kea_ecdhe_rsa) || |
michael@0 | 7580 | (kea_def->kea == kea_ecdhe_ecdsa)) { |
michael@0 | 7581 | rv = ssl3_SendServerKeyExchange(ss); |
michael@0 | 7582 | if (rv != SECSuccess) { |
michael@0 | 7583 | return rv; /* err code was set. */ |
michael@0 | 7584 | } |
michael@0 | 7585 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 7586 | } |
michael@0 | 7587 | |
michael@0 | 7588 | if (ss->opt.requestCertificate) { |
michael@0 | 7589 | rv = ssl3_SendCertificateRequest(ss); |
michael@0 | 7590 | if (rv != SECSuccess) { |
michael@0 | 7591 | return rv; /* err code is set. */ |
michael@0 | 7592 | } |
michael@0 | 7593 | } |
michael@0 | 7594 | rv = ssl3_SendServerHelloDone(ss); |
michael@0 | 7595 | if (rv != SECSuccess) { |
michael@0 | 7596 | return rv; /* err code is set. */ |
michael@0 | 7597 | } |
michael@0 | 7598 | |
michael@0 | 7599 | ss->ssl3.hs.ws = (ss->opt.requestCertificate) ? wait_client_cert |
michael@0 | 7600 | : wait_client_key; |
michael@0 | 7601 | return SECSuccess; |
michael@0 | 7602 | } |
michael@0 | 7603 | |
michael@0 | 7604 | /* An empty TLS Renegotiation Info (RI) extension */ |
michael@0 | 7605 | static const PRUint8 emptyRIext[5] = {0xff, 0x01, 0x00, 0x01, 0x00}; |
michael@0 | 7606 | |
michael@0 | 7607 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 7608 | * ssl3 Client Hello message. |
michael@0 | 7609 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 7610 | */ |
michael@0 | 7611 | static SECStatus |
michael@0 | 7612 | ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 7613 | { |
michael@0 | 7614 | sslSessionID * sid = NULL; |
michael@0 | 7615 | PRInt32 tmp; |
michael@0 | 7616 | unsigned int i; |
michael@0 | 7617 | int j; |
michael@0 | 7618 | SECStatus rv; |
michael@0 | 7619 | int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO; |
michael@0 | 7620 | SSL3AlertDescription desc = illegal_parameter; |
michael@0 | 7621 | SSL3AlertLevel level = alert_fatal; |
michael@0 | 7622 | SSL3ProtocolVersion version; |
michael@0 | 7623 | SECItem sidBytes = {siBuffer, NULL, 0}; |
michael@0 | 7624 | SECItem cookieBytes = {siBuffer, NULL, 0}; |
michael@0 | 7625 | SECItem suites = {siBuffer, NULL, 0}; |
michael@0 | 7626 | SECItem comps = {siBuffer, NULL, 0}; |
michael@0 | 7627 | PRBool haveSpecWriteLock = PR_FALSE; |
michael@0 | 7628 | PRBool haveXmitBufLock = PR_FALSE; |
michael@0 | 7629 | |
michael@0 | 7630 | SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake", |
michael@0 | 7631 | SSL_GETPID(), ss->fd)); |
michael@0 | 7632 | |
michael@0 | 7633 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 7634 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 7635 | PORT_Assert( ss->ssl3.initialized ); |
michael@0 | 7636 | |
michael@0 | 7637 | /* Get peer name of client */ |
michael@0 | 7638 | rv = ssl_GetPeerInfo(ss); |
michael@0 | 7639 | if (rv != SECSuccess) { |
michael@0 | 7640 | return rv; /* error code is set. */ |
michael@0 | 7641 | } |
michael@0 | 7642 | |
michael@0 | 7643 | /* Clearing the handshake pointers so that ssl_Do1stHandshake won't |
michael@0 | 7644 | * call ssl2_HandleMessage. |
michael@0 | 7645 | * |
michael@0 | 7646 | * The issue here is that TLS ordinarily starts out in |
michael@0 | 7647 | * ssl2_HandleV3HandshakeRecord() because of the backward-compatibility |
michael@0 | 7648 | * code paths. That function zeroes these next pointers. But with DTLS, |
michael@0 | 7649 | * we don't even try to do the v2 ClientHello so we skip that function |
michael@0 | 7650 | * and need to reset these values here. |
michael@0 | 7651 | */ |
michael@0 | 7652 | if (IS_DTLS(ss)) { |
michael@0 | 7653 | ss->nextHandshake = 0; |
michael@0 | 7654 | ss->securityHandshake = 0; |
michael@0 | 7655 | } |
michael@0 | 7656 | |
michael@0 | 7657 | /* We might be starting session renegotiation in which case we should |
michael@0 | 7658 | * clear previous state. |
michael@0 | 7659 | */ |
michael@0 | 7660 | PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); |
michael@0 | 7661 | ss->statelessResume = PR_FALSE; |
michael@0 | 7662 | |
michael@0 | 7663 | if ((ss->ssl3.hs.ws != wait_client_hello) && |
michael@0 | 7664 | (ss->ssl3.hs.ws != idle_handshake)) { |
michael@0 | 7665 | desc = unexpected_message; |
michael@0 | 7666 | errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO; |
michael@0 | 7667 | goto alert_loser; |
michael@0 | 7668 | } |
michael@0 | 7669 | if (ss->ssl3.hs.ws == idle_handshake && |
michael@0 | 7670 | ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) { |
michael@0 | 7671 | desc = no_renegotiation; |
michael@0 | 7672 | level = alert_warning; |
michael@0 | 7673 | errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED; |
michael@0 | 7674 | goto alert_loser; |
michael@0 | 7675 | } |
michael@0 | 7676 | |
michael@0 | 7677 | if (IS_DTLS(ss)) { |
michael@0 | 7678 | dtls_RehandshakeCleanup(ss); |
michael@0 | 7679 | } |
michael@0 | 7680 | |
michael@0 | 7681 | tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); |
michael@0 | 7682 | if (tmp < 0) |
michael@0 | 7683 | goto loser; /* malformed, alert already sent */ |
michael@0 | 7684 | |
michael@0 | 7685 | /* Translate the version */ |
michael@0 | 7686 | if (IS_DTLS(ss)) { |
michael@0 | 7687 | ss->clientHelloVersion = version = |
michael@0 | 7688 | dtls_DTLSVersionToTLSVersion((SSL3ProtocolVersion)tmp); |
michael@0 | 7689 | } else { |
michael@0 | 7690 | ss->clientHelloVersion = version = (SSL3ProtocolVersion)tmp; |
michael@0 | 7691 | } |
michael@0 | 7692 | |
michael@0 | 7693 | rv = ssl3_NegotiateVersion(ss, version, PR_TRUE); |
michael@0 | 7694 | if (rv != SECSuccess) { |
michael@0 | 7695 | desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version |
michael@0 | 7696 | : handshake_failure; |
michael@0 | 7697 | errCode = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 7698 | goto alert_loser; |
michael@0 | 7699 | } |
michael@0 | 7700 | |
michael@0 | 7701 | rv = ssl3_InitHandshakeHashes(ss); |
michael@0 | 7702 | if (rv != SECSuccess) { |
michael@0 | 7703 | desc = internal_error; |
michael@0 | 7704 | errCode = PORT_GetError(); |
michael@0 | 7705 | goto alert_loser; |
michael@0 | 7706 | } |
michael@0 | 7707 | |
michael@0 | 7708 | /* grab the client random data. */ |
michael@0 | 7709 | rv = ssl3_ConsumeHandshake( |
michael@0 | 7710 | ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length); |
michael@0 | 7711 | if (rv != SECSuccess) { |
michael@0 | 7712 | goto loser; /* malformed */ |
michael@0 | 7713 | } |
michael@0 | 7714 | |
michael@0 | 7715 | /* grab the client's SID, if present. */ |
michael@0 | 7716 | rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length); |
michael@0 | 7717 | if (rv != SECSuccess) { |
michael@0 | 7718 | goto loser; /* malformed */ |
michael@0 | 7719 | } |
michael@0 | 7720 | |
michael@0 | 7721 | /* grab the client's cookie, if present. */ |
michael@0 | 7722 | if (IS_DTLS(ss)) { |
michael@0 | 7723 | rv = ssl3_ConsumeHandshakeVariable(ss, &cookieBytes, 1, &b, &length); |
michael@0 | 7724 | if (rv != SECSuccess) { |
michael@0 | 7725 | goto loser; /* malformed */ |
michael@0 | 7726 | } |
michael@0 | 7727 | } |
michael@0 | 7728 | |
michael@0 | 7729 | /* grab the list of cipher suites. */ |
michael@0 | 7730 | rv = ssl3_ConsumeHandshakeVariable(ss, &suites, 2, &b, &length); |
michael@0 | 7731 | if (rv != SECSuccess) { |
michael@0 | 7732 | goto loser; /* malformed */ |
michael@0 | 7733 | } |
michael@0 | 7734 | |
michael@0 | 7735 | /* If the ClientHello version is less than our maximum version, check for a |
michael@0 | 7736 | * TLS_FALLBACK_SCSV and reject the connection if found. */ |
michael@0 | 7737 | if (ss->vrange.max > ss->clientHelloVersion) { |
michael@0 | 7738 | for (i = 0; i + 1 < suites.len; i += 2) { |
michael@0 | 7739 | PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; |
michael@0 | 7740 | if (suite_i != TLS_FALLBACK_SCSV) |
michael@0 | 7741 | continue; |
michael@0 | 7742 | desc = inappropriate_fallback; |
michael@0 | 7743 | errCode = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT; |
michael@0 | 7744 | goto alert_loser; |
michael@0 | 7745 | } |
michael@0 | 7746 | } |
michael@0 | 7747 | |
michael@0 | 7748 | /* grab the list of compression methods. */ |
michael@0 | 7749 | rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length); |
michael@0 | 7750 | if (rv != SECSuccess) { |
michael@0 | 7751 | goto loser; /* malformed */ |
michael@0 | 7752 | } |
michael@0 | 7753 | |
michael@0 | 7754 | desc = handshake_failure; |
michael@0 | 7755 | |
michael@0 | 7756 | /* Handle TLS hello extensions for SSL3 & TLS. We do not know if |
michael@0 | 7757 | * we are restarting a previous session until extensions have been |
michael@0 | 7758 | * parsed, since we might have received a SessionTicket extension. |
michael@0 | 7759 | * Note: we allow extensions even when negotiating SSL3 for the sake |
michael@0 | 7760 | * of interoperability (and backwards compatibility). |
michael@0 | 7761 | */ |
michael@0 | 7762 | |
michael@0 | 7763 | if (length) { |
michael@0 | 7764 | /* Get length of hello extensions */ |
michael@0 | 7765 | PRInt32 extension_length; |
michael@0 | 7766 | extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); |
michael@0 | 7767 | if (extension_length < 0) { |
michael@0 | 7768 | goto loser; /* alert already sent */ |
michael@0 | 7769 | } |
michael@0 | 7770 | if (extension_length != length) { |
michael@0 | 7771 | ssl3_DecodeError(ss); /* send alert */ |
michael@0 | 7772 | goto loser; |
michael@0 | 7773 | } |
michael@0 | 7774 | rv = ssl3_HandleHelloExtensions(ss, &b, &length); |
michael@0 | 7775 | if (rv != SECSuccess) { |
michael@0 | 7776 | goto loser; /* malformed */ |
michael@0 | 7777 | } |
michael@0 | 7778 | } |
michael@0 | 7779 | if (!ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) { |
michael@0 | 7780 | /* If we didn't receive an RI extension, look for the SCSV, |
michael@0 | 7781 | * and if found, treat it just like an empty RI extension |
michael@0 | 7782 | * by processing a local copy of an empty RI extension. |
michael@0 | 7783 | */ |
michael@0 | 7784 | for (i = 0; i + 1 < suites.len; i += 2) { |
michael@0 | 7785 | PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; |
michael@0 | 7786 | if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { |
michael@0 | 7787 | SSL3Opaque * b2 = (SSL3Opaque *)emptyRIext; |
michael@0 | 7788 | PRUint32 L2 = sizeof emptyRIext; |
michael@0 | 7789 | (void)ssl3_HandleHelloExtensions(ss, &b2, &L2); |
michael@0 | 7790 | break; |
michael@0 | 7791 | } |
michael@0 | 7792 | } |
michael@0 | 7793 | } |
michael@0 | 7794 | if (ss->firstHsDone && |
michael@0 | 7795 | (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN || |
michael@0 | 7796 | ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) && |
michael@0 | 7797 | !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) { |
michael@0 | 7798 | desc = no_renegotiation; |
michael@0 | 7799 | level = alert_warning; |
michael@0 | 7800 | errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED; |
michael@0 | 7801 | goto alert_loser; |
michael@0 | 7802 | } |
michael@0 | 7803 | if ((ss->opt.requireSafeNegotiation || |
michael@0 | 7804 | (ss->firstHsDone && ss->peerRequestedProtection)) && |
michael@0 | 7805 | !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) { |
michael@0 | 7806 | desc = handshake_failure; |
michael@0 | 7807 | errCode = SSL_ERROR_UNSAFE_NEGOTIATION; |
michael@0 | 7808 | goto alert_loser; |
michael@0 | 7809 | } |
michael@0 | 7810 | |
michael@0 | 7811 | /* We do stateful resumes only if either of the following |
michael@0 | 7812 | * conditions are satisfied: (1) the client does not support the |
michael@0 | 7813 | * session ticket extension, or (2) the client support the session |
michael@0 | 7814 | * ticket extension, but sent an empty ticket. |
michael@0 | 7815 | */ |
michael@0 | 7816 | if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) || |
michael@0 | 7817 | ss->xtnData.emptySessionTicket) { |
michael@0 | 7818 | if (sidBytes.len > 0 && !ss->opt.noCache) { |
michael@0 | 7819 | SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x", |
michael@0 | 7820 | SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], |
michael@0 | 7821 | ss->sec.ci.peer.pr_s6_addr32[1], |
michael@0 | 7822 | ss->sec.ci.peer.pr_s6_addr32[2], |
michael@0 | 7823 | ss->sec.ci.peer.pr_s6_addr32[3])); |
michael@0 | 7824 | if (ssl_sid_lookup) { |
michael@0 | 7825 | sid = (*ssl_sid_lookup)(&ss->sec.ci.peer, sidBytes.data, |
michael@0 | 7826 | sidBytes.len, ss->dbHandle); |
michael@0 | 7827 | } else { |
michael@0 | 7828 | errCode = SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED; |
michael@0 | 7829 | goto loser; |
michael@0 | 7830 | } |
michael@0 | 7831 | } |
michael@0 | 7832 | } else if (ss->statelessResume) { |
michael@0 | 7833 | /* Fill in the client's session ID if doing a stateless resume. |
michael@0 | 7834 | * (When doing stateless resumes, server echos client's SessionID.) |
michael@0 | 7835 | */ |
michael@0 | 7836 | sid = ss->sec.ci.sid; |
michael@0 | 7837 | PORT_Assert(sid != NULL); /* Should have already been filled in.*/ |
michael@0 | 7838 | |
michael@0 | 7839 | if (sidBytes.len > 0 && sidBytes.len <= SSL3_SESSIONID_BYTES) { |
michael@0 | 7840 | sid->u.ssl3.sessionIDLength = sidBytes.len; |
michael@0 | 7841 | PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, |
michael@0 | 7842 | sidBytes.len); |
michael@0 | 7843 | sid->u.ssl3.sessionIDLength = sidBytes.len; |
michael@0 | 7844 | } else { |
michael@0 | 7845 | sid->u.ssl3.sessionIDLength = 0; |
michael@0 | 7846 | } |
michael@0 | 7847 | ss->sec.ci.sid = NULL; |
michael@0 | 7848 | } |
michael@0 | 7849 | |
michael@0 | 7850 | /* We only send a session ticket extension if the client supports |
michael@0 | 7851 | * the extension and we are unable to do either a stateful or |
michael@0 | 7852 | * stateless resume. |
michael@0 | 7853 | * |
michael@0 | 7854 | * TODO: send a session ticket if performing a stateful |
michael@0 | 7855 | * resumption. (As per RFC4507, a server may issue a session |
michael@0 | 7856 | * ticket while doing a (stateless or stateful) session resume, |
michael@0 | 7857 | * but OpenSSL-0.9.8g does not accept session tickets while |
michael@0 | 7858 | * resuming.) |
michael@0 | 7859 | */ |
michael@0 | 7860 | if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && sid == NULL) { |
michael@0 | 7861 | ssl3_RegisterServerHelloExtensionSender(ss, |
michael@0 | 7862 | ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn); |
michael@0 | 7863 | } |
michael@0 | 7864 | |
michael@0 | 7865 | if (sid != NULL) { |
michael@0 | 7866 | /* We've found a session cache entry for this client. |
michael@0 | 7867 | * Now, if we're going to require a client-auth cert, |
michael@0 | 7868 | * and we don't already have this client's cert in the session cache, |
michael@0 | 7869 | * and this is the first handshake on this connection (not a redo), |
michael@0 | 7870 | * then drop this old cache entry and start a new session. |
michael@0 | 7871 | */ |
michael@0 | 7872 | if ((sid->peerCert == NULL) && ss->opt.requestCertificate && |
michael@0 | 7873 | ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) || |
michael@0 | 7874 | (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) || |
michael@0 | 7875 | ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) |
michael@0 | 7876 | && !ss->firstHsDone))) { |
michael@0 | 7877 | |
michael@0 | 7878 | SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_not_ok ); |
michael@0 | 7879 | if (ss->sec.uncache) |
michael@0 | 7880 | ss->sec.uncache(sid); |
michael@0 | 7881 | ssl_FreeSID(sid); |
michael@0 | 7882 | sid = NULL; |
michael@0 | 7883 | } |
michael@0 | 7884 | } |
michael@0 | 7885 | |
michael@0 | 7886 | #ifndef NSS_DISABLE_ECC |
michael@0 | 7887 | /* Disable any ECC cipher suites for which we have no cert. */ |
michael@0 | 7888 | ssl3_FilterECCipherSuitesByServerCerts(ss); |
michael@0 | 7889 | #endif |
michael@0 | 7890 | |
michael@0 | 7891 | if (IS_DTLS(ss)) { |
michael@0 | 7892 | ssl3_DisableNonDTLSSuites(ss); |
michael@0 | 7893 | } |
michael@0 | 7894 | |
michael@0 | 7895 | #ifdef PARANOID |
michael@0 | 7896 | /* Look for a matching cipher suite. */ |
michael@0 | 7897 | j = ssl3_config_match_init(ss); |
michael@0 | 7898 | if (j <= 0) { /* no ciphers are working/supported by PK11 */ |
michael@0 | 7899 | errCode = PORT_GetError(); /* error code is already set. */ |
michael@0 | 7900 | goto alert_loser; |
michael@0 | 7901 | } |
michael@0 | 7902 | #endif |
michael@0 | 7903 | |
michael@0 | 7904 | /* If we already have a session for this client, be sure to pick the |
michael@0 | 7905 | ** same cipher suite and compression method we picked before. |
michael@0 | 7906 | ** This is not a loop, despite appearances. |
michael@0 | 7907 | */ |
michael@0 | 7908 | if (sid) do { |
michael@0 | 7909 | ssl3CipherSuiteCfg *suite; |
michael@0 | 7910 | #ifdef PARANOID |
michael@0 | 7911 | SSLVersionRange vrange = {ss->version, ss->version}; |
michael@0 | 7912 | #endif |
michael@0 | 7913 | |
michael@0 | 7914 | /* Check that the cached compression method is still enabled. */ |
michael@0 | 7915 | if (!compressionEnabled(ss, sid->u.ssl3.compression)) |
michael@0 | 7916 | break; |
michael@0 | 7917 | |
michael@0 | 7918 | /* Check that the cached compression method is in the client's list */ |
michael@0 | 7919 | for (i = 0; i < comps.len; i++) { |
michael@0 | 7920 | if (comps.data[i] == sid->u.ssl3.compression) |
michael@0 | 7921 | break; |
michael@0 | 7922 | } |
michael@0 | 7923 | if (i == comps.len) |
michael@0 | 7924 | break; |
michael@0 | 7925 | |
michael@0 | 7926 | suite = ss->cipherSuites; |
michael@0 | 7927 | /* Find the entry for the cipher suite used in the cached session. */ |
michael@0 | 7928 | for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) { |
michael@0 | 7929 | if (suite->cipher_suite == sid->u.ssl3.cipherSuite) |
michael@0 | 7930 | break; |
michael@0 | 7931 | } |
michael@0 | 7932 | PORT_Assert(j > 0); |
michael@0 | 7933 | if (j <= 0) |
michael@0 | 7934 | break; |
michael@0 | 7935 | #ifdef PARANOID |
michael@0 | 7936 | /* Double check that the cached cipher suite is still enabled, |
michael@0 | 7937 | * implemented, and allowed by policy. Might have been disabled. |
michael@0 | 7938 | * The product policy won't change during the process lifetime. |
michael@0 | 7939 | * Implemented ("isPresent") shouldn't change for servers. |
michael@0 | 7940 | */ |
michael@0 | 7941 | if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) |
michael@0 | 7942 | break; |
michael@0 | 7943 | #else |
michael@0 | 7944 | if (!suite->enabled) |
michael@0 | 7945 | break; |
michael@0 | 7946 | #endif |
michael@0 | 7947 | /* Double check that the cached cipher suite is in the client's list */ |
michael@0 | 7948 | for (i = 0; i + 1 < suites.len; i += 2) { |
michael@0 | 7949 | PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; |
michael@0 | 7950 | if (suite_i == suite->cipher_suite) { |
michael@0 | 7951 | ss->ssl3.hs.cipher_suite = suite->cipher_suite; |
michael@0 | 7952 | ss->ssl3.hs.suite_def = |
michael@0 | 7953 | ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); |
michael@0 | 7954 | |
michael@0 | 7955 | /* Use the cached compression method. */ |
michael@0 | 7956 | ss->ssl3.hs.compression = sid->u.ssl3.compression; |
michael@0 | 7957 | goto compression_found; |
michael@0 | 7958 | } |
michael@0 | 7959 | } |
michael@0 | 7960 | } while (0); |
michael@0 | 7961 | |
michael@0 | 7962 | /* START A NEW SESSION */ |
michael@0 | 7963 | |
michael@0 | 7964 | #ifndef PARANOID |
michael@0 | 7965 | /* Look for a matching cipher suite. */ |
michael@0 | 7966 | j = ssl3_config_match_init(ss); |
michael@0 | 7967 | if (j <= 0) { /* no ciphers are working/supported by PK11 */ |
michael@0 | 7968 | errCode = PORT_GetError(); /* error code is already set. */ |
michael@0 | 7969 | goto alert_loser; |
michael@0 | 7970 | } |
michael@0 | 7971 | #endif |
michael@0 | 7972 | |
michael@0 | 7973 | /* Select a cipher suite. |
michael@0 | 7974 | ** |
michael@0 | 7975 | ** NOTE: This suite selection algorithm should be the same as the one in |
michael@0 | 7976 | ** ssl3_HandleV2ClientHello(). |
michael@0 | 7977 | ** |
michael@0 | 7978 | ** If TLS 1.0 is enabled, we could handle the case where the client |
michael@0 | 7979 | ** offered TLS 1.1 but offered only export cipher suites by choosing TLS |
michael@0 | 7980 | ** 1.0 and selecting one of those export cipher suites. However, a secure |
michael@0 | 7981 | ** TLS 1.1 client should not have export cipher suites enabled at all, |
michael@0 | 7982 | ** and a TLS 1.1 client should definitely not be offering *only* export |
michael@0 | 7983 | ** cipher suites. Therefore, we refuse to negotiate export cipher suites |
michael@0 | 7984 | ** with any client that indicates support for TLS 1.1 or higher when we |
michael@0 | 7985 | ** (the server) have TLS 1.1 support enabled. |
michael@0 | 7986 | */ |
michael@0 | 7987 | for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) { |
michael@0 | 7988 | ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j]; |
michael@0 | 7989 | SSLVersionRange vrange = {ss->version, ss->version}; |
michael@0 | 7990 | if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) { |
michael@0 | 7991 | continue; |
michael@0 | 7992 | } |
michael@0 | 7993 | for (i = 0; i + 1 < suites.len; i += 2) { |
michael@0 | 7994 | PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; |
michael@0 | 7995 | if (suite_i == suite->cipher_suite) { |
michael@0 | 7996 | ss->ssl3.hs.cipher_suite = suite->cipher_suite; |
michael@0 | 7997 | ss->ssl3.hs.suite_def = |
michael@0 | 7998 | ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); |
michael@0 | 7999 | goto suite_found; |
michael@0 | 8000 | } |
michael@0 | 8001 | } |
michael@0 | 8002 | } |
michael@0 | 8003 | errCode = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 8004 | goto alert_loser; |
michael@0 | 8005 | |
michael@0 | 8006 | suite_found: |
michael@0 | 8007 | /* Select a compression algorithm. */ |
michael@0 | 8008 | for (i = 0; i < comps.len; i++) { |
michael@0 | 8009 | if (!compressionEnabled(ss, comps.data[i])) |
michael@0 | 8010 | continue; |
michael@0 | 8011 | for (j = 0; j < compressionMethodsCount; j++) { |
michael@0 | 8012 | if (comps.data[i] == compressions[j]) { |
michael@0 | 8013 | ss->ssl3.hs.compression = |
michael@0 | 8014 | (SSLCompressionMethod)compressions[j]; |
michael@0 | 8015 | goto compression_found; |
michael@0 | 8016 | } |
michael@0 | 8017 | } |
michael@0 | 8018 | } |
michael@0 | 8019 | errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP; |
michael@0 | 8020 | /* null compression must be supported */ |
michael@0 | 8021 | goto alert_loser; |
michael@0 | 8022 | |
michael@0 | 8023 | compression_found: |
michael@0 | 8024 | suites.data = NULL; |
michael@0 | 8025 | comps.data = NULL; |
michael@0 | 8026 | |
michael@0 | 8027 | ss->sec.send = ssl3_SendApplicationData; |
michael@0 | 8028 | |
michael@0 | 8029 | /* If there are any failures while processing the old sid, |
michael@0 | 8030 | * we don't consider them to be errors. Instead, We just behave |
michael@0 | 8031 | * as if the client had sent us no sid to begin with, and make a new one. |
michael@0 | 8032 | */ |
michael@0 | 8033 | if (sid != NULL) do { |
michael@0 | 8034 | ssl3CipherSpec *pwSpec; |
michael@0 | 8035 | SECItem wrappedMS; /* wrapped key */ |
michael@0 | 8036 | |
michael@0 | 8037 | if (sid->version != ss->version || |
michael@0 | 8038 | sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite || |
michael@0 | 8039 | sid->u.ssl3.compression != ss->ssl3.hs.compression) { |
michael@0 | 8040 | break; /* not an error */ |
michael@0 | 8041 | } |
michael@0 | 8042 | |
michael@0 | 8043 | if (ss->sec.ci.sid) { |
michael@0 | 8044 | if (ss->sec.uncache) |
michael@0 | 8045 | ss->sec.uncache(ss->sec.ci.sid); |
michael@0 | 8046 | PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */ |
michael@0 | 8047 | if (ss->sec.ci.sid != sid) { |
michael@0 | 8048 | ssl_FreeSID(ss->sec.ci.sid); |
michael@0 | 8049 | } |
michael@0 | 8050 | ss->sec.ci.sid = NULL; |
michael@0 | 8051 | } |
michael@0 | 8052 | /* we need to resurrect the master secret.... */ |
michael@0 | 8053 | |
michael@0 | 8054 | ssl_GetSpecWriteLock(ss); haveSpecWriteLock = PR_TRUE; |
michael@0 | 8055 | pwSpec = ss->ssl3.pwSpec; |
michael@0 | 8056 | if (sid->u.ssl3.keys.msIsWrapped) { |
michael@0 | 8057 | PK11SymKey * wrapKey; /* wrapping key */ |
michael@0 | 8058 | CK_FLAGS keyFlags = 0; |
michael@0 | 8059 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 8060 | if (ss->opt.bypassPKCS11) { |
michael@0 | 8061 | /* we cannot restart a non-bypass session in a |
michael@0 | 8062 | ** bypass socket. |
michael@0 | 8063 | */ |
michael@0 | 8064 | break; |
michael@0 | 8065 | } |
michael@0 | 8066 | #endif |
michael@0 | 8067 | |
michael@0 | 8068 | wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType, |
michael@0 | 8069 | sid->u.ssl3.masterWrapMech, |
michael@0 | 8070 | ss->pkcs11PinArg); |
michael@0 | 8071 | if (!wrapKey) { |
michael@0 | 8072 | /* we have a SID cache entry, but no wrapping key for it??? */ |
michael@0 | 8073 | break; |
michael@0 | 8074 | } |
michael@0 | 8075 | |
michael@0 | 8076 | if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ |
michael@0 | 8077 | keyFlags = CKF_SIGN | CKF_VERIFY; |
michael@0 | 8078 | } |
michael@0 | 8079 | |
michael@0 | 8080 | wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 8081 | wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 8082 | |
michael@0 | 8083 | /* unwrap the master secret. */ |
michael@0 | 8084 | pwSpec->master_secret = |
michael@0 | 8085 | PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, |
michael@0 | 8086 | NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, |
michael@0 | 8087 | CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); |
michael@0 | 8088 | PK11_FreeSymKey(wrapKey); |
michael@0 | 8089 | if (pwSpec->master_secret == NULL) { |
michael@0 | 8090 | break; /* not an error */ |
michael@0 | 8091 | } |
michael@0 | 8092 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 8093 | } else if (ss->opt.bypassPKCS11) { |
michael@0 | 8094 | wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 8095 | wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 8096 | memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); |
michael@0 | 8097 | pwSpec->msItem.data = pwSpec->raw_master_secret; |
michael@0 | 8098 | pwSpec->msItem.len = wrappedMS.len; |
michael@0 | 8099 | #endif |
michael@0 | 8100 | } else { |
michael@0 | 8101 | /* We CAN restart a bypass session in a non-bypass socket. */ |
michael@0 | 8102 | /* need to import the raw master secret to session object */ |
michael@0 | 8103 | PK11SlotInfo * slot; |
michael@0 | 8104 | wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 8105 | wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 8106 | slot = PK11_GetInternalSlot(); |
michael@0 | 8107 | pwSpec->master_secret = |
michael@0 | 8108 | PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, |
michael@0 | 8109 | PK11_OriginUnwrap, CKA_ENCRYPT, &wrappedMS, |
michael@0 | 8110 | NULL); |
michael@0 | 8111 | PK11_FreeSlot(slot); |
michael@0 | 8112 | if (pwSpec->master_secret == NULL) { |
michael@0 | 8113 | break; /* not an error */ |
michael@0 | 8114 | } |
michael@0 | 8115 | } |
michael@0 | 8116 | ss->sec.ci.sid = sid; |
michael@0 | 8117 | if (sid->peerCert != NULL) { |
michael@0 | 8118 | ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); |
michael@0 | 8119 | } |
michael@0 | 8120 | |
michael@0 | 8121 | /* |
michael@0 | 8122 | * Old SID passed all tests, so resume this old session. |
michael@0 | 8123 | * |
michael@0 | 8124 | * XXX make sure compression still matches |
michael@0 | 8125 | */ |
michael@0 | 8126 | SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_hits ); |
michael@0 | 8127 | if (ss->statelessResume) |
michael@0 | 8128 | SSL_AtomicIncrementLong(& ssl3stats.hch_sid_stateless_resumes ); |
michael@0 | 8129 | ss->ssl3.hs.isResuming = PR_TRUE; |
michael@0 | 8130 | |
michael@0 | 8131 | ss->sec.authAlgorithm = sid->authAlgorithm; |
michael@0 | 8132 | ss->sec.authKeyBits = sid->authKeyBits; |
michael@0 | 8133 | ss->sec.keaType = sid->keaType; |
michael@0 | 8134 | ss->sec.keaKeyBits = sid->keaKeyBits; |
michael@0 | 8135 | |
michael@0 | 8136 | /* server sids don't remember the server cert we previously sent, |
michael@0 | 8137 | ** but they do remember the kea type we originally used, so we |
michael@0 | 8138 | ** can locate it again, provided that the current ssl socket |
michael@0 | 8139 | ** has had its server certs configured the same as the previous one. |
michael@0 | 8140 | */ |
michael@0 | 8141 | ss->sec.localCert = |
michael@0 | 8142 | CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert); |
michael@0 | 8143 | |
michael@0 | 8144 | /* Copy cached name in to pending spec */ |
michael@0 | 8145 | if (sid != NULL && |
michael@0 | 8146 | sid->version > SSL_LIBRARY_VERSION_3_0 && |
michael@0 | 8147 | sid->u.ssl3.srvName.len && sid->u.ssl3.srvName.data) { |
michael@0 | 8148 | /* Set server name from sid */ |
michael@0 | 8149 | SECItem *sidName = &sid->u.ssl3.srvName; |
michael@0 | 8150 | SECItem *pwsName = &ss->ssl3.pwSpec->srvVirtName; |
michael@0 | 8151 | if (pwsName->data) { |
michael@0 | 8152 | SECITEM_FreeItem(pwsName, PR_FALSE); |
michael@0 | 8153 | } |
michael@0 | 8154 | rv = SECITEM_CopyItem(NULL, pwsName, sidName); |
michael@0 | 8155 | if (rv != SECSuccess) { |
michael@0 | 8156 | errCode = PORT_GetError(); |
michael@0 | 8157 | desc = internal_error; |
michael@0 | 8158 | goto alert_loser; |
michael@0 | 8159 | } |
michael@0 | 8160 | } |
michael@0 | 8161 | |
michael@0 | 8162 | /* Clean up sni name array */ |
michael@0 | 8163 | if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn) && |
michael@0 | 8164 | ss->xtnData.sniNameArr) { |
michael@0 | 8165 | PORT_Free(ss->xtnData.sniNameArr); |
michael@0 | 8166 | ss->xtnData.sniNameArr = NULL; |
michael@0 | 8167 | ss->xtnData.sniNameArrSize = 0; |
michael@0 | 8168 | } |
michael@0 | 8169 | |
michael@0 | 8170 | ssl_GetXmitBufLock(ss); haveXmitBufLock = PR_TRUE; |
michael@0 | 8171 | |
michael@0 | 8172 | rv = ssl3_SendServerHello(ss); |
michael@0 | 8173 | if (rv != SECSuccess) { |
michael@0 | 8174 | errCode = PORT_GetError(); |
michael@0 | 8175 | goto loser; |
michael@0 | 8176 | } |
michael@0 | 8177 | |
michael@0 | 8178 | if (haveSpecWriteLock) { |
michael@0 | 8179 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 8180 | haveSpecWriteLock = PR_FALSE; |
michael@0 | 8181 | } |
michael@0 | 8182 | |
michael@0 | 8183 | /* NULL value for PMS signifies re-use of the old MS */ |
michael@0 | 8184 | rv = ssl3_InitPendingCipherSpec(ss, NULL); |
michael@0 | 8185 | if (rv != SECSuccess) { |
michael@0 | 8186 | errCode = PORT_GetError(); |
michael@0 | 8187 | goto loser; |
michael@0 | 8188 | } |
michael@0 | 8189 | |
michael@0 | 8190 | rv = ssl3_SendChangeCipherSpecs(ss); |
michael@0 | 8191 | if (rv != SECSuccess) { |
michael@0 | 8192 | errCode = PORT_GetError(); |
michael@0 | 8193 | goto loser; |
michael@0 | 8194 | } |
michael@0 | 8195 | rv = ssl3_SendFinished(ss, 0); |
michael@0 | 8196 | ss->ssl3.hs.ws = wait_change_cipher; |
michael@0 | 8197 | if (rv != SECSuccess) { |
michael@0 | 8198 | errCode = PORT_GetError(); |
michael@0 | 8199 | goto loser; |
michael@0 | 8200 | } |
michael@0 | 8201 | |
michael@0 | 8202 | if (haveXmitBufLock) { |
michael@0 | 8203 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 8204 | haveXmitBufLock = PR_FALSE; |
michael@0 | 8205 | } |
michael@0 | 8206 | |
michael@0 | 8207 | return SECSuccess; |
michael@0 | 8208 | } while (0); |
michael@0 | 8209 | |
michael@0 | 8210 | if (haveSpecWriteLock) { |
michael@0 | 8211 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 8212 | haveSpecWriteLock = PR_FALSE; |
michael@0 | 8213 | } |
michael@0 | 8214 | |
michael@0 | 8215 | if (sid) { /* we had a sid, but it's no longer valid, free it */ |
michael@0 | 8216 | SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_not_ok ); |
michael@0 | 8217 | if (ss->sec.uncache) |
michael@0 | 8218 | ss->sec.uncache(sid); |
michael@0 | 8219 | ssl_FreeSID(sid); |
michael@0 | 8220 | sid = NULL; |
michael@0 | 8221 | } |
michael@0 | 8222 | SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses ); |
michael@0 | 8223 | |
michael@0 | 8224 | if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) { |
michael@0 | 8225 | int ret = 0; |
michael@0 | 8226 | if (ss->sniSocketConfig) do { /* not a loop */ |
michael@0 | 8227 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8228 | /* If extension is negotiated, the len of names should > 0. */ |
michael@0 | 8229 | if (ss->xtnData.sniNameArrSize) { |
michael@0 | 8230 | /* Calling client callback to reconfigure the socket. */ |
michael@0 | 8231 | ret = (SECStatus)(*ss->sniSocketConfig)(ss->fd, |
michael@0 | 8232 | ss->xtnData.sniNameArr, |
michael@0 | 8233 | ss->xtnData.sniNameArrSize, |
michael@0 | 8234 | ss->sniSocketConfigArg); |
michael@0 | 8235 | } |
michael@0 | 8236 | if (ret <= SSL_SNI_SEND_ALERT) { |
michael@0 | 8237 | /* Application does not know the name or was not able to |
michael@0 | 8238 | * properly reconfigure the socket. */ |
michael@0 | 8239 | errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT; |
michael@0 | 8240 | desc = unrecognized_name; |
michael@0 | 8241 | break; |
michael@0 | 8242 | } else if (ret == SSL_SNI_CURRENT_CONFIG_IS_USED) { |
michael@0 | 8243 | SECStatus rv = SECSuccess; |
michael@0 | 8244 | SECItem * cwsName, *pwsName; |
michael@0 | 8245 | |
michael@0 | 8246 | ssl_GetSpecWriteLock(ss); /*******************************/ |
michael@0 | 8247 | pwsName = &ss->ssl3.pwSpec->srvVirtName; |
michael@0 | 8248 | cwsName = &ss->ssl3.cwSpec->srvVirtName; |
michael@0 | 8249 | #ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS |
michael@0 | 8250 | /* not allow name change on the 2d HS */ |
michael@0 | 8251 | if (ss->firstHsDone) { |
michael@0 | 8252 | if (ssl3_ServerNameCompare(pwsName, cwsName)) { |
michael@0 | 8253 | ssl_ReleaseSpecWriteLock(ss); /******************/ |
michael@0 | 8254 | errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT; |
michael@0 | 8255 | desc = handshake_failure; |
michael@0 | 8256 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8257 | break; |
michael@0 | 8258 | } |
michael@0 | 8259 | } |
michael@0 | 8260 | #endif |
michael@0 | 8261 | if (pwsName->data) { |
michael@0 | 8262 | SECITEM_FreeItem(pwsName, PR_FALSE); |
michael@0 | 8263 | } |
michael@0 | 8264 | if (cwsName->data) { |
michael@0 | 8265 | rv = SECITEM_CopyItem(NULL, pwsName, cwsName); |
michael@0 | 8266 | } |
michael@0 | 8267 | ssl_ReleaseSpecWriteLock(ss); /**************************/ |
michael@0 | 8268 | if (rv != SECSuccess) { |
michael@0 | 8269 | errCode = SSL_ERROR_INTERNAL_ERROR_ALERT; |
michael@0 | 8270 | desc = internal_error; |
michael@0 | 8271 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8272 | break; |
michael@0 | 8273 | } |
michael@0 | 8274 | } else if (ret < ss->xtnData.sniNameArrSize) { |
michael@0 | 8275 | /* Application has configured new socket info. Lets check it |
michael@0 | 8276 | * and save the name. */ |
michael@0 | 8277 | SECStatus rv; |
michael@0 | 8278 | SECItem * name = &ss->xtnData.sniNameArr[ret]; |
michael@0 | 8279 | int configedCiphers; |
michael@0 | 8280 | SECItem * pwsName; |
michael@0 | 8281 | |
michael@0 | 8282 | /* get rid of the old name and save the newly picked. */ |
michael@0 | 8283 | /* This code is protected by ssl3HandshakeLock. */ |
michael@0 | 8284 | ssl_GetSpecWriteLock(ss); /*******************************/ |
michael@0 | 8285 | #ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS |
michael@0 | 8286 | /* not allow name change on the 2d HS */ |
michael@0 | 8287 | if (ss->firstHsDone) { |
michael@0 | 8288 | SECItem *cwsName = &ss->ssl3.cwSpec->srvVirtName; |
michael@0 | 8289 | if (ssl3_ServerNameCompare(name, cwsName)) { |
michael@0 | 8290 | ssl_ReleaseSpecWriteLock(ss); /******************/ |
michael@0 | 8291 | errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT; |
michael@0 | 8292 | desc = handshake_failure; |
michael@0 | 8293 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8294 | break; |
michael@0 | 8295 | } |
michael@0 | 8296 | } |
michael@0 | 8297 | #endif |
michael@0 | 8298 | pwsName = &ss->ssl3.pwSpec->srvVirtName; |
michael@0 | 8299 | if (pwsName->data) { |
michael@0 | 8300 | SECITEM_FreeItem(pwsName, PR_FALSE); |
michael@0 | 8301 | } |
michael@0 | 8302 | rv = SECITEM_CopyItem(NULL, pwsName, name); |
michael@0 | 8303 | ssl_ReleaseSpecWriteLock(ss); /***************************/ |
michael@0 | 8304 | if (rv != SECSuccess) { |
michael@0 | 8305 | errCode = SSL_ERROR_INTERNAL_ERROR_ALERT; |
michael@0 | 8306 | desc = internal_error; |
michael@0 | 8307 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8308 | break; |
michael@0 | 8309 | } |
michael@0 | 8310 | configedCiphers = ssl3_config_match_init(ss); |
michael@0 | 8311 | if (configedCiphers <= 0) { |
michael@0 | 8312 | /* no ciphers are working/supported */ |
michael@0 | 8313 | errCode = PORT_GetError(); |
michael@0 | 8314 | desc = handshake_failure; |
michael@0 | 8315 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8316 | break; |
michael@0 | 8317 | } |
michael@0 | 8318 | /* Need to tell the client that application has picked |
michael@0 | 8319 | * the name from the offered list and reconfigured the socket. |
michael@0 | 8320 | */ |
michael@0 | 8321 | ssl3_RegisterServerHelloExtensionSender(ss, ssl_server_name_xtn, |
michael@0 | 8322 | ssl3_SendServerNameXtn); |
michael@0 | 8323 | } else { |
michael@0 | 8324 | /* Callback returned index outside of the boundary. */ |
michael@0 | 8325 | PORT_Assert(ret < ss->xtnData.sniNameArrSize); |
michael@0 | 8326 | errCode = SSL_ERROR_INTERNAL_ERROR_ALERT; |
michael@0 | 8327 | desc = internal_error; |
michael@0 | 8328 | ret = SSL_SNI_SEND_ALERT; |
michael@0 | 8329 | break; |
michael@0 | 8330 | } |
michael@0 | 8331 | } while (0); |
michael@0 | 8332 | /* Free sniNameArr. The data that each SECItem in the array |
michael@0 | 8333 | * points into is the data from the input buffer "b". It will |
michael@0 | 8334 | * not be available outside the scope of this or it's child |
michael@0 | 8335 | * functions.*/ |
michael@0 | 8336 | if (ss->xtnData.sniNameArr) { |
michael@0 | 8337 | PORT_Free(ss->xtnData.sniNameArr); |
michael@0 | 8338 | ss->xtnData.sniNameArr = NULL; |
michael@0 | 8339 | ss->xtnData.sniNameArrSize = 0; |
michael@0 | 8340 | } |
michael@0 | 8341 | if (ret <= SSL_SNI_SEND_ALERT) { |
michael@0 | 8342 | /* desc and errCode should be set. */ |
michael@0 | 8343 | goto alert_loser; |
michael@0 | 8344 | } |
michael@0 | 8345 | } |
michael@0 | 8346 | #ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS |
michael@0 | 8347 | else if (ss->firstHsDone) { |
michael@0 | 8348 | /* Check that we don't have the name is current spec |
michael@0 | 8349 | * if this extension was not negotiated on the 2d hs. */ |
michael@0 | 8350 | PRBool passed = PR_TRUE; |
michael@0 | 8351 | ssl_GetSpecReadLock(ss); /*******************************/ |
michael@0 | 8352 | if (ss->ssl3.cwSpec->srvVirtName.data) { |
michael@0 | 8353 | passed = PR_FALSE; |
michael@0 | 8354 | } |
michael@0 | 8355 | ssl_ReleaseSpecReadLock(ss); /***************************/ |
michael@0 | 8356 | if (!passed) { |
michael@0 | 8357 | errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT; |
michael@0 | 8358 | desc = handshake_failure; |
michael@0 | 8359 | goto alert_loser; |
michael@0 | 8360 | } |
michael@0 | 8361 | } |
michael@0 | 8362 | #endif |
michael@0 | 8363 | |
michael@0 | 8364 | sid = ssl3_NewSessionID(ss, PR_TRUE); |
michael@0 | 8365 | if (sid == NULL) { |
michael@0 | 8366 | errCode = PORT_GetError(); |
michael@0 | 8367 | goto loser; /* memory error is set. */ |
michael@0 | 8368 | } |
michael@0 | 8369 | ss->sec.ci.sid = sid; |
michael@0 | 8370 | |
michael@0 | 8371 | ss->ssl3.hs.isResuming = PR_FALSE; |
michael@0 | 8372 | ssl_GetXmitBufLock(ss); |
michael@0 | 8373 | rv = ssl3_SendServerHelloSequence(ss); |
michael@0 | 8374 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 8375 | if (rv != SECSuccess) { |
michael@0 | 8376 | errCode = PORT_GetError(); |
michael@0 | 8377 | goto loser; |
michael@0 | 8378 | } |
michael@0 | 8379 | |
michael@0 | 8380 | if (haveXmitBufLock) { |
michael@0 | 8381 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 8382 | haveXmitBufLock = PR_FALSE; |
michael@0 | 8383 | } |
michael@0 | 8384 | |
michael@0 | 8385 | return SECSuccess; |
michael@0 | 8386 | |
michael@0 | 8387 | alert_loser: |
michael@0 | 8388 | if (haveSpecWriteLock) { |
michael@0 | 8389 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 8390 | haveSpecWriteLock = PR_FALSE; |
michael@0 | 8391 | } |
michael@0 | 8392 | (void)SSL3_SendAlert(ss, level, desc); |
michael@0 | 8393 | /* FALLTHRU */ |
michael@0 | 8394 | loser: |
michael@0 | 8395 | if (haveSpecWriteLock) { |
michael@0 | 8396 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 8397 | haveSpecWriteLock = PR_FALSE; |
michael@0 | 8398 | } |
michael@0 | 8399 | |
michael@0 | 8400 | if (haveXmitBufLock) { |
michael@0 | 8401 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 8402 | haveXmitBufLock = PR_FALSE; |
michael@0 | 8403 | } |
michael@0 | 8404 | |
michael@0 | 8405 | PORT_SetError(errCode); |
michael@0 | 8406 | return SECFailure; |
michael@0 | 8407 | } |
michael@0 | 8408 | |
michael@0 | 8409 | /* |
michael@0 | 8410 | * ssl3_HandleV2ClientHello is used when a V2 formatted hello comes |
michael@0 | 8411 | * in asking to use the V3 handshake. |
michael@0 | 8412 | * Called from ssl2_HandleClientHelloMessage() in sslcon.c |
michael@0 | 8413 | */ |
michael@0 | 8414 | SECStatus |
michael@0 | 8415 | ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) |
michael@0 | 8416 | { |
michael@0 | 8417 | sslSessionID * sid = NULL; |
michael@0 | 8418 | unsigned char * suites; |
michael@0 | 8419 | unsigned char * random; |
michael@0 | 8420 | SSL3ProtocolVersion version; |
michael@0 | 8421 | SECStatus rv; |
michael@0 | 8422 | int i; |
michael@0 | 8423 | int j; |
michael@0 | 8424 | int sid_length; |
michael@0 | 8425 | int suite_length; |
michael@0 | 8426 | int rand_length; |
michael@0 | 8427 | int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_HELLO; |
michael@0 | 8428 | SSL3AlertDescription desc = handshake_failure; |
michael@0 | 8429 | |
michael@0 | 8430 | SSL_TRC(3, ("%d: SSL3[%d]: handle v2 client_hello", SSL_GETPID(), ss->fd)); |
michael@0 | 8431 | |
michael@0 | 8432 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 8433 | |
michael@0 | 8434 | ssl_GetSSL3HandshakeLock(ss); |
michael@0 | 8435 | |
michael@0 | 8436 | PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); |
michael@0 | 8437 | |
michael@0 | 8438 | rv = ssl3_InitState(ss); |
michael@0 | 8439 | if (rv != SECSuccess) { |
michael@0 | 8440 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 8441 | return rv; /* ssl3_InitState has set the error code. */ |
michael@0 | 8442 | } |
michael@0 | 8443 | rv = ssl3_RestartHandshakeHashes(ss); |
michael@0 | 8444 | if (rv != SECSuccess) { |
michael@0 | 8445 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 8446 | return rv; |
michael@0 | 8447 | } |
michael@0 | 8448 | |
michael@0 | 8449 | if (ss->ssl3.hs.ws != wait_client_hello) { |
michael@0 | 8450 | desc = unexpected_message; |
michael@0 | 8451 | errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO; |
michael@0 | 8452 | goto loser; /* alert_loser */ |
michael@0 | 8453 | } |
michael@0 | 8454 | |
michael@0 | 8455 | version = (buffer[1] << 8) | buffer[2]; |
michael@0 | 8456 | suite_length = (buffer[3] << 8) | buffer[4]; |
michael@0 | 8457 | sid_length = (buffer[5] << 8) | buffer[6]; |
michael@0 | 8458 | rand_length = (buffer[7] << 8) | buffer[8]; |
michael@0 | 8459 | ss->clientHelloVersion = version; |
michael@0 | 8460 | |
michael@0 | 8461 | rv = ssl3_NegotiateVersion(ss, version, PR_TRUE); |
michael@0 | 8462 | if (rv != SECSuccess) { |
michael@0 | 8463 | /* send back which ever alert client will understand. */ |
michael@0 | 8464 | desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure; |
michael@0 | 8465 | errCode = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 8466 | goto alert_loser; |
michael@0 | 8467 | } |
michael@0 | 8468 | |
michael@0 | 8469 | rv = ssl3_InitHandshakeHashes(ss); |
michael@0 | 8470 | if (rv != SECSuccess) { |
michael@0 | 8471 | desc = internal_error; |
michael@0 | 8472 | errCode = PORT_GetError(); |
michael@0 | 8473 | goto alert_loser; |
michael@0 | 8474 | } |
michael@0 | 8475 | |
michael@0 | 8476 | /* if we get a non-zero SID, just ignore it. */ |
michael@0 | 8477 | if (length != |
michael@0 | 8478 | SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length + rand_length) { |
michael@0 | 8479 | SSL_DBG(("%d: SSL3[%d]: bad v2 client hello message, len=%d should=%d", |
michael@0 | 8480 | SSL_GETPID(), ss->fd, length, |
michael@0 | 8481 | SSL_HL_CLIENT_HELLO_HBYTES + suite_length + sid_length + |
michael@0 | 8482 | rand_length)); |
michael@0 | 8483 | goto loser; /* malformed */ /* alert_loser */ |
michael@0 | 8484 | } |
michael@0 | 8485 | |
michael@0 | 8486 | suites = buffer + SSL_HL_CLIENT_HELLO_HBYTES; |
michael@0 | 8487 | random = suites + suite_length + sid_length; |
michael@0 | 8488 | |
michael@0 | 8489 | if (rand_length < SSL_MIN_CHALLENGE_BYTES || |
michael@0 | 8490 | rand_length > SSL_MAX_CHALLENGE_BYTES) { |
michael@0 | 8491 | goto loser; /* malformed */ /* alert_loser */ |
michael@0 | 8492 | } |
michael@0 | 8493 | |
michael@0 | 8494 | PORT_Assert(SSL_MAX_CHALLENGE_BYTES == SSL3_RANDOM_LENGTH); |
michael@0 | 8495 | |
michael@0 | 8496 | PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH); |
michael@0 | 8497 | PORT_Memcpy( |
michael@0 | 8498 | &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length], |
michael@0 | 8499 | random, rand_length); |
michael@0 | 8500 | |
michael@0 | 8501 | PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0], |
michael@0 | 8502 | SSL3_RANDOM_LENGTH)); |
michael@0 | 8503 | #ifndef NSS_DISABLE_ECC |
michael@0 | 8504 | /* Disable any ECC cipher suites for which we have no cert. */ |
michael@0 | 8505 | ssl3_FilterECCipherSuitesByServerCerts(ss); |
michael@0 | 8506 | #endif |
michael@0 | 8507 | i = ssl3_config_match_init(ss); |
michael@0 | 8508 | if (i <= 0) { |
michael@0 | 8509 | errCode = PORT_GetError(); /* error code is already set. */ |
michael@0 | 8510 | goto alert_loser; |
michael@0 | 8511 | } |
michael@0 | 8512 | |
michael@0 | 8513 | /* Select a cipher suite. |
michael@0 | 8514 | ** |
michael@0 | 8515 | ** NOTE: This suite selection algorithm should be the same as the one in |
michael@0 | 8516 | ** ssl3_HandleClientHello(). |
michael@0 | 8517 | ** |
michael@0 | 8518 | ** See the comments about export cipher suites in ssl3_HandleClientHello(). |
michael@0 | 8519 | */ |
michael@0 | 8520 | for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) { |
michael@0 | 8521 | ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j]; |
michael@0 | 8522 | SSLVersionRange vrange = {ss->version, ss->version}; |
michael@0 | 8523 | if (!config_match(suite, ss->ssl3.policy, PR_TRUE, &vrange)) { |
michael@0 | 8524 | continue; |
michael@0 | 8525 | } |
michael@0 | 8526 | for (i = 0; i+2 < suite_length; i += 3) { |
michael@0 | 8527 | PRUint32 suite_i = (suites[i] << 16)|(suites[i+1] << 8)|suites[i+2]; |
michael@0 | 8528 | if (suite_i == suite->cipher_suite) { |
michael@0 | 8529 | ss->ssl3.hs.cipher_suite = suite->cipher_suite; |
michael@0 | 8530 | ss->ssl3.hs.suite_def = |
michael@0 | 8531 | ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); |
michael@0 | 8532 | goto suite_found; |
michael@0 | 8533 | } |
michael@0 | 8534 | } |
michael@0 | 8535 | } |
michael@0 | 8536 | errCode = SSL_ERROR_NO_CYPHER_OVERLAP; |
michael@0 | 8537 | goto alert_loser; |
michael@0 | 8538 | |
michael@0 | 8539 | suite_found: |
michael@0 | 8540 | |
michael@0 | 8541 | /* Look for the SCSV, and if found, treat it just like an empty RI |
michael@0 | 8542 | * extension by processing a local copy of an empty RI extension. |
michael@0 | 8543 | */ |
michael@0 | 8544 | for (i = 0; i+2 < suite_length; i += 3) { |
michael@0 | 8545 | PRUint32 suite_i = (suites[i] << 16) | (suites[i+1] << 8) | suites[i+2]; |
michael@0 | 8546 | if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { |
michael@0 | 8547 | SSL3Opaque * b2 = (SSL3Opaque *)emptyRIext; |
michael@0 | 8548 | PRUint32 L2 = sizeof emptyRIext; |
michael@0 | 8549 | (void)ssl3_HandleHelloExtensions(ss, &b2, &L2); |
michael@0 | 8550 | break; |
michael@0 | 8551 | } |
michael@0 | 8552 | } |
michael@0 | 8553 | |
michael@0 | 8554 | if (ss->opt.requireSafeNegotiation && |
michael@0 | 8555 | !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) { |
michael@0 | 8556 | desc = handshake_failure; |
michael@0 | 8557 | errCode = SSL_ERROR_UNSAFE_NEGOTIATION; |
michael@0 | 8558 | goto alert_loser; |
michael@0 | 8559 | } |
michael@0 | 8560 | |
michael@0 | 8561 | ss->ssl3.hs.compression = ssl_compression_null; |
michael@0 | 8562 | ss->sec.send = ssl3_SendApplicationData; |
michael@0 | 8563 | |
michael@0 | 8564 | /* we don't even search for a cache hit here. It's just a miss. */ |
michael@0 | 8565 | SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses ); |
michael@0 | 8566 | sid = ssl3_NewSessionID(ss, PR_TRUE); |
michael@0 | 8567 | if (sid == NULL) { |
michael@0 | 8568 | errCode = PORT_GetError(); |
michael@0 | 8569 | goto loser; /* memory error is set. */ |
michael@0 | 8570 | } |
michael@0 | 8571 | ss->sec.ci.sid = sid; |
michael@0 | 8572 | /* do not worry about memory leak of sid since it now belongs to ci */ |
michael@0 | 8573 | |
michael@0 | 8574 | /* We have to update the handshake hashes before we can send stuff */ |
michael@0 | 8575 | rv = ssl3_UpdateHandshakeHashes(ss, buffer, length); |
michael@0 | 8576 | if (rv != SECSuccess) { |
michael@0 | 8577 | errCode = PORT_GetError(); |
michael@0 | 8578 | goto loser; |
michael@0 | 8579 | } |
michael@0 | 8580 | |
michael@0 | 8581 | ssl_GetXmitBufLock(ss); |
michael@0 | 8582 | rv = ssl3_SendServerHelloSequence(ss); |
michael@0 | 8583 | ssl_ReleaseXmitBufLock(ss); |
michael@0 | 8584 | if (rv != SECSuccess) { |
michael@0 | 8585 | errCode = PORT_GetError(); |
michael@0 | 8586 | goto loser; |
michael@0 | 8587 | } |
michael@0 | 8588 | |
michael@0 | 8589 | /* XXX_1 The call stack to here is: |
michael@0 | 8590 | * ssl_Do1stHandshake -> ssl2_HandleClientHelloMessage -> here. |
michael@0 | 8591 | * ssl2_HandleClientHelloMessage returns whatever we return here. |
michael@0 | 8592 | * ssl_Do1stHandshake will continue looping if it gets back either |
michael@0 | 8593 | * SECSuccess or SECWouldBlock. |
michael@0 | 8594 | * SECSuccess is preferable here. See XXX_1 in sslgathr.c. |
michael@0 | 8595 | */ |
michael@0 | 8596 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 8597 | return SECSuccess; |
michael@0 | 8598 | |
michael@0 | 8599 | alert_loser: |
michael@0 | 8600 | SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 8601 | loser: |
michael@0 | 8602 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 8603 | PORT_SetError(errCode); |
michael@0 | 8604 | return SECFailure; |
michael@0 | 8605 | } |
michael@0 | 8606 | |
michael@0 | 8607 | /* The negotiated version number has been already placed in ss->version. |
michael@0 | 8608 | ** |
michael@0 | 8609 | ** Called from: ssl3_HandleClientHello (resuming session), |
michael@0 | 8610 | ** ssl3_SendServerHelloSequence <- ssl3_HandleClientHello (new session), |
michael@0 | 8611 | ** ssl3_SendServerHelloSequence <- ssl3_HandleV2ClientHello (new session) |
michael@0 | 8612 | */ |
michael@0 | 8613 | static SECStatus |
michael@0 | 8614 | ssl3_SendServerHello(sslSocket *ss) |
michael@0 | 8615 | { |
michael@0 | 8616 | sslSessionID *sid; |
michael@0 | 8617 | SECStatus rv; |
michael@0 | 8618 | PRUint32 maxBytes = 65535; |
michael@0 | 8619 | PRUint32 length; |
michael@0 | 8620 | PRInt32 extensions_len = 0; |
michael@0 | 8621 | SSL3ProtocolVersion version; |
michael@0 | 8622 | |
michael@0 | 8623 | SSL_TRC(3, ("%d: SSL3[%d]: send server_hello handshake", SSL_GETPID(), |
michael@0 | 8624 | ss->fd)); |
michael@0 | 8625 | |
michael@0 | 8626 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 8627 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 8628 | |
michael@0 | 8629 | if (!IS_DTLS(ss)) { |
michael@0 | 8630 | PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0)); |
michael@0 | 8631 | |
michael@0 | 8632 | if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) { |
michael@0 | 8633 | PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); |
michael@0 | 8634 | return SECFailure; |
michael@0 | 8635 | } |
michael@0 | 8636 | } else { |
michael@0 | 8637 | PORT_Assert(MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_DTLS_1_0)); |
michael@0 | 8638 | |
michael@0 | 8639 | if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_DTLS_1_0)) { |
michael@0 | 8640 | PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); |
michael@0 | 8641 | return SECFailure; |
michael@0 | 8642 | } |
michael@0 | 8643 | } |
michael@0 | 8644 | |
michael@0 | 8645 | sid = ss->sec.ci.sid; |
michael@0 | 8646 | |
michael@0 | 8647 | extensions_len = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, |
michael@0 | 8648 | &ss->xtnData.serverSenders[0]); |
michael@0 | 8649 | if (extensions_len > 0) |
michael@0 | 8650 | extensions_len += 2; /* Add sizeof total extension length */ |
michael@0 | 8651 | |
michael@0 | 8652 | length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH + 1 + |
michael@0 | 8653 | ((sid == NULL) ? 0: sid->u.ssl3.sessionIDLength) + |
michael@0 | 8654 | sizeof(ssl3CipherSuite) + 1 + extensions_len; |
michael@0 | 8655 | rv = ssl3_AppendHandshakeHeader(ss, server_hello, length); |
michael@0 | 8656 | if (rv != SECSuccess) { |
michael@0 | 8657 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8658 | } |
michael@0 | 8659 | |
michael@0 | 8660 | if (IS_DTLS(ss)) { |
michael@0 | 8661 | version = dtls_TLSVersionToDTLSVersion(ss->version); |
michael@0 | 8662 | } else { |
michael@0 | 8663 | version = ss->version; |
michael@0 | 8664 | } |
michael@0 | 8665 | |
michael@0 | 8666 | rv = ssl3_AppendHandshakeNumber(ss, version, 2); |
michael@0 | 8667 | if (rv != SECSuccess) { |
michael@0 | 8668 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8669 | } |
michael@0 | 8670 | rv = ssl3_GetNewRandom(&ss->ssl3.hs.server_random); |
michael@0 | 8671 | if (rv != SECSuccess) { |
michael@0 | 8672 | ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); |
michael@0 | 8673 | return rv; |
michael@0 | 8674 | } |
michael@0 | 8675 | rv = ssl3_AppendHandshake( |
michael@0 | 8676 | ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH); |
michael@0 | 8677 | if (rv != SECSuccess) { |
michael@0 | 8678 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8679 | } |
michael@0 | 8680 | |
michael@0 | 8681 | if (sid) |
michael@0 | 8682 | rv = ssl3_AppendHandshakeVariable( |
michael@0 | 8683 | ss, sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength, 1); |
michael@0 | 8684 | else |
michael@0 | 8685 | rv = ssl3_AppendHandshakeNumber(ss, 0, 1); |
michael@0 | 8686 | if (rv != SECSuccess) { |
michael@0 | 8687 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8688 | } |
michael@0 | 8689 | |
michael@0 | 8690 | rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2); |
michael@0 | 8691 | if (rv != SECSuccess) { |
michael@0 | 8692 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8693 | } |
michael@0 | 8694 | rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1); |
michael@0 | 8695 | if (rv != SECSuccess) { |
michael@0 | 8696 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8697 | } |
michael@0 | 8698 | if (extensions_len) { |
michael@0 | 8699 | PRInt32 sent_len; |
michael@0 | 8700 | |
michael@0 | 8701 | extensions_len -= 2; |
michael@0 | 8702 | rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2); |
michael@0 | 8703 | if (rv != SECSuccess) |
michael@0 | 8704 | return rv; /* err set by ssl3_SetupPendingCipherSpec */ |
michael@0 | 8705 | sent_len = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extensions_len, |
michael@0 | 8706 | &ss->xtnData.serverSenders[0]); |
michael@0 | 8707 | PORT_Assert(sent_len == extensions_len); |
michael@0 | 8708 | if (sent_len != extensions_len) { |
michael@0 | 8709 | if (sent_len >= 0) |
michael@0 | 8710 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 8711 | return SECFailure; |
michael@0 | 8712 | } |
michael@0 | 8713 | } |
michael@0 | 8714 | rv = ssl3_SetupPendingCipherSpec(ss); |
michael@0 | 8715 | if (rv != SECSuccess) { |
michael@0 | 8716 | return rv; /* err set by ssl3_SetupPendingCipherSpec */ |
michael@0 | 8717 | } |
michael@0 | 8718 | |
michael@0 | 8719 | return SECSuccess; |
michael@0 | 8720 | } |
michael@0 | 8721 | |
michael@0 | 8722 | /* ssl3_PickSignatureHashAlgorithm selects a hash algorithm to use when signing |
michael@0 | 8723 | * elements of the handshake. (The negotiated cipher suite determines the |
michael@0 | 8724 | * signature algorithm.) Prior to TLS 1.2, the MD5/SHA1 combination is always |
michael@0 | 8725 | * used. With TLS 1.2, a client may advertise its support for signature and |
michael@0 | 8726 | * hash combinations. */ |
michael@0 | 8727 | static SECStatus |
michael@0 | 8728 | ssl3_PickSignatureHashAlgorithm(sslSocket *ss, |
michael@0 | 8729 | SSL3SignatureAndHashAlgorithm* out) |
michael@0 | 8730 | { |
michael@0 | 8731 | TLSSignatureAlgorithm sigAlg; |
michael@0 | 8732 | unsigned int i, j; |
michael@0 | 8733 | /* hashPreference expresses our preferences for hash algorithms, most |
michael@0 | 8734 | * preferable first. */ |
michael@0 | 8735 | static const PRUint8 hashPreference[] = { |
michael@0 | 8736 | tls_hash_sha256, |
michael@0 | 8737 | tls_hash_sha384, |
michael@0 | 8738 | tls_hash_sha512, |
michael@0 | 8739 | tls_hash_sha1, |
michael@0 | 8740 | }; |
michael@0 | 8741 | |
michael@0 | 8742 | switch (ss->ssl3.hs.kea_def->kea) { |
michael@0 | 8743 | case kea_rsa: |
michael@0 | 8744 | case kea_rsa_export: |
michael@0 | 8745 | case kea_rsa_export_1024: |
michael@0 | 8746 | case kea_dh_rsa: |
michael@0 | 8747 | case kea_dh_rsa_export: |
michael@0 | 8748 | case kea_dhe_rsa: |
michael@0 | 8749 | case kea_dhe_rsa_export: |
michael@0 | 8750 | case kea_rsa_fips: |
michael@0 | 8751 | case kea_ecdh_rsa: |
michael@0 | 8752 | case kea_ecdhe_rsa: |
michael@0 | 8753 | sigAlg = tls_sig_rsa; |
michael@0 | 8754 | break; |
michael@0 | 8755 | case kea_dh_dss: |
michael@0 | 8756 | case kea_dh_dss_export: |
michael@0 | 8757 | case kea_dhe_dss: |
michael@0 | 8758 | case kea_dhe_dss_export: |
michael@0 | 8759 | sigAlg = tls_sig_dsa; |
michael@0 | 8760 | break; |
michael@0 | 8761 | case kea_ecdh_ecdsa: |
michael@0 | 8762 | case kea_ecdhe_ecdsa: |
michael@0 | 8763 | sigAlg = tls_sig_ecdsa; |
michael@0 | 8764 | break; |
michael@0 | 8765 | default: |
michael@0 | 8766 | PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
michael@0 | 8767 | return SECFailure; |
michael@0 | 8768 | } |
michael@0 | 8769 | out->sigAlg = sigAlg; |
michael@0 | 8770 | |
michael@0 | 8771 | if (ss->version <= SSL_LIBRARY_VERSION_TLS_1_1) { |
michael@0 | 8772 | /* SEC_OID_UNKNOWN means the MD5/SHA1 combo hash used in TLS 1.1 and |
michael@0 | 8773 | * prior. */ |
michael@0 | 8774 | out->hashAlg = SEC_OID_UNKNOWN; |
michael@0 | 8775 | return SECSuccess; |
michael@0 | 8776 | } |
michael@0 | 8777 | |
michael@0 | 8778 | if (ss->ssl3.hs.numClientSigAndHash == 0) { |
michael@0 | 8779 | /* If the client didn't provide any signature_algorithms extension then |
michael@0 | 8780 | * we can assume that they support SHA-1: |
michael@0 | 8781 | * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
michael@0 | 8782 | out->hashAlg = SEC_OID_SHA1; |
michael@0 | 8783 | return SECSuccess; |
michael@0 | 8784 | } |
michael@0 | 8785 | |
michael@0 | 8786 | for (i = 0; i < PR_ARRAY_SIZE(hashPreference); i++) { |
michael@0 | 8787 | for (j = 0; j < ss->ssl3.hs.numClientSigAndHash; j++) { |
michael@0 | 8788 | const SSL3SignatureAndHashAlgorithm* sh = |
michael@0 | 8789 | &ss->ssl3.hs.clientSigAndHash[j]; |
michael@0 | 8790 | if (sh->sigAlg == sigAlg && sh->hashAlg == hashPreference[i]) { |
michael@0 | 8791 | out->hashAlg = sh->hashAlg; |
michael@0 | 8792 | return SECSuccess; |
michael@0 | 8793 | } |
michael@0 | 8794 | } |
michael@0 | 8795 | } |
michael@0 | 8796 | |
michael@0 | 8797 | PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); |
michael@0 | 8798 | return SECFailure; |
michael@0 | 8799 | } |
michael@0 | 8800 | |
michael@0 | 8801 | |
michael@0 | 8802 | static SECStatus |
michael@0 | 8803 | ssl3_SendServerKeyExchange(sslSocket *ss) |
michael@0 | 8804 | { |
michael@0 | 8805 | const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; |
michael@0 | 8806 | SECStatus rv = SECFailure; |
michael@0 | 8807 | int length; |
michael@0 | 8808 | PRBool isTLS; |
michael@0 | 8809 | SECItem signed_hash = {siBuffer, NULL, 0}; |
michael@0 | 8810 | SSL3Hashes hashes; |
michael@0 | 8811 | SECKEYPublicKey * sdPub; /* public key for step-down */ |
michael@0 | 8812 | SSL3SignatureAndHashAlgorithm sigAndHash; |
michael@0 | 8813 | |
michael@0 | 8814 | SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake", |
michael@0 | 8815 | SSL_GETPID(), ss->fd)); |
michael@0 | 8816 | |
michael@0 | 8817 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 8818 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 8819 | |
michael@0 | 8820 | if (ssl3_PickSignatureHashAlgorithm(ss, &sigAndHash) != SECSuccess) { |
michael@0 | 8821 | return SECFailure; |
michael@0 | 8822 | } |
michael@0 | 8823 | |
michael@0 | 8824 | switch (kea_def->exchKeyType) { |
michael@0 | 8825 | case kt_rsa: |
michael@0 | 8826 | /* Perform SSL Step-Down here. */ |
michael@0 | 8827 | sdPub = ss->stepDownKeyPair->pubKey; |
michael@0 | 8828 | PORT_Assert(sdPub != NULL); |
michael@0 | 8829 | if (!sdPub) { |
michael@0 | 8830 | PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 8831 | return SECFailure; |
michael@0 | 8832 | } |
michael@0 | 8833 | rv = ssl3_ComputeExportRSAKeyHash(sigAndHash.hashAlg, |
michael@0 | 8834 | sdPub->u.rsa.modulus, |
michael@0 | 8835 | sdPub->u.rsa.publicExponent, |
michael@0 | 8836 | &ss->ssl3.hs.client_random, |
michael@0 | 8837 | &ss->ssl3.hs.server_random, |
michael@0 | 8838 | &hashes, ss->opt.bypassPKCS11); |
michael@0 | 8839 | if (rv != SECSuccess) { |
michael@0 | 8840 | ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 8841 | return rv; |
michael@0 | 8842 | } |
michael@0 | 8843 | |
michael@0 | 8844 | isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 8845 | rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].SERVERKEY, |
michael@0 | 8846 | &signed_hash, isTLS); |
michael@0 | 8847 | if (rv != SECSuccess) { |
michael@0 | 8848 | goto loser; /* ssl3_SignHashes has set err. */ |
michael@0 | 8849 | } |
michael@0 | 8850 | if (signed_hash.data == NULL) { |
michael@0 | 8851 | /* how can this happen and rv == SECSuccess ?? */ |
michael@0 | 8852 | PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
michael@0 | 8853 | goto loser; |
michael@0 | 8854 | } |
michael@0 | 8855 | length = 2 + sdPub->u.rsa.modulus.len + |
michael@0 | 8856 | 2 + sdPub->u.rsa.publicExponent.len + |
michael@0 | 8857 | 2 + signed_hash.len; |
michael@0 | 8858 | |
michael@0 | 8859 | rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); |
michael@0 | 8860 | if (rv != SECSuccess) { |
michael@0 | 8861 | goto loser; /* err set by AppendHandshake. */ |
michael@0 | 8862 | } |
michael@0 | 8863 | |
michael@0 | 8864 | rv = ssl3_AppendHandshakeVariable(ss, sdPub->u.rsa.modulus.data, |
michael@0 | 8865 | sdPub->u.rsa.modulus.len, 2); |
michael@0 | 8866 | if (rv != SECSuccess) { |
michael@0 | 8867 | goto loser; /* err set by AppendHandshake. */ |
michael@0 | 8868 | } |
michael@0 | 8869 | |
michael@0 | 8870 | rv = ssl3_AppendHandshakeVariable( |
michael@0 | 8871 | ss, sdPub->u.rsa.publicExponent.data, |
michael@0 | 8872 | sdPub->u.rsa.publicExponent.len, 2); |
michael@0 | 8873 | if (rv != SECSuccess) { |
michael@0 | 8874 | goto loser; /* err set by AppendHandshake. */ |
michael@0 | 8875 | } |
michael@0 | 8876 | |
michael@0 | 8877 | if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 8878 | rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash); |
michael@0 | 8879 | if (rv != SECSuccess) { |
michael@0 | 8880 | goto loser; /* err set by AppendHandshake. */ |
michael@0 | 8881 | } |
michael@0 | 8882 | } |
michael@0 | 8883 | |
michael@0 | 8884 | rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data, |
michael@0 | 8885 | signed_hash.len, 2); |
michael@0 | 8886 | if (rv != SECSuccess) { |
michael@0 | 8887 | goto loser; /* err set by AppendHandshake. */ |
michael@0 | 8888 | } |
michael@0 | 8889 | PORT_Free(signed_hash.data); |
michael@0 | 8890 | return SECSuccess; |
michael@0 | 8891 | |
michael@0 | 8892 | #ifndef NSS_DISABLE_ECC |
michael@0 | 8893 | case kt_ecdh: { |
michael@0 | 8894 | rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash); |
michael@0 | 8895 | return rv; |
michael@0 | 8896 | } |
michael@0 | 8897 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 8898 | |
michael@0 | 8899 | case kt_dh: |
michael@0 | 8900 | case kt_null: |
michael@0 | 8901 | default: |
michael@0 | 8902 | PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
michael@0 | 8903 | break; |
michael@0 | 8904 | } |
michael@0 | 8905 | loser: |
michael@0 | 8906 | if (signed_hash.data != NULL) |
michael@0 | 8907 | PORT_Free(signed_hash.data); |
michael@0 | 8908 | return SECFailure; |
michael@0 | 8909 | } |
michael@0 | 8910 | |
michael@0 | 8911 | |
michael@0 | 8912 | static SECStatus |
michael@0 | 8913 | ssl3_SendCertificateRequest(sslSocket *ss) |
michael@0 | 8914 | { |
michael@0 | 8915 | PRBool isTLS12; |
michael@0 | 8916 | SECItem * name; |
michael@0 | 8917 | CERTDistNames *ca_list; |
michael@0 | 8918 | const PRUint8 *certTypes; |
michael@0 | 8919 | const PRUint8 *sigAlgs; |
michael@0 | 8920 | SECItem * names = NULL; |
michael@0 | 8921 | SECStatus rv; |
michael@0 | 8922 | int length; |
michael@0 | 8923 | int i; |
michael@0 | 8924 | int calen = 0; |
michael@0 | 8925 | int nnames = 0; |
michael@0 | 8926 | int certTypesLength; |
michael@0 | 8927 | int sigAlgsLength; |
michael@0 | 8928 | |
michael@0 | 8929 | SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake", |
michael@0 | 8930 | SSL_GETPID(), ss->fd)); |
michael@0 | 8931 | |
michael@0 | 8932 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 8933 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 8934 | |
michael@0 | 8935 | isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 8936 | |
michael@0 | 8937 | /* ssl3.ca_list is initialized to NULL, and never changed. */ |
michael@0 | 8938 | ca_list = ss->ssl3.ca_list; |
michael@0 | 8939 | if (!ca_list) { |
michael@0 | 8940 | ca_list = ssl3_server_ca_list; |
michael@0 | 8941 | } |
michael@0 | 8942 | |
michael@0 | 8943 | if (ca_list != NULL) { |
michael@0 | 8944 | names = ca_list->names; |
michael@0 | 8945 | nnames = ca_list->nnames; |
michael@0 | 8946 | } |
michael@0 | 8947 | |
michael@0 | 8948 | for (i = 0, name = names; i < nnames; i++, name++) { |
michael@0 | 8949 | calen += 2 + name->len; |
michael@0 | 8950 | } |
michael@0 | 8951 | |
michael@0 | 8952 | certTypes = certificate_types; |
michael@0 | 8953 | certTypesLength = sizeof certificate_types; |
michael@0 | 8954 | sigAlgs = supported_signature_algorithms; |
michael@0 | 8955 | sigAlgsLength = sizeof supported_signature_algorithms; |
michael@0 | 8956 | |
michael@0 | 8957 | length = 1 + certTypesLength + 2 + calen; |
michael@0 | 8958 | if (isTLS12) { |
michael@0 | 8959 | length += 2 + sigAlgsLength; |
michael@0 | 8960 | } |
michael@0 | 8961 | |
michael@0 | 8962 | rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length); |
michael@0 | 8963 | if (rv != SECSuccess) { |
michael@0 | 8964 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8965 | } |
michael@0 | 8966 | rv = ssl3_AppendHandshakeVariable(ss, certTypes, certTypesLength, 1); |
michael@0 | 8967 | if (rv != SECSuccess) { |
michael@0 | 8968 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8969 | } |
michael@0 | 8970 | if (isTLS12) { |
michael@0 | 8971 | rv = ssl3_AppendHandshakeVariable(ss, sigAlgs, sigAlgsLength, 2); |
michael@0 | 8972 | if (rv != SECSuccess) { |
michael@0 | 8973 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8974 | } |
michael@0 | 8975 | } |
michael@0 | 8976 | rv = ssl3_AppendHandshakeNumber(ss, calen, 2); |
michael@0 | 8977 | if (rv != SECSuccess) { |
michael@0 | 8978 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8979 | } |
michael@0 | 8980 | for (i = 0, name = names; i < nnames; i++, name++) { |
michael@0 | 8981 | rv = ssl3_AppendHandshakeVariable(ss, name->data, name->len, 2); |
michael@0 | 8982 | if (rv != SECSuccess) { |
michael@0 | 8983 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 8984 | } |
michael@0 | 8985 | } |
michael@0 | 8986 | |
michael@0 | 8987 | return SECSuccess; |
michael@0 | 8988 | } |
michael@0 | 8989 | |
michael@0 | 8990 | static SECStatus |
michael@0 | 8991 | ssl3_SendServerHelloDone(sslSocket *ss) |
michael@0 | 8992 | { |
michael@0 | 8993 | SECStatus rv; |
michael@0 | 8994 | |
michael@0 | 8995 | SSL_TRC(3, ("%d: SSL3[%d]: send server_hello_done handshake", |
michael@0 | 8996 | SSL_GETPID(), ss->fd)); |
michael@0 | 8997 | |
michael@0 | 8998 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 8999 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 9000 | |
michael@0 | 9001 | rv = ssl3_AppendHandshakeHeader(ss, server_hello_done, 0); |
michael@0 | 9002 | if (rv != SECSuccess) { |
michael@0 | 9003 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9004 | } |
michael@0 | 9005 | rv = ssl3_FlushHandshake(ss, 0); |
michael@0 | 9006 | if (rv != SECSuccess) { |
michael@0 | 9007 | return rv; /* error code set by ssl3_FlushHandshake */ |
michael@0 | 9008 | } |
michael@0 | 9009 | return SECSuccess; |
michael@0 | 9010 | } |
michael@0 | 9011 | |
michael@0 | 9012 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 9013 | * ssl3 Certificate Verify message |
michael@0 | 9014 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 9015 | */ |
michael@0 | 9016 | static SECStatus |
michael@0 | 9017 | ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, |
michael@0 | 9018 | SSL3Hashes *hashes) |
michael@0 | 9019 | { |
michael@0 | 9020 | SECItem signed_hash = {siBuffer, NULL, 0}; |
michael@0 | 9021 | SECStatus rv; |
michael@0 | 9022 | int errCode = SSL_ERROR_RX_MALFORMED_CERT_VERIFY; |
michael@0 | 9023 | SSL3AlertDescription desc = handshake_failure; |
michael@0 | 9024 | PRBool isTLS, isTLS12; |
michael@0 | 9025 | SSL3SignatureAndHashAlgorithm sigAndHash; |
michael@0 | 9026 | |
michael@0 | 9027 | SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake", |
michael@0 | 9028 | SSL_GETPID(), ss->fd)); |
michael@0 | 9029 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 9030 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 9031 | |
michael@0 | 9032 | isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 9033 | isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); |
michael@0 | 9034 | |
michael@0 | 9035 | if (ss->ssl3.hs.ws != wait_cert_verify || ss->sec.peerCert == NULL) { |
michael@0 | 9036 | desc = unexpected_message; |
michael@0 | 9037 | errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY; |
michael@0 | 9038 | goto alert_loser; |
michael@0 | 9039 | } |
michael@0 | 9040 | |
michael@0 | 9041 | if (isTLS12) { |
michael@0 | 9042 | rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length, |
michael@0 | 9043 | &sigAndHash); |
michael@0 | 9044 | if (rv != SECSuccess) { |
michael@0 | 9045 | goto loser; /* malformed or unsupported. */ |
michael@0 | 9046 | } |
michael@0 | 9047 | rv = ssl3_CheckSignatureAndHashAlgorithmConsistency( |
michael@0 | 9048 | &sigAndHash, ss->sec.peerCert); |
michael@0 | 9049 | if (rv != SECSuccess) { |
michael@0 | 9050 | errCode = PORT_GetError(); |
michael@0 | 9051 | desc = decrypt_error; |
michael@0 | 9052 | goto alert_loser; |
michael@0 | 9053 | } |
michael@0 | 9054 | |
michael@0 | 9055 | /* We only support CertificateVerify messages that use the handshake |
michael@0 | 9056 | * hash. */ |
michael@0 | 9057 | if (sigAndHash.hashAlg != hashes->hashAlg) { |
michael@0 | 9058 | errCode = SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM; |
michael@0 | 9059 | desc = decrypt_error; |
michael@0 | 9060 | goto alert_loser; |
michael@0 | 9061 | } |
michael@0 | 9062 | } |
michael@0 | 9063 | |
michael@0 | 9064 | rv = ssl3_ConsumeHandshakeVariable(ss, &signed_hash, 2, &b, &length); |
michael@0 | 9065 | if (rv != SECSuccess) { |
michael@0 | 9066 | goto loser; /* malformed. */ |
michael@0 | 9067 | } |
michael@0 | 9068 | |
michael@0 | 9069 | /* XXX verify that the key & kea match */ |
michael@0 | 9070 | rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash, |
michael@0 | 9071 | isTLS, ss->pkcs11PinArg); |
michael@0 | 9072 | if (rv != SECSuccess) { |
michael@0 | 9073 | errCode = PORT_GetError(); |
michael@0 | 9074 | desc = isTLS ? decrypt_error : handshake_failure; |
michael@0 | 9075 | goto alert_loser; |
michael@0 | 9076 | } |
michael@0 | 9077 | |
michael@0 | 9078 | signed_hash.data = NULL; |
michael@0 | 9079 | |
michael@0 | 9080 | if (length != 0) { |
michael@0 | 9081 | desc = isTLS ? decode_error : illegal_parameter; |
michael@0 | 9082 | goto alert_loser; /* malformed */ |
michael@0 | 9083 | } |
michael@0 | 9084 | ss->ssl3.hs.ws = wait_change_cipher; |
michael@0 | 9085 | return SECSuccess; |
michael@0 | 9086 | |
michael@0 | 9087 | alert_loser: |
michael@0 | 9088 | SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 9089 | loser: |
michael@0 | 9090 | PORT_SetError(errCode); |
michael@0 | 9091 | return SECFailure; |
michael@0 | 9092 | } |
michael@0 | 9093 | |
michael@0 | 9094 | |
michael@0 | 9095 | /* find a slot that is able to generate a PMS and wrap it with RSA. |
michael@0 | 9096 | * Then generate and return the PMS. |
michael@0 | 9097 | * If the serverKeySlot parameter is non-null, this function will use |
michael@0 | 9098 | * that slot to do the job, otherwise it will find a slot. |
michael@0 | 9099 | * |
michael@0 | 9100 | * Called from ssl3_DeriveConnectionKeysPKCS11() (above) |
michael@0 | 9101 | * sendRSAClientKeyExchange() (above) |
michael@0 | 9102 | * ssl3_HandleRSAClientKeyExchange() (below) |
michael@0 | 9103 | * Caller must hold the SpecWriteLock, the SSL3HandshakeLock |
michael@0 | 9104 | */ |
michael@0 | 9105 | static PK11SymKey * |
michael@0 | 9106 | ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, |
michael@0 | 9107 | PK11SlotInfo * serverKeySlot) |
michael@0 | 9108 | { |
michael@0 | 9109 | PK11SymKey * pms = NULL; |
michael@0 | 9110 | PK11SlotInfo * slot = serverKeySlot; |
michael@0 | 9111 | void * pwArg = ss->pkcs11PinArg; |
michael@0 | 9112 | SECItem param; |
michael@0 | 9113 | CK_VERSION version; |
michael@0 | 9114 | CK_MECHANISM_TYPE mechanism_array[3]; |
michael@0 | 9115 | |
michael@0 | 9116 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 9117 | |
michael@0 | 9118 | if (slot == NULL) { |
michael@0 | 9119 | SSLCipherAlgorithm calg; |
michael@0 | 9120 | /* The specReadLock would suffice here, but we cannot assert on |
michael@0 | 9121 | ** read locks. Also, all the callers who call with a non-null |
michael@0 | 9122 | ** slot already hold the SpecWriteLock. |
michael@0 | 9123 | */ |
michael@0 | 9124 | PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); |
michael@0 | 9125 | PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); |
michael@0 | 9126 | |
michael@0 | 9127 | calg = spec->cipher_def->calg; |
michael@0 | 9128 | PORT_Assert(alg2Mech[calg].calg == calg); |
michael@0 | 9129 | |
michael@0 | 9130 | /* First get an appropriate slot. */ |
michael@0 | 9131 | mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; |
michael@0 | 9132 | mechanism_array[1] = CKM_RSA_PKCS; |
michael@0 | 9133 | mechanism_array[2] = alg2Mech[calg].cmech; |
michael@0 | 9134 | |
michael@0 | 9135 | slot = PK11_GetBestSlotMultiple(mechanism_array, 3, pwArg); |
michael@0 | 9136 | if (slot == NULL) { |
michael@0 | 9137 | /* can't find a slot with all three, find a slot with the minimum */ |
michael@0 | 9138 | slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg); |
michael@0 | 9139 | if (slot == NULL) { |
michael@0 | 9140 | PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND); |
michael@0 | 9141 | return pms; /* which is NULL */ |
michael@0 | 9142 | } |
michael@0 | 9143 | } |
michael@0 | 9144 | } |
michael@0 | 9145 | |
michael@0 | 9146 | /* Generate the pre-master secret ... */ |
michael@0 | 9147 | if (IS_DTLS(ss)) { |
michael@0 | 9148 | SSL3ProtocolVersion temp; |
michael@0 | 9149 | |
michael@0 | 9150 | temp = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion); |
michael@0 | 9151 | version.major = MSB(temp); |
michael@0 | 9152 | version.minor = LSB(temp); |
michael@0 | 9153 | } else { |
michael@0 | 9154 | version.major = MSB(ss->clientHelloVersion); |
michael@0 | 9155 | version.minor = LSB(ss->clientHelloVersion); |
michael@0 | 9156 | } |
michael@0 | 9157 | |
michael@0 | 9158 | param.data = (unsigned char *)&version; |
michael@0 | 9159 | param.len = sizeof version; |
michael@0 | 9160 | |
michael@0 | 9161 | pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg); |
michael@0 | 9162 | if (!serverKeySlot) |
michael@0 | 9163 | PK11_FreeSlot(slot); |
michael@0 | 9164 | if (pms == NULL) { |
michael@0 | 9165 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 9166 | } |
michael@0 | 9167 | return pms; |
michael@0 | 9168 | } |
michael@0 | 9169 | |
michael@0 | 9170 | /* Note: The Bleichenbacher attack on PKCS#1 necessitates that we NEVER |
michael@0 | 9171 | * return any indication of failure of the Client Key Exchange message, |
michael@0 | 9172 | * where that failure is caused by the content of the client's message. |
michael@0 | 9173 | * This function must not return SECFailure for any reason that is directly |
michael@0 | 9174 | * or indirectly caused by the content of the client's encrypted PMS. |
michael@0 | 9175 | * We must not send an alert and also not drop the connection. |
michael@0 | 9176 | * Instead, we generate a random PMS. This will cause a failure |
michael@0 | 9177 | * in the processing the finished message, which is exactly where |
michael@0 | 9178 | * the failure must occur. |
michael@0 | 9179 | * |
michael@0 | 9180 | * Called from ssl3_HandleClientKeyExchange |
michael@0 | 9181 | */ |
michael@0 | 9182 | static SECStatus |
michael@0 | 9183 | ssl3_HandleRSAClientKeyExchange(sslSocket *ss, |
michael@0 | 9184 | SSL3Opaque *b, |
michael@0 | 9185 | PRUint32 length, |
michael@0 | 9186 | SECKEYPrivateKey *serverKey) |
michael@0 | 9187 | { |
michael@0 | 9188 | PK11SymKey * pms; |
michael@0 | 9189 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 9190 | unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; |
michael@0 | 9191 | unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; |
michael@0 | 9192 | ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; |
michael@0 | 9193 | unsigned int outLen = 0; |
michael@0 | 9194 | #endif |
michael@0 | 9195 | PRBool isTLS = PR_FALSE; |
michael@0 | 9196 | SECStatus rv; |
michael@0 | 9197 | SECItem enc_pms; |
michael@0 | 9198 | unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; |
michael@0 | 9199 | SECItem pmsItem = {siBuffer, NULL, 0}; |
michael@0 | 9200 | |
michael@0 | 9201 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 9202 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 9203 | PORT_Assert( ss->ssl3.prSpec == ss->ssl3.pwSpec ); |
michael@0 | 9204 | |
michael@0 | 9205 | enc_pms.data = b; |
michael@0 | 9206 | enc_pms.len = length; |
michael@0 | 9207 | pmsItem.data = rsaPmsBuf; |
michael@0 | 9208 | pmsItem.len = sizeof rsaPmsBuf; |
michael@0 | 9209 | |
michael@0 | 9210 | if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ |
michael@0 | 9211 | PRInt32 kLen; |
michael@0 | 9212 | kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len); |
michael@0 | 9213 | if (kLen < 0) { |
michael@0 | 9214 | PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 9215 | return SECFailure; |
michael@0 | 9216 | } |
michael@0 | 9217 | if ((unsigned)kLen < enc_pms.len) { |
michael@0 | 9218 | enc_pms.len = kLen; |
michael@0 | 9219 | } |
michael@0 | 9220 | isTLS = PR_TRUE; |
michael@0 | 9221 | } else { |
michael@0 | 9222 | isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0); |
michael@0 | 9223 | } |
michael@0 | 9224 | |
michael@0 | 9225 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 9226 | if (ss->opt.bypassPKCS11) { |
michael@0 | 9227 | /* TRIPLE BYPASS, get PMS directly from RSA decryption. |
michael@0 | 9228 | * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer, |
michael@0 | 9229 | * then, check for version rollback attack, then |
michael@0 | 9230 | * do the equivalent of ssl3_DeriveMasterSecret, placing the MS in |
michael@0 | 9231 | * pwSpec->msItem. Finally call ssl3_InitPendingCipherSpec with |
michael@0 | 9232 | * ss and NULL, so that it will use the MS we've already derived here. |
michael@0 | 9233 | */ |
michael@0 | 9234 | |
michael@0 | 9235 | rv = PK11_PrivDecryptPKCS1(serverKey, rsaPmsBuf, &outLen, |
michael@0 | 9236 | sizeof rsaPmsBuf, enc_pms.data, enc_pms.len); |
michael@0 | 9237 | if (rv != SECSuccess) { |
michael@0 | 9238 | /* triple bypass failed. Let's try for a double bypass. */ |
michael@0 | 9239 | goto double_bypass; |
michael@0 | 9240 | } else if (ss->opt.detectRollBack) { |
michael@0 | 9241 | SSL3ProtocolVersion client_version = |
michael@0 | 9242 | (rsaPmsBuf[0] << 8) | rsaPmsBuf[1]; |
michael@0 | 9243 | |
michael@0 | 9244 | if (IS_DTLS(ss)) { |
michael@0 | 9245 | client_version = dtls_DTLSVersionToTLSVersion(client_version); |
michael@0 | 9246 | } |
michael@0 | 9247 | |
michael@0 | 9248 | if (client_version != ss->clientHelloVersion) { |
michael@0 | 9249 | /* Version roll-back detected. ensure failure. */ |
michael@0 | 9250 | rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf); |
michael@0 | 9251 | } |
michael@0 | 9252 | } |
michael@0 | 9253 | /* have PMS, build MS without PKCS11 */ |
michael@0 | 9254 | rv = ssl3_MasterKeyDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS, |
michael@0 | 9255 | PR_TRUE); |
michael@0 | 9256 | if (rv != SECSuccess) { |
michael@0 | 9257 | pwSpec->msItem.data = pwSpec->raw_master_secret; |
michael@0 | 9258 | pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; |
michael@0 | 9259 | PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len); |
michael@0 | 9260 | } |
michael@0 | 9261 | rv = ssl3_InitPendingCipherSpec(ss, NULL); |
michael@0 | 9262 | } else |
michael@0 | 9263 | #endif |
michael@0 | 9264 | { |
michael@0 | 9265 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 9266 | double_bypass: |
michael@0 | 9267 | #endif |
michael@0 | 9268 | /* |
michael@0 | 9269 | * unwrap pms out of the incoming buffer |
michael@0 | 9270 | * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do |
michael@0 | 9271 | * the unwrap. Rather, it is the mechanism with which the |
michael@0 | 9272 | * unwrapped pms will be used. |
michael@0 | 9273 | */ |
michael@0 | 9274 | pms = PK11_PubUnwrapSymKey(serverKey, &enc_pms, |
michael@0 | 9275 | CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0); |
michael@0 | 9276 | if (pms != NULL) { |
michael@0 | 9277 | PRINT_BUF(60, (ss, "decrypted premaster secret:", |
michael@0 | 9278 | PK11_GetKeyData(pms)->data, |
michael@0 | 9279 | PK11_GetKeyData(pms)->len)); |
michael@0 | 9280 | } else { |
michael@0 | 9281 | /* unwrap failed. Generate a bogus PMS and carry on. */ |
michael@0 | 9282 | PK11SlotInfo * slot = PK11_GetSlotFromPrivateKey(serverKey); |
michael@0 | 9283 | |
michael@0 | 9284 | ssl_GetSpecWriteLock(ss); |
michael@0 | 9285 | pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot); |
michael@0 | 9286 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 9287 | PK11_FreeSlot(slot); |
michael@0 | 9288 | } |
michael@0 | 9289 | |
michael@0 | 9290 | if (pms == NULL) { |
michael@0 | 9291 | /* last gasp. */ |
michael@0 | 9292 | ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
michael@0 | 9293 | return SECFailure; |
michael@0 | 9294 | } |
michael@0 | 9295 | |
michael@0 | 9296 | /* This step will derive the MS from the PMS, among other things. */ |
michael@0 | 9297 | rv = ssl3_InitPendingCipherSpec(ss, pms); |
michael@0 | 9298 | PK11_FreeSymKey(pms); |
michael@0 | 9299 | } |
michael@0 | 9300 | |
michael@0 | 9301 | if (rv != SECSuccess) { |
michael@0 | 9302 | SEND_ALERT |
michael@0 | 9303 | return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ |
michael@0 | 9304 | } |
michael@0 | 9305 | return SECSuccess; |
michael@0 | 9306 | } |
michael@0 | 9307 | |
michael@0 | 9308 | |
michael@0 | 9309 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 9310 | * ssl3 ClientKeyExchange message from the remote client |
michael@0 | 9311 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 9312 | */ |
michael@0 | 9313 | static SECStatus |
michael@0 | 9314 | ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 9315 | { |
michael@0 | 9316 | SECKEYPrivateKey *serverKey = NULL; |
michael@0 | 9317 | SECStatus rv; |
michael@0 | 9318 | const ssl3KEADef *kea_def; |
michael@0 | 9319 | ssl3KeyPair *serverKeyPair = NULL; |
michael@0 | 9320 | #ifndef NSS_DISABLE_ECC |
michael@0 | 9321 | SECKEYPublicKey *serverPubKey = NULL; |
michael@0 | 9322 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 9323 | |
michael@0 | 9324 | SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake", |
michael@0 | 9325 | SSL_GETPID(), ss->fd)); |
michael@0 | 9326 | |
michael@0 | 9327 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 9328 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 9329 | |
michael@0 | 9330 | if (ss->ssl3.hs.ws != wait_client_key) { |
michael@0 | 9331 | SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 9332 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH); |
michael@0 | 9333 | return SECFailure; |
michael@0 | 9334 | } |
michael@0 | 9335 | |
michael@0 | 9336 | kea_def = ss->ssl3.hs.kea_def; |
michael@0 | 9337 | |
michael@0 | 9338 | if (ss->ssl3.hs.usedStepDownKey) { |
michael@0 | 9339 | PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */ |
michael@0 | 9340 | && kea_def->exchKeyType == kt_rsa |
michael@0 | 9341 | && ss->stepDownKeyPair != NULL); |
michael@0 | 9342 | if (!kea_def->is_limited || |
michael@0 | 9343 | kea_def->exchKeyType != kt_rsa || |
michael@0 | 9344 | ss->stepDownKeyPair == NULL) { |
michael@0 | 9345 | /* shouldn't happen, don't use step down if it does */ |
michael@0 | 9346 | goto skip; |
michael@0 | 9347 | } |
michael@0 | 9348 | serverKeyPair = ss->stepDownKeyPair; |
michael@0 | 9349 | ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB; |
michael@0 | 9350 | } else |
michael@0 | 9351 | skip: |
michael@0 | 9352 | #ifndef NSS_DISABLE_ECC |
michael@0 | 9353 | /* XXX Using SSLKEAType to index server certifiates |
michael@0 | 9354 | * does not work for (EC)DHE ciphers. Until we have |
michael@0 | 9355 | * an indexing mechanism general enough for all key |
michael@0 | 9356 | * exchange algorithms, we'll need to deal with each |
michael@0 | 9357 | * one seprately. |
michael@0 | 9358 | */ |
michael@0 | 9359 | if ((kea_def->kea == kea_ecdhe_rsa) || |
michael@0 | 9360 | (kea_def->kea == kea_ecdhe_ecdsa)) { |
michael@0 | 9361 | if (ss->ephemeralECDHKeyPair != NULL) { |
michael@0 | 9362 | serverKeyPair = ss->ephemeralECDHKeyPair; |
michael@0 | 9363 | if (serverKeyPair->pubKey) { |
michael@0 | 9364 | ss->sec.keaKeyBits = |
michael@0 | 9365 | SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey); |
michael@0 | 9366 | } |
michael@0 | 9367 | } |
michael@0 | 9368 | } else |
michael@0 | 9369 | #endif |
michael@0 | 9370 | { |
michael@0 | 9371 | sslServerCerts * sc = ss->serverCerts + kea_def->exchKeyType; |
michael@0 | 9372 | serverKeyPair = sc->serverKeyPair; |
michael@0 | 9373 | ss->sec.keaKeyBits = sc->serverKeyBits; |
michael@0 | 9374 | } |
michael@0 | 9375 | |
michael@0 | 9376 | if (serverKeyPair) { |
michael@0 | 9377 | serverKey = serverKeyPair->privKey; |
michael@0 | 9378 | } |
michael@0 | 9379 | |
michael@0 | 9380 | if (serverKey == NULL) { |
michael@0 | 9381 | SEND_ALERT |
michael@0 | 9382 | PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG); |
michael@0 | 9383 | return SECFailure; |
michael@0 | 9384 | } |
michael@0 | 9385 | |
michael@0 | 9386 | ss->sec.keaType = kea_def->exchKeyType; |
michael@0 | 9387 | |
michael@0 | 9388 | switch (kea_def->exchKeyType) { |
michael@0 | 9389 | case kt_rsa: |
michael@0 | 9390 | rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey); |
michael@0 | 9391 | if (rv != SECSuccess) { |
michael@0 | 9392 | SEND_ALERT |
michael@0 | 9393 | return SECFailure; /* error code set */ |
michael@0 | 9394 | } |
michael@0 | 9395 | break; |
michael@0 | 9396 | |
michael@0 | 9397 | |
michael@0 | 9398 | #ifndef NSS_DISABLE_ECC |
michael@0 | 9399 | case kt_ecdh: |
michael@0 | 9400 | /* XXX We really ought to be able to store multiple |
michael@0 | 9401 | * EC certs (a requirement if we wish to support both |
michael@0 | 9402 | * ECDH-RSA and ECDH-ECDSA key exchanges concurrently). |
michael@0 | 9403 | * When we make that change, we'll need an index other |
michael@0 | 9404 | * than kt_ecdh to pick the right EC certificate. |
michael@0 | 9405 | */ |
michael@0 | 9406 | if (serverKeyPair) { |
michael@0 | 9407 | serverPubKey = serverKeyPair->pubKey; |
michael@0 | 9408 | } |
michael@0 | 9409 | if (serverPubKey == NULL) { |
michael@0 | 9410 | /* XXX Is this the right error code? */ |
michael@0 | 9411 | PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); |
michael@0 | 9412 | return SECFailure; |
michael@0 | 9413 | } |
michael@0 | 9414 | rv = ssl3_HandleECDHClientKeyExchange(ss, b, length, |
michael@0 | 9415 | serverPubKey, serverKey); |
michael@0 | 9416 | if (rv != SECSuccess) { |
michael@0 | 9417 | return SECFailure; /* error code set */ |
michael@0 | 9418 | } |
michael@0 | 9419 | break; |
michael@0 | 9420 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 9421 | |
michael@0 | 9422 | default: |
michael@0 | 9423 | (void) ssl3_HandshakeFailure(ss); |
michael@0 | 9424 | PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
michael@0 | 9425 | return SECFailure; |
michael@0 | 9426 | } |
michael@0 | 9427 | ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher; |
michael@0 | 9428 | return SECSuccess; |
michael@0 | 9429 | |
michael@0 | 9430 | } |
michael@0 | 9431 | |
michael@0 | 9432 | /* This is TLS's equivalent of sending a no_certificate alert. */ |
michael@0 | 9433 | static SECStatus |
michael@0 | 9434 | ssl3_SendEmptyCertificate(sslSocket *ss) |
michael@0 | 9435 | { |
michael@0 | 9436 | SECStatus rv; |
michael@0 | 9437 | |
michael@0 | 9438 | rv = ssl3_AppendHandshakeHeader(ss, certificate, 3); |
michael@0 | 9439 | if (rv == SECSuccess) { |
michael@0 | 9440 | rv = ssl3_AppendHandshakeNumber(ss, 0, 3); |
michael@0 | 9441 | } |
michael@0 | 9442 | return rv; /* error, if any, set by functions called above. */ |
michael@0 | 9443 | } |
michael@0 | 9444 | |
michael@0 | 9445 | SECStatus |
michael@0 | 9446 | ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 9447 | { |
michael@0 | 9448 | SECStatus rv; |
michael@0 | 9449 | SECItem ticketData; |
michael@0 | 9450 | |
michael@0 | 9451 | SSL_TRC(3, ("%d: SSL3[%d]: handle session_ticket handshake", |
michael@0 | 9452 | SSL_GETPID(), ss->fd)); |
michael@0 | 9453 | |
michael@0 | 9454 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 9455 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 9456 | |
michael@0 | 9457 | PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data); |
michael@0 | 9458 | PORT_Assert(!ss->ssl3.hs.receivedNewSessionTicket); |
michael@0 | 9459 | |
michael@0 | 9460 | if (ss->ssl3.hs.ws != wait_new_session_ticket) { |
michael@0 | 9461 | SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 9462 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET); |
michael@0 | 9463 | return SECFailure; |
michael@0 | 9464 | } |
michael@0 | 9465 | |
michael@0 | 9466 | /* RFC5077 Section 3.3: "The client MUST NOT treat the ticket as valid |
michael@0 | 9467 | * until it has verified the server's Finished message." See the comment in |
michael@0 | 9468 | * ssl3_FinishHandshake for more details. |
michael@0 | 9469 | */ |
michael@0 | 9470 | ss->ssl3.hs.newSessionTicket.received_timestamp = ssl_Time(); |
michael@0 | 9471 | if (length < 4) { |
michael@0 | 9472 | (void)SSL3_SendAlert(ss, alert_fatal, decode_error); |
michael@0 | 9473 | PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); |
michael@0 | 9474 | return SECFailure; |
michael@0 | 9475 | } |
michael@0 | 9476 | ss->ssl3.hs.newSessionTicket.ticket_lifetime_hint = |
michael@0 | 9477 | (PRUint32)ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length); |
michael@0 | 9478 | |
michael@0 | 9479 | rv = ssl3_ConsumeHandshakeVariable(ss, &ticketData, 2, &b, &length); |
michael@0 | 9480 | if (rv != SECSuccess || length != 0) { |
michael@0 | 9481 | (void)SSL3_SendAlert(ss, alert_fatal, decode_error); |
michael@0 | 9482 | PORT_SetError(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET); |
michael@0 | 9483 | return SECFailure; /* malformed */ |
michael@0 | 9484 | } |
michael@0 | 9485 | /* If the server sent a zero-length ticket, ignore it and keep the |
michael@0 | 9486 | * existing ticket. */ |
michael@0 | 9487 | if (ticketData.len != 0) { |
michael@0 | 9488 | rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.newSessionTicket.ticket, |
michael@0 | 9489 | &ticketData); |
michael@0 | 9490 | if (rv != SECSuccess) { |
michael@0 | 9491 | return rv; |
michael@0 | 9492 | } |
michael@0 | 9493 | ss->ssl3.hs.receivedNewSessionTicket = PR_TRUE; |
michael@0 | 9494 | } |
michael@0 | 9495 | |
michael@0 | 9496 | ss->ssl3.hs.ws = wait_change_cipher; |
michael@0 | 9497 | return SECSuccess; |
michael@0 | 9498 | } |
michael@0 | 9499 | |
michael@0 | 9500 | #ifdef NISCC_TEST |
michael@0 | 9501 | static PRInt32 connNum = 0; |
michael@0 | 9502 | |
michael@0 | 9503 | static SECStatus |
michael@0 | 9504 | get_fake_cert(SECItem *pCertItem, int *pIndex) |
michael@0 | 9505 | { |
michael@0 | 9506 | PRFileDesc *cf; |
michael@0 | 9507 | char * testdir; |
michael@0 | 9508 | char * startat; |
michael@0 | 9509 | char * stopat; |
michael@0 | 9510 | const char *extension; |
michael@0 | 9511 | int fileNum; |
michael@0 | 9512 | PRInt32 numBytes = 0; |
michael@0 | 9513 | PRStatus prStatus; |
michael@0 | 9514 | PRFileInfo info; |
michael@0 | 9515 | char cfn[100]; |
michael@0 | 9516 | |
michael@0 | 9517 | pCertItem->data = 0; |
michael@0 | 9518 | if ((testdir = PR_GetEnv("NISCC_TEST")) == NULL) { |
michael@0 | 9519 | return SECSuccess; |
michael@0 | 9520 | } |
michael@0 | 9521 | *pIndex = (NULL != strstr(testdir, "root")); |
michael@0 | 9522 | extension = (strstr(testdir, "simple") ? "" : ".der"); |
michael@0 | 9523 | fileNum = PR_ATOMIC_INCREMENT(&connNum) - 1; |
michael@0 | 9524 | if ((startat = PR_GetEnv("START_AT")) != NULL) { |
michael@0 | 9525 | fileNum += atoi(startat); |
michael@0 | 9526 | } |
michael@0 | 9527 | if ((stopat = PR_GetEnv("STOP_AT")) != NULL && |
michael@0 | 9528 | fileNum >= atoi(stopat)) { |
michael@0 | 9529 | *pIndex = -1; |
michael@0 | 9530 | return SECSuccess; |
michael@0 | 9531 | } |
michael@0 | 9532 | sprintf(cfn, "%s/%08d%s", testdir, fileNum, extension); |
michael@0 | 9533 | cf = PR_Open(cfn, PR_RDONLY, 0); |
michael@0 | 9534 | if (!cf) { |
michael@0 | 9535 | goto loser; |
michael@0 | 9536 | } |
michael@0 | 9537 | prStatus = PR_GetOpenFileInfo(cf, &info); |
michael@0 | 9538 | if (prStatus != PR_SUCCESS) { |
michael@0 | 9539 | PR_Close(cf); |
michael@0 | 9540 | goto loser; |
michael@0 | 9541 | } |
michael@0 | 9542 | pCertItem = SECITEM_AllocItem(NULL, pCertItem, info.size); |
michael@0 | 9543 | if (pCertItem) { |
michael@0 | 9544 | numBytes = PR_Read(cf, pCertItem->data, info.size); |
michael@0 | 9545 | } |
michael@0 | 9546 | PR_Close(cf); |
michael@0 | 9547 | if (numBytes != info.size) { |
michael@0 | 9548 | SECITEM_FreeItem(pCertItem, PR_FALSE); |
michael@0 | 9549 | PORT_SetError(SEC_ERROR_IO); |
michael@0 | 9550 | goto loser; |
michael@0 | 9551 | } |
michael@0 | 9552 | fprintf(stderr, "using %s\n", cfn); |
michael@0 | 9553 | return SECSuccess; |
michael@0 | 9554 | |
michael@0 | 9555 | loser: |
michael@0 | 9556 | fprintf(stderr, "failed to use %s\n", cfn); |
michael@0 | 9557 | *pIndex = -1; |
michael@0 | 9558 | return SECFailure; |
michael@0 | 9559 | } |
michael@0 | 9560 | #endif |
michael@0 | 9561 | |
michael@0 | 9562 | /* |
michael@0 | 9563 | * Used by both client and server. |
michael@0 | 9564 | * Called from HandleServerHelloDone and from SendServerHelloSequence. |
michael@0 | 9565 | */ |
michael@0 | 9566 | static SECStatus |
michael@0 | 9567 | ssl3_SendCertificate(sslSocket *ss) |
michael@0 | 9568 | { |
michael@0 | 9569 | SECStatus rv; |
michael@0 | 9570 | CERTCertificateList *certChain; |
michael@0 | 9571 | int len = 0; |
michael@0 | 9572 | int i; |
michael@0 | 9573 | SSL3KEAType certIndex; |
michael@0 | 9574 | #ifdef NISCC_TEST |
michael@0 | 9575 | SECItem fakeCert; |
michael@0 | 9576 | int ndex = -1; |
michael@0 | 9577 | #endif |
michael@0 | 9578 | |
michael@0 | 9579 | SSL_TRC(3, ("%d: SSL3[%d]: send certificate handshake", |
michael@0 | 9580 | SSL_GETPID(), ss->fd)); |
michael@0 | 9581 | |
michael@0 | 9582 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 9583 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 9584 | |
michael@0 | 9585 | if (ss->sec.localCert) |
michael@0 | 9586 | CERT_DestroyCertificate(ss->sec.localCert); |
michael@0 | 9587 | if (ss->sec.isServer) { |
michael@0 | 9588 | sslServerCerts * sc = NULL; |
michael@0 | 9589 | |
michael@0 | 9590 | /* XXX SSLKEAType isn't really a good choice for |
michael@0 | 9591 | * indexing certificates (it breaks when we deal |
michael@0 | 9592 | * with (EC)DHE-* cipher suites. This hack ensures |
michael@0 | 9593 | * the RSA cert is picked for (EC)DHE-RSA. |
michael@0 | 9594 | * Revisit this when we add server side support |
michael@0 | 9595 | * for ECDHE-ECDSA or client-side authentication |
michael@0 | 9596 | * using EC certificates. |
michael@0 | 9597 | */ |
michael@0 | 9598 | if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || |
michael@0 | 9599 | (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { |
michael@0 | 9600 | certIndex = kt_rsa; |
michael@0 | 9601 | } else { |
michael@0 | 9602 | certIndex = ss->ssl3.hs.kea_def->exchKeyType; |
michael@0 | 9603 | } |
michael@0 | 9604 | sc = ss->serverCerts + certIndex; |
michael@0 | 9605 | certChain = sc->serverCertChain; |
michael@0 | 9606 | ss->sec.authKeyBits = sc->serverKeyBits; |
michael@0 | 9607 | ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType; |
michael@0 | 9608 | ss->sec.localCert = CERT_DupCertificate(sc->serverCert); |
michael@0 | 9609 | } else { |
michael@0 | 9610 | certChain = ss->ssl3.clientCertChain; |
michael@0 | 9611 | ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate); |
michael@0 | 9612 | } |
michael@0 | 9613 | |
michael@0 | 9614 | #ifdef NISCC_TEST |
michael@0 | 9615 | rv = get_fake_cert(&fakeCert, &ndex); |
michael@0 | 9616 | #endif |
michael@0 | 9617 | |
michael@0 | 9618 | if (certChain) { |
michael@0 | 9619 | for (i = 0; i < certChain->len; i++) { |
michael@0 | 9620 | #ifdef NISCC_TEST |
michael@0 | 9621 | if (fakeCert.len > 0 && i == ndex) { |
michael@0 | 9622 | len += fakeCert.len + 3; |
michael@0 | 9623 | } else { |
michael@0 | 9624 | len += certChain->certs[i].len + 3; |
michael@0 | 9625 | } |
michael@0 | 9626 | #else |
michael@0 | 9627 | len += certChain->certs[i].len + 3; |
michael@0 | 9628 | #endif |
michael@0 | 9629 | } |
michael@0 | 9630 | } |
michael@0 | 9631 | |
michael@0 | 9632 | rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3); |
michael@0 | 9633 | if (rv != SECSuccess) { |
michael@0 | 9634 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9635 | } |
michael@0 | 9636 | rv = ssl3_AppendHandshakeNumber(ss, len, 3); |
michael@0 | 9637 | if (rv != SECSuccess) { |
michael@0 | 9638 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9639 | } |
michael@0 | 9640 | if (certChain) { |
michael@0 | 9641 | for (i = 0; i < certChain->len; i++) { |
michael@0 | 9642 | #ifdef NISCC_TEST |
michael@0 | 9643 | if (fakeCert.len > 0 && i == ndex) { |
michael@0 | 9644 | rv = ssl3_AppendHandshakeVariable(ss, fakeCert.data, |
michael@0 | 9645 | fakeCert.len, 3); |
michael@0 | 9646 | SECITEM_FreeItem(&fakeCert, PR_FALSE); |
michael@0 | 9647 | } else { |
michael@0 | 9648 | rv = ssl3_AppendHandshakeVariable(ss, certChain->certs[i].data, |
michael@0 | 9649 | certChain->certs[i].len, 3); |
michael@0 | 9650 | } |
michael@0 | 9651 | #else |
michael@0 | 9652 | rv = ssl3_AppendHandshakeVariable(ss, certChain->certs[i].data, |
michael@0 | 9653 | certChain->certs[i].len, 3); |
michael@0 | 9654 | #endif |
michael@0 | 9655 | if (rv != SECSuccess) { |
michael@0 | 9656 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9657 | } |
michael@0 | 9658 | } |
michael@0 | 9659 | } |
michael@0 | 9660 | |
michael@0 | 9661 | return SECSuccess; |
michael@0 | 9662 | } |
michael@0 | 9663 | |
michael@0 | 9664 | /* |
michael@0 | 9665 | * Used by server only. |
michael@0 | 9666 | * single-stapling, send only a single cert status |
michael@0 | 9667 | */ |
michael@0 | 9668 | static SECStatus |
michael@0 | 9669 | ssl3_SendCertificateStatus(sslSocket *ss) |
michael@0 | 9670 | { |
michael@0 | 9671 | SECStatus rv; |
michael@0 | 9672 | int len = 0; |
michael@0 | 9673 | SECItemArray *statusToSend = NULL; |
michael@0 | 9674 | SSL3KEAType certIndex; |
michael@0 | 9675 | |
michael@0 | 9676 | SSL_TRC(3, ("%d: SSL3[%d]: send certificate status handshake", |
michael@0 | 9677 | SSL_GETPID(), ss->fd)); |
michael@0 | 9678 | |
michael@0 | 9679 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 9680 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 9681 | PORT_Assert( ss->sec.isServer); |
michael@0 | 9682 | |
michael@0 | 9683 | if (!ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn)) |
michael@0 | 9684 | return SECSuccess; |
michael@0 | 9685 | |
michael@0 | 9686 | /* Use certStatus based on the cert being used. */ |
michael@0 | 9687 | if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || |
michael@0 | 9688 | (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { |
michael@0 | 9689 | certIndex = kt_rsa; |
michael@0 | 9690 | } else { |
michael@0 | 9691 | certIndex = ss->ssl3.hs.kea_def->exchKeyType; |
michael@0 | 9692 | } |
michael@0 | 9693 | if (ss->certStatusArray[certIndex] && ss->certStatusArray[certIndex]->len) { |
michael@0 | 9694 | statusToSend = ss->certStatusArray[certIndex]; |
michael@0 | 9695 | } |
michael@0 | 9696 | if (!statusToSend) |
michael@0 | 9697 | return SECSuccess; |
michael@0 | 9698 | |
michael@0 | 9699 | /* Use the array's first item only (single stapling) */ |
michael@0 | 9700 | len = 1 + statusToSend->items[0].len + 3; |
michael@0 | 9701 | |
michael@0 | 9702 | rv = ssl3_AppendHandshakeHeader(ss, certificate_status, len); |
michael@0 | 9703 | if (rv != SECSuccess) { |
michael@0 | 9704 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9705 | } |
michael@0 | 9706 | rv = ssl3_AppendHandshakeNumber(ss, 1 /*ocsp*/, 1); |
michael@0 | 9707 | if (rv != SECSuccess) |
michael@0 | 9708 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9709 | |
michael@0 | 9710 | rv = ssl3_AppendHandshakeVariable(ss, |
michael@0 | 9711 | statusToSend->items[0].data, |
michael@0 | 9712 | statusToSend->items[0].len, |
michael@0 | 9713 | 3); |
michael@0 | 9714 | if (rv != SECSuccess) |
michael@0 | 9715 | return rv; /* err set by AppendHandshake. */ |
michael@0 | 9716 | |
michael@0 | 9717 | return SECSuccess; |
michael@0 | 9718 | } |
michael@0 | 9719 | |
michael@0 | 9720 | /* This is used to delete the CA certificates in the peer certificate chain |
michael@0 | 9721 | * from the cert database after they've been validated. |
michael@0 | 9722 | */ |
michael@0 | 9723 | static void |
michael@0 | 9724 | ssl3_CleanupPeerCerts(sslSocket *ss) |
michael@0 | 9725 | { |
michael@0 | 9726 | PLArenaPool * arena = ss->ssl3.peerCertArena; |
michael@0 | 9727 | ssl3CertNode *certs = (ssl3CertNode *)ss->ssl3.peerCertChain; |
michael@0 | 9728 | |
michael@0 | 9729 | for (; certs; certs = certs->next) { |
michael@0 | 9730 | CERT_DestroyCertificate(certs->cert); |
michael@0 | 9731 | } |
michael@0 | 9732 | if (arena) PORT_FreeArena(arena, PR_FALSE); |
michael@0 | 9733 | ss->ssl3.peerCertArena = NULL; |
michael@0 | 9734 | ss->ssl3.peerCertChain = NULL; |
michael@0 | 9735 | } |
michael@0 | 9736 | |
michael@0 | 9737 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 9738 | * ssl3 CertificateStatus message. |
michael@0 | 9739 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 9740 | * This is always called before ssl3_HandleCertificate, even if the Certificate |
michael@0 | 9741 | * message is sent first. |
michael@0 | 9742 | */ |
michael@0 | 9743 | static SECStatus |
michael@0 | 9744 | ssl3_HandleCertificateStatus(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 9745 | { |
michael@0 | 9746 | PRInt32 status, len; |
michael@0 | 9747 | |
michael@0 | 9748 | if (ss->ssl3.hs.ws != wait_certificate_status) { |
michael@0 | 9749 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 9750 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_STATUS); |
michael@0 | 9751 | return SECFailure; |
michael@0 | 9752 | } |
michael@0 | 9753 | |
michael@0 | 9754 | PORT_Assert(!ss->sec.isServer); |
michael@0 | 9755 | |
michael@0 | 9756 | /* Consume the CertificateStatusType enum */ |
michael@0 | 9757 | status = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length); |
michael@0 | 9758 | if (status != 1 /* ocsp */) { |
michael@0 | 9759 | goto format_loser; |
michael@0 | 9760 | } |
michael@0 | 9761 | |
michael@0 | 9762 | len = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
michael@0 | 9763 | if (len != length) { |
michael@0 | 9764 | goto format_loser; |
michael@0 | 9765 | } |
michael@0 | 9766 | |
michael@0 | 9767 | #define MAX_CERTSTATUS_LEN 0x1ffff /* 128k - 1 */ |
michael@0 | 9768 | if (length > MAX_CERTSTATUS_LEN) |
michael@0 | 9769 | goto format_loser; |
michael@0 | 9770 | #undef MAX_CERTSTATUS_LEN |
michael@0 | 9771 | |
michael@0 | 9772 | /* Array size 1, because we currently implement single-stapling only */ |
michael@0 | 9773 | SECITEM_AllocArray(NULL, &ss->sec.ci.sid->peerCertStatus, 1); |
michael@0 | 9774 | if (!ss->sec.ci.sid->peerCertStatus.items) |
michael@0 | 9775 | return SECFailure; |
michael@0 | 9776 | |
michael@0 | 9777 | ss->sec.ci.sid->peerCertStatus.items[0].data = PORT_Alloc(length); |
michael@0 | 9778 | |
michael@0 | 9779 | if (!ss->sec.ci.sid->peerCertStatus.items[0].data) { |
michael@0 | 9780 | SECITEM_FreeArray(&ss->sec.ci.sid->peerCertStatus, PR_FALSE); |
michael@0 | 9781 | return SECFailure; |
michael@0 | 9782 | } |
michael@0 | 9783 | |
michael@0 | 9784 | PORT_Memcpy(ss->sec.ci.sid->peerCertStatus.items[0].data, b, length); |
michael@0 | 9785 | ss->sec.ci.sid->peerCertStatus.items[0].len = length; |
michael@0 | 9786 | ss->sec.ci.sid->peerCertStatus.items[0].type = siBuffer; |
michael@0 | 9787 | |
michael@0 | 9788 | return ssl3_AuthCertificate(ss); |
michael@0 | 9789 | |
michael@0 | 9790 | format_loser: |
michael@0 | 9791 | return ssl3_DecodeError(ss); |
michael@0 | 9792 | } |
michael@0 | 9793 | |
michael@0 | 9794 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 9795 | * ssl3 Certificate message. |
michael@0 | 9796 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 9797 | */ |
michael@0 | 9798 | static SECStatus |
michael@0 | 9799 | ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 9800 | { |
michael@0 | 9801 | ssl3CertNode * c; |
michael@0 | 9802 | ssl3CertNode * lastCert = NULL; |
michael@0 | 9803 | PRInt32 remaining = 0; |
michael@0 | 9804 | PRInt32 size; |
michael@0 | 9805 | SECStatus rv; |
michael@0 | 9806 | PRBool isServer = (PRBool)(!!ss->sec.isServer); |
michael@0 | 9807 | PRBool isTLS; |
michael@0 | 9808 | SSL3AlertDescription desc; |
michael@0 | 9809 | int errCode = SSL_ERROR_RX_MALFORMED_CERTIFICATE; |
michael@0 | 9810 | SECItem certItem; |
michael@0 | 9811 | |
michael@0 | 9812 | SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake", |
michael@0 | 9813 | SSL_GETPID(), ss->fd)); |
michael@0 | 9814 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 9815 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 9816 | |
michael@0 | 9817 | if ((ss->ssl3.hs.ws != wait_server_cert) && |
michael@0 | 9818 | (ss->ssl3.hs.ws != wait_client_cert)) { |
michael@0 | 9819 | desc = unexpected_message; |
michael@0 | 9820 | errCode = SSL_ERROR_RX_UNEXPECTED_CERTIFICATE; |
michael@0 | 9821 | goto alert_loser; |
michael@0 | 9822 | } |
michael@0 | 9823 | |
michael@0 | 9824 | if (ss->sec.peerCert != NULL) { |
michael@0 | 9825 | if (ss->sec.peerKey) { |
michael@0 | 9826 | SECKEY_DestroyPublicKey(ss->sec.peerKey); |
michael@0 | 9827 | ss->sec.peerKey = NULL; |
michael@0 | 9828 | } |
michael@0 | 9829 | CERT_DestroyCertificate(ss->sec.peerCert); |
michael@0 | 9830 | ss->sec.peerCert = NULL; |
michael@0 | 9831 | } |
michael@0 | 9832 | |
michael@0 | 9833 | ssl3_CleanupPeerCerts(ss); |
michael@0 | 9834 | isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 9835 | |
michael@0 | 9836 | /* It is reported that some TLS client sends a Certificate message |
michael@0 | 9837 | ** with a zero-length message body. We'll treat that case like a |
michael@0 | 9838 | ** normal no_certificates message to maximize interoperability. |
michael@0 | 9839 | */ |
michael@0 | 9840 | if (length) { |
michael@0 | 9841 | remaining = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
michael@0 | 9842 | if (remaining < 0) |
michael@0 | 9843 | goto loser; /* fatal alert already sent by ConsumeHandshake. */ |
michael@0 | 9844 | if ((PRUint32)remaining > length) |
michael@0 | 9845 | goto decode_loser; |
michael@0 | 9846 | } |
michael@0 | 9847 | |
michael@0 | 9848 | if (!remaining) { |
michael@0 | 9849 | if (!(isTLS && isServer)) { |
michael@0 | 9850 | desc = bad_certificate; |
michael@0 | 9851 | goto alert_loser; |
michael@0 | 9852 | } |
michael@0 | 9853 | /* This is TLS's version of a no_certificate alert. */ |
michael@0 | 9854 | /* I'm a server. I've requested a client cert. He hasn't got one. */ |
michael@0 | 9855 | rv = ssl3_HandleNoCertificate(ss); |
michael@0 | 9856 | if (rv != SECSuccess) { |
michael@0 | 9857 | errCode = PORT_GetError(); |
michael@0 | 9858 | goto loser; |
michael@0 | 9859 | } |
michael@0 | 9860 | ss->ssl3.hs.ws = wait_client_key; |
michael@0 | 9861 | return SECSuccess; |
michael@0 | 9862 | } |
michael@0 | 9863 | |
michael@0 | 9864 | ss->ssl3.peerCertArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 9865 | if (ss->ssl3.peerCertArena == NULL) { |
michael@0 | 9866 | goto loser; /* don't send alerts on memory errors */ |
michael@0 | 9867 | } |
michael@0 | 9868 | |
michael@0 | 9869 | /* First get the peer cert. */ |
michael@0 | 9870 | remaining -= 3; |
michael@0 | 9871 | if (remaining < 0) |
michael@0 | 9872 | goto decode_loser; |
michael@0 | 9873 | |
michael@0 | 9874 | size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
michael@0 | 9875 | if (size <= 0) |
michael@0 | 9876 | goto loser; /* fatal alert already sent by ConsumeHandshake. */ |
michael@0 | 9877 | |
michael@0 | 9878 | if (remaining < size) |
michael@0 | 9879 | goto decode_loser; |
michael@0 | 9880 | |
michael@0 | 9881 | certItem.data = b; |
michael@0 | 9882 | certItem.len = size; |
michael@0 | 9883 | b += size; |
michael@0 | 9884 | length -= size; |
michael@0 | 9885 | remaining -= size; |
michael@0 | 9886 | |
michael@0 | 9887 | ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, |
michael@0 | 9888 | PR_FALSE, PR_TRUE); |
michael@0 | 9889 | if (ss->sec.peerCert == NULL) { |
michael@0 | 9890 | /* We should report an alert if the cert was bad, but not if the |
michael@0 | 9891 | * problem was just some local problem, like memory error. |
michael@0 | 9892 | */ |
michael@0 | 9893 | goto ambiguous_err; |
michael@0 | 9894 | } |
michael@0 | 9895 | |
michael@0 | 9896 | /* Now get all of the CA certs. */ |
michael@0 | 9897 | while (remaining > 0) { |
michael@0 | 9898 | remaining -= 3; |
michael@0 | 9899 | if (remaining < 0) |
michael@0 | 9900 | goto decode_loser; |
michael@0 | 9901 | |
michael@0 | 9902 | size = ssl3_ConsumeHandshakeNumber(ss, 3, &b, &length); |
michael@0 | 9903 | if (size <= 0) |
michael@0 | 9904 | goto loser; /* fatal alert already sent by ConsumeHandshake. */ |
michael@0 | 9905 | |
michael@0 | 9906 | if (remaining < size) |
michael@0 | 9907 | goto decode_loser; |
michael@0 | 9908 | |
michael@0 | 9909 | certItem.data = b; |
michael@0 | 9910 | certItem.len = size; |
michael@0 | 9911 | b += size; |
michael@0 | 9912 | length -= size; |
michael@0 | 9913 | remaining -= size; |
michael@0 | 9914 | |
michael@0 | 9915 | c = PORT_ArenaNew(ss->ssl3.peerCertArena, ssl3CertNode); |
michael@0 | 9916 | if (c == NULL) { |
michael@0 | 9917 | goto loser; /* don't send alerts on memory errors */ |
michael@0 | 9918 | } |
michael@0 | 9919 | |
michael@0 | 9920 | c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, |
michael@0 | 9921 | PR_FALSE, PR_TRUE); |
michael@0 | 9922 | if (c->cert == NULL) { |
michael@0 | 9923 | goto ambiguous_err; |
michael@0 | 9924 | } |
michael@0 | 9925 | |
michael@0 | 9926 | c->next = NULL; |
michael@0 | 9927 | if (lastCert) { |
michael@0 | 9928 | lastCert->next = c; |
michael@0 | 9929 | } else { |
michael@0 | 9930 | ss->ssl3.peerCertChain = c; |
michael@0 | 9931 | } |
michael@0 | 9932 | lastCert = c; |
michael@0 | 9933 | } |
michael@0 | 9934 | |
michael@0 | 9935 | if (remaining != 0) |
michael@0 | 9936 | goto decode_loser; |
michael@0 | 9937 | |
michael@0 | 9938 | SECKEY_UpdateCertPQG(ss->sec.peerCert); |
michael@0 | 9939 | |
michael@0 | 9940 | if (!isServer && ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn)) { |
michael@0 | 9941 | ss->ssl3.hs.ws = wait_certificate_status; |
michael@0 | 9942 | rv = SECSuccess; |
michael@0 | 9943 | } else { |
michael@0 | 9944 | rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */ |
michael@0 | 9945 | } |
michael@0 | 9946 | |
michael@0 | 9947 | return rv; |
michael@0 | 9948 | |
michael@0 | 9949 | ambiguous_err: |
michael@0 | 9950 | errCode = PORT_GetError(); |
michael@0 | 9951 | switch (errCode) { |
michael@0 | 9952 | case PR_OUT_OF_MEMORY_ERROR: |
michael@0 | 9953 | case SEC_ERROR_BAD_DATABASE: |
michael@0 | 9954 | case SEC_ERROR_NO_MEMORY: |
michael@0 | 9955 | if (isTLS) { |
michael@0 | 9956 | desc = internal_error; |
michael@0 | 9957 | goto alert_loser; |
michael@0 | 9958 | } |
michael@0 | 9959 | goto loser; |
michael@0 | 9960 | } |
michael@0 | 9961 | ssl3_SendAlertForCertError(ss, errCode); |
michael@0 | 9962 | goto loser; |
michael@0 | 9963 | |
michael@0 | 9964 | decode_loser: |
michael@0 | 9965 | desc = isTLS ? decode_error : bad_certificate; |
michael@0 | 9966 | |
michael@0 | 9967 | alert_loser: |
michael@0 | 9968 | (void)SSL3_SendAlert(ss, alert_fatal, desc); |
michael@0 | 9969 | |
michael@0 | 9970 | loser: |
michael@0 | 9971 | (void)ssl_MapLowLevelError(errCode); |
michael@0 | 9972 | return SECFailure; |
michael@0 | 9973 | } |
michael@0 | 9974 | |
michael@0 | 9975 | static SECStatus |
michael@0 | 9976 | ssl3_AuthCertificate(sslSocket *ss) |
michael@0 | 9977 | { |
michael@0 | 9978 | SECStatus rv; |
michael@0 | 9979 | PRBool isServer = (PRBool)(!!ss->sec.isServer); |
michael@0 | 9980 | int errCode; |
michael@0 | 9981 | |
michael@0 | 9982 | ss->ssl3.hs.authCertificatePending = PR_FALSE; |
michael@0 | 9983 | |
michael@0 | 9984 | /* |
michael@0 | 9985 | * Ask caller-supplied callback function to validate cert chain. |
michael@0 | 9986 | */ |
michael@0 | 9987 | rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd, |
michael@0 | 9988 | PR_TRUE, isServer); |
michael@0 | 9989 | if (rv) { |
michael@0 | 9990 | errCode = PORT_GetError(); |
michael@0 | 9991 | if (rv != SECWouldBlock) { |
michael@0 | 9992 | if (ss->handleBadCert) { |
michael@0 | 9993 | rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd); |
michael@0 | 9994 | } |
michael@0 | 9995 | } |
michael@0 | 9996 | |
michael@0 | 9997 | if (rv == SECWouldBlock) { |
michael@0 | 9998 | if (ss->sec.isServer) { |
michael@0 | 9999 | errCode = SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS; |
michael@0 | 10000 | rv = SECFailure; |
michael@0 | 10001 | goto loser; |
michael@0 | 10002 | } |
michael@0 | 10003 | |
michael@0 | 10004 | ss->ssl3.hs.authCertificatePending = PR_TRUE; |
michael@0 | 10005 | rv = SECSuccess; |
michael@0 | 10006 | } |
michael@0 | 10007 | |
michael@0 | 10008 | if (rv != SECSuccess) { |
michael@0 | 10009 | ssl3_SendAlertForCertError(ss, errCode); |
michael@0 | 10010 | goto loser; |
michael@0 | 10011 | } |
michael@0 | 10012 | } |
michael@0 | 10013 | |
michael@0 | 10014 | ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); |
michael@0 | 10015 | |
michael@0 | 10016 | if (!ss->sec.isServer) { |
michael@0 | 10017 | CERTCertificate *cert = ss->sec.peerCert; |
michael@0 | 10018 | |
michael@0 | 10019 | /* set the server authentication and key exchange types and sizes |
michael@0 | 10020 | ** from the value in the cert. If the key exchange key is different, |
michael@0 | 10021 | ** it will get fixed when we handle the server key exchange message. |
michael@0 | 10022 | */ |
michael@0 | 10023 | SECKEYPublicKey * pubKey = CERT_ExtractPublicKey(cert); |
michael@0 | 10024 | ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType; |
michael@0 | 10025 | ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType; |
michael@0 | 10026 | if (pubKey) { |
michael@0 | 10027 | ss->sec.keaKeyBits = ss->sec.authKeyBits = |
michael@0 | 10028 | SECKEY_PublicKeyStrengthInBits(pubKey); |
michael@0 | 10029 | #ifndef NSS_DISABLE_ECC |
michael@0 | 10030 | if (ss->sec.keaType == kt_ecdh) { |
michael@0 | 10031 | /* Get authKeyBits from signing key. |
michael@0 | 10032 | * XXX The code below uses a quick approximation of |
michael@0 | 10033 | * key size based on cert->signatureWrap.signature.data |
michael@0 | 10034 | * (which contains the DER encoded signature). The field |
michael@0 | 10035 | * cert->signatureWrap.signature.len contains the |
michael@0 | 10036 | * length of the encoded signature in bits. |
michael@0 | 10037 | */ |
michael@0 | 10038 | if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) { |
michael@0 | 10039 | ss->sec.authKeyBits = |
michael@0 | 10040 | cert->signatureWrap.signature.data[3]*8; |
michael@0 | 10041 | if (cert->signatureWrap.signature.data[4] == 0x00) |
michael@0 | 10042 | ss->sec.authKeyBits -= 8; |
michael@0 | 10043 | /* |
michael@0 | 10044 | * XXX: if cert is not signed by ecdsa we should |
michael@0 | 10045 | * destroy pubKey and goto bad_cert |
michael@0 | 10046 | */ |
michael@0 | 10047 | } else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) { |
michael@0 | 10048 | ss->sec.authKeyBits = cert->signatureWrap.signature.len; |
michael@0 | 10049 | /* |
michael@0 | 10050 | * XXX: if cert is not signed by rsa we should |
michael@0 | 10051 | * destroy pubKey and goto bad_cert |
michael@0 | 10052 | */ |
michael@0 | 10053 | } |
michael@0 | 10054 | } |
michael@0 | 10055 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 10056 | SECKEY_DestroyPublicKey(pubKey); |
michael@0 | 10057 | pubKey = NULL; |
michael@0 | 10058 | } |
michael@0 | 10059 | |
michael@0 | 10060 | ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */ |
michael@0 | 10061 | if (ss->ssl3.hs.kea_def->is_limited || |
michael@0 | 10062 | /* XXX OR server cert is signing only. */ |
michael@0 | 10063 | #ifndef NSS_DISABLE_ECC |
michael@0 | 10064 | ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa || |
michael@0 | 10065 | ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || |
michael@0 | 10066 | #endif /* NSS_DISABLE_ECC */ |
michael@0 | 10067 | ss->ssl3.hs.kea_def->exchKeyType == kt_dh) { |
michael@0 | 10068 | ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */ |
michael@0 | 10069 | } |
michael@0 | 10070 | } else { |
michael@0 | 10071 | ss->ssl3.hs.ws = wait_client_key; |
michael@0 | 10072 | } |
michael@0 | 10073 | |
michael@0 | 10074 | PORT_Assert(rv == SECSuccess); |
michael@0 | 10075 | if (rv != SECSuccess) { |
michael@0 | 10076 | errCode = SEC_ERROR_LIBRARY_FAILURE; |
michael@0 | 10077 | rv = SECFailure; |
michael@0 | 10078 | goto loser; |
michael@0 | 10079 | } |
michael@0 | 10080 | |
michael@0 | 10081 | return rv; |
michael@0 | 10082 | |
michael@0 | 10083 | loser: |
michael@0 | 10084 | (void)ssl_MapLowLevelError(errCode); |
michael@0 | 10085 | return SECFailure; |
michael@0 | 10086 | } |
michael@0 | 10087 | |
michael@0 | 10088 | static SECStatus ssl3_FinishHandshake(sslSocket *ss); |
michael@0 | 10089 | |
michael@0 | 10090 | static SECStatus |
michael@0 | 10091 | ssl3_AlwaysFail(sslSocket * ss) |
michael@0 | 10092 | { |
michael@0 | 10093 | PORT_SetError(PR_INVALID_STATE_ERROR); |
michael@0 | 10094 | return SECFailure; |
michael@0 | 10095 | } |
michael@0 | 10096 | |
michael@0 | 10097 | /* Caller must hold 1stHandshakeLock. |
michael@0 | 10098 | */ |
michael@0 | 10099 | SECStatus |
michael@0 | 10100 | ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error) |
michael@0 | 10101 | { |
michael@0 | 10102 | SECStatus rv; |
michael@0 | 10103 | |
michael@0 | 10104 | PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); |
michael@0 | 10105 | |
michael@0 | 10106 | if (ss->sec.isServer) { |
michael@0 | 10107 | PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SERVERS); |
michael@0 | 10108 | return SECFailure; |
michael@0 | 10109 | } |
michael@0 | 10110 | |
michael@0 | 10111 | ssl_GetRecvBufLock(ss); |
michael@0 | 10112 | ssl_GetSSL3HandshakeLock(ss); |
michael@0 | 10113 | |
michael@0 | 10114 | if (!ss->ssl3.hs.authCertificatePending) { |
michael@0 | 10115 | PORT_SetError(PR_INVALID_STATE_ERROR); |
michael@0 | 10116 | rv = SECFailure; |
michael@0 | 10117 | goto done; |
michael@0 | 10118 | } |
michael@0 | 10119 | |
michael@0 | 10120 | ss->ssl3.hs.authCertificatePending = PR_FALSE; |
michael@0 | 10121 | |
michael@0 | 10122 | if (error != 0) { |
michael@0 | 10123 | ss->ssl3.hs.restartTarget = ssl3_AlwaysFail; |
michael@0 | 10124 | ssl3_SendAlertForCertError(ss, error); |
michael@0 | 10125 | rv = SECSuccess; |
michael@0 | 10126 | } else if (ss->ssl3.hs.restartTarget != NULL) { |
michael@0 | 10127 | sslRestartTarget target = ss->ssl3.hs.restartTarget; |
michael@0 | 10128 | ss->ssl3.hs.restartTarget = NULL; |
michael@0 | 10129 | |
michael@0 | 10130 | if (target == ssl3_FinishHandshake) { |
michael@0 | 10131 | SSL_TRC(3,("%d: SSL3[%p]: certificate authentication lost the race" |
michael@0 | 10132 | " with peer's finished message", SSL_GETPID(), ss->fd)); |
michael@0 | 10133 | } |
michael@0 | 10134 | |
michael@0 | 10135 | rv = target(ss); |
michael@0 | 10136 | /* Even if we blocked here, we have accomplished enough to claim |
michael@0 | 10137 | * success. Any remaining work will be taken care of by subsequent |
michael@0 | 10138 | * calls to SSL_ForceHandshake/PR_Send/PR_Read/etc. |
michael@0 | 10139 | */ |
michael@0 | 10140 | if (rv == SECWouldBlock) { |
michael@0 | 10141 | rv = SECSuccess; |
michael@0 | 10142 | } |
michael@0 | 10143 | } else { |
michael@0 | 10144 | SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with" |
michael@0 | 10145 | " peer's finished message", SSL_GETPID(), ss->fd)); |
michael@0 | 10146 | |
michael@0 | 10147 | PORT_Assert(!ss->ssl3.hs.isResuming); |
michael@0 | 10148 | PORT_Assert(ss->ssl3.hs.ws != idle_handshake); |
michael@0 | 10149 | |
michael@0 | 10150 | if (ss->opt.enableFalseStart && |
michael@0 | 10151 | !ss->firstHsDone && |
michael@0 | 10152 | !ss->ssl3.hs.isResuming && |
michael@0 | 10153 | ssl3_WaitingForStartOfServerSecondRound(ss)) { |
michael@0 | 10154 | /* ssl3_SendClientSecondRound deferred the false start check because |
michael@0 | 10155 | * certificate authentication was pending, so we do it now if we still |
michael@0 | 10156 | * haven't received any of the server's second round yet. |
michael@0 | 10157 | */ |
michael@0 | 10158 | rv = ssl3_CheckFalseStart(ss); |
michael@0 | 10159 | } else { |
michael@0 | 10160 | rv = SECSuccess; |
michael@0 | 10161 | } |
michael@0 | 10162 | } |
michael@0 | 10163 | |
michael@0 | 10164 | done: |
michael@0 | 10165 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 10166 | ssl_ReleaseRecvBufLock(ss); |
michael@0 | 10167 | |
michael@0 | 10168 | return rv; |
michael@0 | 10169 | } |
michael@0 | 10170 | |
michael@0 | 10171 | static SECStatus |
michael@0 | 10172 | ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, |
michael@0 | 10173 | PRBool isServer, |
michael@0 | 10174 | const SSL3Hashes * hashes, |
michael@0 | 10175 | TLSFinished * tlsFinished) |
michael@0 | 10176 | { |
michael@0 | 10177 | const char * label; |
michael@0 | 10178 | unsigned int len; |
michael@0 | 10179 | SECStatus rv; |
michael@0 | 10180 | |
michael@0 | 10181 | label = isServer ? "server finished" : "client finished"; |
michael@0 | 10182 | len = 15; |
michael@0 | 10183 | |
michael@0 | 10184 | rv = ssl3_TLSPRFWithMasterSecret(spec, label, len, hashes->u.raw, |
michael@0 | 10185 | hashes->len, tlsFinished->verify_data, |
michael@0 | 10186 | sizeof tlsFinished->verify_data); |
michael@0 | 10187 | |
michael@0 | 10188 | return rv; |
michael@0 | 10189 | } |
michael@0 | 10190 | |
michael@0 | 10191 | /* The calling function must acquire and release the appropriate |
michael@0 | 10192 | * lock (e.g., ssl_GetSpecReadLock / ssl_ReleaseSpecReadLock for |
michael@0 | 10193 | * ss->ssl3.crSpec). |
michael@0 | 10194 | */ |
michael@0 | 10195 | SECStatus |
michael@0 | 10196 | ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label, |
michael@0 | 10197 | unsigned int labelLen, const unsigned char *val, unsigned int valLen, |
michael@0 | 10198 | unsigned char *out, unsigned int outLen) |
michael@0 | 10199 | { |
michael@0 | 10200 | SECStatus rv = SECSuccess; |
michael@0 | 10201 | |
michael@0 | 10202 | if (spec->master_secret && !spec->bypassCiphers) { |
michael@0 | 10203 | SECItem param = {siBuffer, NULL, 0}; |
michael@0 | 10204 | CK_MECHANISM_TYPE mech = CKM_TLS_PRF_GENERAL; |
michael@0 | 10205 | PK11Context *prf_context; |
michael@0 | 10206 | unsigned int retLen; |
michael@0 | 10207 | |
michael@0 | 10208 | if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 10209 | mech = CKM_NSS_TLS_PRF_GENERAL_SHA256; |
michael@0 | 10210 | } |
michael@0 | 10211 | prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN, |
michael@0 | 10212 | spec->master_secret, ¶m); |
michael@0 | 10213 | if (!prf_context) |
michael@0 | 10214 | return SECFailure; |
michael@0 | 10215 | |
michael@0 | 10216 | rv = PK11_DigestBegin(prf_context); |
michael@0 | 10217 | rv |= PK11_DigestOp(prf_context, (unsigned char *) label, labelLen); |
michael@0 | 10218 | rv |= PK11_DigestOp(prf_context, val, valLen); |
michael@0 | 10219 | rv |= PK11_DigestFinal(prf_context, out, &retLen, outLen); |
michael@0 | 10220 | PORT_Assert(rv != SECSuccess || retLen == outLen); |
michael@0 | 10221 | |
michael@0 | 10222 | PK11_DestroyContext(prf_context, PR_TRUE); |
michael@0 | 10223 | } else { |
michael@0 | 10224 | /* bypass PKCS11 */ |
michael@0 | 10225 | #ifdef NO_PKCS11_BYPASS |
michael@0 | 10226 | PORT_Assert(spec->master_secret); |
michael@0 | 10227 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 10228 | rv = SECFailure; |
michael@0 | 10229 | #else |
michael@0 | 10230 | SECItem inData = { siBuffer, }; |
michael@0 | 10231 | SECItem outData = { siBuffer, }; |
michael@0 | 10232 | PRBool isFIPS = PR_FALSE; |
michael@0 | 10233 | |
michael@0 | 10234 | inData.data = (unsigned char *) val; |
michael@0 | 10235 | inData.len = valLen; |
michael@0 | 10236 | outData.data = out; |
michael@0 | 10237 | outData.len = outLen; |
michael@0 | 10238 | if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 10239 | rv = TLS_P_hash(HASH_AlgSHA256, &spec->msItem, label, &inData, |
michael@0 | 10240 | &outData, isFIPS); |
michael@0 | 10241 | } else { |
michael@0 | 10242 | rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); |
michael@0 | 10243 | } |
michael@0 | 10244 | PORT_Assert(rv != SECSuccess || outData.len == outLen); |
michael@0 | 10245 | #endif |
michael@0 | 10246 | } |
michael@0 | 10247 | return rv; |
michael@0 | 10248 | } |
michael@0 | 10249 | |
michael@0 | 10250 | /* called from ssl3_SendClientSecondRound |
michael@0 | 10251 | * ssl3_HandleFinished |
michael@0 | 10252 | */ |
michael@0 | 10253 | static SECStatus |
michael@0 | 10254 | ssl3_SendNextProto(sslSocket *ss) |
michael@0 | 10255 | { |
michael@0 | 10256 | SECStatus rv; |
michael@0 | 10257 | int padding_len; |
michael@0 | 10258 | static const unsigned char padding[32] = {0}; |
michael@0 | 10259 | |
michael@0 | 10260 | if (ss->ssl3.nextProto.len == 0 || |
michael@0 | 10261 | ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) { |
michael@0 | 10262 | return SECSuccess; |
michael@0 | 10263 | } |
michael@0 | 10264 | |
michael@0 | 10265 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 10266 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 10267 | |
michael@0 | 10268 | padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32); |
michael@0 | 10269 | |
michael@0 | 10270 | rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len + |
michael@0 | 10271 | 2 + padding_len); |
michael@0 | 10272 | if (rv != SECSuccess) { |
michael@0 | 10273 | return rv; /* error code set by AppendHandshakeHeader */ |
michael@0 | 10274 | } |
michael@0 | 10275 | rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data, |
michael@0 | 10276 | ss->ssl3.nextProto.len, 1); |
michael@0 | 10277 | if (rv != SECSuccess) { |
michael@0 | 10278 | return rv; /* error code set by AppendHandshake */ |
michael@0 | 10279 | } |
michael@0 | 10280 | rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1); |
michael@0 | 10281 | if (rv != SECSuccess) { |
michael@0 | 10282 | return rv; /* error code set by AppendHandshake */ |
michael@0 | 10283 | } |
michael@0 | 10284 | return rv; |
michael@0 | 10285 | } |
michael@0 | 10286 | |
michael@0 | 10287 | /* called from ssl3_SendFinished |
michael@0 | 10288 | * |
michael@0 | 10289 | * This function is simply a debugging aid and therefore does not return a |
michael@0 | 10290 | * SECStatus. */ |
michael@0 | 10291 | static void |
michael@0 | 10292 | ssl3_RecordKeyLog(sslSocket *ss) |
michael@0 | 10293 | { |
michael@0 | 10294 | SECStatus rv; |
michael@0 | 10295 | SECItem *keyData; |
michael@0 | 10296 | char buf[14 /* "CLIENT_RANDOM " */ + |
michael@0 | 10297 | SSL3_RANDOM_LENGTH*2 /* client_random */ + |
michael@0 | 10298 | 1 /* " " */ + |
michael@0 | 10299 | 48*2 /* master secret */ + |
michael@0 | 10300 | 1 /* new line */]; |
michael@0 | 10301 | unsigned int j; |
michael@0 | 10302 | |
michael@0 | 10303 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 10304 | |
michael@0 | 10305 | if (!ssl_keylog_iob) |
michael@0 | 10306 | return; |
michael@0 | 10307 | |
michael@0 | 10308 | rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret); |
michael@0 | 10309 | if (rv != SECSuccess) |
michael@0 | 10310 | return; |
michael@0 | 10311 | |
michael@0 | 10312 | ssl_GetSpecReadLock(ss); |
michael@0 | 10313 | |
michael@0 | 10314 | /* keyData does not need to be freed. */ |
michael@0 | 10315 | keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret); |
michael@0 | 10316 | if (!keyData || !keyData->data || keyData->len != 48) { |
michael@0 | 10317 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 10318 | return; |
michael@0 | 10319 | } |
michael@0 | 10320 | |
michael@0 | 10321 | /* https://developer.mozilla.org/en/NSS_Key_Log_Format */ |
michael@0 | 10322 | |
michael@0 | 10323 | /* There could be multiple, concurrent writers to the |
michael@0 | 10324 | * keylog, so we have to do everything in a single call to |
michael@0 | 10325 | * fwrite. */ |
michael@0 | 10326 | |
michael@0 | 10327 | memcpy(buf, "CLIENT_RANDOM ", 14); |
michael@0 | 10328 | j = 14; |
michael@0 | 10329 | hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); |
michael@0 | 10330 | j += SSL3_RANDOM_LENGTH*2; |
michael@0 | 10331 | buf[j++] = ' '; |
michael@0 | 10332 | hexEncode(buf + j, keyData->data, 48); |
michael@0 | 10333 | j += 48*2; |
michael@0 | 10334 | buf[j++] = '\n'; |
michael@0 | 10335 | |
michael@0 | 10336 | PORT_Assert(j == sizeof(buf)); |
michael@0 | 10337 | |
michael@0 | 10338 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 10339 | |
michael@0 | 10340 | if (fwrite(buf, sizeof(buf), 1, ssl_keylog_iob) != 1) |
michael@0 | 10341 | return; |
michael@0 | 10342 | fflush(ssl_keylog_iob); |
michael@0 | 10343 | return; |
michael@0 | 10344 | } |
michael@0 | 10345 | |
michael@0 | 10346 | /* called from ssl3_SendClientSecondRound |
michael@0 | 10347 | * ssl3_HandleClientHello |
michael@0 | 10348 | * ssl3_HandleFinished |
michael@0 | 10349 | */ |
michael@0 | 10350 | static SECStatus |
michael@0 | 10351 | ssl3_SendFinished(sslSocket *ss, PRInt32 flags) |
michael@0 | 10352 | { |
michael@0 | 10353 | ssl3CipherSpec *cwSpec; |
michael@0 | 10354 | PRBool isTLS; |
michael@0 | 10355 | PRBool isServer = ss->sec.isServer; |
michael@0 | 10356 | SECStatus rv; |
michael@0 | 10357 | SSL3Sender sender = isServer ? sender_server : sender_client; |
michael@0 | 10358 | SSL3Hashes hashes; |
michael@0 | 10359 | TLSFinished tlsFinished; |
michael@0 | 10360 | |
michael@0 | 10361 | SSL_TRC(3, ("%d: SSL3[%d]: send finished handshake", SSL_GETPID(), ss->fd)); |
michael@0 | 10362 | |
michael@0 | 10363 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 10364 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 10365 | |
michael@0 | 10366 | ssl_GetSpecReadLock(ss); |
michael@0 | 10367 | cwSpec = ss->ssl3.cwSpec; |
michael@0 | 10368 | isTLS = (PRBool)(cwSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 10369 | rv = ssl3_ComputeHandshakeHashes(ss, cwSpec, &hashes, sender); |
michael@0 | 10370 | if (isTLS && rv == SECSuccess) { |
michael@0 | 10371 | rv = ssl3_ComputeTLSFinished(cwSpec, isServer, &hashes, &tlsFinished); |
michael@0 | 10372 | } |
michael@0 | 10373 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 10374 | if (rv != SECSuccess) { |
michael@0 | 10375 | goto fail; /* err code was set by ssl3_ComputeHandshakeHashes */ |
michael@0 | 10376 | } |
michael@0 | 10377 | |
michael@0 | 10378 | if (isTLS) { |
michael@0 | 10379 | if (isServer) |
michael@0 | 10380 | ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; |
michael@0 | 10381 | else |
michael@0 | 10382 | ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; |
michael@0 | 10383 | ss->ssl3.hs.finishedBytes = sizeof tlsFinished; |
michael@0 | 10384 | rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof tlsFinished); |
michael@0 | 10385 | if (rv != SECSuccess) |
michael@0 | 10386 | goto fail; /* err set by AppendHandshake. */ |
michael@0 | 10387 | rv = ssl3_AppendHandshake(ss, &tlsFinished, sizeof tlsFinished); |
michael@0 | 10388 | if (rv != SECSuccess) |
michael@0 | 10389 | goto fail; /* err set by AppendHandshake. */ |
michael@0 | 10390 | } else { |
michael@0 | 10391 | if (isServer) |
michael@0 | 10392 | ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes.u.s; |
michael@0 | 10393 | else |
michael@0 | 10394 | ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes.u.s; |
michael@0 | 10395 | PORT_Assert(hashes.len == sizeof hashes.u.s); |
michael@0 | 10396 | ss->ssl3.hs.finishedBytes = sizeof hashes.u.s; |
michael@0 | 10397 | rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes.u.s); |
michael@0 | 10398 | if (rv != SECSuccess) |
michael@0 | 10399 | goto fail; /* err set by AppendHandshake. */ |
michael@0 | 10400 | rv = ssl3_AppendHandshake(ss, &hashes.u.s, sizeof hashes.u.s); |
michael@0 | 10401 | if (rv != SECSuccess) |
michael@0 | 10402 | goto fail; /* err set by AppendHandshake. */ |
michael@0 | 10403 | } |
michael@0 | 10404 | rv = ssl3_FlushHandshake(ss, flags); |
michael@0 | 10405 | if (rv != SECSuccess) { |
michael@0 | 10406 | goto fail; /* error code set by ssl3_FlushHandshake */ |
michael@0 | 10407 | } |
michael@0 | 10408 | |
michael@0 | 10409 | ssl3_RecordKeyLog(ss); |
michael@0 | 10410 | |
michael@0 | 10411 | return SECSuccess; |
michael@0 | 10412 | |
michael@0 | 10413 | fail: |
michael@0 | 10414 | return rv; |
michael@0 | 10415 | } |
michael@0 | 10416 | |
michael@0 | 10417 | /* wrap the master secret, and put it into the SID. |
michael@0 | 10418 | * Caller holds the Spec read lock. |
michael@0 | 10419 | */ |
michael@0 | 10420 | SECStatus |
michael@0 | 10421 | ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, |
michael@0 | 10422 | ssl3CipherSpec *spec, SSL3KEAType effectiveExchKeyType) |
michael@0 | 10423 | { |
michael@0 | 10424 | PK11SymKey * wrappingKey = NULL; |
michael@0 | 10425 | PK11SlotInfo * symKeySlot; |
michael@0 | 10426 | void * pwArg = ss->pkcs11PinArg; |
michael@0 | 10427 | SECStatus rv = SECFailure; |
michael@0 | 10428 | PRBool isServer = ss->sec.isServer; |
michael@0 | 10429 | CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; |
michael@0 | 10430 | symKeySlot = PK11_GetSlotFromKey(spec->master_secret); |
michael@0 | 10431 | if (!isServer) { |
michael@0 | 10432 | int wrapKeyIndex; |
michael@0 | 10433 | int incarnation; |
michael@0 | 10434 | |
michael@0 | 10435 | /* these next few functions are mere accessors and don't fail. */ |
michael@0 | 10436 | sid->u.ssl3.masterWrapIndex = wrapKeyIndex = |
michael@0 | 10437 | PK11_GetCurrentWrapIndex(symKeySlot); |
michael@0 | 10438 | PORT_Assert(wrapKeyIndex == 0); /* array has only one entry! */ |
michael@0 | 10439 | |
michael@0 | 10440 | sid->u.ssl3.masterWrapSeries = incarnation = |
michael@0 | 10441 | PK11_GetSlotSeries(symKeySlot); |
michael@0 | 10442 | sid->u.ssl3.masterSlotID = PK11_GetSlotID(symKeySlot); |
michael@0 | 10443 | sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot); |
michael@0 | 10444 | sid->u.ssl3.masterValid = PR_TRUE; |
michael@0 | 10445 | /* Get the default wrapping key, for wrapping the master secret before |
michael@0 | 10446 | * placing it in the SID cache entry. */ |
michael@0 | 10447 | wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex, |
michael@0 | 10448 | CKM_INVALID_MECHANISM, incarnation, |
michael@0 | 10449 | pwArg); |
michael@0 | 10450 | if (wrappingKey) { |
michael@0 | 10451 | mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ |
michael@0 | 10452 | } else { |
michael@0 | 10453 | int keyLength; |
michael@0 | 10454 | /* if the wrappingKey doesn't exist, attempt to create it. |
michael@0 | 10455 | * Note: we intentionally ignore errors here. If we cannot |
michael@0 | 10456 | * generate a wrapping key, it is not fatal to this SSL connection, |
michael@0 | 10457 | * but we will not be able to restart this session. |
michael@0 | 10458 | */ |
michael@0 | 10459 | mechanism = PK11_GetBestWrapMechanism(symKeySlot); |
michael@0 | 10460 | keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism); |
michael@0 | 10461 | /* Zero length means fixed key length algorithm, or error. |
michael@0 | 10462 | * It's ambiguous. |
michael@0 | 10463 | */ |
michael@0 | 10464 | wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL, |
michael@0 | 10465 | keyLength, pwArg); |
michael@0 | 10466 | if (wrappingKey) { |
michael@0 | 10467 | PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey); |
michael@0 | 10468 | } |
michael@0 | 10469 | } |
michael@0 | 10470 | } else { |
michael@0 | 10471 | /* server socket using session cache. */ |
michael@0 | 10472 | mechanism = PK11_GetBestWrapMechanism(symKeySlot); |
michael@0 | 10473 | if (mechanism != CKM_INVALID_MECHANISM) { |
michael@0 | 10474 | wrappingKey = |
michael@0 | 10475 | getWrappingKey(ss, symKeySlot, effectiveExchKeyType, |
michael@0 | 10476 | mechanism, pwArg); |
michael@0 | 10477 | if (wrappingKey) { |
michael@0 | 10478 | mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ |
michael@0 | 10479 | } |
michael@0 | 10480 | } |
michael@0 | 10481 | } |
michael@0 | 10482 | |
michael@0 | 10483 | sid->u.ssl3.masterWrapMech = mechanism; |
michael@0 | 10484 | PK11_FreeSlot(symKeySlot); |
michael@0 | 10485 | |
michael@0 | 10486 | if (wrappingKey) { |
michael@0 | 10487 | SECItem wmsItem; |
michael@0 | 10488 | |
michael@0 | 10489 | wmsItem.data = sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 10490 | wmsItem.len = sizeof sid->u.ssl3.keys.wrapped_master_secret; |
michael@0 | 10491 | rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey, |
michael@0 | 10492 | spec->master_secret, &wmsItem); |
michael@0 | 10493 | /* rv is examined below. */ |
michael@0 | 10494 | sid->u.ssl3.keys.wrapped_master_secret_len = wmsItem.len; |
michael@0 | 10495 | PK11_FreeSymKey(wrappingKey); |
michael@0 | 10496 | } |
michael@0 | 10497 | return rv; |
michael@0 | 10498 | } |
michael@0 | 10499 | |
michael@0 | 10500 | /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
michael@0 | 10501 | * ssl3 Finished message from the peer. |
michael@0 | 10502 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 10503 | */ |
michael@0 | 10504 | static SECStatus |
michael@0 | 10505 | ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, |
michael@0 | 10506 | const SSL3Hashes *hashes) |
michael@0 | 10507 | { |
michael@0 | 10508 | sslSessionID * sid = ss->sec.ci.sid; |
michael@0 | 10509 | SECStatus rv = SECSuccess; |
michael@0 | 10510 | PRBool isServer = ss->sec.isServer; |
michael@0 | 10511 | PRBool isTLS; |
michael@0 | 10512 | SSL3KEAType effectiveExchKeyType; |
michael@0 | 10513 | |
michael@0 | 10514 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 10515 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 10516 | |
michael@0 | 10517 | SSL_TRC(3, ("%d: SSL3[%d]: handle finished handshake", |
michael@0 | 10518 | SSL_GETPID(), ss->fd)); |
michael@0 | 10519 | |
michael@0 | 10520 | if (ss->ssl3.hs.ws != wait_finished) { |
michael@0 | 10521 | SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10522 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED); |
michael@0 | 10523 | return SECFailure; |
michael@0 | 10524 | } |
michael@0 | 10525 | |
michael@0 | 10526 | isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 10527 | if (isTLS) { |
michael@0 | 10528 | TLSFinished tlsFinished; |
michael@0 | 10529 | |
michael@0 | 10530 | if (length != sizeof tlsFinished) { |
michael@0 | 10531 | (void)SSL3_SendAlert(ss, alert_fatal, decode_error); |
michael@0 | 10532 | PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED); |
michael@0 | 10533 | return SECFailure; |
michael@0 | 10534 | } |
michael@0 | 10535 | rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, |
michael@0 | 10536 | hashes, &tlsFinished); |
michael@0 | 10537 | if (!isServer) |
michael@0 | 10538 | ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; |
michael@0 | 10539 | else |
michael@0 | 10540 | ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; |
michael@0 | 10541 | ss->ssl3.hs.finishedBytes = sizeof tlsFinished; |
michael@0 | 10542 | if (rv != SECSuccess || |
michael@0 | 10543 | 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) { |
michael@0 | 10544 | (void)SSL3_SendAlert(ss, alert_fatal, decrypt_error); |
michael@0 | 10545 | PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
michael@0 | 10546 | return SECFailure; |
michael@0 | 10547 | } |
michael@0 | 10548 | } else { |
michael@0 | 10549 | if (length != sizeof(SSL3Finished)) { |
michael@0 | 10550 | (void)ssl3_IllegalParameter(ss); |
michael@0 | 10551 | PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED); |
michael@0 | 10552 | return SECFailure; |
michael@0 | 10553 | } |
michael@0 | 10554 | |
michael@0 | 10555 | if (!isServer) |
michael@0 | 10556 | ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes->u.s; |
michael@0 | 10557 | else |
michael@0 | 10558 | ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes->u.s; |
michael@0 | 10559 | PORT_Assert(hashes->len == sizeof hashes->u.s); |
michael@0 | 10560 | ss->ssl3.hs.finishedBytes = sizeof hashes->u.s; |
michael@0 | 10561 | if (0 != NSS_SecureMemcmp(&hashes->u.s, b, length)) { |
michael@0 | 10562 | (void)ssl3_HandshakeFailure(ss); |
michael@0 | 10563 | PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
michael@0 | 10564 | return SECFailure; |
michael@0 | 10565 | } |
michael@0 | 10566 | } |
michael@0 | 10567 | |
michael@0 | 10568 | ssl_GetXmitBufLock(ss); /*************************************/ |
michael@0 | 10569 | |
michael@0 | 10570 | if ((isServer && !ss->ssl3.hs.isResuming) || |
michael@0 | 10571 | (!isServer && ss->ssl3.hs.isResuming)) { |
michael@0 | 10572 | PRInt32 flags = 0; |
michael@0 | 10573 | |
michael@0 | 10574 | /* Send a NewSessionTicket message if the client sent us |
michael@0 | 10575 | * either an empty session ticket, or one that did not verify. |
michael@0 | 10576 | * (Note that if either of these conditions was met, then the |
michael@0 | 10577 | * server has sent a SessionTicket extension in the |
michael@0 | 10578 | * ServerHello message.) |
michael@0 | 10579 | */ |
michael@0 | 10580 | if (isServer && !ss->ssl3.hs.isResuming && |
michael@0 | 10581 | ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) { |
michael@0 | 10582 | /* RFC 5077 Section 3.3: "In the case of a full handshake, the |
michael@0 | 10583 | * server MUST verify the client's Finished message before sending |
michael@0 | 10584 | * the ticket." Presumably, this also means that the client's |
michael@0 | 10585 | * certificate, if any, must be verified beforehand too. |
michael@0 | 10586 | */ |
michael@0 | 10587 | rv = ssl3_SendNewSessionTicket(ss); |
michael@0 | 10588 | if (rv != SECSuccess) { |
michael@0 | 10589 | goto xmit_loser; |
michael@0 | 10590 | } |
michael@0 | 10591 | } |
michael@0 | 10592 | |
michael@0 | 10593 | rv = ssl3_SendChangeCipherSpecs(ss); |
michael@0 | 10594 | if (rv != SECSuccess) { |
michael@0 | 10595 | goto xmit_loser; /* err is set. */ |
michael@0 | 10596 | } |
michael@0 | 10597 | /* If this thread is in SSL_SecureSend (trying to write some data) |
michael@0 | 10598 | ** then set the ssl_SEND_FLAG_FORCE_INTO_BUFFER flag, so that the |
michael@0 | 10599 | ** last two handshake messages (change cipher spec and finished) |
michael@0 | 10600 | ** will be sent in the same send/write call as the application data. |
michael@0 | 10601 | */ |
michael@0 | 10602 | if (ss->writerThread == PR_GetCurrentThread()) { |
michael@0 | 10603 | flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER; |
michael@0 | 10604 | } |
michael@0 | 10605 | |
michael@0 | 10606 | if (!isServer && !ss->firstHsDone) { |
michael@0 | 10607 | rv = ssl3_SendNextProto(ss); |
michael@0 | 10608 | if (rv != SECSuccess) { |
michael@0 | 10609 | goto xmit_loser; /* err code was set. */ |
michael@0 | 10610 | } |
michael@0 | 10611 | } |
michael@0 | 10612 | |
michael@0 | 10613 | if (IS_DTLS(ss)) { |
michael@0 | 10614 | flags |= ssl_SEND_FLAG_NO_RETRANSMIT; |
michael@0 | 10615 | } |
michael@0 | 10616 | |
michael@0 | 10617 | rv = ssl3_SendFinished(ss, flags); |
michael@0 | 10618 | if (rv != SECSuccess) { |
michael@0 | 10619 | goto xmit_loser; /* err is set. */ |
michael@0 | 10620 | } |
michael@0 | 10621 | } |
michael@0 | 10622 | |
michael@0 | 10623 | xmit_loser: |
michael@0 | 10624 | ssl_ReleaseXmitBufLock(ss); /*************************************/ |
michael@0 | 10625 | if (rv != SECSuccess) { |
michael@0 | 10626 | return rv; |
michael@0 | 10627 | } |
michael@0 | 10628 | |
michael@0 | 10629 | if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) { |
michael@0 | 10630 | effectiveExchKeyType = kt_rsa; |
michael@0 | 10631 | } else { |
michael@0 | 10632 | effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; |
michael@0 | 10633 | } |
michael@0 | 10634 | |
michael@0 | 10635 | if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) { |
michael@0 | 10636 | /* fill in the sid */ |
michael@0 | 10637 | sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite; |
michael@0 | 10638 | sid->u.ssl3.compression = ss->ssl3.hs.compression; |
michael@0 | 10639 | sid->u.ssl3.policy = ss->ssl3.policy; |
michael@0 | 10640 | #ifndef NSS_DISABLE_ECC |
michael@0 | 10641 | sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves; |
michael@0 | 10642 | #endif |
michael@0 | 10643 | sid->u.ssl3.exchKeyType = effectiveExchKeyType; |
michael@0 | 10644 | sid->version = ss->version; |
michael@0 | 10645 | sid->authAlgorithm = ss->sec.authAlgorithm; |
michael@0 | 10646 | sid->authKeyBits = ss->sec.authKeyBits; |
michael@0 | 10647 | sid->keaType = ss->sec.keaType; |
michael@0 | 10648 | sid->keaKeyBits = ss->sec.keaKeyBits; |
michael@0 | 10649 | sid->lastAccessTime = sid->creationTime = ssl_Time(); |
michael@0 | 10650 | sid->expirationTime = sid->creationTime + ssl3_sid_timeout; |
michael@0 | 10651 | sid->localCert = CERT_DupCertificate(ss->sec.localCert); |
michael@0 | 10652 | |
michael@0 | 10653 | ssl_GetSpecReadLock(ss); /*************************************/ |
michael@0 | 10654 | |
michael@0 | 10655 | /* Copy the master secret (wrapped or unwrapped) into the sid */ |
michael@0 | 10656 | if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) { |
michael@0 | 10657 | sid->u.ssl3.keys.wrapped_master_secret_len = |
michael@0 | 10658 | ss->ssl3.crSpec->msItem.len; |
michael@0 | 10659 | memcpy(sid->u.ssl3.keys.wrapped_master_secret, |
michael@0 | 10660 | ss->ssl3.crSpec->msItem.data, ss->ssl3.crSpec->msItem.len); |
michael@0 | 10661 | sid->u.ssl3.masterValid = PR_TRUE; |
michael@0 | 10662 | sid->u.ssl3.keys.msIsWrapped = PR_FALSE; |
michael@0 | 10663 | rv = SECSuccess; |
michael@0 | 10664 | } else { |
michael@0 | 10665 | rv = ssl3_CacheWrappedMasterSecret(ss, ss->sec.ci.sid, |
michael@0 | 10666 | ss->ssl3.crSpec, |
michael@0 | 10667 | effectiveExchKeyType); |
michael@0 | 10668 | sid->u.ssl3.keys.msIsWrapped = PR_TRUE; |
michael@0 | 10669 | } |
michael@0 | 10670 | ssl_ReleaseSpecReadLock(ss); /*************************************/ |
michael@0 | 10671 | |
michael@0 | 10672 | /* If the wrap failed, we don't cache the sid. |
michael@0 | 10673 | * The connection continues normally however. |
michael@0 | 10674 | */ |
michael@0 | 10675 | ss->ssl3.hs.cacheSID = rv == SECSuccess; |
michael@0 | 10676 | } |
michael@0 | 10677 | |
michael@0 | 10678 | if (ss->ssl3.hs.authCertificatePending) { |
michael@0 | 10679 | if (ss->ssl3.hs.restartTarget) { |
michael@0 | 10680 | PR_NOT_REACHED("ssl3_HandleFinished: unexpected restartTarget"); |
michael@0 | 10681 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 10682 | return SECFailure; |
michael@0 | 10683 | } |
michael@0 | 10684 | |
michael@0 | 10685 | ss->ssl3.hs.restartTarget = ssl3_FinishHandshake; |
michael@0 | 10686 | return SECWouldBlock; |
michael@0 | 10687 | } |
michael@0 | 10688 | |
michael@0 | 10689 | rv = ssl3_FinishHandshake(ss); |
michael@0 | 10690 | return rv; |
michael@0 | 10691 | } |
michael@0 | 10692 | |
michael@0 | 10693 | /* The return type is SECStatus instead of void because this function needs |
michael@0 | 10694 | * to have type sslRestartTarget. |
michael@0 | 10695 | */ |
michael@0 | 10696 | SECStatus |
michael@0 | 10697 | ssl3_FinishHandshake(sslSocket * ss) |
michael@0 | 10698 | { |
michael@0 | 10699 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 10700 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 10701 | PORT_Assert( ss->ssl3.hs.restartTarget == NULL ); |
michael@0 | 10702 | |
michael@0 | 10703 | /* The first handshake is now completed. */ |
michael@0 | 10704 | ss->handshake = NULL; |
michael@0 | 10705 | |
michael@0 | 10706 | /* RFC 5077 Section 3.3: "The client MUST NOT treat the ticket as valid |
michael@0 | 10707 | * until it has verified the server's Finished message." When the server |
michael@0 | 10708 | * sends a NewSessionTicket in a resumption handshake, we must wait until |
michael@0 | 10709 | * the handshake is finished (we have verified the server's Finished |
michael@0 | 10710 | * AND the server's certificate) before we update the ticket in the sid. |
michael@0 | 10711 | * |
michael@0 | 10712 | * This must be done before we call (*ss->sec.cache)(ss->sec.ci.sid) |
michael@0 | 10713 | * because CacheSID requires the session ticket to already be set, and also |
michael@0 | 10714 | * because of the lazy lock creation scheme used by CacheSID and |
michael@0 | 10715 | * ssl3_SetSIDSessionTicket. |
michael@0 | 10716 | */ |
michael@0 | 10717 | if (ss->ssl3.hs.receivedNewSessionTicket) { |
michael@0 | 10718 | PORT_Assert(!ss->sec.isServer); |
michael@0 | 10719 | ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket); |
michael@0 | 10720 | /* The sid took over the ticket data */ |
michael@0 | 10721 | PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data); |
michael@0 | 10722 | ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; |
michael@0 | 10723 | } |
michael@0 | 10724 | |
michael@0 | 10725 | if (ss->ssl3.hs.cacheSID) { |
michael@0 | 10726 | PORT_Assert(ss->sec.ci.sid->cached == never_cached); |
michael@0 | 10727 | (*ss->sec.cache)(ss->sec.ci.sid); |
michael@0 | 10728 | ss->ssl3.hs.cacheSID = PR_FALSE; |
michael@0 | 10729 | } |
michael@0 | 10730 | |
michael@0 | 10731 | ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */ |
michael@0 | 10732 | ss->ssl3.hs.ws = idle_handshake; |
michael@0 | 10733 | |
michael@0 | 10734 | ssl_FinishHandshake(ss); |
michael@0 | 10735 | |
michael@0 | 10736 | return SECSuccess; |
michael@0 | 10737 | } |
michael@0 | 10738 | |
michael@0 | 10739 | /* Called from ssl3_HandleHandshake() when it has gathered a complete ssl3 |
michael@0 | 10740 | * hanshake message. |
michael@0 | 10741 | * Caller must hold Handshake and RecvBuf locks. |
michael@0 | 10742 | */ |
michael@0 | 10743 | SECStatus |
michael@0 | 10744 | ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) |
michael@0 | 10745 | { |
michael@0 | 10746 | SECStatus rv = SECSuccess; |
michael@0 | 10747 | SSL3HandshakeType type = ss->ssl3.hs.msg_type; |
michael@0 | 10748 | SSL3Hashes hashes; /* computed hashes are put here. */ |
michael@0 | 10749 | PRUint8 hdr[4]; |
michael@0 | 10750 | PRUint8 dtlsData[8]; |
michael@0 | 10751 | |
michael@0 | 10752 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 10753 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 10754 | /* |
michael@0 | 10755 | * We have to compute the hashes before we update them with the |
michael@0 | 10756 | * current message. |
michael@0 | 10757 | */ |
michael@0 | 10758 | ssl_GetSpecReadLock(ss); /************************************/ |
michael@0 | 10759 | if((type == finished) || (type == certificate_verify)) { |
michael@0 | 10760 | SSL3Sender sender = (SSL3Sender)0; |
michael@0 | 10761 | ssl3CipherSpec *rSpec = ss->ssl3.prSpec; |
michael@0 | 10762 | |
michael@0 | 10763 | if (type == finished) { |
michael@0 | 10764 | sender = ss->sec.isServer ? sender_client : sender_server; |
michael@0 | 10765 | rSpec = ss->ssl3.crSpec; |
michael@0 | 10766 | } |
michael@0 | 10767 | rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender); |
michael@0 | 10768 | } |
michael@0 | 10769 | ssl_ReleaseSpecReadLock(ss); /************************************/ |
michael@0 | 10770 | if (rv != SECSuccess) { |
michael@0 | 10771 | return rv; /* error code was set by ssl3_ComputeHandshakeHashes*/ |
michael@0 | 10772 | } |
michael@0 | 10773 | SSL_TRC(30,("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(), |
michael@0 | 10774 | ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type))); |
michael@0 | 10775 | |
michael@0 | 10776 | hdr[0] = (PRUint8)ss->ssl3.hs.msg_type; |
michael@0 | 10777 | hdr[1] = (PRUint8)(length >> 16); |
michael@0 | 10778 | hdr[2] = (PRUint8)(length >> 8); |
michael@0 | 10779 | hdr[3] = (PRUint8)(length ); |
michael@0 | 10780 | |
michael@0 | 10781 | /* Start new handshake hashes when we start a new handshake */ |
michael@0 | 10782 | if (ss->ssl3.hs.msg_type == client_hello) { |
michael@0 | 10783 | rv = ssl3_RestartHandshakeHashes(ss); |
michael@0 | 10784 | if (rv != SECSuccess) { |
michael@0 | 10785 | return rv; |
michael@0 | 10786 | } |
michael@0 | 10787 | } |
michael@0 | 10788 | /* We should not include hello_request and hello_verify_request messages |
michael@0 | 10789 | * in the handshake hashes */ |
michael@0 | 10790 | if ((ss->ssl3.hs.msg_type != hello_request) && |
michael@0 | 10791 | (ss->ssl3.hs.msg_type != hello_verify_request)) { |
michael@0 | 10792 | rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4); |
michael@0 | 10793 | if (rv != SECSuccess) return rv; /* err code already set. */ |
michael@0 | 10794 | |
michael@0 | 10795 | /* Extra data to simulate a complete DTLS handshake fragment */ |
michael@0 | 10796 | if (IS_DTLS(ss)) { |
michael@0 | 10797 | /* Sequence number */ |
michael@0 | 10798 | dtlsData[0] = MSB(ss->ssl3.hs.recvMessageSeq); |
michael@0 | 10799 | dtlsData[1] = LSB(ss->ssl3.hs.recvMessageSeq); |
michael@0 | 10800 | |
michael@0 | 10801 | /* Fragment offset */ |
michael@0 | 10802 | dtlsData[2] = 0; |
michael@0 | 10803 | dtlsData[3] = 0; |
michael@0 | 10804 | dtlsData[4] = 0; |
michael@0 | 10805 | |
michael@0 | 10806 | /* Fragment length */ |
michael@0 | 10807 | dtlsData[5] = (PRUint8)(length >> 16); |
michael@0 | 10808 | dtlsData[6] = (PRUint8)(length >> 8); |
michael@0 | 10809 | dtlsData[7] = (PRUint8)(length ); |
michael@0 | 10810 | |
michael@0 | 10811 | rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) dtlsData, |
michael@0 | 10812 | sizeof(dtlsData)); |
michael@0 | 10813 | if (rv != SECSuccess) return rv; /* err code already set. */ |
michael@0 | 10814 | } |
michael@0 | 10815 | |
michael@0 | 10816 | /* The message body */ |
michael@0 | 10817 | rv = ssl3_UpdateHandshakeHashes(ss, b, length); |
michael@0 | 10818 | if (rv != SECSuccess) return rv; /* err code already set. */ |
michael@0 | 10819 | } |
michael@0 | 10820 | |
michael@0 | 10821 | PORT_SetError(0); /* each message starts with no error. */ |
michael@0 | 10822 | |
michael@0 | 10823 | if (ss->ssl3.hs.ws == wait_certificate_status && |
michael@0 | 10824 | ss->ssl3.hs.msg_type != certificate_status) { |
michael@0 | 10825 | /* If we negotiated the certificate_status extension then we deferred |
michael@0 | 10826 | * certificate validation until we get the CertificateStatus messsage. |
michael@0 | 10827 | * But the CertificateStatus message is optional. If the server did |
michael@0 | 10828 | * not send it then we need to validate the certificate now. If the |
michael@0 | 10829 | * server does send the CertificateStatus message then we will |
michael@0 | 10830 | * authenticate the certificate in ssl3_HandleCertificateStatus. |
michael@0 | 10831 | */ |
michael@0 | 10832 | rv = ssl3_AuthCertificate(ss); /* sets ss->ssl3.hs.ws */ |
michael@0 | 10833 | PORT_Assert(rv != SECWouldBlock); |
michael@0 | 10834 | if (rv != SECSuccess) { |
michael@0 | 10835 | return rv; |
michael@0 | 10836 | } |
michael@0 | 10837 | } |
michael@0 | 10838 | |
michael@0 | 10839 | switch (ss->ssl3.hs.msg_type) { |
michael@0 | 10840 | case hello_request: |
michael@0 | 10841 | if (length != 0) { |
michael@0 | 10842 | (void)ssl3_DecodeError(ss); |
michael@0 | 10843 | PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST); |
michael@0 | 10844 | return SECFailure; |
michael@0 | 10845 | } |
michael@0 | 10846 | if (ss->sec.isServer) { |
michael@0 | 10847 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10848 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST); |
michael@0 | 10849 | return SECFailure; |
michael@0 | 10850 | } |
michael@0 | 10851 | rv = ssl3_HandleHelloRequest(ss); |
michael@0 | 10852 | break; |
michael@0 | 10853 | case client_hello: |
michael@0 | 10854 | if (!ss->sec.isServer) { |
michael@0 | 10855 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10856 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO); |
michael@0 | 10857 | return SECFailure; |
michael@0 | 10858 | } |
michael@0 | 10859 | rv = ssl3_HandleClientHello(ss, b, length); |
michael@0 | 10860 | break; |
michael@0 | 10861 | case server_hello: |
michael@0 | 10862 | if (ss->sec.isServer) { |
michael@0 | 10863 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10864 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO); |
michael@0 | 10865 | return SECFailure; |
michael@0 | 10866 | } |
michael@0 | 10867 | rv = ssl3_HandleServerHello(ss, b, length); |
michael@0 | 10868 | break; |
michael@0 | 10869 | case hello_verify_request: |
michael@0 | 10870 | if (!IS_DTLS(ss) || ss->sec.isServer) { |
michael@0 | 10871 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10872 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST); |
michael@0 | 10873 | return SECFailure; |
michael@0 | 10874 | } |
michael@0 | 10875 | rv = dtls_HandleHelloVerifyRequest(ss, b, length); |
michael@0 | 10876 | break; |
michael@0 | 10877 | case certificate: |
michael@0 | 10878 | rv = ssl3_HandleCertificate(ss, b, length); |
michael@0 | 10879 | break; |
michael@0 | 10880 | case certificate_status: |
michael@0 | 10881 | rv = ssl3_HandleCertificateStatus(ss, b, length); |
michael@0 | 10882 | break; |
michael@0 | 10883 | case server_key_exchange: |
michael@0 | 10884 | if (ss->sec.isServer) { |
michael@0 | 10885 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10886 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH); |
michael@0 | 10887 | return SECFailure; |
michael@0 | 10888 | } |
michael@0 | 10889 | rv = ssl3_HandleServerKeyExchange(ss, b, length); |
michael@0 | 10890 | break; |
michael@0 | 10891 | case certificate_request: |
michael@0 | 10892 | if (ss->sec.isServer) { |
michael@0 | 10893 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10894 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST); |
michael@0 | 10895 | return SECFailure; |
michael@0 | 10896 | } |
michael@0 | 10897 | rv = ssl3_HandleCertificateRequest(ss, b, length); |
michael@0 | 10898 | break; |
michael@0 | 10899 | case server_hello_done: |
michael@0 | 10900 | if (length != 0) { |
michael@0 | 10901 | (void)ssl3_DecodeError(ss); |
michael@0 | 10902 | PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_DONE); |
michael@0 | 10903 | return SECFailure; |
michael@0 | 10904 | } |
michael@0 | 10905 | if (ss->sec.isServer) { |
michael@0 | 10906 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10907 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); |
michael@0 | 10908 | return SECFailure; |
michael@0 | 10909 | } |
michael@0 | 10910 | rv = ssl3_HandleServerHelloDone(ss); |
michael@0 | 10911 | break; |
michael@0 | 10912 | case certificate_verify: |
michael@0 | 10913 | if (!ss->sec.isServer) { |
michael@0 | 10914 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10915 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY); |
michael@0 | 10916 | return SECFailure; |
michael@0 | 10917 | } |
michael@0 | 10918 | rv = ssl3_HandleCertificateVerify(ss, b, length, &hashes); |
michael@0 | 10919 | break; |
michael@0 | 10920 | case client_key_exchange: |
michael@0 | 10921 | if (!ss->sec.isServer) { |
michael@0 | 10922 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10923 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH); |
michael@0 | 10924 | return SECFailure; |
michael@0 | 10925 | } |
michael@0 | 10926 | rv = ssl3_HandleClientKeyExchange(ss, b, length); |
michael@0 | 10927 | break; |
michael@0 | 10928 | case new_session_ticket: |
michael@0 | 10929 | if (ss->sec.isServer) { |
michael@0 | 10930 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10931 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET); |
michael@0 | 10932 | return SECFailure; |
michael@0 | 10933 | } |
michael@0 | 10934 | rv = ssl3_HandleNewSessionTicket(ss, b, length); |
michael@0 | 10935 | break; |
michael@0 | 10936 | case finished: |
michael@0 | 10937 | rv = ssl3_HandleFinished(ss, b, length, &hashes); |
michael@0 | 10938 | break; |
michael@0 | 10939 | default: |
michael@0 | 10940 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 10941 | PORT_SetError(SSL_ERROR_RX_UNKNOWN_HANDSHAKE); |
michael@0 | 10942 | rv = SECFailure; |
michael@0 | 10943 | } |
michael@0 | 10944 | |
michael@0 | 10945 | if (IS_DTLS(ss) && (rv != SECFailure)) { |
michael@0 | 10946 | /* Increment the expected sequence number */ |
michael@0 | 10947 | ss->ssl3.hs.recvMessageSeq++; |
michael@0 | 10948 | } |
michael@0 | 10949 | |
michael@0 | 10950 | return rv; |
michael@0 | 10951 | } |
michael@0 | 10952 | |
michael@0 | 10953 | /* Called only from ssl3_HandleRecord, for each (deciphered) ssl3 record. |
michael@0 | 10954 | * origBuf is the decrypted ssl record content. |
michael@0 | 10955 | * Caller must hold the handshake and RecvBuf locks. |
michael@0 | 10956 | */ |
michael@0 | 10957 | static SECStatus |
michael@0 | 10958 | ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) |
michael@0 | 10959 | { |
michael@0 | 10960 | /* |
michael@0 | 10961 | * There may be a partial handshake message already in the handshake |
michael@0 | 10962 | * state. The incoming buffer may contain another portion, or a |
michael@0 | 10963 | * complete message or several messages followed by another portion. |
michael@0 | 10964 | * |
michael@0 | 10965 | * Each message is made contiguous before being passed to the actual |
michael@0 | 10966 | * message parser. |
michael@0 | 10967 | */ |
michael@0 | 10968 | sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */ |
michael@0 | 10969 | SECStatus rv; |
michael@0 | 10970 | |
michael@0 | 10971 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 10972 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 10973 | |
michael@0 | 10974 | if (buf->buf == NULL) { |
michael@0 | 10975 | *buf = *origBuf; |
michael@0 | 10976 | } |
michael@0 | 10977 | while (buf->len > 0) { |
michael@0 | 10978 | if (ss->ssl3.hs.header_bytes < 4) { |
michael@0 | 10979 | PRUint8 t; |
michael@0 | 10980 | t = *(buf->buf++); |
michael@0 | 10981 | buf->len--; |
michael@0 | 10982 | if (ss->ssl3.hs.header_bytes++ == 0) |
michael@0 | 10983 | ss->ssl3.hs.msg_type = (SSL3HandshakeType)t; |
michael@0 | 10984 | else |
michael@0 | 10985 | ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t; |
michael@0 | 10986 | if (ss->ssl3.hs.header_bytes < 4) |
michael@0 | 10987 | continue; |
michael@0 | 10988 | |
michael@0 | 10989 | #define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */ |
michael@0 | 10990 | if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) { |
michael@0 | 10991 | (void)ssl3_DecodeError(ss); |
michael@0 | 10992 | PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); |
michael@0 | 10993 | return SECFailure; |
michael@0 | 10994 | } |
michael@0 | 10995 | #undef MAX_HANDSHAKE_MSG_LEN |
michael@0 | 10996 | |
michael@0 | 10997 | /* If msg_len is zero, be sure we fall through, |
michael@0 | 10998 | ** even if buf->len is zero. |
michael@0 | 10999 | */ |
michael@0 | 11000 | if (ss->ssl3.hs.msg_len > 0) |
michael@0 | 11001 | continue; |
michael@0 | 11002 | } |
michael@0 | 11003 | |
michael@0 | 11004 | /* |
michael@0 | 11005 | * Header has been gathered and there is at least one byte of new |
michael@0 | 11006 | * data available for this message. If it can be done right out |
michael@0 | 11007 | * of the original buffer, then use it from there. |
michael@0 | 11008 | */ |
michael@0 | 11009 | if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) { |
michael@0 | 11010 | /* handle it from input buffer */ |
michael@0 | 11011 | rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len); |
michael@0 | 11012 | if (rv == SECFailure) { |
michael@0 | 11013 | /* This test wants to fall through on either |
michael@0 | 11014 | * SECSuccess or SECWouldBlock. |
michael@0 | 11015 | * ssl3_HandleHandshakeMessage MUST set the error code. |
michael@0 | 11016 | */ |
michael@0 | 11017 | return rv; |
michael@0 | 11018 | } |
michael@0 | 11019 | buf->buf += ss->ssl3.hs.msg_len; |
michael@0 | 11020 | buf->len -= ss->ssl3.hs.msg_len; |
michael@0 | 11021 | ss->ssl3.hs.msg_len = 0; |
michael@0 | 11022 | ss->ssl3.hs.header_bytes = 0; |
michael@0 | 11023 | if (rv != SECSuccess) { /* return if SECWouldBlock. */ |
michael@0 | 11024 | return rv; |
michael@0 | 11025 | } |
michael@0 | 11026 | } else { |
michael@0 | 11027 | /* must be copied to msg_body and dealt with from there */ |
michael@0 | 11028 | unsigned int bytes; |
michael@0 | 11029 | |
michael@0 | 11030 | PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len); |
michael@0 | 11031 | bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len); |
michael@0 | 11032 | |
michael@0 | 11033 | /* Grow the buffer if needed */ |
michael@0 | 11034 | rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len); |
michael@0 | 11035 | if (rv != SECSuccess) { |
michael@0 | 11036 | /* sslBuffer_Grow has set a memory error code. */ |
michael@0 | 11037 | return SECFailure; |
michael@0 | 11038 | } |
michael@0 | 11039 | |
michael@0 | 11040 | PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len, |
michael@0 | 11041 | buf->buf, bytes); |
michael@0 | 11042 | ss->ssl3.hs.msg_body.len += bytes; |
michael@0 | 11043 | buf->buf += bytes; |
michael@0 | 11044 | buf->len -= bytes; |
michael@0 | 11045 | |
michael@0 | 11046 | PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len); |
michael@0 | 11047 | |
michael@0 | 11048 | /* if we have a whole message, do it */ |
michael@0 | 11049 | if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) { |
michael@0 | 11050 | rv = ssl3_HandleHandshakeMessage( |
michael@0 | 11051 | ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len); |
michael@0 | 11052 | if (rv == SECFailure) { |
michael@0 | 11053 | /* This test wants to fall through on either |
michael@0 | 11054 | * SECSuccess or SECWouldBlock. |
michael@0 | 11055 | * ssl3_HandleHandshakeMessage MUST set error code. |
michael@0 | 11056 | */ |
michael@0 | 11057 | return rv; |
michael@0 | 11058 | } |
michael@0 | 11059 | ss->ssl3.hs.msg_body.len = 0; |
michael@0 | 11060 | ss->ssl3.hs.msg_len = 0; |
michael@0 | 11061 | ss->ssl3.hs.header_bytes = 0; |
michael@0 | 11062 | if (rv != SECSuccess) { /* return if SECWouldBlock. */ |
michael@0 | 11063 | return rv; |
michael@0 | 11064 | } |
michael@0 | 11065 | } else { |
michael@0 | 11066 | PORT_Assert(buf->len == 0); |
michael@0 | 11067 | break; |
michael@0 | 11068 | } |
michael@0 | 11069 | } |
michael@0 | 11070 | } /* end loop */ |
michael@0 | 11071 | |
michael@0 | 11072 | origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */ |
michael@0 | 11073 | buf->buf = NULL; /* not a leak. */ |
michael@0 | 11074 | return SECSuccess; |
michael@0 | 11075 | } |
michael@0 | 11076 | |
michael@0 | 11077 | /* These macros return the given value with the MSB copied to all the other |
michael@0 | 11078 | * bits. They use the fact that arithmetic shift shifts-in the sign bit. |
michael@0 | 11079 | * However, this is not ensured by the C standard so you may need to replace |
michael@0 | 11080 | * them with something else for odd compilers. */ |
michael@0 | 11081 | #define DUPLICATE_MSB_TO_ALL(x) ( (unsigned)( (int)(x) >> (sizeof(int)*8-1) ) ) |
michael@0 | 11082 | #define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) |
michael@0 | 11083 | |
michael@0 | 11084 | /* SECStatusToMask returns, in constant time, a mask value of all ones if |
michael@0 | 11085 | * rv == SECSuccess. Otherwise it returns zero. */ |
michael@0 | 11086 | static unsigned int |
michael@0 | 11087 | SECStatusToMask(SECStatus rv) |
michael@0 | 11088 | { |
michael@0 | 11089 | unsigned int good; |
michael@0 | 11090 | /* rv ^ SECSuccess is zero iff rv == SECSuccess. Subtracting one results |
michael@0 | 11091 | * in the MSB being set to one iff it was zero before. */ |
michael@0 | 11092 | good = rv ^ SECSuccess; |
michael@0 | 11093 | good--; |
michael@0 | 11094 | return DUPLICATE_MSB_TO_ALL(good); |
michael@0 | 11095 | } |
michael@0 | 11096 | |
michael@0 | 11097 | /* ssl_ConstantTimeGE returns 0xff if a>=b and 0x00 otherwise. */ |
michael@0 | 11098 | static unsigned char |
michael@0 | 11099 | ssl_ConstantTimeGE(unsigned int a, unsigned int b) |
michael@0 | 11100 | { |
michael@0 | 11101 | a -= b; |
michael@0 | 11102 | return DUPLICATE_MSB_TO_ALL(~a); |
michael@0 | 11103 | } |
michael@0 | 11104 | |
michael@0 | 11105 | /* ssl_ConstantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */ |
michael@0 | 11106 | static unsigned char |
michael@0 | 11107 | ssl_ConstantTimeEQ8(unsigned char a, unsigned char b) |
michael@0 | 11108 | { |
michael@0 | 11109 | unsigned int c = a ^ b; |
michael@0 | 11110 | c--; |
michael@0 | 11111 | return DUPLICATE_MSB_TO_ALL_8(c); |
michael@0 | 11112 | } |
michael@0 | 11113 | |
michael@0 | 11114 | static SECStatus |
michael@0 | 11115 | ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext, |
michael@0 | 11116 | unsigned int blockSize, |
michael@0 | 11117 | unsigned int macSize) |
michael@0 | 11118 | { |
michael@0 | 11119 | unsigned int paddingLength, good, t; |
michael@0 | 11120 | const unsigned int overhead = 1 /* padding length byte */ + macSize; |
michael@0 | 11121 | |
michael@0 | 11122 | /* These lengths are all public so we can test them in non-constant |
michael@0 | 11123 | * time. */ |
michael@0 | 11124 | if (overhead > plaintext->len) { |
michael@0 | 11125 | return SECFailure; |
michael@0 | 11126 | } |
michael@0 | 11127 | |
michael@0 | 11128 | paddingLength = plaintext->buf[plaintext->len-1]; |
michael@0 | 11129 | /* SSLv3 padding bytes are random and cannot be checked. */ |
michael@0 | 11130 | t = plaintext->len; |
michael@0 | 11131 | t -= paddingLength+overhead; |
michael@0 | 11132 | /* If len >= paddingLength+overhead then the MSB of t is zero. */ |
michael@0 | 11133 | good = DUPLICATE_MSB_TO_ALL(~t); |
michael@0 | 11134 | /* SSLv3 requires that the padding is minimal. */ |
michael@0 | 11135 | t = blockSize - (paddingLength+1); |
michael@0 | 11136 | good &= DUPLICATE_MSB_TO_ALL(~t); |
michael@0 | 11137 | plaintext->len -= good & (paddingLength+1); |
michael@0 | 11138 | return (good & SECSuccess) | (~good & SECFailure); |
michael@0 | 11139 | } |
michael@0 | 11140 | |
michael@0 | 11141 | static SECStatus |
michael@0 | 11142 | ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize) |
michael@0 | 11143 | { |
michael@0 | 11144 | unsigned int paddingLength, good, t, toCheck, i; |
michael@0 | 11145 | const unsigned int overhead = 1 /* padding length byte */ + macSize; |
michael@0 | 11146 | |
michael@0 | 11147 | /* These lengths are all public so we can test them in non-constant |
michael@0 | 11148 | * time. */ |
michael@0 | 11149 | if (overhead > plaintext->len) { |
michael@0 | 11150 | return SECFailure; |
michael@0 | 11151 | } |
michael@0 | 11152 | |
michael@0 | 11153 | paddingLength = plaintext->buf[plaintext->len-1]; |
michael@0 | 11154 | t = plaintext->len; |
michael@0 | 11155 | t -= paddingLength+overhead; |
michael@0 | 11156 | /* If len >= paddingLength+overhead then the MSB of t is zero. */ |
michael@0 | 11157 | good = DUPLICATE_MSB_TO_ALL(~t); |
michael@0 | 11158 | |
michael@0 | 11159 | /* The padding consists of a length byte at the end of the record and then |
michael@0 | 11160 | * that many bytes of padding, all with the same value as the length byte. |
michael@0 | 11161 | * Thus, with the length byte included, there are paddingLength+1 bytes of |
michael@0 | 11162 | * padding. |
michael@0 | 11163 | * |
michael@0 | 11164 | * We can't check just |paddingLength+1| bytes because that leaks |
michael@0 | 11165 | * decrypted information. Therefore we always have to check the maximum |
michael@0 | 11166 | * amount of padding possible. (Again, the length of the record is |
michael@0 | 11167 | * public information so we can use it.) */ |
michael@0 | 11168 | toCheck = 255; /* maximum amount of padding. */ |
michael@0 | 11169 | if (toCheck > plaintext->len-1) { |
michael@0 | 11170 | toCheck = plaintext->len-1; |
michael@0 | 11171 | } |
michael@0 | 11172 | |
michael@0 | 11173 | for (i = 0; i < toCheck; i++) { |
michael@0 | 11174 | unsigned int t = paddingLength - i; |
michael@0 | 11175 | /* If i <= paddingLength then the MSB of t is zero and mask is |
michael@0 | 11176 | * 0xff. Otherwise, mask is 0. */ |
michael@0 | 11177 | unsigned char mask = DUPLICATE_MSB_TO_ALL(~t); |
michael@0 | 11178 | unsigned char b = plaintext->buf[plaintext->len-1-i]; |
michael@0 | 11179 | /* The final |paddingLength+1| bytes should all have the value |
michael@0 | 11180 | * |paddingLength|. Therefore the XOR should be zero. */ |
michael@0 | 11181 | good &= ~(mask&(paddingLength ^ b)); |
michael@0 | 11182 | } |
michael@0 | 11183 | |
michael@0 | 11184 | /* If any of the final |paddingLength+1| bytes had the wrong value, |
michael@0 | 11185 | * one or more of the lower eight bits of |good| will be cleared. We |
michael@0 | 11186 | * AND the bottom 8 bits together and duplicate the result to all the |
michael@0 | 11187 | * bits. */ |
michael@0 | 11188 | good &= good >> 4; |
michael@0 | 11189 | good &= good >> 2; |
michael@0 | 11190 | good &= good >> 1; |
michael@0 | 11191 | good <<= sizeof(good)*8-1; |
michael@0 | 11192 | good = DUPLICATE_MSB_TO_ALL(good); |
michael@0 | 11193 | |
michael@0 | 11194 | plaintext->len -= good & (paddingLength+1); |
michael@0 | 11195 | return (good & SECSuccess) | (~good & SECFailure); |
michael@0 | 11196 | } |
michael@0 | 11197 | |
michael@0 | 11198 | /* On entry: |
michael@0 | 11199 | * originalLength >= macSize |
michael@0 | 11200 | * macSize <= MAX_MAC_LENGTH |
michael@0 | 11201 | * plaintext->len >= macSize |
michael@0 | 11202 | */ |
michael@0 | 11203 | static void |
michael@0 | 11204 | ssl_CBCExtractMAC(sslBuffer *plaintext, |
michael@0 | 11205 | unsigned int originalLength, |
michael@0 | 11206 | SSL3Opaque* out, |
michael@0 | 11207 | unsigned int macSize) |
michael@0 | 11208 | { |
michael@0 | 11209 | unsigned char rotatedMac[MAX_MAC_LENGTH]; |
michael@0 | 11210 | /* macEnd is the index of |plaintext->buf| just after the end of the |
michael@0 | 11211 | * MAC. */ |
michael@0 | 11212 | unsigned macEnd = plaintext->len; |
michael@0 | 11213 | unsigned macStart = macEnd - macSize; |
michael@0 | 11214 | /* scanStart contains the number of bytes that we can ignore because |
michael@0 | 11215 | * the MAC's position can only vary by 255 bytes. */ |
michael@0 | 11216 | unsigned scanStart = 0; |
michael@0 | 11217 | unsigned i, j, divSpoiler; |
michael@0 | 11218 | unsigned char rotateOffset; |
michael@0 | 11219 | |
michael@0 | 11220 | if (originalLength > macSize + 255 + 1) |
michael@0 | 11221 | scanStart = originalLength - (macSize + 255 + 1); |
michael@0 | 11222 | |
michael@0 | 11223 | /* divSpoiler contains a multiple of macSize that is used to cause the |
michael@0 | 11224 | * modulo operation to be constant time. Without this, the time varies |
michael@0 | 11225 | * based on the amount of padding when running on Intel chips at least. |
michael@0 | 11226 | * |
michael@0 | 11227 | * The aim of right-shifting macSize is so that the compiler doesn't |
michael@0 | 11228 | * figure out that it can remove divSpoiler as that would require it |
michael@0 | 11229 | * to prove that macSize is always even, which I hope is beyond it. */ |
michael@0 | 11230 | divSpoiler = macSize >> 1; |
michael@0 | 11231 | divSpoiler <<= (sizeof(divSpoiler)-1)*8; |
michael@0 | 11232 | rotateOffset = (divSpoiler + macStart - scanStart) % macSize; |
michael@0 | 11233 | |
michael@0 | 11234 | memset(rotatedMac, 0, macSize); |
michael@0 | 11235 | for (i = scanStart; i < originalLength;) { |
michael@0 | 11236 | for (j = 0; j < macSize && i < originalLength; i++, j++) { |
michael@0 | 11237 | unsigned char macStarted = ssl_ConstantTimeGE(i, macStart); |
michael@0 | 11238 | unsigned char macEnded = ssl_ConstantTimeGE(i, macEnd); |
michael@0 | 11239 | unsigned char b = 0; |
michael@0 | 11240 | b = plaintext->buf[i]; |
michael@0 | 11241 | rotatedMac[j] |= b & macStarted & ~macEnded; |
michael@0 | 11242 | } |
michael@0 | 11243 | } |
michael@0 | 11244 | |
michael@0 | 11245 | /* Now rotate the MAC. If we knew that the MAC fit into a CPU cache line |
michael@0 | 11246 | * we could line-align |rotatedMac| and rotate in place. */ |
michael@0 | 11247 | memset(out, 0, macSize); |
michael@0 | 11248 | for (i = 0; i < macSize; i++) { |
michael@0 | 11249 | unsigned char offset = |
michael@0 | 11250 | (divSpoiler + macSize - rotateOffset + i) % macSize; |
michael@0 | 11251 | for (j = 0; j < macSize; j++) { |
michael@0 | 11252 | out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, offset); |
michael@0 | 11253 | } |
michael@0 | 11254 | } |
michael@0 | 11255 | } |
michael@0 | 11256 | |
michael@0 | 11257 | /* if cText is non-null, then decipher, check MAC, and decompress the |
michael@0 | 11258 | * SSL record from cText->buf (typically gs->inbuf) |
michael@0 | 11259 | * into databuf (typically gs->buf), and any previous contents of databuf |
michael@0 | 11260 | * is lost. Then handle databuf according to its SSL record type, |
michael@0 | 11261 | * unless it's an application record. |
michael@0 | 11262 | * |
michael@0 | 11263 | * If cText is NULL, then the ciphertext has previously been deciphered and |
michael@0 | 11264 | * checked, and is already sitting in databuf. It is processed as an SSL |
michael@0 | 11265 | * Handshake message. |
michael@0 | 11266 | * |
michael@0 | 11267 | * DOES NOT process the decrypted/decompressed application data. |
michael@0 | 11268 | * On return, databuf contains the decrypted/decompressed record. |
michael@0 | 11269 | * |
michael@0 | 11270 | * Called from ssl3_GatherCompleteHandshake |
michael@0 | 11271 | * ssl3_RestartHandshakeAfterCertReq |
michael@0 | 11272 | * |
michael@0 | 11273 | * Caller must hold the RecvBufLock. |
michael@0 | 11274 | * |
michael@0 | 11275 | * This function aquires and releases the SSL3Handshake Lock, holding the |
michael@0 | 11276 | * lock around any calls to functions that handle records other than |
michael@0 | 11277 | * Application Data records. |
michael@0 | 11278 | */ |
michael@0 | 11279 | SECStatus |
michael@0 | 11280 | ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) |
michael@0 | 11281 | { |
michael@0 | 11282 | const ssl3BulkCipherDef *cipher_def; |
michael@0 | 11283 | ssl3CipherSpec * crSpec; |
michael@0 | 11284 | SECStatus rv; |
michael@0 | 11285 | unsigned int hashBytes = MAX_MAC_LENGTH + 1; |
michael@0 | 11286 | PRBool isTLS; |
michael@0 | 11287 | SSL3ContentType rType; |
michael@0 | 11288 | SSL3Opaque hash[MAX_MAC_LENGTH]; |
michael@0 | 11289 | SSL3Opaque givenHashBuf[MAX_MAC_LENGTH]; |
michael@0 | 11290 | SSL3Opaque *givenHash; |
michael@0 | 11291 | sslBuffer *plaintext; |
michael@0 | 11292 | sslBuffer temp_buf; |
michael@0 | 11293 | PRUint64 dtls_seq_num; |
michael@0 | 11294 | unsigned int ivLen = 0; |
michael@0 | 11295 | unsigned int originalLen = 0; |
michael@0 | 11296 | unsigned int good; |
michael@0 | 11297 | unsigned int minLength; |
michael@0 | 11298 | unsigned char header[13]; |
michael@0 | 11299 | unsigned int headerLen; |
michael@0 | 11300 | |
michael@0 | 11301 | PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
michael@0 | 11302 | |
michael@0 | 11303 | if (!ss->ssl3.initialized) { |
michael@0 | 11304 | ssl_GetSSL3HandshakeLock(ss); |
michael@0 | 11305 | rv = ssl3_InitState(ss); |
michael@0 | 11306 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 11307 | if (rv != SECSuccess) { |
michael@0 | 11308 | return rv; /* ssl3_InitState has set the error code. */ |
michael@0 | 11309 | } |
michael@0 | 11310 | } |
michael@0 | 11311 | |
michael@0 | 11312 | /* check for Token Presence */ |
michael@0 | 11313 | if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) { |
michael@0 | 11314 | PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); |
michael@0 | 11315 | return SECFailure; |
michael@0 | 11316 | } |
michael@0 | 11317 | |
michael@0 | 11318 | /* cText is NULL when we're called from ssl3_RestartHandshakeAfterXXX(). |
michael@0 | 11319 | * This implies that databuf holds a previously deciphered SSL Handshake |
michael@0 | 11320 | * message. |
michael@0 | 11321 | */ |
michael@0 | 11322 | if (cText == NULL) { |
michael@0 | 11323 | SSL_DBG(("%d: SSL3[%d]: HandleRecord, resuming handshake", |
michael@0 | 11324 | SSL_GETPID(), ss->fd)); |
michael@0 | 11325 | rType = content_handshake; |
michael@0 | 11326 | goto process_it; |
michael@0 | 11327 | } |
michael@0 | 11328 | |
michael@0 | 11329 | ssl_GetSpecReadLock(ss); /******************************************/ |
michael@0 | 11330 | |
michael@0 | 11331 | crSpec = ss->ssl3.crSpec; |
michael@0 | 11332 | cipher_def = crSpec->cipher_def; |
michael@0 | 11333 | |
michael@0 | 11334 | /* |
michael@0 | 11335 | * DTLS relevance checks: |
michael@0 | 11336 | * Note that this code currently ignores all out-of-epoch packets, |
michael@0 | 11337 | * which means we lose some in the case of rehandshake + |
michael@0 | 11338 | * loss/reordering. Since DTLS is explicitly unreliable, this |
michael@0 | 11339 | * seems like a good tradeoff for implementation effort and is |
michael@0 | 11340 | * consistent with the guidance of RFC 6347 Sections 4.1 and 4.2.4.1 |
michael@0 | 11341 | */ |
michael@0 | 11342 | if (IS_DTLS(ss)) { |
michael@0 | 11343 | DTLSEpoch epoch = (cText->seq_num.high >> 16) & 0xffff; |
michael@0 | 11344 | |
michael@0 | 11345 | if (crSpec->epoch != epoch) { |
michael@0 | 11346 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 11347 | SSL_DBG(("%d: SSL3[%d]: HandleRecord, received packet " |
michael@0 | 11348 | "from irrelevant epoch %d", SSL_GETPID(), ss->fd, epoch)); |
michael@0 | 11349 | /* Silently drop the packet */ |
michael@0 | 11350 | databuf->len = 0; /* Needed to ensure data not left around */ |
michael@0 | 11351 | return SECSuccess; |
michael@0 | 11352 | } |
michael@0 | 11353 | |
michael@0 | 11354 | dtls_seq_num = (((PRUint64)(cText->seq_num.high & 0xffff)) << 32) | |
michael@0 | 11355 | ((PRUint64)cText->seq_num.low); |
michael@0 | 11356 | |
michael@0 | 11357 | if (dtls_RecordGetRecvd(&crSpec->recvdRecords, dtls_seq_num) != 0) { |
michael@0 | 11358 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 11359 | SSL_DBG(("%d: SSL3[%d]: HandleRecord, rejecting " |
michael@0 | 11360 | "potentially replayed packet", SSL_GETPID(), ss->fd)); |
michael@0 | 11361 | /* Silently drop the packet */ |
michael@0 | 11362 | databuf->len = 0; /* Needed to ensure data not left around */ |
michael@0 | 11363 | return SECSuccess; |
michael@0 | 11364 | } |
michael@0 | 11365 | } |
michael@0 | 11366 | |
michael@0 | 11367 | good = ~0U; |
michael@0 | 11368 | minLength = crSpec->mac_size; |
michael@0 | 11369 | if (cipher_def->type == type_block) { |
michael@0 | 11370 | /* CBC records have a padding length byte at the end. */ |
michael@0 | 11371 | minLength++; |
michael@0 | 11372 | if (crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
michael@0 | 11373 | /* With >= TLS 1.1, CBC records have an explicit IV. */ |
michael@0 | 11374 | minLength += cipher_def->iv_size; |
michael@0 | 11375 | } |
michael@0 | 11376 | } else if (cipher_def->type == type_aead) { |
michael@0 | 11377 | minLength = cipher_def->explicit_nonce_size + cipher_def->tag_size; |
michael@0 | 11378 | } |
michael@0 | 11379 | |
michael@0 | 11380 | /* We can perform this test in variable time because the record's total |
michael@0 | 11381 | * length and the ciphersuite are both public knowledge. */ |
michael@0 | 11382 | if (cText->buf->len < minLength) { |
michael@0 | 11383 | goto decrypt_loser; |
michael@0 | 11384 | } |
michael@0 | 11385 | |
michael@0 | 11386 | if (cipher_def->type == type_block && |
michael@0 | 11387 | crSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
michael@0 | 11388 | /* Consume the per-record explicit IV. RFC 4346 Section 6.2.3.2 states |
michael@0 | 11389 | * "The receiver decrypts the entire GenericBlockCipher structure and |
michael@0 | 11390 | * then discards the first cipher block corresponding to the IV |
michael@0 | 11391 | * component." Instead, we decrypt the first cipher block and then |
michael@0 | 11392 | * discard it before decrypting the rest. |
michael@0 | 11393 | */ |
michael@0 | 11394 | SSL3Opaque iv[MAX_IV_LENGTH]; |
michael@0 | 11395 | int decoded; |
michael@0 | 11396 | |
michael@0 | 11397 | ivLen = cipher_def->iv_size; |
michael@0 | 11398 | if (ivLen < 8 || ivLen > sizeof(iv)) { |
michael@0 | 11399 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 11400 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 11401 | return SECFailure; |
michael@0 | 11402 | } |
michael@0 | 11403 | |
michael@0 | 11404 | PRINT_BUF(80, (ss, "IV (ciphertext):", cText->buf->buf, ivLen)); |
michael@0 | 11405 | |
michael@0 | 11406 | /* The decryption result is garbage, but since we just throw away |
michael@0 | 11407 | * the block it doesn't matter. The decryption of the next block |
michael@0 | 11408 | * depends only on the ciphertext of the IV block. |
michael@0 | 11409 | */ |
michael@0 | 11410 | rv = crSpec->decode(crSpec->decodeContext, iv, &decoded, |
michael@0 | 11411 | sizeof(iv), cText->buf->buf, ivLen); |
michael@0 | 11412 | |
michael@0 | 11413 | good &= SECStatusToMask(rv); |
michael@0 | 11414 | } |
michael@0 | 11415 | |
michael@0 | 11416 | /* If we will be decompressing the buffer we need to decrypt somewhere |
michael@0 | 11417 | * other than into databuf */ |
michael@0 | 11418 | if (crSpec->decompressor) { |
michael@0 | 11419 | temp_buf.buf = NULL; |
michael@0 | 11420 | temp_buf.space = 0; |
michael@0 | 11421 | plaintext = &temp_buf; |
michael@0 | 11422 | } else { |
michael@0 | 11423 | plaintext = databuf; |
michael@0 | 11424 | } |
michael@0 | 11425 | |
michael@0 | 11426 | plaintext->len = 0; /* filled in by decode call below. */ |
michael@0 | 11427 | if (plaintext->space < MAX_FRAGMENT_LENGTH) { |
michael@0 | 11428 | rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048); |
michael@0 | 11429 | if (rv != SECSuccess) { |
michael@0 | 11430 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 11431 | SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes", |
michael@0 | 11432 | SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048)); |
michael@0 | 11433 | /* sslBuffer_Grow has set a memory error code. */ |
michael@0 | 11434 | /* Perhaps we should send an alert. (but we have no memory!) */ |
michael@0 | 11435 | return SECFailure; |
michael@0 | 11436 | } |
michael@0 | 11437 | } |
michael@0 | 11438 | |
michael@0 | 11439 | PRINT_BUF(80, (ss, "ciphertext:", cText->buf->buf + ivLen, |
michael@0 | 11440 | cText->buf->len - ivLen)); |
michael@0 | 11441 | |
michael@0 | 11442 | isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0); |
michael@0 | 11443 | |
michael@0 | 11444 | if (isTLS && cText->buf->len - ivLen > (MAX_FRAGMENT_LENGTH + 2048)) { |
michael@0 | 11445 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 11446 | SSL3_SendAlert(ss, alert_fatal, record_overflow); |
michael@0 | 11447 | PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); |
michael@0 | 11448 | return SECFailure; |
michael@0 | 11449 | } |
michael@0 | 11450 | |
michael@0 | 11451 | rType = cText->type; |
michael@0 | 11452 | if (cipher_def->type == type_aead) { |
michael@0 | 11453 | /* XXX For many AEAD ciphers, the plaintext is shorter than the |
michael@0 | 11454 | * ciphertext by a fixed byte count, but it is not true in general. |
michael@0 | 11455 | * Each AEAD cipher should provide a function that returns the |
michael@0 | 11456 | * plaintext length for a given ciphertext. */ |
michael@0 | 11457 | unsigned int decryptedLen = |
michael@0 | 11458 | cText->buf->len - cipher_def->explicit_nonce_size - |
michael@0 | 11459 | cipher_def->tag_size; |
michael@0 | 11460 | headerLen = ssl3_BuildRecordPseudoHeader( |
michael@0 | 11461 | header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
michael@0 | 11462 | rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen); |
michael@0 | 11463 | PORT_Assert(headerLen <= sizeof(header)); |
michael@0 | 11464 | rv = crSpec->aead( |
michael@0 | 11465 | ss->sec.isServer ? &crSpec->client : &crSpec->server, |
michael@0 | 11466 | PR_TRUE, /* do decrypt */ |
michael@0 | 11467 | plaintext->buf, /* out */ |
michael@0 | 11468 | (int*) &plaintext->len, /* outlen */ |
michael@0 | 11469 | plaintext->space, /* maxout */ |
michael@0 | 11470 | cText->buf->buf, /* in */ |
michael@0 | 11471 | cText->buf->len, /* inlen */ |
michael@0 | 11472 | header, headerLen); |
michael@0 | 11473 | if (rv != SECSuccess) { |
michael@0 | 11474 | good = 0; |
michael@0 | 11475 | } |
michael@0 | 11476 | } else { |
michael@0 | 11477 | if (cipher_def->type == type_block && |
michael@0 | 11478 | ((cText->buf->len - ivLen) % cipher_def->block_size) != 0) { |
michael@0 | 11479 | goto decrypt_loser; |
michael@0 | 11480 | } |
michael@0 | 11481 | |
michael@0 | 11482 | /* decrypt from cText buf to plaintext. */ |
michael@0 | 11483 | rv = crSpec->decode( |
michael@0 | 11484 | crSpec->decodeContext, plaintext->buf, (int *)&plaintext->len, |
michael@0 | 11485 | plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); |
michael@0 | 11486 | if (rv != SECSuccess) { |
michael@0 | 11487 | goto decrypt_loser; |
michael@0 | 11488 | } |
michael@0 | 11489 | |
michael@0 | 11490 | PRINT_BUF(80, (ss, "cleartext:", plaintext->buf, plaintext->len)); |
michael@0 | 11491 | |
michael@0 | 11492 | originalLen = plaintext->len; |
michael@0 | 11493 | |
michael@0 | 11494 | /* If it's a block cipher, check and strip the padding. */ |
michael@0 | 11495 | if (cipher_def->type == type_block) { |
michael@0 | 11496 | const unsigned int blockSize = cipher_def->block_size; |
michael@0 | 11497 | const unsigned int macSize = crSpec->mac_size; |
michael@0 | 11498 | |
michael@0 | 11499 | if (!isTLS) { |
michael@0 | 11500 | good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( |
michael@0 | 11501 | plaintext, blockSize, macSize)); |
michael@0 | 11502 | } else { |
michael@0 | 11503 | good &= SECStatusToMask(ssl_RemoveTLSCBCPadding( |
michael@0 | 11504 | plaintext, macSize)); |
michael@0 | 11505 | } |
michael@0 | 11506 | } |
michael@0 | 11507 | |
michael@0 | 11508 | /* compute the MAC */ |
michael@0 | 11509 | headerLen = ssl3_BuildRecordPseudoHeader( |
michael@0 | 11510 | header, IS_DTLS(ss) ? cText->seq_num : crSpec->read_seq_num, |
michael@0 | 11511 | rType, isTLS, cText->version, IS_DTLS(ss), |
michael@0 | 11512 | plaintext->len - crSpec->mac_size); |
michael@0 | 11513 | PORT_Assert(headerLen <= sizeof(header)); |
michael@0 | 11514 | if (cipher_def->type == type_block) { |
michael@0 | 11515 | rv = ssl3_ComputeRecordMACConstantTime( |
michael@0 | 11516 | crSpec, (PRBool)(!ss->sec.isServer), header, headerLen, |
michael@0 | 11517 | plaintext->buf, plaintext->len, originalLen, |
michael@0 | 11518 | hash, &hashBytes); |
michael@0 | 11519 | |
michael@0 | 11520 | ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, |
michael@0 | 11521 | crSpec->mac_size); |
michael@0 | 11522 | givenHash = givenHashBuf; |
michael@0 | 11523 | |
michael@0 | 11524 | /* plaintext->len will always have enough space to remove the MAC |
michael@0 | 11525 | * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust |
michael@0 | 11526 | * plaintext->len if the result has enough space for the MAC and we |
michael@0 | 11527 | * tested the unadjusted size against minLength, above. */ |
michael@0 | 11528 | plaintext->len -= crSpec->mac_size; |
michael@0 | 11529 | } else { |
michael@0 | 11530 | /* This is safe because we checked the minLength above. */ |
michael@0 | 11531 | plaintext->len -= crSpec->mac_size; |
michael@0 | 11532 | |
michael@0 | 11533 | rv = ssl3_ComputeRecordMAC( |
michael@0 | 11534 | crSpec, (PRBool)(!ss->sec.isServer), header, headerLen, |
michael@0 | 11535 | plaintext->buf, plaintext->len, hash, &hashBytes); |
michael@0 | 11536 | |
michael@0 | 11537 | /* We can read the MAC directly from the record because its location |
michael@0 | 11538 | * is public when a stream cipher is used. */ |
michael@0 | 11539 | givenHash = plaintext->buf + plaintext->len; |
michael@0 | 11540 | } |
michael@0 | 11541 | |
michael@0 | 11542 | good &= SECStatusToMask(rv); |
michael@0 | 11543 | |
michael@0 | 11544 | if (hashBytes != (unsigned)crSpec->mac_size || |
michael@0 | 11545 | NSS_SecureMemcmp(givenHash, hash, crSpec->mac_size) != 0) { |
michael@0 | 11546 | /* We're allowed to leak whether or not the MAC check was correct */ |
michael@0 | 11547 | good = 0; |
michael@0 | 11548 | } |
michael@0 | 11549 | } |
michael@0 | 11550 | |
michael@0 | 11551 | if (good == 0) { |
michael@0 | 11552 | decrypt_loser: |
michael@0 | 11553 | /* must not hold spec lock when calling SSL3_SendAlert. */ |
michael@0 | 11554 | ssl_ReleaseSpecReadLock(ss); |
michael@0 | 11555 | |
michael@0 | 11556 | SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd)); |
michael@0 | 11557 | |
michael@0 | 11558 | if (!IS_DTLS(ss)) { |
michael@0 | 11559 | SSL3_SendAlert(ss, alert_fatal, bad_record_mac); |
michael@0 | 11560 | /* always log mac error, in case attacker can read server logs. */ |
michael@0 | 11561 | PORT_SetError(SSL_ERROR_BAD_MAC_READ); |
michael@0 | 11562 | return SECFailure; |
michael@0 | 11563 | } else { |
michael@0 | 11564 | /* Silently drop the packet */ |
michael@0 | 11565 | databuf->len = 0; /* Needed to ensure data not left around */ |
michael@0 | 11566 | return SECSuccess; |
michael@0 | 11567 | } |
michael@0 | 11568 | } |
michael@0 | 11569 | |
michael@0 | 11570 | if (!IS_DTLS(ss)) { |
michael@0 | 11571 | ssl3_BumpSequenceNumber(&crSpec->read_seq_num); |
michael@0 | 11572 | } else { |
michael@0 | 11573 | dtls_RecordSetRecvd(&crSpec->recvdRecords, dtls_seq_num); |
michael@0 | 11574 | } |
michael@0 | 11575 | |
michael@0 | 11576 | ssl_ReleaseSpecReadLock(ss); /*****************************************/ |
michael@0 | 11577 | |
michael@0 | 11578 | /* |
michael@0 | 11579 | * The decrypted data is now in plaintext. |
michael@0 | 11580 | */ |
michael@0 | 11581 | |
michael@0 | 11582 | /* possibly decompress the record. If we aren't using compression then |
michael@0 | 11583 | * plaintext == databuf and so the uncompressed data is already in |
michael@0 | 11584 | * databuf. */ |
michael@0 | 11585 | if (crSpec->decompressor) { |
michael@0 | 11586 | if (databuf->space < plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION) { |
michael@0 | 11587 | rv = sslBuffer_Grow( |
michael@0 | 11588 | databuf, plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION); |
michael@0 | 11589 | if (rv != SECSuccess) { |
michael@0 | 11590 | SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes", |
michael@0 | 11591 | SSL_GETPID(), ss->fd, |
michael@0 | 11592 | plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION)); |
michael@0 | 11593 | /* sslBuffer_Grow has set a memory error code. */ |
michael@0 | 11594 | /* Perhaps we should send an alert. (but we have no memory!) */ |
michael@0 | 11595 | PORT_Free(plaintext->buf); |
michael@0 | 11596 | return SECFailure; |
michael@0 | 11597 | } |
michael@0 | 11598 | } |
michael@0 | 11599 | |
michael@0 | 11600 | rv = crSpec->decompressor(crSpec->decompressContext, |
michael@0 | 11601 | databuf->buf, |
michael@0 | 11602 | (int*) &databuf->len, |
michael@0 | 11603 | databuf->space, |
michael@0 | 11604 | plaintext->buf, |
michael@0 | 11605 | plaintext->len); |
michael@0 | 11606 | |
michael@0 | 11607 | if (rv != SECSuccess) { |
michael@0 | 11608 | int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE); |
michael@0 | 11609 | SSL3_SendAlert(ss, alert_fatal, |
michael@0 | 11610 | isTLS ? decompression_failure : bad_record_mac); |
michael@0 | 11611 | |
michael@0 | 11612 | /* There appears to be a bug with (at least) Apache + OpenSSL where |
michael@0 | 11613 | * resumed SSLv3 connections don't actually use compression. See |
michael@0 | 11614 | * comments 93-95 of |
michael@0 | 11615 | * https://bugzilla.mozilla.org/show_bug.cgi?id=275744 |
michael@0 | 11616 | * |
michael@0 | 11617 | * So, if we get a decompression error, and the record appears to |
michael@0 | 11618 | * be already uncompressed, then we return a more specific error |
michael@0 | 11619 | * code to hopefully save somebody some debugging time in the |
michael@0 | 11620 | * future. |
michael@0 | 11621 | */ |
michael@0 | 11622 | if (plaintext->len >= 4) { |
michael@0 | 11623 | unsigned int len = ((unsigned int) plaintext->buf[1] << 16) | |
michael@0 | 11624 | ((unsigned int) plaintext->buf[2] << 8) | |
michael@0 | 11625 | (unsigned int) plaintext->buf[3]; |
michael@0 | 11626 | if (len == plaintext->len - 4) { |
michael@0 | 11627 | /* This appears to be uncompressed already */ |
michael@0 | 11628 | err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD; |
michael@0 | 11629 | } |
michael@0 | 11630 | } |
michael@0 | 11631 | |
michael@0 | 11632 | PORT_Free(plaintext->buf); |
michael@0 | 11633 | PORT_SetError(err); |
michael@0 | 11634 | return SECFailure; |
michael@0 | 11635 | } |
michael@0 | 11636 | |
michael@0 | 11637 | PORT_Free(plaintext->buf); |
michael@0 | 11638 | } |
michael@0 | 11639 | |
michael@0 | 11640 | /* |
michael@0 | 11641 | ** Having completed the decompression, check the length again. |
michael@0 | 11642 | */ |
michael@0 | 11643 | if (isTLS && databuf->len > (MAX_FRAGMENT_LENGTH + 1024)) { |
michael@0 | 11644 | SSL3_SendAlert(ss, alert_fatal, record_overflow); |
michael@0 | 11645 | PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); |
michael@0 | 11646 | return SECFailure; |
michael@0 | 11647 | } |
michael@0 | 11648 | |
michael@0 | 11649 | /* Application data records are processed by the caller of this |
michael@0 | 11650 | ** function, not by this function. |
michael@0 | 11651 | */ |
michael@0 | 11652 | if (rType == content_application_data) { |
michael@0 | 11653 | if (ss->firstHsDone) |
michael@0 | 11654 | return SECSuccess; |
michael@0 | 11655 | (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
michael@0 | 11656 | PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA); |
michael@0 | 11657 | return SECFailure; |
michael@0 | 11658 | } |
michael@0 | 11659 | |
michael@0 | 11660 | /* It's a record that must be handled by ssl itself, not the application. |
michael@0 | 11661 | */ |
michael@0 | 11662 | process_it: |
michael@0 | 11663 | /* XXX Get the xmit lock here. Odds are very high that we'll be xmiting |
michael@0 | 11664 | * data ang getting the xmit lock here prevents deadlocks. |
michael@0 | 11665 | */ |
michael@0 | 11666 | ssl_GetSSL3HandshakeLock(ss); |
michael@0 | 11667 | |
michael@0 | 11668 | /* All the functions called in this switch MUST set error code if |
michael@0 | 11669 | ** they return SECFailure or SECWouldBlock. |
michael@0 | 11670 | */ |
michael@0 | 11671 | switch (rType) { |
michael@0 | 11672 | case content_change_cipher_spec: |
michael@0 | 11673 | rv = ssl3_HandleChangeCipherSpecs(ss, databuf); |
michael@0 | 11674 | break; |
michael@0 | 11675 | case content_alert: |
michael@0 | 11676 | rv = ssl3_HandleAlert(ss, databuf); |
michael@0 | 11677 | break; |
michael@0 | 11678 | case content_handshake: |
michael@0 | 11679 | if (!IS_DTLS(ss)) { |
michael@0 | 11680 | rv = ssl3_HandleHandshake(ss, databuf); |
michael@0 | 11681 | } else { |
michael@0 | 11682 | rv = dtls_HandleHandshake(ss, databuf); |
michael@0 | 11683 | } |
michael@0 | 11684 | break; |
michael@0 | 11685 | /* |
michael@0 | 11686 | case content_application_data is handled before this switch |
michael@0 | 11687 | */ |
michael@0 | 11688 | default: |
michael@0 | 11689 | SSL_DBG(("%d: SSL3[%d]: bogus content type=%d", |
michael@0 | 11690 | SSL_GETPID(), ss->fd, cText->type)); |
michael@0 | 11691 | /* XXX Send an alert ??? */ |
michael@0 | 11692 | PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE); |
michael@0 | 11693 | rv = SECFailure; |
michael@0 | 11694 | break; |
michael@0 | 11695 | } |
michael@0 | 11696 | |
michael@0 | 11697 | ssl_ReleaseSSL3HandshakeLock(ss); |
michael@0 | 11698 | return rv; |
michael@0 | 11699 | } |
michael@0 | 11700 | |
michael@0 | 11701 | /* |
michael@0 | 11702 | * Initialization functions |
michael@0 | 11703 | */ |
michael@0 | 11704 | |
michael@0 | 11705 | /* Called from ssl3_InitState, immediately below. */ |
michael@0 | 11706 | /* Caller must hold the SpecWriteLock. */ |
michael@0 | 11707 | static void |
michael@0 | 11708 | ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) |
michael@0 | 11709 | { |
michael@0 | 11710 | spec->cipher_def = &bulk_cipher_defs[cipher_null]; |
michael@0 | 11711 | PORT_Assert(spec->cipher_def->cipher == cipher_null); |
michael@0 | 11712 | spec->mac_def = &mac_defs[mac_null]; |
michael@0 | 11713 | PORT_Assert(spec->mac_def->mac == mac_null); |
michael@0 | 11714 | spec->encode = Null_Cipher; |
michael@0 | 11715 | spec->decode = Null_Cipher; |
michael@0 | 11716 | spec->destroy = NULL; |
michael@0 | 11717 | spec->compressor = NULL; |
michael@0 | 11718 | spec->decompressor = NULL; |
michael@0 | 11719 | spec->destroyCompressContext = NULL; |
michael@0 | 11720 | spec->destroyDecompressContext = NULL; |
michael@0 | 11721 | spec->mac_size = 0; |
michael@0 | 11722 | spec->master_secret = NULL; |
michael@0 | 11723 | spec->bypassCiphers = PR_FALSE; |
michael@0 | 11724 | |
michael@0 | 11725 | spec->msItem.data = NULL; |
michael@0 | 11726 | spec->msItem.len = 0; |
michael@0 | 11727 | |
michael@0 | 11728 | spec->client.write_key = NULL; |
michael@0 | 11729 | spec->client.write_mac_key = NULL; |
michael@0 | 11730 | spec->client.write_mac_context = NULL; |
michael@0 | 11731 | |
michael@0 | 11732 | spec->server.write_key = NULL; |
michael@0 | 11733 | spec->server.write_mac_key = NULL; |
michael@0 | 11734 | spec->server.write_mac_context = NULL; |
michael@0 | 11735 | |
michael@0 | 11736 | spec->write_seq_num.high = 0; |
michael@0 | 11737 | spec->write_seq_num.low = 0; |
michael@0 | 11738 | |
michael@0 | 11739 | spec->read_seq_num.high = 0; |
michael@0 | 11740 | spec->read_seq_num.low = 0; |
michael@0 | 11741 | |
michael@0 | 11742 | spec->epoch = 0; |
michael@0 | 11743 | dtls_InitRecvdRecords(&spec->recvdRecords); |
michael@0 | 11744 | |
michael@0 | 11745 | spec->version = ss->vrange.max; |
michael@0 | 11746 | } |
michael@0 | 11747 | |
michael@0 | 11748 | /* Called from: ssl3_SendRecord |
michael@0 | 11749 | ** ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake() |
michael@0 | 11750 | ** ssl3_SendClientHello() |
michael@0 | 11751 | ** ssl3_HandleV2ClientHello() |
michael@0 | 11752 | ** ssl3_HandleRecord() |
michael@0 | 11753 | ** |
michael@0 | 11754 | ** This function should perhaps acquire and release the SpecWriteLock. |
michael@0 | 11755 | ** |
michael@0 | 11756 | ** |
michael@0 | 11757 | */ |
michael@0 | 11758 | static SECStatus |
michael@0 | 11759 | ssl3_InitState(sslSocket *ss) |
michael@0 | 11760 | { |
michael@0 | 11761 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 11762 | |
michael@0 | 11763 | if (ss->ssl3.initialized) |
michael@0 | 11764 | return SECSuccess; /* Function should be idempotent */ |
michael@0 | 11765 | |
michael@0 | 11766 | ss->ssl3.policy = SSL_ALLOWED; |
michael@0 | 11767 | |
michael@0 | 11768 | ssl_GetSpecWriteLock(ss); |
michael@0 | 11769 | ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0]; |
michael@0 | 11770 | ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1]; |
michael@0 | 11771 | ss->ssl3.hs.sendingSCSV = PR_FALSE; |
michael@0 | 11772 | ssl3_InitCipherSpec(ss, ss->ssl3.crSpec); |
michael@0 | 11773 | ssl3_InitCipherSpec(ss, ss->ssl3.prSpec); |
michael@0 | 11774 | |
michael@0 | 11775 | ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello; |
michael@0 | 11776 | #ifndef NSS_DISABLE_ECC |
michael@0 | 11777 | ss->ssl3.hs.negotiatedECCurves = ssl3_GetSupportedECCurveMask(ss); |
michael@0 | 11778 | #endif |
michael@0 | 11779 | ssl_ReleaseSpecWriteLock(ss); |
michael@0 | 11780 | |
michael@0 | 11781 | PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); |
michael@0 | 11782 | |
michael@0 | 11783 | if (IS_DTLS(ss)) { |
michael@0 | 11784 | ss->ssl3.hs.sendMessageSeq = 0; |
michael@0 | 11785 | ss->ssl3.hs.recvMessageSeq = 0; |
michael@0 | 11786 | ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS; |
michael@0 | 11787 | ss->ssl3.hs.rtRetries = 0; |
michael@0 | 11788 | ss->ssl3.hs.recvdHighWater = -1; |
michael@0 | 11789 | PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight); |
michael@0 | 11790 | dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */ |
michael@0 | 11791 | } |
michael@0 | 11792 | |
michael@0 | 11793 | PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); |
michael@0 | 11794 | ss->ssl3.hs.messages.buf = NULL; |
michael@0 | 11795 | ss->ssl3.hs.messages.space = 0; |
michael@0 | 11796 | |
michael@0 | 11797 | ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE; |
michael@0 | 11798 | PORT_Memset(&ss->ssl3.hs.newSessionTicket, 0, |
michael@0 | 11799 | sizeof(ss->ssl3.hs.newSessionTicket)); |
michael@0 | 11800 | |
michael@0 | 11801 | ss->ssl3.initialized = PR_TRUE; |
michael@0 | 11802 | return SECSuccess; |
michael@0 | 11803 | } |
michael@0 | 11804 | |
michael@0 | 11805 | /* Returns a reference counted object that contains a key pair. |
michael@0 | 11806 | * Or NULL on failure. Initial ref count is 1. |
michael@0 | 11807 | * Uses the keys in the pair as input. |
michael@0 | 11808 | */ |
michael@0 | 11809 | ssl3KeyPair * |
michael@0 | 11810 | ssl3_NewKeyPair( SECKEYPrivateKey * privKey, SECKEYPublicKey * pubKey) |
michael@0 | 11811 | { |
michael@0 | 11812 | ssl3KeyPair * pair; |
michael@0 | 11813 | |
michael@0 | 11814 | if (!privKey || !pubKey) { |
michael@0 | 11815 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
michael@0 | 11816 | return NULL; |
michael@0 | 11817 | } |
michael@0 | 11818 | pair = PORT_ZNew(ssl3KeyPair); |
michael@0 | 11819 | if (!pair) |
michael@0 | 11820 | return NULL; /* error code is set. */ |
michael@0 | 11821 | pair->refCount = 1; |
michael@0 | 11822 | pair->privKey = privKey; |
michael@0 | 11823 | pair->pubKey = pubKey; |
michael@0 | 11824 | return pair; /* success */ |
michael@0 | 11825 | } |
michael@0 | 11826 | |
michael@0 | 11827 | ssl3KeyPair * |
michael@0 | 11828 | ssl3_GetKeyPairRef(ssl3KeyPair * keyPair) |
michael@0 | 11829 | { |
michael@0 | 11830 | PR_ATOMIC_INCREMENT(&keyPair->refCount); |
michael@0 | 11831 | return keyPair; |
michael@0 | 11832 | } |
michael@0 | 11833 | |
michael@0 | 11834 | void |
michael@0 | 11835 | ssl3_FreeKeyPair(ssl3KeyPair * keyPair) |
michael@0 | 11836 | { |
michael@0 | 11837 | PRInt32 newCount = PR_ATOMIC_DECREMENT(&keyPair->refCount); |
michael@0 | 11838 | if (!newCount) { |
michael@0 | 11839 | if (keyPair->privKey) |
michael@0 | 11840 | SECKEY_DestroyPrivateKey(keyPair->privKey); |
michael@0 | 11841 | if (keyPair->pubKey) |
michael@0 | 11842 | SECKEY_DestroyPublicKey( keyPair->pubKey); |
michael@0 | 11843 | PORT_Free(keyPair); |
michael@0 | 11844 | } |
michael@0 | 11845 | } |
michael@0 | 11846 | |
michael@0 | 11847 | |
michael@0 | 11848 | |
michael@0 | 11849 | /* |
michael@0 | 11850 | * Creates the public and private RSA keys for SSL Step down. |
michael@0 | 11851 | * Called from SSL_ConfigSecureServer in sslsecur.c |
michael@0 | 11852 | */ |
michael@0 | 11853 | SECStatus |
michael@0 | 11854 | ssl3_CreateRSAStepDownKeys(sslSocket *ss) |
michael@0 | 11855 | { |
michael@0 | 11856 | SECStatus rv = SECSuccess; |
michael@0 | 11857 | SECKEYPrivateKey * privKey; /* RSA step down key */ |
michael@0 | 11858 | SECKEYPublicKey * pubKey; /* RSA step down key */ |
michael@0 | 11859 | |
michael@0 | 11860 | if (ss->stepDownKeyPair) |
michael@0 | 11861 | ssl3_FreeKeyPair(ss->stepDownKeyPair); |
michael@0 | 11862 | ss->stepDownKeyPair = NULL; |
michael@0 | 11863 | #ifndef HACKED_EXPORT_SERVER |
michael@0 | 11864 | /* Sigh, should have a get key strength call for private keys */ |
michael@0 | 11865 | if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].SERVERKEY) > |
michael@0 | 11866 | EXPORT_RSA_KEY_LENGTH) { |
michael@0 | 11867 | /* need to ask for the key size in bits */ |
michael@0 | 11868 | privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB, |
michael@0 | 11869 | &pubKey, NULL); |
michael@0 | 11870 | if (!privKey || !pubKey || |
michael@0 | 11871 | !(ss->stepDownKeyPair = ssl3_NewKeyPair(privKey, pubKey))) { |
michael@0 | 11872 | ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); |
michael@0 | 11873 | rv = SECFailure; |
michael@0 | 11874 | } |
michael@0 | 11875 | } |
michael@0 | 11876 | #endif |
michael@0 | 11877 | return rv; |
michael@0 | 11878 | } |
michael@0 | 11879 | |
michael@0 | 11880 | |
michael@0 | 11881 | /* record the export policy for this cipher suite */ |
michael@0 | 11882 | SECStatus |
michael@0 | 11883 | ssl3_SetPolicy(ssl3CipherSuite which, int policy) |
michael@0 | 11884 | { |
michael@0 | 11885 | ssl3CipherSuiteCfg *suite; |
michael@0 | 11886 | |
michael@0 | 11887 | suite = ssl_LookupCipherSuiteCfg(which, cipherSuites); |
michael@0 | 11888 | if (suite == NULL) { |
michael@0 | 11889 | return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */ |
michael@0 | 11890 | } |
michael@0 | 11891 | suite->policy = policy; |
michael@0 | 11892 | |
michael@0 | 11893 | return SECSuccess; |
michael@0 | 11894 | } |
michael@0 | 11895 | |
michael@0 | 11896 | SECStatus |
michael@0 | 11897 | ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *oPolicy) |
michael@0 | 11898 | { |
michael@0 | 11899 | ssl3CipherSuiteCfg *suite; |
michael@0 | 11900 | PRInt32 policy; |
michael@0 | 11901 | SECStatus rv; |
michael@0 | 11902 | |
michael@0 | 11903 | suite = ssl_LookupCipherSuiteCfg(which, cipherSuites); |
michael@0 | 11904 | if (suite) { |
michael@0 | 11905 | policy = suite->policy; |
michael@0 | 11906 | rv = SECSuccess; |
michael@0 | 11907 | } else { |
michael@0 | 11908 | policy = SSL_NOT_ALLOWED; |
michael@0 | 11909 | rv = SECFailure; /* err code was set by Lookup. */ |
michael@0 | 11910 | } |
michael@0 | 11911 | *oPolicy = policy; |
michael@0 | 11912 | return rv; |
michael@0 | 11913 | } |
michael@0 | 11914 | |
michael@0 | 11915 | /* record the user preference for this suite */ |
michael@0 | 11916 | SECStatus |
michael@0 | 11917 | ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool enabled) |
michael@0 | 11918 | { |
michael@0 | 11919 | ssl3CipherSuiteCfg *suite; |
michael@0 | 11920 | |
michael@0 | 11921 | suite = ssl_LookupCipherSuiteCfg(which, cipherSuites); |
michael@0 | 11922 | if (suite == NULL) { |
michael@0 | 11923 | return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */ |
michael@0 | 11924 | } |
michael@0 | 11925 | suite->enabled = enabled; |
michael@0 | 11926 | return SECSuccess; |
michael@0 | 11927 | } |
michael@0 | 11928 | |
michael@0 | 11929 | /* return the user preference for this suite */ |
michael@0 | 11930 | SECStatus |
michael@0 | 11931 | ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *enabled) |
michael@0 | 11932 | { |
michael@0 | 11933 | ssl3CipherSuiteCfg *suite; |
michael@0 | 11934 | PRBool pref; |
michael@0 | 11935 | SECStatus rv; |
michael@0 | 11936 | |
michael@0 | 11937 | suite = ssl_LookupCipherSuiteCfg(which, cipherSuites); |
michael@0 | 11938 | if (suite) { |
michael@0 | 11939 | pref = suite->enabled; |
michael@0 | 11940 | rv = SECSuccess; |
michael@0 | 11941 | } else { |
michael@0 | 11942 | pref = SSL_NOT_ALLOWED; |
michael@0 | 11943 | rv = SECFailure; /* err code was set by Lookup. */ |
michael@0 | 11944 | } |
michael@0 | 11945 | *enabled = pref; |
michael@0 | 11946 | return rv; |
michael@0 | 11947 | } |
michael@0 | 11948 | |
michael@0 | 11949 | SECStatus |
michael@0 | 11950 | ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool enabled) |
michael@0 | 11951 | { |
michael@0 | 11952 | ssl3CipherSuiteCfg *suite; |
michael@0 | 11953 | |
michael@0 | 11954 | suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites); |
michael@0 | 11955 | if (suite == NULL) { |
michael@0 | 11956 | return SECFailure; /* err code was set by ssl_LookupCipherSuiteCfg */ |
michael@0 | 11957 | } |
michael@0 | 11958 | suite->enabled = enabled; |
michael@0 | 11959 | return SECSuccess; |
michael@0 | 11960 | } |
michael@0 | 11961 | |
michael@0 | 11962 | SECStatus |
michael@0 | 11963 | ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled) |
michael@0 | 11964 | { |
michael@0 | 11965 | ssl3CipherSuiteCfg *suite; |
michael@0 | 11966 | PRBool pref; |
michael@0 | 11967 | SECStatus rv; |
michael@0 | 11968 | |
michael@0 | 11969 | suite = ssl_LookupCipherSuiteCfg(which, ss->cipherSuites); |
michael@0 | 11970 | if (suite) { |
michael@0 | 11971 | pref = suite->enabled; |
michael@0 | 11972 | rv = SECSuccess; |
michael@0 | 11973 | } else { |
michael@0 | 11974 | pref = SSL_NOT_ALLOWED; |
michael@0 | 11975 | rv = SECFailure; /* err code was set by Lookup. */ |
michael@0 | 11976 | } |
michael@0 | 11977 | *enabled = pref; |
michael@0 | 11978 | return rv; |
michael@0 | 11979 | } |
michael@0 | 11980 | |
michael@0 | 11981 | /* copy global default policy into socket. */ |
michael@0 | 11982 | void |
michael@0 | 11983 | ssl3_InitSocketPolicy(sslSocket *ss) |
michael@0 | 11984 | { |
michael@0 | 11985 | PORT_Memcpy(ss->cipherSuites, cipherSuites, sizeof cipherSuites); |
michael@0 | 11986 | } |
michael@0 | 11987 | |
michael@0 | 11988 | /* ssl3_config_match_init must have already been called by |
michael@0 | 11989 | * the caller of this function. |
michael@0 | 11990 | */ |
michael@0 | 11991 | SECStatus |
michael@0 | 11992 | ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size) |
michael@0 | 11993 | { |
michael@0 | 11994 | int i, count = 0; |
michael@0 | 11995 | |
michael@0 | 11996 | PORT_Assert(ss != 0); |
michael@0 | 11997 | if (!ss) { |
michael@0 | 11998 | PORT_SetError(PR_INVALID_ARGUMENT_ERROR); |
michael@0 | 11999 | return SECFailure; |
michael@0 | 12000 | } |
michael@0 | 12001 | if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) { |
michael@0 | 12002 | *size = 0; |
michael@0 | 12003 | return SECSuccess; |
michael@0 | 12004 | } |
michael@0 | 12005 | if (cs == NULL) { |
michael@0 | 12006 | *size = count_cipher_suites(ss, SSL_ALLOWED, PR_TRUE); |
michael@0 | 12007 | return SECSuccess; |
michael@0 | 12008 | } |
michael@0 | 12009 | |
michael@0 | 12010 | /* ssl3_config_match_init was called by the caller of this function. */ |
michael@0 | 12011 | for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
michael@0 | 12012 | ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; |
michael@0 | 12013 | if (config_match(suite, SSL_ALLOWED, PR_TRUE, &ss->vrange)) { |
michael@0 | 12014 | if (cs != NULL) { |
michael@0 | 12015 | *cs++ = 0x00; |
michael@0 | 12016 | *cs++ = (suite->cipher_suite >> 8) & 0xFF; |
michael@0 | 12017 | *cs++ = suite->cipher_suite & 0xFF; |
michael@0 | 12018 | } |
michael@0 | 12019 | count++; |
michael@0 | 12020 | } |
michael@0 | 12021 | } |
michael@0 | 12022 | *size = count; |
michael@0 | 12023 | return SECSuccess; |
michael@0 | 12024 | } |
michael@0 | 12025 | |
michael@0 | 12026 | /* |
michael@0 | 12027 | ** If ssl3 socket has completed the first handshake, and is in idle state, |
michael@0 | 12028 | ** then start a new handshake. |
michael@0 | 12029 | ** If flushCache is true, the SID cache will be flushed first, forcing a |
michael@0 | 12030 | ** "Full" handshake (not a session restart handshake), to be done. |
michael@0 | 12031 | ** |
michael@0 | 12032 | ** called from SSL_RedoHandshake(), which already holds the handshake locks. |
michael@0 | 12033 | */ |
michael@0 | 12034 | SECStatus |
michael@0 | 12035 | ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) |
michael@0 | 12036 | { |
michael@0 | 12037 | sslSessionID * sid = ss->sec.ci.sid; |
michael@0 | 12038 | SECStatus rv; |
michael@0 | 12039 | |
michael@0 | 12040 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
michael@0 | 12041 | |
michael@0 | 12042 | if (!ss->firstHsDone || |
michael@0 | 12043 | ((ss->version >= SSL_LIBRARY_VERSION_3_0) && |
michael@0 | 12044 | ss->ssl3.initialized && |
michael@0 | 12045 | (ss->ssl3.hs.ws != idle_handshake))) { |
michael@0 | 12046 | PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); |
michael@0 | 12047 | return SECFailure; |
michael@0 | 12048 | } |
michael@0 | 12049 | |
michael@0 | 12050 | if (IS_DTLS(ss)) { |
michael@0 | 12051 | dtls_RehandshakeCleanup(ss); |
michael@0 | 12052 | } |
michael@0 | 12053 | |
michael@0 | 12054 | if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) { |
michael@0 | 12055 | PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED); |
michael@0 | 12056 | return SECFailure; |
michael@0 | 12057 | } |
michael@0 | 12058 | if (sid && flushCache) { |
michael@0 | 12059 | if (ss->sec.uncache) |
michael@0 | 12060 | ss->sec.uncache(sid); /* remove it from whichever cache it's in. */ |
michael@0 | 12061 | ssl_FreeSID(sid); /* dec ref count and free if zero. */ |
michael@0 | 12062 | ss->sec.ci.sid = NULL; |
michael@0 | 12063 | } |
michael@0 | 12064 | |
michael@0 | 12065 | ssl_GetXmitBufLock(ss); /**************************************/ |
michael@0 | 12066 | |
michael@0 | 12067 | /* start off a new handshake. */ |
michael@0 | 12068 | rv = (ss->sec.isServer) ? ssl3_SendHelloRequest(ss) |
michael@0 | 12069 | : ssl3_SendClientHello(ss, PR_FALSE); |
michael@0 | 12070 | |
michael@0 | 12071 | ssl_ReleaseXmitBufLock(ss); /**************************************/ |
michael@0 | 12072 | return rv; |
michael@0 | 12073 | } |
michael@0 | 12074 | |
michael@0 | 12075 | /* Called from ssl_DestroySocketContents() in sslsock.c */ |
michael@0 | 12076 | void |
michael@0 | 12077 | ssl3_DestroySSL3Info(sslSocket *ss) |
michael@0 | 12078 | { |
michael@0 | 12079 | |
michael@0 | 12080 | if (ss->ssl3.clientCertificate != NULL) |
michael@0 | 12081 | CERT_DestroyCertificate(ss->ssl3.clientCertificate); |
michael@0 | 12082 | |
michael@0 | 12083 | if (ss->ssl3.clientPrivateKey != NULL) |
michael@0 | 12084 | SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); |
michael@0 | 12085 | |
michael@0 | 12086 | if (ss->ssl3.peerCertArena != NULL) |
michael@0 | 12087 | ssl3_CleanupPeerCerts(ss); |
michael@0 | 12088 | |
michael@0 | 12089 | if (ss->ssl3.clientCertChain != NULL) { |
michael@0 | 12090 | CERT_DestroyCertificateList(ss->ssl3.clientCertChain); |
michael@0 | 12091 | ss->ssl3.clientCertChain = NULL; |
michael@0 | 12092 | } |
michael@0 | 12093 | |
michael@0 | 12094 | /* clean up handshake */ |
michael@0 | 12095 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 12096 | if (ss->opt.bypassPKCS11) { |
michael@0 | 12097 | if (ss->ssl3.hs.hashType == handshake_hash_combo) { |
michael@0 | 12098 | SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); |
michael@0 | 12099 | MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); |
michael@0 | 12100 | } else if (ss->ssl3.hs.hashType == handshake_hash_single) { |
michael@0 | 12101 | ss->ssl3.hs.sha_obj->destroy(ss->ssl3.hs.sha_cx, PR_FALSE); |
michael@0 | 12102 | } |
michael@0 | 12103 | } |
michael@0 | 12104 | #endif |
michael@0 | 12105 | if (ss->ssl3.hs.md5) { |
michael@0 | 12106 | PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE); |
michael@0 | 12107 | } |
michael@0 | 12108 | if (ss->ssl3.hs.sha) { |
michael@0 | 12109 | PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); |
michael@0 | 12110 | } |
michael@0 | 12111 | if (ss->ssl3.hs.clientSigAndHash) { |
michael@0 | 12112 | PORT_Free(ss->ssl3.hs.clientSigAndHash); |
michael@0 | 12113 | } |
michael@0 | 12114 | if (ss->ssl3.hs.messages.buf) { |
michael@0 | 12115 | PORT_Free(ss->ssl3.hs.messages.buf); |
michael@0 | 12116 | ss->ssl3.hs.messages.buf = NULL; |
michael@0 | 12117 | ss->ssl3.hs.messages.len = 0; |
michael@0 | 12118 | ss->ssl3.hs.messages.space = 0; |
michael@0 | 12119 | } |
michael@0 | 12120 | |
michael@0 | 12121 | /* free the SSL3Buffer (msg_body) */ |
michael@0 | 12122 | PORT_Free(ss->ssl3.hs.msg_body.buf); |
michael@0 | 12123 | |
michael@0 | 12124 | SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); |
michael@0 | 12125 | |
michael@0 | 12126 | /* free up the CipherSpecs */ |
michael@0 | 12127 | ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE/*freeSrvName*/); |
michael@0 | 12128 | ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/); |
michael@0 | 12129 | |
michael@0 | 12130 | /* Destroy the DTLS data */ |
michael@0 | 12131 | if (IS_DTLS(ss)) { |
michael@0 | 12132 | dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight); |
michael@0 | 12133 | if (ss->ssl3.hs.recvdFragments.buf) { |
michael@0 | 12134 | PORT_Free(ss->ssl3.hs.recvdFragments.buf); |
michael@0 | 12135 | } |
michael@0 | 12136 | } |
michael@0 | 12137 | |
michael@0 | 12138 | ss->ssl3.initialized = PR_FALSE; |
michael@0 | 12139 | |
michael@0 | 12140 | SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); |
michael@0 | 12141 | } |
michael@0 | 12142 | |
michael@0 | 12143 | /* End of ssl3con.c */ |